dsh-motion-ui 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/client.js CHANGED
@@ -288,7 +288,7 @@ var canvasSource = (node) => ({ html: normalizeCanvasHtml(node.html), css: norma
288
288
  var MECHANISM_RUNTIME = 'var __MotionMechanism=(()=>{var it=Object.defineProperty;var Ot=Object.getOwnPropertyDescriptor;var Et=Object.getOwnPropertyNames;var It=Object.prototype.hasOwnProperty;var zt=(t,a)=>{for(var n in a)it(t,n,{get:a[n],enumerable:!0})},Pt=(t,a,n,o)=>{if(a&&typeof a=="object"||typeof a=="function")for(let e of Et(a))!It.call(t,e)&&e!==n&&it(t,e,{get:()=>a[e],enumerable:!(o=Ot(a,e))||o.enumerable});return t};var _t=t=>Pt(it({},"__esModule",{value:!0}),t);var Tt={};zt(Tt,{createMechanismAPI:()=>Ft});var st=Math.PI/180,Ct=Math.sqrt(1.6);function yt({scale:t,azimuth:a=45,elevation:n=30}){let o=a*st,e=n*st;return{sinA:Math.sin(o),cosA:Math.cos(o),sinE:Math.sin(e),cosE:Math.cos(e),k:t*Ct}}function q([t,a,n],o){let{origin:e}=o,{sinA:i,cosA:r,sinE:p,cosE:d,k:m}=yt(o);return[e[0]+(t*i-a*r)*m,e[1]+((t*r+a*i)*p-n*d)*m]}function tt([t,a,n],o){let{sinA:e,cosA:i,sinE:r,cosE:p}=yt(o);return(t*i+a*e)*p+n*r}function vt({x:t,y:a,w:n,d:o,r:e},i=8){let r=Math.max(0,Math.min(e,n/2,o/2)),p=[[t+n-r,a+r,-90],[t+n-r,a+o-r,0],[t+r,a+o-r,90],[t+r,a+r,180]],d=[];for(let[m,s,c]of p){let u=r>0?i:0;for(let f=0;f<=u;f++){let g=(c+(u?90*f/u:45))*st;d.push([m+r*Math.cos(g),s+r*Math.sin(g)])}}return d}function lt(t,a,n,o=40){return Array.from({length:o},(e,i)=>{let r=i/o*Math.PI*2;return[t+n*Math.cos(r),a+n*Math.sin(r)]})}function ct(t,a,n,{pad:o=24,headroom:e=0,azimuth:i=45,elevation:r=30}={}){let p={origin:[0,0],scale:1,azimuth:i,elevation:r},d=t.map(M=>q(M,p)),m=d.map(([M])=>M),s=d.map(([,M])=>M),c=Math.min(...m),u=Math.max(...m),f=Math.min(...s),g=Math.max(...s),h=Math.min((a-o*2)/(u-c),(n-o*2-e)/(g-f));return{origin:[a/2-(c+u)/2*h,e+(n-e)/2-(f+g)/2*h],scale:h,azimuth:i,elevation:r}}var Nt=Object.freeze({parts:96,teeth:64,faces:8192}),Ht=t=>typeof t=="number"&&Number.isFinite(t),y=t=>{throw Error("Motion mechanism: "+t)},v=(t,a,n=-1e4,o=1e4)=>((!Ht(t)||t<n||t>o)&&y(a+" must be a finite number in "+n+".."+o),t),U=(t,a)=>((!Array.isArray(t)||t.length!==3)&&y(a+" must be [x,y,z]"),t.map((n,o)=>v(n,a+"["+o+"]"))),et=t=>typeof t=="string"&&/^[\\p{L}_][\\p{L}\\p{M}\\p{N}_]{0,63}$/u.test(t)&&!["constructor","prototype","__proto__"].includes(t),kt=["box","cylinder","gear","rod","spring"],I=(t,a)=>t.map((n,o)=>n+a[o]),B=(t,a)=>t.map((n,o)=>n-a[o]),_=(t,a)=>t.map(n=>n*a),dt=(t,a)=>t.reduce((n,o,e)=>n+o*a[e],0),V=(t,a)=>[t[1]*a[2]-t[2]*a[1],t[2]*a[0]-t[0]*a[2],t[0]*a[1]-t[1]*a[0]],J=t=>{let a=Math.hypot(...t);return a<1e-6&&y("zero-length axis"),_(t,1/a)};function Y(t){(!t||typeof t!="object"||Array.isArray(t))&&y("scene must be an object"),(!Array.isArray(t.parts)||!t.parts.length||t.parts.length>Nt.parts)&&y("parts requires 1..96 objects");let a=new Set,n=new Set;for(let[o,e]of t.parts.entries()){let i="parts["+o+"]";(!e||typeof e!="object"||!et(e.id)||a.has(e.id))&&y(i+".id must be a unique identifier"),a.add(e.id),kt.includes(e.type)||y(i+".type must be "+kt.join("/")),e.group!==void 0&&(et(e.group)||y(i+".group must be an identifier"),n.add(e.group));for(let r of["label","description"])e[r]!==void 0&&(typeof e[r]!="string"||e[r].length>1024)&&y(i+"."+r+" must be short text");if(e.cover!==void 0&&typeof e.cover!="boolean"&&y(i+".cover must be boolean"),e.material!==void 0&&!["metal","dark","accent","warm","cool"].includes(e.material)&&y(i+".material must be metal/dark/accent/warm/cool"),e.at!==void 0&&U(e.at,i+".at"),e.explode!==void 0&&U(e.explode,i+".explode"),e.rotation!==void 0&&v(e.rotation,i+".rotation",-1e9,1e9),e.axis!==void 0&&!["x","y","z"].includes(e.axis)&&y(i+".axis must be x/y/z"),e.type==="box"){let r=U(e.size,i+".size");r.some(p=>p<=0||p>2e3)&&y(i+".size must be positive and <=2000"),e.round!==void 0&&v(e.round,i+".round",0,Math.min(r[0],r[1])/2)}if(["cylinder","gear"].includes(e.type)&&(v(e.radius,i+".radius",.1,1e3),v(e.height??8,i+".height",.1,1e3),e.inner!==void 0&&v(e.inner,i+".inner",0,e.radius-.01)),e.type==="gear"){let r=v(e.teeth,i+".teeth",6,64);Number.isInteger(r)||y(i+".teeth must be an integer"),e.module!==void 0&&v(e.module,i+".module",.1,e.radius/3)}if(["rod","spring"].includes(e.type)&&(U(e.from,i+".from"),U(e.to,i+".to"),Math.hypot(...B(e.to,e.from))<.1&&y(i+" endpoints must differ"),v(e.radius??2,i+".radius",.1,200)),e.type==="spring"){let r=v(e.turns??8,i+".turns",2,24);Number.isInteger(r)||y(i+".turns must be integer")}}if(t.groups!==void 0){(!Array.isArray(t.groups)||t.groups.length>12)&&y("groups must be an array of <=12 labels");let o=new Set;for(let e of t.groups)(!e||!et(e.id)||o.has(e.id)||!n.has(e.id)||typeof e.label!="string"||e.label.length>128)&&y("groups must name unique existing part groups"),o.add(e.id)}if(t.bounds!==void 0){(!Array.isArray(t.bounds)||t.bounds.length!==2)&&y("bounds must be [minXYZ,maxXYZ]");let[o,e]=t.bounds.map((i,r)=>U(i,"bounds["+r+"]"));o.some((i,r)=>i>=e[r])&&y("bounds min must be below max on every axis")}if(t.azimuth!==void 0&&v(t.azimuth,"azimuth",10,80),t.elevation!==void 0&&v(t.elevation,"elevation",15,70),t.title!==void 0&&(typeof t.title!="string"||t.title.length>256)&&y("title must be short text"),t.bind!==void 0){(!t.bind||typeof t.bind!="object"||Array.isArray(t.bind))&&y("bind must be an object");for(let[o,e]of Object.entries(t.bind))(!["explode","selected","cutaway"].includes(o)||!et(e))&&y("bind only accepts declared state keys for explode/selected/cutaway")}return t}function Lt(t){return t==="x"?[[0,1,0],[0,0,1],[1,0,0]]:t==="y"?[[0,0,1],[1,0,0],[0,1,0]]:[[1,0,0],[0,1,0],[0,0,1]]}var at=(t,a,n,o)=>I(I(_(t[0],a),_(t[1],n)),_(t[2],o));function Rt(t,a,n,o){let e=t.map(([m,s])=>at(n,m,s,-a/2)),i=t.map(([m,s])=>at(n,m,s,a/2)),r=[],p=o?.map(([m,s])=>at(n,m,s,a/2)),d=o?.map(([m,s])=>at(n,m,s,-a/2));r.push({points:i,holes:p?[p.slice().reverse()]:[],normal:n[2]},{points:e.slice().reverse(),holes:d?[d]:[],normal:_(n[2],-1)});for(let m=0;m<t.length;m++){let s=(m+1)%t.length;Math.hypot(...B(e[s],e[m]))<1e-6||(r.push({points:[e[m],e[s],i[s],i[m]],normal:J(V(B(e[s],e[m]),n[2]))}),o&&r.push({points:[d[s],d[m],p[m],p[s]],normal:J(V(B(d[m],d[s]),n[2]))}))}return r}function ot(t){let a=Lt(t.axis),n,o,e;if(t.type==="box"&&(n=vt({x:-t.size[0]/2,y:-t.size[1]/2,w:t.size[0],d:t.size[1],r:t.round??Math.min(2,t.size[0]/2,t.size[1]/2)},3),o=t.size[2]),t.type==="cylinder"&&(n=lt(0,0,t.radius,24),o=t.height??8),t.type==="gear"){let s=Math.PI*2/t.teeth,c=t.module??t.radius*2/t.teeth;n=[];for(let u=0;u<t.teeth;u++)for(let[f,g]of[[-.5,t.radius-c*.85],[-.32,t.radius-c*.85],[-.17,t.radius+c*.7],[.17,t.radius+c*.7],[.32,t.radius-c*.85]]){let h=(u+f)*s;n.push([Math.cos(h)*g,Math.sin(h)*g])}o=t.height??8}if(t.type==="rod"){let s=J(B(t.to,t.from)),c=J(V(s,Math.abs(s[2])<.9?[0,0,1]:[0,1,0]));a=[c,V(s,c),s],n=lt(0,0,t.radius??2,16),o=Math.hypot(...B(t.to,t.from))}if(t.type==="spring"){let s=J(B(t.to,t.from)),c=J(V(s,Math.abs(s[2])<.9?[0,0,1]:[0,1,0])),u=V(s,c),f=[];for(let g=0;g<=128;g++){let h=g/128,M=h*(t.turns??8)*Math.PI*2,O=Math.min(1,h*12,(1-h)*12);f.push(I(I(t.from,_(B(t.to,t.from),h)),I(_(c,Math.cos(M)*(t.radius??6)*O),_(u,Math.sin(M)*(t.radius??6)*O))))}return{line:f,points:f}}let i=t.rotation??0,r=Math.cos(i),p=Math.sin(i);n=n.map(([s,c])=>[s*r-c*p,s*p+c*r]);let d=t.inner?n.map(([s,c])=>{let u=Math.atan2(c,s);return[Math.cos(u)*t.inner,Math.sin(u)*t.inner]}):void 0;e=Rt(n,o,a,d);let m=t.type==="rod"?_(I(t.from,t.to),.5):t.at??[0,0,0];return e=e.map(s=>({...s,points:s.points.map(c=>I(c,m)),holes:s.holes?.map(c=>c.map(u=>I(u,m)))})),{faces:e,points:e.flatMap(s=>s.points)}}function wt(t){if(t.bounds){let[a,n]=t.bounds;return Array.from({length:8},(o,e)=>[e&1?n[0]:a[0],e&2?n[1]:a[1],e&4?n[2]:a[2]])}return t.parts.flatMap(a=>ot(a).points.flatMap(o=>[o,I(o,a.explode??[0,0,0])]))}function W({driverTeeth:t=16,drivenTeeth:a=32,rpm:n=30,angle:o=0,module:e=2}={}){for(let[i,r]of Object.entries({driverTeeth:t,drivenTeeth:a}))(!Number.isInteger(r)||r<6||r>64)&&y(i+" must be integer 6..64");return v(n,"rpm",-600,600),v(o,"angle",-1e9,1e9),v(e,"module",.1,10),{driverRadius:t*e/2,drivenRadius:a*e/2,centerDistance:(t+a)*e/2,driverAngle:o,drivenAngle:-o*t/a+Math.PI-Math.PI/a,driverRpm:n,drivenRpm:-n*t/a,ratio:a/t}}function X({angle:t=0,radius:a=20,rod:n=70,z:o=20}={}){v(t,"angle",-1e9,1e9),v(a,"radius",.1,200),v(n,"rod",.1,1e3),v(o,"z"),n<=a&&y("connecting rod length must exceed crank radius");let e=[a*Math.cos(t),a*Math.sin(t),o],i=e[0]+Math.sqrt(n*n-e[1]*e[1]);return{crank:e,piston:[i,0,o],position:i,stroke:a*2,angle:t}}function Mt(t,a,n,o=.16){return v(t,"value",-1e9,1e9),v(a,"target",-1e9,1e9),v(n,"delta",0,.1),v(o,"tau",.01,10),t+(a-t)*(1-Math.exp(-n/o))}var $t=Math.PI*2;function nt(t,a){Y(t);let n=a&&!t.bounds?t.parts.filter(o=>!a.cutaway||!o.cover).flatMap(o=>ot(o).points.map(e=>I(e,_(o.explode??[0,0,0],a.explode??0)))):wt(t);return ct(n.length?n:[[0,0,0],[1,1,1]],600,340,{pad:24,azimuth:t.azimuth??45,elevation:t.elevation??30})}var At=t=>t.map(([a,n],o)=>(o?"L":"M")+Math.round(a*10)/10+" "+Math.round(n*10)/10).join("")+"Z";function mt(t,a,{explode:n=0,selected:o="all",cutaway:e=!1,pose:i={}}={},r=new Map){if(typeof n!="number"||!Number.isFinite(n)||n<0||n>1)throw Error("Motion mechanism: explode must be 0..1");if(typeof o!="string"||typeof e!="boolean")throw Error("Motion mechanism: selected must be text and cutaway boolean");if(!i||typeof i!="object"||Array.isArray(i))throw Error("Motion mechanism: pose must be an object");for(let c of Object.keys(i))if(!t.parts.some(u=>u.id===c))throw Error("Motion mechanism: unknown pose part "+c);let p=(a.azimuth??45)*$t/360,d=(a.elevation??30)*$t/360,m=[Math.cos(p)*Math.cos(d),Math.sin(p)*Math.cos(d),Math.sin(d)],s=[];for(let c of t.parts){if(e&&c.cover)continue;let u=i[c.id]??{};for(let $ of Object.keys(u))if(!["at","rotation","from","to"].includes($))throw Error("Motion mechanism: unsupported pose field "+$);let f={...c,...u},g=JSON.stringify(f),h=r.get(c.id);h?.key!==g&&(Y({parts:[f]}),h={key:g,...ot(f)},r.set(c.id,h));let M=_(f.explode??[0,0,0],n),O=Math.min(...h.points.map($=>$[2]))+M[2],N=o==="all"||o===c.id||o===c.group;if(h.line){let $=h.line.map(P=>I(P,M));s.push({floor:O,key:f.id+"_line",part:f.id,group:f.group,d:$.map((P,A)=>(A?"L":"M")+q(P,a).join(" ")).join(""),depth:tt($[Math.floor($.length/2)],a),line:!0,tone:1,material:f.material??"metal",active:N});continue}for(let[$,P]of h.faces.entries()){if(dt(P.normal,m)<=1e-4)continue;let w=P.points.map(S=>I(S,M)),T=P.holes?.map(S=>S.map(H=>I(H,M))),D=_(w.reduce((S,H)=>I(S,H),[0,0,0]),1/w.length),G=dt(P.normal,[-.25,-.4,.88]);s.push({floor:O,key:f.id+"_"+$,part:f.id,group:f.group,d:At(w.map(S=>q(S,a)))+(T??[]).map(S=>At(S.map(H=>q(H,a)))).join(""),depth:tt(D,a),line:!1,tone:G>.5?0:G>.1?1:G>-.4?2:3,material:f.material??"metal",active:N})}}if(s.length>8192)throw Error("Motion mechanism: face budget exceeded");return s.sort((c,u)=>c.floor-u.floor||c.depth-u.depth||c.key.localeCompare(u.key))}var z=(t,a,n,o,e,i={})=>({id:t,type:"box",label:a,at:n,size:o,group:e,...i}),F=(t,a,n,o,e,i,r={})=>({id:t,type:"cylinder",label:a,at:n,radius:o,height:e,group:i,...r});function ut(t,a,n,o,e=3,i=18){return[[-1,-1],[-1,1],[1,-1],[1,1]].map(([r,p],d)=>F(o+"_bolt_"+d,"\\u56FA\\u5B9A\\u87BA\\u6813",[t+r*i,a+p*i,n],e,3,o,{material:"dark",explode:[0,0,26]}))}function ft(){return{title:"\\u5206\\u5C42\\u7ED3\\u6784 \\xB7 \\u793A\\u610F\\u88C5\\u914D",groups:[{id:"base",label:"\\u5E95\\u5EA7",description:"\\u652F\\u6491\\u6574\\u4F53\\uFF0C\\u5E76\\u63D0\\u4F9B\\u5B89\\u88C5\\u4F4D\\u7F6E\\u3002"},{id:"board",label:"\\u529F\\u80FD\\u677F",description:"\\u8FDE\\u63A5\\u8F93\\u5165\\u4E0E\\u5904\\u7406\\u6A21\\u5757\\uFF1B\\u793A\\u610F\\u7ED3\\u6784\\uFF0C\\u4E0D\\u5BF9\\u5E94\\u7279\\u5B9A\\u4EA7\\u54C1\\u3002"},{id:"sink",label:"\\u6563\\u70ED\\u5C42",description:"\\u5C06\\u70ED\\u91CF\\u4F20\\u5230\\u66F4\\u5927\\u7684\\u8868\\u9762\\u79EF\\u3002"},{id:"cover",label:"\\u5916\\u58F3",description:"\\u4FDD\\u62A4\\u5185\\u90E8\\uFF1B\\u5256\\u5F00\\u9009\\u9879\\u901A\\u8FC7\\u9690\\u85CF\\u5916\\u58F3\\u5C55\\u793A\\u7ED3\\u6784\\u3002"}],parts:[z("base","\\u5B89\\u88C5\\u5E95\\u5EA7",[0,0,0],[120,85,10],"base",{round:6,material:"metal"}),...[-1,1].flatMap((t,a)=>[-1,1].map((n,o)=>F("foot_"+a+o,"\\u9632\\u6ED1\\u811A",[t*46,n*30,-8],6,7,"base",{material:"dark"}))),z("board","\\u529F\\u80FD\\u677F",[0,0,15],[96,62,4],"board",{round:3,material:"cool",explode:[0,0,35]}),z("chip","\\u5904\\u7406\\u6A21\\u5757",[-16,0,22],[25,24,10],"board",{round:2,material:"dark",explode:[0,0,35]}),z("connector","\\u8FDE\\u63A5\\u7AEF\\u53E3",[32,0,24],[16,36,14],"board",{round:2,material:"warm",explode:[0,0,35]}),...ut(0,0,20,"board",2,24),z("spreader","\\u5BFC\\u70ED\\u5E95\\u677F",[-16,0,32],[44,42,5],"sink",{round:2,material:"metal",explode:[-10,0,65]}),...Array.from({length:7},(t,a)=>z("fin_"+a,"\\u6563\\u70ED\\u9CCD\\u7247",[-34+a*6,0,44],[2.4,40,20],"sink",{round:1,material:"metal",explode:[-10,0,65]})),z("top","\\u9876\\u76D6",[0,0,61],[124,89,5],"cover",{round:6,cover:!0,material:"metal",explode:[12,0,85]}),z("side","\\u4FA7\\u677F",[0,-44,32],[124,4,58],"cover",{round:2,cover:!0,material:"metal",explode:[12,-22,50]})]}}function pt({driverTeeth:t=16,drivenTeeth:a=32,module:n=1.5}={}){let o=W({driverTeeth:t,drivenTeeth:a,module:n}),e=o.centerDistance;return{title:"\\u9F7F\\u8F6E\\u4F20\\u52A8 \\xB7 \\u7B80\\u5316\\u76F4\\u9F7F\\u8F6E\\u793A\\u610F",azimuth:70,elevation:55,groups:[{id:"frame",label:"\\u652F\\u67B6",description:"\\u56FA\\u5B9A\\u8F74\\u5FC3\\u4F4D\\u7F6E\\uFF1B\\u4E24\\u8F74\\u4E2D\\u5FC3\\u8DDD\\u7531\\u9F7F\\u6570\\u4E0E\\u6A21\\u6570\\u5171\\u540C\\u786E\\u5B9A\\u3002"},{id:"driver",label:"\\u4E3B\\u52A8\\u8F6E",description:"\\u8F93\\u5165\\u8F6C\\u901F\\uFF0C\\u7531\\u9F7F\\u6570\\u51B3\\u5B9A\\u8282\\u5706\\u534A\\u5F84\\u3002"},{id:"driven",label:"\\u4ECE\\u52A8\\u8F6E",description:"\\u5916\\u556E\\u5408\\u8F6C\\u5411\\u76F8\\u53CD\\uFF0C\\u8F6C\\u901F\\u6309\\u9F7F\\u6570\\u6BD4\\u53D8\\u5316\\u3002"},{id:"cover",label:"\\u5916\\u58F3",description:"\\u9690\\u85CF\\u76D6\\u677F\\u4EE5\\u89C2\\u5BDF\\u4F20\\u52A8\\uFF1B\\u4E0D\\u662F\\u52A0\\u5DE5\\u6216\\u53D7\\u529B\\u4EFF\\u771F\\u3002"}],parts:[z("base","\\u5B89\\u88C5\\u5E95\\u5EA7",[30,0,-8],[140,90,10],"frame",{round:6,material:"metal"}),...ut(30,0,0,"frame",3,32),...[0,e].flatMap((i,r)=>[F("bearing_"+r,"\\u8F74\\u627F\\u5EA7",[i,0,4],10,12,"frame",{inner:4,material:"dark"}),F("shaft_"+r,"\\u4F20\\u52A8\\u8F74",[i,0,16],3.8,28,r?"driven":"driver",{material:"metal",explode:[r?24:-24,0,20]}),F("hub_"+r,"\\u8F6E\\u6BC2",[i,0,27],6,6,r?"driven":"driver",{inner:3.8,material:"warm",explode:[r?24:-24,0,20]})]),{id:"driverGear",type:"gear",label:"\\u4E3B\\u52A8\\u9F7F\\u8F6E",group:"driver",at:[0,0,20],radius:o.driverRadius,teeth:t,module:n,height:7,inner:4,material:"accent",explode:[-24,0,20]},{id:"drivenGear",type:"gear",label:"\\u4ECE\\u52A8\\u9F7F\\u8F6E",group:"driven",at:[e,0,20],radius:o.drivenRadius,teeth:a,module:n,height:7,inner:4,material:"cool",rotation:o.drivenAngle,explode:[24,0,20]},z("cover","\\u9632\\u62A4\\u76D6\\u677F",[30,0,36],[140,90,4],"cover",{round:6,cover:!0,material:"metal",explode:[0,0,62]})]}}function ht({radius:t=20,rod:a=70,angle:n=0}={}){let o=X({radius:t,rod:a,angle:n,z:28});return{title:"\\u66F2\\u67C4\\u8FDE\\u6746 \\xB7 \\u65CB\\u8F6C\\u8F6C\\u4E3A\\u5F80\\u590D",groups:[{id:"frame",label:"\\u652F\\u67B6\\u4E0E\\u5BFC\\u8F68",description:"\\u652F\\u6491\\u8F74\\u5FC3\\uFF0C\\u9650\\u5236\\u6ED1\\u5757\\u6CBF\\u540C\\u4E00\\u65B9\\u5411\\u8FD0\\u52A8\\u3002"},{id:"crank",label:"\\u66F2\\u67C4",description:"\\u66F2\\u67C4\\u7ED5\\u56FA\\u5B9A\\u8F74\\u5FC3\\u65CB\\u8F6C\\u3002"},{id:"rod",label:"\\u8FDE\\u6746",description:"\\u8FDE\\u63A5\\u66F2\\u67C4\\u9500\\u548C\\u6ED1\\u5757\\uFF0C\\u957F\\u5EA6\\u4FDD\\u6301\\u4E0D\\u53D8\\u3002"},{id:"piston",label:"\\u6ED1\\u5757",description:"\\u6CBF\\u5BFC\\u8F68\\u5F80\\u590D\\uFF1B\\u5B8C\\u6574\\u884C\\u7A0B\\u7B49\\u4E8E\\u66F2\\u67C4\\u534A\\u5F84\\u7684\\u4E24\\u500D\\u3002"}],parts:[z("base","\\u5B89\\u88C5\\u5E95\\u5EA7",[35,0,-6],[175,80,10],"frame",{round:6,material:"metal"}),...ut(35,0,1,"frame",3,30),F("bearing","\\u66F2\\u8F74\\u8F74\\u627F",[0,0,7],11,15,"frame",{inner:4,material:"dark"}),F("axle","\\u66F2\\u8F74",[0,0,15],3.8,26,"crank",{material:"metal",explode:[0,-18,18]}),F("flywheel","\\u66F2\\u67C4\\u76D8",[0,0,20],t+6,6,"crank",{inner:4,material:"accent",explode:[0,-18,18]}),z("railA","\\u5BFC\\u8F68",[74,-16,13],[85,5,6],"frame",{round:1,material:"dark"}),z("railB","\\u5BFC\\u8F68",[74,16,13],[85,5,6],"frame",{round:1,material:"dark"}),F("crankPin","\\u66F2\\u67C4\\u9500",o.crank,3,12,"crank",{material:"warm",explode:[0,-18,18]}),{id:"link",type:"rod",label:"\\u8FDE\\u6746",from:o.crank,to:o.piston,radius:2.4,group:"rod",material:"metal",explode:[0,0,45]},z("piston","\\u6ED1\\u5757",[o.position,0,22],[18,24,16],"piston",{round:3,material:"cool",explode:[20,0,18]}),F("pistonPin","\\u6ED1\\u5757\\u9500",o.piston,3,10,"piston",{material:"warm",explode:[20,0,18]})]}}var St=`\n.mui-mechanism{font:15px/1.7 system-ui,sans-serif;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:24px;padding:20px;max-width:100%;box-sizing:border-box}.mui-mechanism *{box-sizing:border-box}.mui-mechanism h2{font-size:22px;line-height:1.35;margin:0 0 8px;font-weight:750}.mui-mechanism p{margin:0;color:var(--canvas-muted)}\n.mui-mechanism-svg{display:block;width:100%;height:auto;max-height:420px;touch-action:pan-y}.mui-mechanism-svg path{stroke:color-mix(in srgb,var(--canvas-ink) 38%,var(--canvas-bg));stroke-width:.8;stroke-linejoin:round;vector-effect:non-scaling-stroke;cursor:pointer;fill:var(--mech-base,var(--canvas-soft))}.mui-mechanism-svg [data-material=metal]{--mech-base:color-mix(in srgb,var(--canvas-muted) 32%,var(--canvas-bg))}.mui-mechanism-svg [data-material=dark]{--mech-base:color-mix(in srgb,var(--canvas-ink) 78%,var(--canvas-bg))}.mui-mechanism-svg [data-material=accent]{--mech-base:var(--canvas-accent)}.mui-mechanism-svg [data-material=cool]{--mech-base:color-mix(in srgb,#22998a 70%,var(--canvas-bg))}.mui-mechanism-svg [data-material=warm]{--mech-base:color-mix(in srgb,#dd9c42 75%,var(--canvas-bg))}\n.mui-mechanism-svg [data-tone="0"]{fill:color-mix(in srgb,var(--mech-base) 74%,var(--canvas-bg))}.mui-mechanism-svg [data-tone="1"]{fill:var(--mech-base)}.mui-mechanism-svg [data-tone="2"]{fill:color-mix(in srgb,var(--mech-base) 85%,var(--canvas-ink))}.mui-mechanism-svg [data-tone="3"]{fill:color-mix(in srgb,var(--mech-base) 68%,var(--canvas-ink))}.mui-mechanism-svg [data-line]{fill:none;stroke:var(--mech-base);stroke-width:2}.mui-mechanism-svg [data-active=false]{opacity:.2}.mui-mechanism-svg [data-active=true]{opacity:1}\n.mui-mechanism-nav{display:flex;flex-wrap:wrap;gap:7px;margin:8px 0 12px}.mui-mechanism button{font:inherit;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:999px;padding:6px 13px;cursor:pointer;min-height:36px}.mui-mechanism button[aria-pressed=true]{color:var(--canvas-bg);background:var(--canvas-ink);border-color:var(--canvas-ink)}.mui-mechanism button:focus-visible,.mui-mechanism input:focus-visible{outline:2px solid var(--canvas-accent);outline-offset:3px}.mui-mechanism button:disabled{opacity:.5;cursor:default}\n.mui-mechanism-controls{display:flex;align-items:center;flex-wrap:wrap;gap:14px;padding:12px 14px;border-radius:16px;background:var(--canvas-soft);margin:8px 0}.mui-mechanism-controls label{display:flex;align-items:center;gap:9px;flex:1 1 180px;min-width:0}.mui-mechanism-controls input[type=range]{flex:1;min-width:70px;accent-color:var(--canvas-accent)}.mui-mechanism-controls input[type=checkbox]{accent-color:var(--canvas-accent)}.mui-mechanism-controls output{font-variant-numeric:tabular-nums;min-width:40px;text-align:right;font-weight:650}.mui-mechanism-readout{display:block;padding:10px 0;font-weight:700;font-variant-numeric:tabular-nums;color:var(--canvas-ink)}.mui-mechanism-description{min-height:0;font-size:14px}\n.mui-mechanism[data-style=editorial]{border:0;border-top:1px solid var(--canvas-line);border-radius:0;padding:16px 0}.mui-mechanism[data-style=editorial] h2{font-family:ui-serif,Georgia,serif;font-weight:650}.mui-mechanism[data-style=editorial] .mui-mechanism-controls{border-radius:0;background:transparent;border-block:1px solid var(--canvas-line)}\n.mui-mechanism[data-style=technical]{border-radius:10px}.mui-mechanism[data-style=technical] button,.mui-mechanism[data-style=technical] .mui-mechanism-controls{border-radius:6px}.mui-mechanism[data-style=technical] .mui-mechanism-readout{font-family:ui-monospace,Consolas,monospace}\n.mui-mechanism[data-style=soft]{border:0;background:var(--canvas-soft);border-radius:28px 28px 28px 10px}.mui-mechanism[data-style=soft] .mui-mechanism-controls{background:var(--canvas-bg);border-radius:22px}.mui-mechanism[data-style=expressive] h2{font-size:28px;font-weight:850;border-left:5px solid var(--canvas-accent);padding-left:14px}.mui-mechanism[data-style=expressive]{border:0;border-radius:0}.mui-mechanism[data-style=prismframe]{border:1.5px solid var(--canvas-line);box-shadow:4px 5px 0 color-mix(in srgb,var(--canvas-accent) 14%,var(--canvas-bg))}.mui-mechanism[data-style=aurora]{border-radius:28px;box-shadow:0 16px 30px -25px #30204d66}.mui-mechanism[data-style=aurora] .mui-mechanism-controls{border-radius:24px}\n@media(max-width:500px){.mui-mechanism{padding:14px;border-radius:20px}.mui-mechanism h2{font-size:20px}.mui-mechanism-controls{padding:10px}.mui-mechanism-nav{gap:5px}.mui-mechanism button{padding:6px 10px;font-size:14px}}\n@media(prefers-reduced-motion:reduce){.mui-mechanism *{animation:none!important;transition:none!important}}\n@media(forced-colors:active){.mui-mechanism-svg path{fill:Canvas;stroke:CanvasText}.mui-mechanism button[aria-pressed=true]{background:Highlight;color:HighlightText}}\n`;var xt="http://www.w3.org/2000/svg",C=(t,a,n)=>{let o=document.createElement(t);return a&&(o.className=a),n!==void 0&&(o.textContent=n),o};function Ft(t){function a(o,e){let i=typeof o=="string"?document.querySelector(o):o;if(!i||!i.replaceChildren)throw Error("Motion mechanism: target element not found");Y(e);let r=structuredClone({...e,onSelect:void 0}),p=nt(r),d={explode:0,selected:"all",cutaway:!1,pose:{}},m=!1,s="",c="",u=0,f=new Map,g=new Map,h=new Map,M=[],O=C("section","mui-mechanism"),N=C("h2",null,r.title??"\\u7ED3\\u6784\\u56FE\\u89E3"),$=document.createElementNS(xt,"svg"),P=document.createElementNS(xt,"g"),A=C("div","mui-mechanism-nav"),w=C("div","mui-mechanism-controls"),T=C("p","mui-mechanism-description"),D=C("output","mui-mechanism-readout"),G=C("style");G.textContent=St,N.hidden=r.title==="",O.setAttribute("aria-label",r.title??"\\u7ED3\\u6784\\u56FE\\u89E3"),$.setAttribute("class","mui-mechanism-svg"),$.setAttribute("viewBox","0 0 600 340"),$.setAttribute("role","img"),$.setAttribute("aria-label","\\u53EF\\u62C6\\u89E3\\u7684\\u7ED3\\u6784\\u793A\\u610F\\u56FE\\uFF1B\\u4F7F\\u7528\\u4E0B\\u65B9\\u6309\\u94AE\\u9009\\u62E9\\u90E8\\u4EF6"),$.append(P),O.append(G,N,$,A,w,D,T),i.replaceChildren(O);let S=()=>r.groups?.length?r.groups:r.parts.map(l=>({id:l.id,label:l.label??l.id,description:l.description??""}));function H(l){r.bind?.selected?t.setState({[r.bind.selected]:l}):typeof e.onSelect=="function"?e.onSelect(l):Q({selected:l})}function K(){if(A.replaceChildren(),h.clear(),!r.bind?.selected&&typeof e.onSelect!="function"){A.hidden=!0;return}A.hidden=!1;for(let l of[{id:"all",label:"\\u5168\\u90E8",description:""},...S()]){let b=C("button",null,l.label);b.type="button",b.setAttribute("aria-pressed",String(d.selected===l.id)),b.addEventListener("click",()=>H(l.id)),h.set(l.id,b),A.append(b)}}let x,rt,L;if(r.bind?.explode){let l=C("label",null,"\\u62C6\\u89E3\\u8FDB\\u5EA6");x=C("input"),x.type="range",x.min="0",x.max="1",x.step=".01",x.setAttribute("aria-label","\\u62C6\\u89E3\\u8FDB\\u5EA6"),rt=C("output"),x.addEventListener("input",()=>t.setState({[r.bind.explode]:Number(x.value)})),l.append(x,rt),w.append(l)}if(r.bind?.cutaway&&r.parts.some(l=>l.cover)){let l=C("label",null,"\\u5256\\u5F00\\u5916\\u58F3");L=C("input"),L.type="checkbox",L.setAttribute("aria-label","\\u5256\\u5F00\\u5916\\u58F3"),L.addEventListener("change",()=>t.setState({[r.bind.cutaway]:L.checked})),l.prepend(L),w.append(l)}w.hidden=!w.childNodes.length;function jt(l){let b=JSON.stringify([l.explode,l.cutaway]);b!==s&&(p=nt(r,l),s=b);let E=mt(r,p,l,f),k=new Set;for(let j of E){k.add(j.key);let R=g.get(j.key);R||(R=document.createElementNS(xt,"path"),R.setAttribute("fill-rule","evenodd"),g.set(j.key,R));for(let[gt,bt]of Object.entries({d:j.d,"data-part":j.part,"data-material":j.material,"data-tone":j.tone,"data-active":j.active}))R.getAttribute(gt)!==String(bt)&&R.setAttribute(gt,String(bt));j.line?R.setAttribute("data-line",""):R.removeAttribute("data-line")}for(let[j,R]of g)k.has(j)||(R.remove(),g.delete(j));let Z=E.map(j=>j.key).join("|");if(Z!==c){for(let j of E)P.append(g.get(j.key));c=Z}u++}function Q(l={}){if(m)return;for(let k of Object.keys(l))if(!["explode","selected","cutaway","pose","parts","readout"].includes(k))throw Error("Motion mechanism: unknown update field "+k);if(l.parts){let k={...r,parts:l.parts};Y(k);let Z=nt(k);mt(k,Z,{...d,...l},new Map),r=k,p=Z,f.clear(),c="",s=""}let b={...d,...l};l.pose&&(b.pose=l.pose),jt(b),d=b;for(let[k,Z]of h)Z.setAttribute("aria-pressed",String(b.selected===k));let E=S().find(k=>k.id===b.selected)??r.parts.find(k=>k.id===b.selected);T.textContent=E?.description??(b.selected==="all"?"\\u9009\\u62E9\\u4E00\\u4E2A\\u90E8\\u4EF6\\uFF0C\\u67E5\\u770B\\u5B83\\u7684\\u804C\\u8D23\\uFF1B\\u62C6\\u89E3\\u53EA\\u5C55\\u793A\\u88C5\\u914D\\u5173\\u7CFB\\u3002":""),x&&(x.value=String(b.explode),rt.textContent=Math.round(b.explode*100)+"%"),L&&(L.checked=b.cutaway),l.readout!==void 0&&(D.textContent=String(l.readout))}return $.addEventListener("click",l=>{let b=l.target.closest("[data-part]");if(!b)return;let E=r.parts.find(k=>k.id===b.getAttribute("data-part"));E&&H(r.groups?.length?E.group??E.id:E.id)}),K(),M.push(t.subscribe(l=>{if(m)return;let b={};for(let[E,k]of Object.entries(r.bind??{})){if(!Object.hasOwn(l.state,k))throw Error("Motion mechanism: bind."+E+" names undeclared state "+k);b[E]=l.state[k]}O.dataset.style=l.theme?.visualStyle??"";for(let E of h.values())E.disabled=l.disabled;x&&(x.disabled=l.disabled),L&&(L.disabled=l.disabled),Q(b)})),Object.freeze({update:Q,pose:l=>Q({pose:l}),stats:()=>({frames:u,faces:g.size,parts:r.parts.length}),destroy(){m||(m=!0,M.forEach(l=>l()),g.clear(),f.clear(),i.replaceChildren())}})}function n(o,e,i={}){if(!["assembly","gears","crank"].includes(e))throw Error("Motion mechanism: demo must be assembly/gears/crank");let r=i.bind??{},p=()=>t.snapshot.state,d=(A,w)=>Object.hasOwn(r,A)?p()[r[A]]:w;for(let[A,w]of Object.entries(r))if(!["explode","selected","cutaway","rpm","teeth","running","angle","radius"].includes(A)||typeof w!="string"||!Object.hasOwn(p(),w))throw Error("Motion mechanism: invalid demo binding "+A);let m=d("angle",0)*Math.PI/180,s=m,c="",u=!1,f=Object.fromEntries(Object.entries(r).filter(([A])=>["explode","selected","cutaway"].includes(A)));function g(){return e==="assembly"?ft():e==="gears"?pt({driverTeeth:i.driverTeeth??16,drivenTeeth:d("teeth",32),module:i.module??1.5}):ht({radius:d("radius",20),rod:i.rod??70})}let h=a(o,{...g(),...i.title===void 0?{}:{title:i.title},bind:f}),M=!1;function O(A=0,w=!1,T=!0){if(M)return;let D=d("rpm",30),G=d("running",!1),S=d("angle",0)*Math.PI/180,H=s;S!==m?(H=S,m=S):G&&T&&!w&&(H+=D*Math.PI*2/60*A),s=H;let K=JSON.stringify([e,d("teeth",32),d("radius",20)]);if(K!==c&&(h.update({parts:g().parts}),c=K),e==="gears"){let x=W({driverTeeth:i.driverTeeth??16,drivenTeeth:d("teeth",32),rpm:D,angle:s,module:i.module??1.5});h.update({pose:{driverGear:{rotation:x.driverAngle},drivenGear:{rotation:x.drivenAngle}},readout:"\\u4E3B\\u52A8\\u8F6E "+t.formatNumber(x.driverRpm,0)+" rpm \\xB7 \\u4ECE\\u52A8\\u8F6E "+t.formatNumber(x.drivenRpm,2)+" rpm \\xB7 \\u9F7F\\u6570\\u6BD4 "+t.formatNumber(x.ratio,2)+"\\uFF08\\u8D1F\\u53F7\\u8868\\u793A\\u53CD\\u5411\\uFF09"})}else if(e==="crank"){let x=X({angle:s,radius:d("radius",20),rod:i.rod??70,z:28});h.update({pose:{crankPin:{at:x.crank},link:{from:x.crank,to:x.piston},piston:{at:[x.position,0,22]},pistonPin:{at:x.piston}},readout:"\\u66F2\\u67C4\\u89D2 "+t.formatNumber((s*180/Math.PI%360+360)%360,1)+"\\xB0 \\xB7 \\u6ED1\\u5757\\u4F4D\\u7F6E "+t.formatNumber(x.position,2)+" \\xB7 \\u884C\\u7A0B "+t.formatNumber(x.stroke,1)+"\\uFF08\\u793A\\u610F\\u957F\\u5EA6\\u5355\\u4F4D\\uFF09"})}u=w}let N=null,$=()=>{O(0,u,!0),e!=="assembly"&&(d("running",!1)&&!N?N=t.animate(({delta:A,reducedMotion:w,visible:T})=>{T&&!w?O(A,!1,!0):u!==w&&O(0,w,T)}):!d("running",!1)&&N&&(N(),N=null))},P=t.subscribe($);return O(),Object.freeze({...h,destroy(){M||(M=!0,N?.(),P(),h.destroy())}})}return Object.freeze({mount:a,mountDemo:n,gearPair:W,sliderCrank:X,follow:Mt,scenes:Object.freeze({assembly:ft,gears:pt,crank:ht})})}return _t(Tt);})();\n';
289
289
 
290
290
  // lib/visual-audit.js
291
- function measureVisual(root2, nodeId = "") {
291
+ function measureVisual(root2, nodeId = "", inspectCards = () => []) {
292
292
  const issues = [], seen = /* @__PURE__ */ new Set(), coverage = { nodeId, elements: 0, truncated: false, contrastChecked: 0, contrastUncovered: 0 };
293
293
  const styleCache = /* @__PURE__ */ new WeakMap(), styleOf = (el2) => {
294
294
  let css = styleCache.get(el2);
@@ -393,11 +393,32 @@ function measureVisual(root2, nodeId = "") {
393
393
  }
394
394
  a = a.parentElement;
395
395
  }
396
- } else coverage.contrastUncovered++;
396
+ } else {
397
+ coverage.contrastUncovered++;
398
+ if (!el.closest("#stage")) {
399
+ let parent = el.parentElement, backgrounds = [];
400
+ for (let depth = 0; parent instanceof SVGElement && depth < 4; parent = parent.parentElement, depth++) {
401
+ backgrounds = parent.querySelectorAll(":scope > rect");
402
+ if (backgrounds.length) break;
403
+ }
404
+ for (const background2 of backgrounds) {
405
+ const c = styleOf(background2), rect2 = background2.getBoundingClientRect();
406
+ if (c.fill === "none" || parseFloat(c.fillOpacity) === 0 || !parseFloat(background2.getAttribute("rx")) || rect2.width < box2.width * 0.5 || rect2.height < box2.height * 2) continue;
407
+ const matrix = background2.getScreenCTM(), radius = Math.min(parseFloat(background2.getAttribute("rx")) * (matrix ? Math.hypot(matrix.a, matrix.b) : 1), rect2.height / 2, rect2.width / 2);
408
+ const progress = radius ? Math.max(0, Math.min(1, (box2.bottom - (rect2.bottom - radius)) / radius)) : 0, inset = radius * (1 - Math.sqrt(1 - progress * progress));
409
+ const corner = progress > 0 && (box2.left < rect2.left + inset - 1 || box2.right > rect2.right - inset + 1);
410
+ if (box2.left >= rect2.left - 1 && box2.left < rect2.right && box2.top >= rect2.top && box2.top <= rect2.bottom && (box2.bottom > rect2.bottom + 1 || corner)) {
411
+ add2("cardTextOverflow", Math.max(0, box2.bottom - rect2.bottom), el);
412
+ break;
413
+ }
414
+ }
415
+ }
416
+ }
397
417
  }
398
418
  if (text3 || el.matches("svg,canvas,img,video,input,select,textarea,button")) contentBottom = Math.max(contentBottom, box2.bottom);
399
419
  if (el.matches("input:not([type=hidden]),select,textarea,button,[role=button]") && !el.getAttribute("aria-label") && !el.getAttribute("aria-labelledby") && !el.labels?.length && !el.textContent.trim() && !el.getAttribute("title")) add2("missingLabel", void 0, el);
400
420
  }
421
+ for (const issue of inspectCards(root2)) add2("cardTextOverflow", Math.max(0, issue.excess), issue.target);
401
422
  const rect = root2.getBoundingClientRect(), gap = rect.bottom - contentBottom;
402
423
  if (!coverage.truncated && root2.id === "canvas" && rect.height > 320 && gap > Math.max(96, rect.height * 0.25)) add2("bottomWhitespace", gap, root2);
403
424
  Object.defineProperty(issues, "coverage", { value: coverage });
@@ -495,6 +516,133 @@ function createTimelineAPI(animate, capture = false, notify = () => {
495
516
  } }) };
496
517
  }
497
518
 
519
+ // lib/canvas-controls.js
520
+ function createTimelineControlRepair() {
521
+ const originals = /* @__PURE__ */ new WeakMap();
522
+ const rgb = (text3) => {
523
+ const match = text3.match(/^rgba?\(([^)]+)\)$/);
524
+ if (!match) return null;
525
+ const values = match[1].split(/[,\s/]+/).filter(Boolean).map(Number);
526
+ return values.length >= 3 ? [...values.slice(0, 3), values[3] ?? 1] : null;
527
+ };
528
+ const over = (a, b2) => a.slice(0, 3).map((v2, i) => v2 * a[3] + b2[i] * (1 - a[3]));
529
+ const luminance = (c) => c.slice(0, 3).map((v2) => v2 / 255).map((v2) => v2 <= 0.04045 ? v2 / 12.92 : ((v2 + 0.055) / 1.055) ** 2.4).reduce((n2, v2, i) => n2 + v2 * [0.2126, 0.7152, 0.0722][i], 0);
530
+ const contrast = (a, b2) => {
531
+ const x = luminance(a), y2 = luminance(b2);
532
+ return (Math.max(x, y2) + 0.05) / (Math.min(x, y2) + 0.05);
533
+ };
534
+ return () => {
535
+ const stage = document.getElementById("stage"), root2 = document.getElementById("canvas");
536
+ if (!stage || !root2) return;
537
+ for (const el of root2.querySelectorAll("button,output,select,input:not([type=range]):not([type=checkbox]):not([type=radio])")) {
538
+ if (stage.contains(el)) continue;
539
+ let saved = originals.get(el);
540
+ if (saved) for (const [key2, value, priority] of saved) value ? el.style.setProperty(key2, value, priority) : el.style.removeProperty(key2);
541
+ const style = getComputedStyle(el);
542
+ if (style.display === "none" || style.visibility === "hidden") continue;
543
+ const layers = [];
544
+ let uncertain = false;
545
+ for (let parent = el; parent; parent = parent.parentElement) {
546
+ const backgroundStyle = getComputedStyle(parent);
547
+ if (backgroundStyle.backgroundImage !== "none") {
548
+ uncertain = true;
549
+ break;
550
+ }
551
+ const color = rgb(backgroundStyle.backgroundColor);
552
+ if (color) layers.push(color);
553
+ if (color?.[3] === 1) break;
554
+ }
555
+ if (uncertain) continue;
556
+ const background = layers.reverse().reduce((color, layer) => over(layer, color), [255, 255, 255]);
557
+ const foreground = rgb(style.color);
558
+ if (!foreground || contrast(over(foreground, background), background) >= 4.5) continue;
559
+ if (!saved) {
560
+ saved = ["color", "border-color"].map((key2) => [key2, el.style.getPropertyValue(key2), el.style.getPropertyPriority(key2)]);
561
+ originals.set(el, saved);
562
+ }
563
+ const light = [248, 250, 252], dark = [17, 24, 39];
564
+ el.style.setProperty("color", contrast(light, background) > contrast(dark, background) ? "#f8fafc" : "#111827", "important");
565
+ const border = rgb(style.borderTopColor);
566
+ if (parseFloat(style.borderTopWidth) > 0 && border && contrast(over(border, background), background) < 1.5) el.style.setProperty("border-color", "#64748b", "important");
567
+ }
568
+ };
569
+ }
570
+ function canvasContentHeight(root2) {
571
+ const body = getComputedStyle(document.body);
572
+ return Math.ceil(root2.getBoundingClientRect().bottom + window.scrollY + (parseFloat(body.paddingBottom) || 0) + (parseFloat(body.marginBottom) || 0));
573
+ }
574
+
575
+ // lib/canvas-layout.js
576
+ function inspectTextCards(root2, cards) {
577
+ const result = [];
578
+ const cache = /* @__PURE__ */ new WeakMap(), styleOf = (el) => {
579
+ if (!cache.has(el)) cache.set(el, getComputedStyle(el));
580
+ return cache.get(el);
581
+ };
582
+ for (const card2 of cards ?? [...root2.querySelectorAll("article,section,aside,figure,div")].slice(0, 256).reverse()) {
583
+ if (card2.closest("#stage,svg,pre,code,[role=img],[data-motion-layout=preserve]")) continue;
584
+ const css = styleOf(card2), box2 = card2.getBoundingClientRect();
585
+ const radius = Math.max(parseFloat(css.borderBottomLeftRadius) || 0, parseFloat(css.borderBottomRightRadius) || 0);
586
+ if (box2.width < 120 || box2.height < 24 || css.display === "none" || css.visibility === "hidden") continue;
587
+ if (/auto|scroll/.test(css.overflowY)) continue;
588
+ if (!radius && css.boxShadow === "none") continue;
589
+ const padding = parseFloat(css.paddingBottom) || 0, border = parseFloat(css.borderBottomWidth) || 0;
590
+ const bottom = box2.bottom - padding - border;
591
+ let excess = 0, corner = false, target, flow = !["absolute", "fixed"].includes(css.position) && css.transform === "none" && !/auto|scroll/.test(css.overflowY) && !/size/.test(css.contain) && !css.borderBottomLeftRadius.includes("%") && !css.borderBottomRightRadius.includes("%") && !(css.transitionDuration.split(",").some((v2) => parseFloat(v2) > 0) && /(^|,|\s)(height|max-height|all)(,|\s|$)/.test(css.transitionProperty));
592
+ const walker = document.createTreeWalker(card2, NodeFilter.SHOW_TEXT);
593
+ let text3, count = 0;
594
+ while ((text3 = walker.nextNode()) && ++count <= 128) {
595
+ if (!text3.textContent.trim()) continue;
596
+ const el = text3.parentElement;
597
+ if (el.closest("svg,pre,code,script,style,textarea,[role=img]")) continue;
598
+ const style = styleOf(el);
599
+ if (style.visibility === "hidden" || style.display === "none") continue;
600
+ if (style.webkitLineClamp && style.webkitLineClamp !== "none") continue;
601
+ let intentional = false;
602
+ for (let parent = el; parent && parent !== card2; parent = parent.parentElement) {
603
+ const c = styleOf(parent);
604
+ if (/auto|scroll/.test(c.overflowY) || c.webkitLineClamp && c.webkitLineClamp !== "none") {
605
+ intentional = true;
606
+ break;
607
+ }
608
+ }
609
+ if (intentional) continue;
610
+ const range = document.createRange();
611
+ range.selectNode(text3);
612
+ for (const rect of range.getClientRects()) {
613
+ if (!rect.width || !rect.height) continue;
614
+ const amount = rect.bottom - bottom;
615
+ const r = Math.min(radius, box2.height / 2, box2.width / 2);
616
+ const progress = r ? Math.max(0, Math.min(1, (rect.bottom - (box2.bottom - r)) / r)) : 0;
617
+ const inset = r * (1 - Math.sqrt(1 - progress * progress));
618
+ const touchesCorner = progress > 0 && (rect.left < box2.left + inset - 1 || rect.right > box2.right - inset + 1);
619
+ if (amount <= 1 && !touchesCorner) continue;
620
+ target = el;
621
+ excess = Math.max(excess, amount);
622
+ corner ||= touchesCorner;
623
+ for (let parent = el; parent && parent !== card2; parent = parent.parentElement) {
624
+ const c = styleOf(parent);
625
+ if (["absolute", "fixed"].includes(c.position) || c.transform !== "none" || /auto|scroll/.test(c.overflowY) || c.webkitLineClamp && c.webkitLineClamp !== "none") flow = false;
626
+ }
627
+ }
628
+ }
629
+ if (target) result.push({ card: card2, target, excess, corner, radius, flow });
630
+ }
631
+ return result;
632
+ }
633
+ function fitTextCards(root2, inspect) {
634
+ for (const { card: card2 } of inspect(root2)) {
635
+ const issue = inspect(root2, [card2])[0];
636
+ if (!issue?.flow) continue;
637
+ const css = getComputedStyle(card2), box2 = card2.getBoundingClientRect();
638
+ if (issue.corner) card2.style.setProperty("padding-bottom", Math.max(parseFloat(css.paddingBottom) || 0, Math.min(issue.radius, box2.height / 2)) + "px", "important");
639
+ const inset = css.boxSizing === "border-box" ? 0 : ["paddingTop", "paddingBottom", "borderTopWidth", "borderBottomWidth"].reduce((n2, key2) => n2 + (parseFloat(css[key2]) || 0), 0);
640
+ card2.style.setProperty("min-height", Math.max(parseFloat(css.minHeight) || 0, box2.height - inset) + "px", "important");
641
+ card2.style.setProperty("height", "auto", "important");
642
+ card2.style.setProperty("max-height", "none", "important");
643
+ }
644
+ }
645
+
498
646
  // lib/sandbox.js
499
647
  var SANDBOX_LIMITS = Object.freeze({ source: 49152, height: 1e3, message: 16384, rate: 30 });
500
648
  function canvasSnapshot(node, state2, data, derived, disabled, theme) {
@@ -515,7 +663,12 @@ function sandboxDocument(node, channel, nonce) {
515
663
  let snapshot={state:{},data:{},derived:{},disabled:true,theme:{}}, started=false;
516
664
  const listeners=new Set(), send=(type,payload)=>parent.postMessage({dshCanvas:1,channel,type,payload},'*');
517
665
  const report=e=>send('error',String(e?.message??e).slice(0,1000));
518
- const audit=${measureVisual.toString()};let auditTimer;const scheduleAudit=()=>{clearTimeout(auditTimer);auditTimer=setTimeout(()=>{const issues=audit(document.getElementById('canvas'),${json(node.id ?? "")});send('audit',{issues,coverage:issues.coverage})},400)};
666
+ const repairTimelineControls=(${createTimelineControlRepair.toString()})();
667
+ const inspectCards=${inspectTextCards.toString()}, fitCards=${fitTextCards.toString()};
668
+ const contentHeight=${canvasContentHeight.toString()};
669
+ const repairControls=()=>{if(!window.__DSHMotionRender&&timelineAPI.capture.list().length)repairTimelineControls()};
670
+ for(const type of ['click','input','change'])document.addEventListener(type,()=>queueMicrotask(repairControls));
671
+ const audit=${measureVisual.toString()};let auditTimer;const scheduleAudit=()=>{clearTimeout(auditTimer);auditTimer=setTimeout(()=>{repairControls();fitCards(document.getElementById('canvas'),inspectCards);const issues=audit(document.getElementById('canvas'),${json(node.id ?? "")},inspectCards);send('audit',{issues,coverage:issues.coverage})},400)};
519
672
  addEventListener('resize',scheduleAudit);
520
673
  addEventListener('error',e=>report(e.error??e.message));addEventListener('unhandledrejection',e=>report(e.reason));
521
674
  const animations=new Set(), motion=matchMedia('(prefers-reduced-motion: reduce)');
@@ -540,9 +693,9 @@ function sandboxDocument(node, channel, nonce) {
540
693
  const wasStarted=started;
541
694
  if(!started){started=true;document.getElementById('canvas').innerHTML=source.html;const style=document.createElement('style');style.textContent=source.css;document.head.append(style);const script=document.createElement('script');script.nonce=${json(nonce)};script.textContent=source.script;document.body.append(script)}
542
695
  if(wasStarted)for(const fn of listeners)try{fn(api.snapshot)}catch(e){report(e)}
543
- refresh();if(!wasStarted)send('mounted');scheduleAudit();
696
+ fitCards(document.getElementById('canvas'),inspectCards);repairControls();refresh();if(!wasStarted)send('mounted');scheduleAudit();
544
697
  });
545
- let resizePending=false;new ResizeObserver(()=>{if(!started||resizePending)return;resizePending=true;requestAnimationFrame(()=>{resizePending=false;send('height',Math.ceil(document.getElementById('canvas').getBoundingClientRect().height))})}).observe(document.getElementById('canvas'));
698
+ let resizePending=false;new ResizeObserver(()=>{if(!started||resizePending)return;resizePending=true;requestAnimationFrame(()=>{resizePending=false;send('height',contentHeight(document.getElementById('canvas')))})}).observe(document.getElementById('canvas'));
546
699
  send('ready');
547
700
  })();<\/script></body></html>`;
548
701
  }
@@ -3661,7 +3814,7 @@ function updatePreview(html) {
3661
3814
  morph(document.getElementById("canvas"), template.content);
3662
3815
  }
3663
3816
  function previewFrameDocument(channel, nonce) {
3664
- return `<!doctype html><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-${nonce}';style-src 'unsafe-inline';img-src data:;base-uri 'none';form-action 'none';frame-src 'none'"><style>${CANVAS_SYSTEM_CSS}</style><style id="custom"></style><style>#canvas,#canvas *,#canvas *::before,#canvas *::after{animation:none!important;transition:none!important}html,body{overflow:hidden}</style><main id="canvas" inert></main><script nonce="${nonce}">const update=${updatePreview.toString()};addEventListener('message',e=>{if(e.source!==parent||e.data?.channel!==${JSON.stringify(channel)})return;document.getElementById('custom').textContent=e.data.css;for(const [k,v] of Object.entries(e.data.theme||{}))document.documentElement.style.setProperty('--canvas-'+k,v);document.documentElement.dataset.canvasScheme=e.data.theme?.scheme||'light';update(e.data.html)});new ResizeObserver(()=>parent.postMessage({channel:${JSON.stringify(channel)},previewHeight:Math.ceil(document.getElementById('canvas').getBoundingClientRect().height)},'*')).observe(document.getElementById('canvas'));<\/script>`;
3817
+ return `<!doctype html><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none';script-src 'nonce-${nonce}';style-src 'unsafe-inline';img-src data:;base-uri 'none';form-action 'none';frame-src 'none'"><style>${CANVAS_SYSTEM_CSS}</style><style id="custom"></style><style>#canvas,#canvas *,#canvas *::before,#canvas *::after{animation:none!important;transition:none!important}html,body{overflow:hidden}</style><main id="canvas" inert></main><script nonce="${nonce}">const inspectCards=${inspectTextCards.toString()},fitCards=${fitTextCards.toString()};const contentHeight=${canvasContentHeight.toString()};const update=${updatePreview.toString()};addEventListener('message',e=>{if(e.source!==parent||e.data?.channel!==${JSON.stringify(channel)})return;document.getElementById('custom').textContent=e.data.css;for(const [k,v] of Object.entries(e.data.theme||{}))document.documentElement.style.setProperty('--canvas-'+k,v);document.documentElement.dataset.canvasScheme=e.data.theme?.scheme||'light';update(e.data.html);fitCards(document.getElementById('canvas'),inspectCards)});new ResizeObserver(()=>parent.postMessage({channel:${JSON.stringify(channel)},previewHeight:contentHeight(document.getElementById('canvas'))},'*')).observe(document.getElementById('canvas'));<\/script>`;
3665
3818
  }
3666
3819
 
3667
3820
  // src/canvas-preview.js
@@ -3707,7 +3860,7 @@ function CanvasPreview({ node }) {
3707
3860
  var import_react8 = __toESM(require("react"), 1);
3708
3861
 
3709
3862
  // lib/export-runtime-bundle.js
3710
- var EXPORT_RUNTIME = '(() => {\n // lib/presentation.js\n var UI_ICONS = Object.freeze(["sparkles", "sliders", "layers", "chart", "gauge", "cpu", "database", "info", "check", "warning", "arrow", "target", "external", "file", "globe"]);\n var UI_TONES = Object.freeze(["neutral", "accent", "success", "warning", "danger"]);\n var UI_LAYOUTS = Object.freeze(["dashboard", "workbench", "comparison", "guide", "status", "report"]);\n var UI_ACCENTS = Object.freeze(["blue", "teal", "violet", "amber", "rose"]);\n var UI_SURFACES = Object.freeze(["outline", "soft", "featured"]);\n\n // lib/canvas-source.js\n function normalizeCanvasHtml(html) {\n let protectedDepth = 0;\n return html.replace(/<!--[\\s\\S]*?-->|<(?:"[^"]*"|\'[^\']*\'|[^\'">])*>|[^<]+|</g, (token2) => {\n if (token2.startsWith("<")) {\n const tag = token2.match(/^<(\\/)?(pre|code|textarea|script|style)\\b/i);\n if (tag) protectedDepth = Math.max(0, protectedDepth + (tag[1] ? -1 : 1));\n return token2;\n }\n return !protectedDepth && /^(?:\\s|\\\\[rn])+$/.test(token2) ? token2.replace(/\\\\[rn]/g, "\\n") : token2;\n });\n }\n function normalizeCanvasCss(css) {\n let out = "", quote = "", comment = false, last = "";\n for (let i = 0; i < css.length; i++) {\n const c = css[i], next = css[i + 1];\n if (comment) {\n out += c;\n if (c === "*" && next === "/") {\n out += next;\n i++;\n comment = false;\n }\n continue;\n }\n if (quote) {\n out += c;\n if (c === "\\\\" && next !== void 0) {\n out += next;\n i++;\n } else if (c === quote) quote = "";\n continue;\n }\n if (c === "/" && next === "*") {\n out += "/*";\n i++;\n comment = true;\n continue;\n }\n if (c === \'"\' || c === "\'") {\n quote = c;\n out += c;\n last = c;\n continue;\n }\n if (c === "\\\\" && /[rn]/.test(next ?? "") && /[{};]/.test(last)) {\n out += "\\n";\n i++;\n continue;\n }\n out += c;\n if (!/\\s/.test(c)) last = c;\n }\n return out;\n }\n var canvasSource = (node2) => ({ html: normalizeCanvasHtml(node2.html), css: normalizeCanvasCss(node2.css ?? ""), script: node2.script ?? "" });\n\n // lib/mechanism-runtime-bundle.js\n var MECHANISM_RUNTIME = \'var __MotionMechanism=(()=>{var it=Object.defineProperty;var Ot=Object.getOwnPropertyDescriptor;var Et=Object.getOwnPropertyNames;var It=Object.prototype.hasOwnProperty;var zt=(t,a)=>{for(var n in a)it(t,n,{get:a[n],enumerable:!0})},Pt=(t,a,n,o)=>{if(a&&typeof a=="object"||typeof a=="function")for(let e of Et(a))!It.call(t,e)&&e!==n&&it(t,e,{get:()=>a[e],enumerable:!(o=Ot(a,e))||o.enumerable});return t};var _t=t=>Pt(it({},"__esModule",{value:!0}),t);var Tt={};zt(Tt,{createMechanismAPI:()=>Ft});var st=Math.PI/180,Ct=Math.sqrt(1.6);function yt({scale:t,azimuth:a=45,elevation:n=30}){let o=a*st,e=n*st;return{sinA:Math.sin(o),cosA:Math.cos(o),sinE:Math.sin(e),cosE:Math.cos(e),k:t*Ct}}function q([t,a,n],o){let{origin:e}=o,{sinA:i,cosA:r,sinE:p,cosE:d,k:m}=yt(o);return[e[0]+(t*i-a*r)*m,e[1]+((t*r+a*i)*p-n*d)*m]}function tt([t,a,n],o){let{sinA:e,cosA:i,sinE:r,cosE:p}=yt(o);return(t*i+a*e)*p+n*r}function vt({x:t,y:a,w:n,d:o,r:e},i=8){let r=Math.max(0,Math.min(e,n/2,o/2)),p=[[t+n-r,a+r,-90],[t+n-r,a+o-r,0],[t+r,a+o-r,90],[t+r,a+r,180]],d=[];for(let[m,s,c]of p){let u=r>0?i:0;for(let f=0;f<=u;f++){let g=(c+(u?90*f/u:45))*st;d.push([m+r*Math.cos(g),s+r*Math.sin(g)])}}return d}function lt(t,a,n,o=40){return Array.from({length:o},(e,i)=>{let r=i/o*Math.PI*2;return[t+n*Math.cos(r),a+n*Math.sin(r)]})}function ct(t,a,n,{pad:o=24,headroom:e=0,azimuth:i=45,elevation:r=30}={}){let p={origin:[0,0],scale:1,azimuth:i,elevation:r},d=t.map(M=>q(M,p)),m=d.map(([M])=>M),s=d.map(([,M])=>M),c=Math.min(...m),u=Math.max(...m),f=Math.min(...s),g=Math.max(...s),h=Math.min((a-o*2)/(u-c),(n-o*2-e)/(g-f));return{origin:[a/2-(c+u)/2*h,e+(n-e)/2-(f+g)/2*h],scale:h,azimuth:i,elevation:r}}var Nt=Object.freeze({parts:96,teeth:64,faces:8192}),Ht=t=>typeof t=="number"&&Number.isFinite(t),y=t=>{throw Error("Motion mechanism: "+t)},v=(t,a,n=-1e4,o=1e4)=>((!Ht(t)||t<n||t>o)&&y(a+" must be a finite number in "+n+".."+o),t),U=(t,a)=>((!Array.isArray(t)||t.length!==3)&&y(a+" must be [x,y,z]"),t.map((n,o)=>v(n,a+"["+o+"]"))),et=t=>typeof t=="string"&&/^[\\\\p{L}_][\\\\p{L}\\\\p{M}\\\\p{N}_]{0,63}$/u.test(t)&&!["constructor","prototype","__proto__"].includes(t),kt=["box","cylinder","gear","rod","spring"],I=(t,a)=>t.map((n,o)=>n+a[o]),B=(t,a)=>t.map((n,o)=>n-a[o]),_=(t,a)=>t.map(n=>n*a),dt=(t,a)=>t.reduce((n,o,e)=>n+o*a[e],0),V=(t,a)=>[t[1]*a[2]-t[2]*a[1],t[2]*a[0]-t[0]*a[2],t[0]*a[1]-t[1]*a[0]],J=t=>{let a=Math.hypot(...t);return a<1e-6&&y("zero-length axis"),_(t,1/a)};function Y(t){(!t||typeof t!="object"||Array.isArray(t))&&y("scene must be an object"),(!Array.isArray(t.parts)||!t.parts.length||t.parts.length>Nt.parts)&&y("parts requires 1..96 objects");let a=new Set,n=new Set;for(let[o,e]of t.parts.entries()){let i="parts["+o+"]";(!e||typeof e!="object"||!et(e.id)||a.has(e.id))&&y(i+".id must be a unique identifier"),a.add(e.id),kt.includes(e.type)||y(i+".type must be "+kt.join("/")),e.group!==void 0&&(et(e.group)||y(i+".group must be an identifier"),n.add(e.group));for(let r of["label","description"])e[r]!==void 0&&(typeof e[r]!="string"||e[r].length>1024)&&y(i+"."+r+" must be short text");if(e.cover!==void 0&&typeof e.cover!="boolean"&&y(i+".cover must be boolean"),e.material!==void 0&&!["metal","dark","accent","warm","cool"].includes(e.material)&&y(i+".material must be metal/dark/accent/warm/cool"),e.at!==void 0&&U(e.at,i+".at"),e.explode!==void 0&&U(e.explode,i+".explode"),e.rotation!==void 0&&v(e.rotation,i+".rotation",-1e9,1e9),e.axis!==void 0&&!["x","y","z"].includes(e.axis)&&y(i+".axis must be x/y/z"),e.type==="box"){let r=U(e.size,i+".size");r.some(p=>p<=0||p>2e3)&&y(i+".size must be positive and <=2000"),e.round!==void 0&&v(e.round,i+".round",0,Math.min(r[0],r[1])/2)}if(["cylinder","gear"].includes(e.type)&&(v(e.radius,i+".radius",.1,1e3),v(e.height??8,i+".height",.1,1e3),e.inner!==void 0&&v(e.inner,i+".inner",0,e.radius-.01)),e.type==="gear"){let r=v(e.teeth,i+".teeth",6,64);Number.isInteger(r)||y(i+".teeth must be an integer"),e.module!==void 0&&v(e.module,i+".module",.1,e.radius/3)}if(["rod","spring"].includes(e.type)&&(U(e.from,i+".from"),U(e.to,i+".to"),Math.hypot(...B(e.to,e.from))<.1&&y(i+" endpoints must differ"),v(e.radius??2,i+".radius",.1,200)),e.type==="spring"){let r=v(e.turns??8,i+".turns",2,24);Number.isInteger(r)||y(i+".turns must be integer")}}if(t.groups!==void 0){(!Array.isArray(t.groups)||t.groups.length>12)&&y("groups must be an array of <=12 labels");let o=new Set;for(let e of t.groups)(!e||!et(e.id)||o.has(e.id)||!n.has(e.id)||typeof e.label!="string"||e.label.length>128)&&y("groups must name unique existing part groups"),o.add(e.id)}if(t.bounds!==void 0){(!Array.isArray(t.bounds)||t.bounds.length!==2)&&y("bounds must be [minXYZ,maxXYZ]");let[o,e]=t.bounds.map((i,r)=>U(i,"bounds["+r+"]"));o.some((i,r)=>i>=e[r])&&y("bounds min must be below max on every axis")}if(t.azimuth!==void 0&&v(t.azimuth,"azimuth",10,80),t.elevation!==void 0&&v(t.elevation,"elevation",15,70),t.title!==void 0&&(typeof t.title!="string"||t.title.length>256)&&y("title must be short text"),t.bind!==void 0){(!t.bind||typeof t.bind!="object"||Array.isArray(t.bind))&&y("bind must be an object");for(let[o,e]of Object.entries(t.bind))(!["explode","selected","cutaway"].includes(o)||!et(e))&&y("bind only accepts declared state keys for explode/selected/cutaway")}return t}function Lt(t){return t==="x"?[[0,1,0],[0,0,1],[1,0,0]]:t==="y"?[[0,0,1],[1,0,0],[0,1,0]]:[[1,0,0],[0,1,0],[0,0,1]]}var at=(t,a,n,o)=>I(I(_(t[0],a),_(t[1],n)),_(t[2],o));function Rt(t,a,n,o){let e=t.map(([m,s])=>at(n,m,s,-a/2)),i=t.map(([m,s])=>at(n,m,s,a/2)),r=[],p=o?.map(([m,s])=>at(n,m,s,a/2)),d=o?.map(([m,s])=>at(n,m,s,-a/2));r.push({points:i,holes:p?[p.slice().reverse()]:[],normal:n[2]},{points:e.slice().reverse(),holes:d?[d]:[],normal:_(n[2],-1)});for(let m=0;m<t.length;m++){let s=(m+1)%t.length;Math.hypot(...B(e[s],e[m]))<1e-6||(r.push({points:[e[m],e[s],i[s],i[m]],normal:J(V(B(e[s],e[m]),n[2]))}),o&&r.push({points:[d[s],d[m],p[m],p[s]],normal:J(V(B(d[m],d[s]),n[2]))}))}return r}function ot(t){let a=Lt(t.axis),n,o,e;if(t.type==="box"&&(n=vt({x:-t.size[0]/2,y:-t.size[1]/2,w:t.size[0],d:t.size[1],r:t.round??Math.min(2,t.size[0]/2,t.size[1]/2)},3),o=t.size[2]),t.type==="cylinder"&&(n=lt(0,0,t.radius,24),o=t.height??8),t.type==="gear"){let s=Math.PI*2/t.teeth,c=t.module??t.radius*2/t.teeth;n=[];for(let u=0;u<t.teeth;u++)for(let[f,g]of[[-.5,t.radius-c*.85],[-.32,t.radius-c*.85],[-.17,t.radius+c*.7],[.17,t.radius+c*.7],[.32,t.radius-c*.85]]){let h=(u+f)*s;n.push([Math.cos(h)*g,Math.sin(h)*g])}o=t.height??8}if(t.type==="rod"){let s=J(B(t.to,t.from)),c=J(V(s,Math.abs(s[2])<.9?[0,0,1]:[0,1,0]));a=[c,V(s,c),s],n=lt(0,0,t.radius??2,16),o=Math.hypot(...B(t.to,t.from))}if(t.type==="spring"){let s=J(B(t.to,t.from)),c=J(V(s,Math.abs(s[2])<.9?[0,0,1]:[0,1,0])),u=V(s,c),f=[];for(let g=0;g<=128;g++){let h=g/128,M=h*(t.turns??8)*Math.PI*2,O=Math.min(1,h*12,(1-h)*12);f.push(I(I(t.from,_(B(t.to,t.from),h)),I(_(c,Math.cos(M)*(t.radius??6)*O),_(u,Math.sin(M)*(t.radius??6)*O))))}return{line:f,points:f}}let i=t.rotation??0,r=Math.cos(i),p=Math.sin(i);n=n.map(([s,c])=>[s*r-c*p,s*p+c*r]);let d=t.inner?n.map(([s,c])=>{let u=Math.atan2(c,s);return[Math.cos(u)*t.inner,Math.sin(u)*t.inner]}):void 0;e=Rt(n,o,a,d);let m=t.type==="rod"?_(I(t.from,t.to),.5):t.at??[0,0,0];return e=e.map(s=>({...s,points:s.points.map(c=>I(c,m)),holes:s.holes?.map(c=>c.map(u=>I(u,m)))})),{faces:e,points:e.flatMap(s=>s.points)}}function wt(t){if(t.bounds){let[a,n]=t.bounds;return Array.from({length:8},(o,e)=>[e&1?n[0]:a[0],e&2?n[1]:a[1],e&4?n[2]:a[2]])}return t.parts.flatMap(a=>ot(a).points.flatMap(o=>[o,I(o,a.explode??[0,0,0])]))}function W({driverTeeth:t=16,drivenTeeth:a=32,rpm:n=30,angle:o=0,module:e=2}={}){for(let[i,r]of Object.entries({driverTeeth:t,drivenTeeth:a}))(!Number.isInteger(r)||r<6||r>64)&&y(i+" must be integer 6..64");return v(n,"rpm",-600,600),v(o,"angle",-1e9,1e9),v(e,"module",.1,10),{driverRadius:t*e/2,drivenRadius:a*e/2,centerDistance:(t+a)*e/2,driverAngle:o,drivenAngle:-o*t/a+Math.PI-Math.PI/a,driverRpm:n,drivenRpm:-n*t/a,ratio:a/t}}function X({angle:t=0,radius:a=20,rod:n=70,z:o=20}={}){v(t,"angle",-1e9,1e9),v(a,"radius",.1,200),v(n,"rod",.1,1e3),v(o,"z"),n<=a&&y("connecting rod length must exceed crank radius");let e=[a*Math.cos(t),a*Math.sin(t),o],i=e[0]+Math.sqrt(n*n-e[1]*e[1]);return{crank:e,piston:[i,0,o],position:i,stroke:a*2,angle:t}}function Mt(t,a,n,o=.16){return v(t,"value",-1e9,1e9),v(a,"target",-1e9,1e9),v(n,"delta",0,.1),v(o,"tau",.01,10),t+(a-t)*(1-Math.exp(-n/o))}var $t=Math.PI*2;function nt(t,a){Y(t);let n=a&&!t.bounds?t.parts.filter(o=>!a.cutaway||!o.cover).flatMap(o=>ot(o).points.map(e=>I(e,_(o.explode??[0,0,0],a.explode??0)))):wt(t);return ct(n.length?n:[[0,0,0],[1,1,1]],600,340,{pad:24,azimuth:t.azimuth??45,elevation:t.elevation??30})}var At=t=>t.map(([a,n],o)=>(o?"L":"M")+Math.round(a*10)/10+" "+Math.round(n*10)/10).join("")+"Z";function mt(t,a,{explode:n=0,selected:o="all",cutaway:e=!1,pose:i={}}={},r=new Map){if(typeof n!="number"||!Number.isFinite(n)||n<0||n>1)throw Error("Motion mechanism: explode must be 0..1");if(typeof o!="string"||typeof e!="boolean")throw Error("Motion mechanism: selected must be text and cutaway boolean");if(!i||typeof i!="object"||Array.isArray(i))throw Error("Motion mechanism: pose must be an object");for(let c of Object.keys(i))if(!t.parts.some(u=>u.id===c))throw Error("Motion mechanism: unknown pose part "+c);let p=(a.azimuth??45)*$t/360,d=(a.elevation??30)*$t/360,m=[Math.cos(p)*Math.cos(d),Math.sin(p)*Math.cos(d),Math.sin(d)],s=[];for(let c of t.parts){if(e&&c.cover)continue;let u=i[c.id]??{};for(let $ of Object.keys(u))if(!["at","rotation","from","to"].includes($))throw Error("Motion mechanism: unsupported pose field "+$);let f={...c,...u},g=JSON.stringify(f),h=r.get(c.id);h?.key!==g&&(Y({parts:[f]}),h={key:g,...ot(f)},r.set(c.id,h));let M=_(f.explode??[0,0,0],n),O=Math.min(...h.points.map($=>$[2]))+M[2],N=o==="all"||o===c.id||o===c.group;if(h.line){let $=h.line.map(P=>I(P,M));s.push({floor:O,key:f.id+"_line",part:f.id,group:f.group,d:$.map((P,A)=>(A?"L":"M")+q(P,a).join(" ")).join(""),depth:tt($[Math.floor($.length/2)],a),line:!0,tone:1,material:f.material??"metal",active:N});continue}for(let[$,P]of h.faces.entries()){if(dt(P.normal,m)<=1e-4)continue;let w=P.points.map(S=>I(S,M)),T=P.holes?.map(S=>S.map(H=>I(H,M))),D=_(w.reduce((S,H)=>I(S,H),[0,0,0]),1/w.length),G=dt(P.normal,[-.25,-.4,.88]);s.push({floor:O,key:f.id+"_"+$,part:f.id,group:f.group,d:At(w.map(S=>q(S,a)))+(T??[]).map(S=>At(S.map(H=>q(H,a)))).join(""),depth:tt(D,a),line:!1,tone:G>.5?0:G>.1?1:G>-.4?2:3,material:f.material??"metal",active:N})}}if(s.length>8192)throw Error("Motion mechanism: face budget exceeded");return s.sort((c,u)=>c.floor-u.floor||c.depth-u.depth||c.key.localeCompare(u.key))}var z=(t,a,n,o,e,i={})=>({id:t,type:"box",label:a,at:n,size:o,group:e,...i}),F=(t,a,n,o,e,i,r={})=>({id:t,type:"cylinder",label:a,at:n,radius:o,height:e,group:i,...r});function ut(t,a,n,o,e=3,i=18){return[[-1,-1],[-1,1],[1,-1],[1,1]].map(([r,p],d)=>F(o+"_bolt_"+d,"\\\\u56FA\\\\u5B9A\\\\u87BA\\\\u6813",[t+r*i,a+p*i,n],e,3,o,{material:"dark",explode:[0,0,26]}))}function ft(){return{title:"\\\\u5206\\\\u5C42\\\\u7ED3\\\\u6784 \\\\xB7 \\\\u793A\\\\u610F\\\\u88C5\\\\u914D",groups:[{id:"base",label:"\\\\u5E95\\\\u5EA7",description:"\\\\u652F\\\\u6491\\\\u6574\\\\u4F53\\\\uFF0C\\\\u5E76\\\\u63D0\\\\u4F9B\\\\u5B89\\\\u88C5\\\\u4F4D\\\\u7F6E\\\\u3002"},{id:"board",label:"\\\\u529F\\\\u80FD\\\\u677F",description:"\\\\u8FDE\\\\u63A5\\\\u8F93\\\\u5165\\\\u4E0E\\\\u5904\\\\u7406\\\\u6A21\\\\u5757\\\\uFF1B\\\\u793A\\\\u610F\\\\u7ED3\\\\u6784\\\\uFF0C\\\\u4E0D\\\\u5BF9\\\\u5E94\\\\u7279\\\\u5B9A\\\\u4EA7\\\\u54C1\\\\u3002"},{id:"sink",label:"\\\\u6563\\\\u70ED\\\\u5C42",description:"\\\\u5C06\\\\u70ED\\\\u91CF\\\\u4F20\\\\u5230\\\\u66F4\\\\u5927\\\\u7684\\\\u8868\\\\u9762\\\\u79EF\\\\u3002"},{id:"cover",label:"\\\\u5916\\\\u58F3",description:"\\\\u4FDD\\\\u62A4\\\\u5185\\\\u90E8\\\\uFF1B\\\\u5256\\\\u5F00\\\\u9009\\\\u9879\\\\u901A\\\\u8FC7\\\\u9690\\\\u85CF\\\\u5916\\\\u58F3\\\\u5C55\\\\u793A\\\\u7ED3\\\\u6784\\\\u3002"}],parts:[z("base","\\\\u5B89\\\\u88C5\\\\u5E95\\\\u5EA7",[0,0,0],[120,85,10],"base",{round:6,material:"metal"}),...[-1,1].flatMap((t,a)=>[-1,1].map((n,o)=>F("foot_"+a+o,"\\\\u9632\\\\u6ED1\\\\u811A",[t*46,n*30,-8],6,7,"base",{material:"dark"}))),z("board","\\\\u529F\\\\u80FD\\\\u677F",[0,0,15],[96,62,4],"board",{round:3,material:"cool",explode:[0,0,35]}),z("chip","\\\\u5904\\\\u7406\\\\u6A21\\\\u5757",[-16,0,22],[25,24,10],"board",{round:2,material:"dark",explode:[0,0,35]}),z("connector","\\\\u8FDE\\\\u63A5\\\\u7AEF\\\\u53E3",[32,0,24],[16,36,14],"board",{round:2,material:"warm",explode:[0,0,35]}),...ut(0,0,20,"board",2,24),z("spreader","\\\\u5BFC\\\\u70ED\\\\u5E95\\\\u677F",[-16,0,32],[44,42,5],"sink",{round:2,material:"metal",explode:[-10,0,65]}),...Array.from({length:7},(t,a)=>z("fin_"+a,"\\\\u6563\\\\u70ED\\\\u9CCD\\\\u7247",[-34+a*6,0,44],[2.4,40,20],"sink",{round:1,material:"metal",explode:[-10,0,65]})),z("top","\\\\u9876\\\\u76D6",[0,0,61],[124,89,5],"cover",{round:6,cover:!0,material:"metal",explode:[12,0,85]}),z("side","\\\\u4FA7\\\\u677F",[0,-44,32],[124,4,58],"cover",{round:2,cover:!0,material:"metal",explode:[12,-22,50]})]}}function pt({driverTeeth:t=16,drivenTeeth:a=32,module:n=1.5}={}){let o=W({driverTeeth:t,drivenTeeth:a,module:n}),e=o.centerDistance;return{title:"\\\\u9F7F\\\\u8F6E\\\\u4F20\\\\u52A8 \\\\xB7 \\\\u7B80\\\\u5316\\\\u76F4\\\\u9F7F\\\\u8F6E\\\\u793A\\\\u610F",azimuth:70,elevation:55,groups:[{id:"frame",label:"\\\\u652F\\\\u67B6",description:"\\\\u56FA\\\\u5B9A\\\\u8F74\\\\u5FC3\\\\u4F4D\\\\u7F6E\\\\uFF1B\\\\u4E24\\\\u8F74\\\\u4E2D\\\\u5FC3\\\\u8DDD\\\\u7531\\\\u9F7F\\\\u6570\\\\u4E0E\\\\u6A21\\\\u6570\\\\u5171\\\\u540C\\\\u786E\\\\u5B9A\\\\u3002"},{id:"driver",label:"\\\\u4E3B\\\\u52A8\\\\u8F6E",description:"\\\\u8F93\\\\u5165\\\\u8F6C\\\\u901F\\\\uFF0C\\\\u7531\\\\u9F7F\\\\u6570\\\\u51B3\\\\u5B9A\\\\u8282\\\\u5706\\\\u534A\\\\u5F84\\\\u3002"},{id:"driven",label:"\\\\u4ECE\\\\u52A8\\\\u8F6E",description:"\\\\u5916\\\\u556E\\\\u5408\\\\u8F6C\\\\u5411\\\\u76F8\\\\u53CD\\\\uFF0C\\\\u8F6C\\\\u901F\\\\u6309\\\\u9F7F\\\\u6570\\\\u6BD4\\\\u53D8\\\\u5316\\\\u3002"},{id:"cover",label:"\\\\u5916\\\\u58F3",description:"\\\\u9690\\\\u85CF\\\\u76D6\\\\u677F\\\\u4EE5\\\\u89C2\\\\u5BDF\\\\u4F20\\\\u52A8\\\\uFF1B\\\\u4E0D\\\\u662F\\\\u52A0\\\\u5DE5\\\\u6216\\\\u53D7\\\\u529B\\\\u4EFF\\\\u771F\\\\u3002"}],parts:[z("base","\\\\u5B89\\\\u88C5\\\\u5E95\\\\u5EA7",[30,0,-8],[140,90,10],"frame",{round:6,material:"metal"}),...ut(30,0,0,"frame",3,32),...[0,e].flatMap((i,r)=>[F("bearing_"+r,"\\\\u8F74\\\\u627F\\\\u5EA7",[i,0,4],10,12,"frame",{inner:4,material:"dark"}),F("shaft_"+r,"\\\\u4F20\\\\u52A8\\\\u8F74",[i,0,16],3.8,28,r?"driven":"driver",{material:"metal",explode:[r?24:-24,0,20]}),F("hub_"+r,"\\\\u8F6E\\\\u6BC2",[i,0,27],6,6,r?"driven":"driver",{inner:3.8,material:"warm",explode:[r?24:-24,0,20]})]),{id:"driverGear",type:"gear",label:"\\\\u4E3B\\\\u52A8\\\\u9F7F\\\\u8F6E",group:"driver",at:[0,0,20],radius:o.driverRadius,teeth:t,module:n,height:7,inner:4,material:"accent",explode:[-24,0,20]},{id:"drivenGear",type:"gear",label:"\\\\u4ECE\\\\u52A8\\\\u9F7F\\\\u8F6E",group:"driven",at:[e,0,20],radius:o.drivenRadius,teeth:a,module:n,height:7,inner:4,material:"cool",rotation:o.drivenAngle,explode:[24,0,20]},z("cover","\\\\u9632\\\\u62A4\\\\u76D6\\\\u677F",[30,0,36],[140,90,4],"cover",{round:6,cover:!0,material:"metal",explode:[0,0,62]})]}}function ht({radius:t=20,rod:a=70,angle:n=0}={}){let o=X({radius:t,rod:a,angle:n,z:28});return{title:"\\\\u66F2\\\\u67C4\\\\u8FDE\\\\u6746 \\\\xB7 \\\\u65CB\\\\u8F6C\\\\u8F6C\\\\u4E3A\\\\u5F80\\\\u590D",groups:[{id:"frame",label:"\\\\u652F\\\\u67B6\\\\u4E0E\\\\u5BFC\\\\u8F68",description:"\\\\u652F\\\\u6491\\\\u8F74\\\\u5FC3\\\\uFF0C\\\\u9650\\\\u5236\\\\u6ED1\\\\u5757\\\\u6CBF\\\\u540C\\\\u4E00\\\\u65B9\\\\u5411\\\\u8FD0\\\\u52A8\\\\u3002"},{id:"crank",label:"\\\\u66F2\\\\u67C4",description:"\\\\u66F2\\\\u67C4\\\\u7ED5\\\\u56FA\\\\u5B9A\\\\u8F74\\\\u5FC3\\\\u65CB\\\\u8F6C\\\\u3002"},{id:"rod",label:"\\\\u8FDE\\\\u6746",description:"\\\\u8FDE\\\\u63A5\\\\u66F2\\\\u67C4\\\\u9500\\\\u548C\\\\u6ED1\\\\u5757\\\\uFF0C\\\\u957F\\\\u5EA6\\\\u4FDD\\\\u6301\\\\u4E0D\\\\u53D8\\\\u3002"},{id:"piston",label:"\\\\u6ED1\\\\u5757",description:"\\\\u6CBF\\\\u5BFC\\\\u8F68\\\\u5F80\\\\u590D\\\\uFF1B\\\\u5B8C\\\\u6574\\\\u884C\\\\u7A0B\\\\u7B49\\\\u4E8E\\\\u66F2\\\\u67C4\\\\u534A\\\\u5F84\\\\u7684\\\\u4E24\\\\u500D\\\\u3002"}],parts:[z("base","\\\\u5B89\\\\u88C5\\\\u5E95\\\\u5EA7",[35,0,-6],[175,80,10],"frame",{round:6,material:"metal"}),...ut(35,0,1,"frame",3,30),F("bearing","\\\\u66F2\\\\u8F74\\\\u8F74\\\\u627F",[0,0,7],11,15,"frame",{inner:4,material:"dark"}),F("axle","\\\\u66F2\\\\u8F74",[0,0,15],3.8,26,"crank",{material:"metal",explode:[0,-18,18]}),F("flywheel","\\\\u66F2\\\\u67C4\\\\u76D8",[0,0,20],t+6,6,"crank",{inner:4,material:"accent",explode:[0,-18,18]}),z("railA","\\\\u5BFC\\\\u8F68",[74,-16,13],[85,5,6],"frame",{round:1,material:"dark"}),z("railB","\\\\u5BFC\\\\u8F68",[74,16,13],[85,5,6],"frame",{round:1,material:"dark"}),F("crankPin","\\\\u66F2\\\\u67C4\\\\u9500",o.crank,3,12,"crank",{material:"warm",explode:[0,-18,18]}),{id:"link",type:"rod",label:"\\\\u8FDE\\\\u6746",from:o.crank,to:o.piston,radius:2.4,group:"rod",material:"metal",explode:[0,0,45]},z("piston","\\\\u6ED1\\\\u5757",[o.position,0,22],[18,24,16],"piston",{round:3,material:"cool",explode:[20,0,18]}),F("pistonPin","\\\\u6ED1\\\\u5757\\\\u9500",o.piston,3,10,"piston",{material:"warm",explode:[20,0,18]})]}}var St=`\\n.mui-mechanism{font:15px/1.7 system-ui,sans-serif;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:24px;padding:20px;max-width:100%;box-sizing:border-box}.mui-mechanism *{box-sizing:border-box}.mui-mechanism h2{font-size:22px;line-height:1.35;margin:0 0 8px;font-weight:750}.mui-mechanism p{margin:0;color:var(--canvas-muted)}\\n.mui-mechanism-svg{display:block;width:100%;height:auto;max-height:420px;touch-action:pan-y}.mui-mechanism-svg path{stroke:color-mix(in srgb,var(--canvas-ink) 38%,var(--canvas-bg));stroke-width:.8;stroke-linejoin:round;vector-effect:non-scaling-stroke;cursor:pointer;fill:var(--mech-base,var(--canvas-soft))}.mui-mechanism-svg [data-material=metal]{--mech-base:color-mix(in srgb,var(--canvas-muted) 32%,var(--canvas-bg))}.mui-mechanism-svg [data-material=dark]{--mech-base:color-mix(in srgb,var(--canvas-ink) 78%,var(--canvas-bg))}.mui-mechanism-svg [data-material=accent]{--mech-base:var(--canvas-accent)}.mui-mechanism-svg [data-material=cool]{--mech-base:color-mix(in srgb,#22998a 70%,var(--canvas-bg))}.mui-mechanism-svg [data-material=warm]{--mech-base:color-mix(in srgb,#dd9c42 75%,var(--canvas-bg))}\\n.mui-mechanism-svg [data-tone="0"]{fill:color-mix(in srgb,var(--mech-base) 74%,var(--canvas-bg))}.mui-mechanism-svg [data-tone="1"]{fill:var(--mech-base)}.mui-mechanism-svg [data-tone="2"]{fill:color-mix(in srgb,var(--mech-base) 85%,var(--canvas-ink))}.mui-mechanism-svg [data-tone="3"]{fill:color-mix(in srgb,var(--mech-base) 68%,var(--canvas-ink))}.mui-mechanism-svg [data-line]{fill:none;stroke:var(--mech-base);stroke-width:2}.mui-mechanism-svg [data-active=false]{opacity:.2}.mui-mechanism-svg [data-active=true]{opacity:1}\\n.mui-mechanism-nav{display:flex;flex-wrap:wrap;gap:7px;margin:8px 0 12px}.mui-mechanism button{font:inherit;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:999px;padding:6px 13px;cursor:pointer;min-height:36px}.mui-mechanism button[aria-pressed=true]{color:var(--canvas-bg);background:var(--canvas-ink);border-color:var(--canvas-ink)}.mui-mechanism button:focus-visible,.mui-mechanism input:focus-visible{outline:2px solid var(--canvas-accent);outline-offset:3px}.mui-mechanism button:disabled{opacity:.5;cursor:default}\\n.mui-mechanism-controls{display:flex;align-items:center;flex-wrap:wrap;gap:14px;padding:12px 14px;border-radius:16px;background:var(--canvas-soft);margin:8px 0}.mui-mechanism-controls label{display:flex;align-items:center;gap:9px;flex:1 1 180px;min-width:0}.mui-mechanism-controls input[type=range]{flex:1;min-width:70px;accent-color:var(--canvas-accent)}.mui-mechanism-controls input[type=checkbox]{accent-color:var(--canvas-accent)}.mui-mechanism-controls output{font-variant-numeric:tabular-nums;min-width:40px;text-align:right;font-weight:650}.mui-mechanism-readout{display:block;padding:10px 0;font-weight:700;font-variant-numeric:tabular-nums;color:var(--canvas-ink)}.mui-mechanism-description{min-height:0;font-size:14px}\\n.mui-mechanism[data-style=editorial]{border:0;border-top:1px solid var(--canvas-line);border-radius:0;padding:16px 0}.mui-mechanism[data-style=editorial] h2{font-family:ui-serif,Georgia,serif;font-weight:650}.mui-mechanism[data-style=editorial] .mui-mechanism-controls{border-radius:0;background:transparent;border-block:1px solid var(--canvas-line)}\\n.mui-mechanism[data-style=technical]{border-radius:10px}.mui-mechanism[data-style=technical] button,.mui-mechanism[data-style=technical] .mui-mechanism-controls{border-radius:6px}.mui-mechanism[data-style=technical] .mui-mechanism-readout{font-family:ui-monospace,Consolas,monospace}\\n.mui-mechanism[data-style=soft]{border:0;background:var(--canvas-soft);border-radius:28px 28px 28px 10px}.mui-mechanism[data-style=soft] .mui-mechanism-controls{background:var(--canvas-bg);border-radius:22px}.mui-mechanism[data-style=expressive] h2{font-size:28px;font-weight:850;border-left:5px solid var(--canvas-accent);padding-left:14px}.mui-mechanism[data-style=expressive]{border:0;border-radius:0}.mui-mechanism[data-style=prismframe]{border:1.5px solid var(--canvas-line);box-shadow:4px 5px 0 color-mix(in srgb,var(--canvas-accent) 14%,var(--canvas-bg))}.mui-mechanism[data-style=aurora]{border-radius:28px;box-shadow:0 16px 30px -25px #30204d66}.mui-mechanism[data-style=aurora] .mui-mechanism-controls{border-radius:24px}\\n@media(max-width:500px){.mui-mechanism{padding:14px;border-radius:20px}.mui-mechanism h2{font-size:20px}.mui-mechanism-controls{padding:10px}.mui-mechanism-nav{gap:5px}.mui-mechanism button{padding:6px 10px;font-size:14px}}\\n@media(prefers-reduced-motion:reduce){.mui-mechanism *{animation:none!important;transition:none!important}}\\n@media(forced-colors:active){.mui-mechanism-svg path{fill:Canvas;stroke:CanvasText}.mui-mechanism button[aria-pressed=true]{background:Highlight;color:HighlightText}}\\n`;var xt="http://www.w3.org/2000/svg",C=(t,a,n)=>{let o=document.createElement(t);return a&&(o.className=a),n!==void 0&&(o.textContent=n),o};function Ft(t){function a(o,e){let i=typeof o=="string"?document.querySelector(o):o;if(!i||!i.replaceChildren)throw Error("Motion mechanism: target element not found");Y(e);let r=structuredClone({...e,onSelect:void 0}),p=nt(r),d={explode:0,selected:"all",cutaway:!1,pose:{}},m=!1,s="",c="",u=0,f=new Map,g=new Map,h=new Map,M=[],O=C("section","mui-mechanism"),N=C("h2",null,r.title??"\\\\u7ED3\\\\u6784\\\\u56FE\\\\u89E3"),$=document.createElementNS(xt,"svg"),P=document.createElementNS(xt,"g"),A=C("div","mui-mechanism-nav"),w=C("div","mui-mechanism-controls"),T=C("p","mui-mechanism-description"),D=C("output","mui-mechanism-readout"),G=C("style");G.textContent=St,N.hidden=r.title==="",O.setAttribute("aria-label",r.title??"\\\\u7ED3\\\\u6784\\\\u56FE\\\\u89E3"),$.setAttribute("class","mui-mechanism-svg"),$.setAttribute("viewBox","0 0 600 340"),$.setAttribute("role","img"),$.setAttribute("aria-label","\\\\u53EF\\\\u62C6\\\\u89E3\\\\u7684\\\\u7ED3\\\\u6784\\\\u793A\\\\u610F\\\\u56FE\\\\uFF1B\\\\u4F7F\\\\u7528\\\\u4E0B\\\\u65B9\\\\u6309\\\\u94AE\\\\u9009\\\\u62E9\\\\u90E8\\\\u4EF6"),$.append(P),O.append(G,N,$,A,w,D,T),i.replaceChildren(O);let S=()=>r.groups?.length?r.groups:r.parts.map(l=>({id:l.id,label:l.label??l.id,description:l.description??""}));function H(l){r.bind?.selected?t.setState({[r.bind.selected]:l}):typeof e.onSelect=="function"?e.onSelect(l):Q({selected:l})}function K(){if(A.replaceChildren(),h.clear(),!r.bind?.selected&&typeof e.onSelect!="function"){A.hidden=!0;return}A.hidden=!1;for(let l of[{id:"all",label:"\\\\u5168\\\\u90E8",description:""},...S()]){let b=C("button",null,l.label);b.type="button",b.setAttribute("aria-pressed",String(d.selected===l.id)),b.addEventListener("click",()=>H(l.id)),h.set(l.id,b),A.append(b)}}let x,rt,L;if(r.bind?.explode){let l=C("label",null,"\\\\u62C6\\\\u89E3\\\\u8FDB\\\\u5EA6");x=C("input"),x.type="range",x.min="0",x.max="1",x.step=".01",x.setAttribute("aria-label","\\\\u62C6\\\\u89E3\\\\u8FDB\\\\u5EA6"),rt=C("output"),x.addEventListener("input",()=>t.setState({[r.bind.explode]:Number(x.value)})),l.append(x,rt),w.append(l)}if(r.bind?.cutaway&&r.parts.some(l=>l.cover)){let l=C("label",null,"\\\\u5256\\\\u5F00\\\\u5916\\\\u58F3");L=C("input"),L.type="checkbox",L.setAttribute("aria-label","\\\\u5256\\\\u5F00\\\\u5916\\\\u58F3"),L.addEventListener("change",()=>t.setState({[r.bind.cutaway]:L.checked})),l.prepend(L),w.append(l)}w.hidden=!w.childNodes.length;function jt(l){let b=JSON.stringify([l.explode,l.cutaway]);b!==s&&(p=nt(r,l),s=b);let E=mt(r,p,l,f),k=new Set;for(let j of E){k.add(j.key);let R=g.get(j.key);R||(R=document.createElementNS(xt,"path"),R.setAttribute("fill-rule","evenodd"),g.set(j.key,R));for(let[gt,bt]of Object.entries({d:j.d,"data-part":j.part,"data-material":j.material,"data-tone":j.tone,"data-active":j.active}))R.getAttribute(gt)!==String(bt)&&R.setAttribute(gt,String(bt));j.line?R.setAttribute("data-line",""):R.removeAttribute("data-line")}for(let[j,R]of g)k.has(j)||(R.remove(),g.delete(j));let Z=E.map(j=>j.key).join("|");if(Z!==c){for(let j of E)P.append(g.get(j.key));c=Z}u++}function Q(l={}){if(m)return;for(let k of Object.keys(l))if(!["explode","selected","cutaway","pose","parts","readout"].includes(k))throw Error("Motion mechanism: unknown update field "+k);if(l.parts){let k={...r,parts:l.parts};Y(k);let Z=nt(k);mt(k,Z,{...d,...l},new Map),r=k,p=Z,f.clear(),c="",s=""}let b={...d,...l};l.pose&&(b.pose=l.pose),jt(b),d=b;for(let[k,Z]of h)Z.setAttribute("aria-pressed",String(b.selected===k));let E=S().find(k=>k.id===b.selected)??r.parts.find(k=>k.id===b.selected);T.textContent=E?.description??(b.selected==="all"?"\\\\u9009\\\\u62E9\\\\u4E00\\\\u4E2A\\\\u90E8\\\\u4EF6\\\\uFF0C\\\\u67E5\\\\u770B\\\\u5B83\\\\u7684\\\\u804C\\\\u8D23\\\\uFF1B\\\\u62C6\\\\u89E3\\\\u53EA\\\\u5C55\\\\u793A\\\\u88C5\\\\u914D\\\\u5173\\\\u7CFB\\\\u3002":""),x&&(x.value=String(b.explode),rt.textContent=Math.round(b.explode*100)+"%"),L&&(L.checked=b.cutaway),l.readout!==void 0&&(D.textContent=String(l.readout))}return $.addEventListener("click",l=>{let b=l.target.closest("[data-part]");if(!b)return;let E=r.parts.find(k=>k.id===b.getAttribute("data-part"));E&&H(r.groups?.length?E.group??E.id:E.id)}),K(),M.push(t.subscribe(l=>{if(m)return;let b={};for(let[E,k]of Object.entries(r.bind??{})){if(!Object.hasOwn(l.state,k))throw Error("Motion mechanism: bind."+E+" names undeclared state "+k);b[E]=l.state[k]}O.dataset.style=l.theme?.visualStyle??"";for(let E of h.values())E.disabled=l.disabled;x&&(x.disabled=l.disabled),L&&(L.disabled=l.disabled),Q(b)})),Object.freeze({update:Q,pose:l=>Q({pose:l}),stats:()=>({frames:u,faces:g.size,parts:r.parts.length}),destroy(){m||(m=!0,M.forEach(l=>l()),g.clear(),f.clear(),i.replaceChildren())}})}function n(o,e,i={}){if(!["assembly","gears","crank"].includes(e))throw Error("Motion mechanism: demo must be assembly/gears/crank");let r=i.bind??{},p=()=>t.snapshot.state,d=(A,w)=>Object.hasOwn(r,A)?p()[r[A]]:w;for(let[A,w]of Object.entries(r))if(!["explode","selected","cutaway","rpm","teeth","running","angle","radius"].includes(A)||typeof w!="string"||!Object.hasOwn(p(),w))throw Error("Motion mechanism: invalid demo binding "+A);let m=d("angle",0)*Math.PI/180,s=m,c="",u=!1,f=Object.fromEntries(Object.entries(r).filter(([A])=>["explode","selected","cutaway"].includes(A)));function g(){return e==="assembly"?ft():e==="gears"?pt({driverTeeth:i.driverTeeth??16,drivenTeeth:d("teeth",32),module:i.module??1.5}):ht({radius:d("radius",20),rod:i.rod??70})}let h=a(o,{...g(),...i.title===void 0?{}:{title:i.title},bind:f}),M=!1;function O(A=0,w=!1,T=!0){if(M)return;let D=d("rpm",30),G=d("running",!1),S=d("angle",0)*Math.PI/180,H=s;S!==m?(H=S,m=S):G&&T&&!w&&(H+=D*Math.PI*2/60*A),s=H;let K=JSON.stringify([e,d("teeth",32),d("radius",20)]);if(K!==c&&(h.update({parts:g().parts}),c=K),e==="gears"){let x=W({driverTeeth:i.driverTeeth??16,drivenTeeth:d("teeth",32),rpm:D,angle:s,module:i.module??1.5});h.update({pose:{driverGear:{rotation:x.driverAngle},drivenGear:{rotation:x.drivenAngle}},readout:"\\\\u4E3B\\\\u52A8\\\\u8F6E "+t.formatNumber(x.driverRpm,0)+" rpm \\\\xB7 \\\\u4ECE\\\\u52A8\\\\u8F6E "+t.formatNumber(x.drivenRpm,2)+" rpm \\\\xB7 \\\\u9F7F\\\\u6570\\\\u6BD4 "+t.formatNumber(x.ratio,2)+"\\\\uFF08\\\\u8D1F\\\\u53F7\\\\u8868\\\\u793A\\\\u53CD\\\\u5411\\\\uFF09"})}else if(e==="crank"){let x=X({angle:s,radius:d("radius",20),rod:i.rod??70,z:28});h.update({pose:{crankPin:{at:x.crank},link:{from:x.crank,to:x.piston},piston:{at:[x.position,0,22]},pistonPin:{at:x.piston}},readout:"\\\\u66F2\\\\u67C4\\\\u89D2 "+t.formatNumber((s*180/Math.PI%360+360)%360,1)+"\\\\xB0 \\\\xB7 \\\\u6ED1\\\\u5757\\\\u4F4D\\\\u7F6E "+t.formatNumber(x.position,2)+" \\\\xB7 \\\\u884C\\\\u7A0B "+t.formatNumber(x.stroke,1)+"\\\\uFF08\\\\u793A\\\\u610F\\\\u957F\\\\u5EA6\\\\u5355\\\\u4F4D\\\\uFF09"})}u=w}let N=null,$=()=>{O(0,u,!0),e!=="assembly"&&(d("running",!1)&&!N?N=t.animate(({delta:A,reducedMotion:w,visible:T})=>{T&&!w?O(A,!1,!0):u!==w&&O(0,w,T)}):!d("running",!1)&&N&&(N(),N=null))},P=t.subscribe($);return O(),Object.freeze({...h,destroy(){M||(M=!0,N?.(),P(),h.destroy())}})}return Object.freeze({mount:a,mountDemo:n,gearPair:W,sliderCrank:X,follow:Mt,scenes:Object.freeze({assembly:ft,gears:pt,crank:ht})})}return _t(Tt);})();\\n\';\n\n // lib/visual-audit.js\n function measureVisual(root, nodeId = "") {\n const issues = [], seen = /* @__PURE__ */ new Set(), coverage = { nodeId, elements: 0, truncated: false, contrastChecked: 0, contrastUncovered: 0 };\n const styleCache = /* @__PURE__ */ new WeakMap(), styleOf = (el2) => {\n let css = styleCache.get(el2);\n if (!css) {\n css = getComputedStyle(el2);\n styleCache.set(el2, css);\n }\n return css;\n };\n const target = (el2) => {\n if (!el2) return void 0;\n const tag = el2.tagName.toLowerCase(), id = el2.id;\n return { selector: id && id.length <= 64 ? "#" + CSS.escape(id) : tag, text: (el2.textContent ?? "").trim().replace(/\\s+/g, " ").slice(0, 120), tag };\n };\n const add = (code, value, el2) => {\n if (issues.length >= 40) return;\n const id = el2?.closest("[data-ui-node]")?.getAttribute("data-ui-node") ?? nodeId;\n const location = target(el2);\n const k2 = id + ":" + code + ":" + (location?.selector ?? "") + ":" + (location?.text ?? "") + ":" + Math.round(value ?? 0);\n if (!seen.has(k2) && issues.length < 40) {\n seen.add(k2);\n issues.push({ code, nodeId: id, ...location ? { target: location } : {}, ...value === void 0 ? {} : { value: Number(value.toFixed(2)) } });\n }\n };\n const color = (s) => {\n let m2 = s.match(/^rgba?\\(([^)]+)\\)/);\n if (m2) {\n const a = m2[1].split(/[\\s,\\/]+/).map(Number);\n return [a[0] / 255, a[1] / 255, a[2] / 255, a[3] ?? 1];\n }\n m2 = s.match(/^color\\(srgb ([^)]+)\\)/);\n if (m2) {\n const a = m2[1].split(/[\\s\\/]+/).map(Number);\n return [a[0], a[1], a[2], a[3] ?? 1];\n }\n return null;\n };\n const luminance = (c) => c.slice(0, 3).map((v2) => v2 <= 0.04045 ? v2 / 12.92 : ((v2 + 0.055) / 1.055) ** 2.4).reduce((s, v2, i) => s + v2 * [0.2126, 0.7152, 0.0722][i], 0);\n const blend = (front, back) => front.slice(0, 3).map((v2, i) => v2 * front[3] + back[i] * (1 - front[3])).concat(1);\n const background = (el2) => {\n const layers = [];\n let n = el2;\n for (let i = 0; n && i < 64; i++, n = n.parentElement) {\n const c = styleOf(n);\n if (c.backgroundImage !== "none") return null;\n const colorValue = color(c.backgroundColor);\n if (!colorValue) return null;\n if (colorValue[3] > 0) layers.push(colorValue);\n if (colorValue[3] === 1) {\n let out = layers.pop();\n while (layers.length) out = blend(layers.pop(), out);\n return out;\n }\n }\n return null;\n };\n let contentBottom = root.getBoundingClientRect().top;\n const widthRoot = root.id === "canvas" ? document.documentElement : root;\n if (widthRoot.scrollWidth > widthRoot.clientWidth + 2) add("overflow", widthRoot.scrollWidth - widthRoot.clientWidth);\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n let el;\n while (el = walker.nextNode()) {\n if (coverage.elements >= 2e3) {\n coverage.truncated = true;\n break;\n }\n coverage.elements++;\n if (el.matches("[data-canvas-phase=error]")) add("runtimeError", void 0, el);\n const css = styleOf(el), box = el.getBoundingClientRect();\n if (!box.width || !box.height || css.visibility === "hidden" || css.display === "none") continue;\n const text2 = [...el.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim());\n if (text2) {\n let size = parseFloat(css.fontSize);\n if (el instanceof SVGElement && el.getScreenCTM) {\n const m2 = el.getScreenCTM();\n if (m2) size *= Math.hypot(m2.c, m2.d);\n }\n if (size < 11.9) add("smallText", size, el);\n if (!(el instanceof SVGElement)) {\n const fg = color(css.color), bg = background(el);\n let opacitySafe = true, opacityDepth = 0;\n for (let a2 = el; a2; a2 = a2.parentElement) {\n if (++opacityDepth > 64 || parseFloat(styleOf(a2).opacity) < 1) {\n opacitySafe = false;\n break;\n }\n }\n if (fg && bg && opacitySafe) {\n coverage.contrastChecked++;\n const a2 = luminance(blend(fg, bg)), b2 = luminance(bg), ratio = (Math.max(a2, b2) + 0.05) / (Math.min(a2, b2) + 0.05);\n if (ratio < (size >= 24 || size >= 18.66 && parseFloat(css.fontWeight) >= 700 ? 3 : 4.5)) add("contrast", ratio, el);\n } else coverage.contrastUncovered++;\n const range = document.createRange();\n range.selectNodeContents(el);\n const bounds = range.getBoundingClientRect();\n let a = el, depth = 0;\n while (a && a !== root.parentElement && depth++ < 24) {\n const c = styleOf(a), clip = a.getBoundingClientRect();\n if (["hidden", "clip"].includes(c.overflowX) && (bounds.left < clip.left - 2 || bounds.right > clip.right + 2) || ["hidden", "clip"].includes(c.overflowY) && (bounds.top < clip.top - 2 || bounds.bottom > clip.bottom + 2)) {\n add("clippedText", void 0, el);\n break;\n }\n a = a.parentElement;\n }\n } else coverage.contrastUncovered++;\n }\n if (text2 || el.matches("svg,canvas,img,video,input,select,textarea,button")) contentBottom = Math.max(contentBottom, box.bottom);\n if (el.matches("input:not([type=hidden]),select,textarea,button,[role=button]") && !el.getAttribute("aria-label") && !el.getAttribute("aria-labelledby") && !el.labels?.length && !el.textContent.trim() && !el.getAttribute("title")) add("missingLabel", void 0, el);\n }\n const rect = root.getBoundingClientRect(), gap = rect.bottom - contentBottom;\n if (!coverage.truncated && root.id === "canvas" && rect.height > 320 && gap > Math.max(96, rect.height * 0.25)) add("bottomWhitespace", gap, root);\n Object.defineProperty(issues, "coverage", { value: coverage });\n return issues;\n }\n\n // lib/format-number.js\n function formatNumber(value, decimals = 2) {\n if (typeof value !== "number" || !Number.isFinite(value)) throw new Error("DSH UI: formatNumber requires a finite number");\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 6) throw new Error("DSH UI: formatNumber decimals must be an integer from 0 to 6");\n return value.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });\n }\n\n // lib/canvas-system.js\n var CANVAS_SYSTEM_CSS = `\n:root{--canvas-radius:16px;--canvas-gap:16px;--canvas-positive:#167456;--canvas-negative:#b13b3b;--canvas-warning:#875b15}\n:root[data-canvas-scheme=dark]{--canvas-positive:#78d9b4;--canvas-negative:#ffaaaa;--canvas-warning:#edc87e}\n#canvas{display:flow-root}html,body{margin:0;min-width:0;background:var(--canvas-bg,#fff);color:var(--canvas-ink,#182537);font:14px/1.6 system-ui,"Microsoft YaHei",sans-serif}*{box-sizing:border-box}svg{max-width:100%;height:auto}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--canvas-line,#ced4df);border-radius:8px;background:var(--canvas-bg,#fff);padding:8px 12px;max-width:100%}button{cursor:pointer}button:disabled{cursor:default;opacity:.55}input[type=range]{padding:0;accent-color:var(--canvas-accent,#3e60d3)}input[type=checkbox],input[type=radio]{accent-color:var(--canvas-accent,#3e60d3)}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--canvas-accent,#3e60d3);outline-offset:3px}\n.ui-stack{display:grid;gap:var(--canvas-gap)}.ui-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--canvas-gap)}.ui-surface{padding:20px;border:1px solid var(--canvas-line,#ced4df);border-radius:var(--canvas-radius);background:var(--canvas-soft,#f3f5f8)}.ui-title{margin:0;font-size:clamp(20px,3vw,28px);line-height:1.3;letter-spacing:-.02em}.ui-caption{color:var(--canvas-muted,#526176);margin:8px 0;font-size:14px}.ui-value{font-size:clamp(24px,4vw,36px);font-variant-numeric:tabular-nums;line-height:1.2}.ui-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.ui-field{display:grid;gap:6px;min-width:0}.ui-legend{display:flex;gap:16px;flex-wrap:wrap;font-size:13px}.ui-status{min-height:1.6em}.ui-error{color:var(--canvas-negative)}.ui-primary{background:var(--canvas-accent,#3e60d3);color:var(--canvas-accent-ink,#fff);border-color:transparent}\nsvg .ui-node{fill:var(--canvas-soft,#f3f5f8);stroke:var(--canvas-line,#ced4df);stroke-width:1}svg .ui-edge{fill:none;stroke:var(--canvas-muted,#526176);stroke-width:1.5}svg .ui-label{fill:var(--canvas-ink,#182537);font:500 14px system-ui,sans-serif}svg .ui-note{fill:var(--canvas-muted,#526176);font:400 13px system-ui,sans-serif}svg .ui-leader{fill:none;stroke:var(--canvas-muted,#526176);stroke-dasharray:3 4}svg .ui-accent{fill:color-mix(in srgb,var(--canvas-accent,#3e60d3) 12%,var(--canvas-bg,#fff));stroke:var(--canvas-accent,#3e60d3)}\n.ui-flow{display:flex;align-items:center;justify-content:center;gap:16px;padding:24px 8px;flex-wrap:wrap}.ui-step{display:grid;gap:6px;min-width:130px;max-width:240px;padding:16px 20px;border:1px solid var(--canvas-line);border-radius:6px;background:var(--canvas-bg)}.ui-step strong{font-size:16px;font-weight:600}.ui-step span{font-size:14px;color:var(--canvas-muted)}.ui-arrow{color:var(--canvas-muted);font-size:22px}.ui-callout{border-inline-start:3px solid var(--canvas-accent);padding:8px 16px;color:var(--canvas-ink)}\n.ui-surface,.ui-step{border-radius:var(--canvas-radius);background:var(--canvas-bg,#fff)}button,input:not([type=checkbox]):not([type=radio]):not([type=range]),select,textarea{border-radius:12px}button{border-radius:999px}.ui-primary{background:var(--canvas-ink,#182537);color:var(--canvas-bg,#fff)}.ui-callout{border-radius:0 12px 12px 0;background:color-mix(in srgb,var(--canvas-accent,#3e60d3) 5%,var(--canvas-bg,#fff))}\n@media(max-width:480px){.ui-flow{flex-direction:column;padding:16px 8px;gap:12px}.ui-step{width:100%;max-width:none}.ui-arrow{transform:rotate(90deg)}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}`;\n\n // lib/timeline.js\n function createTimelineAPI(animate, capture = false, notify = () => {\n }) {\n const timelines = /* @__PURE__ */ new Map();\n function timeline(options) {\n const { id = "main", duration, draw, loop = false, autoplay = true, chapters = [] } = options ?? {};\n if (typeof id !== "string" || !/^[A-Za-z_][\\w-]{0,63}$/.test(id) || timelines.has(id)) throw Error("Timeline id must be unique");\n if (!Number.isFinite(duration) || duration <= 0 || duration > 86400 || typeof draw !== "function") throw Error("Timeline requires positive duration and draw(time, info)");\n if (!Array.isArray(chapters) || chapters.length > 100 || chapters.some((c) => !c || typeof c.label !== "string" || !Number.isFinite(c.time) || c.time < 0 || c.time >= duration)) throw Error("Invalid timeline chapters");\n let time = 0, playing = !!autoplay && !capture, disposed = false, reduced = false, visible = true;\n const listeners = /* @__PURE__ */ new Set();\n const state2 = () => ({ id, time, duration, playing, loop: !!loop, reducedMotion: reduced, visible, chapters: chapters.map((c) => ({ time: c.time, label: c.label })) });\n const render = () => {\n draw(time, state2());\n notify(state2());\n for (const fn2 of listeners) fn2(state2());\n };\n const seek = (value) => {\n if (disposed) throw Error("Timeline disposed");\n if (!Number.isFinite(value)) throw Error("Timeline seek requires finite seconds");\n time = Math.max(0, Math.min(duration, value));\n render();\n return state2();\n };\n const api = Object.freeze({ state: state2, seek, play() {\n if (disposed) throw Error("Timeline disposed");\n playing = true;\n render();\n }, pause() {\n playing = false;\n render();\n }, replay() {\n playing = !capture;\n seek(0);\n }, chapter(index) {\n if (!Number.isInteger(index) || !chapters[index]) throw Error("Invalid chapter");\n playing = false;\n return seek(chapters[index].time);\n }, subscribe(fn2) {\n if (typeof fn2 !== "function") throw Error("Timeline listener required");\n listeners.add(fn2);\n fn2(state2());\n return () => listeners.delete(fn2);\n }, dispose() {\n if (disposed) return;\n disposed = true;\n stop();\n listeners.clear();\n timelines.delete(id);\n } });\n timelines.set(id, api);\n const stop = animate((info) => {\n reduced = !!info.reducedMotion;\n visible = info.visible !== false;\n if (!capture && playing && !reduced && visible) {\n const next = time + info.delta;\n time = loop ? next % duration : Math.min(duration, next);\n if (!loop && time === duration) playing = false;\n }\n render();\n });\n return api;\n }\n return { timeline, capture: Object.freeze({ list: () => [...timelines.values()].map((t) => t.state()), seek: (id, time) => {\n const t = timelines.get(id);\n if (!t) throw Error("Timeline not found: " + id);\n t.seek(time);\n t.pause();\n return t.state();\n } }) };\n }\n\n // lib/sandbox.js\n var SANDBOX_LIMITS = Object.freeze({ source: 49152, height: 1e3, message: 16384, rate: 30 });\n function canvasSnapshot(node2, state2, data, derived, disabled, theme) {\n const pick = (keys, values) => Object.fromEntries((keys ?? []).map((k2) => [k2, values[k2]]));\n return { state: pick(node2.stateKeys, state2), data: pick(node2.dataKeys, data), derived: pick(node2.derivedKeys, derived), disabled, theme };\n }\n function canvasPatch(message, node2) {\n if (!message || typeof message !== "object" || Array.isArray(message)) throw new Error("Invalid canvas patch");\n const keys = Object.keys(message);\n if (!keys.length || keys.length > 64 || keys.some((k2) => !(node2.stateKeys ?? []).includes(k2))) throw new Error("Canvas state key is not declared");\n if (JSON.stringify(message).length > SANDBOX_LIMITS.message) throw new Error("Canvas patch is too large");\n return message;\n }\n function sandboxDocument(node2, channel2, nonce2) {\n const json = (value) => JSON.stringify(value).replace(/</g, "\\\\u003c").replace(/\\u2028/g, "\\\\u2028").replace(/\\u2029/g, "\\\\u2029");\n return `<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src \'none\'; script-src \'nonce-${nonce2}\'; style-src \'unsafe-inline\'; img-src data:; font-src \'none\'; connect-src \'none\'; media-src \'none\'; object-src \'none\'; frame-src \'none\'; worker-src \'none\'; base-uri \'none\'; form-action \'none\'"><meta name="viewport" content="width=device-width,initial-scale=1"><style>${CANVAS_SYSTEM_CSS}</style></head><body><main id="canvas"></main><script nonce="${nonce2}">(()=>{\n const channel=${json(channel2)}, source=${json(canvasSource(node2))};\n let snapshot={state:{},data:{},derived:{},disabled:true,theme:{}}, started=false;\n const listeners=new Set(), send=(type,payload)=>parent.postMessage({dshCanvas:1,channel,type,payload},\'*\');\n const report=e=>send(\'error\',String(e?.message??e).slice(0,1000));\n const audit=${measureVisual.toString()};let auditTimer;const scheduleAudit=()=>{clearTimeout(auditTimer);auditTimer=setTimeout(()=>{const issues=audit(document.getElementById(\'canvas\'),${json(node2.id ?? "")});send(\'audit\',{issues,coverage:issues.coverage})},400)};\n addEventListener(\'resize\',scheduleAudit);\n addEventListener(\'error\',e=>report(e.error??e.message));addEventListener(\'unhandledrejection\',e=>report(e.reason));\n const animations=new Set(), motion=matchMedia(\'(prefers-reduced-motion: reduce)\');\n let raf=0,last=0,time=0;\n const visible=()=>snapshot.visible!==false&&!document.hidden;\n const canAnimate=()=>visible()&&!snapshot.disabled&&!motion.matches&&!window.__DSHMotionRender;\n const draw=delta=>{for(const fn of animations)try{fn({time,delta,reducedMotion:motion.matches,visible:visible()})}catch(e){animations.delete(fn);report(e)}};\n const tick=t=>{raf=0;if(!canAnimate()||!animations.size){last=0;draw(0);return}const delta=last?Math.min(.05,(t-last)/1000):0;last=t;time+=delta;draw(delta);if(animations.size)raf=requestAnimationFrame(tick)};\n const refresh=()=>{draw(0);if(canAnimate()&&animations.size){if(!raf){last=0;raf=requestAnimationFrame(tick)}}else{cancelAnimationFrame(raf);raf=0;last=0}};\n motion.addEventListener(\'change\',refresh);document.addEventListener(\'visibilitychange\',refresh);\n const formatNumber=${formatNumber.toString()};\n const api={formatNumber,get snapshot(){return structuredClone(snapshot)},subscribe(fn){if(typeof fn!==\'function\')throw Error(\'Listener required\');listeners.add(fn);fn(api.snapshot);return()=>listeners.delete(fn)},setState(patch){if(!snapshot.disabled)send(\'patch\',patch)},animate(fn){if(typeof fn!==\'function\')throw Error(\'Animation callback required\');animations.add(fn);refresh();return()=>{animations.delete(fn);if(!animations.size){cancelAnimationFrame(raf);raf=0;last=0}}}};\n let soundTick=0,soundPlaying,soundTime,soundVisible;const timelineAPI=(${createTimelineAPI.toString()})(api.animate,!!window.__DSHMotionRender,s=>{if(snapshot.motionSound){const now=performance.now();if(now-soundTick>=100||s.playing!==soundPlaying||s.visible!==soundVisible||(!s.playing&&s.time!==soundTime)){soundTick=now;soundPlaying=s.playing;soundTime=s.time;soundVisible=s.visible;send(\'timeline\',s)}}});api.timeline=timelineAPI.timeline;\n Object.defineProperty(window,\'__DSHMotionCapture\',{value:timelineAPI.capture,writable:false});\n ${node2.libraries?.includes("mechanism") ? MECHANISM_RUNTIME.replace(/<\\/script/gi, "<\\\\/script") + ";api.mechanism=__MotionMechanism.createMechanismAPI(api);" : ""}\n Object.defineProperty(window,\'DSHUI\',{value:Object.freeze(api),writable:false});\n for(const type of [\'click\',\'input\',\'change\',\'keydown\',\'pointerdown\'])document.addEventListener(type,e=>{if(snapshot.disabled){e.preventDefault();e.stopImmediatePropagation()}},true);\n addEventListener(\'message\',event=>{\n const m=event.data;if(event.source!==parent||m?.dshCanvas!==1||m.channel!==channel||m.type!==\'snapshot\')return;\n snapshot=m.payload;for(const [k,v] of Object.entries(snapshot.theme??{}))document.documentElement.style.setProperty(\'--canvas-\'+k,v);\n document.documentElement.style.colorScheme=snapshot.theme?.scheme??\'light\';document.documentElement.dataset.canvasScheme=snapshot.theme?.scheme??\'light\';\n const wasStarted=started;\n if(!started){started=true;document.getElementById(\'canvas\').innerHTML=source.html;const style=document.createElement(\'style\');style.textContent=source.css;document.head.append(style);const script=document.createElement(\'script\');script.nonce=${json(nonce2)};script.textContent=source.script;document.body.append(script)}\n if(wasStarted)for(const fn of listeners)try{fn(api.snapshot)}catch(e){report(e)}\n refresh();if(!wasStarted)send(\'mounted\');scheduleAudit();\n });\n let resizePending=false;new ResizeObserver(()=>{if(!started||resizePending)return;resizePending=true;requestAnimationFrame(()=>{resizePending=false;send(\'height\',Math.ceil(document.getElementById(\'canvas\').getBoundingClientRect().height))})}).observe(document.getElementById(\'canvas\'));\n send(\'ready\');\n})();<\\/script></body></html>`;\n }\n\n // lib/components.js\n var define = (fields2, purpose, presentation = "") => Object.freeze({ fields: Object.freeze(fields2), purpose, presentation });\n var COMPONENTS = Object.freeze({\n visual: define(["spec", "stateKey", "warnings"], "Extended native charts, tables, plots, quiz, forms, diagrams, media and 3D"),\n heading: define(["text", "spans", "size", "weight", "color", "align", "lineHeight"], "Section heading", "tone"),\n text: define(["text", "spans", "size", "weight", "color", "align", "lineHeight", "copyable", "title"], "Readable explanation; copyable:true adds a reusable text panel", "tone"),\n code: define(["code", "lang", "title", "wrap"], "Literal copyable code; displayed only, never executed"),\n callout: define(["text", "spans", "size", "weight", "color", "align", "lineHeight"], "A short emphasized paragraph", "tone"),\n row: define(["children", "columns", "gap"], "Wrapping parallel content"),\n column: define(["children", "gap"], "Ordered vertical content"),\n card: define(["title", "children", "surface"], "Meaningful grouped section", "tone"),\n details: define(["title", "children", "open"], "Collapsible supporting content", "tone"),\n badge: define(["text"], "Short explicit status label", "tone"),\n progress: define(["label", "value", "max", "unit"], "Declared numeric progress snapshot", "tone"),\n steps: define(["title", "items"], "Ordered declared steps with an optional heading"),\n metric: define(["label", "value", "unit", "decimals"], "Number with units, or a literal/bound status string", "tone"),\n input: define(["label", "bind"], "String or numeric state input"),\n slider: define(["label", "bind"], "Numeric state control"),\n select: define(["label", "bind", "variant"], "Selection from declared state options; variant:segmented for 2..8 short options, dropdown otherwise"),\n toggle: define(["label", "bind"], "Boolean state control"),\n button: define(["text", "action", "href", "path", "variant"], "Agent follow-up, web link or host file opener", "icon"),\n link: define(["text", "href", "path", "variant"], "User-clicked webpage or local file button", "icon"),\n divider: define(["label"], "Quiet section divider"),\n table: define(["label", "rows", "columns"], "Supplied or derived values; inline rows or data/derived reference"),\n chart: define(["kind", "rows", "labelKey", "valueKey", "label", "unit", "xScale"], "Bar/line comparison with accessible data"),\n sandbox: define(["title", "html", "css", "script", "fallback", "height", "libraries", "stateKeys", "dataKeys", "derivedKeys"], "Freeform isolated HTML/SVG/CSS/JavaScript visualization")\n });\n function componentFields(type) {\n const c = Object.hasOwn(COMPONENTS, type) ? COMPONENTS[type] : void 0;\n return c && ["id", "type", ...c.fields, ...c.presentation ? ["icon"] : [], ...c.presentation === "tone" ? ["tone"] : []];\n }\n\n // lib/identifiers.js\n var IDENTIFIER_SOURCE = "[\\\\p{L}_][\\\\p{L}\\\\p{M}\\\\p{N}_]{0,63}";\n var pattern = new RegExp(`^${IDENTIFIER_SOURCE}$`, "u");\n var validIdentifier = (value) => typeof value === "string" && pattern.test(value) && !["constructor", "prototype", "__proto__"].includes(value);\n\n // lib/author-expression.js\n function compileExpression(source) {\n const fail2 = () => {\n throw new Error("DSH UI: invalid formula; use state.x, data.x, derived.x, item.x, numbers, strings, + - * /, comparisons, ?: and min/max/round/ceil/floor/abs");\n };\n if (typeof source !== "string" || !source.trim() || source.length > 2048) fail2();\n const tokens = [];\n let offset = 0;\n const token2 = new RegExp(String.raw`\\s*(?:(\\d+(?:\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?|("(?:[^"\\\\]|\\\\.)*")|(${IDENTIFIER_SOURCE}(?:\\.${IDENTIFIER_SOURCE})?)|(===|!==|<=|>=|==|!=|[+*/()?,:<>-]))`, "uy");\n while (offset < source.length) {\n if (!source.slice(offset).trim()) break;\n token2.lastIndex = offset;\n const m2 = token2.exec(source);\n if (!m2) fail2();\n offset = token2.lastIndex;\n tokens.push(m2[1] ? { number: Number(m2[1] + (m2[2] ?? "")) } : m2[3] ? { string: JSON.parse(m2[3]) } : m2[4] ?? m2[5]);\n if (tokens.length > 256) fail2();\n }\n let pos = 0;\n const operators = { "==": ["eq", 1], "===": ["eq", 1], "!=": ["neq", 1], "!==": ["neq", 1], "<": ["lt", 2], "<=": ["lte", 2], ">": ["gt", 2], ">=": ["gte", 2], "+": ["add", 3], "-": ["sub", 3], "*": ["mul", 4], "/": ["div", 4] };\n const take = (t) => {\n if (tokens[pos++] !== t) fail2();\n };\n function parse(min = 0, depth = 0) {\n if (depth > 12) fail2();\n const t = tokens[pos++];\n let out;\n if (t && typeof t === "object") out = { const: Object.hasOwn(t, "number") ? t.number : t.string };\n else if (t === "true" || t === "false") out = { const: t === "true" };\n else if (t === "(") {\n out = parse(0, depth + 1);\n take(")");\n } else if (t === "-" || t === "+") {\n const arg = parse(5, depth + 1);\n out = t === "-" ? { op: "sub", args: [{ const: 0 }, arg] } : arg;\n } else if (typeof t === "string" && t.split(".").length === 2 && ["state", "data", "derived", "item"].includes(t.split(".")[0]) && validIdentifier(t.split(".")[1])) out = { ref: t };\n else if (["min", "max", "round", "ceil", "floor", "abs"].includes(t)) {\n take("(");\n const args = [parse(0, depth + 1)];\n while (tokens[pos] === ",") {\n pos++;\n args.push(parse(0, depth + 1));\n if (args.length > 8) fail2();\n }\n take(")");\n out = { op: t, args };\n } else fail2();\n while (typeof tokens[pos] === "string" && Object.hasOwn(operators, tokens[pos]) && operators[tokens[pos]][1] >= min) {\n const [op, precedence] = operators[tokens[pos++]];\n out = { op, args: [out, parse(precedence + 1, depth + 1)] };\n }\n if (min === 0 && tokens[pos] === "?") {\n pos++;\n const yes = parse(0, depth + 1);\n take(":");\n out = { op: "if", args: [out, yes, parse(0, depth + 1)] };\n }\n return out;\n }\n const result = parse();\n if (pos !== tokens.length) fail2();\n return result;\n }\n function expandExpressions(doc2) {\n const expression2 = (e, at2) => {\n if (!e || typeof e !== "object" || Array.isArray(e)) return e;\n if (Object.hasOwn(e, "expr")) {\n if (Object.keys(e).length !== 1) throw new Error("DSH UI: expr must be the only formula field");\n try {\n return compileExpression(e.expr);\n } catch (error) {\n error.message = "DSH UI: " + at2 + ": " + error.message.replace(/^DSH UI: /, "");\n error.path = at2;\n throw error;\n }\n }\n if (Array.isArray(e.args)) e.args = e.args.map((v2, i) => expression2(v2, at2 + ".args[" + i + "]"));\n if (e.map?.fields) for (const k2 of Object.keys(e.map.fields)) e.map.fields[k2] = expression2(e.map.fields[k2], at2 + ".map.fields." + k2);\n return e;\n };\n if (doc2.derived && typeof doc2.derived === "object") for (const k2 of Object.keys(doc2.derived)) doc2.derived[k2] = expression2(doc2.derived[k2], "derived." + k2);\n const walk = (nodes) => {\n if (!Array.isArray(nodes)) return;\n for (const node2 of nodes) {\n if (!node2 || typeof node2 !== "object") continue;\n for (const field of ["text", "value", "max", "rows"]) if (Object.hasOwn(node2, field)) node2[field] = expression2(node2[field], "node." + node2.id + "." + field);\n if (["table", "chart"].includes(node2.type) && Array.isArray(node2.rows)) {\n for (const [rowIndex, row] of node2.rows.entries()) if (row && typeof row === "object" && !Array.isArray(row)) for (const k2 of Object.keys(row)) row[k2] = expression2(row[k2], "node." + node2.id + ".rows[" + rowIndex + "]." + k2);\n }\n walk(node2.children);\n }\n };\n walk(doc2.nodes);\n return doc2;\n }\n\n // lib/visual-guard.js\n var ne = ["h1", "h2", "h3", "body", "muted", "caption"];\n var te = ["primary", "danger", "success", "ghost"];\n var ie = ["success", "warn", "danger", "accent"];\n var re = ["text", "email", "password", "color"];\n var se = ["info", "success", "warning", "error"];\n var U = ["bars", "line", "donut"];\n var oe = ["line", "area", "scatter"];\n var ae = ["16:9", "4:3", "1:1", "9:16"];\n var ue = ["box", "sphere", "cone", "cylinder", "torus"];\n var le = ["file", "dir"];\n var de = ["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"];\n var ce = ["focal", "backend", "store", "external", "input", "optional", "security"];\n var fe = ["light", "dark", "editorial"];\n var pe = ["solid", "dashed", "accent", "link"];\n var me = ["auto", "orthogonal", "straight"];\n var ge = ["bar", "line", "area", "pie", "scatter", "radar", "gauge", "funnel", "treemap", "sankey", "graph", "heatmap", "bigline", "wordCloud"];\n var tn = ["hero"];\n var ye = ["bar", "ring"];\n var be = ["info", "success", "warning", "danger"];\n var he = ["accent", "success", "warning", "danger"];\n var Ee = ["text", "num", "delta", "bar", "badge", "spark", "ring", "index", "group"];\n var b = (t, i, r = {}, e = {}) => {\n let s = Object.fromEntries(Object.entries(i).filter(([u]) => u !== "type" && !t.includes(u))), n = e.oneOfRequired ?? [], o = e.conditionalRequired ?? [], a = [...n.map((u) => ({ kind: "one-of-required", fields: u })), ...o];\n return { required: t, fields: i, optional: s, aliases: r, valueAliases: e.valueAliases ?? {}, oneOfRequired: n, conditionalRequired: o, rules: a, enums: e.enums ?? {}, nested: e.nested ?? {}, ...e.validator === void 0 ? {} : { validator: e.validator } };\n };\n var G = (t, i, r = {}, e = {}, s = {}) => ({ required: t, fields: i, enums: e, nested: r, aliases: s });\n var h = { type: "string", span: "number", id: "string" };\n var De = G(["label", "value"], { label: "string", value: "number", color: "string" });\n var rn = G(["label", "data"], { label: "string", color: "string", data: "array" }, { data: De });\n var sn = G(["title"], { title: "string", desc: "string" });\n var on = G(["key", "value"], { key: "string", value: "string" }, {}, {}, { label: "key" });\n var an = G(["title"], { title: "string", desc: "string", time: "string" });\n var un = G(["path", "newText"], { path: "string", oldText: "string-or-null", newText: "string" });\n var ln = G(["name", "value"], { name: "string", value: "number", min: "number", max: "number", step: "number", animateTo: "number", durationMs: "number", loop: "boolean" });\n var dn = G(["expr"], { expr: "string", label: "string", color: "string", kind: "string", params: "array" }, { params: ln }, { kind: oe });\n var cn = G(["shape"], { shape: "string", color: "string", position: "array", rotation: "array", scale: "unknown", size: "unknown" }, {}, { shape: ue });\n function Oe(t) {\n return G(["name"], { name: "string", type: "string", children: "array" }, t > 0 ? { children: Oe(t - 1) } : {}, { type: le }, { label: "name" });\n }\n var fn = Oe(6);\n var pn = G(["label", "items"], { label: "string", items: "nodes", content: "nodes" });\n var mn = G(["title", "items"], { title: "string", items: "nodes" });\n var gn = G(["id", "label"], { id: "string", label: "string", sub: "string", type: "string", x: "number", y: "number", w: "number", h: "number", tag: "string" }, {}, { type: ce });\n var yn = G(["from", "to"], { from: "string", to: "string", label: "string", kind: "string", route: "string" }, {}, { kind: pe, route: me });\n var bn = G(["label"], { label: "string", x: "number", y: "number", w: "number", h: "number" });\n var hn = G([], { paper: "string", "paper-2": "string", ink: "string", muted: "string", soft: "string", rule: "string", accent: "string", "accent-tint": "string", link: "string" });\n var V = b(["items"], { title: "string", gap: "number", panel: "boolean", append: "boolean", items: "nodes" });\n var T = { accordion: b(["items"], { ...h, items: "array" }, {}, { nested: { items: mn } }), audio: b(["src"], { ...h, src: "string", alt: "string", loop: "boolean" }, { url: "src", link: "src" }), avatar: b(["name"], { ...h, name: "string", color: "string" }), badge: b(["label"], { ...h, label: "string", tone: "string", icon: "string" }, { text: "label", value: "label" }, { enums: { tone: ie } }), breadcrumb: b(["items"], { ...h, items: "array" }), button: b(["label"], { ...h, label: "string", tone: "string", full: "boolean", small: "boolean", icon: "string", action: "string" }, {}, { enums: { tone: te } }), callout: b(["content"], { ...h, title: "string", content: "string", tone: "string" }, { kind: "tone", text: "content", body: "content", desc: "content" }, { enums: { tone: se }, valueAliases: { tone: { danger: "error", warn: "warning" } } }), card: b(["items"], { ...h, title: "string", items: "nodes", tone: "string", accent: "string" }, { label: "title", content: "items" }, { enums: { tone: be } }), chart: b([], { ...h, kind: "string", data: "array", series: "array", horizontal: "boolean", stacked: "boolean", filter: "string", palette: "array" }, {}, { oneOfRequired: [["data", "series"]], conditionalRequired: [{ kind: "required-if", when: { field: "kind", equals: "donut" }, required: ["data"] }], nested: { data: De, series: rn }, enums: { kind: U }, validator: { name: "chart-renderability" } }), checkbox: b(["label"], { ...h, label: "string", checked: "boolean", action: "string", group: "string" }), code: b(["code"], { ...h, lang: "string", code: "string", title: "string", wrap: "boolean" }, { content: "code", text: "code" }), col: b(["items"], { ...h, items: "nodes", gap: "number" }), copy: b(["text"], { ...h, label: "string", text: "string" }, { content: "text", code: "text", value: "text" }), diagram: b(["kind", "nodes"], { ...h, kind: "string", variant: "string", title: "string", nodes: "array", edges: "array", zones: "array", theme: "object" }, {}, { nested: { nodes: gn, edges: yn, zones: bn, theme: hn }, enums: { kind: de, variant: fe } }), diff: b(["diffs"], { ...h, diffs: "array" }, { items: "diffs", files: "diffs" }, { nested: { diffs: un } }), divider: b([], h), echart: b([], { ...h, title: "string", height: "number", preset: "string", data: "array", series: "array", links: "array", palette: "array", option: "object" }, {}, { oneOfRequired: [["option", "data", "series", "links"]], enums: { preset: ge } }), "file-tree": b(["items"], { ...h, items: "array" }, { nodes: "items" }, { nested: { items: fn } }), grid: b(["items"], { ...h, cols: "number", items: "nodes" }), image: b(["src"], { ...h, src: "string", alt: "string" }, { url: "src", link: "src" }), input: b([], { ...h, label: "string", placeholder: "string", value: "string", inputType: "string", action: "string", id: "string" }, {}, { enums: { inputType: re } }), json: b(["value"], { ...h, value: "unknown" }), keyvalue: b(["pairs"], { ...h, pairs: "array" }, { items: "pairs", rows: "pairs", entries: "pairs" }, { nested: { pairs: on } }), link: b(["label"], { ...h, label: "string", href: "string" }), list: b(["items"], { ...h, items: "array", filter: "string" }), mermaid: b(["code"], { ...h, code: "string" }), svg: b(["code"], { ...h, code: "string", title: "string", height: "number" }), plot: b(["series"], { ...h, series: "array", xMin: "number", xMax: "number", yMin: "number", yMax: "number", title: "string" }, {}, { nested: { series: dn } }), progress: b(["value"], { ...h, value: "number", label: "string", valueLabel: "string", variant: "string", target: "number" }, {}, { enums: { variant: ye } }), quiz: b(["question", "options"], { ...h, question: "string", options: "array", explanation: "string", id: "string", action: "string" }, { title: "question", text: "question", choices: "options", items: "options" }), radio: b(["options"], { ...h, label: "string", options: "array", selected: "number", action: "string", group: "string", answer: "unknown", explanation: "string" }, { items: "options" }), row: b(["items"], { ...h, items: "nodes", wrap: "boolean", spacer: "boolean" }), scene3d: b(["meshes"], { ...h, title: "string", meshes: "array", ambient: "number", background: "string" }, {}, { nested: { meshes: cn } }), select: b(["options"], { ...h, label: "string", options: "array", action: "string", selected: "number", id: "string" }, { items: "options" }), slider: b([], { ...h, label: "string", min: "number", max: "number", step: "number", value: "number", action: "string", id: "string" }), spacer: b([], h), hero: b(["title"], { ...h, title: "string", subtitle: "string", value: "string", label: "string", delta: "string", spark: "array", tone: "string" }, {}, { enums: { tone: he } }), stat: b(["label", "value"], { ...h, label: "string", value: "string", delta: "string", spark: "array", size: "string" }, {}, { enums: { size: tn } }), steps: b(["steps"], { ...h, steps: "array", current: "number" }, { items: "steps" }, { nested: { steps: sn } }), submit: b(["label"], { ...h, label: "string", action: "string", resetAction: "string", groups: "array" }), switch: b(["label"], { ...h, label: "string", checked: "boolean", action: "string" }), table: b(["columns", "rows"], { ...h, columns: "array", rows: "array", types: "array", total: "boolean", details: "array", filter: "string", filterColumn: "number", sortField: "string", export: "boolean" }, { headers: "columns", data: "rows", items: "rows" }), tabs: b(["tabs"], { ...h, tabs: "array" }, {}, { nested: { tabs: pn } }), text: b(["content"], { ...h, content: "string", size: "string", center: "boolean", copyable: "boolean", title: "string" }, { text: "content" }, { enums: { size: ne } }), textarea: b([], { ...h, label: "string", placeholder: "string", rows: "number", value: "string", action: "string", id: "string" }), timeline: b(["items"], { ...h, items: "array" }, {}, { nested: { items: an } }), video: b(["src"], { ...h, src: "string", alt: "string", poster: "string", loop: "boolean", muted: "boolean", aspectRatio: "string" }, { url: "src", link: "src" }, { enums: { aspectRatio: ae } }) };\n var q = new Set(Object.keys(T));\n function N(t) {\n if (typeof t != "object" || t === null) return false;\n let i = t;\n return typeof i.type != "string" || i.type === "" ? false : Array.isArray(i.items) ? q.has(i.type) : true;\n }\n function z(t) {\n if (typeof t != "object" || t === null) return null;\n let i = t;\n if (typeof i.type != "string" || i.type === "") return null;\n let r = q.has(i.type) ? T[i.type] : void 0, e = typeof i.title == "string" && r !== void 0 && !("title" in r.fields) ? i.title : void 0, s = { ...t };\n return e !== void 0 && delete s.title, { items: [s], ...e !== void 0 ? { title: e } : {}, ...i.panel === true ? { panel: true } : {}, ...i.append === true ? { append: true } : {} };\n }\n var m = { 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 };\n function ke(t) {\n let i = t.columns, r = Array.isArray(i) && i.length > 0, e = r && Array.isArray(i) && typeof i[0] == "object" && i[0] !== null ? i.map($n) : i, s = kn(e), n = t.rows !== void 0 ? t.rows : t.data;\n if (Array.isArray(n) && n.length > 0 && typeof n[0] == "object" && n[0] !== null && !Array.isArray(n[0])) {\n let u = Array.isArray(t.columns) && t.columns.length > 0 && typeof t.columns[0] == "object" && t.columns[0] !== null ? t.columns.map(Sn).filter((d) => d !== void 0) : Object.keys(n[0]);\n n = n.map((d) => u.map((c) => wn(d[c])));\n }\n let o = null;\n if (!r && Array.isArray(n) && n.length > 0 && Array.isArray(n[0])) {\n let u = xe(n), d = u.length === 0 ? null : An(u);\n d !== null && xe(d.rows).length === d.rows.length && (o = d, s = d.columns.map((c) => c.slice(0, 128)));\n }\n if (s.length === 0 && !Array.isArray(t.columns)) return null;\n let a = xe(o === null ? n : o.rows);\n return Array.isArray(n) ? { columns: s.slice(0, m.maxTableCols), rows: a } : null;\n }\n function I(t) {\n return ke(t)?.rows ?? [];\n }\n function xn(t, i) {\n return !Array.isArray(t) || !Array.isArray(i) || i[0] !== "group" ? false : String(t[0] ?? "").trim() !== "" && t.slice(1).every((r) => String(r ?? "").trim() === "");\n }\n function C(t, i) {\n let r = I(t);\n return i >= 0 && i < r.length && !xn(r[i], t.types);\n }\n function kn(t) {\n if (!Array.isArray(t)) return [];\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxTableCols) break;\n if (typeof r == "string") i.push(r.slice(0, 128));\n else if (r !== null && typeof r == "object") {\n let e = r, s = typeof e.label == "string" ? e.label : typeof e.value == "string" ? e.value : typeof e.title == "string" ? e.title : JSON.stringify(r);\n i.push(s.slice(0, 128));\n }\n }\n return i;\n }\n function xe(t) {\n if (!Array.isArray(t)) return [];\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxTableRows) break;\n if (!Array.isArray(r)) continue;\n let e = [];\n for (let s of r) {\n if (e.length >= m.maxTableCols) break;\n typeof s == "string" ? e.push(s.slice(0, 256)) : typeof s == "number" && Number.isFinite(s) && e.push(s);\n }\n e.length > 0 && i.push(e);\n }\n return i;\n }\n function An(t) {\n let i = t[0];\n if (i === void 0 || i.length === 0) return null;\n let r = t.slice(1);\n if (r.length === 0) {\n let e = i.map((s) => String(s).trim());\n return e.every((s) => s !== "") ? { columns: e, rows: [] } : null;\n }\n return r.every((e) => e.length === i.length) ? { columns: i.map((e) => String(e).trim()), rows: r } : { columns: Array.from({ length: i.length }, (e, s) => `\\u5217${s + 1}`), rows: t };\n }\n function Sn(t) {\n if (t === null || typeof t != "object" || Array.isArray(t)) return;\n let i = t;\n for (let r of ["key", "dataIndex", "title", "label"]) if (typeof i[r] == "string" && i[r] !== "") return i[r];\n }\n function wn(t) {\n return typeof t == "string" || typeof t == "number" && Number.isFinite(t) ? t : t == null ? "" : JSON.stringify(t);\n }\n function $n(t) {\n if (t === null || typeof t != "object" || Array.isArray(t)) return String(t);\n let i = t;\n for (let r of ["title", "label", "key", "dataIndex"]) if (typeof i[r] == "string" && i[r] !== "") return i[r];\n return JSON.stringify(t);\n }\n function O(t) {\n return typeof t == "object" && t !== null && !Array.isArray(t) ? t : void 0;\n }\n function Ae(t) {\n let i = O(t);\n return i !== void 0 && typeof i.type == "string";\n }\n var Gn = ["label", "value", "delta", "spark", "size"];\n var Rn = { label: "title", name: "title", description: "desc", content: "desc", text: "desc", body: "desc", detail: "desc" };\n function Tn(t, i, r) {\n if (t.length === 0) return null;\n let e = [];\n for (let s = 0; s < t.length; s++) {\n let n = t[s], o = O(n);\n if (o === void 0) return null;\n if (Ae(n)) {\n e.push(r(n, `${i}.items[${s}]`));\n continue;\n }\n if (typeof o.label != "string" && typeof o.value != "string") return null;\n let a = { type: "stat" };\n for (let u of Gn) o[u] !== void 0 && (a[u] = o[u]);\n e.push(a);\n }\n return e;\n }\n function Cn(t, i, r, e) {\n let s = T[r];\n if (s === void 0) return t;\n let n = { ...t };\n for (let [o, a] of Object.entries(s.aliases)) {\n if (!(o in n)) continue;\n let u = `${i}.${o}`, d = a in n;\n d || (n[a] = n[o]), delete n[o], e.push({ kind: "alias", path: u, message: d ? `${u} is ignored because canonical field \'${a}\' is present` : `${u} normalized/adopted as \'${a}\'`, type: r, field: o, canonical: a });\n }\n for (let [o, a] of Object.entries(s.valueAliases)) {\n let u = n[o];\n if (typeof u != "string") continue;\n let d = a[u];\n d === void 0 || d === u || (n[o] = d, e.push({ kind: "alias", path: `${i}.${o}`, message: `${i}.${o} \'${u}\' normalized to \'${d}\'`, type: r, field: o, canonical: d }));\n }\n return n;\n }\n function Se(t, i, r, e, s) {\n if (Array.isArray(t)) return t.map((a, u) => Se(a, i, `${r}[${u}]`, e, s));\n let n = O(t);\n if (n === void 0) return t;\n let o = { ...n };\n for (let [a, u] of Object.entries(i.aliases)) !(a in o) || u in o || (o[u] = o[a], delete o[a], s.push({ kind: "alias", path: `${r}.${a}`, message: `${r}.${a} normalized/adopted as \'${u}\'`, type: e, field: a, canonical: u }));\n for (let [a, u] of Object.entries(i.nested)) o[a] !== void 0 && (o[a] = Se(o[a], u, `${r}.${a}`, e, s));\n return o;\n }\n function we(t) {\n if (Array.isArray(t)) return t.map(we);\n let i = O(t);\n if (i === void 0) return t;\n let r = { ...i };\n return r.type === void 0 && Array.isArray(r.children) && (r.type = "dir"), r.children !== void 0 && (r.children = we(r.children)), r;\n }\n function $e(t, i, r) {\n if (!Ae(t)) return t;\n let e = t.type, s = T[e];\n if (s === void 0) return t;\n let n = Cn(t, i, e, r);\n for (let [u, d] of Object.entries(s.nested)) n[u] !== void 0 && (n[u] = Se(n[u], d, `${i}.${u}`, e, r));\n let o = (u, d) => $e(u, d, r), a = (u, d) => Array.isArray(u) ? u.map((c, f) => o(c, `${d}[${f}]`)) : u;\n if (e === "file-tree" && n.items !== void 0 && (n.items = we(n.items)), e === "stat" && Array.isArray(n.items) && n.label === void 0 && n.value === void 0) {\n let u = Tn(n.items, i, o);\n if (u !== null) return r.push({ kind: "alias", path: `${i}.items`, message: `${i}.items normalized into a row of \'stat\' nodes`, type: e, field: "items", canonical: "row" }), { type: "row", items: u, ...n.span !== void 0 ? { span: n.span } : {} };\n }\n if (e === "row" || e === "col" || e === "grid" || e === "card" || e === "file-tree" || e === "timeline" || e === "breadcrumb") e !== "file-tree" && e !== "timeline" && e !== "breadcrumb" && (n.items = a(n.items, `${i}.items`));\n else if (e === "list" && Array.isArray(n.items)) n.items = n.items.map((u, d) => {\n if (Ae(u)) return o(u, `${i}.items[${d}]`);\n if (Array.isArray(u) && u.length === 1 && typeof u[0] == "string") return u[0];\n let c = O(u);\n if (c === void 0) return u;\n let f = { ...c }, g = `${i}.items[${d}]`;\n for (let [x, $] of Object.entries(Rn)) {\n if (!(x in f)) continue;\n let J = $ in f;\n J || (f[$] = f[x]), delete f[x], r.push({ kind: "alias", path: `${g}.${x}`, type: e, field: x, canonical: $, message: J ? `${g}.${x} is ignored because canonical field \'${$}\' is present` : `${g}.${x} normalized/adopted as \'${$}\'` });\n }\n return !("title" in f) && typeof f.desc == "string" && (f.title = f.desc, delete f.desc, r.push({ kind: "alias", path: `${g}.desc`, type: e, field: "desc", canonical: "title", message: `${g}.desc normalized/adopted as \'title\'` })), f;\n });\n else if (e === "keyvalue" && Array.isArray(n.pairs)) n.pairs.length > 0 && n.pairs.every((u) => Array.isArray(u)) && (n.pairs = n.pairs.map((u) => {\n let d = u;\n return { key: d[0], value: d.length > 1 ? d[1] : "" };\n }));\n else if (e === "tabs" && Array.isArray(n.tabs)) n.tabs = n.tabs.map((u, d) => {\n let c = O(u);\n if (c === void 0) return u;\n let f = { ...c };\n if ("content" in f) {\n let g = `${i}.tabs[${d}].content`, x = "items" in f;\n x || (f.items = f.content), delete f.content, r.push({ kind: "alias", path: g, message: x ? `${g} is ignored because canonical field \'items\' is present` : `${g} normalized/adopted as \'items\'`, type: e, field: "content", canonical: "items" });\n }\n return f.items = Array.isArray(f.items) ? f.items.map((g, x) => o(g, `${i}.tabs[${d}].items[${x}]`)) : f.items === void 0 ? [] : [o(f.items, `${i}.tabs[${d}].items[0]`)], f;\n });\n else if (e === "accordion" && Array.isArray(n.items)) n.items = n.items.map((u, d) => {\n let c = O(u);\n return c === void 0 ? u : { ...c, items: Array.isArray(c.items) ? c.items.map((f, g) => o(f, `${i}.items[${d}].items[${g}]`)) : c.items };\n });\n else if (e === "table" && Array.isArray(n.details)) {\n let u = { columns: n.columns, rows: n.rows, types: n.types };\n n.details = n.details.map((d, c) => !Array.isArray(d) || !C(u, c) ? d : d.map((f, g) => o(f, `${i}.details[${c}][${g}]`)));\n }\n return n;\n }\n function Ie(t) {\n let i = [];\n if (typeof t == "string") try {\n let s = JSON.parse(t);\n (O(s) !== void 0 || Array.isArray(s)) && (t = s, i.push({ kind: "alias", path: "spec", message: "double-encoded JSON string unwrapped into a spec value" }));\n } catch {\n }\n Array.isArray(t) && t.length > 0 && (t = { items: t }, i.push({ kind: "alias", path: "items", message: "root array normalized into an items envelope" }));\n let r = O(t);\n if (r === void 0) return { value: t, warnings: i };\n let e = { ...r };\n return N(e) ? { value: $e(e, "spec", i), warnings: i } : (Array.isArray(e.items) && (e.items = e.items.map((s, n) => $e(s, `items[${n}]`, i))), { value: e, warnings: i });\n }\n function F(t) {\n return typeof t == "object" && t !== null && !Array.isArray(t) ? t : void 0;\n }\n function _e(t) {\n let i = F(t);\n return i !== void 0 && typeof i.type == "string";\n }\n function Ge(t, i, r) {\n if (!_e(t)) return;\n let e = t.type, s = T[e];\n if (s === void 0) return;\n r(t, i, s);\n let n = (o, a) => Ge(o, a, r);\n if ((e === "row" || e === "col" || e === "grid" || e === "card") && Array.isArray(t.items)) t.items.forEach((o, a) => n(o, `${i}.items[${a}]`));\n else if (e === "list" && Array.isArray(t.items)) t.items.forEach((o, a) => n(o, `${i}.items[${a}]`));\n else if (e === "tabs" && Array.isArray(t.tabs)) t.tabs.forEach((o, a) => {\n let u = F(o);\n u !== void 0 && (Array.isArray(u.items) ? u.items.forEach((d, c) => n(d, `${i}.tabs[${a}].items[${c}]`)) : n(u.items, `${i}.tabs[${a}].items`));\n });\n else if (e === "accordion" && Array.isArray(t.items)) t.items.forEach((o, a) => {\n let u = F(o);\n u?.items !== void 0 && Array.isArray(u.items) && u.items.forEach((d, c) => n(d, `${i}.items[${a}].items[${c}]`));\n });\n else if (e === "table" && Array.isArray(t.details)) {\n let o = { columns: t.columns, rows: t.rows, types: t.types };\n t.details.forEach((a, u) => {\n Array.isArray(a) && C(o, u) && a.forEach((d, c) => n(d, `${i}.details[${u}][${c}]`));\n });\n }\n }\n function B(t, i, r, e) {\n t.push({ kind: "unknown-field", path: `${i}.${r}`, message: `${i}.${r}: unknown field for \'${e}\'`, type: e, field: r });\n }\n function Y(t, i, r, e, s) {\n let n = F(t);\n if (n !== void 0) {\n for (let o of Object.keys(n)) o in r.fields || B(s, i, o, e);\n for (let [o, a] of Object.entries(r.nested)) {\n let u = n[o];\n Array.isArray(u) ? u.forEach((d, c) => Y(d, `${i}.${o}[${c}]`, a, e, s)) : u !== void 0 && Y(u, `${i}.${o}`, a, e, s);\n }\n }\n }\n function Nn(t, i, r, e) {\n for (let [s, n] of Object.entries(r.nested)) {\n let o = t[s];\n Array.isArray(o) ? o.forEach((a, u) => Y(a, `${i}.${s}[${u}]`, n, t.type, e)) : o !== void 0 && Y(o, `${i}.${s}`, n, t.type, e);\n }\n }\n function Pe(t) {\n let i = [], r = F(t);\n if (r === void 0) return i;\n let e = (s, n, o) => {\n for (let a of Object.keys(s)) a === "type" || a in o.fields || B(i, n, a, s.type);\n Nn(s, n, o, i), s.type === "list" && Array.isArray(s.items) && s.items.forEach((a, u) => {\n if (_e(a)) return;\n let d = F(a);\n if (d !== void 0) for (let c of Object.keys(d)) {\n if (c === "title" || c === "desc") continue;\n let f = `${n}.items[${u}]`;\n i.push({ kind: "unknown-field", path: `${f}.${c}`, message: `${f}.${c}: list items render \'title\' and \'desc\' only \\u2014 \'${c}\' is dropped`, type: "list", field: c });\n }\n });\n };\n if (Array.isArray(r.items) && !N(r)) {\n for (let s of Object.keys(r)) s in V.fields || B(i, "spec", s, "spec");\n r.items.forEach((s, n) => Ge(s, `items[${n}]`, e));\n } else if (typeof r.type == "string") Ge(r, "spec", e);\n else for (let s of Object.keys(r)) s in V.fields || B(i, "spec", s, "spec");\n return i;\n }\n function ve(t, i) {\n let r = (s, n, o) => {\n o > m.maxDepth || s.forEach((a, u) => e(a, `${n}[${u}]`, o));\n }, e = (s, n, o) => {\n if (!(o > m.maxDepth) && (i(s, n), !(o >= m.maxDepth))) switch (s.type) {\n case "row":\n case "col":\n case "grid":\n case "card":\n r(s.items, `${n}.items`, o + 1);\n break;\n case "tabs":\n s.tabs.forEach((a, u) => r(a.items, `${n}.tabs[${u}].items`, o + 1));\n break;\n case "accordion":\n s.items.forEach((a, u) => r(a.items, `${n}.items[${u}].items`, o + 1));\n break;\n case "list":\n s.items.forEach((a, u) => {\n a !== null && typeof a == "object" && "type" in a && e(a, `${n}.items[${u}]`, o + 1);\n });\n break;\n case "table":\n s.details?.slice(0, I(s).length).forEach((a, u) => {\n a !== null && C(s, u) && r(a, `${n}.details[${u}]`, o + 1);\n });\n break;\n }\n };\n r(t.items, "items", 0);\n }\n function Re(t) {\n let i = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), e = [], s = [];\n ve(t, (n, o) => {\n if (n.type === "submit") {\n n.groups !== void 0 && s.push({ groups: n.groups, path: o });\n return;\n }\n let a, u;\n switch (n.type) {\n case "radio":\n if (n.group === void 0) return;\n a = { kind: "radio", key: n.group, label: n.label ?? n.group, options: n.options.slice(0, m.maxOptions), ...n.answer === void 0 ? {} : { answer: n.answer }, ...n.explanation === void 0 ? {} : { explanation: n.explanation } }, u = `${o}.group`;\n break;\n case "checkbox":\n if (n.group === void 0) return;\n a = { kind: "checkbox", key: n.group }, u = `${o}.group`;\n break;\n case "input":\n case "textarea":\n case "select":\n case "slider":\n if (n.id === void 0) return;\n a = { kind: "field", key: n.id, fieldType: n.type, secret: n.type === "input" && n.inputType === "password" }, u = `${o}.id`;\n break;\n default:\n return;\n }\n if (a === void 0) return;\n let d = i.get(a.key);\n if (d !== void 0) {\n (d.kind !== "checkbox" || a.kind !== "checkbox") && e.push(`${u} conflicts with ${r.get(a.key)}: submission key \'${a.key}\' is already used`);\n return;\n }\n i.set(a.key, a), r.set(a.key, u);\n });\n for (let { groups: n, path: o } of s) {\n let a = /* @__PURE__ */ new Set();\n n.forEach((u, d) => {\n let c = `${o}.groups[${d}]`;\n a.has(u) && e.push(`${c}: duplicate submission member \'${u}\'`), a.add(u);\n let f = i.get(u);\n f === void 0 ? e.push(`${c}: submit.groups references unknown submission member \'${u}\'`) : f.kind === "field" && f.secret && e.push(`${c}: submit.groups cannot require secret field \'${u}\'`);\n });\n }\n return { registry: { members: i }, diagnostics: e };\n }\n function En(t, i) {\n return typeof t == "string" && i.includes(t);\n }\n function p(t, i) {\n return typeof t == "string" ? t.slice(0, i) : void 0;\n }\n var Dn = /^(?:#[\\da-fA-F]{3,8}|rgba?\\([^)]{0,64}\\)|hsla?\\([^)]{0,64}\\)|var\\(--dsw-[\\w-]+(?:,\\s*#[0-9a-fA-F]{3,8})?\\))$/;\n function E(t) {\n if (typeof t != "string") return;\n let i = t.trim();\n return i.length <= 64 && Dn.test(i) ? i : void 0;\n }\n function qe(t) {\n if (typeof t != "string") return;\n let i = t.trim();\n if (!(i.length > 2048)) return /^https?:\\/\\//i.test(i) || /^mailto:[^@\\s]+@[^@\\s]+$/i.test(i) ? i : void 0;\n }\n function K(t) {\n if (typeof t != "string") return;\n let i = t.trim();\n if (!(i === "" || i.length > 2048)) {\n if (/^https?:\\/\\//i.test(i)) return i;\n if (!(/^[a-z][a-z0-9+.-]*:/i.test(i) || /^[/\\\\]{2}/.test(i))) return i;\n }\n }\n function k(t, i, r) {\n return typeof t == "number" && Number.isFinite(t) ? Math.min(r, Math.max(i, t)) : void 0;\n }\n function D(t, i, r) {\n return typeof t == "number" && Number.isFinite(t) ? Math.min(r, Math.max(i, Math.trunc(t))) : void 0;\n }\n function w(t, i) {\n return En(t, i) ? t : void 0;\n }\n function y(t) {\n return typeof t == "object" && t !== null && !Array.isArray(t) ? t : void 0;\n }\n function l(t, i) {\n return i === void 0 ? {} : { [t]: i };\n }\n function On(t) {\n if (t.length > 2048) return;\n let i = t.indexOf("#"), r = i < 0 ? t : t.slice(0, i);\n if (r.includes("?")) return;\n let e;\n try {\n e = decodeURIComponent(r);\n } catch {\n return;\n }\n if (e === "" || /[\\u0000-\\u001f\\u007f]/.test(e) || /^[\\\\/]{2}/.test(e) || /^[a-z][a-z\\d+.-]*:/i.test(e) && !/^[a-z]:[\\\\/]/i.test(e)) return;\n if (i < 0) return { path: e };\n let s = /^L([1-9]\\d*)(?:-L([1-9]\\d*))?$/.exec(t.slice(i + 1));\n if (s === null) return;\n let n = Number(s[1]), o = s[2] === void 0 ? n : Number(s[2]);\n if (!(!Number.isSafeInteger(n) || !Number.isSafeInteger(o) || o < n)) return { path: e, line: n };\n }\n function ze(t) {\n let i = qe(t);\n if (i !== void 0) return { type: "external", href: i };\n if (typeof t != "string") return { type: "invalid" };\n let r = On(t.trim());\n return r === void 0 ? { type: "invalid" } : { type: "file", file: r };\n }\n function H(t, i) {\n switch (i) {\n case "string":\n return typeof t == "string";\n case "string-or-null":\n return t === null || typeof t == "string";\n case "number":\n return typeof t == "number" && Number.isFinite(t);\n case "boolean":\n return typeof t == "boolean";\n case "nodes":\n return Array.isArray(t);\n case "array":\n return Array.isArray(t);\n case "object":\n return y(t) !== void 0;\n case "unknown":\n return true;\n }\n }\n function j(t) {\n switch (t) {\n case "string-or-null":\n return "a string or null";\n case "number":\n return "a finite number";\n case "boolean":\n return "a boolean";\n case "nodes":\n case "array":\n return "an array";\n case "object":\n return "an object";\n case "unknown":\n return "a value";\n default:\n return "a string";\n }\n }\n function v(t, i, r) {\n return t.some((e) => e.startsWith(`${i}.${r} `) || e.includes(`\'${r}\'`) || e.includes(`requires ${r}`));\n }\n function Ke(t, i, r, e, s = []) {\n for (let [n, o] of Object.entries(r.fields)) s.includes(n) || t[n] === void 0 || !H(t[n], o) && !v(e, i, n) && e.push(`${i}.${n} must be ${j(o)}`);\n for (let [n, o] of Object.entries(r.enums)) s.includes(n) || t[n] === void 0 || !H(t[n], "string") || !o.includes(t[n]) && !v(e, i, n) && e.push(`${i}.${n} must be one of ${o.join(", ")}`);\n }\n function W(t, i, r, e) {\n let s = y(t);\n if (s === void 0) {\n e.push(`${i} must be an object`);\n return;\n }\n for (let n of r.required) {\n let o = r.fields[n];\n s[n] === void 0 ? v(e, i, n) || e.push(`${i}: requires ${n}${o === void 0 ? "" : ` (${j(o)})`}`) : o !== void 0 && !H(s[n], o) && (v(e, i, n) || e.push(`${i}.${n} must be ${j(o)}`));\n }\n for (let [n, o] of Object.entries(r.fields)) s[n] !== void 0 && !H(s[n], o) && (v(e, i, n) || e.push(`${i}.${n} must be ${j(o)}`));\n for (let [n, o] of Object.entries(r.enums)) s[n] !== void 0 && typeof s[n] == "string" && !o.includes(s[n]) && (v(e, i, n) || e.push(`${i}.${n} must be one of ${o.join(", ")}`));\n for (let [n, o] of Object.entries(r.nested)) {\n let a = s[n];\n a !== void 0 && (Array.isArray(a) ? a.forEach((u, d) => W(u, `${i}.${n}[${d}]`, o, e)) : W(a, `${i}.${n}`, o, e));\n }\n }\n function Mn(t, i, r, e) {\n for (let [s, n] of Object.entries(r.nested)) {\n let o = t[s];\n o !== void 0 && (Array.isArray(o) ? o.forEach((a, u) => W(a, `${i}.${s}[${u}]`, n, e)) : W(o, `${i}.${s}`, n, e));\n }\n }\n function He(t) {\n let i = t.rows !== void 0 ? t.rows : t.data;\n return !Array.isArray(i) || i.length === 0 ? false : Array.isArray(i[0]);\n }\n function In(t, i, r, e) {\n let s = String(t.type), n = (a) => v(e, i, a), o = s === "table" && He(t) ? "columns" : null;\n for (let a of r.required) {\n let u = r.fields[a];\n if (u === void 0 || t[a] === void 0) {\n a !== o && !n(a) && e.push(`${i}: type \'${s}\' requires ${a}${u === void 0 ? "" : ` (${j(u)})`}`);\n continue;\n }\n !H(t[a], u) && !n(a) && e.push(`${i}.${a} must be ${j(u)}`);\n }\n Ke(t, i, r, e, ["type"]);\n for (let a of r.oneOfRequired) !a.some((u) => t[u] !== void 0) && !e.some((u) => u.includes(`requires ${a.join(" or ")}`)) && e.push(`${i}: type \'${s}\' requires one of ${a.join(" or ")}`);\n for (let a of r.conditionalRequired) if (t[a.when.field] === a.when.equals) for (let u of a.required) t[u] === void 0 && !n(u) && e.push(`${i}: type \'${s}\' requires ${u}${a.message === void 0 ? "" : ` (${a.message})`}`);\n Mn(t, i, r, e);\n }\n function _(t, i, r) {\n if (!Array.isArray(t)) return [];\n let e = [];\n for (let s of t) {\n if (i.remaining <= 0) break;\n i.remaining -= 1;\n let n = Je(s, i, r);\n n !== null && e.push(n);\n }\n return e;\n }\n function Fe(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t.slice(0, 12)) {\n let e = E(r);\n e !== void 0 && i.push(e);\n }\n return i.length > 0 ? i : void 0;\n }\n function je(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t.slice(0, 60)) {\n let e = typeof r == "number" ? r : Number(r);\n if (!Number.isFinite(e)) return;\n i.push(e);\n }\n return i.length >= 2 ? i : void 0;\n }\n function Je(t, i, r) {\n let e = _n(t, i, r);\n if (e === null) return null;\n let s = D(y(t)?.span, 2, 12), n = p(y(t)?.id, 64);\n return { ...e, ...l("span", s), ...l("id", n) };\n }\n function _n(t, i, r) {\n if (r > m.maxDepth) return null;\n let e = y(t);\n if (e === void 0) return null;\n let s = e.type;\n if (typeof s != "string") return null;\n switch (s) {\n case "text": {\n let n = p(e.content, m.maxString) ?? p(e.text, m.maxString);\n return n === void 0 ? null : { type: "text", content: n, ...l("copyable", e.copyable === true ? true : void 0), ...l("title", p(e.title, m.maxString)), ...l("size", w(e.size, ne)), ...l("center", e.center === true ? true : void 0) };\n }\n case "row":\n return { type: "row", items: _(e.items, i, r + 1), ...l("wrap", e.wrap === true ? true : void 0), ...l("spacer", e.spacer === true ? true : void 0) };\n case "col":\n return { type: "col", items: _(e.items, i, r + 1), ...l("gap", k(e.gap, 0, 96)) };\n case "grid":\n return { type: "grid", cols: D(e.cols, 1, m.maxGridCols) ?? 1, items: _(e.items, i, r + 1) };\n case "card":\n return { type: "card", items: _(e.items, i, r + 1), ...l("title", p(e.title, m.maxString)), ...l("tone", w(e.tone, be)), ...l("accent", E(e.accent)) };\n case "button": {\n let n = p(e.label, m.maxString);\n return n === void 0 ? null : { type: "button", label: n, ...l("tone", w(e.tone, te)), ...l("full", e.full === true ? true : void 0), ...l("small", e.small === true ? true : void 0), ...l("icon", p(e.icon, 64)), ...l("action", p(e.action, 200)) };\n }\n case "input":\n return { type: "input", ...l("label", p(e.label, m.maxString)), ...l("placeholder", p(e.placeholder, m.maxString)), ...l("value", p(e.value, m.maxString)), ...l("inputType", w(e.inputType, re)), ...l("action", p(e.action, 200)), ...l("id", p(e.id, 200)) };\n case "select": {\n let n = Q(e.options, m.maxOptions, m.maxString);\n return n === void 0 ? null : { type: "select", options: n, ...l("label", p(e.label, m.maxString)), ...l("action", p(e.action, 200)), ...l("selected", D(e.selected, 0, n.length - 1)), ...l("id", p(e.id, 200)) };\n }\n case "checkbox": {\n let n = p(e.label, m.maxString);\n return n === void 0 ? null : { type: "checkbox", label: n, ...l("checked", e.checked === true ? true : void 0), ...l("action", p(e.action, 200)), ...l("group", p(e.group, 200)) };\n }\n case "link": {\n let n = p(e.label, m.maxString);\n if (n === void 0) return null;\n let o = ze(e.href), a = o.type === "external" ? o.href : o.type === "file" ? String(e.href).trim() : void 0;\n return { type: "link", label: n, ...l("href", a) };\n }\n case "image": {\n let n = K(e.src);\n return n === void 0 ? null : { type: "image", src: n, ...l("alt", p(e.alt, m.maxString)) };\n }\n case "audio": {\n let n = K(e.src);\n return n === void 0 ? null : { type: "audio", src: n, ...l("alt", p(e.alt, m.maxString)), ...l("loop", e.loop === true ? true : void 0) };\n }\n case "video": {\n let n = K(e.src);\n return n === void 0 ? null : { type: "video", src: n, ...l("alt", p(e.alt, m.maxString)), ...l("poster", K(e.poster)), ...l("loop", e.loop === true ? true : void 0), ...l("muted", e.muted === true ? true : void 0), ...l("aspectRatio", w(e.aspectRatio, ae)) };\n }\n case "badge": {\n let n = p(e.label, m.maxString) ?? p(e.text, m.maxString) ?? p(e.value, m.maxString);\n return n === void 0 ? null : { type: "badge", label: n, ...l("tone", w(e.tone, ie)), ...l("icon", p(e.icon, 64)) };\n }\n case "hero": {\n let n = p(e.title, m.maxString);\n return n === void 0 ? null : { type: "hero", title: n, ...l("subtitle", p(e.subtitle, m.maxString)), ...l("value", p(e.value, 128)), ...l("label", p(e.label, m.maxString)), ...l("delta", p(e.delta, 64)), ...l("spark", je(e.spark)), ...l("tone", w(e.tone, he)) };\n }\n case "stat": {\n let n = p(e.label, m.maxString), o = p(e.value, 128);\n return n === void 0 || o === void 0 ? null : { type: "stat", label: n, value: o, ...l("delta", p(e.delta, 64)), ...l("spark", je(e.spark)), ...l("size", e.size === "hero" ? "hero" : void 0) };\n }\n case "progress": {\n let n = k(e.value, 0, 100);\n return n === void 0 ? null : { type: "progress", value: n, ...l("label", p(e.label, m.maxString)), ...l("valueLabel", p(e.valueLabel, 64)), ...l("variant", w(e.variant, ye)), ...l("target", k(e.target, 0, 100)) };\n }\n case "divider":\n return { type: "divider" };\n case "spacer":\n return { type: "spacer" };\n case "avatar": {\n let n = p(e.name, 64);\n return n === void 0 ? null : { type: "avatar", name: n, ...l("color", E(e.color)) };\n }\n case "list": {\n let n = Pn(e.items, m.maxListItems, i, r + 1);\n return n === void 0 ? null : { type: "list", items: n, ...l("filter", p(e.filter, 64)) };\n }\n case "table": {\n let n = ke(e);\n if (n === null) return null;\n let { columns: o, rows: a } = n, u = Array.isArray(e.types) ? e.types : void 0, d = u === void 0 ? void 0 : o.map((g, x) => {\n let $ = u[x];\n return typeof $ == "string" && Ee.includes($) ? $ : "text";\n }), c = Array.isArray(e.details) ? e.details : void 0, f = c === void 0 ? void 0 : a.map((g, x) => {\n if (!C({ columns: o, rows: a, types: d }, x)) return null;\n let $ = _(c[x], i, r + 1);\n return $.length === 0 ? null : $;\n });\n return { type: "table", columns: o, rows: a, ...l("types", d), ...l("total", e.total === true ? true : void 0), ...l("export", e.export === true ? true : void 0), ...l("filter", p(e.filter, 64)), ...l("filterColumn", D(e.filterColumn, 0, m.maxTableCols - 1)), ...l("sortField", p(e.sortField, 64)), ...l("details", f !== void 0 && f.some((g) => g !== null) ? f : void 0) };\n }\n case "chart": {\n let n = Te(e.data, m.maxChartPoints), o = Array.isArray(e.series) ? Le(e.series, m.maxPlotSeries, m.maxChartPoints) : void 0;\n return n === void 0 && o === void 0 ? null : { type: "chart", data: n ?? [], ...l("kind", w(e.kind, U)), ...l("series", o), ...l("horizontal", e.horizontal === true ? true : void 0), ...l("stacked", e.stacked === true ? true : void 0), ...l("filter", p(e.filter, 64)), ...l("palette", Fe(e.palette)) };\n }\n case "tabs": {\n let n = vn(e.tabs, i, r);\n return n === void 0 ? null : { type: "tabs", tabs: n };\n }\n case "plot": {\n let n = qn(e.series, m.maxPlotSeries);\n return n === void 0 ? null : { type: "plot", series: n, ...l("xMin", k(e.xMin, -1e6, 1e6)), ...l("xMax", k(e.xMax, -1e6, 1e6)), ...l("yMin", k(e.yMin, -1e9, 1e9)), ...l("yMax", k(e.yMax, -1e9, 1e9)), ...l("title", p(e.title, m.maxString)) };\n }\n case "callout": {\n let n = p(e.content, m.maxString);\n return n === void 0 ? null : { type: "callout", content: n, ...l("tone", w(e.tone, se)), ...l("title", p(e.title, m.maxString)) };\n }\n case "steps": {\n let n = zn(e.steps);\n return n === void 0 ? null : { type: "steps", steps: n, ...l("current", D(e.current, 0, n.length)) };\n }\n case "keyvalue": {\n let n = Fn(e.pairs, m.maxKeyValuePairs);\n return n === void 0 ? null : { type: "keyvalue", pairs: n };\n }\n case "diff": {\n let n = jn(e.diffs);\n return n === void 0 ? null : { type: "diff", diffs: n };\n }\n case "json":\n return "value" in e ? { type: "json", value: e.value } : null;\n case "code": {\n let n = p(e.code, m.maxCode);\n return n === void 0 ? null : { type: "code", code: n, ...l("lang", p(e.lang, 64)), ...l("title", p(e.title, m.maxString)), ...l("wrap", e.wrap === true ? true : void 0) };\n }\n case "radio": {\n let n = Q(e.options, m.maxOptions, m.maxString);\n return n === void 0 ? null : { type: "radio", options: n, ...l("label", p(e.label, m.maxString)), ...l("selected", D(e.selected, 0, n.length - 1)), ...l("action", p(e.action, 200)), ...l("group", p(e.group, 200)), ...l("answer", typeof e.answer == "number" && Number.isFinite(e.answer) && e.answer >= 0 && e.answer < n.length ? Math.trunc(e.answer) : typeof e.answer == "string" ? e.answer.slice(0, 512) : void 0), ...l("explanation", p(e.explanation, m.maxString)) };\n }\n case "submit": {\n let n = p(e.label, m.maxString), o = p(e.action, 200);\n return n === void 0 ? null : { type: "submit", label: n, ...l("action", o), ...l("resetAction", p(e.resetAction, 200)), ...l("groups", Q(e.groups, m.maxOptions, 200)) };\n }\n case "switch": {\n let n = p(e.label, m.maxString);\n return n === void 0 ? null : { type: "switch", label: n, ...l("checked", e.checked === true ? true : void 0), ...l("action", p(e.action, 200)) };\n }\n case "slider": {\n let n = k(e.min, -1e9, 1e9) ?? 0, o = k(e.max, -1e9, 1e9) ?? 100, a = Math.min(n, o), u = Math.max(n, o), d = k(e.step, 1e-9, Math.max(u - a, 1e-9)), c = k(e.value, a, u) ?? a;\n return { type: "slider", min: a, max: u, ...l("step", d), value: c, ...l("label", p(e.label, m.maxString)), ...l("action", p(e.action, 200)), ...l("id", p(e.id, 200)) };\n }\n case "textarea":\n return { type: "textarea", ...l("label", p(e.label, m.maxString)), ...l("placeholder", p(e.placeholder, m.maxString)), ...l("rows", D(e.rows, 1, 30)), ...l("value", p(e.value, m.maxString)), ...l("action", p(e.action, 200)), ...l("id", p(e.id, 200)) };\n case "accordion": {\n let n = Ln(e.items, i, r);\n return n === void 0 ? null : { type: "accordion", items: n };\n }\n case "copy": {\n let n = p(e.text, m.maxCode);\n return n === void 0 ? null : { type: "copy", text: n, ...l("label", p(e.label, 128)) };\n }\n case "svg": {\n let n = p(e.code, m.maxCode);\n return n === void 0 ? null : { type: "svg", code: n, ...l("title", p(e.title, m.maxString)), ...l("height", D(e.height, 100, 800)) };\n }\n case "mermaid": {\n let n = p(e.code, m.maxMermaid);\n return n === void 0 ? null : { type: "mermaid", code: n };\n }\n case "scene3d": {\n let n = Vn(e.meshes);\n return n === void 0 ? null : { type: "scene3d", meshes: n, ...l("title", p(e.title, m.maxString)), ...l("ambient", k(e.ambient, 0, 2)), ...l("background", E(e.background)) };\n }\n case "diagram":\n return Bn(e);\n case "timeline": {\n let n = Yn(e.items, m.maxTimelineItems);\n return n === void 0 ? null : { type: "timeline", items: n };\n }\n case "file-tree": {\n let n = Qn(e.items, m.maxListItems);\n return n === void 0 ? null : { type: "file-tree", items: n };\n }\n case "breadcrumb": {\n let n = Q(e.items, m.maxBreadcrumbItems, m.maxString);\n return n === void 0 ? null : { type: "breadcrumb", items: n };\n }\n case "quiz": {\n let n = p(e.question, m.maxString), o = Zn(e.options, e.answer);\n return n === void 0 || o === void 0 ? null : { type: "quiz", question: n, options: o, ...l("explanation", p(e.explanation, m.maxString)), ...l("id", p(e.id, 200)), ...l("action", p(e.action, 200)) };\n }\n case "echart": {\n let n = e.data !== void 0 ? Te(e.data, m.maxChartPoints) : void 0, o = e.series !== void 0 && Array.isArray(e.series) ? Le(e.series, m.maxPlotSeries, m.maxChartPoints) : void 0, a = Array.isArray(e.links) ? e.links.slice(0, m.maxChartPoints).flatMap((c) => {\n let f = y(c), g = f === void 0 ? void 0 : p(f.from, 64), x = f === void 0 ? void 0 : p(f.to, 64);\n return g === void 0 || x === void 0 ? [] : [{ from: g, to: x, ...l("value", k(f.value, 0, 1e9)) }];\n }) : void 0, u = e.option !== void 0 ? Ce(e.option, 0, { count: m.maxEChartOptionNodes }) : void 0, d = u === void 0 || typeof u != "object" || u === null || Array.isArray(u) ? void 0 : u;\n return d === void 0 && n === void 0 && o === void 0 && (a === void 0 || a.length === 0) ? null : { type: "echart", ...l("title", p(e.title, m.maxString)), ...l("height", D(e.height, 100, 800)), ...l("preset", w(e.preset, ge)), ...l("data", n), ...l("series", o), ...l("links", a !== void 0 && a.length > 0 ? a : void 0), ...l("palette", Fe(e.palette)), ...l("option", d) };\n }\n default:\n return t;\n }\n }\n function Q(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= i) break;\n if (typeof s == "string") e.push(s.slice(0, r));\n else if (s !== null && typeof s == "object") {\n let n = s, o = typeof n.label == "string" ? n.label : typeof n.value == "string" ? n.value : typeof n.title == "string" ? n.title : JSON.stringify(s);\n e.push(o.slice(0, r));\n }\n }\n return e;\n }\n function Pn(t, i, r, e) {\n if (!Array.isArray(t)) return;\n let s = [];\n for (let n of t) {\n if (s.length >= i) break;\n if (typeof n == "string") {\n s.push(n.slice(0, m.maxString));\n continue;\n }\n let o = y(n);\n if (o !== void 0 && typeof o.type == "string") {\n if (r.remaining <= 0) break;\n r.remaining -= 1;\n let u = Je(o, r, e);\n u !== null && s.push(u);\n continue;\n }\n let a = o === void 0 ? void 0 : p(o.title, m.maxString);\n a !== void 0 && s.push({ title: a, ...l("desc", p(o?.desc, m.maxString)) });\n }\n return s;\n }\n function Te(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.label, 128), o = s === void 0 ? void 0 : k(s.value, -1e12, 1e12);\n n === void 0 || o === void 0 || r.push({ label: n, value: o, ...l("color", s === void 0 ? void 0 : E(s.color)) });\n }\n return r;\n }\n function Le(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= i) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.label, 128), a = n === void 0 ? void 0 : Te(n.data, r);\n o === void 0 || a === void 0 || e.push({ label: o, data: a, ...l("color", n === void 0 ? void 0 : E(n.color)) });\n }\n return e;\n }\n function vn(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= m.maxTabs) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.label, 128);\n if (o === void 0 || n === void 0) continue;\n let a = n.items !== void 0 ? n.items : n.content !== void 0 ? Array.isArray(n.content) ? n.content : [n.content] : void 0;\n e.push({ label: o, items: _(a, i, r + 1) });\n }\n return e;\n }\n function qn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.expr, 512);\n if (n === void 0 || s === void 0) continue;\n let o = [];\n if (Array.isArray(s.params)) for (let a of s.params) {\n if (o.length >= m.maxPlotParams) break;\n let u = y(a), d = u === void 0 ? void 0 : p(u.name, 64), c = u === void 0 ? void 0 : k(u.value, -1e9, 1e9);\n d === void 0 || c === void 0 || o.push({ name: d, value: c, ...l("min", u === void 0 ? void 0 : k(u.min, -1e9, 1e9)), ...l("max", u === void 0 ? void 0 : k(u.max, -1e9, 1e9)), ...l("step", u === void 0 ? void 0 : k(u.step, 1e-9, 1e9)), ...l("animateTo", u === void 0 ? void 0 : k(u.animateTo, -1e9, 1e9)), ...l("durationMs", u === void 0 ? void 0 : k(u.durationMs, 1, 12e4)), ...l("loop", u === void 0 ? void 0 : u.loop === true ? true : void 0) });\n }\n r.push({ expr: n, ...l("label", p(s.label, 128)), ...l("color", E(s.color)), ...l("kind", w(s.kind, oe)), ...l("params", o.length > 0 ? o : void 0) });\n }\n return r;\n }\n function zn(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxSteps) break;\n let e = y(r), s = e === void 0 ? void 0 : p(e.title, 256);\n s !== void 0 && i.push({ title: s, ...l("desc", e === void 0 ? void 0 : p(e.desc, m.maxString)) });\n }\n return i;\n }\n function Fn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.key, 256), o = s === void 0 ? void 0 : p(s.value, m.maxString);\n n === void 0 || o === void 0 || r.push({ key: n, value: o });\n }\n return r;\n }\n function jn(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= 24) break;\n let e = y(r), s = e === void 0 ? void 0 : p(e.path, 1024), n = e === void 0 ? void 0 : p(e.newText, 2e4);\n if (s === void 0 || n === void 0) continue;\n let o = e === void 0 ? void 0 : e.oldText;\n i.push({ path: s, newText: n, oldText: o === null || typeof o != "string" ? null : o.slice(0, 2e4) });\n }\n return i;\n }\n function Ln(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= m.maxAccordionItems) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.title, 256);\n o === void 0 || n === void 0 || e.push({ title: o, items: _(n.items, i, r + 1) });\n }\n return e;\n }\n function Vn(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxMeshes) break;\n let e = y(r), s = e === void 0 ? void 0 : w(e.shape, ue);\n if (s === void 0) continue;\n let n = e === void 0 ? void 0 : k(e.scale, -1e6, 1e6) ?? Z(e.scale), o = e === void 0 ? void 0 : k(e.size, -1e6, 1e6) ?? Z(e.size);\n i.push({ shape: s, ...l("color", e === void 0 ? void 0 : E(e.color)), ...l("position", e === void 0 ? void 0 : Z(e.position)), ...l("rotation", e === void 0 ? void 0 : Z(e.rotation)), ...l("scale", n), ...l("size", o) });\n }\n return i;\n }\n function Z(t) {\n if (!Array.isArray(t) || t.length !== 3) return;\n let [i, r, e] = t;\n if (!(typeof i != "number" || !Number.isFinite(i) || typeof r != "number" || !Number.isFinite(r) || typeof e != "number" || !Number.isFinite(e))) return [Math.min(1e6, Math.max(-1e6, i)), Math.min(1e6, Math.max(-1e6, r)), Math.min(1e6, Math.max(-1e6, e))];\n }\n function P(t, i, r) {\n return Math.min(r, Math.max(i, Math.round(t / 4) * 4));\n }\n function Kn(t) {\n if (!Array.isArray(t)) return;\n let i = [], r = /* @__PURE__ */ new Set();\n for (let e of t) {\n if (i.length >= m.maxDiagramNodes) break;\n let s = y(e);\n if (s === void 0) continue;\n let n = p(s.id, 128), o = p(s.label, m.maxString);\n if (n === void 0 || o === void 0 || r.has(n)) continue;\n r.add(n);\n let a = w(s.type, ce), u = s.x === void 0 ? void 0 : P(k(s.x, -1e6, 1e6) ?? 0, 0, 1e6), d = s.y === void 0 ? void 0 : P(k(s.y, -1e6, 1e6) ?? 0, 0, 1e6), c = s.w === void 0 ? void 0 : P(k(s.w, -1e6, 1e6) ?? 96, 40, 2e3), f = s.h === void 0 ? void 0 : P(k(s.h, -1e6, 1e6) ?? 48, 24, 1200);\n i.push({ id: n, label: o, ...l("sub", p(s.sub, 256)), ...l("type", a), ...l("x", u), ...l("y", d), ...l("w", c), ...l("h", f), ...l("tag", p(s.tag, 32)) });\n }\n return i;\n }\n function Hn(t) {\n if (t === void 0) return [];\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxDiagramEdges) break;\n let e = y(r);\n if (e === void 0) continue;\n let s = p(e.from, 128), n = p(e.to, 128);\n s === void 0 || n === void 0 || i.push({ from: s, to: n, ...l("label", p(e.label, m.maxDiagramLabel)), ...l("kind", w(e.kind, pe)), ...l("route", w(e.route, me)) });\n }\n return i;\n }\n function Jn(t) {\n let i = y(t);\n if (i === void 0) return;\n let r = {};\n for (let e of ["paper", "paper-2", "ink", "muted", "soft", "rule", "accent", "accent-tint", "link"]) {\n let s = E(i[e]);\n s !== void 0 && (r[e] = s);\n }\n return Object.keys(r).length === 0 ? void 0 : r;\n }\n function Un(t) {\n if (t === void 0) return [];\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxDiagramZones) break;\n let e = y(r);\n if (e === void 0) continue;\n let s = p(e.label, 64);\n s !== void 0 && i.push({ label: s, ...l("x", e.x === void 0 ? void 0 : P(k(e.x, -1e6, 1e6) ?? 0, 0, 1e6)), ...l("y", e.y === void 0 ? void 0 : P(k(e.y, -1e6, 1e6) ?? 0, 0, 1e6)), ...l("w", e.w === void 0 ? void 0 : P(k(e.w, -1e6, 1e6) ?? 100, 40, 2e3)), ...l("h", e.h === void 0 ? void 0 : P(k(e.h, -1e6, 1e6) ?? 100, 40, 1200)) });\n }\n return i;\n }\n function Bn(t) {\n let i = y(t);\n if (i === void 0) return null;\n let r = w(i.kind, de);\n if (r === void 0) return null;\n let e = Kn(i.nodes);\n if (e === void 0) return null;\n let s = Hn(i.edges);\n if (s === void 0) return null;\n let n = Un(i.zones);\n return n === void 0 ? null : { type: "diagram", kind: r, nodes: e, edges: s, ...l("zones", n.length > 0 ? n : void 0), ...l("variant", w(i.variant, fe)), ...l("title", p(i.title, 256)), ...l("theme", Jn(i.theme)) };\n }\n function Yn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.title, 256);\n n !== void 0 && r.push({ title: n, ...l("desc", s === void 0 ? void 0 : p(s.desc, m.maxString)), ...l("time", s === void 0 ? void 0 : p(s.time, 128)) });\n }\n return r;\n }\n function Qn(t, i) {\n return Ue(t, i, m.maxTreeDepth);\n }\n function Ue(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= i) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.name, 256);\n if (o === void 0) continue;\n let a = n !== void 0 && r > 0 && Array.isArray(n.children) ? Ue(n.children, i, r - 1) : void 0;\n e.push({ name: o, ...l("type", n === void 0 ? void 0 : w(n.type, le)), ...l("children", a) });\n }\n return e;\n }\n function Zn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let s of t) {\n if (r.length >= m.maxQuizOptions) break;\n let n = y(s), o = typeof s == "string" ? p(s, 512) : n === void 0 ? void 0 : p(n.label, 512);\n o !== void 0 && r.push({ label: o, ...l("correct", n === void 0 ? void 0 : n.correct === true ? true : void 0), ...l("feedback", n === void 0 ? void 0 : p(n.feedback, m.maxString)) });\n }\n if (r.length === 0) return;\n if (r.some((s) => s.correct === true)) return r;\n let e = typeof i == "number" && Number.isFinite(i) ? Math.trunc(i) : typeof i == "string" ? r.findIndex((s) => s.label === i.slice(0, 512)) : -1;\n return e < 0 || e >= r.length ? r : r.map((s, n) => n === e ? { ...s, correct: true } : s);\n }\n var Wn = /<(?:script|img|svg|iframe|video|audio|object|embed|source)\\b|on[a-z]+\\s*=|javascript:/i;\n function Ce(t, i, r) {\n if (r.count <= 0 || (r.count -= 1, i > m.maxEChartOptionDepth)) return;\n if (typeof t == "string") {\n let n = t.slice(0, m.maxString);\n return n.toLowerCase().includes("url(") || Wn.test(n) ? void 0 : n;\n }\n if (typeof t == "number" && Number.isFinite(t) || typeof t == "boolean") return t;\n if (t === null) return null;\n if (Array.isArray(t)) {\n let n = Math.min(t.length, m.maxEChartArrayLen), o = [];\n for (let a = 0; a < n; a++) {\n let u = Ce(t[a], i + 1, r);\n u !== void 0 && o.push(u);\n }\n return o.length > 0 || t.length === 0 ? o : void 0;\n }\n let e = y(t);\n if (e === void 0) return;\n let s = {};\n for (let [n, o] of Object.entries(e)) {\n let a = Ce(o, i + 1, r);\n a !== void 0 && (n === "tooltip" && typeof a == "object" && a !== null && !Array.isArray(a) && (a.renderMode = "richText"), s[n] = a);\n }\n return Object.keys(s).length > 0 || Object.keys(e).length === 0 ? s : void 0;\n }\n function Be(t) {\n let i = y(t);\n if (i === void 0) return null;\n if (N(t)) {\n let e = z(t);\n return e === null ? null : Be(e);\n }\n if (!Array.isArray(i.items)) return null;\n let r = { remaining: m.maxNodes };\n return { ...l("title", p(i.title, m.maxString)), ...l("gap", k(i.gap, 0, 96)), ...l("panel", i.panel === true ? true : void 0), ...l("append", i.append === true ? true : void 0), items: _(i.items, r, 0) };\n }\n function Xn(t, i = Number.POSITIVE_INFINITY) {\n let r = 0, e = (n) => {\n if (Array.isArray(n)) for (let o of n) {\n if (r >= i) return;\n r += 1;\n let a = y(o);\n if (a !== void 0) {\n if (a.type === "tabs" && Array.isArray(a.tabs)) for (let u of a.tabs) {\n if (r >= i) return;\n let d = y(u);\n d !== void 0 && e(d.items);\n }\n else if (a.type === "accordion" && Array.isArray(a.items)) for (let u of a.items) {\n if (r >= i) return;\n let d = y(u);\n d !== void 0 && e(d.items);\n }\n else if ((a.type === "row" || a.type === "col" || a.type === "grid" || a.type === "card") && Array.isArray(a.items)) e(a.items);\n else if (a.type !== "file-tree") {\n if (a.type === "list" && Array.isArray(a.items)) for (let u of a.items) {\n if (r >= i) return;\n let d = y(u);\n d !== void 0 && typeof d.type == "string" && e([d]);\n }\n else if (a.type === "table" && Array.isArray(a.details)) {\n let u = I(a).length;\n for (let d = 0; d < Math.min(a.details.length, u); d++) {\n if (r >= i) return;\n let c = a.details[d];\n Array.isArray(c) && C(a, d) && e(c);\n }\n }\n }\n }\n }\n }, s = y(t);\n return e(s === void 0 ? [] : s.items), r;\n }\n var et = q;\n function nt(t, i, r) {\n let e = 0, s = (d) => {\n let c = y(d);\n return c !== void 0 && typeof c.type == "string" && et.has(c.type);\n };\n function n(d, c) {\n if (Array.isArray(d)) {\n for (let f = 0; f < d.length; f++) if (o(d[f], `${c}[${f}]`), e >= i) return;\n }\n }\n function o(d, c) {\n if (e >= i || !s(d)) return;\n let f = y(d);\n if (f !== void 0) {\n if (e += 1, r(f, c), f.type === "tabs" && Array.isArray(f.tabs)) for (let g = 0; g < f.tabs.length; g++) a(f.tabs[g], `${c}.tabs[${g}]`);\n else if (f.type === "accordion" && Array.isArray(f.items)) for (let g = 0; g < f.items.length; g++) a(f.items[g], `${c}.items[${g}]`);\n else if ((f.type === "row" || f.type === "col" || f.type === "grid" || f.type === "card") && Array.isArray(f.items)) n(f.items, `${c}.items`);\n else if (f.type === "list" && Array.isArray(f.items)) for (let g = 0; g < f.items.length; g++) o(f.items[g], `${c}.items[${g}]`);\n else if (f.type === "table" && Array.isArray(f.details)) {\n let g = I(f).length;\n for (let x = 0; x < Math.min(f.details.length, g); x++) Array.isArray(f.details[x]) && C(f, x) && n(f.details[x], `${c}.details[${x}]`);\n }\n }\n }\n function a(d, c) {\n let f = y(d);\n if (f === void 0) return;\n let g = f.items !== void 0 ? f.items : f.content;\n Array.isArray(g) ? n(g, `${c}.items`) : o(g, `${c}.items`);\n }\n let u = y(t);\n return u === void 0 || (N(u) && s(t) ? o(t, "spec") : n(u.items, "items")), e;\n }\n function Ye(t, i = Number.POSITIVE_INFINITY) {\n return nt(t, i, () => {\n });\n }\n function tt(t, i = Number.POSITIVE_INFINITY) {\n return Ye(t, i);\n }\n function Qe(t) {\n let i = [], r = y(t);\n if (r === void 0) return { ok: false, errors: ["spec root must be an object"] };\n if (N(t)) {\n let a = z(t);\n return a !== null ? Qe(a) : { ok: false, errors: ["spec.items must be an array"] };\n }\n if (!Array.isArray(r.items)) return { ok: false, errors: ["spec.items must be an array"] };\n Ke(r, "spec", V, i, ["items"]);\n let e = 0, s = false, n = (a, u, d) => {\n if (!s) {\n if (!Array.isArray(a)) {\n i.push(`${d} must be an array`);\n return;\n }\n for (let c = 0; c < a.length; c++) {\n if (s || e >= m.maxNodes) {\n s || (i.push(`spec exceeds ${m.maxNodes} nodes; tail elided`), s = true);\n return;\n }\n e += 1;\n let f = `${d}[${c}]`;\n Xe(a[c], u, f, i, n);\n }\n }\n };\n n(r.items, 0, "items"), i.length === 0 && i.push(...Re(r).diagnostics);\n let o = [...new Set(i)];\n return { ok: o.length === 0, errors: o };\n }\n function Ze(t) {\n let i = Ie(t), r = Be(i.value), e = Qe(i.value), s = Ye(i.value, m.maxNodes + 1), n = r === null ? 0 : tt(r), o = r === null ? 0 : Xn(r), a = e.errors.filter((u) => !u.includes(": unknown type "));\n return r !== null && a.length === 0 && a.push(...Re(r).diagnostics), s > n && a.push(`repair dropped ${s - n} declared native node(s): declared ${s}, rendered ${n}`), { value: i.value, normalized: i.value, repaired: r, spec: r, errors: [...new Set(a)], warnings: [...i.warnings, ...Pe(i.value)], declaredCount: s, renderedCount: o, declaredNativeCount: s, renderedNativeCount: n, renderedTotalCount: o };\n }\n function it(t) {\n return t.errors.length > 0 && t.errors.every((i) => i.startsWith("spec exceeds ") || i.startsWith("repair dropped ")) && t.renderedNativeCount === m.maxNodes && t.declaredNativeCount === m.maxNodes + 1;\n }\n function Ne(t) {\n return t.spec !== null && (t.errors.length === 0 || it(t));\n }\n var rt = /^(items\\[\\d+\\](?:\\.(?:items\\[\\d+\\]|tabs\\[\\d+\\]\\.items\\[\\d+\\]|details\\[\\d+\\](?:\\[\\d+\\])?))*)/;\n function st(t) {\n let i = rt.exec(t);\n return i === null ? null : i[1] ?? null;\n }\n function Ve(t, i) {\n let r = [...i.matchAll(/(?:^|\\.)(items|tabs|details)\\[(\\d+)\\]|\\[(\\d+)\\]/g)];\n if (r.length === 0 || r[r.length - 1][1] === "tabs") return;\n let e = t;\n for (let s = 0; s < r.length; s++) {\n let n = r[s], o = n[1] === void 0 ? e : y(e)?.[n[1]], a = Number(n[2] ?? n[3]);\n if (!Array.isArray(o) || a >= o.length) return;\n if (s === r.length - 1) return { array: o, index: a, preserveIndex: n[1] === "details" };\n if (e = o[a], e === void 0) return;\n }\n }\n function ot(t) {\n try {\n return y(JSON.parse(JSON.stringify(t))) ?? null;\n } catch {\n return null;\n }\n }\n function at(t) {\n if (Ne(t)) return t.spec;\n if (t.spec === null) return null;\n let i = y(t.value);\n if (i === void 0) return null;\n let r = /* @__PURE__ */ new Set(), e = /* @__PURE__ */ new Set();\n for (let d of t.errors) {\n if (d.startsWith("spec exceeds ")) continue;\n let c = st(d);\n c !== null && (d === `${c}.details must not contain more entries than rows` ? e.add(c) : r.add(c));\n }\n if (r.size === 0 && e.size === 0) return null;\n let s = ot(N(i) ? z(i) : i);\n if (s === null) return null;\n let n = [...r].map((d) => Ve(s, d)).filter((d) => d !== void 0), o = [...e].map((d) => Ve(s, d)).filter((d) => d !== void 0);\n for (let { array: d, index: c } of o) {\n let f = y(d[c]);\n f?.type === "table" && Array.isArray(f.details) && (f.details.length = Math.min(f.details.length, I(f).length));\n }\n let a = /* @__PURE__ */ new Map();\n for (let { array: d, index: c, preserveIndex: f } of n) {\n if (f) {\n d[c] = null;\n continue;\n }\n let g = a.get(d);\n g === void 0 ? a.set(d, [c]) : g.push(c);\n }\n for (let [d, c] of a) {\n c.sort((f, g) => g - f);\n for (let f of c) d.splice(f, 1);\n }\n let u = Ze(s);\n return !Ne(u) || u.renderedNativeCount === 0 ? null : u.spec;\n }\n function We(t, i, r) {\n if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {\n let s = y(t[e]), n = `${i}[${e}]`;\n if (s === void 0) {\n r.push(`${n} must be an object`);\n continue;\n }\n typeof s.label != "string" && r.push(`${n}.label must be a string`), (typeof s.value != "number" || !Number.isFinite(s.value)) && r.push(`${n}.value must be a finite number`), s.color !== void 0 && typeof s.color != "string" && r.push(`${n}.color must be a string`);\n }\n }\n function ut(t, i, r) {\n if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {\n let s = y(t[e]), n = `${i}[${e}]`;\n if (s === void 0) {\n r.push(`${n} must be an object`);\n continue;\n }\n typeof s.label != "string" && r.push(`${n}.label must be a string`), s.color !== void 0 && typeof s.color != "string" && r.push(`${n}.color must be a string`), Array.isArray(s.data) || r.push(`${n}.data must be an array`), We(s.data, `${n}.data`, r);\n }\n }\n function lt(t, i, r) {\n !Array.isArray(t.data) && !Array.isArray(t.series) && r.push(`${i}: type \'chart\' requires data or series (array)`), t.variant !== void 0 && r.push(`${i}.variant is unsupported; use kind`), t.data !== void 0 && !Array.isArray(t.data) && r.push(`${i}.data must be an array`), t.series !== void 0 && !Array.isArray(t.series) && r.push(`${i}.series must be an array`), t.kind !== void 0 && (typeof t.kind != "string" || !U.includes(t.kind)) && r.push(`${i}.kind must be bars, line, or donut`);\n let e = t.kind === void 0 ? "bars" : t.kind, s = Array.isArray(t.series) ? t.series : void 0;\n if (Array.isArray(t.data) && t.data.length === 0 && (s === void 0 || s.length === 0) && r.push(`${i}.data must not be empty`), s !== void 0) {\n s.length === 0 && r.push(`${i}.series must not be empty`), e === "donut" && r.push(`${i}.series is only supported for bars and line`);\n for (let n = 0; n < s.length; n++) {\n let o = y(s[n]);\n o !== void 0 && Array.isArray(o.data) && o.data.length === 0 && r.push(`${i}.series[${n}].data must not be empty`);\n }\n }\n e === "donut" && t.data === void 0 && r.push(`${i}.data is required for donut`), e === "line" && t.data === void 0 && (s === void 0 || s.length === 0) && r.push(`${i}.data is required for line (or provide series)`), We(t.data, `${i}.data`, r), ut(t.series, `${i}.series`, r);\n }\n function dt(t, i, r) {\n if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {\n let s = t[e];\n if (y(s) === void 0) {\n if (!Array.isArray(s)) {\n r.push(`${i}[${e}] must be an array or object`);\n continue;\n }\n for (let n = 0; n < s.length; n++) {\n let o = s[n];\n typeof o != "string" && (typeof o != "number" || !Number.isFinite(o)) && r.push(`${i}[${e}][${n}] must be a string or finite number`);\n }\n }\n }\n }\n function Xe(t, i, r, e, s) {\n if (i > m.maxDepth) {\n e.push(`${r}: exceeds max depth ${m.maxDepth}`);\n return;\n }\n let n = y(t);\n if (n === void 0) {\n e.push(`${r}: must be an object`);\n return;\n }\n let o = n.type;\n if (typeof o != "string") {\n e.push(`${r}: missing string \'type\'`);\n return;\n }\n let a = (c) => {\n n[c] !== void 0 && typeof n[c] != "string" && e.push(`${r}: \'${c}\' must be a string`);\n }, u = (c) => {\n n[c] !== void 0 && (typeof n[c] != "number" || !Number.isFinite(n[c])) && e.push(`${r}: \'${c}\' must be a finite number`);\n };\n switch (o) {\n case "text":\n typeof n.content != "string" && typeof n.text != "string" && e.push(`${r}: type \'text\' requires content or text (string)`), a("content"), a("text");\n break;\n case "row":\n case "col":\n case "card":\n case "grid":\n Array.isArray(n.items) || e.push(`${r}: type \'${o}\' requires items (array)`), s(n.items, i + 1, `${r}.items`), o === "grid" && u("cols");\n break;\n case "button":\n case "checkbox":\n case "link":\n case "switch":\n typeof n.label != "string" && e.push(`${r}: type \'${o}\' requires label (string)`), a("label");\n break;\n case "image":\n case "audio":\n case "video":\n typeof n.src != "string" && e.push(`${r}: type \'${o}\' requires src (string)`), a("src"), a("alt"), o === "video" && a("poster");\n break;\n case "slider":\n a("label"), u("min"), u("max"), u("step"), u("value");\n break;\n case "input":\n case "textarea":\n a("label"), a("placeholder"), a("value");\n break;\n case "select":\n case "radio":\n Array.isArray(n.options) || e.push(`${r}: type \'${o}\' requires options (array)`);\n break;\n case "submit":\n typeof n.label != "string" && e.push(`${r}: type \'submit\' requires label (string)`);\n break;\n case "badge":\n typeof n.label != "string" && typeof n.text != "string" && typeof n.value != "string" && e.push(`${r}: type \'badge\' requires label, text, or value (string)`), a("label"), a("text"), a("value");\n break;\n case "hero":\n typeof n.title != "string" && e.push(`${r}: type \'hero\' requires title (string)`), a("subtitle");\n break;\n case "stat":\n typeof n.label != "string" && e.push(`${r}: type \'stat\' requires label (string)`), typeof n.value != "string" && e.push(`${r}: type \'stat\' requires value (string)`), a("delta");\n break;\n case "progress":\n (typeof n.value != "number" || !Number.isFinite(n.value) || n.value < 0 || n.value > 100) && e.push(`${r}: type \'progress\' requires value (number 0..100)`), u("value");\n break;\n case "avatar":\n typeof n.name != "string" && e.push(`${r}: type \'avatar\' requires name (string)`);\n break;\n case "list":\n if (Array.isArray(n.items) || e.push(`${r}: type \'list\' requires items (array)`), Array.isArray(n.items)) for (let c = 0; c < n.items.length; c++) {\n let f = y(n.items[c]);\n f !== void 0 && typeof f.type == "string" && Xe(f, i + 1, `${r}.items[${c}]`, e, s);\n }\n break;\n case "table":\n if (!Array.isArray(n.columns) && !He(n) && e.push(`${r}: type \'table\' requires columns (array)`), Array.isArray(n.rows) || e.push(`${r}: type \'table\' requires rows (array)`), n.types !== void 0 && !Array.isArray(n.types) && e.push(`${r}.types must be an array of column cell types`), n.details !== void 0 && !Array.isArray(n.details) && e.push(`${r}.details must be an array aligned with rows`), Array.isArray(n.details)) {\n let c = { columns: n.columns, rows: n.rows, types: n.types }, f = I(c).length;\n n.details.length > f && e.push(`${r}.details must not contain more entries than rows`);\n for (let g = 0; g < Math.min(n.details.length, f); g++) {\n let x = n.details[g];\n if (!(x === null || !C(c, g))) {\n if (!Array.isArray(x)) {\n e.push(`${r}.details[${g}] must be an array or null`);\n continue;\n }\n s(x, i + 1, `${r}.details[${g}]`);\n }\n }\n }\n dt(n.rows, `${r}.rows`, e);\n break;\n case "chart":\n lt(n, r, e);\n break;\n case "tabs": {\n if (Array.isArray(n.tabs) || e.push(`${r}: type \'tabs\' requires tabs (array)`), Array.isArray(n.tabs)) for (let c = 0; c < n.tabs.length; c++) {\n let f = y(n.tabs[c]);\n if (f === void 0) {\n e.push(`${r}.tabs[${c}] must be an object`);\n continue;\n }\n typeof f.label != "string" && e.push(`${r}.tabs[${c}].label must be a string`), s(f.items, i + 1, `${r}.tabs[${c}].items`);\n }\n break;\n }\n case "plot":\n Array.isArray(n.series) || e.push(`${r}: type \'plot\' requires series (array)`);\n break;\n case "callout":\n typeof n.content != "string" && e.push(`${r}: type \'callout\' requires content (string)`);\n break;\n case "steps":\n Array.isArray(n.steps) || e.push(`${r}: type \'steps\' requires steps (array)`);\n break;\n case "keyvalue":\n Array.isArray(n.pairs) || e.push(`${r}: type \'keyvalue\' requires pairs (array)`);\n break;\n case "diff":\n Array.isArray(n.diffs) || e.push(`${r}: type \'diff\' requires diffs (array)`);\n break;\n case "json":\n "value" in n || e.push(`${r}: type \'json\' requires value`);\n break;\n case "code":\n typeof n.code != "string" && e.push(`${r}: type \'code\' requires code (string)`);\n break;\n case "accordion":\n if (Array.isArray(n.items) || e.push(`${r}: type \'accordion\' requires items (array)`), Array.isArray(n.items)) for (let c = 0; c < n.items.length; c++) {\n let f = y(n.items[c]);\n if (f === void 0) {\n e.push(`${r}.items[${c}] must be an object`);\n continue;\n }\n typeof f.title != "string" && e.push(`${r}.items[${c}].title must be a string`), s(f.items, i + 1, `${r}.items[${c}].items`);\n }\n break;\n case "copy":\n typeof n.text != "string" && e.push(`${r}: type \'copy\' requires text (string)`);\n break;\n case "svg":\n typeof n.code != "string" && e.push(`${r}: type \'svg\' requires code (string)`), u("height");\n break;\n case "mermaid":\n typeof n.code != "string" && e.push(`${r}: type \'mermaid\' requires code (string)`);\n break;\n case "scene3d":\n Array.isArray(n.meshes) || e.push(`${r}: type \'scene3d\' requires meshes (array)`);\n break;\n case "timeline":\n Array.isArray(n.items) || e.push(`${r}: type \'timeline\' requires items (array)`);\n break;\n case "file-tree":\n Array.isArray(n.items) || e.push(`${r}: type \'file-tree\' requires items (array)`);\n break;\n case "breadcrumb":\n Array.isArray(n.items) || e.push(`${r}: type \'breadcrumb\' requires items (array)`);\n break;\n case "quiz":\n typeof n.question != "string" && e.push(`${r}: type \'quiz\' requires question (string)`), Array.isArray(n.options) || e.push(`${r}: type \'quiz\' requires options (array)`);\n break;\n case "diagram":\n typeof n.kind != "string" && e.push(`${r}: type \'diagram\' requires kind (string)`), Array.isArray(n.nodes) || e.push(`${r}: type \'diagram\' requires nodes (array)`), n.edges !== void 0 && !Array.isArray(n.edges) && e.push(`${r}: type \'diagram\' requires edges (array) when present`);\n break;\n case "echart":\n n.option === void 0 && n.data === void 0 && n.series === void 0 && (!Array.isArray(n.links) || n.links.length === 0) && e.push(`${r}: type \'echart\' requires option, data, series, or links`), u("height");\n break;\n default:\n e.push(`${r}: unknown type \'${o}\' (custom renderer?)`);\n }\n let d = T[o];\n d !== void 0 && In(n, r, d, e);\n }\n\n // lib/normalize-visual.js\n function normalizeVisual(value, schemas) {\n const unwrap = (v2) => v2 && typeof v2 === "object" && !Array.isArray(v2) && Object.keys(v2).length === 1 && Array.isArray(v2.item) ? v2.item : v2;\n const scalar2 = (v2, kind) => kind === "number" && typeof v2 === "string" && v2.trim() !== "" && Number.isFinite(Number(v2)) ? Number(v2) : kind === "boolean" && (v2 === "true" || v2 === "false") ? v2 === "true" : v2;\n function record(input, schema, depth = 0) {\n if (!input || typeof input !== "object" || Array.isArray(input) || depth > 32) return input;\n const out2 = { ...input };\n for (const [key, v2] of Object.entries(input)) {\n const target = schema.aliases?.[key] ?? key, kind = schema.fields?.[target];\n if (kind === "array" || kind === "nodes") {\n let array2 = unwrap(v2);\n if (Array.isArray(array2)) array2 = array2.map((x) => kind === "nodes" ? node2(x, depth + 1) : schema.nested?.[target] ? record(x, schema.nested[target], depth + 1) : x);\n out2[key] = array2;\n } else out2[key] = scalar2(v2, kind);\n }\n return out2;\n }\n function node2(v2, depth) {\n if (!v2 || typeof v2 !== "object" || Array.isArray(v2)) return v2;\n if (v2.type === "heading") {\n v2 = { ...v2, type: "text", content: v2.content ?? v2.text ?? v2.title, size: v2.size ?? "h3" };\n delete v2.text;\n delete v2.title;\n }\n if (["card", "row", "col", "grid"].includes(v2.type) && v2.items === void 0 && Array.isArray(unwrap(v2.children))) {\n v2 = { ...v2, items: unwrap(v2.children) };\n delete v2.children;\n }\n const out2 = record(v2, schemas[v2.type] ?? {}, depth);\n if (v2.type === "quiz" && Array.isArray(out2.options)) out2.options = out2.options.map((x) => record(x, { fields: { correct: "boolean" } }));\n if (v2.type === "table") {\n for (const key of ["rows", "data", "items", "details"]) if (Array.isArray(out2[key])) out2[key] = out2[key].map((row) => {\n row = unwrap(row);\n return key === "details" && Array.isArray(row) ? row.map((x) => node2(x, depth + 1)) : row;\n });\n }\n if (v2.type === "echart") {\n for (const key of ["data", "series", "links"]) if (Array.isArray(out2[key])) out2[key] = out2[key].map((x) => record(x, { fields: { value: "number", data: "array" }, nested: { data: { fields: { value: "number" } } } }));\n }\n return out2;\n }\n if (Array.isArray(value)) return { items: value.map((x) => node2(x, 0)) };\n if (!value || typeof value !== "object") return value;\n const out = { ...value }, items = unwrap(value.items);\n if (Array.isArray(items)) out.items = items.map((x) => node2(x, 0));\n return out;\n }\n\n // lib/visual.js\n var VISUAL_TYPES = Object.freeze([...q]);\n function validateVisual(value) {\n const encoded = JSON.stringify(value);\n if (!encoded || new TextEncoder().encode(encoded).length > 131072) throw Error("DSH UI: visual spec exceeds 128 KiB");\n const processed = Ze(normalizeVisual(value, T)), spec = Ne(processed) ? processed.spec : at(processed);\n if (!spec || !processed.renderedNativeCount) throw Error("DSH UI: visual spec: " + (processed.errors.slice(0, 4).join("; ") || "requires registered components"));\n const critical = /* @__PURE__ */ new Set(["quiz", "radio", "submit", "input", "textarea", "select", "slider", "checkbox", "switch"]);\n const inventory = (items, path = "items", result = []) => {\n for (const [n, v2] of (Array.isArray(items) ? items : []).entries()) {\n if (!v2 || typeof v2 !== "object") continue;\n const at2 = path + "[" + n + "]";\n if (critical.has(v2.type)) result.push({ type: v2.type, id: v2.id ?? v2.group ?? v2.question ?? v2.label, path: at2 });\n if (["row", "col", "grid", "card"].includes(v2.type)) inventory(v2.items, at2 + ".items", result);\n if (v2.type === "tabs") for (const [i, t] of (v2.tabs ?? []).entries()) inventory(t.items, at2 + ".tabs[" + i + "].items", result);\n if (v2.type === "accordion") for (const [i, t] of (v2.items ?? []).entries()) inventory(t.items, at2 + ".items[" + i + "].items", result);\n }\n return result;\n };\n const source = normalizeVisual(value, T), before = inventory(source.items), after = inventory(spec.items);\n const available = [...after], missing = before.filter((v2) => {\n const i = available.findIndex((n) => n.type === v2.type && n.id === v2.id);\n if (i < 0) return true;\n available.splice(i, 1);\n return false;\n });\n if (missing.length) throw Error("DSH UI: critical component was rejected at " + missing.map((v2) => v2.path + " (" + v2.type + ")").join(", ") + ". " + processed.errors.slice(0, 4).join("; "));\n const stableIds = /* @__PURE__ */ new Set();\n function walk(items) {\n for (const n of items) {\n if (n.id !== void 0) {\n if (stableIds.has(n.id)) throw Error("DSH UI: duplicate extended component id " + n.id);\n stableIds.add(n.id);\n }\n if (!VISUAL_TYPES.includes(n.type)) throw Error("DSH UI: unsupported visual component " + n.type);\n if (n.type === "input" && n.inputType === "password") throw Error("DSH UI: do not collect passwords or secrets in a UI");\n if (n.type !== "file-tree" && Array.isArray(n.items)) walk(n.items.filter((x) => x && typeof x === "object" && "type" in x));\n for (const t of n.tabs ?? []) walk(t.items ?? []);\n if (n.type === "table") {\n for (const d of n.details ?? []) if (d) walk(d);\n }\n }\n }\n walk(spec.items);\n delete spec.panel;\n delete spec.append;\n return { spec, warnings: processed.errors.slice(0, 12), count: processed.renderedNativeCount };\n }\n function visualDocument(value) {\n if (Array.isArray(value)) value = { items: value };\n const { spec, warnings } = validateVisual(value), title = spec.title || "\\u53EF\\u89C6\\u5316";\n const texts = [];\n function gather(v2) {\n if (!v2 || typeof v2 !== "object") return;\n for (const [k2, x] of Object.entries(v2)) {\n if (["title", "content", "label", "question", "explanation", "alt"].includes(k2) && typeof x === "string") texts.push(x);\n else if (x && typeof x === "object") Array.isArray(x) ? x.forEach(gather) : gather(x);\n }\n }\n gather(spec);\n return { version: 1, title, fallback: texts.join("\\n").slice(0, 8192) || title, nodes: [{ id: "visual", type: "visual", spec, warnings }] };\n }\n\n // lib/normalize-authoring.js\n var object = (v2) => v2 !== null && typeof v2 === "object" && !Array.isArray(v2);\n var own = (v2, k2) => Object.hasOwn(v2, k2);\n var singleItem = (v2) => object(v2) && Object.keys(v2).length === 1 && own(v2, "item");\n var array = (v2) => {\n let candidate = v2;\n for (let i = 0; i < 8 && singleItem(candidate); i++) candidate = candidate.item;\n return Array.isArray(candidate) ? candidate : v2;\n };\n var numericOps = /* @__PURE__ */ new Set(["add", "sub", "mul", "div", "min", "max", "round", "ceil", "floor", "abs", "lt", "lte", "gt", "gte"]);\n function number(v2) {\n if (typeof v2 !== "string" || !/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:e[+-]?\\d+)?$/i.test(v2.trim())) return v2;\n const n = Number(v2);\n return Number.isFinite(n) && (!Number.isInteger(n) || Number.isSafeInteger(n)) ? n : v2;\n }\n var boolean = (v2) => v2 === "true" ? true : v2 === "false" ? false : v2;\n function expression(e, numeric = false, logical = false) {\n if (!object(e)) return e;\n if (Object.keys(e).length === 1 && own(e, "expr") && typeof e.expr === "number" && Number.isFinite(e.expr)) {\n e.const = e.expr;\n delete e.expr;\n }\n if (own(e, "const")) {\n if (numeric) e.const = number(e.const);\n if (logical) e.const = boolean(e.const);\n }\n if (own(e, "args")) e.args = array(e.args);\n if (Array.isArray(e.args)) e.args.forEach((arg, i) => expression(arg, numericOps.has(e.op) || e.op === "if" && i > 0 && numeric, e.op === "if" && i === 0));\n if (object(e.map?.fields)) Object.values(e.map.fields).forEach((e2) => expression(e2));\n return e;\n }\n function normalizeAuthoring(doc2) {\n if (Array.isArray(doc2)) doc2 = visualDocument(doc2);\n if (object(doc2) && !own(doc2, "nodes") && (own(doc2, "items") || typeof doc2.type === "string")) doc2 = visualDocument(doc2);\n if (!object(doc2)) return doc2;\n if (own(doc2, "version")) doc2.version = number(doc2.version);\n if (object(doc2.presentation) && doc2.presentation.layout === "flow" && (!own(doc2.presentation, "preset") || doc2.presentation.preset === "flow")) {\n doc2.presentation.layout = "guide";\n doc2.presentation.preset = "flow";\n }\n if (object(doc2.state)) for (const k2 of Object.keys(doc2.state)) {\n let s = doc2.state[k2];\n if (typeof s === "string" && s.trim().startsWith("{")) {\n try {\n const parsed = JSON.parse(s);\n if (object(parsed)) s = parsed;\n } catch {\n }\n }\n if (singleItem(s) && object(s.item)) s = s.item;\n doc2.state[k2] = s;\n if (!object(s)) continue;\n if (own(s, "options")) s.options = array(s.options);\n if (s.type === "number") {\n for (const field of ["default", "min", "max", "step"]) if (own(s, field)) s[field] = number(s[field]);\n if (Array.isArray(s.options)) s.options = s.options.map(number);\n } else if (s.type === "boolean") {\n if (own(s, "default")) s.default = boolean(s.default);\n if (Array.isArray(s.options)) s.options = s.options.map(boolean);\n }\n }\n if (object(doc2.derived)) Object.values(doc2.derived).forEach((e) => expression(e));\n if (object(doc2.actions)) {\n for (const action of Object.values(doc2.actions)) if (object(action) && own(action, "stateKeys")) action.stateKeys = array(action.stateKeys);\n }\n function nodes(list) {\n list = array(list);\n if (!Array.isArray(list)) return list;\n for (const node2 of list) {\n if (!object(node2)) continue;\n if (node2.type === "code" && (node2.copyable === true || node2.copyable === "true")) delete node2.copyable;\n if (["slider", "input"].includes(node2.type) && typeof node2.bind === "string" && node2.bind.startsWith("state.")) {\n const spec = doc2.state?.[node2.bind.slice(6)];\n if (spec?.type === "number") {\n for (const field of ["min", "max", "step"]) if (own(node2, field) && number(node2[field]) === spec[field]) delete node2[field];\n }\n }\n if (["text", "heading", "callout"].includes(node2.type) && own(node2, "content")) {\n if (!own(node2, "text")) {\n node2.text = node2.content;\n delete node2.content;\n } else if (node2.text === node2.content) delete node2.content;\n }\n if (["text", "heading", "callout"].includes(node2.type) && typeof node2.text === "string") {\n const spans = array(node2.spans);\n if (Array.isArray(spans) && spans.every((s) => object(s) && typeof s.text === "string") && spans.map((s) => s.text).join("") === node2.text) delete node2.text;\n }\n if (node2.type === "table" && own(node2, "types")) {\n const columns = array(node2.columns), rows = array(node2.rows), types = array(node2.types);\n const allowed = ["id", "type", "label", "columns", "rows", "types"];\n if (Object.keys(node2).every((k2) => allowed.includes(k2)) && Array.isArray(columns) && columns.length && columns.every((c) => object(c) && typeof c.key === "string" && typeof c.label === "string" && Object.keys(c).every((k2) => ["key", "label", "unit"].includes(k2))) && new Set(columns.map((c) => c.key)).size === columns.length && Array.isArray(rows) && rows.every(object) && Array.isArray(types) && types.length === columns.length && types.every((t) => ["text", "num", "delta", "bar", "badge"].includes(t))) {\n const spec = { ...node2.label ? { title: node2.label } : {}, items: [{ type: "table", columns: columns.map((c) => c.label + (c.unit ? ` (${c.unit})` : "")), rows: rows.map((row) => columns.map((c) => row[c.key] ?? null)), types }] }, id = node2.id;\n for (const k2 of Object.keys(node2)) delete node2[k2];\n Object.assign(node2, { ...id !== void 0 ? { id } : {}, type: "visual", spec });\n }\n }\n if (typeof node2.id === "string" && VISUAL_TYPES.includes(node2.type) && !own(COMPONENTS, node2.type)) {\n const spec = { items: [{ ...node2 }] }, id = node2.id;\n for (const k2 of Object.keys(node2)) delete node2[k2];\n Object.assign(node2, { id, type: "visual", spec });\n }\n if (node2.type === "table" && Array.isArray(node2.columns) && node2.columns.length && node2.columns.every((c) => object(c) && typeof c.key === "string") && new Set(node2.columns.map((c) => c.key)).size === node2.columns.length && Array.isArray(node2.rows) && node2.rows.every((row) => Array.isArray(row) && row.length === node2.columns.length)) {\n node2.rows = node2.rows.map((row) => Object.fromEntries(node2.columns.map((c, i) => [c.key, row[i]])));\n }\n if (node2.type === "table" && Array.isArray(node2.columns) && node2.columns.length && Array.isArray(node2.rows) && node2.rows.every(Array.isArray) && node2.columns.every((c) => object(c) && Number.isInteger(c.key) && c.key >= 0) && new Set(node2.columns.map((c) => c.key)).size === node2.columns.length) {\n const columns = node2.columns.map((c) => ({ ...c, key: "col_" + c.key }));\n node2.rows = node2.rows.map((row) => Object.fromEntries(node2.columns.map((c) => ["col_" + c.key, row[c.key] ?? null])));\n node2.columns = columns;\n }\n if (node2.type === "visual" && typeof node2.id === "string") {\n node2.stateKey ??= "visual_" + node2.id;\n doc2.state ??= {};\n if (!own(doc2.state, node2.stateKey)) doc2.state[node2.stateKey] = { type: "json", default: {} };\n }\n if (node2.type === "sandbox") {\n if (!own(node2, "title")) node2.title = doc2.title;\n if (!own(node2, "fallback")) node2.fallback = doc2.fallback;\n }\n for (const field of ["children", "items", "columns", "libraries", "stateKeys", "dataKeys", "derivedKeys"]) if (own(node2, field)) node2[field] = array(node2[field]);\n if (["table", "chart"].includes(node2.type) && own(node2, "rows")) node2.rows = array(node2.rows);\n for (const field of ["decimals", "height"]) if (own(node2, field)) node2[field] = number(node2[field]);\n if (["row", "column"].includes(node2.type)) {\n if (own(node2, "gap")) node2.gap = number(node2.gap);\n if (node2.type === "row" && own(node2, "columns")) node2.columns = number(node2.columns);\n }\n if (["text", "heading", "callout"].includes(node2.type)) {\n for (const field of ["size", "weight", "lineHeight"]) if (own(node2, field)) node2[field] = number(node2[field]);\n if (own(node2, "spans")) node2.spans = array(node2.spans);\n if (Array.isArray(node2.spans)) {\n for (const span of node2.spans) if (object(span)) {\n for (const field of ["size", "weight", "lineHeight"]) if (own(span, field)) span[field] = number(span[field]);\n }\n }\n }\n if (node2.type === "details" && own(node2, "open")) node2.open = boolean(node2.open);\n if (node2.type === "text" && own(node2, "copyable")) node2.copyable = boolean(node2.copyable);\n if (node2.type === "code" && own(node2, "wrap")) node2.wrap = boolean(node2.wrap);\n if (["table", "chart"].includes(node2.type) && Array.isArray(node2.rows)) {\n for (const row of node2.rows) if (object(row)) for (const cell of Object.values(row)) expression(cell);\n }\n for (const field of ["text", "value", "max", "rows"]) if (own(node2, field)) expression(node2[field], node2.type === "progress");\n if (["row", "column", "card", "details"].includes(node2.type) && own(node2, "children")) node2.children = nodes(node2.children);\n }\n return list;\n }\n if (own(doc2, "nodes")) doc2.nodes = nodes(doc2.nodes);\n return doc2;\n }\n\n // lib/typography.js\n var TEXT_PRESETS = Object.freeze(["reading", "brief", "comparison", "list", "callout", "scorecard", "flow", "minimal"]);\n var TYPE_FIELDS = Object.freeze(["size", "weight", "color", "align", "lineHeight"]);\n var TEXT_SIZES = Object.freeze({ sm: 14, md: 16, lg: 20, xl: 26, hero: 36 });\n var TEXT_COLORS = Object.freeze({ default: "var(--du-ink)", muted: "var(--du-muted)", accent: "var(--du-accent)", success: "var(--du-green)", warning: "var(--du-amber)", danger: "var(--du-red)", violet: "var(--du-violet)" });\n function validateTypography(value, at2 = "text") {\n const fail2 = (message) => {\n throw Error(`DSH UI: ${at2}.${message}`);\n };\n if (value.size !== void 0 && !(typeof value.size === "number" && Number.isFinite(value.size) && value.size >= 12 && value.size <= 48) && !Object.hasOwn(TEXT_SIZES, value.size)) fail2("size must be 12..48 px or sm/md/lg/xl/hero");\n if (value.weight !== void 0 && ![400, 500, 600, 700, 800].includes(value.weight)) fail2("weight must be 400/500/600/700/800");\n if (value.color !== void 0 && (typeof value.color !== "string" || !Object.hasOwn(TEXT_COLORS, value.color) && !/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test(value.color))) fail2("color must be default/muted/accent/success/warning/danger/violet or #RGB/#RRGGBB");\n if (value.align !== void 0 && !["left", "center", "right"].includes(value.align)) fail2("align must be left/center/right");\n if (value.lineHeight !== void 0 && !(typeof value.lineHeight === "number" && value.lineHeight >= 1.2 && value.lineHeight <= 2.4)) fail2("lineHeight must be 1.2..2.4");\n }\n\n // lib/links.js\n function validateLink(node2) {\n const fail2 = (message) => {\n throw Error("DSH UI: " + message);\n };\n if ([node2.href, node2.path, node2.action].filter((v2) => v2 !== void 0).length !== 1) fail2(`node.${node2.id}: choose exactly one href (http/https), path (file), or action (Agent follow-up)`);\n if (node2.variant !== void 0 && !["primary", "secondary", "text"].includes(node2.variant)) fail2("link/button variant must be primary/secondary/text");\n if (node2.href !== void 0) {\n if (typeof node2.href !== "string" || node2.href.length > 8192 || /[\\u0000-\\u0020\\u007f]/.test(node2.href) || !/^https?:\\/\\//i.test(node2.href)) fail2("href must be an absolute http/https URL; encode spaces");\n let url;\n try {\n url = new URL(node2.href);\n } catch {\n fail2("invalid href URL");\n }\n if (!url.hostname || url.username || url.password) fail2("href must have a host and must not contain credentials");\n }\n if (node2.path !== void 0) {\n if (typeof node2.path !== "string" || !node2.path.trim() || node2.path.length > 8192 || /[\\u0000-\\u001f\\u007f]/.test(node2.path) || /^\\s*(?:[a-z][a-z\\d+.-]*:|[\\\\/]{2})/i.test(node2.path) && !/^\\s*[a-z]:[\\\\/]/i.test(node2.path)) fail2("path must be a local file path, not a URL, network path or command");\n }\n }\n\n // lib/protocol.js\n var LIMITS = Object.freeze({ bytes: 131072, nodes: 160, depth: 12, rows: 500, expressions: 128, steps: 4096 });\n var own2 = (o, k2) => Object.hasOwn(o, k2);\n var fail = (message) => {\n throw new Error(`DSH UI: ${message}`);\n };\n var object2 = (x) => x !== null && typeof x === "object" && !Array.isArray(x);\n var finite = (x) => typeof x === "number" && Number.isFinite(x);\n var scalar = (x) => typeof x === "string" || typeof x === "boolean" || finite(x);\n var text = (x, at2) => {\n if (typeof x !== "string" || x.length > 8192) fail(`${at2} must be a string of at most 8192 characters`);\n };\n function fields(value, allowed, at2) {\n if (!object2(value)) fail(`${at2} must be an object`);\n for (const k2 of Object.keys(value)) if (!allowed.includes(k2)) {\n const hint = at2 === "document" ? " Controls and visual components belong in nodes as registered typed nodes, not extra document fields." : "";\n fail(`unknown field ${at2}.${k2}; allowed fields at ${at2}: ${allowed.join(", ")}.${hint}`);\n }\n }\n function safeJson(value, depth = 0, source = false) {\n if (depth > 48) fail("JSON nesting is too deep");\n if (value === null || typeof value === "boolean") return;\n if (typeof value === "string") {\n if (source) {\n if (value.length > SANDBOX_LIMITS.source) fail("canvas source exceeds 48 Ki characters");\n return;\n }\n return text(value, "value");\n }\n if (typeof value === "number") {\n if (!finite(value)) fail("numbers must be finite");\n return;\n }\n if (typeof value !== "object") fail("only JSON values are accepted");\n if (Array.isArray(value) && value.length > LIMITS.rows) fail("too many array items");\n for (const k2 of Object.keys(value)) {\n if (["__proto__", "prototype", "constructor"].includes(k2)) fail("unsafe property name");\n safeJson(value[k2], depth + 1, value.type === "sandbox" && ["html", "css", "script"].includes(k2));\n }\n }\n function initialState(doc2) {\n return Object.fromEntries(Object.entries(doc2.state).map(([k2, spec]) => [k2, spec.default]));\n }\n function validateState(doc2, state2) {\n if (!object2(state2) || Object.keys(state2).length !== Object.keys(doc2.state).length) fail("state keys do not match the document");\n const result = {};\n for (const [k2, s] of Object.entries(doc2.state)) {\n if (!own2(state2, k2)) fail(`missing state.${k2}`);\n const v2 = state2[k2];\n if (s.type === "number") {\n if (!finite(v2) || v2 < s.min || v2 > s.max) fail(`state.${k2} is outside its numeric range`);\n const offset = (v2 - s.min) / s.step;\n if (Math.abs(offset - Math.round(offset)) > 1e-6) fail(`state.${k2} does not match its step`);\n } else if (s.type === "json") {\n if (!object2(v2) && !Array.isArray(v2)) fail(`state.${k2} must be an array or object for type json`);\n safeJson(v2);\n if (new TextEncoder().encode(JSON.stringify(v2)).length > 16384) fail(`state.${k2} JSON exceeds 16 KiB`);\n } else if (s.type === "string") text(v2, `state.${k2}`);\n else if (typeof v2 !== "boolean") fail(`state.${k2} must be boolean`);\n if (s.options && !s.options.includes(v2)) fail(`invalid option for state.${k2}`);\n result[k2] = v2;\n }\n return result;\n }\n var ARITY = { add: [1, 8], sub: [2, 2], mul: [1, 8], div: [2, 2], min: [1, 8], max: [1, 8], round: [1, 1], ceil: [1, 1], floor: [1, 1], abs: [1, 1], eq: [2, 2], neq: [2, 2], lt: [2, 2], lte: [2, 2], gt: [2, 2], gte: [2, 2], if: [3, 3] };\n function reference(doc2, ref) {\n if (typeof ref !== "string" || !["state", "data", "derived"].includes(ref.split(".")[0]) || ref.split(".").length !== 2 || !validIdentifier(ref.split(".")[1])) fail(`invalid reference ${JSON.stringify(ref)}; use state.key, data.key or derived.key with a letter/underscore identifier`);\n const [group, k2] = ref.split(".");\n if (!own2(doc2[group], k2)) fail(`unknown reference ${ref}`);\n return [group, k2];\n }\n function evaluate(doc2, state2) {\n const derived = {}, active = /* @__PURE__ */ new Set();\n let steps = 0, generatedRows = 0;\n const budget = () => {\n if (++steps > LIMITS.steps) fail("calculation budget exceeded");\n };\n const resolve = (ref) => {\n budget();\n const [group, k2] = reference(doc2, ref);\n if (group !== "derived") return (group === "state" ? state2 : doc2.data)[k2];\n if (own2(derived, k2)) return derived[k2];\n if (active.has(k2)) fail(`cyclic calculation ${k2}`);\n active.add(k2);\n const result2 = expression2(doc2.derived[k2]);\n active.delete(k2);\n derived[k2] = result2;\n return result2;\n };\n const expression2 = (e, item) => {\n budget();\n if (own2(e, "map")) {\n const rows = resolve(e.map.source);\n if ((generatedRows += rows.length) > LIMITS.rows) fail("generated row limit exceeded");\n return rows.map((row) => Object.fromEntries(Object.entries(e.map.fields).map(([k2, value]) => {\n const out2 = expression2(value, row);\n if (!scalar(out2)) fail("generated cells must be scalar");\n return [k2, out2];\n })));\n }\n if (own2(e, "const")) return e.const;\n if (own2(e, "ref")) {\n if (e.ref.startsWith("item.")) {\n const k2 = e.ref.slice(5);\n if (!item || !own2(item, k2) || !scalar(item[k2])) fail("invalid item reference");\n return item[k2];\n }\n return resolve(e.ref);\n }\n if (e.op === "if") {\n const condition = expression2(e.args[0], item);\n if (typeof condition !== "boolean") fail("if condition must be boolean");\n return expression2(e.args[condition ? 1 : 2], item);\n }\n const a = e.args.map((arg) => expression2(arg, item));\n if (e.op === "eq") return a[0] === a[1];\n if (e.op === "neq") return a[0] !== a[1];\n if (!a.every(finite)) fail(`operator ${e.op} requires finite numbers`);\n let out;\n switch (e.op) {\n case "add":\n out = a.reduce((x, y2) => x + y2, 0);\n break;\n case "sub":\n out = a[0] - a[1];\n break;\n case "mul":\n out = a.reduce((x, y2) => x * y2, 1);\n break;\n case "div":\n if (a[1] === 0) fail("division by zero");\n out = a[0] / a[1];\n break;\n case "min":\n out = Math.min(...a);\n break;\n case "max":\n out = Math.max(...a);\n break;\n case "round":\n out = Math.round(a[0]);\n break;\n case "ceil":\n out = Math.ceil(a[0]);\n break;\n case "floor":\n out = Math.floor(a[0]);\n break;\n case "abs":\n out = Math.abs(a[0]);\n break;\n case "lt":\n return a[0] < a[1];\n case "lte":\n return a[0] <= a[1];\n case "gt":\n return a[0] > a[1];\n case "gte":\n return a[0] >= a[1];\n default:\n fail(`unsupported operator ${e.op}`);\n }\n if (!finite(out)) fail("non-finite calculation result");\n return out;\n };\n for (const k2 of Object.keys(doc2.derived)) resolve(`derived.${k2}`);\n if (new TextEncoder().encode(JSON.stringify(derived)).length > LIMITS.bytes) fail("derived output exceeds 128 KiB");\n const resolveCell = (cell) => {\n const out = expression2(cell);\n if (!scalar(out)) fail("inline row formula cells must resolve to a string, boolean or finite number");\n return out;\n };\n const result = { derived, resolveValue: (value) => {\n if (Array.isArray(value)) return value.map((row) => object2(row) ? Object.fromEntries(Object.entries(row).map(([k2, cell]) => [k2, object2(cell) && ["const", "ref", "op"].some((field) => own2(cell, field)) ? resolveCell(cell) : cell])) : row);\n if (!object2(value)) return value;\n return expression2(value);\n } };\n checkViewValues(doc2, result);\n return result;\n }\n function checkViewValues(doc2, evaluated) {\n function walk(list) {\n for (const n of list) {\n if (n.type === "table" || n.type === "chart") {\n const rows = evaluated.resolveValue(n.rows);\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object2)) fail("table/chart rows must reference an array of objects");\n if (n.type === "chart") {\n const index = rows.findIndex((r) => !own2(r, n.labelKey) || !scalar(r[n.labelKey]) || !own2(r, n.valueKey) || !finite(r[n.valueKey]));\n if (index >= 0) {\n const row = rows[index], missing = [n.labelKey, n.valueKey].filter((k2) => !own2(row, k2));\n fail("chart requires labels and finite numeric values. node." + n.id + ".rows[" + index + "]: " + (missing.length ? "missing field(s) " + missing.join(", ") : n.valueKey + " must resolve to a finite number") + ". Available keys: " + Object.keys(row).slice(0, 16).join(", ") + ". For live values use inline rows:[{" + n.labelKey + \':"\\u9879\\u76EE",\' + n.valueKey + \':{ref:"derived.amount"}}]; static data labels alone contain no amounts. Keep all nodes/state/derived when correcting the document\');\n }\n }\n if (n.type === "chart" && n.xScale === "linear" && rows.some((r) => !finite(r[n.labelKey]))) fail("linear chart requires numeric x values");\n }\n if (n.type === "metric" && !scalar(evaluated.resolveValue(n.value))) fail(`node.${n.id}.value must resolve to a number, string or boolean; use table for rows or a canvas for structured data`);\n if (n.type === "progress") {\n const v2 = evaluated.resolveValue(n.value), max = evaluated.resolveValue(n.max);\n if (!finite(v2) || !finite(max) || max <= 0 || v2 < 0 || v2 > max) fail("progress requires 0 <= value <= positive max");\n }\n if (n.children) walk(n.children);\n }\n }\n walk(doc2.nodes);\n }\n function validateDocument(input) {\n safeJson(input);\n const json = JSON.stringify(input);\n if (new TextEncoder().encode(json).length > LIMITS.bytes) fail("document exceeds 128 KiB");\n const normalized = normalizeAuthoring(JSON.parse(json));\n safeJson(normalized);\n const doc2 = expandExpressions(normalized);\n fields(doc2, ["version", "title", "fallback", "state", "data", "derived", "nodes", "actions", "presentation"], "document");\n if (doc2.presentation !== void 0) {\n fields(doc2.presentation, ["layout", "accent", "density", "preset"], "presentation");\n if (doc2.presentation.preset !== void 0 && !TEXT_PRESETS.includes(doc2.presentation.preset)) fail("unknown presentation preset; use " + TEXT_PRESETS.join("/"));\n for (const [k2, allowed] of Object.entries({ layout: UI_LAYOUTS, accent: UI_ACCENTS, density: ["comfortable", "compact"] }))\n if (doc2.presentation[k2] !== void 0 && !allowed.includes(doc2.presentation[k2])) fail(`unknown presentation ${k2}`);\n }\n if (doc2.version !== 1) fail(own2(doc2, "version") ? "document.version must be 1" : "document.version is missing. render_ui creates a complete document, not a partial patch: send {version:1,title,fallback,nodes:[...]} for shared controls/formulas, or {title,items:[...]} for extended visuals. Include all content, not only data/derived");\n text(doc2.title, "title");\n text(doc2.fallback, "fallback");\n if (!doc2.title.trim() || !doc2.fallback.trim()) fail("title and fallback cannot be empty");\n for (const group of ["state", "data", "derived", "actions"]) {\n doc2[group] ??= {};\n if (!object2(doc2[group]) || Object.keys(doc2[group]).length > 64) fail(`invalid ${group}`);\n for (const k2 of Object.keys(doc2[group])) if (!validIdentifier(k2)) fail(`invalid key in ${group}: ${JSON.stringify(k2)}; use 1..64 letters, numbers or underscores, starting with a letter/underscore (Chinese letters supported); no spaces, dots or hyphens. Put display labels in label/text`);\n }\n for (const [k2, s] of Object.entries(doc2.state)) {\n fields(s, ["type", "default", "min", "max", "step", "options"], `state.${k2}`);\n if (s.type === "string" && (Array.isArray(s.default) || object2(s.default)) && !own2(s, "options")) s.type = "json";\n if (!["number", "string", "boolean", "json"].includes(s.type)) fail(`unsupported state type ${k2}; use number, string, boolean or json (arrays/objects)`);\n if (s.type === "json" && own2(s, "options")) fail(`state.${k2}: json state does not support select options; use scalar options or a canvas`);\n if (s.type === "number") {\n for (const field of ["default", "min", "max", "step"]) if (!finite(s[field])) fail(`state.${k2}.${field} must be a finite JSON number; received ${s[field] === null ? "null" : typeof s[field]}. Supply {type:"number",default:2,min:1,max:12,step:1}; do not omit limits or include units in numeric fields`);\n if (s.min >= s.max || s.step <= 0) fail(`invalid numeric limits for state.${k2}: require min < max and step > 0; received min=${s.min}, max=${s.max}, step=${s.step}`);\n if ((s.max - s.min) / s.step > 1e9) fail(`numeric step too small for ${k2}`);\n } else if (["min", "max", "step"].some((p2) => own2(s, p2))) fail(`numeric limits on non-number ${k2}`);\n if (s.options !== void 0 && (!Array.isArray(s.options) || !s.options.length || s.options.length > 64 || !s.options.every(scalar))) fail(`state.${k2}.options must be a direct array of 1..64 scalar values, e.g. options:["3","5","7"], not {item:[...]}`);\n }\n const defaults = validateState(doc2, initialState(doc2));\n let expressions = 0;\n const expressionShapes = /* @__PURE__ */ new Set();\n for (const [k2, spec] of Object.entries(doc2.state))\n for (const option of spec.options ?? []) validateState(doc2, { ...defaults, [k2]: option });\n function validateExpression(e, depth = 0, itemRows, at2 = "expression") {\n if (depth > LIMITS.depth) fail(at2 + ": expression nesting exceeds " + LIMITS.depth);\n const shape = JSON.stringify(e);\n if (!expressionShapes.has(shape)) {\n expressionShapes.add(shape);\n if (++expressions > LIMITS.expressions) fail(at2 + ": expression limit exceeded (128 distinct expressions). Reuse derived references instead of expanding long formulas; keep the complete document when retrying");\n }\n if (!object2(e)) fail(`${at2}: expression must be an object`);\n if (own2(e, "map")) {\n if (depth !== 0) fail("map is only allowed at the root of a derived value");\n fields(e, ["map"], "expression");\n fields(e.map, ["source", "fields"], "map");\n if (typeof e.map.source !== "string" || !e.map.source.startsWith("data.")) fail(\'map source must reference static data using a string such as "data.samples"; put object rows in document.data.samples, not inline in map.source\');\n const [, k2] = reference(doc2, e.map.source), rows = doc2.data[k2];\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object2)) fail("map source must be object rows");\n if (!object2(e.map.fields) || !Object.keys(e.map.fields).length || Object.keys(e.map.fields).length > 16) fail("map requires 1..16 fields");\n for (const [k3, value2] of Object.entries(e.map.fields)) {\n if (!validIdentifier(k3)) fail(`invalid map field ${JSON.stringify(k3).slice(0, 100)}; use a letter/underscore identifier such as powerW or \\u529F\\u7387, without spaces, dots or hyphens`);\n validateExpression(value2, depth + 1, rows, `${at2}.map.fields.${k3}`);\n }\n return;\n }\n if (own2(e, "const")) {\n fields(e, ["const"], "expression");\n if (!scalar(e.const)) fail("constant must be scalar");\n return;\n }\n if (own2(e, "ref")) {\n fields(e, ["ref"], "expression");\n if (typeof e.ref === "string" && e.ref.startsWith("item.")) {\n const k2 = e.ref.slice(5);\n if (!itemRows || !validIdentifier(k2) || itemRows.some((row) => !own2(row, k2) || !scalar(row[k2]))) fail("invalid or unscoped item reference");\n } else reference(doc2, e.ref);\n return;\n }\n fields(e, ["op", "args"], "expression");\n const arity = ARITY[e.op];\n if (!arity || !Array.isArray(e.args) || e.args.length < arity[0] || e.args.length > arity[1]) fail(`${at2}: invalid operator or argument count for ${JSON.stringify(e.op)}; args must be a direct array${arity ? ` with ${arity[0]}..${arity[1]} expressions` : " and op must be registered"}. Received ${Array.isArray(e.args) ? e.args.length + " arguments" : typeof e.args}. Prefer {expr:"state.people * state.days"} for arithmetic; missing operands cannot be inferred`);\n e.args.forEach((a, i) => validateExpression(a, depth + 1, itemRows, `${at2}.args[${i}]`));\n }\n Object.entries(doc2.derived).forEach(([k2, e]) => validateExpression(e, 0, void 0, `derived.${k2}`));\n const visited = /* @__PURE__ */ new Set(), active = /* @__PURE__ */ new Set();\n function visit(k2) {\n if (active.has(k2)) fail(`cyclic calculation ${k2}`);\n if (visited.has(k2)) return;\n active.add(k2);\n function walk(e) {\n if (e.ref?.startsWith("derived.")) visit(e.ref.split(".")[1]);\n for (const a of e.args ?? []) walk(a);\n for (const value2 of Object.values(e.map?.fields ?? {})) walk(value2);\n }\n walk(doc2.derived[k2]);\n active.delete(k2);\n visited.add(k2);\n }\n Object.keys(doc2.derived).forEach(visit);\n for (const [k2, a] of Object.entries(doc2.actions)) {\n fields(a, ["type", "intent", "stateKeys"], `actions.${k2}`);\n if (a.type !== "agent.followup") fail("only agent.followup actions are supported");\n text(a.intent, "action intent");\n if (!a.intent.trim() || !Array.isArray(a.stateKeys) || a.stateKeys.length > 64 || new Set(a.stateKeys).size !== a.stateKeys.length || a.stateKeys.some((s) => !own2(doc2.state, s))) fail("invalid action stateKeys");\n }\n const ids = /* @__PURE__ */ new Map();\n let count2 = 0;\n const value = (v2, at2) => {\n if (object2(v2)) {\n if (own2(v2, "map")) fail("map belongs in derived");\n validateExpression(v2, 0, void 0, at2);\n } else if (!scalar(v2)) fail(`invalid value at ${at2}`);\n };\n function nodes(list, depth = 0, path = "nodes") {\n if (!Array.isArray(list)) fail(path === "nodes" ? \'document.nodes is missing or is not an array. State/derived define values but do not create visible UI. Include nodes:[{id:"heading",type:"heading",text:"..."},...] and actual controls in the SAME complete document; do not resend state/data/derived alone. Declared state keys: \' + Object.keys(doc2.state).join(", ") : path + " must be an array of child nodes; use children:[{id,type,...}]");\n if (depth > LIMITS.depth) fail(path + " exceeds maximum node depth " + LIMITS.depth);\n for (const [index, n] of list.entries()) {\n const at2 = `${path}[${index}]`;\n if (++count2 > LIMITS.nodes) fail("too many nodes");\n if (!object2(n)) fail(`${at2} must be a node object`);\n if (!own2(n, "id")) fail(`${at2}.id is missing (type=${JSON.stringify(n.type)}). Every node, including sandbox, needs its own id; add e.g. id:"canvas". JSON field order does not matter`);\n if (!validIdentifier(n.id)) fail(`${at2}.id is invalid: ${JSON.stringify(n.id)}. Use 1..64 letters/numbers/underscores starting with a letter/underscore`);\n if (ids.has(n.id)) fail(`${at2}.id duplicates ${JSON.stringify(n.id)} first declared at ${ids.get(n.id)}. Give each node a unique id; state keys and node ids are separate namespaces`);\n ids.set(n.id, `${at2}.id`);\n if (!Object.hasOwn(COMPONENTS, n.type)) fail("unsupported component " + n.type);\n if (["table", "chart"].includes(n.type) && typeof n.rows === "string" && /^(data|derived)\\./.test(n.rows)) n.rows = { ref: n.rows };\n switch (n.type) {\n case "visual": {\n const previous = Array.isArray(n.warnings) ? n.warnings.filter((x) => typeof x === "string").map((x) => x.slice(0, 512)).slice(0, 12) : [];\n const checked = validateVisual(n.spec);\n n.spec = checked.spec;\n n.warnings = [.../* @__PURE__ */ new Set([...previous, ...checked.warnings])].slice(0, 12);\n count2 += checked.count;\n if (count2 > LIMITS.nodes) fail("too many nodes, including visual components");\n if (!validIdentifier(n.stateKey) || doc2.state[n.stateKey]?.type !== "json") fail("visual requires its own json stateKey");\n break;\n }\n case "sandbox": {\n text(n.title, `${at2}.title (canvas title)`);\n text(n.fallback, `${at2}.fallback (canvas fallback)`);\n if (!n.title.trim()) fail(`${at2}.title must not be empty`);\n if (!n.fallback.trim()) fail(`${at2}.fallback must not be empty`);\n if (typeof n.html !== "string" || !n.html.trim()) fail(`${at2}.html must be a non-empty HTML string; script/css/fallback belong beside html on the sandbox node, not inside it`);\n for (const field of ["html", "css", "script"]) if (n[field] !== void 0 && (typeof n[field] !== "string" || n[field].length > SANDBOX_LIMITS.source)) fail("canvas source exceeds 48 Ki characters");\n if (n.libraries !== void 0 && (!Array.isArray(n.libraries) || n.libraries.length > 1 || n.libraries.some((v2) => v2 !== "mechanism"))) fail(\'canvas libraries supports only ["mechanism"] or []\');\n if (n.height !== void 0 && (!Number.isInteger(n.height) || n.height < 160 || n.height > SANDBOX_LIMITS.height)) fail("canvas height must be 160..1000");\n for (const [field, group] of [["stateKeys", "state"], ["dataKeys", "data"], ["derivedKeys", "derived"]]) if (n[field] !== void 0 && (!Array.isArray(n[field]) || n[field].length > 64 || new Set(n[field]).size !== n[field].length || n[field].some((k2) => !own2(doc2[group], k2)))) fail("invalid canvas " + field);\n break;\n }\n case "row":\n case "column":\n if (n.gap !== void 0 && !(typeof n.gap === "number" && Number.isFinite(n.gap) && n.gap >= 0 && n.gap <= 40)) fail("gap must be 0..40 pixels");\n if (n.columns !== void 0 && (!Number.isInteger(n.columns) || n.columns < 1 || n.columns > 4)) fail("columns must be 1..4");\n break;\n case "card":\n if (n.title !== void 0) text(n.title, "card title");\n if (n.surface !== void 0 && !UI_SURFACES.includes(n.surface)) fail("unknown card surface");\n break;\n case "details":\n text(n.title, "details title");\n if (n.open === "true" || n.open === "false") n.open = n.open === "true";\n if (n.open !== void 0 && typeof n.open !== "boolean") fail(`node.${n.id}.open must be boolean true or false`);\n break;\n case "badge":\n value(n.text, "badge text");\n break;\n case "progress":\n text(n.label, "progress label");\n value(n.value, "progress value");\n value(n.max, "progress max");\n if (n.unit !== void 0) text(n.unit, "progress unit");\n break;\n case "steps": {\n if (n.title !== void 0) text(n.title, "steps title");\n const at3 = `node.${n.id}.items`;\n if (!Array.isArray(n.items)) fail(`${at3} must be an array of 1..12 step objects, received ${n.items === null ? "null" : typeof n.items}. Use items:[{"title":"First step","description":"One sentence"}], not items:{item:[...]}. status is optional for a static guide`);\n if (!n.items.length || n.items.length > 12) fail(`${at3} requires 1..12 items; received ${n.items.length}. Split a longer guide into separate steps nodes`);\n for (const [i, item] of n.items.entries()) {\n const stepAt = `${at3}[${i}]`;\n fields(item, ["title", "description", "status"], stepAt);\n text(item.title, `${stepAt}.title`);\n if (item.description !== void 0) text(item.description, `${stepAt}.description`);\n if (item.status !== void 0 && !["pending", "active", "done", "error"].includes(item.status)) fail(`${stepAt}.status must be pending, active, done or error; omit status for a static guide`);\n }\n break;\n }\n case "heading":\n case "text":\n case "callout":\n if (n.type === "text") {\n if (n.title !== void 0) text(n.title, "text block title");\n if (n.copyable !== void 0 && typeof n.copyable !== "boolean") fail("copyable must be boolean");\n }\n validateTypography(n, `node.${n.id}`);\n if (n.spans !== void 0) {\n if (n.text !== void 0) fail(`node.${n.id}: use text or spans, not both`);\n if (!Array.isArray(n.spans) || !n.spans.length || n.spans.length > 80) fail("spans must contain 1..80 text fragments");\n for (const [i, span] of n.spans.entries()) {\n fields(span, ["text", ...TYPE_FIELDS], `node.${n.id}.spans[${i}]`);\n text(span.text, "span text");\n validateTypography(span, `node.${n.id}.spans[${i}]`);\n }\n } else value(n.text, "text");\n break;\n case "metric":\n text(n.label, "metric label");\n value(n.value, "metric value");\n if (n.unit !== void 0) text(n.unit, "unit");\n if (n.decimals !== void 0 && (!Number.isInteger(n.decimals) || n.decimals < 0 || n.decimals > 6)) fail("invalid decimals");\n break;\n case "input":\n case "slider":\n case "select":\n case "toggle": {\n text(n.label, "control label");\n if (typeof n.bind !== "string" || !n.bind.startsWith("state.")) fail("controls must bind state");\n const [, k2] = reference(doc2, n.bind), spec = doc2.state[k2];\n if (n.type === "slider" && spec.type !== "number") fail("slider requires numeric state");\n if (n.type === "toggle" && spec.type !== "boolean") fail("toggle requires boolean state");\n if (["input", "select"].includes(n.type) && spec.type === "json") fail(`node.${n.id}: structured state requires a sandbox with DSHUI.setState; use separate boolean states and toggle nodes for a native checklist`);\n if (n.type === "input" && spec.type === "boolean") fail("use toggle for boolean state");\n if (n.type === "select" && !spec.options) fail("select requires options");\n if (n.type === "select" && n.variant !== void 0 && !["dropdown", "segmented"].includes(n.variant)) fail(`node.${n.id}.variant must be dropdown or segmented`);\n break;\n }\n case "code":\n if (typeof n.code !== "string" || n.code.length > SANDBOX_LIMITS.source) fail("code must be a string of at most 48 Ki characters");\n if (n.lang !== void 0) text(n.lang, "code language");\n if (n.title !== void 0) text(n.title, "code title");\n if (n.wrap !== void 0 && typeof n.wrap !== "boolean") fail("code wrap must be boolean");\n break;\n case "button":\n case "link":\n text(n.text, "button text");\n validateLink(n);\n if (n.action !== void 0 && !own2(doc2.actions, n.action)) fail("unknown action");\n break;\n case "divider":\n if (n.label !== void 0) text(n.label, "divider label");\n break;\n case "table": {\n if (n.label !== void 0) text(n.label, "table label");\n if (!Array.isArray(n.rows)) value(n.rows, "node." + n.id + ".rows");\n if (!Array.isArray(n.columns) || !n.columns.length || n.columns.length > 16) fail("invalid table columns");\n const cols = /* @__PURE__ */ new Set();\n for (const c of n.columns) {\n fields(c, ["key", "label", "unit"], "column");\n if (!validIdentifier(c.key) || cols.has(c.key)) fail("invalid or duplicate column key");\n cols.add(c.key);\n text(c.label, "column label");\n if (c.unit !== void 0) text(c.unit, "column unit");\n }\n break;\n }\n case "chart":\n if (n.rows === void 0) fail("node." + n.id + \'.rows is missing; supply rows:[{label:"\\u9879\\u76EE",value:123}] or a rows binding, plus labelKey/valueKey matching its fields. Do not invent missing amounts\');\n if (!Array.isArray(n.rows)) value(n.rows, "node." + n.id + ".rows");\n if (!["bar", "line"].includes(n.kind) || !validIdentifier(n.labelKey) || !validIdentifier(n.valueKey)) fail("invalid chart");\n text(n.label, "chart label");\n if (n.unit !== void 0) text(n.unit, "chart unit");\n if (n.xScale !== void 0 && (!["category", "linear"].includes(n.xScale) || n.xScale === "linear" && n.kind !== "line")) fail("invalid xScale");\n break;\n default:\n fail(`unsupported component ${n.type}`);\n }\n if (["heading", "text", "callout", "card", "metric", "button", "link", "badge", "progress", "details"].includes(n.type)) {\n if (n.icon !== void 0 && !UI_ICONS.includes(n.icon)) fail("unknown UI icon");\n if (!["button", "link"].includes(n.type)) {\n if (n.tone !== void 0 && !UI_TONES.includes(n.tone)) fail("unknown UI tone");\n }\n }\n if (["table", "chart"].includes(n.type) && Array.isArray(n.rows)) {\n for (const [i, row] of n.rows.entries()) if (object2(row)) {\n for (const [k2, cell] of Object.entries(row)) if (object2(cell) && ["const", "ref", "op"].some((field) => own2(cell, field))) value(cell, at2 + ".rows[" + i + "]." + k2);\n }\n }\n fields(n, componentFields(n.type), `node.${n.id}`);\n if (["row", "column", "card", "details"].includes(n.type)) nodes(n.children, depth + 1, `${at2}.children`);\n }\n }\n nodes(doc2.nodes);\n if (!count2) fail("at least one node is required");\n evaluate(doc2, defaults);\n return doc2;\n }\n\n // src/export-runtime.js\n var payload = JSON.parse(document.getElementById("dsh-ui-export").textContent);\n var doc = validateDocument(payload.document);\n var node = doc.nodes.flatMap(function flatten(n) {\n return [n, ...(n.children ?? []).flatMap(flatten)];\n }).find((n) => n.id === payload.nodeId && n.type === "sandbox");\n if (!node) throw Error("\\u5BFC\\u51FA\\u7684\\u753B\\u5E03\\u4E0D\\u5B58\\u5728");\n var state = validateState(doc, payload.state);\n var connected = false;\n var start = Date.now();\n var count = 0;\n var token = () => Array.from(crypto.getRandomValues(new Uint8Array(16)), (b2) => b2.toString(16).padStart(2, "0")).join("");\n var channel = token();\n var nonce = payload.nonce;\n var frame = document.createElement("iframe");\n frame.title = node.title;\n frame.sandbox = "allow-scripts";\n frame.referrerPolicy = "no-referrer";\n frame.style.cssText = "display:block;width:100%;height:" + (node.height ?? 420) + "px;border:0";\n var status = document.getElementById("status");\n var sound = payload.soundtrack;\n var audio;\n var unlocked = false;\n var soundState;\n var caption;\n if (payload.captions?.length && !window.__DSHMotionRender) {\n caption = document.createElement("div");\n caption.setAttribute("aria-live", "off");\n caption.style.cssText = "position:absolute;bottom:5%;left:10%;right:10%;text-align:center;white-space:pre-line;pointer-events:none;font:600 clamp(14px,2.1vw,28px)/1.4 system-ui;color:white;text-shadow:0 1px 4px black";\n const surface = document.getElementById("surface");\n surface.style.position = "relative";\n surface.append(caption);\n }\n var soundAllowed = () => unlocked && soundState?.playing && !soundState.reducedMotion && soundState.visible && !document.hidden;\n if (sound && !window.__DSHMotionRender && /^[\\w-]+\\.(wav|mp3|m4a|aac|ogg|flac)$/.test(sound.file)) {\n audio = document.createElement("audio");\n audio.src = sound.file;\n audio.preload = "auto";\n audio.volume = Math.max(0, Math.min(1, sound.volume ?? 0.3));\n const button = document.createElement("button");\n button.textContent = "\\u5F00\\u542F\\u914D\\u4E50";\n button.type = "button";\n button.addEventListener("click", () => {\n unlocked = !unlocked;\n button.textContent = unlocked ? "\\u5173\\u95ED\\u914D\\u4E50" : "\\u5F00\\u542F\\u914D\\u4E50";\n if (!soundAllowed()) audio.pause();\n else audio.play().then(() => {\n if (!soundAllowed()) audio.pause();\n }).catch(() => {\n unlocked = false;\n button.textContent = "\\u70B9\\u51FB\\u91CD\\u8BD5\\u914D\\u4E50";\n });\n });\n status.before(button);\n status.before(audio);\n }\n var publish = () => {\n try {\n frame.contentWindow.postMessage({ dshCanvas: 1, channel, type: "snapshot", payload: { ...canvasSnapshot(node, state, doc.data, evaluate(doc, state).derived, false, payload.theme), visible: !document.hidden, motionSound: !!audio || !!caption } }, "*");\n } catch (e) {\n status.textContent = "\\u8BA1\\u7B97\\u5931\\u8D25\\uFF1A" + e.message;\n }\n };\n addEventListener("message", (event) => {\n const m2 = event.data;\n if (event.source !== frame.contentWindow || m2?.channel !== channel || m2.dshCanvas !== 1) return;\n if (Date.now() - start > 1e3) {\n start = Date.now();\n count = 0;\n }\n if (++count > SANDBOX_LIMITS.rate) return;\n if (m2.type === "ready") {\n connected = true;\n publish();\n } else if (m2.type === "patch" && connected) {\n try {\n const next = validateState(doc, { ...state, ...canvasPatch(m2.payload, node) });\n evaluate(doc, next);\n state = next;\n status.textContent = "\\u672C\\u5730\\u53C2\\u6570\\u5DF2\\u66F4\\u65B0\\uFF1B\\u5237\\u65B0\\u6587\\u4EF6\\u4F1A\\u56DE\\u5230\\u5BFC\\u51FA\\u65F6\\u7684\\u53C2\\u6570\\u3002";\n } catch (e) {\n status.textContent = "\\u53C2\\u6570\\u65E0\\u6548\\uFF1A" + e.message;\n }\n publish();\n } else if (m2.type === "height" && Number.isFinite(m2.payload) && m2.payload >= 0) frame.style.height = Math.max(32, Math.min(1e3, Math.ceil(m2.payload))) + "px";\n else if (m2.type === "error") status.textContent = "\\u753B\\u5E03\\u8FD0\\u884C\\u5F02\\u5E38\\uFF1A" + String(m2.payload).slice(0, 1e3);\n else if (m2.type === "timeline" && m2.payload.id === "main") {\n soundState = m2.payload;\n if (caption) caption.textContent = payload.captions.find((c) => m2.payload.time >= c.start && m2.payload.time < c.end)?.text ?? "";\n if (!audio) return;\n const t = m2.payload.time;\n if (Number.isFinite(t) && Math.abs(audio.currentTime - t) > 0.2) audio.currentTime = t;\n if (!soundAllowed()) audio.pause();\n else if (audio.paused) audio.play().then(() => {\n if (!soundAllowed()) audio.pause();\n }).catch(() => {\n unlocked = false;\n status.textContent = "\\u8BF7\\u70B9\\u51FB\\u5F00\\u542F\\u914D\\u4E50\\u4EE5\\u5141\\u8BB8\\u64AD\\u653E\\u58F0\\u97F3\\u3002";\n });\n }\n });\n document.addEventListener("visibilitychange", () => {\n if (document.hidden) audio?.pause();\n if (connected) publish();\n });\n addEventListener("pagehide", () => audio?.pause());\n document.getElementById("surface").append(frame);\n frame.srcdoc = sandboxDocument(node, channel, nonce);\n})();\n';
3863
+ var EXPORT_RUNTIME = '(() => {\n // lib/presentation.js\n var UI_ICONS = Object.freeze(["sparkles", "sliders", "layers", "chart", "gauge", "cpu", "database", "info", "check", "warning", "arrow", "target", "external", "file", "globe"]);\n var UI_TONES = Object.freeze(["neutral", "accent", "success", "warning", "danger"]);\n var UI_LAYOUTS = Object.freeze(["dashboard", "workbench", "comparison", "guide", "status", "report"]);\n var UI_ACCENTS = Object.freeze(["blue", "teal", "violet", "amber", "rose"]);\n var UI_SURFACES = Object.freeze(["outline", "soft", "featured"]);\n\n // lib/canvas-source.js\n function normalizeCanvasHtml(html) {\n let protectedDepth = 0;\n return html.replace(/<!--[\\s\\S]*?-->|<(?:"[^"]*"|\'[^\']*\'|[^\'">])*>|[^<]+|</g, (token2) => {\n if (token2.startsWith("<")) {\n const tag = token2.match(/^<(\\/)?(pre|code|textarea|script|style)\\b/i);\n if (tag) protectedDepth = Math.max(0, protectedDepth + (tag[1] ? -1 : 1));\n return token2;\n }\n return !protectedDepth && /^(?:\\s|\\\\[rn])+$/.test(token2) ? token2.replace(/\\\\[rn]/g, "\\n") : token2;\n });\n }\n function normalizeCanvasCss(css) {\n let out = "", quote = "", comment = false, last = "";\n for (let i = 0; i < css.length; i++) {\n const c = css[i], next = css[i + 1];\n if (comment) {\n out += c;\n if (c === "*" && next === "/") {\n out += next;\n i++;\n comment = false;\n }\n continue;\n }\n if (quote) {\n out += c;\n if (c === "\\\\" && next !== void 0) {\n out += next;\n i++;\n } else if (c === quote) quote = "";\n continue;\n }\n if (c === "/" && next === "*") {\n out += "/*";\n i++;\n comment = true;\n continue;\n }\n if (c === \'"\' || c === "\'") {\n quote = c;\n out += c;\n last = c;\n continue;\n }\n if (c === "\\\\" && /[rn]/.test(next ?? "") && /[{};]/.test(last)) {\n out += "\\n";\n i++;\n continue;\n }\n out += c;\n if (!/\\s/.test(c)) last = c;\n }\n return out;\n }\n var canvasSource = (node2) => ({ html: normalizeCanvasHtml(node2.html), css: normalizeCanvasCss(node2.css ?? ""), script: node2.script ?? "" });\n\n // lib/mechanism-runtime-bundle.js\n var MECHANISM_RUNTIME = \'var __MotionMechanism=(()=>{var it=Object.defineProperty;var Ot=Object.getOwnPropertyDescriptor;var Et=Object.getOwnPropertyNames;var It=Object.prototype.hasOwnProperty;var zt=(t,a)=>{for(var n in a)it(t,n,{get:a[n],enumerable:!0})},Pt=(t,a,n,o)=>{if(a&&typeof a=="object"||typeof a=="function")for(let e of Et(a))!It.call(t,e)&&e!==n&&it(t,e,{get:()=>a[e],enumerable:!(o=Ot(a,e))||o.enumerable});return t};var _t=t=>Pt(it({},"__esModule",{value:!0}),t);var Tt={};zt(Tt,{createMechanismAPI:()=>Ft});var st=Math.PI/180,Ct=Math.sqrt(1.6);function yt({scale:t,azimuth:a=45,elevation:n=30}){let o=a*st,e=n*st;return{sinA:Math.sin(o),cosA:Math.cos(o),sinE:Math.sin(e),cosE:Math.cos(e),k:t*Ct}}function q([t,a,n],o){let{origin:e}=o,{sinA:i,cosA:r,sinE:p,cosE:d,k:m}=yt(o);return[e[0]+(t*i-a*r)*m,e[1]+((t*r+a*i)*p-n*d)*m]}function tt([t,a,n],o){let{sinA:e,cosA:i,sinE:r,cosE:p}=yt(o);return(t*i+a*e)*p+n*r}function vt({x:t,y:a,w:n,d:o,r:e},i=8){let r=Math.max(0,Math.min(e,n/2,o/2)),p=[[t+n-r,a+r,-90],[t+n-r,a+o-r,0],[t+r,a+o-r,90],[t+r,a+r,180]],d=[];for(let[m,s,c]of p){let u=r>0?i:0;for(let f=0;f<=u;f++){let g=(c+(u?90*f/u:45))*st;d.push([m+r*Math.cos(g),s+r*Math.sin(g)])}}return d}function lt(t,a,n,o=40){return Array.from({length:o},(e,i)=>{let r=i/o*Math.PI*2;return[t+n*Math.cos(r),a+n*Math.sin(r)]})}function ct(t,a,n,{pad:o=24,headroom:e=0,azimuth:i=45,elevation:r=30}={}){let p={origin:[0,0],scale:1,azimuth:i,elevation:r},d=t.map(M=>q(M,p)),m=d.map(([M])=>M),s=d.map(([,M])=>M),c=Math.min(...m),u=Math.max(...m),f=Math.min(...s),g=Math.max(...s),h=Math.min((a-o*2)/(u-c),(n-o*2-e)/(g-f));return{origin:[a/2-(c+u)/2*h,e+(n-e)/2-(f+g)/2*h],scale:h,azimuth:i,elevation:r}}var Nt=Object.freeze({parts:96,teeth:64,faces:8192}),Ht=t=>typeof t=="number"&&Number.isFinite(t),y=t=>{throw Error("Motion mechanism: "+t)},v=(t,a,n=-1e4,o=1e4)=>((!Ht(t)||t<n||t>o)&&y(a+" must be a finite number in "+n+".."+o),t),U=(t,a)=>((!Array.isArray(t)||t.length!==3)&&y(a+" must be [x,y,z]"),t.map((n,o)=>v(n,a+"["+o+"]"))),et=t=>typeof t=="string"&&/^[\\\\p{L}_][\\\\p{L}\\\\p{M}\\\\p{N}_]{0,63}$/u.test(t)&&!["constructor","prototype","__proto__"].includes(t),kt=["box","cylinder","gear","rod","spring"],I=(t,a)=>t.map((n,o)=>n+a[o]),B=(t,a)=>t.map((n,o)=>n-a[o]),_=(t,a)=>t.map(n=>n*a),dt=(t,a)=>t.reduce((n,o,e)=>n+o*a[e],0),V=(t,a)=>[t[1]*a[2]-t[2]*a[1],t[2]*a[0]-t[0]*a[2],t[0]*a[1]-t[1]*a[0]],J=t=>{let a=Math.hypot(...t);return a<1e-6&&y("zero-length axis"),_(t,1/a)};function Y(t){(!t||typeof t!="object"||Array.isArray(t))&&y("scene must be an object"),(!Array.isArray(t.parts)||!t.parts.length||t.parts.length>Nt.parts)&&y("parts requires 1..96 objects");let a=new Set,n=new Set;for(let[o,e]of t.parts.entries()){let i="parts["+o+"]";(!e||typeof e!="object"||!et(e.id)||a.has(e.id))&&y(i+".id must be a unique identifier"),a.add(e.id),kt.includes(e.type)||y(i+".type must be "+kt.join("/")),e.group!==void 0&&(et(e.group)||y(i+".group must be an identifier"),n.add(e.group));for(let r of["label","description"])e[r]!==void 0&&(typeof e[r]!="string"||e[r].length>1024)&&y(i+"."+r+" must be short text");if(e.cover!==void 0&&typeof e.cover!="boolean"&&y(i+".cover must be boolean"),e.material!==void 0&&!["metal","dark","accent","warm","cool"].includes(e.material)&&y(i+".material must be metal/dark/accent/warm/cool"),e.at!==void 0&&U(e.at,i+".at"),e.explode!==void 0&&U(e.explode,i+".explode"),e.rotation!==void 0&&v(e.rotation,i+".rotation",-1e9,1e9),e.axis!==void 0&&!["x","y","z"].includes(e.axis)&&y(i+".axis must be x/y/z"),e.type==="box"){let r=U(e.size,i+".size");r.some(p=>p<=0||p>2e3)&&y(i+".size must be positive and <=2000"),e.round!==void 0&&v(e.round,i+".round",0,Math.min(r[0],r[1])/2)}if(["cylinder","gear"].includes(e.type)&&(v(e.radius,i+".radius",.1,1e3),v(e.height??8,i+".height",.1,1e3),e.inner!==void 0&&v(e.inner,i+".inner",0,e.radius-.01)),e.type==="gear"){let r=v(e.teeth,i+".teeth",6,64);Number.isInteger(r)||y(i+".teeth must be an integer"),e.module!==void 0&&v(e.module,i+".module",.1,e.radius/3)}if(["rod","spring"].includes(e.type)&&(U(e.from,i+".from"),U(e.to,i+".to"),Math.hypot(...B(e.to,e.from))<.1&&y(i+" endpoints must differ"),v(e.radius??2,i+".radius",.1,200)),e.type==="spring"){let r=v(e.turns??8,i+".turns",2,24);Number.isInteger(r)||y(i+".turns must be integer")}}if(t.groups!==void 0){(!Array.isArray(t.groups)||t.groups.length>12)&&y("groups must be an array of <=12 labels");let o=new Set;for(let e of t.groups)(!e||!et(e.id)||o.has(e.id)||!n.has(e.id)||typeof e.label!="string"||e.label.length>128)&&y("groups must name unique existing part groups"),o.add(e.id)}if(t.bounds!==void 0){(!Array.isArray(t.bounds)||t.bounds.length!==2)&&y("bounds must be [minXYZ,maxXYZ]");let[o,e]=t.bounds.map((i,r)=>U(i,"bounds["+r+"]"));o.some((i,r)=>i>=e[r])&&y("bounds min must be below max on every axis")}if(t.azimuth!==void 0&&v(t.azimuth,"azimuth",10,80),t.elevation!==void 0&&v(t.elevation,"elevation",15,70),t.title!==void 0&&(typeof t.title!="string"||t.title.length>256)&&y("title must be short text"),t.bind!==void 0){(!t.bind||typeof t.bind!="object"||Array.isArray(t.bind))&&y("bind must be an object");for(let[o,e]of Object.entries(t.bind))(!["explode","selected","cutaway"].includes(o)||!et(e))&&y("bind only accepts declared state keys for explode/selected/cutaway")}return t}function Lt(t){return t==="x"?[[0,1,0],[0,0,1],[1,0,0]]:t==="y"?[[0,0,1],[1,0,0],[0,1,0]]:[[1,0,0],[0,1,0],[0,0,1]]}var at=(t,a,n,o)=>I(I(_(t[0],a),_(t[1],n)),_(t[2],o));function Rt(t,a,n,o){let e=t.map(([m,s])=>at(n,m,s,-a/2)),i=t.map(([m,s])=>at(n,m,s,a/2)),r=[],p=o?.map(([m,s])=>at(n,m,s,a/2)),d=o?.map(([m,s])=>at(n,m,s,-a/2));r.push({points:i,holes:p?[p.slice().reverse()]:[],normal:n[2]},{points:e.slice().reverse(),holes:d?[d]:[],normal:_(n[2],-1)});for(let m=0;m<t.length;m++){let s=(m+1)%t.length;Math.hypot(...B(e[s],e[m]))<1e-6||(r.push({points:[e[m],e[s],i[s],i[m]],normal:J(V(B(e[s],e[m]),n[2]))}),o&&r.push({points:[d[s],d[m],p[m],p[s]],normal:J(V(B(d[m],d[s]),n[2]))}))}return r}function ot(t){let a=Lt(t.axis),n,o,e;if(t.type==="box"&&(n=vt({x:-t.size[0]/2,y:-t.size[1]/2,w:t.size[0],d:t.size[1],r:t.round??Math.min(2,t.size[0]/2,t.size[1]/2)},3),o=t.size[2]),t.type==="cylinder"&&(n=lt(0,0,t.radius,24),o=t.height??8),t.type==="gear"){let s=Math.PI*2/t.teeth,c=t.module??t.radius*2/t.teeth;n=[];for(let u=0;u<t.teeth;u++)for(let[f,g]of[[-.5,t.radius-c*.85],[-.32,t.radius-c*.85],[-.17,t.radius+c*.7],[.17,t.radius+c*.7],[.32,t.radius-c*.85]]){let h=(u+f)*s;n.push([Math.cos(h)*g,Math.sin(h)*g])}o=t.height??8}if(t.type==="rod"){let s=J(B(t.to,t.from)),c=J(V(s,Math.abs(s[2])<.9?[0,0,1]:[0,1,0]));a=[c,V(s,c),s],n=lt(0,0,t.radius??2,16),o=Math.hypot(...B(t.to,t.from))}if(t.type==="spring"){let s=J(B(t.to,t.from)),c=J(V(s,Math.abs(s[2])<.9?[0,0,1]:[0,1,0])),u=V(s,c),f=[];for(let g=0;g<=128;g++){let h=g/128,M=h*(t.turns??8)*Math.PI*2,O=Math.min(1,h*12,(1-h)*12);f.push(I(I(t.from,_(B(t.to,t.from),h)),I(_(c,Math.cos(M)*(t.radius??6)*O),_(u,Math.sin(M)*(t.radius??6)*O))))}return{line:f,points:f}}let i=t.rotation??0,r=Math.cos(i),p=Math.sin(i);n=n.map(([s,c])=>[s*r-c*p,s*p+c*r]);let d=t.inner?n.map(([s,c])=>{let u=Math.atan2(c,s);return[Math.cos(u)*t.inner,Math.sin(u)*t.inner]}):void 0;e=Rt(n,o,a,d);let m=t.type==="rod"?_(I(t.from,t.to),.5):t.at??[0,0,0];return e=e.map(s=>({...s,points:s.points.map(c=>I(c,m)),holes:s.holes?.map(c=>c.map(u=>I(u,m)))})),{faces:e,points:e.flatMap(s=>s.points)}}function wt(t){if(t.bounds){let[a,n]=t.bounds;return Array.from({length:8},(o,e)=>[e&1?n[0]:a[0],e&2?n[1]:a[1],e&4?n[2]:a[2]])}return t.parts.flatMap(a=>ot(a).points.flatMap(o=>[o,I(o,a.explode??[0,0,0])]))}function W({driverTeeth:t=16,drivenTeeth:a=32,rpm:n=30,angle:o=0,module:e=2}={}){for(let[i,r]of Object.entries({driverTeeth:t,drivenTeeth:a}))(!Number.isInteger(r)||r<6||r>64)&&y(i+" must be integer 6..64");return v(n,"rpm",-600,600),v(o,"angle",-1e9,1e9),v(e,"module",.1,10),{driverRadius:t*e/2,drivenRadius:a*e/2,centerDistance:(t+a)*e/2,driverAngle:o,drivenAngle:-o*t/a+Math.PI-Math.PI/a,driverRpm:n,drivenRpm:-n*t/a,ratio:a/t}}function X({angle:t=0,radius:a=20,rod:n=70,z:o=20}={}){v(t,"angle",-1e9,1e9),v(a,"radius",.1,200),v(n,"rod",.1,1e3),v(o,"z"),n<=a&&y("connecting rod length must exceed crank radius");let e=[a*Math.cos(t),a*Math.sin(t),o],i=e[0]+Math.sqrt(n*n-e[1]*e[1]);return{crank:e,piston:[i,0,o],position:i,stroke:a*2,angle:t}}function Mt(t,a,n,o=.16){return v(t,"value",-1e9,1e9),v(a,"target",-1e9,1e9),v(n,"delta",0,.1),v(o,"tau",.01,10),t+(a-t)*(1-Math.exp(-n/o))}var $t=Math.PI*2;function nt(t,a){Y(t);let n=a&&!t.bounds?t.parts.filter(o=>!a.cutaway||!o.cover).flatMap(o=>ot(o).points.map(e=>I(e,_(o.explode??[0,0,0],a.explode??0)))):wt(t);return ct(n.length?n:[[0,0,0],[1,1,1]],600,340,{pad:24,azimuth:t.azimuth??45,elevation:t.elevation??30})}var At=t=>t.map(([a,n],o)=>(o?"L":"M")+Math.round(a*10)/10+" "+Math.round(n*10)/10).join("")+"Z";function mt(t,a,{explode:n=0,selected:o="all",cutaway:e=!1,pose:i={}}={},r=new Map){if(typeof n!="number"||!Number.isFinite(n)||n<0||n>1)throw Error("Motion mechanism: explode must be 0..1");if(typeof o!="string"||typeof e!="boolean")throw Error("Motion mechanism: selected must be text and cutaway boolean");if(!i||typeof i!="object"||Array.isArray(i))throw Error("Motion mechanism: pose must be an object");for(let c of Object.keys(i))if(!t.parts.some(u=>u.id===c))throw Error("Motion mechanism: unknown pose part "+c);let p=(a.azimuth??45)*$t/360,d=(a.elevation??30)*$t/360,m=[Math.cos(p)*Math.cos(d),Math.sin(p)*Math.cos(d),Math.sin(d)],s=[];for(let c of t.parts){if(e&&c.cover)continue;let u=i[c.id]??{};for(let $ of Object.keys(u))if(!["at","rotation","from","to"].includes($))throw Error("Motion mechanism: unsupported pose field "+$);let f={...c,...u},g=JSON.stringify(f),h=r.get(c.id);h?.key!==g&&(Y({parts:[f]}),h={key:g,...ot(f)},r.set(c.id,h));let M=_(f.explode??[0,0,0],n),O=Math.min(...h.points.map($=>$[2]))+M[2],N=o==="all"||o===c.id||o===c.group;if(h.line){let $=h.line.map(P=>I(P,M));s.push({floor:O,key:f.id+"_line",part:f.id,group:f.group,d:$.map((P,A)=>(A?"L":"M")+q(P,a).join(" ")).join(""),depth:tt($[Math.floor($.length/2)],a),line:!0,tone:1,material:f.material??"metal",active:N});continue}for(let[$,P]of h.faces.entries()){if(dt(P.normal,m)<=1e-4)continue;let w=P.points.map(S=>I(S,M)),T=P.holes?.map(S=>S.map(H=>I(H,M))),D=_(w.reduce((S,H)=>I(S,H),[0,0,0]),1/w.length),G=dt(P.normal,[-.25,-.4,.88]);s.push({floor:O,key:f.id+"_"+$,part:f.id,group:f.group,d:At(w.map(S=>q(S,a)))+(T??[]).map(S=>At(S.map(H=>q(H,a)))).join(""),depth:tt(D,a),line:!1,tone:G>.5?0:G>.1?1:G>-.4?2:3,material:f.material??"metal",active:N})}}if(s.length>8192)throw Error("Motion mechanism: face budget exceeded");return s.sort((c,u)=>c.floor-u.floor||c.depth-u.depth||c.key.localeCompare(u.key))}var z=(t,a,n,o,e,i={})=>({id:t,type:"box",label:a,at:n,size:o,group:e,...i}),F=(t,a,n,o,e,i,r={})=>({id:t,type:"cylinder",label:a,at:n,radius:o,height:e,group:i,...r});function ut(t,a,n,o,e=3,i=18){return[[-1,-1],[-1,1],[1,-1],[1,1]].map(([r,p],d)=>F(o+"_bolt_"+d,"\\\\u56FA\\\\u5B9A\\\\u87BA\\\\u6813",[t+r*i,a+p*i,n],e,3,o,{material:"dark",explode:[0,0,26]}))}function ft(){return{title:"\\\\u5206\\\\u5C42\\\\u7ED3\\\\u6784 \\\\xB7 \\\\u793A\\\\u610F\\\\u88C5\\\\u914D",groups:[{id:"base",label:"\\\\u5E95\\\\u5EA7",description:"\\\\u652F\\\\u6491\\\\u6574\\\\u4F53\\\\uFF0C\\\\u5E76\\\\u63D0\\\\u4F9B\\\\u5B89\\\\u88C5\\\\u4F4D\\\\u7F6E\\\\u3002"},{id:"board",label:"\\\\u529F\\\\u80FD\\\\u677F",description:"\\\\u8FDE\\\\u63A5\\\\u8F93\\\\u5165\\\\u4E0E\\\\u5904\\\\u7406\\\\u6A21\\\\u5757\\\\uFF1B\\\\u793A\\\\u610F\\\\u7ED3\\\\u6784\\\\uFF0C\\\\u4E0D\\\\u5BF9\\\\u5E94\\\\u7279\\\\u5B9A\\\\u4EA7\\\\u54C1\\\\u3002"},{id:"sink",label:"\\\\u6563\\\\u70ED\\\\u5C42",description:"\\\\u5C06\\\\u70ED\\\\u91CF\\\\u4F20\\\\u5230\\\\u66F4\\\\u5927\\\\u7684\\\\u8868\\\\u9762\\\\u79EF\\\\u3002"},{id:"cover",label:"\\\\u5916\\\\u58F3",description:"\\\\u4FDD\\\\u62A4\\\\u5185\\\\u90E8\\\\uFF1B\\\\u5256\\\\u5F00\\\\u9009\\\\u9879\\\\u901A\\\\u8FC7\\\\u9690\\\\u85CF\\\\u5916\\\\u58F3\\\\u5C55\\\\u793A\\\\u7ED3\\\\u6784\\\\u3002"}],parts:[z("base","\\\\u5B89\\\\u88C5\\\\u5E95\\\\u5EA7",[0,0,0],[120,85,10],"base",{round:6,material:"metal"}),...[-1,1].flatMap((t,a)=>[-1,1].map((n,o)=>F("foot_"+a+o,"\\\\u9632\\\\u6ED1\\\\u811A",[t*46,n*30,-8],6,7,"base",{material:"dark"}))),z("board","\\\\u529F\\\\u80FD\\\\u677F",[0,0,15],[96,62,4],"board",{round:3,material:"cool",explode:[0,0,35]}),z("chip","\\\\u5904\\\\u7406\\\\u6A21\\\\u5757",[-16,0,22],[25,24,10],"board",{round:2,material:"dark",explode:[0,0,35]}),z("connector","\\\\u8FDE\\\\u63A5\\\\u7AEF\\\\u53E3",[32,0,24],[16,36,14],"board",{round:2,material:"warm",explode:[0,0,35]}),...ut(0,0,20,"board",2,24),z("spreader","\\\\u5BFC\\\\u70ED\\\\u5E95\\\\u677F",[-16,0,32],[44,42,5],"sink",{round:2,material:"metal",explode:[-10,0,65]}),...Array.from({length:7},(t,a)=>z("fin_"+a,"\\\\u6563\\\\u70ED\\\\u9CCD\\\\u7247",[-34+a*6,0,44],[2.4,40,20],"sink",{round:1,material:"metal",explode:[-10,0,65]})),z("top","\\\\u9876\\\\u76D6",[0,0,61],[124,89,5],"cover",{round:6,cover:!0,material:"metal",explode:[12,0,85]}),z("side","\\\\u4FA7\\\\u677F",[0,-44,32],[124,4,58],"cover",{round:2,cover:!0,material:"metal",explode:[12,-22,50]})]}}function pt({driverTeeth:t=16,drivenTeeth:a=32,module:n=1.5}={}){let o=W({driverTeeth:t,drivenTeeth:a,module:n}),e=o.centerDistance;return{title:"\\\\u9F7F\\\\u8F6E\\\\u4F20\\\\u52A8 \\\\xB7 \\\\u7B80\\\\u5316\\\\u76F4\\\\u9F7F\\\\u8F6E\\\\u793A\\\\u610F",azimuth:70,elevation:55,groups:[{id:"frame",label:"\\\\u652F\\\\u67B6",description:"\\\\u56FA\\\\u5B9A\\\\u8F74\\\\u5FC3\\\\u4F4D\\\\u7F6E\\\\uFF1B\\\\u4E24\\\\u8F74\\\\u4E2D\\\\u5FC3\\\\u8DDD\\\\u7531\\\\u9F7F\\\\u6570\\\\u4E0E\\\\u6A21\\\\u6570\\\\u5171\\\\u540C\\\\u786E\\\\u5B9A\\\\u3002"},{id:"driver",label:"\\\\u4E3B\\\\u52A8\\\\u8F6E",description:"\\\\u8F93\\\\u5165\\\\u8F6C\\\\u901F\\\\uFF0C\\\\u7531\\\\u9F7F\\\\u6570\\\\u51B3\\\\u5B9A\\\\u8282\\\\u5706\\\\u534A\\\\u5F84\\\\u3002"},{id:"driven",label:"\\\\u4ECE\\\\u52A8\\\\u8F6E",description:"\\\\u5916\\\\u556E\\\\u5408\\\\u8F6C\\\\u5411\\\\u76F8\\\\u53CD\\\\uFF0C\\\\u8F6C\\\\u901F\\\\u6309\\\\u9F7F\\\\u6570\\\\u6BD4\\\\u53D8\\\\u5316\\\\u3002"},{id:"cover",label:"\\\\u5916\\\\u58F3",description:"\\\\u9690\\\\u85CF\\\\u76D6\\\\u677F\\\\u4EE5\\\\u89C2\\\\u5BDF\\\\u4F20\\\\u52A8\\\\uFF1B\\\\u4E0D\\\\u662F\\\\u52A0\\\\u5DE5\\\\u6216\\\\u53D7\\\\u529B\\\\u4EFF\\\\u771F\\\\u3002"}],parts:[z("base","\\\\u5B89\\\\u88C5\\\\u5E95\\\\u5EA7",[30,0,-8],[140,90,10],"frame",{round:6,material:"metal"}),...ut(30,0,0,"frame",3,32),...[0,e].flatMap((i,r)=>[F("bearing_"+r,"\\\\u8F74\\\\u627F\\\\u5EA7",[i,0,4],10,12,"frame",{inner:4,material:"dark"}),F("shaft_"+r,"\\\\u4F20\\\\u52A8\\\\u8F74",[i,0,16],3.8,28,r?"driven":"driver",{material:"metal",explode:[r?24:-24,0,20]}),F("hub_"+r,"\\\\u8F6E\\\\u6BC2",[i,0,27],6,6,r?"driven":"driver",{inner:3.8,material:"warm",explode:[r?24:-24,0,20]})]),{id:"driverGear",type:"gear",label:"\\\\u4E3B\\\\u52A8\\\\u9F7F\\\\u8F6E",group:"driver",at:[0,0,20],radius:o.driverRadius,teeth:t,module:n,height:7,inner:4,material:"accent",explode:[-24,0,20]},{id:"drivenGear",type:"gear",label:"\\\\u4ECE\\\\u52A8\\\\u9F7F\\\\u8F6E",group:"driven",at:[e,0,20],radius:o.drivenRadius,teeth:a,module:n,height:7,inner:4,material:"cool",rotation:o.drivenAngle,explode:[24,0,20]},z("cover","\\\\u9632\\\\u62A4\\\\u76D6\\\\u677F",[30,0,36],[140,90,4],"cover",{round:6,cover:!0,material:"metal",explode:[0,0,62]})]}}function ht({radius:t=20,rod:a=70,angle:n=0}={}){let o=X({radius:t,rod:a,angle:n,z:28});return{title:"\\\\u66F2\\\\u67C4\\\\u8FDE\\\\u6746 \\\\xB7 \\\\u65CB\\\\u8F6C\\\\u8F6C\\\\u4E3A\\\\u5F80\\\\u590D",groups:[{id:"frame",label:"\\\\u652F\\\\u67B6\\\\u4E0E\\\\u5BFC\\\\u8F68",description:"\\\\u652F\\\\u6491\\\\u8F74\\\\u5FC3\\\\uFF0C\\\\u9650\\\\u5236\\\\u6ED1\\\\u5757\\\\u6CBF\\\\u540C\\\\u4E00\\\\u65B9\\\\u5411\\\\u8FD0\\\\u52A8\\\\u3002"},{id:"crank",label:"\\\\u66F2\\\\u67C4",description:"\\\\u66F2\\\\u67C4\\\\u7ED5\\\\u56FA\\\\u5B9A\\\\u8F74\\\\u5FC3\\\\u65CB\\\\u8F6C\\\\u3002"},{id:"rod",label:"\\\\u8FDE\\\\u6746",description:"\\\\u8FDE\\\\u63A5\\\\u66F2\\\\u67C4\\\\u9500\\\\u548C\\\\u6ED1\\\\u5757\\\\uFF0C\\\\u957F\\\\u5EA6\\\\u4FDD\\\\u6301\\\\u4E0D\\\\u53D8\\\\u3002"},{id:"piston",label:"\\\\u6ED1\\\\u5757",description:"\\\\u6CBF\\\\u5BFC\\\\u8F68\\\\u5F80\\\\u590D\\\\uFF1B\\\\u5B8C\\\\u6574\\\\u884C\\\\u7A0B\\\\u7B49\\\\u4E8E\\\\u66F2\\\\u67C4\\\\u534A\\\\u5F84\\\\u7684\\\\u4E24\\\\u500D\\\\u3002"}],parts:[z("base","\\\\u5B89\\\\u88C5\\\\u5E95\\\\u5EA7",[35,0,-6],[175,80,10],"frame",{round:6,material:"metal"}),...ut(35,0,1,"frame",3,30),F("bearing","\\\\u66F2\\\\u8F74\\\\u8F74\\\\u627F",[0,0,7],11,15,"frame",{inner:4,material:"dark"}),F("axle","\\\\u66F2\\\\u8F74",[0,0,15],3.8,26,"crank",{material:"metal",explode:[0,-18,18]}),F("flywheel","\\\\u66F2\\\\u67C4\\\\u76D8",[0,0,20],t+6,6,"crank",{inner:4,material:"accent",explode:[0,-18,18]}),z("railA","\\\\u5BFC\\\\u8F68",[74,-16,13],[85,5,6],"frame",{round:1,material:"dark"}),z("railB","\\\\u5BFC\\\\u8F68",[74,16,13],[85,5,6],"frame",{round:1,material:"dark"}),F("crankPin","\\\\u66F2\\\\u67C4\\\\u9500",o.crank,3,12,"crank",{material:"warm",explode:[0,-18,18]}),{id:"link",type:"rod",label:"\\\\u8FDE\\\\u6746",from:o.crank,to:o.piston,radius:2.4,group:"rod",material:"metal",explode:[0,0,45]},z("piston","\\\\u6ED1\\\\u5757",[o.position,0,22],[18,24,16],"piston",{round:3,material:"cool",explode:[20,0,18]}),F("pistonPin","\\\\u6ED1\\\\u5757\\\\u9500",o.piston,3,10,"piston",{material:"warm",explode:[20,0,18]})]}}var St=`\\n.mui-mechanism{font:15px/1.7 system-ui,sans-serif;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:24px;padding:20px;max-width:100%;box-sizing:border-box}.mui-mechanism *{box-sizing:border-box}.mui-mechanism h2{font-size:22px;line-height:1.35;margin:0 0 8px;font-weight:750}.mui-mechanism p{margin:0;color:var(--canvas-muted)}\\n.mui-mechanism-svg{display:block;width:100%;height:auto;max-height:420px;touch-action:pan-y}.mui-mechanism-svg path{stroke:color-mix(in srgb,var(--canvas-ink) 38%,var(--canvas-bg));stroke-width:.8;stroke-linejoin:round;vector-effect:non-scaling-stroke;cursor:pointer;fill:var(--mech-base,var(--canvas-soft))}.mui-mechanism-svg [data-material=metal]{--mech-base:color-mix(in srgb,var(--canvas-muted) 32%,var(--canvas-bg))}.mui-mechanism-svg [data-material=dark]{--mech-base:color-mix(in srgb,var(--canvas-ink) 78%,var(--canvas-bg))}.mui-mechanism-svg [data-material=accent]{--mech-base:var(--canvas-accent)}.mui-mechanism-svg [data-material=cool]{--mech-base:color-mix(in srgb,#22998a 70%,var(--canvas-bg))}.mui-mechanism-svg [data-material=warm]{--mech-base:color-mix(in srgb,#dd9c42 75%,var(--canvas-bg))}\\n.mui-mechanism-svg [data-tone="0"]{fill:color-mix(in srgb,var(--mech-base) 74%,var(--canvas-bg))}.mui-mechanism-svg [data-tone="1"]{fill:var(--mech-base)}.mui-mechanism-svg [data-tone="2"]{fill:color-mix(in srgb,var(--mech-base) 85%,var(--canvas-ink))}.mui-mechanism-svg [data-tone="3"]{fill:color-mix(in srgb,var(--mech-base) 68%,var(--canvas-ink))}.mui-mechanism-svg [data-line]{fill:none;stroke:var(--mech-base);stroke-width:2}.mui-mechanism-svg [data-active=false]{opacity:.2}.mui-mechanism-svg [data-active=true]{opacity:1}\\n.mui-mechanism-nav{display:flex;flex-wrap:wrap;gap:7px;margin:8px 0 12px}.mui-mechanism button{font:inherit;color:var(--canvas-ink);background:var(--canvas-bg);border:1px solid var(--canvas-line);border-radius:999px;padding:6px 13px;cursor:pointer;min-height:36px}.mui-mechanism button[aria-pressed=true]{color:var(--canvas-bg);background:var(--canvas-ink);border-color:var(--canvas-ink)}.mui-mechanism button:focus-visible,.mui-mechanism input:focus-visible{outline:2px solid var(--canvas-accent);outline-offset:3px}.mui-mechanism button:disabled{opacity:.5;cursor:default}\\n.mui-mechanism-controls{display:flex;align-items:center;flex-wrap:wrap;gap:14px;padding:12px 14px;border-radius:16px;background:var(--canvas-soft);margin:8px 0}.mui-mechanism-controls label{display:flex;align-items:center;gap:9px;flex:1 1 180px;min-width:0}.mui-mechanism-controls input[type=range]{flex:1;min-width:70px;accent-color:var(--canvas-accent)}.mui-mechanism-controls input[type=checkbox]{accent-color:var(--canvas-accent)}.mui-mechanism-controls output{font-variant-numeric:tabular-nums;min-width:40px;text-align:right;font-weight:650}.mui-mechanism-readout{display:block;padding:10px 0;font-weight:700;font-variant-numeric:tabular-nums;color:var(--canvas-ink)}.mui-mechanism-description{min-height:0;font-size:14px}\\n.mui-mechanism[data-style=editorial]{border:0;border-top:1px solid var(--canvas-line);border-radius:0;padding:16px 0}.mui-mechanism[data-style=editorial] h2{font-family:ui-serif,Georgia,serif;font-weight:650}.mui-mechanism[data-style=editorial] .mui-mechanism-controls{border-radius:0;background:transparent;border-block:1px solid var(--canvas-line)}\\n.mui-mechanism[data-style=technical]{border-radius:10px}.mui-mechanism[data-style=technical] button,.mui-mechanism[data-style=technical] .mui-mechanism-controls{border-radius:6px}.mui-mechanism[data-style=technical] .mui-mechanism-readout{font-family:ui-monospace,Consolas,monospace}\\n.mui-mechanism[data-style=soft]{border:0;background:var(--canvas-soft);border-radius:28px 28px 28px 10px}.mui-mechanism[data-style=soft] .mui-mechanism-controls{background:var(--canvas-bg);border-radius:22px}.mui-mechanism[data-style=expressive] h2{font-size:28px;font-weight:850;border-left:5px solid var(--canvas-accent);padding-left:14px}.mui-mechanism[data-style=expressive]{border:0;border-radius:0}.mui-mechanism[data-style=prismframe]{border:1.5px solid var(--canvas-line);box-shadow:4px 5px 0 color-mix(in srgb,var(--canvas-accent) 14%,var(--canvas-bg))}.mui-mechanism[data-style=aurora]{border-radius:28px;box-shadow:0 16px 30px -25px #30204d66}.mui-mechanism[data-style=aurora] .mui-mechanism-controls{border-radius:24px}\\n@media(max-width:500px){.mui-mechanism{padding:14px;border-radius:20px}.mui-mechanism h2{font-size:20px}.mui-mechanism-controls{padding:10px}.mui-mechanism-nav{gap:5px}.mui-mechanism button{padding:6px 10px;font-size:14px}}\\n@media(prefers-reduced-motion:reduce){.mui-mechanism *{animation:none!important;transition:none!important}}\\n@media(forced-colors:active){.mui-mechanism-svg path{fill:Canvas;stroke:CanvasText}.mui-mechanism button[aria-pressed=true]{background:Highlight;color:HighlightText}}\\n`;var xt="http://www.w3.org/2000/svg",C=(t,a,n)=>{let o=document.createElement(t);return a&&(o.className=a),n!==void 0&&(o.textContent=n),o};function Ft(t){function a(o,e){let i=typeof o=="string"?document.querySelector(o):o;if(!i||!i.replaceChildren)throw Error("Motion mechanism: target element not found");Y(e);let r=structuredClone({...e,onSelect:void 0}),p=nt(r),d={explode:0,selected:"all",cutaway:!1,pose:{}},m=!1,s="",c="",u=0,f=new Map,g=new Map,h=new Map,M=[],O=C("section","mui-mechanism"),N=C("h2",null,r.title??"\\\\u7ED3\\\\u6784\\\\u56FE\\\\u89E3"),$=document.createElementNS(xt,"svg"),P=document.createElementNS(xt,"g"),A=C("div","mui-mechanism-nav"),w=C("div","mui-mechanism-controls"),T=C("p","mui-mechanism-description"),D=C("output","mui-mechanism-readout"),G=C("style");G.textContent=St,N.hidden=r.title==="",O.setAttribute("aria-label",r.title??"\\\\u7ED3\\\\u6784\\\\u56FE\\\\u89E3"),$.setAttribute("class","mui-mechanism-svg"),$.setAttribute("viewBox","0 0 600 340"),$.setAttribute("role","img"),$.setAttribute("aria-label","\\\\u53EF\\\\u62C6\\\\u89E3\\\\u7684\\\\u7ED3\\\\u6784\\\\u793A\\\\u610F\\\\u56FE\\\\uFF1B\\\\u4F7F\\\\u7528\\\\u4E0B\\\\u65B9\\\\u6309\\\\u94AE\\\\u9009\\\\u62E9\\\\u90E8\\\\u4EF6"),$.append(P),O.append(G,N,$,A,w,D,T),i.replaceChildren(O);let S=()=>r.groups?.length?r.groups:r.parts.map(l=>({id:l.id,label:l.label??l.id,description:l.description??""}));function H(l){r.bind?.selected?t.setState({[r.bind.selected]:l}):typeof e.onSelect=="function"?e.onSelect(l):Q({selected:l})}function K(){if(A.replaceChildren(),h.clear(),!r.bind?.selected&&typeof e.onSelect!="function"){A.hidden=!0;return}A.hidden=!1;for(let l of[{id:"all",label:"\\\\u5168\\\\u90E8",description:""},...S()]){let b=C("button",null,l.label);b.type="button",b.setAttribute("aria-pressed",String(d.selected===l.id)),b.addEventListener("click",()=>H(l.id)),h.set(l.id,b),A.append(b)}}let x,rt,L;if(r.bind?.explode){let l=C("label",null,"\\\\u62C6\\\\u89E3\\\\u8FDB\\\\u5EA6");x=C("input"),x.type="range",x.min="0",x.max="1",x.step=".01",x.setAttribute("aria-label","\\\\u62C6\\\\u89E3\\\\u8FDB\\\\u5EA6"),rt=C("output"),x.addEventListener("input",()=>t.setState({[r.bind.explode]:Number(x.value)})),l.append(x,rt),w.append(l)}if(r.bind?.cutaway&&r.parts.some(l=>l.cover)){let l=C("label",null,"\\\\u5256\\\\u5F00\\\\u5916\\\\u58F3");L=C("input"),L.type="checkbox",L.setAttribute("aria-label","\\\\u5256\\\\u5F00\\\\u5916\\\\u58F3"),L.addEventListener("change",()=>t.setState({[r.bind.cutaway]:L.checked})),l.prepend(L),w.append(l)}w.hidden=!w.childNodes.length;function jt(l){let b=JSON.stringify([l.explode,l.cutaway]);b!==s&&(p=nt(r,l),s=b);let E=mt(r,p,l,f),k=new Set;for(let j of E){k.add(j.key);let R=g.get(j.key);R||(R=document.createElementNS(xt,"path"),R.setAttribute("fill-rule","evenodd"),g.set(j.key,R));for(let[gt,bt]of Object.entries({d:j.d,"data-part":j.part,"data-material":j.material,"data-tone":j.tone,"data-active":j.active}))R.getAttribute(gt)!==String(bt)&&R.setAttribute(gt,String(bt));j.line?R.setAttribute("data-line",""):R.removeAttribute("data-line")}for(let[j,R]of g)k.has(j)||(R.remove(),g.delete(j));let Z=E.map(j=>j.key).join("|");if(Z!==c){for(let j of E)P.append(g.get(j.key));c=Z}u++}function Q(l={}){if(m)return;for(let k of Object.keys(l))if(!["explode","selected","cutaway","pose","parts","readout"].includes(k))throw Error("Motion mechanism: unknown update field "+k);if(l.parts){let k={...r,parts:l.parts};Y(k);let Z=nt(k);mt(k,Z,{...d,...l},new Map),r=k,p=Z,f.clear(),c="",s=""}let b={...d,...l};l.pose&&(b.pose=l.pose),jt(b),d=b;for(let[k,Z]of h)Z.setAttribute("aria-pressed",String(b.selected===k));let E=S().find(k=>k.id===b.selected)??r.parts.find(k=>k.id===b.selected);T.textContent=E?.description??(b.selected==="all"?"\\\\u9009\\\\u62E9\\\\u4E00\\\\u4E2A\\\\u90E8\\\\u4EF6\\\\uFF0C\\\\u67E5\\\\u770B\\\\u5B83\\\\u7684\\\\u804C\\\\u8D23\\\\uFF1B\\\\u62C6\\\\u89E3\\\\u53EA\\\\u5C55\\\\u793A\\\\u88C5\\\\u914D\\\\u5173\\\\u7CFB\\\\u3002":""),x&&(x.value=String(b.explode),rt.textContent=Math.round(b.explode*100)+"%"),L&&(L.checked=b.cutaway),l.readout!==void 0&&(D.textContent=String(l.readout))}return $.addEventListener("click",l=>{let b=l.target.closest("[data-part]");if(!b)return;let E=r.parts.find(k=>k.id===b.getAttribute("data-part"));E&&H(r.groups?.length?E.group??E.id:E.id)}),K(),M.push(t.subscribe(l=>{if(m)return;let b={};for(let[E,k]of Object.entries(r.bind??{})){if(!Object.hasOwn(l.state,k))throw Error("Motion mechanism: bind."+E+" names undeclared state "+k);b[E]=l.state[k]}O.dataset.style=l.theme?.visualStyle??"";for(let E of h.values())E.disabled=l.disabled;x&&(x.disabled=l.disabled),L&&(L.disabled=l.disabled),Q(b)})),Object.freeze({update:Q,pose:l=>Q({pose:l}),stats:()=>({frames:u,faces:g.size,parts:r.parts.length}),destroy(){m||(m=!0,M.forEach(l=>l()),g.clear(),f.clear(),i.replaceChildren())}})}function n(o,e,i={}){if(!["assembly","gears","crank"].includes(e))throw Error("Motion mechanism: demo must be assembly/gears/crank");let r=i.bind??{},p=()=>t.snapshot.state,d=(A,w)=>Object.hasOwn(r,A)?p()[r[A]]:w;for(let[A,w]of Object.entries(r))if(!["explode","selected","cutaway","rpm","teeth","running","angle","radius"].includes(A)||typeof w!="string"||!Object.hasOwn(p(),w))throw Error("Motion mechanism: invalid demo binding "+A);let m=d("angle",0)*Math.PI/180,s=m,c="",u=!1,f=Object.fromEntries(Object.entries(r).filter(([A])=>["explode","selected","cutaway"].includes(A)));function g(){return e==="assembly"?ft():e==="gears"?pt({driverTeeth:i.driverTeeth??16,drivenTeeth:d("teeth",32),module:i.module??1.5}):ht({radius:d("radius",20),rod:i.rod??70})}let h=a(o,{...g(),...i.title===void 0?{}:{title:i.title},bind:f}),M=!1;function O(A=0,w=!1,T=!0){if(M)return;let D=d("rpm",30),G=d("running",!1),S=d("angle",0)*Math.PI/180,H=s;S!==m?(H=S,m=S):G&&T&&!w&&(H+=D*Math.PI*2/60*A),s=H;let K=JSON.stringify([e,d("teeth",32),d("radius",20)]);if(K!==c&&(h.update({parts:g().parts}),c=K),e==="gears"){let x=W({driverTeeth:i.driverTeeth??16,drivenTeeth:d("teeth",32),rpm:D,angle:s,module:i.module??1.5});h.update({pose:{driverGear:{rotation:x.driverAngle},drivenGear:{rotation:x.drivenAngle}},readout:"\\\\u4E3B\\\\u52A8\\\\u8F6E "+t.formatNumber(x.driverRpm,0)+" rpm \\\\xB7 \\\\u4ECE\\\\u52A8\\\\u8F6E "+t.formatNumber(x.drivenRpm,2)+" rpm \\\\xB7 \\\\u9F7F\\\\u6570\\\\u6BD4 "+t.formatNumber(x.ratio,2)+"\\\\uFF08\\\\u8D1F\\\\u53F7\\\\u8868\\\\u793A\\\\u53CD\\\\u5411\\\\uFF09"})}else if(e==="crank"){let x=X({angle:s,radius:d("radius",20),rod:i.rod??70,z:28});h.update({pose:{crankPin:{at:x.crank},link:{from:x.crank,to:x.piston},piston:{at:[x.position,0,22]},pistonPin:{at:x.piston}},readout:"\\\\u66F2\\\\u67C4\\\\u89D2 "+t.formatNumber((s*180/Math.PI%360+360)%360,1)+"\\\\xB0 \\\\xB7 \\\\u6ED1\\\\u5757\\\\u4F4D\\\\u7F6E "+t.formatNumber(x.position,2)+" \\\\xB7 \\\\u884C\\\\u7A0B "+t.formatNumber(x.stroke,1)+"\\\\uFF08\\\\u793A\\\\u610F\\\\u957F\\\\u5EA6\\\\u5355\\\\u4F4D\\\\uFF09"})}u=w}let N=null,$=()=>{O(0,u,!0),e!=="assembly"&&(d("running",!1)&&!N?N=t.animate(({delta:A,reducedMotion:w,visible:T})=>{T&&!w?O(A,!1,!0):u!==w&&O(0,w,T)}):!d("running",!1)&&N&&(N(),N=null))},P=t.subscribe($);return O(),Object.freeze({...h,destroy(){M||(M=!0,N?.(),P(),h.destroy())}})}return Object.freeze({mount:a,mountDemo:n,gearPair:W,sliderCrank:X,follow:Mt,scenes:Object.freeze({assembly:ft,gears:pt,crank:ht})})}return _t(Tt);})();\\n\';\n\n // lib/visual-audit.js\n function measureVisual(root, nodeId = "", inspectCards = () => []) {\n const issues = [], seen = /* @__PURE__ */ new Set(), coverage = { nodeId, elements: 0, truncated: false, contrastChecked: 0, contrastUncovered: 0 };\n const styleCache = /* @__PURE__ */ new WeakMap(), styleOf = (el2) => {\n let css = styleCache.get(el2);\n if (!css) {\n css = getComputedStyle(el2);\n styleCache.set(el2, css);\n }\n return css;\n };\n const target = (el2) => {\n if (!el2) return void 0;\n const tag = el2.tagName.toLowerCase(), id = el2.id;\n return { selector: id && id.length <= 64 ? "#" + CSS.escape(id) : tag, text: (el2.textContent ?? "").trim().replace(/\\s+/g, " ").slice(0, 120), tag };\n };\n const add = (code, value, el2) => {\n if (issues.length >= 40) return;\n const id = el2?.closest("[data-ui-node]")?.getAttribute("data-ui-node") ?? nodeId;\n const location = target(el2);\n const k2 = id + ":" + code + ":" + (location?.selector ?? "") + ":" + (location?.text ?? "") + ":" + Math.round(value ?? 0);\n if (!seen.has(k2) && issues.length < 40) {\n seen.add(k2);\n issues.push({ code, nodeId: id, ...location ? { target: location } : {}, ...value === void 0 ? {} : { value: Number(value.toFixed(2)) } });\n }\n };\n const color = (s) => {\n let m2 = s.match(/^rgba?\\(([^)]+)\\)/);\n if (m2) {\n const a = m2[1].split(/[\\s,\\/]+/).map(Number);\n return [a[0] / 255, a[1] / 255, a[2] / 255, a[3] ?? 1];\n }\n m2 = s.match(/^color\\(srgb ([^)]+)\\)/);\n if (m2) {\n const a = m2[1].split(/[\\s\\/]+/).map(Number);\n return [a[0], a[1], a[2], a[3] ?? 1];\n }\n return null;\n };\n const luminance = (c) => c.slice(0, 3).map((v2) => v2 <= 0.04045 ? v2 / 12.92 : ((v2 + 0.055) / 1.055) ** 2.4).reduce((s, v2, i) => s + v2 * [0.2126, 0.7152, 0.0722][i], 0);\n const blend = (front, back) => front.slice(0, 3).map((v2, i) => v2 * front[3] + back[i] * (1 - front[3])).concat(1);\n const background = (el2) => {\n const layers = [];\n let n = el2;\n for (let i = 0; n && i < 64; i++, n = n.parentElement) {\n const c = styleOf(n);\n if (c.backgroundImage !== "none") return null;\n const colorValue = color(c.backgroundColor);\n if (!colorValue) return null;\n if (colorValue[3] > 0) layers.push(colorValue);\n if (colorValue[3] === 1) {\n let out = layers.pop();\n while (layers.length) out = blend(layers.pop(), out);\n return out;\n }\n }\n return null;\n };\n let contentBottom = root.getBoundingClientRect().top;\n const widthRoot = root.id === "canvas" ? document.documentElement : root;\n if (widthRoot.scrollWidth > widthRoot.clientWidth + 2) add("overflow", widthRoot.scrollWidth - widthRoot.clientWidth);\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);\n let el;\n while (el = walker.nextNode()) {\n if (coverage.elements >= 2e3) {\n coverage.truncated = true;\n break;\n }\n coverage.elements++;\n if (el.matches("[data-canvas-phase=error]")) add("runtimeError", void 0, el);\n const css = styleOf(el), box = el.getBoundingClientRect();\n if (!box.width || !box.height || css.visibility === "hidden" || css.display === "none") continue;\n const text2 = [...el.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim());\n if (text2) {\n let size = parseFloat(css.fontSize);\n if (el instanceof SVGElement && el.getScreenCTM) {\n const m2 = el.getScreenCTM();\n if (m2) size *= Math.hypot(m2.c, m2.d);\n }\n if (size < 11.9) add("smallText", size, el);\n if (!(el instanceof SVGElement)) {\n const fg = color(css.color), bg = background(el);\n let opacitySafe = true, opacityDepth = 0;\n for (let a2 = el; a2; a2 = a2.parentElement) {\n if (++opacityDepth > 64 || parseFloat(styleOf(a2).opacity) < 1) {\n opacitySafe = false;\n break;\n }\n }\n if (fg && bg && opacitySafe) {\n coverage.contrastChecked++;\n const a2 = luminance(blend(fg, bg)), b2 = luminance(bg), ratio = (Math.max(a2, b2) + 0.05) / (Math.min(a2, b2) + 0.05);\n if (ratio < (size >= 24 || size >= 18.66 && parseFloat(css.fontWeight) >= 700 ? 3 : 4.5)) add("contrast", ratio, el);\n } else coverage.contrastUncovered++;\n const range = document.createRange();\n range.selectNodeContents(el);\n const bounds = range.getBoundingClientRect();\n let a = el, depth = 0;\n while (a && a !== root.parentElement && depth++ < 24) {\n const c = styleOf(a), clip = a.getBoundingClientRect();\n if (["hidden", "clip"].includes(c.overflowX) && (bounds.left < clip.left - 2 || bounds.right > clip.right + 2) || ["hidden", "clip"].includes(c.overflowY) && (bounds.top < clip.top - 2 || bounds.bottom > clip.bottom + 2)) {\n add("clippedText", void 0, el);\n break;\n }\n a = a.parentElement;\n }\n } else {\n coverage.contrastUncovered++;\n if (!el.closest("#stage")) {\n let parent = el.parentElement, backgrounds = [];\n for (let depth = 0; parent instanceof SVGElement && depth < 4; parent = parent.parentElement, depth++) {\n backgrounds = parent.querySelectorAll(":scope > rect");\n if (backgrounds.length) break;\n }\n for (const background2 of backgrounds) {\n const c = styleOf(background2), rect2 = background2.getBoundingClientRect();\n if (c.fill === "none" || parseFloat(c.fillOpacity) === 0 || !parseFloat(background2.getAttribute("rx")) || rect2.width < box.width * 0.5 || rect2.height < box.height * 2) continue;\n const matrix = background2.getScreenCTM(), radius = Math.min(parseFloat(background2.getAttribute("rx")) * (matrix ? Math.hypot(matrix.a, matrix.b) : 1), rect2.height / 2, rect2.width / 2);\n const progress = radius ? Math.max(0, Math.min(1, (box.bottom - (rect2.bottom - radius)) / radius)) : 0, inset = radius * (1 - Math.sqrt(1 - progress * progress));\n const corner = progress > 0 && (box.left < rect2.left + inset - 1 || box.right > rect2.right - inset + 1);\n if (box.left >= rect2.left - 1 && box.left < rect2.right && box.top >= rect2.top && box.top <= rect2.bottom && (box.bottom > rect2.bottom + 1 || corner)) {\n add("cardTextOverflow", Math.max(0, box.bottom - rect2.bottom), el);\n break;\n }\n }\n }\n }\n }\n if (text2 || el.matches("svg,canvas,img,video,input,select,textarea,button")) contentBottom = Math.max(contentBottom, box.bottom);\n if (el.matches("input:not([type=hidden]),select,textarea,button,[role=button]") && !el.getAttribute("aria-label") && !el.getAttribute("aria-labelledby") && !el.labels?.length && !el.textContent.trim() && !el.getAttribute("title")) add("missingLabel", void 0, el);\n }\n for (const issue of inspectCards(root)) add("cardTextOverflow", Math.max(0, issue.excess), issue.target);\n const rect = root.getBoundingClientRect(), gap = rect.bottom - contentBottom;\n if (!coverage.truncated && root.id === "canvas" && rect.height > 320 && gap > Math.max(96, rect.height * 0.25)) add("bottomWhitespace", gap, root);\n Object.defineProperty(issues, "coverage", { value: coverage });\n return issues;\n }\n\n // lib/format-number.js\n function formatNumber(value, decimals = 2) {\n if (typeof value !== "number" || !Number.isFinite(value)) throw new Error("DSH UI: formatNumber requires a finite number");\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 6) throw new Error("DSH UI: formatNumber decimals must be an integer from 0 to 6");\n return value.toLocaleString("en-US", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });\n }\n\n // lib/canvas-system.js\n var CANVAS_SYSTEM_CSS = `\n:root{--canvas-radius:16px;--canvas-gap:16px;--canvas-positive:#167456;--canvas-negative:#b13b3b;--canvas-warning:#875b15}\n:root[data-canvas-scheme=dark]{--canvas-positive:#78d9b4;--canvas-negative:#ffaaaa;--canvas-warning:#edc87e}\n#canvas{display:flow-root}html,body{margin:0;min-width:0;background:var(--canvas-bg,#fff);color:var(--canvas-ink,#182537);font:14px/1.6 system-ui,"Microsoft YaHei",sans-serif}*{box-sizing:border-box}svg{max-width:100%;height:auto}button,input,select,textarea{font:inherit;color:inherit}button,input,select,textarea{border:1px solid var(--canvas-line,#ced4df);border-radius:8px;background:var(--canvas-bg,#fff);padding:8px 12px;max-width:100%}button{cursor:pointer}button:disabled{cursor:default;opacity:.55}input[type=range]{padding:0;accent-color:var(--canvas-accent,#3e60d3)}input[type=checkbox],input[type=radio]{accent-color:var(--canvas-accent,#3e60d3)}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--canvas-accent,#3e60d3);outline-offset:3px}\n.ui-stack{display:grid;gap:var(--canvas-gap)}.ui-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr));gap:var(--canvas-gap)}.ui-surface{padding:20px;border:1px solid var(--canvas-line,#ced4df);border-radius:var(--canvas-radius);background:var(--canvas-soft,#f3f5f8)}.ui-title{margin:0;font-size:clamp(20px,3vw,28px);line-height:1.3;letter-spacing:-.02em}.ui-caption{color:var(--canvas-muted,#526176);margin:8px 0;font-size:14px}.ui-value{font-size:clamp(24px,4vw,36px);font-variant-numeric:tabular-nums;line-height:1.2}.ui-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap}.ui-field{display:grid;gap:6px;min-width:0}.ui-legend{display:flex;gap:16px;flex-wrap:wrap;font-size:13px}.ui-status{min-height:1.6em}.ui-error{color:var(--canvas-negative)}.ui-primary{background:var(--canvas-accent,#3e60d3);color:var(--canvas-accent-ink,#fff);border-color:transparent}\nsvg .ui-node{fill:var(--canvas-soft,#f3f5f8);stroke:var(--canvas-line,#ced4df);stroke-width:1}svg .ui-edge{fill:none;stroke:var(--canvas-muted,#526176);stroke-width:1.5}svg .ui-label{fill:var(--canvas-ink,#182537);font:500 14px system-ui,sans-serif}svg .ui-note{fill:var(--canvas-muted,#526176);font:400 13px system-ui,sans-serif}svg .ui-leader{fill:none;stroke:var(--canvas-muted,#526176);stroke-dasharray:3 4}svg .ui-accent{fill:color-mix(in srgb,var(--canvas-accent,#3e60d3) 12%,var(--canvas-bg,#fff));stroke:var(--canvas-accent,#3e60d3)}\n.ui-flow{display:flex;align-items:center;justify-content:center;gap:16px;padding:24px 8px;flex-wrap:wrap}.ui-step{display:grid;gap:6px;min-width:130px;max-width:240px;padding:16px 20px;border:1px solid var(--canvas-line);border-radius:6px;background:var(--canvas-bg)}.ui-step strong{font-size:16px;font-weight:600}.ui-step span{font-size:14px;color:var(--canvas-muted)}.ui-arrow{color:var(--canvas-muted);font-size:22px}.ui-callout{border-inline-start:3px solid var(--canvas-accent);padding:8px 16px;color:var(--canvas-ink)}\n.ui-surface,.ui-step{border-radius:var(--canvas-radius);background:var(--canvas-bg,#fff)}button,input:not([type=checkbox]):not([type=radio]):not([type=range]),select,textarea{border-radius:12px}button{border-radius:999px}.ui-primary{background:var(--canvas-ink,#182537);color:var(--canvas-bg,#fff)}.ui-callout{border-radius:0 12px 12px 0;background:color-mix(in srgb,var(--canvas-accent,#3e60d3) 5%,var(--canvas-bg,#fff))}\n@media(max-width:480px){.ui-flow{flex-direction:column;padding:16px 8px;gap:12px}.ui-step{width:100%;max-width:none}.ui-arrow{transform:rotate(90deg)}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation:none!important;transition:none!important}}`;\n\n // lib/timeline.js\n function createTimelineAPI(animate, capture = false, notify = () => {\n }) {\n const timelines = /* @__PURE__ */ new Map();\n function timeline(options) {\n const { id = "main", duration, draw, loop = false, autoplay = true, chapters = [] } = options ?? {};\n if (typeof id !== "string" || !/^[A-Za-z_][\\w-]{0,63}$/.test(id) || timelines.has(id)) throw Error("Timeline id must be unique");\n if (!Number.isFinite(duration) || duration <= 0 || duration > 86400 || typeof draw !== "function") throw Error("Timeline requires positive duration and draw(time, info)");\n if (!Array.isArray(chapters) || chapters.length > 100 || chapters.some((c) => !c || typeof c.label !== "string" || !Number.isFinite(c.time) || c.time < 0 || c.time >= duration)) throw Error("Invalid timeline chapters");\n let time = 0, playing = !!autoplay && !capture, disposed = false, reduced = false, visible = true;\n const listeners = /* @__PURE__ */ new Set();\n const state2 = () => ({ id, time, duration, playing, loop: !!loop, reducedMotion: reduced, visible, chapters: chapters.map((c) => ({ time: c.time, label: c.label })) });\n const render = () => {\n draw(time, state2());\n notify(state2());\n for (const fn2 of listeners) fn2(state2());\n };\n const seek = (value) => {\n if (disposed) throw Error("Timeline disposed");\n if (!Number.isFinite(value)) throw Error("Timeline seek requires finite seconds");\n time = Math.max(0, Math.min(duration, value));\n render();\n return state2();\n };\n const api = Object.freeze({ state: state2, seek, play() {\n if (disposed) throw Error("Timeline disposed");\n playing = true;\n render();\n }, pause() {\n playing = false;\n render();\n }, replay() {\n playing = !capture;\n seek(0);\n }, chapter(index) {\n if (!Number.isInteger(index) || !chapters[index]) throw Error("Invalid chapter");\n playing = false;\n return seek(chapters[index].time);\n }, subscribe(fn2) {\n if (typeof fn2 !== "function") throw Error("Timeline listener required");\n listeners.add(fn2);\n fn2(state2());\n return () => listeners.delete(fn2);\n }, dispose() {\n if (disposed) return;\n disposed = true;\n stop();\n listeners.clear();\n timelines.delete(id);\n } });\n timelines.set(id, api);\n const stop = animate((info) => {\n reduced = !!info.reducedMotion;\n visible = info.visible !== false;\n if (!capture && playing && !reduced && visible) {\n const next = time + info.delta;\n time = loop ? next % duration : Math.min(duration, next);\n if (!loop && time === duration) playing = false;\n }\n render();\n });\n return api;\n }\n return { timeline, capture: Object.freeze({ list: () => [...timelines.values()].map((t) => t.state()), seek: (id, time) => {\n const t = timelines.get(id);\n if (!t) throw Error("Timeline not found: " + id);\n t.seek(time);\n t.pause();\n return t.state();\n } }) };\n }\n\n // lib/canvas-controls.js\n function createTimelineControlRepair() {\n const originals = /* @__PURE__ */ new WeakMap();\n const rgb = (text2) => {\n const match = text2.match(/^rgba?\\(([^)]+)\\)$/);\n if (!match) return null;\n const values = match[1].split(/[,\\s/]+/).filter(Boolean).map(Number);\n return values.length >= 3 ? [...values.slice(0, 3), values[3] ?? 1] : null;\n };\n const over = (a, b2) => a.slice(0, 3).map((v2, i) => v2 * a[3] + b2[i] * (1 - a[3]));\n const luminance = (c) => c.slice(0, 3).map((v2) => v2 / 255).map((v2) => v2 <= 0.04045 ? v2 / 12.92 : ((v2 + 0.055) / 1.055) ** 2.4).reduce((n, v2, i) => n + v2 * [0.2126, 0.7152, 0.0722][i], 0);\n const contrast = (a, b2) => {\n const x = luminance(a), y2 = luminance(b2);\n return (Math.max(x, y2) + 0.05) / (Math.min(x, y2) + 0.05);\n };\n return () => {\n const stage = document.getElementById("stage"), root = document.getElementById("canvas");\n if (!stage || !root) return;\n for (const el of root.querySelectorAll("button,output,select,input:not([type=range]):not([type=checkbox]):not([type=radio])")) {\n if (stage.contains(el)) continue;\n let saved = originals.get(el);\n if (saved) for (const [key, value, priority] of saved) value ? el.style.setProperty(key, value, priority) : el.style.removeProperty(key);\n const style = getComputedStyle(el);\n if (style.display === "none" || style.visibility === "hidden") continue;\n const layers = [];\n let uncertain = false;\n for (let parent = el; parent; parent = parent.parentElement) {\n const backgroundStyle = getComputedStyle(parent);\n if (backgroundStyle.backgroundImage !== "none") {\n uncertain = true;\n break;\n }\n const color = rgb(backgroundStyle.backgroundColor);\n if (color) layers.push(color);\n if (color?.[3] === 1) break;\n }\n if (uncertain) continue;\n const background = layers.reverse().reduce((color, layer) => over(layer, color), [255, 255, 255]);\n const foreground = rgb(style.color);\n if (!foreground || contrast(over(foreground, background), background) >= 4.5) continue;\n if (!saved) {\n saved = ["color", "border-color"].map((key) => [key, el.style.getPropertyValue(key), el.style.getPropertyPriority(key)]);\n originals.set(el, saved);\n }\n const light = [248, 250, 252], dark = [17, 24, 39];\n el.style.setProperty("color", contrast(light, background) > contrast(dark, background) ? "#f8fafc" : "#111827", "important");\n const border = rgb(style.borderTopColor);\n if (parseFloat(style.borderTopWidth) > 0 && border && contrast(over(border, background), background) < 1.5) el.style.setProperty("border-color", "#64748b", "important");\n }\n };\n }\n function canvasContentHeight(root) {\n const body = getComputedStyle(document.body);\n return Math.ceil(root.getBoundingClientRect().bottom + window.scrollY + (parseFloat(body.paddingBottom) || 0) + (parseFloat(body.marginBottom) || 0));\n }\n\n // lib/canvas-layout.js\n function inspectTextCards(root, cards) {\n const result = [];\n const cache = /* @__PURE__ */ new WeakMap(), styleOf = (el) => {\n if (!cache.has(el)) cache.set(el, getComputedStyle(el));\n return cache.get(el);\n };\n for (const card of cards ?? [...root.querySelectorAll("article,section,aside,figure,div")].slice(0, 256).reverse()) {\n if (card.closest("#stage,svg,pre,code,[role=img],[data-motion-layout=preserve]")) continue;\n const css = styleOf(card), box = card.getBoundingClientRect();\n const radius = Math.max(parseFloat(css.borderBottomLeftRadius) || 0, parseFloat(css.borderBottomRightRadius) || 0);\n if (box.width < 120 || box.height < 24 || css.display === "none" || css.visibility === "hidden") continue;\n if (/auto|scroll/.test(css.overflowY)) continue;\n if (!radius && css.boxShadow === "none") continue;\n const padding = parseFloat(css.paddingBottom) || 0, border = parseFloat(css.borderBottomWidth) || 0;\n const bottom = box.bottom - padding - border;\n let excess = 0, corner = false, target, flow = !["absolute", "fixed"].includes(css.position) && css.transform === "none" && !/auto|scroll/.test(css.overflowY) && !/size/.test(css.contain) && !css.borderBottomLeftRadius.includes("%") && !css.borderBottomRightRadius.includes("%") && !(css.transitionDuration.split(",").some((v2) => parseFloat(v2) > 0) && /(^|,|\\s)(height|max-height|all)(,|\\s|$)/.test(css.transitionProperty));\n const walker = document.createTreeWalker(card, NodeFilter.SHOW_TEXT);\n let text2, count2 = 0;\n while ((text2 = walker.nextNode()) && ++count2 <= 128) {\n if (!text2.textContent.trim()) continue;\n const el = text2.parentElement;\n if (el.closest("svg,pre,code,script,style,textarea,[role=img]")) continue;\n const style = styleOf(el);\n if (style.visibility === "hidden" || style.display === "none") continue;\n if (style.webkitLineClamp && style.webkitLineClamp !== "none") continue;\n let intentional = false;\n for (let parent = el; parent && parent !== card; parent = parent.parentElement) {\n const c = styleOf(parent);\n if (/auto|scroll/.test(c.overflowY) || c.webkitLineClamp && c.webkitLineClamp !== "none") {\n intentional = true;\n break;\n }\n }\n if (intentional) continue;\n const range = document.createRange();\n range.selectNode(text2);\n for (const rect of range.getClientRects()) {\n if (!rect.width || !rect.height) continue;\n const amount = rect.bottom - bottom;\n const r = Math.min(radius, box.height / 2, box.width / 2);\n const progress = r ? Math.max(0, Math.min(1, (rect.bottom - (box.bottom - r)) / r)) : 0;\n const inset = r * (1 - Math.sqrt(1 - progress * progress));\n const touchesCorner = progress > 0 && (rect.left < box.left + inset - 1 || rect.right > box.right - inset + 1);\n if (amount <= 1 && !touchesCorner) continue;\n target = el;\n excess = Math.max(excess, amount);\n corner ||= touchesCorner;\n for (let parent = el; parent && parent !== card; parent = parent.parentElement) {\n const c = styleOf(parent);\n if (["absolute", "fixed"].includes(c.position) || c.transform !== "none" || /auto|scroll/.test(c.overflowY) || c.webkitLineClamp && c.webkitLineClamp !== "none") flow = false;\n }\n }\n }\n if (target) result.push({ card, target, excess, corner, radius, flow });\n }\n return result;\n }\n function fitTextCards(root, inspect) {\n for (const { card } of inspect(root)) {\n const issue = inspect(root, [card])[0];\n if (!issue?.flow) continue;\n const css = getComputedStyle(card), box = card.getBoundingClientRect();\n if (issue.corner) card.style.setProperty("padding-bottom", Math.max(parseFloat(css.paddingBottom) || 0, Math.min(issue.radius, box.height / 2)) + "px", "important");\n const inset = css.boxSizing === "border-box" ? 0 : ["paddingTop", "paddingBottom", "borderTopWidth", "borderBottomWidth"].reduce((n, key) => n + (parseFloat(css[key]) || 0), 0);\n card.style.setProperty("min-height", Math.max(parseFloat(css.minHeight) || 0, box.height - inset) + "px", "important");\n card.style.setProperty("height", "auto", "important");\n card.style.setProperty("max-height", "none", "important");\n }\n }\n\n // lib/sandbox.js\n var SANDBOX_LIMITS = Object.freeze({ source: 49152, height: 1e3, message: 16384, rate: 30 });\n function canvasSnapshot(node2, state2, data, derived, disabled, theme) {\n const pick = (keys, values) => Object.fromEntries((keys ?? []).map((k2) => [k2, values[k2]]));\n return { state: pick(node2.stateKeys, state2), data: pick(node2.dataKeys, data), derived: pick(node2.derivedKeys, derived), disabled, theme };\n }\n function canvasPatch(message, node2) {\n if (!message || typeof message !== "object" || Array.isArray(message)) throw new Error("Invalid canvas patch");\n const keys = Object.keys(message);\n if (!keys.length || keys.length > 64 || keys.some((k2) => !(node2.stateKeys ?? []).includes(k2))) throw new Error("Canvas state key is not declared");\n if (JSON.stringify(message).length > SANDBOX_LIMITS.message) throw new Error("Canvas patch is too large");\n return message;\n }\n function sandboxDocument(node2, channel2, nonce2) {\n const json = (value) => JSON.stringify(value).replace(/</g, "\\\\u003c").replace(/\\u2028/g, "\\\\u2028").replace(/\\u2029/g, "\\\\u2029");\n return `<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src \'none\'; script-src \'nonce-${nonce2}\'; style-src \'unsafe-inline\'; img-src data:; font-src \'none\'; connect-src \'none\'; media-src \'none\'; object-src \'none\'; frame-src \'none\'; worker-src \'none\'; base-uri \'none\'; form-action \'none\'"><meta name="viewport" content="width=device-width,initial-scale=1"><style>${CANVAS_SYSTEM_CSS}</style></head><body><main id="canvas"></main><script nonce="${nonce2}">(()=>{\n const channel=${json(channel2)}, source=${json(canvasSource(node2))};\n let snapshot={state:{},data:{},derived:{},disabled:true,theme:{}}, started=false;\n const listeners=new Set(), send=(type,payload)=>parent.postMessage({dshCanvas:1,channel,type,payload},\'*\');\n const report=e=>send(\'error\',String(e?.message??e).slice(0,1000));\n const repairTimelineControls=(${createTimelineControlRepair.toString()})();\n const inspectCards=${inspectTextCards.toString()}, fitCards=${fitTextCards.toString()};\n const contentHeight=${canvasContentHeight.toString()};\n const repairControls=()=>{if(!window.__DSHMotionRender&&timelineAPI.capture.list().length)repairTimelineControls()};\n for(const type of [\'click\',\'input\',\'change\'])document.addEventListener(type,()=>queueMicrotask(repairControls));\n const audit=${measureVisual.toString()};let auditTimer;const scheduleAudit=()=>{clearTimeout(auditTimer);auditTimer=setTimeout(()=>{repairControls();fitCards(document.getElementById(\'canvas\'),inspectCards);const issues=audit(document.getElementById(\'canvas\'),${json(node2.id ?? "")},inspectCards);send(\'audit\',{issues,coverage:issues.coverage})},400)};\n addEventListener(\'resize\',scheduleAudit);\n addEventListener(\'error\',e=>report(e.error??e.message));addEventListener(\'unhandledrejection\',e=>report(e.reason));\n const animations=new Set(), motion=matchMedia(\'(prefers-reduced-motion: reduce)\');\n let raf=0,last=0,time=0;\n const visible=()=>snapshot.visible!==false&&!document.hidden;\n const canAnimate=()=>visible()&&!snapshot.disabled&&!motion.matches&&!window.__DSHMotionRender;\n const draw=delta=>{for(const fn of animations)try{fn({time,delta,reducedMotion:motion.matches,visible:visible()})}catch(e){animations.delete(fn);report(e)}};\n const tick=t=>{raf=0;if(!canAnimate()||!animations.size){last=0;draw(0);return}const delta=last?Math.min(.05,(t-last)/1000):0;last=t;time+=delta;draw(delta);if(animations.size)raf=requestAnimationFrame(tick)};\n const refresh=()=>{draw(0);if(canAnimate()&&animations.size){if(!raf){last=0;raf=requestAnimationFrame(tick)}}else{cancelAnimationFrame(raf);raf=0;last=0}};\n motion.addEventListener(\'change\',refresh);document.addEventListener(\'visibilitychange\',refresh);\n const formatNumber=${formatNumber.toString()};\n const api={formatNumber,get snapshot(){return structuredClone(snapshot)},subscribe(fn){if(typeof fn!==\'function\')throw Error(\'Listener required\');listeners.add(fn);fn(api.snapshot);return()=>listeners.delete(fn)},setState(patch){if(!snapshot.disabled)send(\'patch\',patch)},animate(fn){if(typeof fn!==\'function\')throw Error(\'Animation callback required\');animations.add(fn);refresh();return()=>{animations.delete(fn);if(!animations.size){cancelAnimationFrame(raf);raf=0;last=0}}}};\n let soundTick=0,soundPlaying,soundTime,soundVisible;const timelineAPI=(${createTimelineAPI.toString()})(api.animate,!!window.__DSHMotionRender,s=>{if(snapshot.motionSound){const now=performance.now();if(now-soundTick>=100||s.playing!==soundPlaying||s.visible!==soundVisible||(!s.playing&&s.time!==soundTime)){soundTick=now;soundPlaying=s.playing;soundTime=s.time;soundVisible=s.visible;send(\'timeline\',s)}}});api.timeline=timelineAPI.timeline;\n Object.defineProperty(window,\'__DSHMotionCapture\',{value:timelineAPI.capture,writable:false});\n ${node2.libraries?.includes("mechanism") ? MECHANISM_RUNTIME.replace(/<\\/script/gi, "<\\\\/script") + ";api.mechanism=__MotionMechanism.createMechanismAPI(api);" : ""}\n Object.defineProperty(window,\'DSHUI\',{value:Object.freeze(api),writable:false});\n for(const type of [\'click\',\'input\',\'change\',\'keydown\',\'pointerdown\'])document.addEventListener(type,e=>{if(snapshot.disabled){e.preventDefault();e.stopImmediatePropagation()}},true);\n addEventListener(\'message\',event=>{\n const m=event.data;if(event.source!==parent||m?.dshCanvas!==1||m.channel!==channel||m.type!==\'snapshot\')return;\n snapshot=m.payload;for(const [k,v] of Object.entries(snapshot.theme??{}))document.documentElement.style.setProperty(\'--canvas-\'+k,v);\n document.documentElement.style.colorScheme=snapshot.theme?.scheme??\'light\';document.documentElement.dataset.canvasScheme=snapshot.theme?.scheme??\'light\';\n const wasStarted=started;\n if(!started){started=true;document.getElementById(\'canvas\').innerHTML=source.html;const style=document.createElement(\'style\');style.textContent=source.css;document.head.append(style);const script=document.createElement(\'script\');script.nonce=${json(nonce2)};script.textContent=source.script;document.body.append(script)}\n if(wasStarted)for(const fn of listeners)try{fn(api.snapshot)}catch(e){report(e)}\n fitCards(document.getElementById(\'canvas\'),inspectCards);repairControls();refresh();if(!wasStarted)send(\'mounted\');scheduleAudit();\n });\n let resizePending=false;new ResizeObserver(()=>{if(!started||resizePending)return;resizePending=true;requestAnimationFrame(()=>{resizePending=false;send(\'height\',contentHeight(document.getElementById(\'canvas\')))})}).observe(document.getElementById(\'canvas\'));\n send(\'ready\');\n})();<\\/script></body></html>`;\n }\n\n // lib/components.js\n var define = (fields2, purpose, presentation = "") => Object.freeze({ fields: Object.freeze(fields2), purpose, presentation });\n var COMPONENTS = Object.freeze({\n visual: define(["spec", "stateKey", "warnings"], "Extended native charts, tables, plots, quiz, forms, diagrams, media and 3D"),\n heading: define(["text", "spans", "size", "weight", "color", "align", "lineHeight"], "Section heading", "tone"),\n text: define(["text", "spans", "size", "weight", "color", "align", "lineHeight", "copyable", "title"], "Readable explanation; copyable:true adds a reusable text panel", "tone"),\n code: define(["code", "lang", "title", "wrap"], "Literal copyable code; displayed only, never executed"),\n callout: define(["text", "spans", "size", "weight", "color", "align", "lineHeight"], "A short emphasized paragraph", "tone"),\n row: define(["children", "columns", "gap"], "Wrapping parallel content"),\n column: define(["children", "gap"], "Ordered vertical content"),\n card: define(["title", "children", "surface"], "Meaningful grouped section", "tone"),\n details: define(["title", "children", "open"], "Collapsible supporting content", "tone"),\n badge: define(["text"], "Short explicit status label", "tone"),\n progress: define(["label", "value", "max", "unit"], "Declared numeric progress snapshot", "tone"),\n steps: define(["title", "items"], "Ordered declared steps with an optional heading"),\n metric: define(["label", "value", "unit", "decimals"], "Number with units, or a literal/bound status string", "tone"),\n input: define(["label", "bind"], "String or numeric state input"),\n slider: define(["label", "bind"], "Numeric state control"),\n select: define(["label", "bind", "variant"], "Selection from declared state options; variant:segmented for 2..8 short options, dropdown otherwise"),\n toggle: define(["label", "bind"], "Boolean state control"),\n button: define(["text", "action", "href", "path", "variant"], "Agent follow-up, web link or host file opener", "icon"),\n link: define(["text", "href", "path", "variant"], "User-clicked webpage or local file button", "icon"),\n divider: define(["label"], "Quiet section divider"),\n table: define(["label", "rows", "columns"], "Supplied or derived values; inline rows or data/derived reference"),\n chart: define(["kind", "rows", "labelKey", "valueKey", "label", "unit", "xScale"], "Bar/line comparison with accessible data"),\n sandbox: define(["title", "html", "css", "script", "fallback", "height", "libraries", "stateKeys", "dataKeys", "derivedKeys"], "Freeform isolated HTML/SVG/CSS/JavaScript visualization")\n });\n function componentFields(type) {\n const c = Object.hasOwn(COMPONENTS, type) ? COMPONENTS[type] : void 0;\n return c && ["id", "type", ...c.fields, ...c.presentation ? ["icon"] : [], ...c.presentation === "tone" ? ["tone"] : []];\n }\n\n // lib/identifiers.js\n var IDENTIFIER_SOURCE = "[\\\\p{L}_][\\\\p{L}\\\\p{M}\\\\p{N}_]{0,63}";\n var pattern = new RegExp(`^${IDENTIFIER_SOURCE}$`, "u");\n var validIdentifier = (value) => typeof value === "string" && pattern.test(value) && !["constructor", "prototype", "__proto__"].includes(value);\n\n // lib/author-expression.js\n function compileExpression(source) {\n const fail2 = () => {\n throw new Error("DSH UI: invalid formula; use state.x, data.x, derived.x, item.x, numbers, strings, + - * /, comparisons, ?: and min/max/round/ceil/floor/abs");\n };\n if (typeof source !== "string" || !source.trim() || source.length > 2048) fail2();\n const tokens = [];\n let offset = 0;\n const token2 = new RegExp(String.raw`\\s*(?:(\\d+(?:\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?|("(?:[^"\\\\]|\\\\.)*")|(${IDENTIFIER_SOURCE}(?:\\.${IDENTIFIER_SOURCE})?)|(===|!==|<=|>=|==|!=|[+*/()?,:<>-]))`, "uy");\n while (offset < source.length) {\n if (!source.slice(offset).trim()) break;\n token2.lastIndex = offset;\n const m2 = token2.exec(source);\n if (!m2) fail2();\n offset = token2.lastIndex;\n tokens.push(m2[1] ? { number: Number(m2[1] + (m2[2] ?? "")) } : m2[3] ? { string: JSON.parse(m2[3]) } : m2[4] ?? m2[5]);\n if (tokens.length > 256) fail2();\n }\n let pos = 0;\n const operators = { "==": ["eq", 1], "===": ["eq", 1], "!=": ["neq", 1], "!==": ["neq", 1], "<": ["lt", 2], "<=": ["lte", 2], ">": ["gt", 2], ">=": ["gte", 2], "+": ["add", 3], "-": ["sub", 3], "*": ["mul", 4], "/": ["div", 4] };\n const take = (t) => {\n if (tokens[pos++] !== t) fail2();\n };\n function parse(min = 0, depth = 0) {\n if (depth > 12) fail2();\n const t = tokens[pos++];\n let out;\n if (t && typeof t === "object") out = { const: Object.hasOwn(t, "number") ? t.number : t.string };\n else if (t === "true" || t === "false") out = { const: t === "true" };\n else if (t === "(") {\n out = parse(0, depth + 1);\n take(")");\n } else if (t === "-" || t === "+") {\n const arg = parse(5, depth + 1);\n out = t === "-" ? { op: "sub", args: [{ const: 0 }, arg] } : arg;\n } else if (typeof t === "string" && t.split(".").length === 2 && ["state", "data", "derived", "item"].includes(t.split(".")[0]) && validIdentifier(t.split(".")[1])) out = { ref: t };\n else if (["min", "max", "round", "ceil", "floor", "abs"].includes(t)) {\n take("(");\n const args = [parse(0, depth + 1)];\n while (tokens[pos] === ",") {\n pos++;\n args.push(parse(0, depth + 1));\n if (args.length > 8) fail2();\n }\n take(")");\n out = { op: t, args };\n } else fail2();\n while (typeof tokens[pos] === "string" && Object.hasOwn(operators, tokens[pos]) && operators[tokens[pos]][1] >= min) {\n const [op, precedence] = operators[tokens[pos++]];\n out = { op, args: [out, parse(precedence + 1, depth + 1)] };\n }\n if (min === 0 && tokens[pos] === "?") {\n pos++;\n const yes = parse(0, depth + 1);\n take(":");\n out = { op: "if", args: [out, yes, parse(0, depth + 1)] };\n }\n return out;\n }\n const result = parse();\n if (pos !== tokens.length) fail2();\n return result;\n }\n function expandExpressions(doc2) {\n const expression2 = (e, at2) => {\n if (!e || typeof e !== "object" || Array.isArray(e)) return e;\n if (Object.hasOwn(e, "expr")) {\n if (Object.keys(e).length !== 1) throw new Error("DSH UI: expr must be the only formula field");\n try {\n return compileExpression(e.expr);\n } catch (error) {\n error.message = "DSH UI: " + at2 + ": " + error.message.replace(/^DSH UI: /, "");\n error.path = at2;\n throw error;\n }\n }\n if (Array.isArray(e.args)) e.args = e.args.map((v2, i) => expression2(v2, at2 + ".args[" + i + "]"));\n if (e.map?.fields) for (const k2 of Object.keys(e.map.fields)) e.map.fields[k2] = expression2(e.map.fields[k2], at2 + ".map.fields." + k2);\n return e;\n };\n if (doc2.derived && typeof doc2.derived === "object") for (const k2 of Object.keys(doc2.derived)) doc2.derived[k2] = expression2(doc2.derived[k2], "derived." + k2);\n const walk = (nodes) => {\n if (!Array.isArray(nodes)) return;\n for (const node2 of nodes) {\n if (!node2 || typeof node2 !== "object") continue;\n for (const field of ["text", "value", "max", "rows"]) if (Object.hasOwn(node2, field)) node2[field] = expression2(node2[field], "node." + node2.id + "." + field);\n if (["table", "chart"].includes(node2.type) && Array.isArray(node2.rows)) {\n for (const [rowIndex, row] of node2.rows.entries()) if (row && typeof row === "object" && !Array.isArray(row)) for (const k2 of Object.keys(row)) row[k2] = expression2(row[k2], "node." + node2.id + ".rows[" + rowIndex + "]." + k2);\n }\n walk(node2.children);\n }\n };\n walk(doc2.nodes);\n return doc2;\n }\n\n // lib/visual-guard.js\n var ne = ["h1", "h2", "h3", "body", "muted", "caption"];\n var te = ["primary", "danger", "success", "ghost"];\n var ie = ["success", "warn", "danger", "accent"];\n var re = ["text", "email", "password", "color"];\n var se = ["info", "success", "warning", "error"];\n var U = ["bars", "line", "donut"];\n var oe = ["line", "area", "scatter"];\n var ae = ["16:9", "4:3", "1:1", "9:16"];\n var ue = ["box", "sphere", "cone", "cylinder", "torus"];\n var le = ["file", "dir"];\n var de = ["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"];\n var ce = ["focal", "backend", "store", "external", "input", "optional", "security"];\n var fe = ["light", "dark", "editorial"];\n var pe = ["solid", "dashed", "accent", "link"];\n var me = ["auto", "orthogonal", "straight"];\n var ge = ["bar", "line", "area", "pie", "scatter", "radar", "gauge", "funnel", "treemap", "sankey", "graph", "heatmap", "bigline", "wordCloud"];\n var tn = ["hero"];\n var ye = ["bar", "ring"];\n var be = ["info", "success", "warning", "danger"];\n var he = ["accent", "success", "warning", "danger"];\n var Ee = ["text", "num", "delta", "bar", "badge", "spark", "ring", "index", "group"];\n var b = (t, i, r = {}, e = {}) => {\n let s = Object.fromEntries(Object.entries(i).filter(([u]) => u !== "type" && !t.includes(u))), n = e.oneOfRequired ?? [], o = e.conditionalRequired ?? [], a = [...n.map((u) => ({ kind: "one-of-required", fields: u })), ...o];\n return { required: t, fields: i, optional: s, aliases: r, valueAliases: e.valueAliases ?? {}, oneOfRequired: n, conditionalRequired: o, rules: a, enums: e.enums ?? {}, nested: e.nested ?? {}, ...e.validator === void 0 ? {} : { validator: e.validator } };\n };\n var G = (t, i, r = {}, e = {}, s = {}) => ({ required: t, fields: i, enums: e, nested: r, aliases: s });\n var h = { type: "string", span: "number", id: "string" };\n var De = G(["label", "value"], { label: "string", value: "number", color: "string" });\n var rn = G(["label", "data"], { label: "string", color: "string", data: "array" }, { data: De });\n var sn = G(["title"], { title: "string", desc: "string" });\n var on = G(["key", "value"], { key: "string", value: "string" }, {}, {}, { label: "key" });\n var an = G(["title"], { title: "string", desc: "string", time: "string" });\n var un = G(["path", "newText"], { path: "string", oldText: "string-or-null", newText: "string" });\n var ln = G(["name", "value"], { name: "string", value: "number", min: "number", max: "number", step: "number", animateTo: "number", durationMs: "number", loop: "boolean" });\n var dn = G(["expr"], { expr: "string", label: "string", color: "string", kind: "string", params: "array" }, { params: ln }, { kind: oe });\n var cn = G(["shape"], { shape: "string", color: "string", position: "array", rotation: "array", scale: "unknown", size: "unknown" }, {}, { shape: ue });\n function Oe(t) {\n return G(["name"], { name: "string", type: "string", children: "array" }, t > 0 ? { children: Oe(t - 1) } : {}, { type: le }, { label: "name" });\n }\n var fn = Oe(6);\n var pn = G(["label", "items"], { label: "string", items: "nodes", content: "nodes" });\n var mn = G(["title", "items"], { title: "string", items: "nodes" });\n var gn = G(["id", "label"], { id: "string", label: "string", sub: "string", type: "string", x: "number", y: "number", w: "number", h: "number", tag: "string" }, {}, { type: ce });\n var yn = G(["from", "to"], { from: "string", to: "string", label: "string", kind: "string", route: "string" }, {}, { kind: pe, route: me });\n var bn = G(["label"], { label: "string", x: "number", y: "number", w: "number", h: "number" });\n var hn = G([], { paper: "string", "paper-2": "string", ink: "string", muted: "string", soft: "string", rule: "string", accent: "string", "accent-tint": "string", link: "string" });\n var V = b(["items"], { title: "string", gap: "number", panel: "boolean", append: "boolean", items: "nodes" });\n var T = { accordion: b(["items"], { ...h, items: "array" }, {}, { nested: { items: mn } }), audio: b(["src"], { ...h, src: "string", alt: "string", loop: "boolean" }, { url: "src", link: "src" }), avatar: b(["name"], { ...h, name: "string", color: "string" }), badge: b(["label"], { ...h, label: "string", tone: "string", icon: "string" }, { text: "label", value: "label" }, { enums: { tone: ie } }), breadcrumb: b(["items"], { ...h, items: "array" }), button: b(["label"], { ...h, label: "string", tone: "string", full: "boolean", small: "boolean", icon: "string", action: "string" }, {}, { enums: { tone: te } }), callout: b(["content"], { ...h, title: "string", content: "string", tone: "string" }, { kind: "tone", text: "content", body: "content", desc: "content" }, { enums: { tone: se }, valueAliases: { tone: { danger: "error", warn: "warning" } } }), card: b(["items"], { ...h, title: "string", items: "nodes", tone: "string", accent: "string" }, { label: "title", content: "items" }, { enums: { tone: be } }), chart: b([], { ...h, kind: "string", data: "array", series: "array", horizontal: "boolean", stacked: "boolean", filter: "string", palette: "array" }, {}, { oneOfRequired: [["data", "series"]], conditionalRequired: [{ kind: "required-if", when: { field: "kind", equals: "donut" }, required: ["data"] }], nested: { data: De, series: rn }, enums: { kind: U }, validator: { name: "chart-renderability" } }), checkbox: b(["label"], { ...h, label: "string", checked: "boolean", action: "string", group: "string" }), code: b(["code"], { ...h, lang: "string", code: "string", title: "string", wrap: "boolean" }, { content: "code", text: "code" }), col: b(["items"], { ...h, items: "nodes", gap: "number" }), copy: b(["text"], { ...h, label: "string", text: "string" }, { content: "text", code: "text", value: "text" }), diagram: b(["kind", "nodes"], { ...h, kind: "string", variant: "string", title: "string", nodes: "array", edges: "array", zones: "array", theme: "object" }, {}, { nested: { nodes: gn, edges: yn, zones: bn, theme: hn }, enums: { kind: de, variant: fe } }), diff: b(["diffs"], { ...h, diffs: "array" }, { items: "diffs", files: "diffs" }, { nested: { diffs: un } }), divider: b([], h), echart: b([], { ...h, title: "string", height: "number", preset: "string", data: "array", series: "array", links: "array", palette: "array", option: "object" }, {}, { oneOfRequired: [["option", "data", "series", "links"]], enums: { preset: ge } }), "file-tree": b(["items"], { ...h, items: "array" }, { nodes: "items" }, { nested: { items: fn } }), grid: b(["items"], { ...h, cols: "number", items: "nodes" }), image: b(["src"], { ...h, src: "string", alt: "string" }, { url: "src", link: "src" }), input: b([], { ...h, label: "string", placeholder: "string", value: "string", inputType: "string", action: "string", id: "string" }, {}, { enums: { inputType: re } }), json: b(["value"], { ...h, value: "unknown" }), keyvalue: b(["pairs"], { ...h, pairs: "array" }, { items: "pairs", rows: "pairs", entries: "pairs" }, { nested: { pairs: on } }), link: b(["label"], { ...h, label: "string", href: "string" }), list: b(["items"], { ...h, items: "array", filter: "string" }), mermaid: b(["code"], { ...h, code: "string" }), svg: b(["code"], { ...h, code: "string", title: "string", height: "number" }), plot: b(["series"], { ...h, series: "array", xMin: "number", xMax: "number", yMin: "number", yMax: "number", title: "string" }, {}, { nested: { series: dn } }), progress: b(["value"], { ...h, value: "number", label: "string", valueLabel: "string", variant: "string", target: "number" }, {}, { enums: { variant: ye } }), quiz: b(["question", "options"], { ...h, question: "string", options: "array", explanation: "string", id: "string", action: "string" }, { title: "question", text: "question", choices: "options", items: "options" }), radio: b(["options"], { ...h, label: "string", options: "array", selected: "number", action: "string", group: "string", answer: "unknown", explanation: "string" }, { items: "options" }), row: b(["items"], { ...h, items: "nodes", wrap: "boolean", spacer: "boolean" }), scene3d: b(["meshes"], { ...h, title: "string", meshes: "array", ambient: "number", background: "string" }, {}, { nested: { meshes: cn } }), select: b(["options"], { ...h, label: "string", options: "array", action: "string", selected: "number", id: "string" }, { items: "options" }), slider: b([], { ...h, label: "string", min: "number", max: "number", step: "number", value: "number", action: "string", id: "string" }), spacer: b([], h), hero: b(["title"], { ...h, title: "string", subtitle: "string", value: "string", label: "string", delta: "string", spark: "array", tone: "string" }, {}, { enums: { tone: he } }), stat: b(["label", "value"], { ...h, label: "string", value: "string", delta: "string", spark: "array", size: "string" }, {}, { enums: { size: tn } }), steps: b(["steps"], { ...h, steps: "array", current: "number" }, { items: "steps" }, { nested: { steps: sn } }), submit: b(["label"], { ...h, label: "string", action: "string", resetAction: "string", groups: "array" }), switch: b(["label"], { ...h, label: "string", checked: "boolean", action: "string" }), table: b(["columns", "rows"], { ...h, columns: "array", rows: "array", types: "array", total: "boolean", details: "array", filter: "string", filterColumn: "number", sortField: "string", export: "boolean" }, { headers: "columns", data: "rows", items: "rows" }), tabs: b(["tabs"], { ...h, tabs: "array" }, {}, { nested: { tabs: pn } }), text: b(["content"], { ...h, content: "string", size: "string", center: "boolean", copyable: "boolean", title: "string" }, { text: "content" }, { enums: { size: ne } }), textarea: b([], { ...h, label: "string", placeholder: "string", rows: "number", value: "string", action: "string", id: "string" }), timeline: b(["items"], { ...h, items: "array" }, {}, { nested: { items: an } }), video: b(["src"], { ...h, src: "string", alt: "string", poster: "string", loop: "boolean", muted: "boolean", aspectRatio: "string" }, { url: "src", link: "src" }, { enums: { aspectRatio: ae } }) };\n var q = new Set(Object.keys(T));\n function N(t) {\n if (typeof t != "object" || t === null) return false;\n let i = t;\n return typeof i.type != "string" || i.type === "" ? false : Array.isArray(i.items) ? q.has(i.type) : true;\n }\n function z(t) {\n if (typeof t != "object" || t === null) return null;\n let i = t;\n if (typeof i.type != "string" || i.type === "") return null;\n let r = q.has(i.type) ? T[i.type] : void 0, e = typeof i.title == "string" && r !== void 0 && !("title" in r.fields) ? i.title : void 0, s = { ...t };\n return e !== void 0 && delete s.title, { items: [s], ...e !== void 0 ? { title: e } : {}, ...i.panel === true ? { panel: true } : {}, ...i.append === true ? { append: true } : {} };\n }\n var m = { 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 };\n function ke(t) {\n let i = t.columns, r = Array.isArray(i) && i.length > 0, e = r && Array.isArray(i) && typeof i[0] == "object" && i[0] !== null ? i.map($n) : i, s = kn(e), n = t.rows !== void 0 ? t.rows : t.data;\n if (Array.isArray(n) && n.length > 0 && typeof n[0] == "object" && n[0] !== null && !Array.isArray(n[0])) {\n let u = Array.isArray(t.columns) && t.columns.length > 0 && typeof t.columns[0] == "object" && t.columns[0] !== null ? t.columns.map(Sn).filter((d) => d !== void 0) : Object.keys(n[0]);\n n = n.map((d) => u.map((c) => wn(d[c])));\n }\n let o = null;\n if (!r && Array.isArray(n) && n.length > 0 && Array.isArray(n[0])) {\n let u = xe(n), d = u.length === 0 ? null : An(u);\n d !== null && xe(d.rows).length === d.rows.length && (o = d, s = d.columns.map((c) => c.slice(0, 128)));\n }\n if (s.length === 0 && !Array.isArray(t.columns)) return null;\n let a = xe(o === null ? n : o.rows);\n return Array.isArray(n) ? { columns: s.slice(0, m.maxTableCols), rows: a } : null;\n }\n function I(t) {\n return ke(t)?.rows ?? [];\n }\n function xn(t, i) {\n return !Array.isArray(t) || !Array.isArray(i) || i[0] !== "group" ? false : String(t[0] ?? "").trim() !== "" && t.slice(1).every((r) => String(r ?? "").trim() === "");\n }\n function C(t, i) {\n let r = I(t);\n return i >= 0 && i < r.length && !xn(r[i], t.types);\n }\n function kn(t) {\n if (!Array.isArray(t)) return [];\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxTableCols) break;\n if (typeof r == "string") i.push(r.slice(0, 128));\n else if (r !== null && typeof r == "object") {\n let e = r, s = typeof e.label == "string" ? e.label : typeof e.value == "string" ? e.value : typeof e.title == "string" ? e.title : JSON.stringify(r);\n i.push(s.slice(0, 128));\n }\n }\n return i;\n }\n function xe(t) {\n if (!Array.isArray(t)) return [];\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxTableRows) break;\n if (!Array.isArray(r)) continue;\n let e = [];\n for (let s of r) {\n if (e.length >= m.maxTableCols) break;\n typeof s == "string" ? e.push(s.slice(0, 256)) : typeof s == "number" && Number.isFinite(s) && e.push(s);\n }\n e.length > 0 && i.push(e);\n }\n return i;\n }\n function An(t) {\n let i = t[0];\n if (i === void 0 || i.length === 0) return null;\n let r = t.slice(1);\n if (r.length === 0) {\n let e = i.map((s) => String(s).trim());\n return e.every((s) => s !== "") ? { columns: e, rows: [] } : null;\n }\n return r.every((e) => e.length === i.length) ? { columns: i.map((e) => String(e).trim()), rows: r } : { columns: Array.from({ length: i.length }, (e, s) => `\\u5217${s + 1}`), rows: t };\n }\n function Sn(t) {\n if (t === null || typeof t != "object" || Array.isArray(t)) return;\n let i = t;\n for (let r of ["key", "dataIndex", "title", "label"]) if (typeof i[r] == "string" && i[r] !== "") return i[r];\n }\n function wn(t) {\n return typeof t == "string" || typeof t == "number" && Number.isFinite(t) ? t : t == null ? "" : JSON.stringify(t);\n }\n function $n(t) {\n if (t === null || typeof t != "object" || Array.isArray(t)) return String(t);\n let i = t;\n for (let r of ["title", "label", "key", "dataIndex"]) if (typeof i[r] == "string" && i[r] !== "") return i[r];\n return JSON.stringify(t);\n }\n function O(t) {\n return typeof t == "object" && t !== null && !Array.isArray(t) ? t : void 0;\n }\n function Ae(t) {\n let i = O(t);\n return i !== void 0 && typeof i.type == "string";\n }\n var Gn = ["label", "value", "delta", "spark", "size"];\n var Rn = { label: "title", name: "title", description: "desc", content: "desc", text: "desc", body: "desc", detail: "desc" };\n function Tn(t, i, r) {\n if (t.length === 0) return null;\n let e = [];\n for (let s = 0; s < t.length; s++) {\n let n = t[s], o = O(n);\n if (o === void 0) return null;\n if (Ae(n)) {\n e.push(r(n, `${i}.items[${s}]`));\n continue;\n }\n if (typeof o.label != "string" && typeof o.value != "string") return null;\n let a = { type: "stat" };\n for (let u of Gn) o[u] !== void 0 && (a[u] = o[u]);\n e.push(a);\n }\n return e;\n }\n function Cn(t, i, r, e) {\n let s = T[r];\n if (s === void 0) return t;\n let n = { ...t };\n for (let [o, a] of Object.entries(s.aliases)) {\n if (!(o in n)) continue;\n let u = `${i}.${o}`, d = a in n;\n d || (n[a] = n[o]), delete n[o], e.push({ kind: "alias", path: u, message: d ? `${u} is ignored because canonical field \'${a}\' is present` : `${u} normalized/adopted as \'${a}\'`, type: r, field: o, canonical: a });\n }\n for (let [o, a] of Object.entries(s.valueAliases)) {\n let u = n[o];\n if (typeof u != "string") continue;\n let d = a[u];\n d === void 0 || d === u || (n[o] = d, e.push({ kind: "alias", path: `${i}.${o}`, message: `${i}.${o} \'${u}\' normalized to \'${d}\'`, type: r, field: o, canonical: d }));\n }\n return n;\n }\n function Se(t, i, r, e, s) {\n if (Array.isArray(t)) return t.map((a, u) => Se(a, i, `${r}[${u}]`, e, s));\n let n = O(t);\n if (n === void 0) return t;\n let o = { ...n };\n for (let [a, u] of Object.entries(i.aliases)) !(a in o) || u in o || (o[u] = o[a], delete o[a], s.push({ kind: "alias", path: `${r}.${a}`, message: `${r}.${a} normalized/adopted as \'${u}\'`, type: e, field: a, canonical: u }));\n for (let [a, u] of Object.entries(i.nested)) o[a] !== void 0 && (o[a] = Se(o[a], u, `${r}.${a}`, e, s));\n return o;\n }\n function we(t) {\n if (Array.isArray(t)) return t.map(we);\n let i = O(t);\n if (i === void 0) return t;\n let r = { ...i };\n return r.type === void 0 && Array.isArray(r.children) && (r.type = "dir"), r.children !== void 0 && (r.children = we(r.children)), r;\n }\n function $e(t, i, r) {\n if (!Ae(t)) return t;\n let e = t.type, s = T[e];\n if (s === void 0) return t;\n let n = Cn(t, i, e, r);\n for (let [u, d] of Object.entries(s.nested)) n[u] !== void 0 && (n[u] = Se(n[u], d, `${i}.${u}`, e, r));\n let o = (u, d) => $e(u, d, r), a = (u, d) => Array.isArray(u) ? u.map((c, f) => o(c, `${d}[${f}]`)) : u;\n if (e === "file-tree" && n.items !== void 0 && (n.items = we(n.items)), e === "stat" && Array.isArray(n.items) && n.label === void 0 && n.value === void 0) {\n let u = Tn(n.items, i, o);\n if (u !== null) return r.push({ kind: "alias", path: `${i}.items`, message: `${i}.items normalized into a row of \'stat\' nodes`, type: e, field: "items", canonical: "row" }), { type: "row", items: u, ...n.span !== void 0 ? { span: n.span } : {} };\n }\n if (e === "row" || e === "col" || e === "grid" || e === "card" || e === "file-tree" || e === "timeline" || e === "breadcrumb") e !== "file-tree" && e !== "timeline" && e !== "breadcrumb" && (n.items = a(n.items, `${i}.items`));\n else if (e === "list" && Array.isArray(n.items)) n.items = n.items.map((u, d) => {\n if (Ae(u)) return o(u, `${i}.items[${d}]`);\n if (Array.isArray(u) && u.length === 1 && typeof u[0] == "string") return u[0];\n let c = O(u);\n if (c === void 0) return u;\n let f = { ...c }, g = `${i}.items[${d}]`;\n for (let [x, $] of Object.entries(Rn)) {\n if (!(x in f)) continue;\n let J = $ in f;\n J || (f[$] = f[x]), delete f[x], r.push({ kind: "alias", path: `${g}.${x}`, type: e, field: x, canonical: $, message: J ? `${g}.${x} is ignored because canonical field \'${$}\' is present` : `${g}.${x} normalized/adopted as \'${$}\'` });\n }\n return !("title" in f) && typeof f.desc == "string" && (f.title = f.desc, delete f.desc, r.push({ kind: "alias", path: `${g}.desc`, type: e, field: "desc", canonical: "title", message: `${g}.desc normalized/adopted as \'title\'` })), f;\n });\n else if (e === "keyvalue" && Array.isArray(n.pairs)) n.pairs.length > 0 && n.pairs.every((u) => Array.isArray(u)) && (n.pairs = n.pairs.map((u) => {\n let d = u;\n return { key: d[0], value: d.length > 1 ? d[1] : "" };\n }));\n else if (e === "tabs" && Array.isArray(n.tabs)) n.tabs = n.tabs.map((u, d) => {\n let c = O(u);\n if (c === void 0) return u;\n let f = { ...c };\n if ("content" in f) {\n let g = `${i}.tabs[${d}].content`, x = "items" in f;\n x || (f.items = f.content), delete f.content, r.push({ kind: "alias", path: g, message: x ? `${g} is ignored because canonical field \'items\' is present` : `${g} normalized/adopted as \'items\'`, type: e, field: "content", canonical: "items" });\n }\n return f.items = Array.isArray(f.items) ? f.items.map((g, x) => o(g, `${i}.tabs[${d}].items[${x}]`)) : f.items === void 0 ? [] : [o(f.items, `${i}.tabs[${d}].items[0]`)], f;\n });\n else if (e === "accordion" && Array.isArray(n.items)) n.items = n.items.map((u, d) => {\n let c = O(u);\n return c === void 0 ? u : { ...c, items: Array.isArray(c.items) ? c.items.map((f, g) => o(f, `${i}.items[${d}].items[${g}]`)) : c.items };\n });\n else if (e === "table" && Array.isArray(n.details)) {\n let u = { columns: n.columns, rows: n.rows, types: n.types };\n n.details = n.details.map((d, c) => !Array.isArray(d) || !C(u, c) ? d : d.map((f, g) => o(f, `${i}.details[${c}][${g}]`)));\n }\n return n;\n }\n function Ie(t) {\n let i = [];\n if (typeof t == "string") try {\n let s = JSON.parse(t);\n (O(s) !== void 0 || Array.isArray(s)) && (t = s, i.push({ kind: "alias", path: "spec", message: "double-encoded JSON string unwrapped into a spec value" }));\n } catch {\n }\n Array.isArray(t) && t.length > 0 && (t = { items: t }, i.push({ kind: "alias", path: "items", message: "root array normalized into an items envelope" }));\n let r = O(t);\n if (r === void 0) return { value: t, warnings: i };\n let e = { ...r };\n return N(e) ? { value: $e(e, "spec", i), warnings: i } : (Array.isArray(e.items) && (e.items = e.items.map((s, n) => $e(s, `items[${n}]`, i))), { value: e, warnings: i });\n }\n function F(t) {\n return typeof t == "object" && t !== null && !Array.isArray(t) ? t : void 0;\n }\n function _e(t) {\n let i = F(t);\n return i !== void 0 && typeof i.type == "string";\n }\n function Ge(t, i, r) {\n if (!_e(t)) return;\n let e = t.type, s = T[e];\n if (s === void 0) return;\n r(t, i, s);\n let n = (o, a) => Ge(o, a, r);\n if ((e === "row" || e === "col" || e === "grid" || e === "card") && Array.isArray(t.items)) t.items.forEach((o, a) => n(o, `${i}.items[${a}]`));\n else if (e === "list" && Array.isArray(t.items)) t.items.forEach((o, a) => n(o, `${i}.items[${a}]`));\n else if (e === "tabs" && Array.isArray(t.tabs)) t.tabs.forEach((o, a) => {\n let u = F(o);\n u !== void 0 && (Array.isArray(u.items) ? u.items.forEach((d, c) => n(d, `${i}.tabs[${a}].items[${c}]`)) : n(u.items, `${i}.tabs[${a}].items`));\n });\n else if (e === "accordion" && Array.isArray(t.items)) t.items.forEach((o, a) => {\n let u = F(o);\n u?.items !== void 0 && Array.isArray(u.items) && u.items.forEach((d, c) => n(d, `${i}.items[${a}].items[${c}]`));\n });\n else if (e === "table" && Array.isArray(t.details)) {\n let o = { columns: t.columns, rows: t.rows, types: t.types };\n t.details.forEach((a, u) => {\n Array.isArray(a) && C(o, u) && a.forEach((d, c) => n(d, `${i}.details[${u}][${c}]`));\n });\n }\n }\n function B(t, i, r, e) {\n t.push({ kind: "unknown-field", path: `${i}.${r}`, message: `${i}.${r}: unknown field for \'${e}\'`, type: e, field: r });\n }\n function Y(t, i, r, e, s) {\n let n = F(t);\n if (n !== void 0) {\n for (let o of Object.keys(n)) o in r.fields || B(s, i, o, e);\n for (let [o, a] of Object.entries(r.nested)) {\n let u = n[o];\n Array.isArray(u) ? u.forEach((d, c) => Y(d, `${i}.${o}[${c}]`, a, e, s)) : u !== void 0 && Y(u, `${i}.${o}`, a, e, s);\n }\n }\n }\n function Nn(t, i, r, e) {\n for (let [s, n] of Object.entries(r.nested)) {\n let o = t[s];\n Array.isArray(o) ? o.forEach((a, u) => Y(a, `${i}.${s}[${u}]`, n, t.type, e)) : o !== void 0 && Y(o, `${i}.${s}`, n, t.type, e);\n }\n }\n function Pe(t) {\n let i = [], r = F(t);\n if (r === void 0) return i;\n let e = (s, n, o) => {\n for (let a of Object.keys(s)) a === "type" || a in o.fields || B(i, n, a, s.type);\n Nn(s, n, o, i), s.type === "list" && Array.isArray(s.items) && s.items.forEach((a, u) => {\n if (_e(a)) return;\n let d = F(a);\n if (d !== void 0) for (let c of Object.keys(d)) {\n if (c === "title" || c === "desc") continue;\n let f = `${n}.items[${u}]`;\n i.push({ kind: "unknown-field", path: `${f}.${c}`, message: `${f}.${c}: list items render \'title\' and \'desc\' only \\u2014 \'${c}\' is dropped`, type: "list", field: c });\n }\n });\n };\n if (Array.isArray(r.items) && !N(r)) {\n for (let s of Object.keys(r)) s in V.fields || B(i, "spec", s, "spec");\n r.items.forEach((s, n) => Ge(s, `items[${n}]`, e));\n } else if (typeof r.type == "string") Ge(r, "spec", e);\n else for (let s of Object.keys(r)) s in V.fields || B(i, "spec", s, "spec");\n return i;\n }\n function ve(t, i) {\n let r = (s, n, o) => {\n o > m.maxDepth || s.forEach((a, u) => e(a, `${n}[${u}]`, o));\n }, e = (s, n, o) => {\n if (!(o > m.maxDepth) && (i(s, n), !(o >= m.maxDepth))) switch (s.type) {\n case "row":\n case "col":\n case "grid":\n case "card":\n r(s.items, `${n}.items`, o + 1);\n break;\n case "tabs":\n s.tabs.forEach((a, u) => r(a.items, `${n}.tabs[${u}].items`, o + 1));\n break;\n case "accordion":\n s.items.forEach((a, u) => r(a.items, `${n}.items[${u}].items`, o + 1));\n break;\n case "list":\n s.items.forEach((a, u) => {\n a !== null && typeof a == "object" && "type" in a && e(a, `${n}.items[${u}]`, o + 1);\n });\n break;\n case "table":\n s.details?.slice(0, I(s).length).forEach((a, u) => {\n a !== null && C(s, u) && r(a, `${n}.details[${u}]`, o + 1);\n });\n break;\n }\n };\n r(t.items, "items", 0);\n }\n function Re(t) {\n let i = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), e = [], s = [];\n ve(t, (n, o) => {\n if (n.type === "submit") {\n n.groups !== void 0 && s.push({ groups: n.groups, path: o });\n return;\n }\n let a, u;\n switch (n.type) {\n case "radio":\n if (n.group === void 0) return;\n a = { kind: "radio", key: n.group, label: n.label ?? n.group, options: n.options.slice(0, m.maxOptions), ...n.answer === void 0 ? {} : { answer: n.answer }, ...n.explanation === void 0 ? {} : { explanation: n.explanation } }, u = `${o}.group`;\n break;\n case "checkbox":\n if (n.group === void 0) return;\n a = { kind: "checkbox", key: n.group }, u = `${o}.group`;\n break;\n case "input":\n case "textarea":\n case "select":\n case "slider":\n if (n.id === void 0) return;\n a = { kind: "field", key: n.id, fieldType: n.type, secret: n.type === "input" && n.inputType === "password" }, u = `${o}.id`;\n break;\n default:\n return;\n }\n if (a === void 0) return;\n let d = i.get(a.key);\n if (d !== void 0) {\n (d.kind !== "checkbox" || a.kind !== "checkbox") && e.push(`${u} conflicts with ${r.get(a.key)}: submission key \'${a.key}\' is already used`);\n return;\n }\n i.set(a.key, a), r.set(a.key, u);\n });\n for (let { groups: n, path: o } of s) {\n let a = /* @__PURE__ */ new Set();\n n.forEach((u, d) => {\n let c = `${o}.groups[${d}]`;\n a.has(u) && e.push(`${c}: duplicate submission member \'${u}\'`), a.add(u);\n let f = i.get(u);\n f === void 0 ? e.push(`${c}: submit.groups references unknown submission member \'${u}\'`) : f.kind === "field" && f.secret && e.push(`${c}: submit.groups cannot require secret field \'${u}\'`);\n });\n }\n return { registry: { members: i }, diagnostics: e };\n }\n function En(t, i) {\n return typeof t == "string" && i.includes(t);\n }\n function p(t, i) {\n return typeof t == "string" ? t.slice(0, i) : void 0;\n }\n var Dn = /^(?:#[\\da-fA-F]{3,8}|rgba?\\([^)]{0,64}\\)|hsla?\\([^)]{0,64}\\)|var\\(--dsw-[\\w-]+(?:,\\s*#[0-9a-fA-F]{3,8})?\\))$/;\n function E(t) {\n if (typeof t != "string") return;\n let i = t.trim();\n return i.length <= 64 && Dn.test(i) ? i : void 0;\n }\n function qe(t) {\n if (typeof t != "string") return;\n let i = t.trim();\n if (!(i.length > 2048)) return /^https?:\\/\\//i.test(i) || /^mailto:[^@\\s]+@[^@\\s]+$/i.test(i) ? i : void 0;\n }\n function K(t) {\n if (typeof t != "string") return;\n let i = t.trim();\n if (!(i === "" || i.length > 2048)) {\n if (/^https?:\\/\\//i.test(i)) return i;\n if (!(/^[a-z][a-z0-9+.-]*:/i.test(i) || /^[/\\\\]{2}/.test(i))) return i;\n }\n }\n function k(t, i, r) {\n return typeof t == "number" && Number.isFinite(t) ? Math.min(r, Math.max(i, t)) : void 0;\n }\n function D(t, i, r) {\n return typeof t == "number" && Number.isFinite(t) ? Math.min(r, Math.max(i, Math.trunc(t))) : void 0;\n }\n function w(t, i) {\n return En(t, i) ? t : void 0;\n }\n function y(t) {\n return typeof t == "object" && t !== null && !Array.isArray(t) ? t : void 0;\n }\n function l(t, i) {\n return i === void 0 ? {} : { [t]: i };\n }\n function On(t) {\n if (t.length > 2048) return;\n let i = t.indexOf("#"), r = i < 0 ? t : t.slice(0, i);\n if (r.includes("?")) return;\n let e;\n try {\n e = decodeURIComponent(r);\n } catch {\n return;\n }\n if (e === "" || /[\\u0000-\\u001f\\u007f]/.test(e) || /^[\\\\/]{2}/.test(e) || /^[a-z][a-z\\d+.-]*:/i.test(e) && !/^[a-z]:[\\\\/]/i.test(e)) return;\n if (i < 0) return { path: e };\n let s = /^L([1-9]\\d*)(?:-L([1-9]\\d*))?$/.exec(t.slice(i + 1));\n if (s === null) return;\n let n = Number(s[1]), o = s[2] === void 0 ? n : Number(s[2]);\n if (!(!Number.isSafeInteger(n) || !Number.isSafeInteger(o) || o < n)) return { path: e, line: n };\n }\n function ze(t) {\n let i = qe(t);\n if (i !== void 0) return { type: "external", href: i };\n if (typeof t != "string") return { type: "invalid" };\n let r = On(t.trim());\n return r === void 0 ? { type: "invalid" } : { type: "file", file: r };\n }\n function H(t, i) {\n switch (i) {\n case "string":\n return typeof t == "string";\n case "string-or-null":\n return t === null || typeof t == "string";\n case "number":\n return typeof t == "number" && Number.isFinite(t);\n case "boolean":\n return typeof t == "boolean";\n case "nodes":\n return Array.isArray(t);\n case "array":\n return Array.isArray(t);\n case "object":\n return y(t) !== void 0;\n case "unknown":\n return true;\n }\n }\n function j(t) {\n switch (t) {\n case "string-or-null":\n return "a string or null";\n case "number":\n return "a finite number";\n case "boolean":\n return "a boolean";\n case "nodes":\n case "array":\n return "an array";\n case "object":\n return "an object";\n case "unknown":\n return "a value";\n default:\n return "a string";\n }\n }\n function v(t, i, r) {\n return t.some((e) => e.startsWith(`${i}.${r} `) || e.includes(`\'${r}\'`) || e.includes(`requires ${r}`));\n }\n function Ke(t, i, r, e, s = []) {\n for (let [n, o] of Object.entries(r.fields)) s.includes(n) || t[n] === void 0 || !H(t[n], o) && !v(e, i, n) && e.push(`${i}.${n} must be ${j(o)}`);\n for (let [n, o] of Object.entries(r.enums)) s.includes(n) || t[n] === void 0 || !H(t[n], "string") || !o.includes(t[n]) && !v(e, i, n) && e.push(`${i}.${n} must be one of ${o.join(", ")}`);\n }\n function W(t, i, r, e) {\n let s = y(t);\n if (s === void 0) {\n e.push(`${i} must be an object`);\n return;\n }\n for (let n of r.required) {\n let o = r.fields[n];\n s[n] === void 0 ? v(e, i, n) || e.push(`${i}: requires ${n}${o === void 0 ? "" : ` (${j(o)})`}`) : o !== void 0 && !H(s[n], o) && (v(e, i, n) || e.push(`${i}.${n} must be ${j(o)}`));\n }\n for (let [n, o] of Object.entries(r.fields)) s[n] !== void 0 && !H(s[n], o) && (v(e, i, n) || e.push(`${i}.${n} must be ${j(o)}`));\n for (let [n, o] of Object.entries(r.enums)) s[n] !== void 0 && typeof s[n] == "string" && !o.includes(s[n]) && (v(e, i, n) || e.push(`${i}.${n} must be one of ${o.join(", ")}`));\n for (let [n, o] of Object.entries(r.nested)) {\n let a = s[n];\n a !== void 0 && (Array.isArray(a) ? a.forEach((u, d) => W(u, `${i}.${n}[${d}]`, o, e)) : W(a, `${i}.${n}`, o, e));\n }\n }\n function Mn(t, i, r, e) {\n for (let [s, n] of Object.entries(r.nested)) {\n let o = t[s];\n o !== void 0 && (Array.isArray(o) ? o.forEach((a, u) => W(a, `${i}.${s}[${u}]`, n, e)) : W(o, `${i}.${s}`, n, e));\n }\n }\n function He(t) {\n let i = t.rows !== void 0 ? t.rows : t.data;\n return !Array.isArray(i) || i.length === 0 ? false : Array.isArray(i[0]);\n }\n function In(t, i, r, e) {\n let s = String(t.type), n = (a) => v(e, i, a), o = s === "table" && He(t) ? "columns" : null;\n for (let a of r.required) {\n let u = r.fields[a];\n if (u === void 0 || t[a] === void 0) {\n a !== o && !n(a) && e.push(`${i}: type \'${s}\' requires ${a}${u === void 0 ? "" : ` (${j(u)})`}`);\n continue;\n }\n !H(t[a], u) && !n(a) && e.push(`${i}.${a} must be ${j(u)}`);\n }\n Ke(t, i, r, e, ["type"]);\n for (let a of r.oneOfRequired) !a.some((u) => t[u] !== void 0) && !e.some((u) => u.includes(`requires ${a.join(" or ")}`)) && e.push(`${i}: type \'${s}\' requires one of ${a.join(" or ")}`);\n for (let a of r.conditionalRequired) if (t[a.when.field] === a.when.equals) for (let u of a.required) t[u] === void 0 && !n(u) && e.push(`${i}: type \'${s}\' requires ${u}${a.message === void 0 ? "" : ` (${a.message})`}`);\n Mn(t, i, r, e);\n }\n function _(t, i, r) {\n if (!Array.isArray(t)) return [];\n let e = [];\n for (let s of t) {\n if (i.remaining <= 0) break;\n i.remaining -= 1;\n let n = Je(s, i, r);\n n !== null && e.push(n);\n }\n return e;\n }\n function Fe(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t.slice(0, 12)) {\n let e = E(r);\n e !== void 0 && i.push(e);\n }\n return i.length > 0 ? i : void 0;\n }\n function je(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t.slice(0, 60)) {\n let e = typeof r == "number" ? r : Number(r);\n if (!Number.isFinite(e)) return;\n i.push(e);\n }\n return i.length >= 2 ? i : void 0;\n }\n function Je(t, i, r) {\n let e = _n(t, i, r);\n if (e === null) return null;\n let s = D(y(t)?.span, 2, 12), n = p(y(t)?.id, 64);\n return { ...e, ...l("span", s), ...l("id", n) };\n }\n function _n(t, i, r) {\n if (r > m.maxDepth) return null;\n let e = y(t);\n if (e === void 0) return null;\n let s = e.type;\n if (typeof s != "string") return null;\n switch (s) {\n case "text": {\n let n = p(e.content, m.maxString) ?? p(e.text, m.maxString);\n return n === void 0 ? null : { type: "text", content: n, ...l("copyable", e.copyable === true ? true : void 0), ...l("title", p(e.title, m.maxString)), ...l("size", w(e.size, ne)), ...l("center", e.center === true ? true : void 0) };\n }\n case "row":\n return { type: "row", items: _(e.items, i, r + 1), ...l("wrap", e.wrap === true ? true : void 0), ...l("spacer", e.spacer === true ? true : void 0) };\n case "col":\n return { type: "col", items: _(e.items, i, r + 1), ...l("gap", k(e.gap, 0, 96)) };\n case "grid":\n return { type: "grid", cols: D(e.cols, 1, m.maxGridCols) ?? 1, items: _(e.items, i, r + 1) };\n case "card":\n return { type: "card", items: _(e.items, i, r + 1), ...l("title", p(e.title, m.maxString)), ...l("tone", w(e.tone, be)), ...l("accent", E(e.accent)) };\n case "button": {\n let n = p(e.label, m.maxString);\n return n === void 0 ? null : { type: "button", label: n, ...l("tone", w(e.tone, te)), ...l("full", e.full === true ? true : void 0), ...l("small", e.small === true ? true : void 0), ...l("icon", p(e.icon, 64)), ...l("action", p(e.action, 200)) };\n }\n case "input":\n return { type: "input", ...l("label", p(e.label, m.maxString)), ...l("placeholder", p(e.placeholder, m.maxString)), ...l("value", p(e.value, m.maxString)), ...l("inputType", w(e.inputType, re)), ...l("action", p(e.action, 200)), ...l("id", p(e.id, 200)) };\n case "select": {\n let n = Q(e.options, m.maxOptions, m.maxString);\n return n === void 0 ? null : { type: "select", options: n, ...l("label", p(e.label, m.maxString)), ...l("action", p(e.action, 200)), ...l("selected", D(e.selected, 0, n.length - 1)), ...l("id", p(e.id, 200)) };\n }\n case "checkbox": {\n let n = p(e.label, m.maxString);\n return n === void 0 ? null : { type: "checkbox", label: n, ...l("checked", e.checked === true ? true : void 0), ...l("action", p(e.action, 200)), ...l("group", p(e.group, 200)) };\n }\n case "link": {\n let n = p(e.label, m.maxString);\n if (n === void 0) return null;\n let o = ze(e.href), a = o.type === "external" ? o.href : o.type === "file" ? String(e.href).trim() : void 0;\n return { type: "link", label: n, ...l("href", a) };\n }\n case "image": {\n let n = K(e.src);\n return n === void 0 ? null : { type: "image", src: n, ...l("alt", p(e.alt, m.maxString)) };\n }\n case "audio": {\n let n = K(e.src);\n return n === void 0 ? null : { type: "audio", src: n, ...l("alt", p(e.alt, m.maxString)), ...l("loop", e.loop === true ? true : void 0) };\n }\n case "video": {\n let n = K(e.src);\n return n === void 0 ? null : { type: "video", src: n, ...l("alt", p(e.alt, m.maxString)), ...l("poster", K(e.poster)), ...l("loop", e.loop === true ? true : void 0), ...l("muted", e.muted === true ? true : void 0), ...l("aspectRatio", w(e.aspectRatio, ae)) };\n }\n case "badge": {\n let n = p(e.label, m.maxString) ?? p(e.text, m.maxString) ?? p(e.value, m.maxString);\n return n === void 0 ? null : { type: "badge", label: n, ...l("tone", w(e.tone, ie)), ...l("icon", p(e.icon, 64)) };\n }\n case "hero": {\n let n = p(e.title, m.maxString);\n return n === void 0 ? null : { type: "hero", title: n, ...l("subtitle", p(e.subtitle, m.maxString)), ...l("value", p(e.value, 128)), ...l("label", p(e.label, m.maxString)), ...l("delta", p(e.delta, 64)), ...l("spark", je(e.spark)), ...l("tone", w(e.tone, he)) };\n }\n case "stat": {\n let n = p(e.label, m.maxString), o = p(e.value, 128);\n return n === void 0 || o === void 0 ? null : { type: "stat", label: n, value: o, ...l("delta", p(e.delta, 64)), ...l("spark", je(e.spark)), ...l("size", e.size === "hero" ? "hero" : void 0) };\n }\n case "progress": {\n let n = k(e.value, 0, 100);\n return n === void 0 ? null : { type: "progress", value: n, ...l("label", p(e.label, m.maxString)), ...l("valueLabel", p(e.valueLabel, 64)), ...l("variant", w(e.variant, ye)), ...l("target", k(e.target, 0, 100)) };\n }\n case "divider":\n return { type: "divider" };\n case "spacer":\n return { type: "spacer" };\n case "avatar": {\n let n = p(e.name, 64);\n return n === void 0 ? null : { type: "avatar", name: n, ...l("color", E(e.color)) };\n }\n case "list": {\n let n = Pn(e.items, m.maxListItems, i, r + 1);\n return n === void 0 ? null : { type: "list", items: n, ...l("filter", p(e.filter, 64)) };\n }\n case "table": {\n let n = ke(e);\n if (n === null) return null;\n let { columns: o, rows: a } = n, u = Array.isArray(e.types) ? e.types : void 0, d = u === void 0 ? void 0 : o.map((g, x) => {\n let $ = u[x];\n return typeof $ == "string" && Ee.includes($) ? $ : "text";\n }), c = Array.isArray(e.details) ? e.details : void 0, f = c === void 0 ? void 0 : a.map((g, x) => {\n if (!C({ columns: o, rows: a, types: d }, x)) return null;\n let $ = _(c[x], i, r + 1);\n return $.length === 0 ? null : $;\n });\n return { type: "table", columns: o, rows: a, ...l("types", d), ...l("total", e.total === true ? true : void 0), ...l("export", e.export === true ? true : void 0), ...l("filter", p(e.filter, 64)), ...l("filterColumn", D(e.filterColumn, 0, m.maxTableCols - 1)), ...l("sortField", p(e.sortField, 64)), ...l("details", f !== void 0 && f.some((g) => g !== null) ? f : void 0) };\n }\n case "chart": {\n let n = Te(e.data, m.maxChartPoints), o = Array.isArray(e.series) ? Le(e.series, m.maxPlotSeries, m.maxChartPoints) : void 0;\n return n === void 0 && o === void 0 ? null : { type: "chart", data: n ?? [], ...l("kind", w(e.kind, U)), ...l("series", o), ...l("horizontal", e.horizontal === true ? true : void 0), ...l("stacked", e.stacked === true ? true : void 0), ...l("filter", p(e.filter, 64)), ...l("palette", Fe(e.palette)) };\n }\n case "tabs": {\n let n = vn(e.tabs, i, r);\n return n === void 0 ? null : { type: "tabs", tabs: n };\n }\n case "plot": {\n let n = qn(e.series, m.maxPlotSeries);\n return n === void 0 ? null : { type: "plot", series: n, ...l("xMin", k(e.xMin, -1e6, 1e6)), ...l("xMax", k(e.xMax, -1e6, 1e6)), ...l("yMin", k(e.yMin, -1e9, 1e9)), ...l("yMax", k(e.yMax, -1e9, 1e9)), ...l("title", p(e.title, m.maxString)) };\n }\n case "callout": {\n let n = p(e.content, m.maxString);\n return n === void 0 ? null : { type: "callout", content: n, ...l("tone", w(e.tone, se)), ...l("title", p(e.title, m.maxString)) };\n }\n case "steps": {\n let n = zn(e.steps);\n return n === void 0 ? null : { type: "steps", steps: n, ...l("current", D(e.current, 0, n.length)) };\n }\n case "keyvalue": {\n let n = Fn(e.pairs, m.maxKeyValuePairs);\n return n === void 0 ? null : { type: "keyvalue", pairs: n };\n }\n case "diff": {\n let n = jn(e.diffs);\n return n === void 0 ? null : { type: "diff", diffs: n };\n }\n case "json":\n return "value" in e ? { type: "json", value: e.value } : null;\n case "code": {\n let n = p(e.code, m.maxCode);\n return n === void 0 ? null : { type: "code", code: n, ...l("lang", p(e.lang, 64)), ...l("title", p(e.title, m.maxString)), ...l("wrap", e.wrap === true ? true : void 0) };\n }\n case "radio": {\n let n = Q(e.options, m.maxOptions, m.maxString);\n return n === void 0 ? null : { type: "radio", options: n, ...l("label", p(e.label, m.maxString)), ...l("selected", D(e.selected, 0, n.length - 1)), ...l("action", p(e.action, 200)), ...l("group", p(e.group, 200)), ...l("answer", typeof e.answer == "number" && Number.isFinite(e.answer) && e.answer >= 0 && e.answer < n.length ? Math.trunc(e.answer) : typeof e.answer == "string" ? e.answer.slice(0, 512) : void 0), ...l("explanation", p(e.explanation, m.maxString)) };\n }\n case "submit": {\n let n = p(e.label, m.maxString), o = p(e.action, 200);\n return n === void 0 ? null : { type: "submit", label: n, ...l("action", o), ...l("resetAction", p(e.resetAction, 200)), ...l("groups", Q(e.groups, m.maxOptions, 200)) };\n }\n case "switch": {\n let n = p(e.label, m.maxString);\n return n === void 0 ? null : { type: "switch", label: n, ...l("checked", e.checked === true ? true : void 0), ...l("action", p(e.action, 200)) };\n }\n case "slider": {\n let n = k(e.min, -1e9, 1e9) ?? 0, o = k(e.max, -1e9, 1e9) ?? 100, a = Math.min(n, o), u = Math.max(n, o), d = k(e.step, 1e-9, Math.max(u - a, 1e-9)), c = k(e.value, a, u) ?? a;\n return { type: "slider", min: a, max: u, ...l("step", d), value: c, ...l("label", p(e.label, m.maxString)), ...l("action", p(e.action, 200)), ...l("id", p(e.id, 200)) };\n }\n case "textarea":\n return { type: "textarea", ...l("label", p(e.label, m.maxString)), ...l("placeholder", p(e.placeholder, m.maxString)), ...l("rows", D(e.rows, 1, 30)), ...l("value", p(e.value, m.maxString)), ...l("action", p(e.action, 200)), ...l("id", p(e.id, 200)) };\n case "accordion": {\n let n = Ln(e.items, i, r);\n return n === void 0 ? null : { type: "accordion", items: n };\n }\n case "copy": {\n let n = p(e.text, m.maxCode);\n return n === void 0 ? null : { type: "copy", text: n, ...l("label", p(e.label, 128)) };\n }\n case "svg": {\n let n = p(e.code, m.maxCode);\n return n === void 0 ? null : { type: "svg", code: n, ...l("title", p(e.title, m.maxString)), ...l("height", D(e.height, 100, 800)) };\n }\n case "mermaid": {\n let n = p(e.code, m.maxMermaid);\n return n === void 0 ? null : { type: "mermaid", code: n };\n }\n case "scene3d": {\n let n = Vn(e.meshes);\n return n === void 0 ? null : { type: "scene3d", meshes: n, ...l("title", p(e.title, m.maxString)), ...l("ambient", k(e.ambient, 0, 2)), ...l("background", E(e.background)) };\n }\n case "diagram":\n return Bn(e);\n case "timeline": {\n let n = Yn(e.items, m.maxTimelineItems);\n return n === void 0 ? null : { type: "timeline", items: n };\n }\n case "file-tree": {\n let n = Qn(e.items, m.maxListItems);\n return n === void 0 ? null : { type: "file-tree", items: n };\n }\n case "breadcrumb": {\n let n = Q(e.items, m.maxBreadcrumbItems, m.maxString);\n return n === void 0 ? null : { type: "breadcrumb", items: n };\n }\n case "quiz": {\n let n = p(e.question, m.maxString), o = Zn(e.options, e.answer);\n return n === void 0 || o === void 0 ? null : { type: "quiz", question: n, options: o, ...l("explanation", p(e.explanation, m.maxString)), ...l("id", p(e.id, 200)), ...l("action", p(e.action, 200)) };\n }\n case "echart": {\n let n = e.data !== void 0 ? Te(e.data, m.maxChartPoints) : void 0, o = e.series !== void 0 && Array.isArray(e.series) ? Le(e.series, m.maxPlotSeries, m.maxChartPoints) : void 0, a = Array.isArray(e.links) ? e.links.slice(0, m.maxChartPoints).flatMap((c) => {\n let f = y(c), g = f === void 0 ? void 0 : p(f.from, 64), x = f === void 0 ? void 0 : p(f.to, 64);\n return g === void 0 || x === void 0 ? [] : [{ from: g, to: x, ...l("value", k(f.value, 0, 1e9)) }];\n }) : void 0, u = e.option !== void 0 ? Ce(e.option, 0, { count: m.maxEChartOptionNodes }) : void 0, d = u === void 0 || typeof u != "object" || u === null || Array.isArray(u) ? void 0 : u;\n return d === void 0 && n === void 0 && o === void 0 && (a === void 0 || a.length === 0) ? null : { type: "echart", ...l("title", p(e.title, m.maxString)), ...l("height", D(e.height, 100, 800)), ...l("preset", w(e.preset, ge)), ...l("data", n), ...l("series", o), ...l("links", a !== void 0 && a.length > 0 ? a : void 0), ...l("palette", Fe(e.palette)), ...l("option", d) };\n }\n default:\n return t;\n }\n }\n function Q(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= i) break;\n if (typeof s == "string") e.push(s.slice(0, r));\n else if (s !== null && typeof s == "object") {\n let n = s, o = typeof n.label == "string" ? n.label : typeof n.value == "string" ? n.value : typeof n.title == "string" ? n.title : JSON.stringify(s);\n e.push(o.slice(0, r));\n }\n }\n return e;\n }\n function Pn(t, i, r, e) {\n if (!Array.isArray(t)) return;\n let s = [];\n for (let n of t) {\n if (s.length >= i) break;\n if (typeof n == "string") {\n s.push(n.slice(0, m.maxString));\n continue;\n }\n let o = y(n);\n if (o !== void 0 && typeof o.type == "string") {\n if (r.remaining <= 0) break;\n r.remaining -= 1;\n let u = Je(o, r, e);\n u !== null && s.push(u);\n continue;\n }\n let a = o === void 0 ? void 0 : p(o.title, m.maxString);\n a !== void 0 && s.push({ title: a, ...l("desc", p(o?.desc, m.maxString)) });\n }\n return s;\n }\n function Te(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.label, 128), o = s === void 0 ? void 0 : k(s.value, -1e12, 1e12);\n n === void 0 || o === void 0 || r.push({ label: n, value: o, ...l("color", s === void 0 ? void 0 : E(s.color)) });\n }\n return r;\n }\n function Le(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= i) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.label, 128), a = n === void 0 ? void 0 : Te(n.data, r);\n o === void 0 || a === void 0 || e.push({ label: o, data: a, ...l("color", n === void 0 ? void 0 : E(n.color)) });\n }\n return e;\n }\n function vn(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= m.maxTabs) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.label, 128);\n if (o === void 0 || n === void 0) continue;\n let a = n.items !== void 0 ? n.items : n.content !== void 0 ? Array.isArray(n.content) ? n.content : [n.content] : void 0;\n e.push({ label: o, items: _(a, i, r + 1) });\n }\n return e;\n }\n function qn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.expr, 512);\n if (n === void 0 || s === void 0) continue;\n let o = [];\n if (Array.isArray(s.params)) for (let a of s.params) {\n if (o.length >= m.maxPlotParams) break;\n let u = y(a), d = u === void 0 ? void 0 : p(u.name, 64), c = u === void 0 ? void 0 : k(u.value, -1e9, 1e9);\n d === void 0 || c === void 0 || o.push({ name: d, value: c, ...l("min", u === void 0 ? void 0 : k(u.min, -1e9, 1e9)), ...l("max", u === void 0 ? void 0 : k(u.max, -1e9, 1e9)), ...l("step", u === void 0 ? void 0 : k(u.step, 1e-9, 1e9)), ...l("animateTo", u === void 0 ? void 0 : k(u.animateTo, -1e9, 1e9)), ...l("durationMs", u === void 0 ? void 0 : k(u.durationMs, 1, 12e4)), ...l("loop", u === void 0 ? void 0 : u.loop === true ? true : void 0) });\n }\n r.push({ expr: n, ...l("label", p(s.label, 128)), ...l("color", E(s.color)), ...l("kind", w(s.kind, oe)), ...l("params", o.length > 0 ? o : void 0) });\n }\n return r;\n }\n function zn(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxSteps) break;\n let e = y(r), s = e === void 0 ? void 0 : p(e.title, 256);\n s !== void 0 && i.push({ title: s, ...l("desc", e === void 0 ? void 0 : p(e.desc, m.maxString)) });\n }\n return i;\n }\n function Fn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.key, 256), o = s === void 0 ? void 0 : p(s.value, m.maxString);\n n === void 0 || o === void 0 || r.push({ key: n, value: o });\n }\n return r;\n }\n function jn(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= 24) break;\n let e = y(r), s = e === void 0 ? void 0 : p(e.path, 1024), n = e === void 0 ? void 0 : p(e.newText, 2e4);\n if (s === void 0 || n === void 0) continue;\n let o = e === void 0 ? void 0 : e.oldText;\n i.push({ path: s, newText: n, oldText: o === null || typeof o != "string" ? null : o.slice(0, 2e4) });\n }\n return i;\n }\n function Ln(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= m.maxAccordionItems) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.title, 256);\n o === void 0 || n === void 0 || e.push({ title: o, items: _(n.items, i, r + 1) });\n }\n return e;\n }\n function Vn(t) {\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxMeshes) break;\n let e = y(r), s = e === void 0 ? void 0 : w(e.shape, ue);\n if (s === void 0) continue;\n let n = e === void 0 ? void 0 : k(e.scale, -1e6, 1e6) ?? Z(e.scale), o = e === void 0 ? void 0 : k(e.size, -1e6, 1e6) ?? Z(e.size);\n i.push({ shape: s, ...l("color", e === void 0 ? void 0 : E(e.color)), ...l("position", e === void 0 ? void 0 : Z(e.position)), ...l("rotation", e === void 0 ? void 0 : Z(e.rotation)), ...l("scale", n), ...l("size", o) });\n }\n return i;\n }\n function Z(t) {\n if (!Array.isArray(t) || t.length !== 3) return;\n let [i, r, e] = t;\n if (!(typeof i != "number" || !Number.isFinite(i) || typeof r != "number" || !Number.isFinite(r) || typeof e != "number" || !Number.isFinite(e))) return [Math.min(1e6, Math.max(-1e6, i)), Math.min(1e6, Math.max(-1e6, r)), Math.min(1e6, Math.max(-1e6, e))];\n }\n function P(t, i, r) {\n return Math.min(r, Math.max(i, Math.round(t / 4) * 4));\n }\n function Kn(t) {\n if (!Array.isArray(t)) return;\n let i = [], r = /* @__PURE__ */ new Set();\n for (let e of t) {\n if (i.length >= m.maxDiagramNodes) break;\n let s = y(e);\n if (s === void 0) continue;\n let n = p(s.id, 128), o = p(s.label, m.maxString);\n if (n === void 0 || o === void 0 || r.has(n)) continue;\n r.add(n);\n let a = w(s.type, ce), u = s.x === void 0 ? void 0 : P(k(s.x, -1e6, 1e6) ?? 0, 0, 1e6), d = s.y === void 0 ? void 0 : P(k(s.y, -1e6, 1e6) ?? 0, 0, 1e6), c = s.w === void 0 ? void 0 : P(k(s.w, -1e6, 1e6) ?? 96, 40, 2e3), f = s.h === void 0 ? void 0 : P(k(s.h, -1e6, 1e6) ?? 48, 24, 1200);\n i.push({ id: n, label: o, ...l("sub", p(s.sub, 256)), ...l("type", a), ...l("x", u), ...l("y", d), ...l("w", c), ...l("h", f), ...l("tag", p(s.tag, 32)) });\n }\n return i;\n }\n function Hn(t) {\n if (t === void 0) return [];\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxDiagramEdges) break;\n let e = y(r);\n if (e === void 0) continue;\n let s = p(e.from, 128), n = p(e.to, 128);\n s === void 0 || n === void 0 || i.push({ from: s, to: n, ...l("label", p(e.label, m.maxDiagramLabel)), ...l("kind", w(e.kind, pe)), ...l("route", w(e.route, me)) });\n }\n return i;\n }\n function Jn(t) {\n let i = y(t);\n if (i === void 0) return;\n let r = {};\n for (let e of ["paper", "paper-2", "ink", "muted", "soft", "rule", "accent", "accent-tint", "link"]) {\n let s = E(i[e]);\n s !== void 0 && (r[e] = s);\n }\n return Object.keys(r).length === 0 ? void 0 : r;\n }\n function Un(t) {\n if (t === void 0) return [];\n if (!Array.isArray(t)) return;\n let i = [];\n for (let r of t) {\n if (i.length >= m.maxDiagramZones) break;\n let e = y(r);\n if (e === void 0) continue;\n let s = p(e.label, 64);\n s !== void 0 && i.push({ label: s, ...l("x", e.x === void 0 ? void 0 : P(k(e.x, -1e6, 1e6) ?? 0, 0, 1e6)), ...l("y", e.y === void 0 ? void 0 : P(k(e.y, -1e6, 1e6) ?? 0, 0, 1e6)), ...l("w", e.w === void 0 ? void 0 : P(k(e.w, -1e6, 1e6) ?? 100, 40, 2e3)), ...l("h", e.h === void 0 ? void 0 : P(k(e.h, -1e6, 1e6) ?? 100, 40, 1200)) });\n }\n return i;\n }\n function Bn(t) {\n let i = y(t);\n if (i === void 0) return null;\n let r = w(i.kind, de);\n if (r === void 0) return null;\n let e = Kn(i.nodes);\n if (e === void 0) return null;\n let s = Hn(i.edges);\n if (s === void 0) return null;\n let n = Un(i.zones);\n return n === void 0 ? null : { type: "diagram", kind: r, nodes: e, edges: s, ...l("zones", n.length > 0 ? n : void 0), ...l("variant", w(i.variant, fe)), ...l("title", p(i.title, 256)), ...l("theme", Jn(i.theme)) };\n }\n function Yn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let e of t) {\n if (r.length >= i) break;\n let s = y(e), n = s === void 0 ? void 0 : p(s.title, 256);\n n !== void 0 && r.push({ title: n, ...l("desc", s === void 0 ? void 0 : p(s.desc, m.maxString)), ...l("time", s === void 0 ? void 0 : p(s.time, 128)) });\n }\n return r;\n }\n function Qn(t, i) {\n return Ue(t, i, m.maxTreeDepth);\n }\n function Ue(t, i, r) {\n if (!Array.isArray(t)) return;\n let e = [];\n for (let s of t) {\n if (e.length >= i) break;\n let n = y(s), o = n === void 0 ? void 0 : p(n.name, 256);\n if (o === void 0) continue;\n let a = n !== void 0 && r > 0 && Array.isArray(n.children) ? Ue(n.children, i, r - 1) : void 0;\n e.push({ name: o, ...l("type", n === void 0 ? void 0 : w(n.type, le)), ...l("children", a) });\n }\n return e;\n }\n function Zn(t, i) {\n if (!Array.isArray(t)) return;\n let r = [];\n for (let s of t) {\n if (r.length >= m.maxQuizOptions) break;\n let n = y(s), o = typeof s == "string" ? p(s, 512) : n === void 0 ? void 0 : p(n.label, 512);\n o !== void 0 && r.push({ label: o, ...l("correct", n === void 0 ? void 0 : n.correct === true ? true : void 0), ...l("feedback", n === void 0 ? void 0 : p(n.feedback, m.maxString)) });\n }\n if (r.length === 0) return;\n if (r.some((s) => s.correct === true)) return r;\n let e = typeof i == "number" && Number.isFinite(i) ? Math.trunc(i) : typeof i == "string" ? r.findIndex((s) => s.label === i.slice(0, 512)) : -1;\n return e < 0 || e >= r.length ? r : r.map((s, n) => n === e ? { ...s, correct: true } : s);\n }\n var Wn = /<(?:script|img|svg|iframe|video|audio|object|embed|source)\\b|on[a-z]+\\s*=|javascript:/i;\n function Ce(t, i, r) {\n if (r.count <= 0 || (r.count -= 1, i > m.maxEChartOptionDepth)) return;\n if (typeof t == "string") {\n let n = t.slice(0, m.maxString);\n return n.toLowerCase().includes("url(") || Wn.test(n) ? void 0 : n;\n }\n if (typeof t == "number" && Number.isFinite(t) || typeof t == "boolean") return t;\n if (t === null) return null;\n if (Array.isArray(t)) {\n let n = Math.min(t.length, m.maxEChartArrayLen), o = [];\n for (let a = 0; a < n; a++) {\n let u = Ce(t[a], i + 1, r);\n u !== void 0 && o.push(u);\n }\n return o.length > 0 || t.length === 0 ? o : void 0;\n }\n let e = y(t);\n if (e === void 0) return;\n let s = {};\n for (let [n, o] of Object.entries(e)) {\n let a = Ce(o, i + 1, r);\n a !== void 0 && (n === "tooltip" && typeof a == "object" && a !== null && !Array.isArray(a) && (a.renderMode = "richText"), s[n] = a);\n }\n return Object.keys(s).length > 0 || Object.keys(e).length === 0 ? s : void 0;\n }\n function Be(t) {\n let i = y(t);\n if (i === void 0) return null;\n if (N(t)) {\n let e = z(t);\n return e === null ? null : Be(e);\n }\n if (!Array.isArray(i.items)) return null;\n let r = { remaining: m.maxNodes };\n return { ...l("title", p(i.title, m.maxString)), ...l("gap", k(i.gap, 0, 96)), ...l("panel", i.panel === true ? true : void 0), ...l("append", i.append === true ? true : void 0), items: _(i.items, r, 0) };\n }\n function Xn(t, i = Number.POSITIVE_INFINITY) {\n let r = 0, e = (n) => {\n if (Array.isArray(n)) for (let o of n) {\n if (r >= i) return;\n r += 1;\n let a = y(o);\n if (a !== void 0) {\n if (a.type === "tabs" && Array.isArray(a.tabs)) for (let u of a.tabs) {\n if (r >= i) return;\n let d = y(u);\n d !== void 0 && e(d.items);\n }\n else if (a.type === "accordion" && Array.isArray(a.items)) for (let u of a.items) {\n if (r >= i) return;\n let d = y(u);\n d !== void 0 && e(d.items);\n }\n else if ((a.type === "row" || a.type === "col" || a.type === "grid" || a.type === "card") && Array.isArray(a.items)) e(a.items);\n else if (a.type !== "file-tree") {\n if (a.type === "list" && Array.isArray(a.items)) for (let u of a.items) {\n if (r >= i) return;\n let d = y(u);\n d !== void 0 && typeof d.type == "string" && e([d]);\n }\n else if (a.type === "table" && Array.isArray(a.details)) {\n let u = I(a).length;\n for (let d = 0; d < Math.min(a.details.length, u); d++) {\n if (r >= i) return;\n let c = a.details[d];\n Array.isArray(c) && C(a, d) && e(c);\n }\n }\n }\n }\n }\n }, s = y(t);\n return e(s === void 0 ? [] : s.items), r;\n }\n var et = q;\n function nt(t, i, r) {\n let e = 0, s = (d) => {\n let c = y(d);\n return c !== void 0 && typeof c.type == "string" && et.has(c.type);\n };\n function n(d, c) {\n if (Array.isArray(d)) {\n for (let f = 0; f < d.length; f++) if (o(d[f], `${c}[${f}]`), e >= i) return;\n }\n }\n function o(d, c) {\n if (e >= i || !s(d)) return;\n let f = y(d);\n if (f !== void 0) {\n if (e += 1, r(f, c), f.type === "tabs" && Array.isArray(f.tabs)) for (let g = 0; g < f.tabs.length; g++) a(f.tabs[g], `${c}.tabs[${g}]`);\n else if (f.type === "accordion" && Array.isArray(f.items)) for (let g = 0; g < f.items.length; g++) a(f.items[g], `${c}.items[${g}]`);\n else if ((f.type === "row" || f.type === "col" || f.type === "grid" || f.type === "card") && Array.isArray(f.items)) n(f.items, `${c}.items`);\n else if (f.type === "list" && Array.isArray(f.items)) for (let g = 0; g < f.items.length; g++) o(f.items[g], `${c}.items[${g}]`);\n else if (f.type === "table" && Array.isArray(f.details)) {\n let g = I(f).length;\n for (let x = 0; x < Math.min(f.details.length, g); x++) Array.isArray(f.details[x]) && C(f, x) && n(f.details[x], `${c}.details[${x}]`);\n }\n }\n }\n function a(d, c) {\n let f = y(d);\n if (f === void 0) return;\n let g = f.items !== void 0 ? f.items : f.content;\n Array.isArray(g) ? n(g, `${c}.items`) : o(g, `${c}.items`);\n }\n let u = y(t);\n return u === void 0 || (N(u) && s(t) ? o(t, "spec") : n(u.items, "items")), e;\n }\n function Ye(t, i = Number.POSITIVE_INFINITY) {\n return nt(t, i, () => {\n });\n }\n function tt(t, i = Number.POSITIVE_INFINITY) {\n return Ye(t, i);\n }\n function Qe(t) {\n let i = [], r = y(t);\n if (r === void 0) return { ok: false, errors: ["spec root must be an object"] };\n if (N(t)) {\n let a = z(t);\n return a !== null ? Qe(a) : { ok: false, errors: ["spec.items must be an array"] };\n }\n if (!Array.isArray(r.items)) return { ok: false, errors: ["spec.items must be an array"] };\n Ke(r, "spec", V, i, ["items"]);\n let e = 0, s = false, n = (a, u, d) => {\n if (!s) {\n if (!Array.isArray(a)) {\n i.push(`${d} must be an array`);\n return;\n }\n for (let c = 0; c < a.length; c++) {\n if (s || e >= m.maxNodes) {\n s || (i.push(`spec exceeds ${m.maxNodes} nodes; tail elided`), s = true);\n return;\n }\n e += 1;\n let f = `${d}[${c}]`;\n Xe(a[c], u, f, i, n);\n }\n }\n };\n n(r.items, 0, "items"), i.length === 0 && i.push(...Re(r).diagnostics);\n let o = [...new Set(i)];\n return { ok: o.length === 0, errors: o };\n }\n function Ze(t) {\n let i = Ie(t), r = Be(i.value), e = Qe(i.value), s = Ye(i.value, m.maxNodes + 1), n = r === null ? 0 : tt(r), o = r === null ? 0 : Xn(r), a = e.errors.filter((u) => !u.includes(": unknown type "));\n return r !== null && a.length === 0 && a.push(...Re(r).diagnostics), s > n && a.push(`repair dropped ${s - n} declared native node(s): declared ${s}, rendered ${n}`), { value: i.value, normalized: i.value, repaired: r, spec: r, errors: [...new Set(a)], warnings: [...i.warnings, ...Pe(i.value)], declaredCount: s, renderedCount: o, declaredNativeCount: s, renderedNativeCount: n, renderedTotalCount: o };\n }\n function it(t) {\n return t.errors.length > 0 && t.errors.every((i) => i.startsWith("spec exceeds ") || i.startsWith("repair dropped ")) && t.renderedNativeCount === m.maxNodes && t.declaredNativeCount === m.maxNodes + 1;\n }\n function Ne(t) {\n return t.spec !== null && (t.errors.length === 0 || it(t));\n }\n var rt = /^(items\\[\\d+\\](?:\\.(?:items\\[\\d+\\]|tabs\\[\\d+\\]\\.items\\[\\d+\\]|details\\[\\d+\\](?:\\[\\d+\\])?))*)/;\n function st(t) {\n let i = rt.exec(t);\n return i === null ? null : i[1] ?? null;\n }\n function Ve(t, i) {\n let r = [...i.matchAll(/(?:^|\\.)(items|tabs|details)\\[(\\d+)\\]|\\[(\\d+)\\]/g)];\n if (r.length === 0 || r[r.length - 1][1] === "tabs") return;\n let e = t;\n for (let s = 0; s < r.length; s++) {\n let n = r[s], o = n[1] === void 0 ? e : y(e)?.[n[1]], a = Number(n[2] ?? n[3]);\n if (!Array.isArray(o) || a >= o.length) return;\n if (s === r.length - 1) return { array: o, index: a, preserveIndex: n[1] === "details" };\n if (e = o[a], e === void 0) return;\n }\n }\n function ot(t) {\n try {\n return y(JSON.parse(JSON.stringify(t))) ?? null;\n } catch {\n return null;\n }\n }\n function at(t) {\n if (Ne(t)) return t.spec;\n if (t.spec === null) return null;\n let i = y(t.value);\n if (i === void 0) return null;\n let r = /* @__PURE__ */ new Set(), e = /* @__PURE__ */ new Set();\n for (let d of t.errors) {\n if (d.startsWith("spec exceeds ")) continue;\n let c = st(d);\n c !== null && (d === `${c}.details must not contain more entries than rows` ? e.add(c) : r.add(c));\n }\n if (r.size === 0 && e.size === 0) return null;\n let s = ot(N(i) ? z(i) : i);\n if (s === null) return null;\n let n = [...r].map((d) => Ve(s, d)).filter((d) => d !== void 0), o = [...e].map((d) => Ve(s, d)).filter((d) => d !== void 0);\n for (let { array: d, index: c } of o) {\n let f = y(d[c]);\n f?.type === "table" && Array.isArray(f.details) && (f.details.length = Math.min(f.details.length, I(f).length));\n }\n let a = /* @__PURE__ */ new Map();\n for (let { array: d, index: c, preserveIndex: f } of n) {\n if (f) {\n d[c] = null;\n continue;\n }\n let g = a.get(d);\n g === void 0 ? a.set(d, [c]) : g.push(c);\n }\n for (let [d, c] of a) {\n c.sort((f, g) => g - f);\n for (let f of c) d.splice(f, 1);\n }\n let u = Ze(s);\n return !Ne(u) || u.renderedNativeCount === 0 ? null : u.spec;\n }\n function We(t, i, r) {\n if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {\n let s = y(t[e]), n = `${i}[${e}]`;\n if (s === void 0) {\n r.push(`${n} must be an object`);\n continue;\n }\n typeof s.label != "string" && r.push(`${n}.label must be a string`), (typeof s.value != "number" || !Number.isFinite(s.value)) && r.push(`${n}.value must be a finite number`), s.color !== void 0 && typeof s.color != "string" && r.push(`${n}.color must be a string`);\n }\n }\n function ut(t, i, r) {\n if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {\n let s = y(t[e]), n = `${i}[${e}]`;\n if (s === void 0) {\n r.push(`${n} must be an object`);\n continue;\n }\n typeof s.label != "string" && r.push(`${n}.label must be a string`), s.color !== void 0 && typeof s.color != "string" && r.push(`${n}.color must be a string`), Array.isArray(s.data) || r.push(`${n}.data must be an array`), We(s.data, `${n}.data`, r);\n }\n }\n function lt(t, i, r) {\n !Array.isArray(t.data) && !Array.isArray(t.series) && r.push(`${i}: type \'chart\' requires data or series (array)`), t.variant !== void 0 && r.push(`${i}.variant is unsupported; use kind`), t.data !== void 0 && !Array.isArray(t.data) && r.push(`${i}.data must be an array`), t.series !== void 0 && !Array.isArray(t.series) && r.push(`${i}.series must be an array`), t.kind !== void 0 && (typeof t.kind != "string" || !U.includes(t.kind)) && r.push(`${i}.kind must be bars, line, or donut`);\n let e = t.kind === void 0 ? "bars" : t.kind, s = Array.isArray(t.series) ? t.series : void 0;\n if (Array.isArray(t.data) && t.data.length === 0 && (s === void 0 || s.length === 0) && r.push(`${i}.data must not be empty`), s !== void 0) {\n s.length === 0 && r.push(`${i}.series must not be empty`), e === "donut" && r.push(`${i}.series is only supported for bars and line`);\n for (let n = 0; n < s.length; n++) {\n let o = y(s[n]);\n o !== void 0 && Array.isArray(o.data) && o.data.length === 0 && r.push(`${i}.series[${n}].data must not be empty`);\n }\n }\n e === "donut" && t.data === void 0 && r.push(`${i}.data is required for donut`), e === "line" && t.data === void 0 && (s === void 0 || s.length === 0) && r.push(`${i}.data is required for line (or provide series)`), We(t.data, `${i}.data`, r), ut(t.series, `${i}.series`, r);\n }\n function dt(t, i, r) {\n if (Array.isArray(t)) for (let e = 0; e < t.length; e++) {\n let s = t[e];\n if (y(s) === void 0) {\n if (!Array.isArray(s)) {\n r.push(`${i}[${e}] must be an array or object`);\n continue;\n }\n for (let n = 0; n < s.length; n++) {\n let o = s[n];\n typeof o != "string" && (typeof o != "number" || !Number.isFinite(o)) && r.push(`${i}[${e}][${n}] must be a string or finite number`);\n }\n }\n }\n }\n function Xe(t, i, r, e, s) {\n if (i > m.maxDepth) {\n e.push(`${r}: exceeds max depth ${m.maxDepth}`);\n return;\n }\n let n = y(t);\n if (n === void 0) {\n e.push(`${r}: must be an object`);\n return;\n }\n let o = n.type;\n if (typeof o != "string") {\n e.push(`${r}: missing string \'type\'`);\n return;\n }\n let a = (c) => {\n n[c] !== void 0 && typeof n[c] != "string" && e.push(`${r}: \'${c}\' must be a string`);\n }, u = (c) => {\n n[c] !== void 0 && (typeof n[c] != "number" || !Number.isFinite(n[c])) && e.push(`${r}: \'${c}\' must be a finite number`);\n };\n switch (o) {\n case "text":\n typeof n.content != "string" && typeof n.text != "string" && e.push(`${r}: type \'text\' requires content or text (string)`), a("content"), a("text");\n break;\n case "row":\n case "col":\n case "card":\n case "grid":\n Array.isArray(n.items) || e.push(`${r}: type \'${o}\' requires items (array)`), s(n.items, i + 1, `${r}.items`), o === "grid" && u("cols");\n break;\n case "button":\n case "checkbox":\n case "link":\n case "switch":\n typeof n.label != "string" && e.push(`${r}: type \'${o}\' requires label (string)`), a("label");\n break;\n case "image":\n case "audio":\n case "video":\n typeof n.src != "string" && e.push(`${r}: type \'${o}\' requires src (string)`), a("src"), a("alt"), o === "video" && a("poster");\n break;\n case "slider":\n a("label"), u("min"), u("max"), u("step"), u("value");\n break;\n case "input":\n case "textarea":\n a("label"), a("placeholder"), a("value");\n break;\n case "select":\n case "radio":\n Array.isArray(n.options) || e.push(`${r}: type \'${o}\' requires options (array)`);\n break;\n case "submit":\n typeof n.label != "string" && e.push(`${r}: type \'submit\' requires label (string)`);\n break;\n case "badge":\n typeof n.label != "string" && typeof n.text != "string" && typeof n.value != "string" && e.push(`${r}: type \'badge\' requires label, text, or value (string)`), a("label"), a("text"), a("value");\n break;\n case "hero":\n typeof n.title != "string" && e.push(`${r}: type \'hero\' requires title (string)`), a("subtitle");\n break;\n case "stat":\n typeof n.label != "string" && e.push(`${r}: type \'stat\' requires label (string)`), typeof n.value != "string" && e.push(`${r}: type \'stat\' requires value (string)`), a("delta");\n break;\n case "progress":\n (typeof n.value != "number" || !Number.isFinite(n.value) || n.value < 0 || n.value > 100) && e.push(`${r}: type \'progress\' requires value (number 0..100)`), u("value");\n break;\n case "avatar":\n typeof n.name != "string" && e.push(`${r}: type \'avatar\' requires name (string)`);\n break;\n case "list":\n if (Array.isArray(n.items) || e.push(`${r}: type \'list\' requires items (array)`), Array.isArray(n.items)) for (let c = 0; c < n.items.length; c++) {\n let f = y(n.items[c]);\n f !== void 0 && typeof f.type == "string" && Xe(f, i + 1, `${r}.items[${c}]`, e, s);\n }\n break;\n case "table":\n if (!Array.isArray(n.columns) && !He(n) && e.push(`${r}: type \'table\' requires columns (array)`), Array.isArray(n.rows) || e.push(`${r}: type \'table\' requires rows (array)`), n.types !== void 0 && !Array.isArray(n.types) && e.push(`${r}.types must be an array of column cell types`), n.details !== void 0 && !Array.isArray(n.details) && e.push(`${r}.details must be an array aligned with rows`), Array.isArray(n.details)) {\n let c = { columns: n.columns, rows: n.rows, types: n.types }, f = I(c).length;\n n.details.length > f && e.push(`${r}.details must not contain more entries than rows`);\n for (let g = 0; g < Math.min(n.details.length, f); g++) {\n let x = n.details[g];\n if (!(x === null || !C(c, g))) {\n if (!Array.isArray(x)) {\n e.push(`${r}.details[${g}] must be an array or null`);\n continue;\n }\n s(x, i + 1, `${r}.details[${g}]`);\n }\n }\n }\n dt(n.rows, `${r}.rows`, e);\n break;\n case "chart":\n lt(n, r, e);\n break;\n case "tabs": {\n if (Array.isArray(n.tabs) || e.push(`${r}: type \'tabs\' requires tabs (array)`), Array.isArray(n.tabs)) for (let c = 0; c < n.tabs.length; c++) {\n let f = y(n.tabs[c]);\n if (f === void 0) {\n e.push(`${r}.tabs[${c}] must be an object`);\n continue;\n }\n typeof f.label != "string" && e.push(`${r}.tabs[${c}].label must be a string`), s(f.items, i + 1, `${r}.tabs[${c}].items`);\n }\n break;\n }\n case "plot":\n Array.isArray(n.series) || e.push(`${r}: type \'plot\' requires series (array)`);\n break;\n case "callout":\n typeof n.content != "string" && e.push(`${r}: type \'callout\' requires content (string)`);\n break;\n case "steps":\n Array.isArray(n.steps) || e.push(`${r}: type \'steps\' requires steps (array)`);\n break;\n case "keyvalue":\n Array.isArray(n.pairs) || e.push(`${r}: type \'keyvalue\' requires pairs (array)`);\n break;\n case "diff":\n Array.isArray(n.diffs) || e.push(`${r}: type \'diff\' requires diffs (array)`);\n break;\n case "json":\n "value" in n || e.push(`${r}: type \'json\' requires value`);\n break;\n case "code":\n typeof n.code != "string" && e.push(`${r}: type \'code\' requires code (string)`);\n break;\n case "accordion":\n if (Array.isArray(n.items) || e.push(`${r}: type \'accordion\' requires items (array)`), Array.isArray(n.items)) for (let c = 0; c < n.items.length; c++) {\n let f = y(n.items[c]);\n if (f === void 0) {\n e.push(`${r}.items[${c}] must be an object`);\n continue;\n }\n typeof f.title != "string" && e.push(`${r}.items[${c}].title must be a string`), s(f.items, i + 1, `${r}.items[${c}].items`);\n }\n break;\n case "copy":\n typeof n.text != "string" && e.push(`${r}: type \'copy\' requires text (string)`);\n break;\n case "svg":\n typeof n.code != "string" && e.push(`${r}: type \'svg\' requires code (string)`), u("height");\n break;\n case "mermaid":\n typeof n.code != "string" && e.push(`${r}: type \'mermaid\' requires code (string)`);\n break;\n case "scene3d":\n Array.isArray(n.meshes) || e.push(`${r}: type \'scene3d\' requires meshes (array)`);\n break;\n case "timeline":\n Array.isArray(n.items) || e.push(`${r}: type \'timeline\' requires items (array)`);\n break;\n case "file-tree":\n Array.isArray(n.items) || e.push(`${r}: type \'file-tree\' requires items (array)`);\n break;\n case "breadcrumb":\n Array.isArray(n.items) || e.push(`${r}: type \'breadcrumb\' requires items (array)`);\n break;\n case "quiz":\n typeof n.question != "string" && e.push(`${r}: type \'quiz\' requires question (string)`), Array.isArray(n.options) || e.push(`${r}: type \'quiz\' requires options (array)`);\n break;\n case "diagram":\n typeof n.kind != "string" && e.push(`${r}: type \'diagram\' requires kind (string)`), Array.isArray(n.nodes) || e.push(`${r}: type \'diagram\' requires nodes (array)`), n.edges !== void 0 && !Array.isArray(n.edges) && e.push(`${r}: type \'diagram\' requires edges (array) when present`);\n break;\n case "echart":\n n.option === void 0 && n.data === void 0 && n.series === void 0 && (!Array.isArray(n.links) || n.links.length === 0) && e.push(`${r}: type \'echart\' requires option, data, series, or links`), u("height");\n break;\n default:\n e.push(`${r}: unknown type \'${o}\' (custom renderer?)`);\n }\n let d = T[o];\n d !== void 0 && In(n, r, d, e);\n }\n\n // lib/normalize-visual.js\n function normalizeVisual(value, schemas) {\n const unwrap = (v2) => v2 && typeof v2 === "object" && !Array.isArray(v2) && Object.keys(v2).length === 1 && Array.isArray(v2.item) ? v2.item : v2;\n const scalar2 = (v2, kind) => kind === "number" && typeof v2 === "string" && v2.trim() !== "" && Number.isFinite(Number(v2)) ? Number(v2) : kind === "boolean" && (v2 === "true" || v2 === "false") ? v2 === "true" : v2;\n function record(input, schema, depth = 0) {\n if (!input || typeof input !== "object" || Array.isArray(input) || depth > 32) return input;\n const out2 = { ...input };\n for (const [key, v2] of Object.entries(input)) {\n const target = schema.aliases?.[key] ?? key, kind = schema.fields?.[target];\n if (kind === "array" || kind === "nodes") {\n let array2 = unwrap(v2);\n if (Array.isArray(array2)) array2 = array2.map((x) => kind === "nodes" ? node2(x, depth + 1) : schema.nested?.[target] ? record(x, schema.nested[target], depth + 1) : x);\n out2[key] = array2;\n } else out2[key] = scalar2(v2, kind);\n }\n return out2;\n }\n function node2(v2, depth) {\n if (!v2 || typeof v2 !== "object" || Array.isArray(v2)) return v2;\n if (v2.type === "heading") {\n v2 = { ...v2, type: "text", content: v2.content ?? v2.text ?? v2.title, size: v2.size ?? "h3" };\n delete v2.text;\n delete v2.title;\n }\n if (["card", "row", "col", "grid"].includes(v2.type) && v2.items === void 0 && Array.isArray(unwrap(v2.children))) {\n v2 = { ...v2, items: unwrap(v2.children) };\n delete v2.children;\n }\n const out2 = record(v2, schemas[v2.type] ?? {}, depth);\n if (v2.type === "quiz" && Array.isArray(out2.options)) out2.options = out2.options.map((x) => record(x, { fields: { correct: "boolean" } }));\n if (v2.type === "table") {\n for (const key of ["rows", "data", "items", "details"]) if (Array.isArray(out2[key])) out2[key] = out2[key].map((row) => {\n row = unwrap(row);\n return key === "details" && Array.isArray(row) ? row.map((x) => node2(x, depth + 1)) : row;\n });\n }\n if (v2.type === "echart") {\n for (const key of ["data", "series", "links"]) if (Array.isArray(out2[key])) out2[key] = out2[key].map((x) => record(x, { fields: { value: "number", data: "array" }, nested: { data: { fields: { value: "number" } } } }));\n }\n return out2;\n }\n if (Array.isArray(value)) return { items: value.map((x) => node2(x, 0)) };\n if (!value || typeof value !== "object") return value;\n const out = { ...value }, items = unwrap(value.items);\n if (Array.isArray(items)) out.items = items.map((x) => node2(x, 0));\n return out;\n }\n\n // lib/visual.js\n var VISUAL_TYPES = Object.freeze([...q]);\n function validateVisual(value) {\n const encoded = JSON.stringify(value);\n if (!encoded || new TextEncoder().encode(encoded).length > 131072) throw Error("DSH UI: visual spec exceeds 128 KiB");\n const processed = Ze(normalizeVisual(value, T)), spec = Ne(processed) ? processed.spec : at(processed);\n if (!spec || !processed.renderedNativeCount) throw Error("DSH UI: visual spec: " + (processed.errors.slice(0, 4).join("; ") || "requires registered components"));\n const critical = /* @__PURE__ */ new Set(["quiz", "radio", "submit", "input", "textarea", "select", "slider", "checkbox", "switch"]);\n const inventory = (items, path = "items", result = []) => {\n for (const [n, v2] of (Array.isArray(items) ? items : []).entries()) {\n if (!v2 || typeof v2 !== "object") continue;\n const at2 = path + "[" + n + "]";\n if (critical.has(v2.type)) result.push({ type: v2.type, id: v2.id ?? v2.group ?? v2.question ?? v2.label, path: at2 });\n if (["row", "col", "grid", "card"].includes(v2.type)) inventory(v2.items, at2 + ".items", result);\n if (v2.type === "tabs") for (const [i, t] of (v2.tabs ?? []).entries()) inventory(t.items, at2 + ".tabs[" + i + "].items", result);\n if (v2.type === "accordion") for (const [i, t] of (v2.items ?? []).entries()) inventory(t.items, at2 + ".items[" + i + "].items", result);\n }\n return result;\n };\n const source = normalizeVisual(value, T), before = inventory(source.items), after = inventory(spec.items);\n const available = [...after], missing = before.filter((v2) => {\n const i = available.findIndex((n) => n.type === v2.type && n.id === v2.id);\n if (i < 0) return true;\n available.splice(i, 1);\n return false;\n });\n if (missing.length) throw Error("DSH UI: critical component was rejected at " + missing.map((v2) => v2.path + " (" + v2.type + ")").join(", ") + ". " + processed.errors.slice(0, 4).join("; "));\n const stableIds = /* @__PURE__ */ new Set();\n function walk(items) {\n for (const n of items) {\n if (n.id !== void 0) {\n if (stableIds.has(n.id)) throw Error("DSH UI: duplicate extended component id " + n.id);\n stableIds.add(n.id);\n }\n if (!VISUAL_TYPES.includes(n.type)) throw Error("DSH UI: unsupported visual component " + n.type);\n if (n.type === "input" && n.inputType === "password") throw Error("DSH UI: do not collect passwords or secrets in a UI");\n if (n.type !== "file-tree" && Array.isArray(n.items)) walk(n.items.filter((x) => x && typeof x === "object" && "type" in x));\n for (const t of n.tabs ?? []) walk(t.items ?? []);\n if (n.type === "table") {\n for (const d of n.details ?? []) if (d) walk(d);\n }\n }\n }\n walk(spec.items);\n delete spec.panel;\n delete spec.append;\n return { spec, warnings: processed.errors.slice(0, 12), count: processed.renderedNativeCount };\n }\n function visualDocument(value) {\n if (Array.isArray(value)) value = { items: value };\n const { spec, warnings } = validateVisual(value), title = spec.title || "\\u53EF\\u89C6\\u5316";\n const texts = [];\n function gather(v2) {\n if (!v2 || typeof v2 !== "object") return;\n for (const [k2, x] of Object.entries(v2)) {\n if (["title", "content", "label", "question", "explanation", "alt"].includes(k2) && typeof x === "string") texts.push(x);\n else if (x && typeof x === "object") Array.isArray(x) ? x.forEach(gather) : gather(x);\n }\n }\n gather(spec);\n return { version: 1, title, fallback: texts.join("\\n").slice(0, 8192) || title, nodes: [{ id: "visual", type: "visual", spec, warnings }] };\n }\n\n // lib/normalize-authoring.js\n var object = (v2) => v2 !== null && typeof v2 === "object" && !Array.isArray(v2);\n var own = (v2, k2) => Object.hasOwn(v2, k2);\n var singleItem = (v2) => object(v2) && Object.keys(v2).length === 1 && own(v2, "item");\n var array = (v2) => {\n let candidate = v2;\n for (let i = 0; i < 8 && singleItem(candidate); i++) candidate = candidate.item;\n return Array.isArray(candidate) ? candidate : v2;\n };\n var numericOps = /* @__PURE__ */ new Set(["add", "sub", "mul", "div", "min", "max", "round", "ceil", "floor", "abs", "lt", "lte", "gt", "gte"]);\n function number(v2) {\n if (typeof v2 !== "string" || !/^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:e[+-]?\\d+)?$/i.test(v2.trim())) return v2;\n const n = Number(v2);\n return Number.isFinite(n) && (!Number.isInteger(n) || Number.isSafeInteger(n)) ? n : v2;\n }\n var boolean = (v2) => v2 === "true" ? true : v2 === "false" ? false : v2;\n function expression(e, numeric = false, logical = false) {\n if (!object(e)) return e;\n if (Object.keys(e).length === 1 && own(e, "expr") && typeof e.expr === "number" && Number.isFinite(e.expr)) {\n e.const = e.expr;\n delete e.expr;\n }\n if (own(e, "const")) {\n if (numeric) e.const = number(e.const);\n if (logical) e.const = boolean(e.const);\n }\n if (own(e, "args")) e.args = array(e.args);\n if (Array.isArray(e.args)) e.args.forEach((arg, i) => expression(arg, numericOps.has(e.op) || e.op === "if" && i > 0 && numeric, e.op === "if" && i === 0));\n if (object(e.map?.fields)) Object.values(e.map.fields).forEach((e2) => expression(e2));\n return e;\n }\n function normalizeAuthoring(doc2) {\n if (Array.isArray(doc2)) doc2 = visualDocument(doc2);\n if (object(doc2) && !own(doc2, "nodes") && (own(doc2, "items") || typeof doc2.type === "string")) doc2 = visualDocument(doc2);\n if (!object(doc2)) return doc2;\n if (own(doc2, "version")) doc2.version = number(doc2.version);\n if (object(doc2.presentation) && doc2.presentation.layout === "flow" && (!own(doc2.presentation, "preset") || doc2.presentation.preset === "flow")) {\n doc2.presentation.layout = "guide";\n doc2.presentation.preset = "flow";\n }\n if (object(doc2.state)) for (const k2 of Object.keys(doc2.state)) {\n let s = doc2.state[k2];\n if (typeof s === "string" && s.trim().startsWith("{")) {\n try {\n const parsed = JSON.parse(s);\n if (object(parsed)) s = parsed;\n } catch {\n }\n }\n if (singleItem(s) && object(s.item)) s = s.item;\n doc2.state[k2] = s;\n if (!object(s)) continue;\n if (own(s, "options")) s.options = array(s.options);\n if (s.type === "number") {\n for (const field of ["default", "min", "max", "step"]) if (own(s, field)) s[field] = number(s[field]);\n if (Array.isArray(s.options)) s.options = s.options.map(number);\n } else if (s.type === "boolean") {\n if (own(s, "default")) s.default = boolean(s.default);\n if (Array.isArray(s.options)) s.options = s.options.map(boolean);\n }\n }\n if (object(doc2.derived)) Object.values(doc2.derived).forEach((e) => expression(e));\n if (object(doc2.actions)) {\n for (const action of Object.values(doc2.actions)) if (object(action) && own(action, "stateKeys")) action.stateKeys = array(action.stateKeys);\n }\n function nodes(list) {\n list = array(list);\n if (!Array.isArray(list)) return list;\n for (const node2 of list) {\n if (!object(node2)) continue;\n if (node2.type === "code" && (node2.copyable === true || node2.copyable === "true")) delete node2.copyable;\n if (["slider", "input"].includes(node2.type) && typeof node2.bind === "string" && node2.bind.startsWith("state.")) {\n const spec = doc2.state?.[node2.bind.slice(6)];\n if (spec?.type === "number") {\n for (const field of ["min", "max", "step"]) if (own(node2, field) && number(node2[field]) === spec[field]) delete node2[field];\n }\n }\n if (["text", "heading", "callout"].includes(node2.type) && own(node2, "content")) {\n if (!own(node2, "text")) {\n node2.text = node2.content;\n delete node2.content;\n } else if (node2.text === node2.content) delete node2.content;\n }\n if (["text", "heading", "callout"].includes(node2.type) && typeof node2.text === "string") {\n const spans = array(node2.spans);\n if (Array.isArray(spans) && spans.every((s) => object(s) && typeof s.text === "string") && spans.map((s) => s.text).join("") === node2.text) delete node2.text;\n }\n if (node2.type === "table" && own(node2, "types")) {\n const columns = array(node2.columns), rows = array(node2.rows), types = array(node2.types);\n const allowed = ["id", "type", "label", "columns", "rows", "types"];\n if (Object.keys(node2).every((k2) => allowed.includes(k2)) && Array.isArray(columns) && columns.length && columns.every((c) => object(c) && typeof c.key === "string" && typeof c.label === "string" && Object.keys(c).every((k2) => ["key", "label", "unit"].includes(k2))) && new Set(columns.map((c) => c.key)).size === columns.length && Array.isArray(rows) && rows.every(object) && Array.isArray(types) && types.length === columns.length && types.every((t) => ["text", "num", "delta", "bar", "badge"].includes(t))) {\n const spec = { ...node2.label ? { title: node2.label } : {}, items: [{ type: "table", columns: columns.map((c) => c.label + (c.unit ? ` (${c.unit})` : "")), rows: rows.map((row) => columns.map((c) => row[c.key] ?? null)), types }] }, id = node2.id;\n for (const k2 of Object.keys(node2)) delete node2[k2];\n Object.assign(node2, { ...id !== void 0 ? { id } : {}, type: "visual", spec });\n }\n }\n if (typeof node2.id === "string" && VISUAL_TYPES.includes(node2.type) && !own(COMPONENTS, node2.type)) {\n const spec = { items: [{ ...node2 }] }, id = node2.id;\n for (const k2 of Object.keys(node2)) delete node2[k2];\n Object.assign(node2, { id, type: "visual", spec });\n }\n if (node2.type === "table" && Array.isArray(node2.columns) && node2.columns.length && node2.columns.every((c) => object(c) && typeof c.key === "string") && new Set(node2.columns.map((c) => c.key)).size === node2.columns.length && Array.isArray(node2.rows) && node2.rows.every((row) => Array.isArray(row) && row.length === node2.columns.length)) {\n node2.rows = node2.rows.map((row) => Object.fromEntries(node2.columns.map((c, i) => [c.key, row[i]])));\n }\n if (node2.type === "table" && Array.isArray(node2.columns) && node2.columns.length && Array.isArray(node2.rows) && node2.rows.every(Array.isArray) && node2.columns.every((c) => object(c) && Number.isInteger(c.key) && c.key >= 0) && new Set(node2.columns.map((c) => c.key)).size === node2.columns.length) {\n const columns = node2.columns.map((c) => ({ ...c, key: "col_" + c.key }));\n node2.rows = node2.rows.map((row) => Object.fromEntries(node2.columns.map((c) => ["col_" + c.key, row[c.key] ?? null])));\n node2.columns = columns;\n }\n if (node2.type === "visual" && typeof node2.id === "string") {\n node2.stateKey ??= "visual_" + node2.id;\n doc2.state ??= {};\n if (!own(doc2.state, node2.stateKey)) doc2.state[node2.stateKey] = { type: "json", default: {} };\n }\n if (node2.type === "sandbox") {\n if (!own(node2, "title")) node2.title = doc2.title;\n if (!own(node2, "fallback")) node2.fallback = doc2.fallback;\n }\n for (const field of ["children", "items", "columns", "libraries", "stateKeys", "dataKeys", "derivedKeys"]) if (own(node2, field)) node2[field] = array(node2[field]);\n if (["table", "chart"].includes(node2.type) && own(node2, "rows")) node2.rows = array(node2.rows);\n for (const field of ["decimals", "height"]) if (own(node2, field)) node2[field] = number(node2[field]);\n if (["row", "column"].includes(node2.type)) {\n if (own(node2, "gap")) node2.gap = number(node2.gap);\n if (node2.type === "row" && own(node2, "columns")) node2.columns = number(node2.columns);\n }\n if (["text", "heading", "callout"].includes(node2.type)) {\n for (const field of ["size", "weight", "lineHeight"]) if (own(node2, field)) node2[field] = number(node2[field]);\n if (own(node2, "spans")) node2.spans = array(node2.spans);\n if (Array.isArray(node2.spans)) {\n for (const span of node2.spans) if (object(span)) {\n for (const field of ["size", "weight", "lineHeight"]) if (own(span, field)) span[field] = number(span[field]);\n }\n }\n }\n if (node2.type === "details" && own(node2, "open")) node2.open = boolean(node2.open);\n if (node2.type === "text" && own(node2, "copyable")) node2.copyable = boolean(node2.copyable);\n if (node2.type === "code" && own(node2, "wrap")) node2.wrap = boolean(node2.wrap);\n if (["table", "chart"].includes(node2.type) && Array.isArray(node2.rows)) {\n for (const row of node2.rows) if (object(row)) for (const cell of Object.values(row)) expression(cell);\n }\n for (const field of ["text", "value", "max", "rows"]) if (own(node2, field)) expression(node2[field], node2.type === "progress");\n if (["row", "column", "card", "details"].includes(node2.type) && own(node2, "children")) node2.children = nodes(node2.children);\n }\n return list;\n }\n if (own(doc2, "nodes")) doc2.nodes = nodes(doc2.nodes);\n return doc2;\n }\n\n // lib/typography.js\n var TEXT_PRESETS = Object.freeze(["reading", "brief", "comparison", "list", "callout", "scorecard", "flow", "minimal"]);\n var TYPE_FIELDS = Object.freeze(["size", "weight", "color", "align", "lineHeight"]);\n var TEXT_SIZES = Object.freeze({ sm: 14, md: 16, lg: 20, xl: 26, hero: 36 });\n var TEXT_COLORS = Object.freeze({ default: "var(--du-ink)", muted: "var(--du-muted)", accent: "var(--du-accent)", success: "var(--du-green)", warning: "var(--du-amber)", danger: "var(--du-red)", violet: "var(--du-violet)" });\n function validateTypography(value, at2 = "text") {\n const fail2 = (message) => {\n throw Error(`DSH UI: ${at2}.${message}`);\n };\n if (value.size !== void 0 && !(typeof value.size === "number" && Number.isFinite(value.size) && value.size >= 12 && value.size <= 48) && !Object.hasOwn(TEXT_SIZES, value.size)) fail2("size must be 12..48 px or sm/md/lg/xl/hero");\n if (value.weight !== void 0 && ![400, 500, 600, 700, 800].includes(value.weight)) fail2("weight must be 400/500/600/700/800");\n if (value.color !== void 0 && (typeof value.color !== "string" || !Object.hasOwn(TEXT_COLORS, value.color) && !/^#(?:[0-9a-f]{3}|[0-9a-f]{6})$/i.test(value.color))) fail2("color must be default/muted/accent/success/warning/danger/violet or #RGB/#RRGGBB");\n if (value.align !== void 0 && !["left", "center", "right"].includes(value.align)) fail2("align must be left/center/right");\n if (value.lineHeight !== void 0 && !(typeof value.lineHeight === "number" && value.lineHeight >= 1.2 && value.lineHeight <= 2.4)) fail2("lineHeight must be 1.2..2.4");\n }\n\n // lib/links.js\n function validateLink(node2) {\n const fail2 = (message) => {\n throw Error("DSH UI: " + message);\n };\n if ([node2.href, node2.path, node2.action].filter((v2) => v2 !== void 0).length !== 1) fail2(`node.${node2.id}: choose exactly one href (http/https), path (file), or action (Agent follow-up)`);\n if (node2.variant !== void 0 && !["primary", "secondary", "text"].includes(node2.variant)) fail2("link/button variant must be primary/secondary/text");\n if (node2.href !== void 0) {\n if (typeof node2.href !== "string" || node2.href.length > 8192 || /[\\u0000-\\u0020\\u007f]/.test(node2.href) || !/^https?:\\/\\//i.test(node2.href)) fail2("href must be an absolute http/https URL; encode spaces");\n let url;\n try {\n url = new URL(node2.href);\n } catch {\n fail2("invalid href URL");\n }\n if (!url.hostname || url.username || url.password) fail2("href must have a host and must not contain credentials");\n }\n if (node2.path !== void 0) {\n if (typeof node2.path !== "string" || !node2.path.trim() || node2.path.length > 8192 || /[\\u0000-\\u001f\\u007f]/.test(node2.path) || /^\\s*(?:[a-z][a-z\\d+.-]*:|[\\\\/]{2})/i.test(node2.path) && !/^\\s*[a-z]:[\\\\/]/i.test(node2.path)) fail2("path must be a local file path, not a URL, network path or command");\n }\n }\n\n // lib/protocol.js\n var LIMITS = Object.freeze({ bytes: 131072, nodes: 160, depth: 12, rows: 500, expressions: 128, steps: 4096 });\n var own2 = (o, k2) => Object.hasOwn(o, k2);\n var fail = (message) => {\n throw new Error(`DSH UI: ${message}`);\n };\n var object2 = (x) => x !== null && typeof x === "object" && !Array.isArray(x);\n var finite = (x) => typeof x === "number" && Number.isFinite(x);\n var scalar = (x) => typeof x === "string" || typeof x === "boolean" || finite(x);\n var text = (x, at2) => {\n if (typeof x !== "string" || x.length > 8192) fail(`${at2} must be a string of at most 8192 characters`);\n };\n function fields(value, allowed, at2) {\n if (!object2(value)) fail(`${at2} must be an object`);\n for (const k2 of Object.keys(value)) if (!allowed.includes(k2)) {\n const hint = at2 === "document" ? " Controls and visual components belong in nodes as registered typed nodes, not extra document fields." : "";\n fail(`unknown field ${at2}.${k2}; allowed fields at ${at2}: ${allowed.join(", ")}.${hint}`);\n }\n }\n function safeJson(value, depth = 0, source = false) {\n if (depth > 48) fail("JSON nesting is too deep");\n if (value === null || typeof value === "boolean") return;\n if (typeof value === "string") {\n if (source) {\n if (value.length > SANDBOX_LIMITS.source) fail("canvas source exceeds 48 Ki characters");\n return;\n }\n return text(value, "value");\n }\n if (typeof value === "number") {\n if (!finite(value)) fail("numbers must be finite");\n return;\n }\n if (typeof value !== "object") fail("only JSON values are accepted");\n if (Array.isArray(value) && value.length > LIMITS.rows) fail("too many array items");\n for (const k2 of Object.keys(value)) {\n if (["__proto__", "prototype", "constructor"].includes(k2)) fail("unsafe property name");\n safeJson(value[k2], depth + 1, value.type === "sandbox" && ["html", "css", "script"].includes(k2));\n }\n }\n function initialState(doc2) {\n return Object.fromEntries(Object.entries(doc2.state).map(([k2, spec]) => [k2, spec.default]));\n }\n function validateState(doc2, state2) {\n if (!object2(state2) || Object.keys(state2).length !== Object.keys(doc2.state).length) fail("state keys do not match the document");\n const result = {};\n for (const [k2, s] of Object.entries(doc2.state)) {\n if (!own2(state2, k2)) fail(`missing state.${k2}`);\n const v2 = state2[k2];\n if (s.type === "number") {\n if (!finite(v2) || v2 < s.min || v2 > s.max) fail(`state.${k2} is outside its numeric range`);\n const offset = (v2 - s.min) / s.step;\n if (Math.abs(offset - Math.round(offset)) > 1e-6) fail(`state.${k2} does not match its step`);\n } else if (s.type === "json") {\n if (!object2(v2) && !Array.isArray(v2)) fail(`state.${k2} must be an array or object for type json`);\n safeJson(v2);\n if (new TextEncoder().encode(JSON.stringify(v2)).length > 16384) fail(`state.${k2} JSON exceeds 16 KiB`);\n } else if (s.type === "string") text(v2, `state.${k2}`);\n else if (typeof v2 !== "boolean") fail(`state.${k2} must be boolean`);\n if (s.options && !s.options.includes(v2)) fail(`invalid option for state.${k2}`);\n result[k2] = v2;\n }\n return result;\n }\n var ARITY = { add: [1, 8], sub: [2, 2], mul: [1, 8], div: [2, 2], min: [1, 8], max: [1, 8], round: [1, 1], ceil: [1, 1], floor: [1, 1], abs: [1, 1], eq: [2, 2], neq: [2, 2], lt: [2, 2], lte: [2, 2], gt: [2, 2], gte: [2, 2], if: [3, 3] };\n function reference(doc2, ref) {\n if (typeof ref !== "string" || !["state", "data", "derived"].includes(ref.split(".")[0]) || ref.split(".").length !== 2 || !validIdentifier(ref.split(".")[1])) fail(`invalid reference ${JSON.stringify(ref)}; use state.key, data.key or derived.key with a letter/underscore identifier`);\n const [group, k2] = ref.split(".");\n if (!own2(doc2[group], k2)) fail(`unknown reference ${ref}`);\n return [group, k2];\n }\n function evaluate(doc2, state2) {\n const derived = {}, active = /* @__PURE__ */ new Set();\n let steps = 0, generatedRows = 0;\n const budget = () => {\n if (++steps > LIMITS.steps) fail("calculation budget exceeded");\n };\n const resolve = (ref) => {\n budget();\n const [group, k2] = reference(doc2, ref);\n if (group !== "derived") return (group === "state" ? state2 : doc2.data)[k2];\n if (own2(derived, k2)) return derived[k2];\n if (active.has(k2)) fail(`cyclic calculation ${k2}`);\n active.add(k2);\n const result2 = expression2(doc2.derived[k2]);\n active.delete(k2);\n derived[k2] = result2;\n return result2;\n };\n const expression2 = (e, item) => {\n budget();\n if (own2(e, "map")) {\n const rows = resolve(e.map.source);\n if ((generatedRows += rows.length) > LIMITS.rows) fail("generated row limit exceeded");\n return rows.map((row) => Object.fromEntries(Object.entries(e.map.fields).map(([k2, value]) => {\n const out2 = expression2(value, row);\n if (!scalar(out2)) fail("generated cells must be scalar");\n return [k2, out2];\n })));\n }\n if (own2(e, "const")) return e.const;\n if (own2(e, "ref")) {\n if (e.ref.startsWith("item.")) {\n const k2 = e.ref.slice(5);\n if (!item || !own2(item, k2) || !scalar(item[k2])) fail("invalid item reference");\n return item[k2];\n }\n return resolve(e.ref);\n }\n if (e.op === "if") {\n const condition = expression2(e.args[0], item);\n if (typeof condition !== "boolean") fail("if condition must be boolean");\n return expression2(e.args[condition ? 1 : 2], item);\n }\n const a = e.args.map((arg) => expression2(arg, item));\n if (e.op === "eq") return a[0] === a[1];\n if (e.op === "neq") return a[0] !== a[1];\n if (!a.every(finite)) fail(`operator ${e.op} requires finite numbers`);\n let out;\n switch (e.op) {\n case "add":\n out = a.reduce((x, y2) => x + y2, 0);\n break;\n case "sub":\n out = a[0] - a[1];\n break;\n case "mul":\n out = a.reduce((x, y2) => x * y2, 1);\n break;\n case "div":\n if (a[1] === 0) fail("division by zero");\n out = a[0] / a[1];\n break;\n case "min":\n out = Math.min(...a);\n break;\n case "max":\n out = Math.max(...a);\n break;\n case "round":\n out = Math.round(a[0]);\n break;\n case "ceil":\n out = Math.ceil(a[0]);\n break;\n case "floor":\n out = Math.floor(a[0]);\n break;\n case "abs":\n out = Math.abs(a[0]);\n break;\n case "lt":\n return a[0] < a[1];\n case "lte":\n return a[0] <= a[1];\n case "gt":\n return a[0] > a[1];\n case "gte":\n return a[0] >= a[1];\n default:\n fail(`unsupported operator ${e.op}`);\n }\n if (!finite(out)) fail("non-finite calculation result");\n return out;\n };\n for (const k2 of Object.keys(doc2.derived)) resolve(`derived.${k2}`);\n if (new TextEncoder().encode(JSON.stringify(derived)).length > LIMITS.bytes) fail("derived output exceeds 128 KiB");\n const resolveCell = (cell) => {\n const out = expression2(cell);\n if (!scalar(out)) fail("inline row formula cells must resolve to a string, boolean or finite number");\n return out;\n };\n const result = { derived, resolveValue: (value) => {\n if (Array.isArray(value)) return value.map((row) => object2(row) ? Object.fromEntries(Object.entries(row).map(([k2, cell]) => [k2, object2(cell) && ["const", "ref", "op"].some((field) => own2(cell, field)) ? resolveCell(cell) : cell])) : row);\n if (!object2(value)) return value;\n return expression2(value);\n } };\n checkViewValues(doc2, result);\n return result;\n }\n function checkViewValues(doc2, evaluated) {\n function walk(list) {\n for (const n of list) {\n if (n.type === "table" || n.type === "chart") {\n const rows = evaluated.resolveValue(n.rows);\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object2)) fail("table/chart rows must reference an array of objects");\n if (n.type === "chart") {\n const index = rows.findIndex((r) => !own2(r, n.labelKey) || !scalar(r[n.labelKey]) || !own2(r, n.valueKey) || !finite(r[n.valueKey]));\n if (index >= 0) {\n const row = rows[index], missing = [n.labelKey, n.valueKey].filter((k2) => !own2(row, k2));\n fail("chart requires labels and finite numeric values. node." + n.id + ".rows[" + index + "]: " + (missing.length ? "missing field(s) " + missing.join(", ") : n.valueKey + " must resolve to a finite number") + ". Available keys: " + Object.keys(row).slice(0, 16).join(", ") + ". For live values use inline rows:[{" + n.labelKey + \':"\\u9879\\u76EE",\' + n.valueKey + \':{ref:"derived.amount"}}]; static data labels alone contain no amounts. Keep all nodes/state/derived when correcting the document\');\n }\n }\n if (n.type === "chart" && n.xScale === "linear" && rows.some((r) => !finite(r[n.labelKey]))) fail("linear chart requires numeric x values");\n }\n if (n.type === "metric" && !scalar(evaluated.resolveValue(n.value))) fail(`node.${n.id}.value must resolve to a number, string or boolean; use table for rows or a canvas for structured data`);\n if (n.type === "progress") {\n const v2 = evaluated.resolveValue(n.value), max = evaluated.resolveValue(n.max);\n if (!finite(v2) || !finite(max) || max <= 0 || v2 < 0 || v2 > max) fail("progress requires 0 <= value <= positive max");\n }\n if (n.children) walk(n.children);\n }\n }\n walk(doc2.nodes);\n }\n function validateDocument(input) {\n safeJson(input);\n const json = JSON.stringify(input);\n if (new TextEncoder().encode(json).length > LIMITS.bytes) fail("document exceeds 128 KiB");\n const normalized = normalizeAuthoring(JSON.parse(json));\n safeJson(normalized);\n const doc2 = expandExpressions(normalized);\n fields(doc2, ["version", "title", "fallback", "state", "data", "derived", "nodes", "actions", "presentation"], "document");\n if (doc2.presentation !== void 0) {\n fields(doc2.presentation, ["layout", "accent", "density", "preset"], "presentation");\n if (doc2.presentation.preset !== void 0 && !TEXT_PRESETS.includes(doc2.presentation.preset)) fail("unknown presentation preset; use " + TEXT_PRESETS.join("/"));\n for (const [k2, allowed] of Object.entries({ layout: UI_LAYOUTS, accent: UI_ACCENTS, density: ["comfortable", "compact"] }))\n if (doc2.presentation[k2] !== void 0 && !allowed.includes(doc2.presentation[k2])) fail(`unknown presentation ${k2}`);\n }\n if (doc2.version !== 1) fail(own2(doc2, "version") ? "document.version must be 1" : "document.version is missing. render_ui creates a complete document, not a partial patch: send {version:1,title,fallback,nodes:[...]} for shared controls/formulas, or {title,items:[...]} for extended visuals. Include all content, not only data/derived");\n text(doc2.title, "title");\n text(doc2.fallback, "fallback");\n if (!doc2.title.trim() || !doc2.fallback.trim()) fail("title and fallback cannot be empty");\n for (const group of ["state", "data", "derived", "actions"]) {\n doc2[group] ??= {};\n if (!object2(doc2[group]) || Object.keys(doc2[group]).length > 64) fail(`invalid ${group}`);\n for (const k2 of Object.keys(doc2[group])) if (!validIdentifier(k2)) fail(`invalid key in ${group}: ${JSON.stringify(k2)}; use 1..64 letters, numbers or underscores, starting with a letter/underscore (Chinese letters supported); no spaces, dots or hyphens. Put display labels in label/text`);\n }\n for (const [k2, s] of Object.entries(doc2.state)) {\n fields(s, ["type", "default", "min", "max", "step", "options"], `state.${k2}`);\n if (s.type === "string" && (Array.isArray(s.default) || object2(s.default)) && !own2(s, "options")) s.type = "json";\n if (!["number", "string", "boolean", "json"].includes(s.type)) fail(`unsupported state type ${k2}; use number, string, boolean or json (arrays/objects)`);\n if (s.type === "json" && own2(s, "options")) fail(`state.${k2}: json state does not support select options; use scalar options or a canvas`);\n if (s.type === "number") {\n for (const field of ["default", "min", "max", "step"]) if (!finite(s[field])) fail(`state.${k2}.${field} must be a finite JSON number; received ${s[field] === null ? "null" : typeof s[field]}. Supply {type:"number",default:2,min:1,max:12,step:1}; do not omit limits or include units in numeric fields`);\n if (s.min >= s.max || s.step <= 0) fail(`invalid numeric limits for state.${k2}: require min < max and step > 0; received min=${s.min}, max=${s.max}, step=${s.step}`);\n if ((s.max - s.min) / s.step > 1e9) fail(`numeric step too small for ${k2}`);\n } else if (["min", "max", "step"].some((p2) => own2(s, p2))) fail(`numeric limits on non-number ${k2}`);\n if (s.options !== void 0 && (!Array.isArray(s.options) || !s.options.length || s.options.length > 64 || !s.options.every(scalar))) fail(`state.${k2}.options must be a direct array of 1..64 scalar values, e.g. options:["3","5","7"], not {item:[...]}`);\n }\n const defaults = validateState(doc2, initialState(doc2));\n let expressions = 0;\n const expressionShapes = /* @__PURE__ */ new Set();\n for (const [k2, spec] of Object.entries(doc2.state))\n for (const option of spec.options ?? []) validateState(doc2, { ...defaults, [k2]: option });\n function validateExpression(e, depth = 0, itemRows, at2 = "expression") {\n if (depth > LIMITS.depth) fail(at2 + ": expression nesting exceeds " + LIMITS.depth);\n const shape = JSON.stringify(e);\n if (!expressionShapes.has(shape)) {\n expressionShapes.add(shape);\n if (++expressions > LIMITS.expressions) fail(at2 + ": expression limit exceeded (128 distinct expressions). Reuse derived references instead of expanding long formulas; keep the complete document when retrying");\n }\n if (!object2(e)) fail(`${at2}: expression must be an object`);\n if (own2(e, "map")) {\n if (depth !== 0) fail("map is only allowed at the root of a derived value");\n fields(e, ["map"], "expression");\n fields(e.map, ["source", "fields"], "map");\n if (typeof e.map.source !== "string" || !e.map.source.startsWith("data.")) fail(\'map source must reference static data using a string such as "data.samples"; put object rows in document.data.samples, not inline in map.source\');\n const [, k2] = reference(doc2, e.map.source), rows = doc2.data[k2];\n if (!Array.isArray(rows) || rows.length > LIMITS.rows || !rows.every(object2)) fail("map source must be object rows");\n if (!object2(e.map.fields) || !Object.keys(e.map.fields).length || Object.keys(e.map.fields).length > 16) fail("map requires 1..16 fields");\n for (const [k3, value2] of Object.entries(e.map.fields)) {\n if (!validIdentifier(k3)) fail(`invalid map field ${JSON.stringify(k3).slice(0, 100)}; use a letter/underscore identifier such as powerW or \\u529F\\u7387, without spaces, dots or hyphens`);\n validateExpression(value2, depth + 1, rows, `${at2}.map.fields.${k3}`);\n }\n return;\n }\n if (own2(e, "const")) {\n fields(e, ["const"], "expression");\n if (!scalar(e.const)) fail("constant must be scalar");\n return;\n }\n if (own2(e, "ref")) {\n fields(e, ["ref"], "expression");\n if (typeof e.ref === "string" && e.ref.startsWith("item.")) {\n const k2 = e.ref.slice(5);\n if (!itemRows || !validIdentifier(k2) || itemRows.some((row) => !own2(row, k2) || !scalar(row[k2]))) fail("invalid or unscoped item reference");\n } else reference(doc2, e.ref);\n return;\n }\n fields(e, ["op", "args"], "expression");\n const arity = ARITY[e.op];\n if (!arity || !Array.isArray(e.args) || e.args.length < arity[0] || e.args.length > arity[1]) fail(`${at2}: invalid operator or argument count for ${JSON.stringify(e.op)}; args must be a direct array${arity ? ` with ${arity[0]}..${arity[1]} expressions` : " and op must be registered"}. Received ${Array.isArray(e.args) ? e.args.length + " arguments" : typeof e.args}. Prefer {expr:"state.people * state.days"} for arithmetic; missing operands cannot be inferred`);\n e.args.forEach((a, i) => validateExpression(a, depth + 1, itemRows, `${at2}.args[${i}]`));\n }\n Object.entries(doc2.derived).forEach(([k2, e]) => validateExpression(e, 0, void 0, `derived.${k2}`));\n const visited = /* @__PURE__ */ new Set(), active = /* @__PURE__ */ new Set();\n function visit(k2) {\n if (active.has(k2)) fail(`cyclic calculation ${k2}`);\n if (visited.has(k2)) return;\n active.add(k2);\n function walk(e) {\n if (e.ref?.startsWith("derived.")) visit(e.ref.split(".")[1]);\n for (const a of e.args ?? []) walk(a);\n for (const value2 of Object.values(e.map?.fields ?? {})) walk(value2);\n }\n walk(doc2.derived[k2]);\n active.delete(k2);\n visited.add(k2);\n }\n Object.keys(doc2.derived).forEach(visit);\n for (const [k2, a] of Object.entries(doc2.actions)) {\n fields(a, ["type", "intent", "stateKeys"], `actions.${k2}`);\n if (a.type !== "agent.followup") fail("only agent.followup actions are supported");\n text(a.intent, "action intent");\n if (!a.intent.trim() || !Array.isArray(a.stateKeys) || a.stateKeys.length > 64 || new Set(a.stateKeys).size !== a.stateKeys.length || a.stateKeys.some((s) => !own2(doc2.state, s))) fail("invalid action stateKeys");\n }\n const ids = /* @__PURE__ */ new Map();\n let count2 = 0;\n const value = (v2, at2) => {\n if (object2(v2)) {\n if (own2(v2, "map")) fail("map belongs in derived");\n validateExpression(v2, 0, void 0, at2);\n } else if (!scalar(v2)) fail(`invalid value at ${at2}`);\n };\n function nodes(list, depth = 0, path = "nodes") {\n if (!Array.isArray(list)) fail(path === "nodes" ? \'document.nodes is missing or is not an array. State/derived define values but do not create visible UI. Include nodes:[{id:"heading",type:"heading",text:"..."},...] and actual controls in the SAME complete document; do not resend state/data/derived alone. Declared state keys: \' + Object.keys(doc2.state).join(", ") : path + " must be an array of child nodes; use children:[{id,type,...}]");\n if (depth > LIMITS.depth) fail(path + " exceeds maximum node depth " + LIMITS.depth);\n for (const [index, n] of list.entries()) {\n const at2 = `${path}[${index}]`;\n if (++count2 > LIMITS.nodes) fail("too many nodes");\n if (!object2(n)) fail(`${at2} must be a node object`);\n if (!own2(n, "id")) fail(`${at2}.id is missing (type=${JSON.stringify(n.type)}). Every node, including sandbox, needs its own id; add e.g. id:"canvas". JSON field order does not matter`);\n if (!validIdentifier(n.id)) fail(`${at2}.id is invalid: ${JSON.stringify(n.id)}. Use 1..64 letters/numbers/underscores starting with a letter/underscore`);\n if (ids.has(n.id)) fail(`${at2}.id duplicates ${JSON.stringify(n.id)} first declared at ${ids.get(n.id)}. Give each node a unique id; state keys and node ids are separate namespaces`);\n ids.set(n.id, `${at2}.id`);\n if (!Object.hasOwn(COMPONENTS, n.type)) fail("unsupported component " + n.type);\n if (["table", "chart"].includes(n.type) && typeof n.rows === "string" && /^(data|derived)\\./.test(n.rows)) n.rows = { ref: n.rows };\n switch (n.type) {\n case "visual": {\n const previous = Array.isArray(n.warnings) ? n.warnings.filter((x) => typeof x === "string").map((x) => x.slice(0, 512)).slice(0, 12) : [];\n const checked = validateVisual(n.spec);\n n.spec = checked.spec;\n n.warnings = [.../* @__PURE__ */ new Set([...previous, ...checked.warnings])].slice(0, 12);\n count2 += checked.count;\n if (count2 > LIMITS.nodes) fail("too many nodes, including visual components");\n if (!validIdentifier(n.stateKey) || doc2.state[n.stateKey]?.type !== "json") fail("visual requires its own json stateKey");\n break;\n }\n case "sandbox": {\n text(n.title, `${at2}.title (canvas title)`);\n text(n.fallback, `${at2}.fallback (canvas fallback)`);\n if (!n.title.trim()) fail(`${at2}.title must not be empty`);\n if (!n.fallback.trim()) fail(`${at2}.fallback must not be empty`);\n if (typeof n.html !== "string" || !n.html.trim()) fail(`${at2}.html must be a non-empty HTML string; script/css/fallback belong beside html on the sandbox node, not inside it`);\n for (const field of ["html", "css", "script"]) if (n[field] !== void 0 && (typeof n[field] !== "string" || n[field].length > SANDBOX_LIMITS.source)) fail("canvas source exceeds 48 Ki characters");\n if (n.libraries !== void 0 && (!Array.isArray(n.libraries) || n.libraries.length > 1 || n.libraries.some((v2) => v2 !== "mechanism"))) fail(\'canvas libraries supports only ["mechanism"] or []\');\n if (n.height !== void 0 && (!Number.isInteger(n.height) || n.height < 160 || n.height > SANDBOX_LIMITS.height)) fail("canvas height must be 160..1000");\n for (const [field, group] of [["stateKeys", "state"], ["dataKeys", "data"], ["derivedKeys", "derived"]]) if (n[field] !== void 0 && (!Array.isArray(n[field]) || n[field].length > 64 || new Set(n[field]).size !== n[field].length || n[field].some((k2) => !own2(doc2[group], k2)))) fail("invalid canvas " + field);\n break;\n }\n case "row":\n case "column":\n if (n.gap !== void 0 && !(typeof n.gap === "number" && Number.isFinite(n.gap) && n.gap >= 0 && n.gap <= 40)) fail("gap must be 0..40 pixels");\n if (n.columns !== void 0 && (!Number.isInteger(n.columns) || n.columns < 1 || n.columns > 4)) fail("columns must be 1..4");\n break;\n case "card":\n if (n.title !== void 0) text(n.title, "card title");\n if (n.surface !== void 0 && !UI_SURFACES.includes(n.surface)) fail("unknown card surface");\n break;\n case "details":\n text(n.title, "details title");\n if (n.open === "true" || n.open === "false") n.open = n.open === "true";\n if (n.open !== void 0 && typeof n.open !== "boolean") fail(`node.${n.id}.open must be boolean true or false`);\n break;\n case "badge":\n value(n.text, "badge text");\n break;\n case "progress":\n text(n.label, "progress label");\n value(n.value, "progress value");\n value(n.max, "progress max");\n if (n.unit !== void 0) text(n.unit, "progress unit");\n break;\n case "steps": {\n if (n.title !== void 0) text(n.title, "steps title");\n const at3 = `node.${n.id}.items`;\n if (!Array.isArray(n.items)) fail(`${at3} must be an array of 1..12 step objects, received ${n.items === null ? "null" : typeof n.items}. Use items:[{"title":"First step","description":"One sentence"}], not items:{item:[...]}. status is optional for a static guide`);\n if (!n.items.length || n.items.length > 12) fail(`${at3} requires 1..12 items; received ${n.items.length}. Split a longer guide into separate steps nodes`);\n for (const [i, item] of n.items.entries()) {\n const stepAt = `${at3}[${i}]`;\n fields(item, ["title", "description", "status"], stepAt);\n text(item.title, `${stepAt}.title`);\n if (item.description !== void 0) text(item.description, `${stepAt}.description`);\n if (item.status !== void 0 && !["pending", "active", "done", "error"].includes(item.status)) fail(`${stepAt}.status must be pending, active, done or error; omit status for a static guide`);\n }\n break;\n }\n case "heading":\n case "text":\n case "callout":\n if (n.type === "text") {\n if (n.title !== void 0) text(n.title, "text block title");\n if (n.copyable !== void 0 && typeof n.copyable !== "boolean") fail("copyable must be boolean");\n }\n validateTypography(n, `node.${n.id}`);\n if (n.spans !== void 0) {\n if (n.text !== void 0) fail(`node.${n.id}: use text or spans, not both`);\n if (!Array.isArray(n.spans) || !n.spans.length || n.spans.length > 80) fail("spans must contain 1..80 text fragments");\n for (const [i, span] of n.spans.entries()) {\n fields(span, ["text", ...TYPE_FIELDS], `node.${n.id}.spans[${i}]`);\n text(span.text, "span text");\n validateTypography(span, `node.${n.id}.spans[${i}]`);\n }\n } else value(n.text, "text");\n break;\n case "metric":\n text(n.label, "metric label");\n value(n.value, "metric value");\n if (n.unit !== void 0) text(n.unit, "unit");\n if (n.decimals !== void 0 && (!Number.isInteger(n.decimals) || n.decimals < 0 || n.decimals > 6)) fail("invalid decimals");\n break;\n case "input":\n case "slider":\n case "select":\n case "toggle": {\n text(n.label, "control label");\n if (typeof n.bind !== "string" || !n.bind.startsWith("state.")) fail("controls must bind state");\n const [, k2] = reference(doc2, n.bind), spec = doc2.state[k2];\n if (n.type === "slider" && spec.type !== "number") fail("slider requires numeric state");\n if (n.type === "toggle" && spec.type !== "boolean") fail("toggle requires boolean state");\n if (["input", "select"].includes(n.type) && spec.type === "json") fail(`node.${n.id}: structured state requires a sandbox with DSHUI.setState; use separate boolean states and toggle nodes for a native checklist`);\n if (n.type === "input" && spec.type === "boolean") fail("use toggle for boolean state");\n if (n.type === "select" && !spec.options) fail("select requires options");\n if (n.type === "select" && n.variant !== void 0 && !["dropdown", "segmented"].includes(n.variant)) fail(`node.${n.id}.variant must be dropdown or segmented`);\n break;\n }\n case "code":\n if (typeof n.code !== "string" || n.code.length > SANDBOX_LIMITS.source) fail("code must be a string of at most 48 Ki characters");\n if (n.lang !== void 0) text(n.lang, "code language");\n if (n.title !== void 0) text(n.title, "code title");\n if (n.wrap !== void 0 && typeof n.wrap !== "boolean") fail("code wrap must be boolean");\n break;\n case "button":\n case "link":\n text(n.text, "button text");\n validateLink(n);\n if (n.action !== void 0 && !own2(doc2.actions, n.action)) fail("unknown action");\n break;\n case "divider":\n if (n.label !== void 0) text(n.label, "divider label");\n break;\n case "table": {\n if (n.label !== void 0) text(n.label, "table label");\n if (!Array.isArray(n.rows)) value(n.rows, "node." + n.id + ".rows");\n if (!Array.isArray(n.columns) || !n.columns.length || n.columns.length > 16) fail("invalid table columns");\n const cols = /* @__PURE__ */ new Set();\n for (const c of n.columns) {\n fields(c, ["key", "label", "unit"], "column");\n if (!validIdentifier(c.key) || cols.has(c.key)) fail("invalid or duplicate column key");\n cols.add(c.key);\n text(c.label, "column label");\n if (c.unit !== void 0) text(c.unit, "column unit");\n }\n break;\n }\n case "chart":\n if (n.rows === void 0) fail("node." + n.id + \'.rows is missing; supply rows:[{label:"\\u9879\\u76EE",value:123}] or a rows binding, plus labelKey/valueKey matching its fields. Do not invent missing amounts\');\n if (!Array.isArray(n.rows)) value(n.rows, "node." + n.id + ".rows");\n if (!["bar", "line"].includes(n.kind) || !validIdentifier(n.labelKey) || !validIdentifier(n.valueKey)) fail("invalid chart");\n text(n.label, "chart label");\n if (n.unit !== void 0) text(n.unit, "chart unit");\n if (n.xScale !== void 0 && (!["category", "linear"].includes(n.xScale) || n.xScale === "linear" && n.kind !== "line")) fail("invalid xScale");\n break;\n default:\n fail(`unsupported component ${n.type}`);\n }\n if (["heading", "text", "callout", "card", "metric", "button", "link", "badge", "progress", "details"].includes(n.type)) {\n if (n.icon !== void 0 && !UI_ICONS.includes(n.icon)) fail("unknown UI icon");\n if (!["button", "link"].includes(n.type)) {\n if (n.tone !== void 0 && !UI_TONES.includes(n.tone)) fail("unknown UI tone");\n }\n }\n if (["table", "chart"].includes(n.type) && Array.isArray(n.rows)) {\n for (const [i, row] of n.rows.entries()) if (object2(row)) {\n for (const [k2, cell] of Object.entries(row)) if (object2(cell) && ["const", "ref", "op"].some((field) => own2(cell, field))) value(cell, at2 + ".rows[" + i + "]." + k2);\n }\n }\n fields(n, componentFields(n.type), `node.${n.id}`);\n if (["row", "column", "card", "details"].includes(n.type)) nodes(n.children, depth + 1, `${at2}.children`);\n }\n }\n nodes(doc2.nodes);\n if (!count2) fail("at least one node is required");\n evaluate(doc2, defaults);\n return doc2;\n }\n\n // src/export-runtime.js\n var payload = JSON.parse(document.getElementById("dsh-ui-export").textContent);\n var doc = validateDocument(payload.document);\n var node = doc.nodes.flatMap(function flatten(n) {\n return [n, ...(n.children ?? []).flatMap(flatten)];\n }).find((n) => n.id === payload.nodeId && n.type === "sandbox");\n if (!node) throw Error("\\u5BFC\\u51FA\\u7684\\u753B\\u5E03\\u4E0D\\u5B58\\u5728");\n var state = validateState(doc, payload.state);\n var connected = false;\n var start = Date.now();\n var count = 0;\n var token = () => Array.from(crypto.getRandomValues(new Uint8Array(16)), (b2) => b2.toString(16).padStart(2, "0")).join("");\n var channel = token();\n var nonce = payload.nonce;\n var frame = document.createElement("iframe");\n frame.title = node.title;\n frame.sandbox = "allow-scripts";\n frame.referrerPolicy = "no-referrer";\n frame.style.cssText = "display:block;width:100%;height:" + (node.height ?? 420) + "px;border:0";\n var status = document.getElementById("status");\n var sound = payload.soundtrack;\n var audio;\n var unlocked = false;\n var soundState;\n var caption;\n if (payload.captions?.length && !window.__DSHMotionRender) {\n caption = document.createElement("div");\n caption.setAttribute("aria-live", "off");\n caption.style.cssText = "position:absolute;bottom:5%;left:10%;right:10%;text-align:center;white-space:pre-line;pointer-events:none;font:600 clamp(14px,2.1vw,28px)/1.4 system-ui;color:white;text-shadow:0 1px 4px black";\n const surface = document.getElementById("surface");\n surface.style.position = "relative";\n surface.append(caption);\n }\n var soundAllowed = () => unlocked && soundState?.playing && !soundState.reducedMotion && soundState.visible && !document.hidden;\n if (sound && !window.__DSHMotionRender && /^[\\w-]+\\.(wav|mp3|m4a|aac|ogg|flac)$/.test(sound.file)) {\n audio = document.createElement("audio");\n audio.src = sound.file;\n audio.preload = "auto";\n audio.volume = Math.max(0, Math.min(1, sound.volume ?? 0.3));\n const button = document.createElement("button");\n button.textContent = "\\u5F00\\u542F\\u914D\\u4E50";\n button.type = "button";\n button.addEventListener("click", () => {\n unlocked = !unlocked;\n button.textContent = unlocked ? "\\u5173\\u95ED\\u914D\\u4E50" : "\\u5F00\\u542F\\u914D\\u4E50";\n if (!soundAllowed()) audio.pause();\n else audio.play().then(() => {\n if (!soundAllowed()) audio.pause();\n }).catch(() => {\n unlocked = false;\n button.textContent = "\\u70B9\\u51FB\\u91CD\\u8BD5\\u914D\\u4E50";\n });\n });\n status.before(button);\n status.before(audio);\n }\n var publish = () => {\n try {\n frame.contentWindow.postMessage({ dshCanvas: 1, channel, type: "snapshot", payload: { ...canvasSnapshot(node, state, doc.data, evaluate(doc, state).derived, false, payload.theme), visible: !document.hidden, motionSound: !!audio || !!caption } }, "*");\n } catch (e) {\n status.textContent = "\\u8BA1\\u7B97\\u5931\\u8D25\\uFF1A" + e.message;\n }\n };\n addEventListener("message", (event) => {\n const m2 = event.data;\n if (event.source !== frame.contentWindow || m2?.channel !== channel || m2.dshCanvas !== 1) return;\n if (Date.now() - start > 1e3) {\n start = Date.now();\n count = 0;\n }\n if (++count > SANDBOX_LIMITS.rate) return;\n if (m2.type === "ready") {\n connected = true;\n publish();\n } else if (m2.type === "patch" && connected) {\n try {\n const next = validateState(doc, { ...state, ...canvasPatch(m2.payload, node) });\n evaluate(doc, next);\n state = next;\n status.textContent = "\\u672C\\u5730\\u53C2\\u6570\\u5DF2\\u66F4\\u65B0\\uFF1B\\u5237\\u65B0\\u6587\\u4EF6\\u4F1A\\u56DE\\u5230\\u5BFC\\u51FA\\u65F6\\u7684\\u53C2\\u6570\\u3002";\n } catch (e) {\n status.textContent = "\\u53C2\\u6570\\u65E0\\u6548\\uFF1A" + e.message;\n }\n publish();\n } else if (m2.type === "height" && Number.isFinite(m2.payload) && m2.payload >= 0) frame.style.height = Math.max(32, Math.min(1e3, Math.ceil(m2.payload))) + "px";\n else if (m2.type === "error") status.textContent = "\\u753B\\u5E03\\u8FD0\\u884C\\u5F02\\u5E38\\uFF1A" + String(m2.payload).slice(0, 1e3);\n else if (m2.type === "timeline" && m2.payload.id === "main") {\n soundState = m2.payload;\n if (caption) caption.textContent = payload.captions.find((c) => m2.payload.time >= c.start && m2.payload.time < c.end)?.text ?? "";\n if (!audio) return;\n const t = m2.payload.time;\n if (Number.isFinite(t) && Math.abs(audio.currentTime - t) > 0.2) audio.currentTime = t;\n if (!soundAllowed()) audio.pause();\n else if (audio.paused) audio.play().then(() => {\n if (!soundAllowed()) audio.pause();\n }).catch(() => {\n unlocked = false;\n status.textContent = "\\u8BF7\\u70B9\\u51FB\\u5F00\\u542F\\u914D\\u4E50\\u4EE5\\u5141\\u8BB8\\u64AD\\u653E\\u58F0\\u97F3\\u3002";\n });\n }\n });\n document.addEventListener("visibilitychange", () => {\n if (document.hidden) audio?.pause();\n if (connected) publish();\n });\n addEventListener("pagehide", () => audio?.pause());\n document.getElementById("surface").append(frame);\n frame.srcdoc = sandboxDocument(node, channel, nonce);\n})();\n';
3711
3864
 
3712
3865
  // lib/canvas-export.js
3713
3866
  function standaloneCanvas(document2, node, state2, theme = {}, soundtrack, captions) {
@@ -4107,10 +4260,10 @@ function Sandbox({ node, document: doc, state: state2, data, derived, disabled,
4107
4260
  }
4108
4261
 
4109
4262
  // lib/build-info.js
4110
- var BUILD_INFO = Object.freeze({ "version": "0.8.2", "id": "0.8.2+6fdf57d9db59", "sourceHash": "6fdf57d9db591895145d01ed117f72cb06d080b49061ecb5a064d369ac6c3157" });
4263
+ var BUILD_INFO = Object.freeze({ "version": "0.8.4", "id": "0.8.4+c46ceb568893", "sourceHash": "c46ceb5688935d2508f4929e89c18c1e468f13cf9179f4183ffd910304d8daa0" });
4111
4264
 
4112
4265
  // lib/refinement.js
4113
- var AUDIT_MESSAGES = Object.freeze({ overflow: "\u5185\u5BB9\u8D85\u51FA\u89C6\u53E3\u5BBD\u5EA6", smallText: "\u6587\u5B57\u5B9E\u9645\u663E\u793A\u5C3A\u5BF8\u5C0F\u4E8E 12px", contrast: "\u6587\u5B57\u4E0E\u80CC\u666F\u5BF9\u6BD4\u5EA6\u504F\u4F4E", missingLabel: "\u4EA4\u4E92\u63A7\u4EF6\u7F3A\u5C11\u53EF\u8BBF\u95EE\u540D\u79F0", runtimeError: "\u753B\u5E03\u62A5\u544A\u8FD0\u884C\u5F02\u5E38", clippedText: "\u6587\u5B57\u53EF\u80FD\u88AB\u9690\u85CF\u6216\u88C1\u5207", bottomWhitespace: "\u5185\u5BB9\u4E0B\u65B9\u5B58\u5728\u660E\u663E\u7A7A\u767D" });
4266
+ var AUDIT_MESSAGES = Object.freeze({ overflow: "\u5185\u5BB9\u8D85\u51FA\u89C6\u53E3\u5BBD\u5EA6", smallText: "\u6587\u5B57\u5B9E\u9645\u663E\u793A\u5C3A\u5BF8\u5C0F\u4E8E 12px", contrast: "\u6587\u5B57\u4E0E\u80CC\u666F\u5BF9\u6BD4\u5EA6\u504F\u4F4E", missingLabel: "\u4EA4\u4E92\u63A7\u4EF6\u7F3A\u5C11\u53EF\u8BBF\u95EE\u540D\u79F0", runtimeError: "\u753B\u5E03\u62A5\u544A\u8FD0\u884C\u5F02\u5E38", clippedText: "\u6587\u5B57\u53EF\u80FD\u88AB\u9690\u85CF\u6216\u88C1\u5207", cardTextOverflow: "\u6587\u5B57\u8D85\u51FA\u5361\u7247\u5185\u5BB9\u8FB9\u754C\uFF1B\u8BF7\u4FDD\u7559\u9634\u5F71\u5E76\u8C03\u6574\u5BB9\u5668\u5C3A\u5BF8\u3001\u5185\u8FB9\u8DDD\u6216\u6587\u5B57\u6392\u7248", bottomWhitespace: "\u5185\u5BB9\u4E0B\u65B9\u5B58\u5728\u660E\u663E\u7A7A\u767D" });
4114
4267
 
4115
4268
  // src/current-document.js
4116
4269
  var import_react9 = require("react");
@@ -5761,7 +5914,7 @@ ${root} [data-motion-component=card],${root} [data-motion-component=stat]{border
5761
5914
  ${root} [data-motion-component=stat] [class*="statValue"]{font-size:var(--du-metric-size);font-weight:var(--du-title-weight);line-height:1.15;letter-spacing:-.7px}
5762
5915
  ${root} [data-motion-component=card] [class*="cardTitle"]{font-size:20px;font-weight:var(--du-title-weight)}
5763
5916
  ${root} [data-motion-visual] [class*="block"]{--dsl-g-radius-surface:var(--du-radius-inner);--dsl-g-radius-control:var(--du-action-radius);--dsl-g-font-body:16px;--dsl-g-font-title:18px}
5764
- ${root}[data-preset=reading],${root}[data-preset=minimal]{padding:0;border:0;background:transparent;box-shadow:none}
5917
+
5765
5918
  body[data-ds-dark-theme] ${root},${root}[data-preview-theme=dark]{--du-style-color:color-mix(in srgb,var(--du-style-wash) 58%,var(--du-style-base));--du-line:color-mix(in srgb,var(--du-style-color) 24%,var(--du-bg));--du-soft:color-mix(in srgb,var(--du-style-color) 8%,var(--du-bg))}
5766
5919
  body[data-ds-dark-theme] ${root}:not([data-accent]),${root}[data-preview-theme=dark]:not([data-accent]){--du-accent:var(--du-style-color)}
5767
5920
  ` + grammar("editorial", `
@@ -5835,6 +5988,9 @@ body[data-ds-dark-theme] &,&[data-preview-theme=dark]{background:var(--du-soft);
5835
5988
  ${root} .dgui-card[data-surface=featured]{border-color:var(--du-accent)}${root} .dgui-card[data-surface=soft]{background:var(--du-soft)}${root} .dgui-card[data-tone]>.dgui-section-title{color:var(--du-tone)}
5836
5989
  ${root} .dgui-steps li[data-step-status=active]{border-color:var(--du-accent)}${root} .dgui-step-dot .dgui-icon{color:inherit}
5837
5990
  @media(max-width:600px){${root}{padding:16px}${root}[data-preset=reading],${root}[data-preset=minimal]{padding:0}${root} .dgui-card,${root} .dgui-metric{padding:16px}${root} .dgui-control{padding:10px}${root}[data-visual-style=editorial] .dgui-card{padding:12px 0}${root}[data-visual-style=expressive] .dgui-metric{padding:10px 0}${root} .dgui-row:has(>.dgui-metric){flex-wrap:wrap}}
5991
+ /* Unframed presets win after every style grammar, including dark preview rules. */
5992
+ ${root}[data-preset=reading],${root}[data-preset=minimal]{padding:0;border:0;background:transparent;box-shadow:none}
5993
+ body[data-ds-dark-theme] ${root}[data-preset=reading],body[data-ds-dark-theme] ${root}[data-preset=minimal],${root}[data-preview-theme=dark][data-preset=reading],${root}[data-preview-theme=dark][data-preset=minimal]{background:transparent}
5838
5994
  @media(forced-colors:active){${root},${root} .dgui-card,${root} .dgui-metric,${root} .dgui-control,${root} .dgui-chart,${root} .motion-copy-block{background:Canvas;color:CanvasText;box-shadow:none;border-color:CanvasText}${root} .dgui-steps li{background:Canvas}}
5839
5995
  `;
5840
5996
 
@@ -6421,6 +6577,19 @@ var VISUAL_CSS = `
6421
6577
  // src/media-history.js
6422
6578
  var uuid = /^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/;
6423
6579
  var allowedFiles = /* @__PURE__ */ new Set(["video.mp4", "poster.jpg", "source.html", "project.zip"]);
6580
+ function inputAssetIds(value) {
6581
+ const clips = value.kind === "process" ? value.clips ?? value.recipe?.clips : null;
6582
+ if (!Array.isArray(clips)) return [];
6583
+ return [...new Set(clips.slice(0, 256).flatMap((clip) => {
6584
+ if (typeof clip?.path !== "string") return [];
6585
+ const parts = clip.path.replaceAll("\\", "/").split("/"), id2 = parts.at(-2);
6586
+ return parts.at(-1) === "video.mp4" && uuid.test(id2) ? [id2] : [];
6587
+ }))];
6588
+ }
6589
+ function visibleMediaRecords(records2) {
6590
+ const consumed = new Set(records2.flatMap((r) => r.inputAssetIds ?? []));
6591
+ return records2.filter((r) => !consumed.has(r.id));
6592
+ }
6424
6593
  function mediaRecord(message) {
6425
6594
  if (message?.isError) return null;
6426
6595
  for (const part of message?.content ?? []) {
@@ -6431,7 +6600,7 @@ function mediaRecord(message) {
6431
6600
  const files = (value.files ?? []).map((f) => typeof f === "string" ? f : f?.name).filter((f) => allowedFiles.has(f));
6432
6601
  if (!files.includes("video.mp4")) continue;
6433
6602
  const output = value.output ?? {}, positive = (n2) => typeof n2 === "number" && Number.isFinite(n2) && n2 > 0 ? n2 : null;
6434
- return { id: value.id, sessionId: value.sessionId, kind: value.kind, files: [...new Set(files)], documentId: uuid.test(value.documentId) ? value.documentId : null, documentRevision: Number.isSafeInteger(value.documentRevision) && value.documentRevision >= 0 ? value.documentRevision : null, nodeId: typeof value.nodeId === "string" ? value.nodeId : null, duration: positive(output.duration), width: positive(output.width), height: positive(output.height), hasAudio: Array.isArray(output.audio) ? output.audio.length > 0 : null };
6603
+ return { id: value.id, sessionId: value.sessionId, kind: value.kind, inputAssetIds: inputAssetIds(value), files: [...new Set(files)], documentId: uuid.test(value.documentId) ? value.documentId : null, documentRevision: Number.isSafeInteger(value.documentRevision) && value.documentRevision >= 0 ? value.documentRevision : null, nodeId: typeof value.nodeId === "string" ? value.nodeId : null, duration: positive(output.duration), width: positive(output.width), height: positive(output.height), hasAudio: Array.isArray(output.audio) ? output.audio.length > 0 : null };
6435
6604
  } catch {
6436
6605
  }
6437
6606
  }
@@ -6712,7 +6881,7 @@ function VideoPlayer({ record }) {
6712
6881
  function MediaRecords({ records: records2, sessionId }) {
6713
6882
  const owner = (0, import_react27.useRef)({});
6714
6883
  (0, import_react27.useLayoutEffect)(() => presentMedia(owner.current, sessionId, records2), [records2, sessionId]);
6715
- return h20(import_react27.default.Fragment, null, records2.filter((r) => r.sessionId === sessionId).map((record) => h20(VideoPlayer, { key: record.id, record })));
6884
+ return h20(import_react27.default.Fragment, null, visibleMediaRecords(records2.filter((r) => r.sessionId === sessionId)).map((record) => h20(VideoPlayer, { key: record.id, record })));
6716
6885
  }
6717
6886
  var mediaRoots = /* @__PURE__ */ new WeakMap();
6718
6887
  var allMediaRoots = /* @__PURE__ */ new Set();
@@ -6728,12 +6897,15 @@ function disposeSurface(entry) {
6728
6897
  function disposeMediaSurfaces() {
6729
6898
  for (const entry of [...allMediaRoots]) disposeSurface(entry);
6730
6899
  }
6900
+ function mediaSeat(anchor, scroll) {
6901
+ let seat = anchor.closest("[data-chat-turn]") ?? anchor;
6902
+ for (let el = anchor.parentElement; el && el !== scroll; el = el.parentElement)
6903
+ if (el.getAttribute("hidden") === "until-found") seat = el;
6904
+ return seat;
6905
+ }
6731
6906
  function placeOutsideFold(entry) {
6732
6907
  if (!entry.anchor?.isConnected) return;
6733
- let folded = null;
6734
- for (let el = entry.anchor; el && el !== entry.scroll; el = el.parentElement) if (el.getAttribute("hidden") === "until-found") folded = el;
6735
- if (!folded) return;
6736
- const seat = folded.parentElement, parent = seat === entry.scroll ? entry.scroll : seat.parentElement, before = seat === entry.scroll ? null : seat.nextSibling;
6908
+ const seat = mediaSeat(entry.anchor, entry.scroll), parent = seat.parentElement, before = seat.nextSibling;
6737
6909
  if (before === entry.host || !before && parent.lastChild === entry.host) return;
6738
6910
  try {
6739
6911
  if (parent.moveBefore) {
@@ -6773,9 +6945,7 @@ function MediaNodeView({ node, sessionId }) {
6773
6945
  return;
6774
6946
  }
6775
6947
  if (!entry) {
6776
- let folded = null;
6777
- for (let el = anchor.current; el && el !== scroll; el = el.parentElement) if (el.getAttribute("hidden") === "until-found") folded = el;
6778
- const seat = folded?.parentElement ?? anchor.current.closest("[data-chat-turn]") ?? anchor.current;
6948
+ const seat = mediaSeat(anchor.current, scroll);
6779
6949
  const host = document.createElement("div");
6780
6950
  host.dataset.motionMediaTurn = String(state2.turn);
6781
6951
  if (seat === scroll) scroll.append(host);