@three-blocks/devtools 4.0.0 → 5.0.0-alpha.320.g7e6e67cd7214

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @three-blocks/devtools
2
2
 
3
+ ## 5.0.0-alpha.320.g7e6e67cd7214
4
+
5
+ - Website: Stripe billing events now reach the production webhook reliably.
6
+
7
+ - Devtools: Loading no longer spins the status chip or terminal progress indicator.
8
+
9
+ - Devtools: Vite asset config and inspection handle HDR files and report exact GPU memory.
10
+
11
+ - Packages: Text projects hydrate precompiled shaders and stay crisp across display resolutions.
12
+
13
+ - Packages: Gaussian benchmarks now compare Babylon.js and fully revealed GaussianSplats3D scenes.
14
+
15
+ - Packages: Built from `7e6e67cd7214`.
16
+
17
+
3
18
  ## 4.0.0
4
19
 
5
20
  ### Minor Changes
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @three-blocks/devtools
2
2
 
3
- `@three-blocks/devtools` is the public, account-free command engine behind `npx three-blocks`. It captures and verifies WebGPU shaders and eligible shaders from `WebGPURenderer`'s WebGL fallback, generates text atlases, bakes environment lighting, and checks browser integrations. The runtime overlay and shader hydrator ship from `three-blocks/devtools` and `three-blocks/shaders` in the core package.
3
+ `@three-blocks/devtools` is the public, account-free command engine behind `npx three-blocks`. It captures and verifies WebGPU shaders and eligible shaders from `WebGPURenderer`'s WebGL fallback, generates text atlases, bakes environment lighting, optimizes GLB, texture, and HDR assets to meshopt + KTX2, and checks browser integrations. The runtime overlay and shader hydrator ship from `three-blocks/devtools` and `three-blocks/shaders` in the core package.
4
4
 
5
5
  ## Add Devtools to a Vite app
6
6
 
@@ -129,13 +129,15 @@ Use `npx three-blocks` in applications. This package also exposes `three-blocks-
129
129
  | --------------------------------------------- | --------------------------------------------------------------------------- |
130
130
  | `npx three-blocks status` | Report worker, asset, shader, and text state |
131
131
  | `npx three-blocks shaders` | Verify shader freshness without a browser or graphics processing unit (GPU) |
132
- | `npx three-blocks shaders capture --if-stale` | Capture changed scenes and write a local timing estimate |
132
+ | `npx three-blocks shaders capture --if-stale` | Capture changed scenes, write a local timing estimate, and optimize public GLB/HDR assets |
133
133
  | `npx three-blocks shaders test --parity-only` | Run one live and precompiled correctness pair per scene |
134
134
  | `npx three-blocks shaders test` | Run parity, repeated timing, and the published-page soak |
135
135
  | `npx three-blocks shaders watch` | Recapture when shader inputs change |
136
136
  | `npx three-blocks text generate` | Generate multi-channel signed distance field (MSDF) atlases and receipts |
137
137
  | `npx three-blocks text status` | Verify text assets and glyph coverage |
138
138
  | `npx three-blocks environment bake` | Bake a prefiltered environment KTX2 |
139
+ | `npx three-blocks optimize` | Compress GLB, texture, or HDR inputs to meshopt + KTX2 with exact VRAM math |
140
+ | `npx three-blocks assets status` | Re-verify the optimized-asset receipt (exit 1 with `--check` when stale) |
139
141
  | `npx three-blocks browser smoke` | Verify development readiness and hot module replacement (HMR) |
140
142
  | `npx three-blocks browser preview` | Build and verify the production preview |
141
143
 
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import {d}from'./chunk-EE64MV27.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import {b,a as a$1,c,h,d as d$1,f}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {readFile,lstat,readdir,realpath,mkdir}from'fs/promises';import i from'path';import {read,KHR_DF_PRIMARIES_BT709,write}from'ktx-parse';var U=2,ie="ktx2-encoder@0.6.0",ae=i.join(".three-blocks","assets"),ue=i.join(ae,"meta.json"),we=i.join(ae,"cache"),Te=256*1024*1024,Ae=64*1024*1024,ee=115e5,te=64,Ee=163,Re=166,ve=167,Se=1000066e3,de=1,le=2,$e=/baseColor|emissive|diffuse|sheenColor|specularColor/u,Me=/normal/iu,Oe=/(?:^|[_\-.])(?:normal|nrm|nor)(?:[_\-.]|map|$)/iu,_e=/(?:rough|metal|orm\b|occlusion|ambient|[_\-.]ao(?:[_\-.]|$)|height|disp|thick|mask)/iu;function Ie(t){return t.some(e=>Me.test(e))?"normal":t.some(e=>$e.test(e))||t.length===0?"color":"data"}a(Ie,"presetForTextureSlots");function De(t){let e=i.basename(t);return Oe.test(e)?"normal":_e.test(e)?"data":"color"}a(De,"presetForImageName");function V(t){let e=i.extname(t).toLowerCase();return e===".glb"?"glb":e===".png"||e===".jpg"||e===".jpeg"||e===".webp"?"image":e===".hdr"?"hdr":null}a(V,"assetKindFor");function P(t,e){let r=i.relative(t,e);return (r!==""&&!r.startsWith("..")&&!i.isAbsolute(r)?r:e).split(i.sep).join("/")}a(P,"portable");var X;function ce(){return X??=Promise.all([import('ktx2-encoder'),import('sharp')]).then(([t,e])=>({encodeToKTX2:t.encodeToKTX2,sharp:e.default})),X}a(ce,"loadEncoderTools");function me(t,e){let r=e.quality==="high";return t==="hdr"?{mode:"uastc-hdr",options:{isHDR:true,imageType:"hdr",isUASTC:true,isYFlip:true,generateMipmap:true,needSupercompression:true,hdrQualityLevel:r?2:1}}:t==="color"&&!r?{mode:"etc1s",options:{isUASTC:false,qualityLevel:160,compressionLevel:2,isPerceptual:true,isSRGB:true,generateMipmap:true}}:{mode:"uastc",options:{isUASTC:true,uastcLDRQualityLevel:r?2:1,enableRDO:true,rdoQualityLevel:1,generateMipmap:true,needSupercompression:true,isPerceptual:t==="color",isSRGB:t==="color",isNormalMap:t==="normal"}}}a(me,"encoderOptionsFor");function Le(t,e){let r=read(t),s=r.dataFormatDescriptor[0];if(s===void 0)return t;let n=e==="color"?le:de;return s.transferFunction===n&&(e!=="color"||s.colorPrimaries===KHR_DF_PRIMARIES_BT709)?t:(s.transferFunction=n,e==="color"&&(s.colorPrimaries=KHR_DF_PRIMARIES_BT709),write(r,{keepWriter:true}))}a(Le,"normalizeDfdTransfer");function he(t,e,r,s){let n=read(t),o=n.dataFormatDescriptor[0];if(o===void 0)throw new Error(`${s} produced a KTX2 container without a data format descriptor.`);if(e==="hdr"){if(n.vkFormat!==Se||o.colorModel!==ve)throw new Error(`${s} is not a UASTC HDR container (vkFormat ${n.vkFormat}, color model ${o.colorModel}).`)}else {let c=r==="etc1s"?Ee:Re;if(n.vkFormat!==0||o.colorModel!==c)throw new Error(`${s} is not a ${r} container (vkFormat ${n.vkFormat}, color model ${o.colorModel}).`)}let a=e==="color",u=o.transferFunction;if(a&&u!==le)throw new Error(`${s} must carry the sRGB transfer function; found ${u}.`);if(!a&&u!==de)throw new Error(`${s} must carry the linear transfer function; found ${u}.`);if(Math.max(n.pixelWidth,n.pixelHeight)>=8&&n.levels.length<2)throw new Error(`${s} is missing its mip chain.`);return {width:n.pixelWidth,height:n.pixelHeight,levels:n.levels.length}}a(he,"verifyKtx2");async function ye(t,e,r,s){let{encodeToKTX2:n,sharp:o}=await ce(),a$1=r.maxDimension,{mode:u,options:c}=me(e,r),d=performance.now(),m=false,p=Le(await n(t,{...c,imageDecoder:a(async $=>{let E=o($),M=await E.metadata(),O=M.width??0,b=M.height??0;if(O<1||b<1)throw new Error(`${s} has no decodable dimensions.`);let y=Math.min(1,a$1/Math.max(O,b));O*y*b*y>ee&&(y=Math.sqrt(ee/(O*b)));let x=y<1,w=x?Math.max(4,Math.floor(O*y/4)*4):O,I=x?Math.max(4,Math.floor(b*y/4)*4):b,_=x?E.resize(w,I,{fit:"fill",kernel:"lanczos3"}):E,{data:h,info:v}=await _.ensureAlpha().raw().toBuffer({resolveWithObject:true});for(let S=3;S<h.byteLength;S+=4)if(h[S]!==255){m=true;break}return {data:new Uint8Array(h.buffer,h.byteOffset,h.byteLength),width:v.width,height:v.height}},"decode")}),e),{width:f,height:R,levels:g}=he(p,e,u,s);return {bytes:p,width:f,height:R,levels:g,hasAlpha:m,mode:u,durationMs:performance.now()-d}}a(ye,"encodeLdrTexture");function Be(t,e){let r=new TextDecoder("latin1").decode(t.subarray(0,Math.min(t.byteLength,4096))),s=/-Y\s+(\d+)\s+\+X\s+(\d+)/u.exec(r);if(s?.[1]===void 0||s[2]===void 0)throw new Error(`${e} is not a supported Radiance .hdr file (missing "-Y <h> +X <w>" resolution).`);return {width:Number(s[2]),height:Number(s[1])}}a(Be,"hdrDimensions");async function ke(t,e,r){let s=Be(t,r);if(Math.max(s.width,s.height)>e.hdrMaxDimension)throw new Error(`${r} is ${s.width}x${s.height}, above the ${e.hdrMaxDimension}px HDR cap; resize the source (HDR resize is not supported yet).`);let{encodeToKTX2:n}=await ce(),{mode:o,options:a}=me("hdr",e),u=performance.now(),c=await n(t,a),{width:d,height:m,levels:A}=he(c,"hdr",o,r);return {bytes:c,width:d,height:m,levels:A,hasAlpha:false,mode:o,durationMs:performance.now()-u}}a(ke,"encodeHdrTexture");function pe(t,e,r,s){let n=0,o=t,a=e;for(let u=0;u<r;u+=1)n+=o*a*s,o=Math.max(1,o>>1),a=Math.max(1,a>>1);return n}a(pe,"uncompressedMipBytes");function q(t,e,r,s){let n=0,o=t,a=e;for(let u=0;u<r;u+=1)n+=Math.ceil(o/4)*Math.ceil(a/4)*s,o=Math.max(1,o>>1),a=Math.max(1,a>>1);return n}a(q,"compressedMipBytes");function fe(t,e){return t==="etc1s"&&!e?8:16}a(fe,"transcodedBlockBytes");async function Fe(t,e,r){let s=r.preset??De(e),n=`Image ${JSON.stringify(i.basename(e))}`,o=await ye(t,s,r,n),a=[`preset ${s} (${r.preset===null?"from filename":"explicit"})`];return s!=="color"&&a.push("linear DFD: consumers must treat this texture as non-color data"),a.push("compressed textures never flip: sample with glTF-style (flipY=false) UVs"),{bytes:o.bytes,metadata:{vramBytesIn:pe(o.width,o.height,o.levels,4),vramBytesOut:q(o.width,o.height,o.levels,fe(o.mode,o.hasAlpha)),textures:[{name:i.basename(e),slots:[],preset:s,mode:o.mode,width:o.width,height:o.height,bytesIn:t.byteLength,bytesOut:o.bytes.byteLength,durationMs:Math.round(o.durationMs)}],notes:a}}}a(Fe,"buildImageAsset");async function Pe(t,e,r){let s=`Environment ${JSON.stringify(i.basename(e))}`,n=await ke(t,r,s);return {bytes:n.bytes,metadata:{vramBytesIn:n.width*n.height*8,vramBytesOut:q(n.width,n.height,n.levels,16),textures:[{name:i.basename(e),slots:["equirectangular"],preset:"hdr",mode:n.mode,width:n.width,height:n.height,bytesIn:t.byteLength,bytesOut:n.bytes.byteLength,durationMs:Math.round(n.durationMs)}],notes:["BC6H on BC-capable devices; transcodes to RGBA16F elsewhere"]}}}a(Pe,"buildHdrAsset");async function Ne(t,e,r,s){let[{Logger:n,NodeIO:o},{ALL_EXTENSIONS:a,KHRTextureBasisu:u},{dedup:c,listTextureSlots:d,meshopt:m,prune:A,weld:p},{MeshoptDecoder:f,MeshoptEncoder:R}]=await Promise.all([import('@gltf-transform/core'),import('@gltf-transform/extensions'),import('@gltf-transform/functions'),import('meshoptimizer')]);await R.ready,await f.ready;let g=new o().registerExtensions(a).registerDependencies({"meshopt.encoder":R,"meshopt.decoder":f}),$=`GLB ${JSON.stringify(i.basename(e))}`;g.setLogger(new n(n.Verbosity.SILENT));let E=await g.readBinary(t);E.setLogger(new n(n.Verbosity.SILENT));let M=E.getRoot().listTextures();if(M.length>0&&M.every(h=>h.getMimeType()==="image/ktx2")&&E.getRoot().listExtensionsUsed().some(h=>h.extensionName==="EXT_meshopt_compression"))return {bytes:t,metadata:{vramBytesIn:0,vramBytesOut:0,textures:[],notes:["already optimized (KTX2 + meshopt); copied unchanged"]}};s?.("optimizing geometry"),await E.transform(c(),A({keepAttributes:true,keepExtras:true,keepSolidTextures:true}),p(),m({encoder:R,level:"medium"}));let b=[],y=[],x=0,w=0,I=0;for(let h of M){let v=h.getName()||h.getURI()||`texture-${b.length}`,S=h.getImage(),k=h.getMimeType();if(S===null||S.byteLength===0)continue;if(k==="image/ktx2"){y.push(`${v}: already KTX2, kept`);continue}if(!/^image\/(?:png|jpeg|webp)$/u.test(k)){y.push(`${v}: unsupported ${k}, kept`);continue}let z=h.getSize();if(z!==null&&Math.max(z[0],z[1])<te){y.push(`${v}: below ${te}px, kept`);continue}let W=d(h),j=Ie(W);s?.(`encoding ${v} (${j})`);let T=await ye(new Uint8Array(S),j,r,`${$} texture ${JSON.stringify(v)}`);h.setImage(T.bytes).setMimeType("image/ktx2");let G=h.getURI();G!==""&&h.setURI(G.replace(/\.(?:png|jpe?g|webp)$/iu,".ktx2")),I+=1,x+=pe(T.width,T.height,T.levels,4),w+=q(T.width,T.height,T.levels,fe(T.mode,T.hasAlpha)),b.push({name:v,slots:W,preset:j,mode:T.mode,width:T.width,height:T.height,bytesIn:S.byteLength,bytesOut:T.bytes.byteLength,durationMs:Math.round(T.durationMs)});}I>0&&E.createExtension(u).setRequired(true);let _=await g.writeBinary(E);return await g.readBinary(_),I>0&&y.push("requires a KTX2-wired loader (three-blocks/assets or GLTFLoader.setKTX2Loader)"),{bytes:_,metadata:{vramBytesIn:x,vramBytesOut:w,textures:b,notes:y}}}a(Ne,"buildGlbAsset");function Ce(t,e,r){let s=i.basename(t,i.extname(t));if(e==="glb"){let n=r===null?i.join(i.dirname(t),`${s}.tb.glb`):i.join(r,`${s}.glb`);if(i.resolve(n)===i.resolve(t))throw new Error(`Output would overwrite the input: ${JSON.stringify(t)}. Pass a different output directory.`);return n}return i.join(r??i.dirname(t),`${s}.ktx2`)}a(Ce,"outputPathFor");async function ge(t){let e={schemaVersion:U,tool:{name:"three-blocks-devtools",assetOptimizeVersion:U,encoder:ie},assets:{}},r;try{r=await readFile(t,"utf8");}catch(s){if(b(s)==="ENOENT")return e;throw s}if(r.length>a$1.receipt)return e;try{let s=JSON.parse(r);if(typeof s!="object"||s===null)return e;let n=s;return n.schemaVersion!==U||typeof n.assets!="object"||n.assets===null?e:{...e,assets:{...n.assets}}}catch{return e}}a(ge,"readReceipt");async function Ue(t){let e=[];for(let r of t){let s=i.resolve(r);if((await lstat(s)).isDirectory()){let o=[s],a=0;for(;o.length>0;){let u=o.shift();if(u===void 0)break;let c=(await readdir(u,{withFileTypes:true})).sort((d,m)=>d.name.localeCompare(m.name));for(let d of c){if(a+=1,a>8192)throw new Error("Input directory expansion exceeds the 8192-entry limit.");if(d.isSymbolicLink()||d.name.startsWith("."))continue;let m=i.join(u,d.name);if(d.isDirectory()){d.name!=="three-blocks"&&o.push(m);continue}d.isFile()&&!d.name.endsWith(".tb.glb")&&V(d.name)!==null&&e.push(m);}}}else e.push(s);}if(e.length===0)throw new Error("No optimizable inputs found (.glb, .png, .jpg, .webp, .hdr).");return e}a(Ue,"expandInputs");async function Ve(t){let e=await realpath(t.root),r={maxDimension:re(t.maxDimension,2048),hdrMaxDimension:re(t.hdrMaxDimension,4096),quality:t.quality??"default",preset:t.preset??null},s=t.outDir===void 0?null:i.resolve(e,t.outDir);s!==null&&await mkdir(s,{recursive:true});let n=i.join(e,we),o=i.join(e,ue),a$2=c(d({version:U,encoder:ie,...r})),u=await Ue(t.inputs),c$1=[],d$2=[],m=await ge(o);for(let[A,p]of u.entries()){let f$1=V(p);try{if(f$1===null)throw new Error(`Unsupported asset type ${JSON.stringify(i.extname(p))}; expected .glb, .png, .jpg, .webp, or .hdr (EXR sources are not supported yet \u2014 convert environments to .hdr).`);t.onProgress?.(`${i.basename(p)} (${A+1}/${u.length})`);let R=f$1==="glb"?Te:f$1==="hdr"?Ae:a$1.texture,g=await h(p,R,"Asset input"),$=g.path,E=c(g.data),M=c(`${E}\0${a$2}`),O=f$1==="glb"?"glb":"ktx2",b=i.join(n,`${M}.${O}`),y=i.join(n,`${M}.json`),x,w,I=!1;if(t.force!==!0&&await d$1(b)&&await d$1(y))x=(await h(b,R,"Cached asset")).data,w=JSON.parse((await h(y,a$1.metadata,"Cached asset metadata")).data.toString("utf8")),I=!0;else {let v=a(k=>t.onProgress?.(`${i.basename(p)}: ${k}`),"progress"),S=f$1==="glb"?await Ne(g.data,$,r,v):f$1==="hdr"?await Pe(g.data,$,r):await Fe(g.data,$,r);x=S.bytes,w=S.metadata,await f(b,x),await f(y,`${JSON.stringify(w,null," ")}
3
+ `);}let _=Ce($,f$1,s);await mkdir(i.dirname(_),{recursive:!0}),await f(_,x);let h$1=c(x);m.assets[P(e,$)]={kind:f$1,inputSha256:E,output:P(e,_),outputSha256:h$1,settingsSha256:a$2,bytesIn:g.data.byteLength,bytesOut:x.byteLength,vramBytesIn:w.vramBytesIn,vramBytesOut:w.vramBytesOut},c$1.push({input:P(e,$),output:P(e,_),kind:f$1,cached:I,bytesIn:g.data.byteLength,bytesOut:x.byteLength,vramBytesIn:w.vramBytesIn,vramBytesOut:w.vramBytesOut,textures:w.textures,notes:w.notes});}catch(R){d$2.push({input:P(e,p),error:R instanceof Error?R.message:String(R)});}}return c$1.length>0&&await f(o,`${JSON.stringify(m,null," ")}
4
+ `),{schemaVersion:1,command:"assets optimize",root:e,results:c$1,failed:d$2,bytesIn:c$1.reduce((A,p)=>A+p.bytesIn,0),bytesOut:c$1.reduce((A,p)=>A+p.bytesOut,0)}}a(Ve,"optimizeAssets");function re(t,e){if(t===void 0)return e;if(!Number.isInteger(t)||t<64||t>16384)throw new Error("Texture dimension caps must be integers between 64 and 16384.");return t}a(re,"boundedDimension");function D(t){if(t<1e3)return `${t} B`;if(t<1e6){let r=t/1e3;return `${r>=100?Math.round(r):r.toFixed(1)} kB`}let e=t/1e6;return `${e>=100?Math.round(e):e.toFixed(2)} MB`}a(D,"formatBytes");function ne(t,e){if(t===0)return "";let r=Math.round((e-t)/t*100);return r===0?"":` (${r>0?"+":""}${r}%)`}a(ne,"percentDelta");function qe(t){let e=[];for(let r of t.results){let s=r.cached?" \xB7 cached":"";e.push(`${r.input} -> ${r.output}`),e.push(` ${D(r.bytesIn)} -> ${D(r.bytesOut)}${ne(r.bytesIn,r.bytesOut)}${s}`),r.vramBytesOut>0&&e.push(` VRAM \u2248 ${D(r.vramBytesIn)} -> ${D(r.vramBytesOut)}`);for(let n of r.textures){let o=n.slots.length>0?` [${n.slots.join(", ")}]`:"";e.push(` ${n.name}${o} ${n.preset}/${n.mode} ${n.width}x${n.height} ${D(n.bytesIn)} -> ${D(n.bytesOut)}`);}for(let n of r.notes)e.push(` note: ${n}`);}for(let r of t.failed)e.push(`failed ${r.input}: ${r.error}`);return t.results.length>1&&e.push(`total ${D(t.bytesIn)} -> ${D(t.bytesOut)}${ne(t.bytesIn,t.bytesOut)}`),e.join(`
5
+ `)}a(qe,"formatAssetOptimizeReport");async function We(t,e){let r=await realpath(t),s=i.resolve(r,e);if(!await d$1(s))return [];let n=[],o=[s],a=0;for(;o.length>0;){let u=o.shift();if(u===void 0)break;let c=(await readdir(u,{withFileTypes:true})).sort((d,m)=>d.name.localeCompare(m.name));for(let d of c){if(a+=1,a>8192)throw new Error("Public asset discovery exceeds the 8192-entry limit.");if(d.isSymbolicLink()||d.name.startsWith("."))continue;let m=i.join(u,d.name);if(d.isDirectory()){if(u===s&&d.name==="three-blocks")continue;o.push(m);continue}if(!d.isFile()||d.name.endsWith(".tb.glb"))continue;let A=V(d.name);(A==="glb"||A==="hdr")&&n.push(m);}}return n.sort()}a(We,"discoverPublicAssets");async function Ge(t){let e=await realpath(t),r=await ge(i.join(e,ue)),s=[];for(let[n,o]of Object.entries(r.assets).sort(([a],[u])=>a.localeCompare(u))){let a=i.resolve(e,n),u=i.resolve(e,o.output),c$1="fresh";if(!await d$1(a))c$1="missing-input";else if(!await d$1(u))c$1="missing-output";else {let[d,m]=await Promise.all([readFile(a),readFile(u)]);(c(d)!==o.inputSha256||c(m)!==o.outputSha256)&&(c$1="stale");}s.push({input:n,output:o.output,kind:o.kind,state:c$1});}return {schemaVersion:1,command:"assets status",root:e,state:s.length===0?"empty":s.every(n=>n.state==="fresh")?"fresh":"stale",entries:s}}a(Ge,"inspectAssets");function Je(t){if(t.state==="empty")return "No optimized assets recorded. Run `assets optimize <file|directory>` first.";let e=t.entries.map(r=>`${r.state==="fresh"?"fresh ":r.state.padEnd(14)} ${r.input} -> ${r.output}`);return t.state==="stale"&&e.push("Some assets moved or changed; re-run `assets optimize` on the stale inputs."),e.join(`
6
+ `)}a(Je,"formatAssetStatusReport");function Ye(){X=void 0;}a(Ye,"resetAssetOptimizeToolsForTests");export{U as ASSET_OPTIMIZE_VERSION,ae as ASSET_RECEIPT_DIRECTORY,ue as ASSET_RECEIPT_FILE,We as discoverPublicAssets,qe as formatAssetOptimizeReport,Je as formatAssetStatusReport,Ge as inspectAssets,Ve as optimizeAssets,De as presetForImageName,Ie as presetForTextureSlots,Ye as resetAssetOptimizeToolsForTests};
package/dist/cli.js CHANGED
@@ -7,16 +7,16 @@ ${e}
7
7
  `)}a(ce,"formatShaderCapture");function ge(e){let t=[L(c.tick,"shaders",`no-GPU ${e.noGpu.state} ${c.dot} browser ${e.browser}`)];for(let o of e.scenes){let r=e.timing?.scenes[o.scene],c$1=r===void 0?`${o.coverage.render+o.coverage.compute} TSL build${o.coverage.render+o.coverage.compute===1?"":"s"} skipped`:`${r.builds} TSL build${r.builds===1?"":"s"} skipped ${c.dot} \u2248${ie(r.avoidedBuildMs)} ms \xB1 ${ie(r.spreadMs)} TSL work avoided ${c.dot} median of ${r.runs} ${c.dot} Latest local capture`,b$1=r!==void 0&&r.spreadMs>r.avoidedBuildMs*.4?` ${c.dot} ${b.warn("noisy measurement \u2014 close other GPU apps and re-run")}`:"";t.push(L(c.tick,o.scene,`${c$1} ${c.dot} ${o.coverage.compute} compute ${c.dot} ${(o.parity.diffRatio*100).toFixed(3)}% pixel diff${b$1}`));}return t.join(`
8
8
  `)}a(ge,"formatShaderTest");async function $e(){if(ue!==void 0)throw new Error(ue);if(v==="help"||v==="--help"||n.includes("--help"))return me();if(v==="version"||n.includes("--version")){f(h?JSON.stringify({version:a$1}):a$1);return}if(v==="browser"){let{formatBrowserPreviewReport:a,formatBrowserSmokeReport:m,runBrowserPreview:R,runBrowserSmoke:l}=await import('./browser-smoke-WWMWRM6S.js'),{findProjectRoot:y}=await import('./status-EK3BIJ2K.js');if(O==="preview"){let T=$("--root")??await y(),M=fe("--route"),F=$("--build-mode"),A=$("--expect-shaders")??"precompiled";if(A!=="precompiled"&&A!=="live")throw new Error('--expect-shaders must be "precompiled" or "live".');let _=k("--width"),X=k("--height"),P=k("--timeout"),V=k("--settle"),K=k("--min-luminance"),Y=C("building and verifying the production bundle"),z;try{z=await R({root:T,...M.length===0?{}:{routes:M},...F===void 0?{}:{buildMode:F},expectShaders:A,text:n.includes("--text"),...P===void 0?{}:{timeoutMs:P},...V===void 0?{}:{settleMs:V},...K===void 0?{}:{minimumLuminance:K},..._===void 0&&X===void 0?{}:{viewport:{width:_??1024,height:X??640}},headed:n.includes("--headed")});}finally{Y.stop();}s.stdout.write(`${h?JSON.stringify(z,null,2):a(z)}
9
9
  `),z.passed||(s.exitCode=1);return}if(O!=="smoke")throw new Error(`Unsupported browser command "${O??""}".`);let w=$("--root")??await y(),p=k("--width"),E=k("--height"),S=$("--route"),N=k("--timeout"),G=k("--settle"),I=k("--min-luminance"),j=$("--hmr");if(n.includes("--webgl")&&n.includes("--unsupported-worker"))throw new Error("--webgl and --unsupported-worker are mutually exclusive.");let B=C(`smoking ${S??"/"} in a real browser`),g;try{g=await l({root:w,...S===void 0?{}:{route:S},...N===void 0?{}:{timeoutMs:N},...G===void 0?{}:{settleMs:G},...I===void 0?{}:{minimumLuminance:I},...j===void 0?{}:{hmrModule:j},forceWebgl:n.includes("--webgl"),unsupportedWorker:n.includes("--unsupported-worker"),expectTextGenerationFailure:n.includes("--expect-text-generation-failure"),...p===void 0&&E===void 0?{}:{viewport:{width:p??1024,height:E??640}},headed:n.includes("--headed")});}finally{B.stop();}s.stdout.write(`${h?JSON.stringify(g,null,2):m(g)}
10
- `),g.passed||(s.exitCode=1);return}if(v==="assets"||v==="optimize"){let a$1=v==="optimize"?"optimize":O??"status",m=se.slice(v==="optimize"?1:2),{findProjectRoot:R}=await import('./status-EK3BIJ2K.js'),l=$("--root")??await R().catch(()=>s.cwd());if(a$1==="status"){let{formatAssetStatusReport:B,inspectAssets:g}=await import('./asset-optimize-WFEMLDJF.js'),T=await g(l);s.stdout.write(`${h?JSON.stringify(T,null,2):B(T)}
11
- `),n.includes("--check")&&T.state==="stale"&&(s.exitCode=1);return}if(a$1!=="optimize")throw new Error(`Unsupported assets command "${a$1}".`);if(m.length===0)throw new Error("assets optimize needs at least one file or directory (.glb, .png, .jpg, .webp, .hdr).");let y=$("--quality");if(y!==void 0&&y!=="default"&&y!=="high")throw new Error('--quality must be "default" or "high".');let w=$("--preset");if(w!==void 0&&w!=="color"&&w!=="normal"&&w!=="data")throw new Error('--preset must be "color", "normal", or "data".');let p=$("--out"),E=k("--max-dim"),S=k("--hdr-max-dim"),{formatAssetOptimizeReport:N,optimizeAssets:G}=await import('./asset-optimize-WFEMLDJF.js'),I=C("optimizing assets"),j;try{j=await G({root:l,inputs:m,...p===void 0?{}:{outDir:p},...E===void 0?{}:{maxDimension:E},...S===void 0?{}:{hdrMaxDimension:S},...y===void 0?{}:{quality:y},...w===void 0?{}:{preset:w},force:n.includes("--force"),onProgress:a(B=>I.update(`optimizing ${b.accent(B)}`),"onProgress")});}finally{I.stop();}s.stdout.write(`${h?JSON.stringify(j,null,2):N(j)}
10
+ `),g.passed||(s.exitCode=1);return}if(v==="assets"||v==="optimize"){let a$1=v==="optimize"?"optimize":O??"status",m=se.slice(v==="optimize"?1:2),{findProjectRoot:R}=await import('./status-EK3BIJ2K.js'),l=$("--root")??await R().catch(()=>s.cwd());if(a$1==="status"){let{formatAssetStatusReport:B,inspectAssets:g}=await import('./asset-optimize-KY2NOFIQ.js'),T=await g(l);s.stdout.write(`${h?JSON.stringify(T,null,2):B(T)}
11
+ `),n.includes("--check")&&T.state==="stale"&&(s.exitCode=1);return}if(a$1!=="optimize")throw new Error(`Unsupported assets command "${a$1}".`);if(m.length===0)throw new Error("assets optimize needs at least one file or directory (.glb, .png, .jpg, .webp, .hdr).");let y=$("--quality");if(y!==void 0&&y!=="default"&&y!=="high")throw new Error('--quality must be "default" or "high".');let w=$("--preset");if(w!==void 0&&w!=="color"&&w!=="normal"&&w!=="data")throw new Error('--preset must be "color", "normal", or "data".');let p=$("--out"),E=k("--max-dim"),S=k("--hdr-max-dim"),{formatAssetOptimizeReport:N,optimizeAssets:G}=await import('./asset-optimize-KY2NOFIQ.js'),I=C("optimizing assets"),j;try{j=await G({root:l,inputs:m,...p===void 0?{}:{outDir:p},...E===void 0?{}:{maxDimension:E},...S===void 0?{}:{hdrMaxDimension:S},...y===void 0?{}:{quality:y},...w===void 0?{}:{preset:w},force:n.includes("--force"),onProgress:a(B=>I.update(`optimizing ${b.accent(B)}`),"onProgress")});}finally{I.stop();}s.stdout.write(`${h?JSON.stringify(j,null,2):N(j)}
12
12
  `),j.failed.length>0&&(s.exitCode=1);return}if(v==="environment"){if(O!=="bake")throw new Error(`Unsupported environment command "${O??""}".`);let{bakeRoomEnvironment:a,formatEnvironmentBakeReport:m}=await import('./environment-bake-BGMGFAVK.js'),{findProjectRoot:R}=await import('./status-EK3BIJ2K.js'),l=$("--root")??await R(),y=k("--size"),w=$("--output"),p=k("--timeout"),E=C("baking the room environment on the GPU"),S;try{S=await a({root:l,...y===void 0?{}:{size:y},...w===void 0?{}:{output:w},...p===void 0?{}:{timeoutMs:p},compression:n.includes("--no-zstd")?"none":"zstd",headed:n.includes("--headed")});}finally{E.stop();}s.stdout.write(`${h?JSON.stringify(S,null,2):m(S)}
13
13
  `);return}if(v==="shaders"){let{findShaderProjectRoot:a$1}=await import('./shader-config-EOFU5D3Y.js'),m=O??"status";if(!["status","capture","test","watch"].includes(m))throw new Error(`Unsupported shader command "${m}".`);let R=$("--root"),l=await a$1(R),y=$("--driver");if(y!==void 0&&y!=="vite"&&y!=="static")throw new Error('--driver must be "vite" or "static".');let w=y,p=$("--serve"),E=$("--url"),S=$("--backend");if(S!==void 0&&S!=="webgpu"&&S!=="webgl"&&S!=="both")throw new Error('--backend must be "webgpu", "webgl", or "both".');let N=S;if(m==="status"){let{inspectShaderMatrix:g}=await import('./shader-workflow-BYF3IJOU.js'),{formatShaderMatrixStatus:T}=await import('./status-EK3BIJ2K.js'),M=await g(l,void 0,N);s.stdout.write(`${h?JSON.stringify(M,null,2):T(M)}
14
14
  `),(n.includes("--check")||O===void 0)&&M.state!=="fresh"&&(s.exitCode=1);return}if(m==="capture"){let{captureShaders:g}=await import('./shader-workflow-BYF3IJOU.js'),{applyShaderAutoWire:T,hasRegisterDevtoolsCall:M,inspectShaderAutoWire:F}=await import('./shader-autowire-SPE5DM2X.js'),{buildShaderCaptureProject:A,startNextShaderCaptureServer:_}=await import('./shader-project-runner-S2AID2RJ.js'),{inferShaderCaptureTarget:X}=await import('./shader-config-EOFU5D3Y.js'),P=w,V=p,K=E,Y,z,Q;try{if(P===void 0&&V===void 0&&K===void 0){let d=await F(l);if(!d.configured&&d.plan!==void 0){if(!await he(d.plan.diff))throw new Error("Adapter wiring was declined; no files were changed.");await T(d.plan);}else if(!d.configured&&d.bundler!=="vite"&&d.bundler!=="unknown")throw new Error(`${d.reason} No files were changed.`);if(d.bundler==="next")z=C("starting the project-local Next.js capture server"),Y=await _(l),K=Y.url,z.update("capturing shader scenes");else if(d.bundler==="webpack"||d.bundler==="esbuild"||d.bundler==="rollup"){z=C(`building the ${d.bundler} capture target`),await A(l);let x=await X(l);if(x.driverKind!=="static"||x.serve===void 0)throw new Error(`${d.bundler} build completed but no dist/, build/, or out/index.html was found; pass --driver static --serve <directory>.`);P="static",V=x.serve,z.update("capturing shader scenes");}}z??=C("capturing shader scenes"),Q=await g({root:l,headed:n.includes("--headed"),ifStale:n.includes("--if-stale"),commitTiming:n.includes("--commit-timing"),...N===void 0?{}:{backend:N},...P===void 0?{}:{driverKind:P},...V===void 0?{}:{serve:V},...K===void 0?{}:{url:K},onSceneStart:a((d,x,W)=>z?.update(`capturing ${b.accent(d)} ${b.dim(`(${x+1}/${W})`)}`),"onSceneStart"),onSceneRetry:a((d,x,W,q,D)=>{let Z=D instanceof Error&&/timed out/iu.test(D.message),ee=`capture attempt ${x}/${W} for "${d}" after ${Z?`timeout (${Math.round(q/1e3)} s burned)`:`failure (${D instanceof Error?D.message:String(D)})`}`;s.stderr.write(h?`${JSON.stringify({type:"shader-capture-retry",scene:d,attempt:x,total:W,timeoutMs:q,message:ee})}
15
15
  `:`${ee}
16
- `);},"onSceneRetry")});}finally{z?.stop(),await Y?.close();}let J;if(!n.includes("--no-assets"))try{let{discoverPublicAssets:d,optimizeAssets:x}=await import('./asset-optimize-WFEMLDJF.js'),{loadShaderToolConfig:W}=await import('./shader-config-EOFU5D3Y.js'),q=(await W(l)).publicDir??"public",D=await d(l,q);if(D.length>0){let Z=C("optimizing project assets");try{J=await x({root:l,inputs:D,onProgress:a(ee=>Z.update(`optimizing ${b.accent(ee)}`),"onProgress")});}finally{Z.stop();}}}catch(d){let x=`Asset optimization skipped: ${d instanceof Error?d.message:String(d)}`;s.stderr.write(h?`${JSON.stringify({type:"asset-optimize-error",message:x})}
16
+ `);},"onSceneRetry")});}finally{z?.stop(),await Y?.close();}let J;if(!n.includes("--no-assets"))try{let{discoverPublicAssets:d,optimizeAssets:x}=await import('./asset-optimize-KY2NOFIQ.js'),{loadShaderToolConfig:W}=await import('./shader-config-EOFU5D3Y.js'),q=(await W(l)).publicDir??"public",D=await d(l,q);if(D.length>0){let Z=C("optimizing project assets");try{J=await x({root:l,inputs:D,onProgress:a(ee=>Z.update(`optimizing ${b.accent(ee)}`),"onProgress")});}finally{Z.stop();}}}catch(d){let x=`Asset optimization skipped: ${d instanceof Error?d.message:String(d)}`;s.stderr.write(h?`${JSON.stringify({type:"asset-optimize-error",message:x})}
17
17
  `:`${c.warn} ${x}
18
18
  `);}let le=J===void 0?Q:{...Q,assets:J};if(s.stdout.write(`${h?JSON.stringify(le,null,2):ce(Q)}
19
- `),!h&&J!==void 0){let{formatAssetOptimizeReport:d}=await import('./asset-optimize-WFEMLDJF.js'),x=J.results.filter(q=>q.cached).length;f(L(J.failed.length>0?c.warn:c.tick,"assets",`${J.results.length} optimized${x>0?` (${x} cached)`:""} ${c.dot} ${b.dim("meshopt + KTX2, receipt .three-blocks/assets/meta.json")}`));let W=d(J);W.length>0&&f(W.split(`
19
+ `),!h&&J!==void 0){let{formatAssetOptimizeReport:d}=await import('./asset-optimize-KY2NOFIQ.js'),x=J.results.filter(q=>q.cached).length;f(L(J.failed.length>0?c.warn:c.tick,"assets",`${J.results.length} optimized${x>0?` (${x} cached)`:""} ${c.dot} ${b.dim("meshopt + KTX2, receipt .three-blocks/assets/meta.json")}`));let W=d(J);W.length>0&&f(W.split(`
20
20
  `).map(q=>` ${q}`).join(`
21
21
  `));}if(!await M(l)){let d="Add registerDevtools({ renderer }) from three-blocks/devtools so committed shader artifacts hydrate in development and production.";s.stderr.write(h?`${JSON.stringify({type:"shader-runtime-registration",state:"missing",message:d})}
22
22
  `:`${c.warn} ${d}
package/dist/index.d.ts CHANGED
@@ -1248,7 +1248,8 @@ declare function watchShaders(options?: WatchShadersOptions): Promise<ShaderWatc
1248
1248
  * their DFD, and LDR sources must be resized below the wasm encoder's
1249
1249
  * ~12-Mpix source ceiling before encoding.
1250
1250
  */
1251
- declare const ASSET_OPTIMIZE_VERSION = 1;
1251
+ /** v2: exact per-mip VRAM math persisted in receipt entries (invalidates v1 caches/receipts). */
1252
+ declare const ASSET_OPTIMIZE_VERSION = 2;
1252
1253
  declare const ASSET_RECEIPT_DIRECTORY: string;
1253
1254
  declare const ASSET_RECEIPT_FILE: string;
1254
1255
  type AssetKind = 'glb' | 'image' | 'hdr';
package/dist/index.js CHANGED
@@ -1,24 +1,24 @@
1
- import {c,d,b as b$1}from'./chunk-YHHGR2AJ.js';export{a as DOCUMENTED_BROWSER_NOISE,l as createAttachedPlaywrightShaderDriver,j as createPlaywrightShaderDriver,k as createStaticPlaywrightShaderDriver,b as isDocumentedBrowserNoise,i as isRetryableShaderObservationNavigation,c as webgpuBrowserArgs,d as webgpuBrowserHeadless}from'./chunk-YHHGR2AJ.js';import {a as a$1,l,d as d$1,f,j,e,i,g,m,h,B,v,w,q,r,t,o,k,c as c$1,K,A,z,H,y,s,x,G,R,Q,N as N$1,p,P,O,b}from'./chunk-3CKEE22B.js';export{o as SHADER_ARTIFACT_DIRECTORY,T as SHADER_CAPTURE_CLIENT_ID,D as SHADER_COMMITTED_TIMING_FILE,A as SHADER_DEVTOOLS_VERSION,C as SHADER_LOCAL_TIMING_FILE,p as SHADER_PARITY_DIRECTORY,E as SHADER_PARITY_EVIDENCE_FILE,B as SHADER_PROVIDER_TRANSFORM_VERSION,n as SHADER_TOOL_CONFIG_FILE,W as applyShaderProviderTransform,Y as assertShaderProviderTransform,X as createShaderProviderTransform,y as ensureShaderToolConfig,v as findShaderProjectRoot,x as inferShaderCaptureTarget,S as loadShaderCaptureRuntimeSource,w as loadShaderToolConfig,b as parseProjectMetadata,c as parseShaderReceipt,u as parseShaderToolConfig,M as readShaderCommittedTiming,J as readShaderLocalTiming,L as readShaderParityEvidence,K as readShaderTiming,I as serializeShaderManifest,F as shaderCoverage,H as stableStringify,G as validateShaderCapture,R as writeShaderArtifacts,N as writeShaderLocalTiming,O as writeShaderParityEvidence,Q as writeShaderTimingTwins}from'./chunk-3CKEE22B.js';export{b as compareShaderScreenshots,a as shaderScreenshotMetrics}from'./chunk-UDUICSME.js';import {a}from'./chunk-EI7MMDWY.js';import {rm,mkdir,writeFile,rename,realpath,readdir,readFile,lstat}from'fs/promises';import F from'path';import {createRequire}from'module';import {createHash,randomUUID}from'crypto';import Gt,{platform,homedir}from'os';import {fileURLToPath}from'url';import*as Rt from'zlib';import Rt__default from'zlib';import {createDefaultContainer,VK_FORMAT_R8G8B8A8_UNORM,KHR_SUPERCOMPRESSION_ZSTD,KHR_SUPERCOMPRESSION_NONE,KHR_DF_FLAG_ALPHA_STRAIGHT,KHR_DF_TRANSFER_LINEAR,KHR_DF_PRIMARIES_BT709,KHR_DF_MODEL_RGBSDA,KHR_DF_VERSION,KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,KHR_DF_VENDORID_KHRONOS,KHR_DF_CHANNEL_RGBSDA_RED,KHR_DF_CHANNEL_RGBSDA_GREEN,KHR_DF_CHANNEL_RGBSDA_BLUE,KHR_DF_CHANNEL_RGBSDA_ALPHA,KHR_DF_SAMPLE_DATATYPE_LINEAR,write,read,VK_FORMAT_R16G16B16A16_SFLOAT}from'ktx-parse';import oa from'msdf-bmfont-xml';import hn from'opentype.js';import {PNG}from'pngjs';import {SHADER_ADDRESS_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_HYDRATION_SCHEMA_VERSION}from'three-blocks/shaders';import {watch}from'fs';var Zr=4096,fs=createRequire(import.meta.url),Yr,Z=new Proxy({},{get(e,t){return Yr??=fs("typescript"),Reflect.get(Yr,t)}});function Oe(e){let t=e;for(;Z.isParenthesizedExpression(t)||Z.isAsExpression(t)||Z.isSatisfiesExpression(t)||Z.isNonNullExpression(t);)t=t.expression;return t}a(Oe,"unwrap");function ps(e){if(Z.isIdentifier(e)||Z.isStringLiteral(e)||Z.isNumericLiteral(e))return e.text}a(ps,"propertyName");function gt(e,t){let r=new Map;for(let n of e.properties){if(!Z.isPropertyAssignment(n))throw new Error(`${t} may contain only static property assignments.`);let o=ps(n.name);if(o===void 0||r.has(o))throw new Error(`${t} contains a computed or duplicate property.`);r.set(o,n.initializer);}return r}a(gt,"properties");function wt(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isObjectLiteralExpression(r))throw new Error(`${t} must be a static object literal.`);return r}a(wt,"objectLiteral");function bt(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isStringLiteral(r)&&!Z.isNoSubstitutionTemplateLiteral(r))throw new Error(`${t} must be a string literal.`);return r.text}a(bt,"stringLiteral");function Lt(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isNumericLiteral(r))throw new Error(`${t} must be a numeric literal.`);return Number(r.text)}a(Lt,"numericLiteral");function Qr(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isArrayLiteralExpression(r))throw new Error(`${t} must be a static array literal.`);return r.elements}a(Qr,"arrayLiteral");function hs(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(r.kind===Z.SyntaxKind.NullKeyword)return null;if(!Z.isNumericLiteral(r))throw new Error(`${t} must be null or a numeric literal.`);return Number(r.text)}a(hs,"numericOrNullLiteral");function ys(e){return e.parseDiagnostics??[]}a(ys,"parseDiagnostics");function jt(e,t,r,n){let o=Z.createSourceFile(t,e,Z.ScriptTarget.Latest,true,Z.ScriptKind.TS),s=ys(o);if(s.length>0)throw new Error(`Shader manifest is not valid TypeScript: ${Z.flattenDiagnosticMessageText(s[0]?.messageText??"parse error"," ")}`);let i=o.statements.filter(Z.isExportAssignment).filter(w=>!w.isExportEquals);if(i.length!==1)throw new Error("Shader manifest must contain exactly one default export.");let a$1=gt(wt(i[0]?.expression,"Shader manifest default export"),"Shader manifest"),c=a$1.get("version");if(c===void 0||!Z.isNumericLiteral(Oe(c))||Number(Oe(c).getText(o))!==3)throw new Error("Shader manifest version must be the numeric literal 3.");if(bt(a$1.get("scene"),"Shader manifest scene")!==r)throw new Error(`Shader manifest scene does not match "${r}".`);let u=a$1.get("runtime"),l=(n?.compatibility??(u===void 0?"":bt(gt(wt(u,"Shader manifest runtime"),"Shader manifest runtime").get("id"),"Shader manifest runtime id"))).startsWith("three-webgl-");if(n){if(bt(a$1.get("three"),"Shader manifest Three.js version")!==n.three||bt(a$1.get("threeBlocks"),"Shader manifest Three Blocks version")!==n.threeBlocks)throw new Error("Shader manifest runtime versions do not match its receipt.");let w=gt(wt(a$1.get("runtime"),"Shader manifest runtime"),"Shader manifest runtime");if(bt(w.get("id"),"Shader manifest runtime id")!==n.compatibility||Lt(w.get("address"),"Shader manifest address schema")!==n.address||Lt(w.get("recipe"),"Shader manifest recipe schema")!==n.recipe||Lt(w.get("hydration"),"Shader manifest hydration schema")!==n.hydration)throw new Error("Shader manifest runtime compatibility schemas do not match its receipt.")}let m=gt(wt(a$1.get("entries"),"Shader manifest entries"),"Shader manifest entries");if(m.size===0&&!l||m.size>Zr)throw new Error(`Shader manifest must contain ${l?"0":"1"}...${Zr} entries.`);let p=Qr(a$1.get("modules"),"Shader manifest modules").map((w,b)=>{let k=Oe(w);if(!Z.isStringLiteral(k)&&!Z.isNoSubstitutionTemplateLiteral(k))throw new Error(`Shader manifest module ${b} must be a shader string literal.`);if(k.text.length===0)throw new Error(`Shader manifest module ${b} is empty.`);return k.text}),h=Qr(a$1.get("states"),"Shader manifest states").map((w,b)=>{let k=gt(wt(w,`Shader manifest state ${b}`),`Shader manifest state ${b}`),g=a((C,S)=>{let B=hs(k.get(C),`Shader manifest state ${b} ${C}`);if(B===null)return false;let T=p[B];if(T===void 0||!l&&!T.includes(S))throw new Error(`Shader manifest state ${b} ${C} does not reference a ${S} module.`);return true},"moduleAt"),P=g("vertex","@vertex"),R=g("fragment","@fragment"),_=g("compute","@compute");if(_&&(P||R))throw new Error(`Shader manifest state ${b} mixes render and compute stages.`);if(!_&&!P&&!R)throw new Error(`Shader manifest state ${b} contains no shader stage.`);return {vertex:P,fragment:R,compute:_}}),y={render:0,vertex:0,fragment:0,compute:0};for(let[w,b]of m){if(w.length===0||/[\u0000-\u001f\u007f]/.test(w))throw new Error("Shader manifest contains an invalid entry key.");let k=Lt(b,`Shader manifest entry "${w}"`),g=h[k];if(g===void 0)throw new Error(`Shader manifest entry "${w}" references an absent state.`);(g.vertex||g.fragment)&&(y.render+=1),g.vertex&&(y.vertex+=1),g.fragment&&(y.fragment+=1),g.compute&&(y.compute+=1);}return y}a(jt,"inspectPrecompiledManifest");var bs=createRequire(import.meta.url),en,Y=new Proxy({},{get(e,t){return en??=bs("typescript"),Reflect.get(en,t)}}),Ss=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),ks=new Set(["script","style","template"]),tn=2e5,xs={amp:"&",apos:"'",copy:"\xA9",deg:"\xB0",gt:">",hellip:"\u2026",ldquo:"\u201C",lsquo:"\u2018",lt:"<",mdash:"\u2014",nbsp:"\xA0",ndash:"\u2013",quot:'"',rdquo:"\u201D",rsquo:"\u2019"};function Rs(e){return e.replace(/&(#x[0-9a-f]+|#[0-9]+|[a-z][a-z0-9]+);/giu,(t,r)=>{if(r.startsWith("#x")||r.startsWith("#X")){let n=Number.parseInt(r.slice(2),16);return St(n)?String.fromCodePoint(n):t}if(r.startsWith("#")){let n=Number.parseInt(r.slice(1),10);return St(n)?String.fromCodePoint(n):t}return xs[r.toLowerCase()]??t})}a(Rs,"decodeHtmlEntities");function St(e){return Number.isSafeInteger(e)&&e>=0&&e<=1114111&&!(e>=55296&&e<=57343)}a(St,"validCodePoint");function nn(e){return St(e)&&e>=32&&!(e>=127&&e<=159)}a(nn,"renderableCodePoint");function vs(e){return /(?:^|\s)data-canvas-text(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?(?=\s|\/?>)/iu.test(e)}a(vs,"hasCanvasTextAttribute");function ar(e){let t=[],r=[],n=e.match(/<!--[\s\S]*?-->|<![^>]*>|<[^>]*>|[^<]+/gu)??[];for(let o of n){if(!o.startsWith("<")){if(r.some(c=>c.synchronized)&&!r.some(c=>c.skipped)){let c=Rs(o);c.trim().length>0&&t.push(c);}continue}if(o.startsWith("<!--")||o.startsWith("<!")||o.startsWith("<?"))continue;let s=/^<\s*\//u.test(o),i=/^<\s*\/?\s*([a-z][a-z0-9:-]*)/iu.exec(o)?.[1]?.toLowerCase();if(!i)continue;if(s){let c=r.map(u=>u.tag).lastIndexOf(i);c>=0&&r.splice(c);continue}/\/\s*>$/u.test(o)||Ss.has(i)||r.push({tag:i,synchronized:vs(o),skipped:ks.has(i)});}return t}a(ar,"extractCanvasTextFromHtml");function Es(e){let t=new Set,r=new Set;for(let n of e.statements){if(!Y.isImportDeclaration(n)||!Y.isStringLiteral(n.moduleSpecifier)||n.moduleSpecifier.text!=="three-blocks/text")continue;let o=n.importClause?.namedBindings;if(o&&Y.isNamespaceImport(o)&&r.add(o.name.text),o&&Y.isNamedImports(o))for(let s of o.elements)(s.propertyName?.text??s.name.text)==="defineTextContent"&&t.add(s.name.text);}return {named:t,namespaces:r}}a(Es,"importedTextHelpers");function Ts(e,t){return Y.isIdentifier(e)?t.named.has(e.text):Y.isPropertyAccessExpression(e)&&Y.isIdentifier(e.expression)&&t.namespaces.has(e.expression.text)&&e.name.text==="defineTextContent"}a(Ts,"isDefineTextContentCall");function Bs(e){let t=e;for(;Y.isParenthesizedExpression(t)||Y.isAsExpression(t)||Y.isSatisfiesExpression(t)||Y.isTypeAssertionExpression(t);)t=t.expression;return t}a(Bs,"unwrapExpression");function sr(e,t,r){let n=Bs(e);if(Y.isStringLiteral(n)||Y.isNoSubstitutionTemplateLiteral(n)){t.push(n.text);return}if(Y.isArrayLiteralExpression(n)){for(let i of n.elements){if(Y.isSpreadElement(i))throw new Error(`${r}: defineTextContent() cannot use spread elements.`);sr(i,t,r);}return}if(Y.isObjectLiteralExpression(n)){for(let i of n.properties){if(!Y.isPropertyAssignment(i))throw new Error(`${r}: defineTextContent() accepts only static property assignments.`);sr(i.initializer,t,r);}return}let o=n.getStart(),s=n.getSourceFile().getLineAndCharacterOfPosition(o).line+1;throw new Error(`${r}:${s}: defineTextContent() contains dynamic text; declare a Unicode range or an explicit static string.`)}a(sr,"collectStaticStrings");function ir(e,t="content.ts"){let r=Y.createSourceFile(t,e,Y.ScriptTarget.Latest,true,t.endsWith(".tsx")?Y.ScriptKind.TSX:Y.ScriptKind.TS),n=Es(r),o=[];function s(i){if(Y.isCallExpression(i)&&Ts(i.expression,n)){if(i.arguments.length!==1||!i.arguments[0])throw new Error(`${t}: defineTextContent() requires exactly one static argument.`);sr(i.arguments[0],o,t);return}Y.forEachChild(i,s);}return a(s,"visit"),s(r),o}a(ir,"extractDefinedTextContent");function $s(e){let t=[];if(e==="latin"){for(let r=32;r<=126;r++)t.push(r);for(let r of "\u2018\u2019\u201C\u201D\u2013\u2014\u2026\u2022\xB7\xAB\xBB\u2039\u203A\u20AC\xA3\xA5\xB0\xB1\xD7\xF7\xA9\xAE\u2122\xA0"){let n=r.codePointAt(0);n!==void 0&&t.push(n);}}else {for(let r=12353;r<=12438;r++)t.push(r);for(let r=12443;r<=12447;r++)t.push(r);for(let r=12448;r<=12543;r++)t.push(r);for(let r of "\u3000\u3001\u3002\u300C\u300D\u300E\u300F\uFF08\uFF09\u30FB\u30FC\u301C\u3008\u3009\u300A\u300B\u3010\u3011\uFF01\uFF1F\uFF1A\uFF1B\uFF10\uFF11\uFF12\uFF13\uFF14\uFF15\uFF16\uFF17\uFF18\uFF19\uFF05\uFF06"){let n=r.codePointAt(0);n!==void 0&&t.push(n);}}return t}a($s,"presetCodePoints");function rn(e,t){for(let r of t.normalize("NFC")){let n=r.codePointAt(0);n!==void 0&&nn(n)&&e.add(n);}}a(rn,"addCharacters");function dr(e,t={}){let r=new Set;for(let a of e)rn(r,a);t.additionalCharacters&&rn(r,t.additionalCharacters);for(let a of t.presets??[])for(let c of $s(a))r.add(c);let n=0;for(let a of t.ranges??[]){if(!St(a.start)||!St(a.end)||a.end<a.start)throw new RangeError("Text Unicode ranges must contain ordered Unicode scalar values.");if(n+=a.end-a.start+1,n>tn)throw new RangeError(`Configured Unicode ranges exceed the ${tn}-code-point safety limit.`);for(let c=a.start;c<=a.end;c++)nn(c)&&r.add(c);}r.add(32),r.add(63),r.add(65533);let o=[...r].sort((a,c)=>a-c),s=o.map(a=>String.fromCodePoint(a)).join(""),i=createHash("sha256").update(s.normalize("NFC")).digest("hex");return {codePoints:o,characters:s,hash:i}}a(dr,"buildGlyphSet");var As=createRequire(import.meta.url),on,D=new Proxy({},{get(e,t){return on??=As("typescript"),Reflect.get(on,t)}});function _s(e){let t=e;for(;D.isParenthesizedExpression(t)||D.isAsExpression(t)||D.isSatisfiesExpression(t)||D.isTypeAssertionExpression(t);)t=t.expression;return t}a(_s,"unwrap");function Ms(e,t){if(D.isIdentifier(e)||D.isStringLiteral(e)||D.isNumericLiteral(e))return e.text;throw new Error(`${t}: text configuration property names must be static.`)}a(Ms,"propertyName");function Dt(e,t){let r=_s(e);if(D.isStringLiteral(r)||D.isNoSubstitutionTemplateLiteral(r))return r.text;if(D.isNumericLiteral(r))return Number(r.text);if(r.kind===D.SyntaxKind.TrueKeyword)return true;if(r.kind===D.SyntaxKind.FalseKeyword)return false;if(r.kind===D.SyntaxKind.NullKeyword)return null;if(D.isPrefixUnaryExpression(r)&&(r.operator===D.SyntaxKind.MinusToken||r.operator===D.SyntaxKind.PlusToken)){let o=Dt(r.operand,t);if(typeof o=="number")return r.operator===D.SyntaxKind.MinusToken?-o:o}if(D.isArrayLiteralExpression(r))return r.elements.map(o=>{if(D.isSpreadElement(o))throw new Error(`${t}: text configuration cannot use spread elements.`);return Dt(o,t)});if(D.isObjectLiteralExpression(r)){let o=Object.create(null);for(let s of r.properties){if(!D.isPropertyAssignment(s))throw new Error(`${t}: text configuration accepts only static property assignments.`);let i=Ms(s.name,t);if(Object.hasOwn(o,i))throw new Error(`${t}: duplicate text configuration property "${i}".`);o[i]=Dt(s.initializer,t);}return o}let n=r.getSourceFile().getLineAndCharacterOfPosition(r.getStart()).line+1;throw new Error(`${t}:${n}: text configuration must be statically inspectable.`)}a(Dt,"evaluateStatic");function Cs(e){let t=new Set,r=new Set;for(let n of e.statements){if(!D.isImportDeclaration(n)||!D.isStringLiteral(n.moduleSpecifier)||n.moduleSpecifier.text!=="three-blocks/text")continue;let o=n.importClause?.namedBindings;if(o&&D.isNamespaceImport(o)&&r.add(o.name.text),o&&D.isNamedImports(o))for(let s of o.elements)(s.propertyName?.text??s.name.text)==="defineText"&&t.add(s.name.text);}return {named:t,namespaces:r}}a(Cs,"helperNames");function Os(e,t){return D.isIdentifier(e)?t.named.has(e.text):D.isPropertyAccessExpression(e)&&D.isIdentifier(e.expression)&&t.namespaces.has(e.expression.text)&&e.name.text==="defineText"}a(Os,"isDefineTextCall");function $e(e,t){if(typeof e!="string"||e.trim().length===0)throw new Error(`${t} must be a non-empty string.`);return e}a($e,"requiredString");function Nt(e,t,r=false){if(!Array.isArray(e)||!r&&e.length===0)throw new Error(`${t} must be ${r?"an":"a non-empty"} array of strings.`);return e.map((n,o)=>$e(n,`${t}[${o}]`))}a(Nt,"stringArray");function Vt(e,t){if(e.includes("\\")||F.posix.isAbsolute(e)||F.posix.normalize(e)!==e||e===".."||e.startsWith("../")||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a safe project-relative path.`);return e}a(Vt,"safeProjectPath");function Fs(e,t){if(!a$1(e))throw new Error(`${t} must be an object.`);let r=Object.keys(e).sort();if(r.length===1&&r[0]==="builtin")return {builtin:$e(e.builtin,`${t}.builtin`)};if(r.length===1&&r[0]==="path")return {path:Vt($e(e.path,`${t}.path`),`${t}.path`)};if(r.join(",")==="checksum,file,package")return {package:$e(e.package,`${t}.package`),file:Vt($e(e.file,`${t}.file`),`${t}.file`),checksum:$e(e.checksum,`${t}.checksum`)};throw new Error(`${t} must select exactly one supported source.`)}a(Fs,"parseFontSource");function cr(e,t){let r=$e(e,t);if(r.includes("\\")||/[\u0000-\u001f\u007f]/u.test(r)||r.split("/").includes(".."))throw new Error(`${t} is unsafe.`);return r}a(cr,"deployedPath");function Is(e){if(e===void 0)return {};if(!a$1(e))throw new Error("Text generation options must be an object.");let t=e.presets===void 0?void 0:Nt(e.presets,"Text generation presets",true).map(c=>{if(c!=="latin"&&c!=="japanese-kana")throw new Error(`Unsupported text preset "${c}".`);return c}),r;if(e.ranges!==void 0){if(!Array.isArray(e.ranges))throw new Error("Text generation ranges must be an array.");r=e.ranges.map((c,u)=>{if(!a$1(c)||typeof c.start!="number"||typeof c.end!="number")throw new Error(`Text generation range ${u} is invalid.`);return {start:c.start,end:c.end}});}let n=a(c=>{let u=e[c];if(u!==void 0){if(typeof u!="number"||!Number.isFinite(u))throw new Error(`Text generation ${c} must be finite.`);return u}},"numeric"),o=n("size"),s=n("distanceRange"),i=n("padding"),a$2=n("maxTextureSize");return {...t===void 0?{}:{presets:t},...r===void 0?{}:{ranges:r},...e.additionalCharacters===void 0?{}:{additionalCharacters:$e(e.additionalCharacters,"Text generation additionalCharacters")},...o===void 0?{}:{size:o},...s===void 0?{}:{distanceRange:s},...i===void 0?{}:{padding:i},...a$2===void 0?{}:{maxTextureSize:a$2}}}a(Is,"parseGeneration");function Ls(e){if(!a$1(e)||e.schemaVersion!==void 0&&e.schemaVersion!==1)throw new Error("Text configuration must use schemaVersion 1.");let t=Nt(e.content,"Text content inputs").map(o=>Vt(o,"Text content input"));if(!a$1(e.fonts)||Object.keys(e.fonts).length===0)throw new Error("Text fonts must be a non-empty object.");let r={},n=0;for(let[o,s]of Object.entries(e.fonts)){if($e(o,"Text font key"),!a$1(s))throw new Error(`Text font "${o}" must be an object.`);let i=s.default===true;i&&n++,r[o]={source:Fs(s.source,`Text font "${o}" source`),browser:cr(s.browser,`Text font "${o}" browser path`),atlas:cr(s.atlas,`Text font "${o}" atlas path`),metrics:cr(s.metrics,`Text font "${o}" metrics path`),families:Nt(s.families,`Text font "${o}" families`),languages:s.languages===void 0?[]:Nt(s.languages,`Text font "${o}" languages`,true),default:i};}if(Object.keys(r).length>1&&n!==1)throw new Error("Multiple text fonts require exactly one default route.");if(n>1)throw new Error("Text fonts can select only one default route.");return {schemaVersion:1,content:t,fonts:r,generation:Is(e.generation)}}a(Ls,"validateConfiguration");function sn(e,t="three-blocks.text.ts"){let r=D.createSourceFile(t,e,D.ScriptTarget.Latest,true,D.ScriptKind.TS),n=Cs(r),o=[];function s(i){if(D.isCallExpression(i)&&Os(i.expression,n)){if(i.arguments.length!==1||!i.arguments[0])throw new Error(`${t}: defineText() requires one static argument.`);o.push(Dt(i.arguments[0],t));return}D.forEachChild(i,s);}if(a(s,"visit"),s(r),o.length!==1)throw new Error(`${t} must contain exactly one imported defineText() call.`);return Ls(o[0])}a(sn,"parseTextConfiguration");function lr(e,t){if(typeof e=="string")t.push(e);else if(Array.isArray(e))for(let r of e)lr(r,t);else if(a$1(e))for(let r of Object.values(e))lr(r,t);}a(lr,"jsonStrings");async function Ht(e,t="three-blocks.text.ts"){let r=Vt(t,"Text configuration path"),n=await l(e,F.join(e,r),d$1.semanticInput,"Text configuration");return sn(n.data.toString("utf8"),r)}a(Ht,"readTextConfiguration");async function Ut(e,t){let r=[],n={},o=0;for(let s of t.content){let i=await l(e,F.join(e,s),d$1.semanticInput,"Text content input");if(o+=i.data.byteLength,o>d$1.semanticTotal)throw new Error("Text content inputs exceed the total inspection size limit.");n[s]=f(i.data);let a=i.data.toString("utf8"),c=F.extname(s).toLowerCase();if(c===".html"||c===".htm")r.push(...ar(a));else if([".ts",".tsx",".js",".jsx",".mts",".cts",".mjs",".cjs"].includes(c))r.push(...ir(a,s));else if(c===".json")lr(JSON.parse(a),r);else if(c===".txt"||c===".md")r.push(a);else throw new Error(`Unsupported configured text content type: ${s}.`)}return {values:r,glyphs:dr(r,t.generation),inputs:n}}a(Ut,"discoverTextContent");var gr=1,vt="1.0.0",aa=Object.freeze({"geist-sans":{id:"geist-sans",family:"Geist Sans",version:"1.600",license:"OFL-1.1",licenseFile:"OFL-1.1.txt",sourceFile:"geist-sans/Geist-Variable.ttf",sourceUrl:"https://raw.githubusercontent.com/vercel/geist-font/1.6.0/fonts/Geist/variable/Geist%5Bwght%5D.ttf",sourceBytes:168472,sourceChecksum:"995c579489b33cd28a6732d7aa7ca1b46c2faa832c18b4063933d7652c39932b",browserFile:"geist-sans/Geist-Variable.woff2",browserUrl:"https://raw.githubusercontent.com/vercel/geist-font/449415077ee4ffc191b4e7e557cd35e88b1b98fd/packages/next/dist/fonts/geist-sans/Geist-Variable.woff2",browserBytes:58512,browserChecksum:"46525b05bbf4527d263f8624ca7024c7d0dce3c64430267d30c31c6dd3821e4d"},"noto-sans-jp":{id:"noto-sans-jp",family:"Noto Sans JP",version:"2.004-H2",license:"OFL-1.1",licenseFile:"OFL-1.1.txt",sourceFile:"noto-sans-jp/NotoSansJP[wght].ttf",sourceUrl:"https://raw.githubusercontent.com/google/fonts/295d98a7a0c17c68f1341eaeea354e7960ea70d3/ofl/notosansjp/NotoSansJP%5Bwght%5D.ttf",sourceBytes:9589900,sourceChecksum:"c2f3b4d463500a2ddcd3849cded1fceeb9fd6d1c32e6cbecd568453ba50fc68f",browserFile:"noto-sans-jp/NotoSansJP[wght].woff2",browserUrl:"https://raw.githubusercontent.com/RenaudRohlinger/three-blocks-monorepo/364a50cc5f6f92735a110b50144e8d62404c9d87/packages/three-blocks-devtools/fonts/noto-sans-jp/NotoSansJP%5Bwght%5D.woff2",browserBytes:4350080,browserChecksum:"6fd94964d1990baa2a392cea7a036683d2b80b9dfd590cb3918e8dab98d8e188"}}),ia="THREE_BLOCKS_FONT_CACHE_DIR",da=6e4,Wt=new Map,ca=fileURLToPath(new URL("../fonts/",import.meta.url));function ge(e,t){if(typeof e!="number"||!Number.isFinite(e))throw new Error(`${t} must be finite.`);return e}a(ge,"finiteNumber");function Fe(e,t){let r=ge(e,t);if(!Number.isSafeInteger(r))throw new Error(`${t} must be an integer.`);return r}a(Fe,"integer");function la(e){if(!a$1(e)||!a$1(e.info)||!a$1(e.common)||!Array.isArray(e.chars))throw new Error("MSDF generator returned invalid BMFont metadata.");let t=e.chars.map((o,s)=>{if(!a$1(o))throw new Error(`BMFont character ${s} is invalid.`);return {id:Fe(o.id,`BMFont character ${s}.id`),x:ge(o.x,`BMFont character ${s}.x`),y:ge(o.y,`BMFont character ${s}.y`),width:ge(o.width,`BMFont character ${s}.width`),height:ge(o.height,`BMFont character ${s}.height`),xoffset:ge(o.xoffset,`BMFont character ${s}.xoffset`),yoffset:ge(o.yoffset,`BMFont character ${s}.yoffset`),xadvance:ge(o.xadvance,`BMFont character ${s}.xadvance`)}}),r=e.kernings===void 0?[]:e.kernings;if(!Array.isArray(r))throw new Error("BMFont kernings are invalid.");let n=r.map((o,s)=>{if(!a$1(o))throw new Error(`BMFont kerning ${s} is invalid.`);return {first:Fe(o.first,`BMFont kerning ${s}.first`),second:Fe(o.second,`BMFont kerning ${s}.second`),amount:ge(o.amount,`BMFont kerning ${s}.amount`)}});return {info:{size:ge(e.info.size,"BMFont info.size"),face:typeof e.info.face=="string"?e.info.face:"Font"},common:{base:ge(e.common.base,"BMFont common.base"),scaleW:Fe(e.common.scaleW,"BMFont common.scaleW"),scaleH:Fe(e.common.scaleH,"BMFont common.scaleH")},chars:t,kernings:n}}a(la,"parseBMFont");function yn(e){let t=e.generation.size??48,r=e.generation.distanceRange??8,n=e.generation.padding??2,o=e.generation.maxTextureSize??4096;if(!Number.isInteger(t)||t<8||t>256)throw new Error("Text generation size must be an integer from 8 to 256.");if(!Number.isInteger(r)||r<1||r>64)throw new Error("Text generation distanceRange must be an integer from 1 to 64.");if(!Number.isInteger(n)||n<0||n>32)throw new Error("Text generation padding must be an integer from 0 to 32.");if(!Number.isInteger(o)||o<64||o>8192||(o&o-1)!==0)throw new Error("Text generation maxTextureSize must be a power of two from 64 to 8192.");return {size:t,distanceRange:r,padding:n,maxTextureSize:o}}a(yn,"atlasOptions");function wr(e){let t=aa[e];if(t===void 0)throw new Error(`Unknown built-in font ${JSON.stringify(e)}.`);return t}a(wr,"builtinFontMetadata");function gn(e){let t=e.cacheDirectory??process.env[ia];return t?F.resolve(t):platform()==="darwin"?F.join(homedir(),"Library","Caches","three-blocks","fonts"):platform()==="win32"?F.join(process.env.LOCALAPPDATA?.trim()||F.join(homedir(),"AppData","Local"),"Three Blocks","Cache","fonts"):F.join(process.env.XDG_CACHE_HOME?.trim()||F.join(homedir(),".cache"),"three-blocks","fonts")}a(gn,"fontCacheRoot");function dn(e,t){return t==="source"?{font:e,kind:t,file:e.sourceFile,url:e.sourceUrl,bytes:e.sourceBytes,checksum:e.sourceChecksum,...e.sourceArchive===void 0?{}:{archive:e.sourceArchive}}:{font:e,kind:t,file:e.browserFile,url:e.browserUrl,bytes:e.browserBytes,checksum:e.browserChecksum}}a(dn,"builtinAsset");function wn(e,t){let r=wr(e),n=t.mapBuiltinFont?.(r)??r;if(n.id!==r.id||n.version!==r.version||n.sourceBytes!==r.sourceBytes||n.sourceChecksum!==r.sourceChecksum||n.browserBytes!==r.browserBytes||n.browserChecksum!==r.browserChecksum)throw new Error(`Runtime metadata for built-in font ${JSON.stringify(e)} changed its pinned identity.`);return n}a(wn,"runtimeBuiltinFontMetadata");function ua(e,t){return F.join(gn(t),e.font.id,e.font.version,e.checksum,F.basename(e.file))}a(ua,"builtinCachePath");async function ma(e$1,t){try{let r=await j(e$1,d$1.texture,`${t.font.id} cached ${t.kind} font`);if(r.data.byteLength===t.bytes&&f(r.data)===t.checksum)return r.data;await rm(e$1,{force:!0});return}catch(r){if(e(r)==="ENOENT")return;throw r}}a(ma,"readCachedFont");async function fa(e$1){try{let t=await j(F.join(ca,e$1.file),e$1.bytes,`${e$1.font.id} packaged ${e$1.kind} font`);return t.data.byteLength===e$1.bytes&&f(t.data)===e$1.checksum?t.data:void 0}catch(t){if(e(t)==="ENOENT")return;throw t}}a(fa,"readPackagedFont");async function pa(e,t){try{let r=await l(e.root,e.filePath,t.bytes,`${t.font.id} existing browser font output`);return r.data.byteLength!==t.bytes||f(r.data)!==t.checksum?void 0:r.data}catch{return}}a(pa,"readBuiltinBrowserSeed");function ha(e,t,r){let n=Math.max(0,e.byteLength-65557),o=-1;for(let u=e.byteLength-22;u>=n;u--)if(e.readUInt32LE(u)===101010256){o=u;break}if(o<0)throw new Error("downloaded ZIP has no end-of-central-directory record");let s=e.readUInt16LE(o+10),i=e.readUInt32LE(o+12),a=e.readUInt32LE(o+16);if(a+i>o)throw new Error("downloaded ZIP central directory is out of bounds");let c=a;for(let u=0;u<s;u++){if(c+46>e.byteLength||e.readUInt32LE(c)!==33639248)throw new Error("downloaded ZIP central directory is invalid");let f=e.readUInt16LE(c+10),l=e.readUInt32LE(c+20),m=e.readUInt32LE(c+24),p=e.readUInt16LE(c+28),h=e.readUInt16LE(c+30),y=e.readUInt16LE(c+32),w=e.readUInt32LE(c+42),b=c+46+p+h+y;if(b>e.byteLength)throw new Error("downloaded ZIP entry metadata is out of bounds");let k=e.subarray(c+46,c+46+p).toString("utf8");if(c=b,k!==t)continue;if(m!==r)throw new Error(`ZIP entry has ${m} bytes; expected ${r}`);if(w+30>e.byteLength||e.readUInt32LE(w)!==67324752)throw new Error("downloaded ZIP local entry is invalid");let g=e.readUInt16LE(w+26),P=e.readUInt16LE(w+28),R=w+30+g+P;if(R+l>e.byteLength)throw new Error("downloaded ZIP entry data is out of bounds");let _=e.subarray(R,R+l);if(f===0)return Buffer.from(_);if(f===8)return Rt.inflateRawSync(_,{maxOutputLength:r});throw new Error(`ZIP entry uses unsupported compression method ${f}`)}throw new Error(`downloaded ZIP does not contain ${JSON.stringify(t)}`)}a(ha,"zipEntry");async function ya(e,t){let r=new URL(e.url);if(r.protocol!=="https:")throw new Error(`Built-in font source must use HTTPS: ${e.url}.`);let n;try{n=await t(r,{signal:AbortSignal.timeout(da)});}catch(h){throw new Error(`request failed: ${h instanceof Error?h.message:String(h)}`,{cause:h})}if(!n.ok)throw new Error(`server returned HTTP ${n.status} ${n.statusText}`.trim());let o=e.archive?.bytes??e.bytes,s=e.archive?.checksum??e.checksum,i=n.headers.get("content-length");if(i!==null){let h=Number(i);if(!Number.isSafeInteger(h)||h!==o)throw new Error(`server declared ${i} bytes; expected ${o}`)}if(n.body===null)throw new Error("server returned an empty response body");let a=n.body.getReader(),c=[],u=0;for(;;){let h=await a.read();if(h.done)break;if(u+=h.value.byteLength,u>o||u>d$1.texture)throw await a.cancel(),new Error(`download exceeded the expected ${o}-byte size`);c.push(Buffer.from(h.value.buffer,h.value.byteOffset,h.value.byteLength));}let f$1=Buffer.concat(c,u);if(f$1.byteLength!==o)throw new Error(`downloaded ${f$1.byteLength} bytes; expected ${o}`);let l=f(f$1);if(l!==s)throw new Error(`checksum mismatch: expected ${s}, received ${l}`);let m=e.archive===void 0?f$1:ha(f$1,e.archive.entry,e.bytes);if(m.byteLength!==e.bytes)throw new Error(`resolved ${m.byteLength} bytes; expected ${e.bytes}`);let p=f(m);if(p!==e.checksum)throw new Error(`resolved checksum mismatch: expected ${e.checksum}, received ${p}`);return m}a(ya,"downloadFont");async function mr(e,t){await mkdir(F.dirname(e),{recursive:true});let r=`${e}.${process.pid}.${randomUUID()}.tmp`;try{await writeFile(r,t,{flag:"wx"}),await rename(r,e);}finally{await rm(r,{force:true});}}a(mr,"writeCachedFont");async function cn(e,t,r){let n=ua(e,t),o=Wt.get(n);if(o)return o;let s=(async()=>{let i=await ma(n,e);if(i)return i;if(t.fetch===void 0&&t.mapBuiltinFont===void 0){let a=await fa(e);if(a!==void 0)return await mr(n,a),a}if(r!==void 0){let a=await pa(r,e);if(a!==void 0)return await mr(n,a),a}try{let a=await ya(e,t.fetch??globalThis.fetch);return await mr(n,a),a}catch(a){throw new Error(`Could not download the built-in ${e.font.id} ${e.kind} font from ${e.url}: ${a instanceof Error?a.message:String(a)}. Connect once to prewarm the checksum-keyed cache at ${JSON.stringify(gn(t))}, or configure source.path/source.package for fully offline text generation.`,{cause:a})}})();Wt.set(n,s);try{return await s}finally{Wt.get(n)===s&&Wt.delete(n);}}a(cn,"cachedBuiltinAsset");async function bn(e,t,r){let[n,o]=await Promise.allSettled([cn(dn(e,"source"),t),cn(dn(e,"browser"),t,r)]);if(n.status==="rejected")throw n.reason;if(o.status==="rejected")throw o.reason;return [n.value,o.value]}a(bn,"cachedBuiltinPair");async function ga(e,t={}){let r=wn(e,t);await bn(r,t);}a(ga,"prewarmBuiltinFont");async function Sn(e,t,r){let n=await j(e,d$1.texture,r),o=f(n.data);if(t!=="pending"&&o!==t)throw new Error(`${r} checksum mismatch: expected ${t}, received ${o}.`);return n.data}a(Sn,"checkedExternalFile");function kn(e,t){if(!/^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/iu.test(t))throw new Error("Text font package name is unsafe.");return F.join(e,"node_modules",...t.split("/"))}a(kn,"packageRoot");async function wa(e,t){if("builtin"in t){let o=wr(t.builtin);return {sourceHash:o.sourceChecksum,browserHash:o.browserChecksum,description:`builtin:${o.id}@${o.version}`,license:o.license}}if("path"in t){let o=await l(e,F.join(e,t.path),d$1.texture,"Text source font");return {sourceHash:f(o.data),browserHash:f(o.data),description:t.path}}let r=F.join(kn(e,t.package),t.file),n=await Sn(r,t.checksum,"Package text source font");return {sourceHash:f(n),browserHash:f(n),description:`${t.package}/${t.file}`}}a(wa,"resolveFontIdentity");async function ba(e,t,r,n){if("builtin"in t){let a=wn(t.builtin,r),[c,u]=await bn(a,r,n===void 0?void 0:{root:e,filePath:n});return {source:c,sourceHash:a.sourceChecksum,browser:u,browserHash:a.browserChecksum,description:`builtin:${a.id}@${a.version}`,license:a.license}}if("path"in t){let a=await l(e,F.join(e,t.path),d$1.texture,"Text source font"),c=f(a.data);return {source:a.data,sourceHash:c,browser:a.data,browserHash:c,description:t.path}}let o=F.join(kn(e,t.package),t.file),s=await Sn(o,t.checksum,"Package text source font"),i=f(s);return {source:s,sourceHash:i,browser:s,browserHash:i,description:`${t.package}/${t.file}`}}a(ba,"resolveFont");function xt(e,t){let r=t.replace(/^\/+/,""),n=F.resolve(e,"public",r),o=F.resolve(e,"public"),s=F.relative(o,n);if(s===""||s===".."||s.startsWith(`..${F.sep}`)||F.isAbsolute(s))throw new Error(`Deployed text path ${JSON.stringify(t)} escapes public/.`);return n}a(xt,"deployedFile");function yr(e,t){return F.relative(e,t).split(F.sep).join("/")}a(yr,"portablePath");function xn(e){return e.endsWith(".json")?`${e.slice(0,-5)}.meta.json`:`${e}.meta.json`}a(xn,"metadataPath");function Rn(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}a(Rn,"bufferArray");function Sa(e,t){return t.filter(r=>r===65533||e.charToGlyphIndex(String.fromCodePoint(r))!==0)}a(Sa,"supportedCodePoints");function ka(e,t,r,n){return new Promise((o,s)=>{oa(e,{filename:r,charset:t.map(i=>String.fromCodePoint(i)),outputType:"json",fieldType:"msdf",fontSize:n.size,distanceRange:n.distanceRange,texturePadding:n.padding,textureSize:[n.maxTextureSize,n.maxTextureSize],smartSize:true,pot:true},(i,a,c)=>{if(i)return s(i);if(a.length!==1||a[0]===void 0)return s(new Error(`Text glyphs require ${a.length} atlas pages; raise maxTextureSize or lower size.`));try{o({png:a[0].texture,data:la(JSON.parse(c.data))});}catch(u){s(u);}});})}a(ka,"generateBMFontData");function xa(e,t,r){let n=1/e.info.size,o=e.common.base,s=t.unitsPerEm,i=t.tables.hhea;return {name:t.names?.fontFamily?.en??e.info.face,atlas:{type:"msdf",distanceRange:r.distanceRange,size:e.info.size,width:e.common.scaleW,height:e.common.scaleH,yOrigin:"top"},metrics:{emSize:1,lineHeight:(i.ascender-i.descender+i.lineGap)/s,ascender:i.ascender/s,descender:i.descender/s,underlineY:(t.tables.post?.underlinePosition??-s*.1)/s,underlineThickness:(t.tables.post?.underlineThickness??s*.05)/s},glyphs:e.chars.slice().sort((a,c)=>a.id-c.id).map(a=>({unicode:a.id,advance:a.xadvance*n,...a.width>0&&a.height>0?{planeBounds:{left:a.xoffset*n,bottom:(o-a.yoffset-a.height)*n,right:(a.xoffset+a.width)*n,top:(o-a.yoffset)*n},atlasBounds:{left:a.x,top:a.y,right:a.x+a.width,bottom:a.y+a.height}}:{}})),kerning:e.kernings.filter(a=>a.amount!==0).sort((a,c)=>a.first-c.first||a.second-c.second).map(a=>({unicode1:a.first,unicode2:a.second,advance:a.amount*n}))}}a(xa,"convertMetrics");function vn(){return Rt}a(vn,"zstdFunctions");function Ra(e){let t=PNG.sync.read(e),r=new Uint8Array(t.data.buffer,t.data.byteOffset,t.data.byteLength),o=vn().zstdCompressSync,s=o===void 0?"none":"zstd",i=Rt.constants.ZSTD_c_compressionLevel,a$1=o?.(r,i===void 0?{}:{params:{[i]:19}}),c=createDefaultContainer();c.vkFormat=VK_FORMAT_R8G8B8A8_UNORM,c.typeSize=1,c.pixelWidth=t.width,c.pixelHeight=t.height,c.supercompressionScheme=s==="zstd"?KHR_SUPERCOMPRESSION_ZSTD:KHR_SUPERCOMPRESSION_NONE,c.levels=[{levelData:a$1===void 0?r:new Uint8Array(a$1.buffer,a$1.byteOffset,a$1.byteLength),uncompressedByteLength:r.byteLength}];let u=a((l,m)=>({bitOffset:l*8,bitLength:7,channelType:m,samplePosition:[0,0,0,0],sampleLower:0,sampleUpper:255}),"sample");c.dataFormatDescriptor=[{vendorId:KHR_DF_VENDORID_KHRONOS,descriptorType:KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,versionNumber:KHR_DF_VERSION,colorModel:KHR_DF_MODEL_RGBSDA,colorPrimaries:KHR_DF_PRIMARIES_BT709,transferFunction:KHR_DF_TRANSFER_LINEAR,flags:KHR_DF_FLAG_ALPHA_STRAIGHT,texelBlockDimension:[0,0,0,0],bytesPlane:[0,0,0,0,0,0,0,0],samples:[u(0,KHR_DF_CHANNEL_RGBSDA_RED),u(1,KHR_DF_CHANNEL_RGBSDA_GREEN),u(2,KHR_DF_CHANNEL_RGBSDA_BLUE),u(3,KHR_DF_CHANNEL_RGBSDA_ALPHA|KHR_DF_SAMPLE_DATATYPE_LINEAR)]}],c.keyValue.KTXwriter=`three-blocks text ${vt}`,c.keyValue.KTXorientation="rd";let f=write(c,{keepWriter:true});return En(f,t.width,t.height),{bytes:f,width:t.width,height:t.height,compression:s}}a(Ra,"createKtx2");function En(e,t,r){let n=read(e);if(n.vkFormat!==VK_FORMAT_R8G8B8A8_UNORM)throw new Error("Text atlas must use RGBA8 KTX2.");if(n.pixelWidth<=0||n.pixelHeight<=0||n.levels.length!==1||n.levels[0]===void 0)throw new Error("Text atlas KTX2 dimensions or levels are invalid.");if(t!==void 0&&n.pixelWidth!==t)throw new Error("Text atlas KTX2 width does not match metrics.");if(r!==void 0&&n.pixelHeight!==r)throw new Error("Text atlas KTX2 height does not match metrics.");if(n.keyValue.KTXorientation!=="rd")throw new Error("Text atlas KTX2 orientation must be rd.");let o=n.levels[0],s,i;if(n.supercompressionScheme===KHR_SUPERCOMPRESSION_ZSTD){let c=vn().zstdDecompressSync;if(c===void 0)throw new Error("This Node.js runtime cannot validate Zstandard KTX2 text atlases.");s=c(o.levelData),i="zstd";}else if(n.supercompressionScheme===KHR_SUPERCOMPRESSION_NONE)s=o.levelData,i="none";else throw new Error("Text atlas uses an unsupported KTX2 supercompression scheme.");let a=n.pixelWidth*n.pixelHeight*4;if(s.byteLength!==a||o.uncompressedByteLength!==a)throw new Error("Text atlas KTX2 decoded byte length is invalid.");return {width:n.pixelWidth,height:n.pixelHeight,compression:i}}a(En,"validateKtx2Bytes");function ln(e){return `${JSON.stringify(e)}
2
- `}a(ln,"stableJson");function fr(e,t,r){return {path:yr(e,t),sha256:f(r),bytes:r.byteLength}}a(fr,"fileReceipt");function Tn(e,t,r,n){return f(JSON.stringify({generator:vt,fontKey:n,fontHash:e.sourceHash,glyphSetHash:t,options:r}))}a(Tn,"createInputHash");async function va(e,t,r,n,o,s,i$1){if(o.length===0)throw new Error(`Text font ${JSON.stringify(t)} covers no required glyphs.`);let a=hn.parse(Rn(n.source)),c=await ka(n.source,o,t,i$1),u=xa(c.data,a,i$1),f=Buffer.from(ln(u)),l=Ra(c.png);if(c.data.common.scaleW!==l.width||c.data.common.scaleH!==l.height)throw new Error(`Text font ${JSON.stringify(t)} metrics and texture dimensions differ.`);let m=xt(e,r.browser),p=xt(e,r.atlas),h=xt(e,r.metrics),y=xn(h),w={schemaVersion:gr,generatorVersion:vt,font:{key:t,source:n.description,sourceHash:n.sourceHash,...n.license===void 0?{}:{license:n.license}},inputHash:Tn(n,s,i$1,t),glyphSetHash:s,codePoints:o,options:i$1,texture:{format:"RGBA8",orientation:"rd",compression:l.compression,width:l.width,height:l.height},files:{browser:fr(e,m,n.browser),atlas:fr(e,p,l.bytes),metrics:fr(e,h,f)}},b=Buffer.from(ln(w));await i(m,n.browser),await i(p,l.bytes),await i(h,f),await i(y,b);let k=[m,p,h,y].map(g=>yr(e,g));return {font:t,receipt:w,metadataPath:yr(e,y),updatedFiles:k}}a(va,"generateRoute");async function Ea(e,t="three-blocks.text.ts",r={}){let n=await Ht(e,t),o=await Ut(e,n),s=yn(n),i=[];for(let[f,l]of Object.entries(n.fonts).sort((m,p)=>m[0].localeCompare(p[0]))){let m=await ba(e,l.source,r,"builtin"in l.source?xt(e,l.browser):void 0),p=hn.parse(Rn(m.source));i.push({key:f,route:l,resolved:m,font:p,codePoints:Sa(p,o.glyphs.codePoints)});}let a=new Set(i.flatMap(f=>f.codePoints)),c=o.glyphs.codePoints.filter(f=>!a.has(f));if(c.length>0)throw new Error(`Configured fonts do not cover ${c.length} required glyph(s): ${c.map(f=>String.fromCodePoint(f)).join(" ")}`);let u=[];for(let f of i)u.push(await va(e,f.key,f.route,f.resolved,f.codePoints,o.glyphs.hash,s));return {glyphs:o.glyphs.codePoints.length,glyphSetHash:o.glyphs.hash,atlases:u,updatedFiles:u.flatMap(f=>f.updatedFiles)}}a(Ea,"generateTextAtlases");function pr(e,t){if(!a$1(e)||typeof e.path!="string"||typeof e.sha256!="string"||!/^[a-f0-9]{64}$/u.test(e.sha256)||!Number.isSafeInteger(e.bytes)||e.bytes<0)throw new Error(`${t} receipt is invalid.`);return e}a(pr,"parseFileReceipt");function Bn(e){if(!a$1(e)||e.schemaVersion!==gr||e.generatorVersion!==vt||!a$1(e.font)||typeof e.font.key!="string"||typeof e.font.source!="string"||typeof e.font.sourceHash!="string"||!/^[a-f0-9]{64}$/u.test(e.font.sourceHash)||typeof e.inputHash!="string"||!/^[a-f0-9]{64}$/u.test(e.inputHash)||typeof e.glyphSetHash!="string"||!/^[a-f0-9]{64}$/u.test(e.glyphSetHash)||!Array.isArray(e.codePoints)||!e.codePoints.every(t=>Number.isSafeInteger(t))||!a$1(e.options)||!a$1(e.texture)||!a$1(e.files))throw new Error("Text atlas generation metadata is invalid.");if(e.texture.format!=="RGBA8"||e.texture.orientation!=="rd"||!["zstd","none"].includes(e.texture.compression))throw new Error("Text atlas texture metadata is invalid.");return pr(e.files.browser,"Browser font"),pr(e.files.atlas,"Text atlas"),pr(e.files.metrics,"Text metrics"),e}a(Bn,"parseTextAtlasReceipt");function Ta(e){if(!a$1(e)||!a$1(e.atlas)||!Array.isArray(e.glyphs))throw new Error("Text metrics are invalid.");let t=Fe(e.atlas.width,"Text metrics atlas.width"),r=Fe(e.atlas.height,"Text metrics atlas.height"),n=e.glyphs.map((o,s)=>{if(!a$1(o))throw new Error(`Text metrics glyph ${s} is invalid.`);return Fe(o.unicode,`Text metrics glyph ${s}.unicode`)});return {width:t,height:r,codePoints:n}}a(Ta,"metricsCoverage");async function hr(e,t,r,n){let o=await l(e,F.join(e,t.path),r,n);if(o.data.byteLength!==t.bytes||f(o.data)!==t.sha256)throw new Error(`${n} checksum or byte length differs from generation metadata.`);return o.data}a(hr,"verifyReceiptFile");async function zt(e,t="three-blocks.text.ts"){let r;try{r=await Ht(e,t);}catch(n){return {state:"invalid",reason:`Text configuration is invalid: ${n instanceof Error?n.message:String(n)}`,missing:[],atlases:[]}}try{let n=await Ut(e,r),o=yn(r),s=[],i=new Set;for(let[c,u]of Object.entries(r.fonts).sort((f,l)=>f[0].localeCompare(l[0]))){let f$1=await l(e,xn(xt(e,u.metrics)),d$1.metadata,"Text atlas generation metadata"),l$1=Bn(JSON.parse(f$1.data.toString("utf8")));if(l$1.font.key!==c)throw new Error(`Text atlas metadata belongs to ${JSON.stringify(l$1.font.key)}, not ${JSON.stringify(c)}.`);let m=await wa(e,u.source),p=Tn(m,l$1.glyphSetHash,o,c);if(l$1.inputHash!==p)return {state:"invalid",reason:`Text atlas ${c} font source or generation options changed.`,missing:[],atlases:[...s,l$1]};let[h,y,w]=await Promise.all([hr(e,l$1.files.browser,d$1.texture,"Browser font"),hr(e,l$1.files.atlas,d$1.texture,"Text atlas"),hr(e,l$1.files.metrics,d$1.metrics,"Text metrics")]);if(f(h)!==m.browserHash)throw new Error(`Browser font ${c} differs from its resolved source.`);let b=Ta(JSON.parse(w.toString("utf8"))),k=En(y,b.width,b.height);if(k.width!==l$1.texture.width||k.height!==l$1.texture.height||k.compression!==l$1.texture.compression)throw new Error(`Text atlas ${c} texture metadata does not match KTX2.`);for(let g of b.codePoints)i.add(g);s.push(l$1);}let a=n.glyphs.codePoints.filter(c=>!i.has(c));return a.length>0?{state:"missing",reason:`${a.length} required glyph(s) are missing.`,missing:a,atlases:s}:{state:"ready",reason:`${n.glyphs.codePoints.length} required glyphs are covered by ${s.length} atlas(es).`,missing:[],atlases:s}}catch(n){return (typeof n=="object"&&n!==null&&"code"in n?n.code:void 0)==="ENOENT"?{state:"missing",reason:"Text atlas files or generation metadata are absent.",missing:[],atlases:[]}:{state:"invalid",reason:n instanceof Error?n.message:String(n),missing:[],atlases:[]}}}a(zt,"inspectTextAtlases");var Sr=[".ts",".tsx",".mts",".cts",".js",".jsx",".mjs",".cjs",".wgsl",".glsl",".vert",".frag",".json",".css"],kr=new Set(Sr),br=/^(?:three-blocks\.shaders\.json|(?:precompile|three-blocks\.shaders)\.config\.(?:cjs|cts|js|mjs|mts|ts))$/u,$a=/(?:^|\/)scene\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx)$/u,Pa=/\b(?:export\s+)?(?:async\s+)?function\s+createScene\b|\bcreateScene\s*=\s*(?:async\s*)?\(/u,Aa=/\b(?:[A-Za-z_$][\w$]*\.)*(?:shaders|shaderCache|sceneShaders)\s*\.\s*(?:material|pipeline|compute|container)\s*\(/u,_a=/\b(import|export)(?!\s*\()\s*(type\b\s*)?(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']/gu,Ma=/\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,Ca=/\b(?:import|export)(?!\s*\()\s*(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,Oa=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/u,xr=4096,Fa="./shaders";function An(e,t){let r=F.relative(e,t).split(F.sep).join("/");if(r.length===0||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Semantic input has an unsafe relative path.");return r}a(An,"portableRelativePath");function Rr(e,t){try{return new TextDecoder("utf-8",{fatal:!0}).decode(e)}catch{throw new Error(`Shader-relevant source ${JSON.stringify(t)} is not valid UTF-8.`)}}a(Rr,"sourceText");function Er(e,t){let r="",n="code";for(let o=0;o<e.length;o++){let s=e[o]??"",i=e[o+1]??"";if(n==="code"){if(s==="/"&&i==="/"){r+=" ",n="line-comment",o++;continue}if(s==="/"&&i==="*"){r+=" ",n="block-comment",o++;continue}if(s==="'"||s==='"'||s==="`"){n=s==="'"?"single":s==='"'?"double":"template",r+=t?s:" ";continue}r+=s;continue}if(n==="line-comment"){s===`
1
+ import {c,d,b as b$1}from'./chunk-YHHGR2AJ.js';export{a as DOCUMENTED_BROWSER_NOISE,l as createAttachedPlaywrightShaderDriver,j as createPlaywrightShaderDriver,k as createStaticPlaywrightShaderDriver,b as isDocumentedBrowserNoise,i as isRetryableShaderObservationNavigation,c as webgpuBrowserArgs,d as webgpuBrowserHeadless}from'./chunk-YHHGR2AJ.js';import {a as a$1,l,d as d$1,f,j,e,i,g,m,h,B,v,w,q,r,t,o,k,c as c$1,K,A,z,H,y,s,x,G,R,Q,N as N$1,p,P,O,b}from'./chunk-3CKEE22B.js';export{o as SHADER_ARTIFACT_DIRECTORY,T as SHADER_CAPTURE_CLIENT_ID,D as SHADER_COMMITTED_TIMING_FILE,A as SHADER_DEVTOOLS_VERSION,C as SHADER_LOCAL_TIMING_FILE,p as SHADER_PARITY_DIRECTORY,E as SHADER_PARITY_EVIDENCE_FILE,B as SHADER_PROVIDER_TRANSFORM_VERSION,n as SHADER_TOOL_CONFIG_FILE,W as applyShaderProviderTransform,Y as assertShaderProviderTransform,X as createShaderProviderTransform,y as ensureShaderToolConfig,v as findShaderProjectRoot,x as inferShaderCaptureTarget,S as loadShaderCaptureRuntimeSource,w as loadShaderToolConfig,b as parseProjectMetadata,c as parseShaderReceipt,u as parseShaderToolConfig,M as readShaderCommittedTiming,J as readShaderLocalTiming,L as readShaderParityEvidence,K as readShaderTiming,I as serializeShaderManifest,F as shaderCoverage,H as stableStringify,G as validateShaderCapture,R as writeShaderArtifacts,N as writeShaderLocalTiming,O as writeShaderParityEvidence,Q as writeShaderTimingTwins}from'./chunk-3CKEE22B.js';export{b as compareShaderScreenshots,a as shaderScreenshotMetrics}from'./chunk-UDUICSME.js';import {a}from'./chunk-EI7MMDWY.js';import {rm,mkdir,writeFile,rename,realpath,readdir,readFile,lstat}from'fs/promises';import F from'path';import {createRequire}from'module';import {createHash,randomUUID}from'crypto';import zt,{platform,homedir}from'os';import {fileURLToPath}from'url';import*as xt from'zlib';import xt__default from'zlib';import {createDefaultContainer,VK_FORMAT_R8G8B8A8_UNORM,KHR_SUPERCOMPRESSION_ZSTD,KHR_SUPERCOMPRESSION_NONE,KHR_DF_FLAG_ALPHA_STRAIGHT,KHR_DF_TRANSFER_LINEAR,KHR_DF_PRIMARIES_BT709,KHR_DF_MODEL_RGBSDA,KHR_DF_VERSION,KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,KHR_DF_VENDORID_KHRONOS,KHR_DF_CHANNEL_RGBSDA_RED,KHR_DF_CHANNEL_RGBSDA_GREEN,KHR_DF_CHANNEL_RGBSDA_BLUE,KHR_DF_CHANNEL_RGBSDA_ALPHA,KHR_DF_SAMPLE_DATATYPE_LINEAR,write,read,VK_FORMAT_R16G16B16A16_SFLOAT}from'ktx-parse';import aa from'msdf-bmfont-xml';import hn from'opentype.js';import {PNG}from'pngjs';import {SHADER_ADDRESS_SCHEMA_VERSION,SHADER_RECIPE_SCHEMA_VERSION,SHADER_HYDRATION_SCHEMA_VERSION}from'three-blocks/shaders';import {watch}from'fs';var Zr=4096,hs=createRequire(import.meta.url),Yr,Z=new Proxy({},{get(e,t){return Yr??=hs("typescript"),Reflect.get(Yr,t)}});function Oe(e){let t=e;for(;Z.isParenthesizedExpression(t)||Z.isAsExpression(t)||Z.isSatisfiesExpression(t)||Z.isNonNullExpression(t);)t=t.expression;return t}a(Oe,"unwrap");function ys(e){if(Z.isIdentifier(e)||Z.isStringLiteral(e)||Z.isNumericLiteral(e))return e.text}a(ys,"propertyName");function yt(e,t){let r=new Map;for(let n of e.properties){if(!Z.isPropertyAssignment(n))throw new Error(`${t} may contain only static property assignments.`);let o=ys(n.name);if(o===void 0||r.has(o))throw new Error(`${t} contains a computed or duplicate property.`);r.set(o,n.initializer);}return r}a(yt,"properties");function gt(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isObjectLiteralExpression(r))throw new Error(`${t} must be a static object literal.`);return r}a(gt,"objectLiteral");function wt(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isStringLiteral(r)&&!Z.isNoSubstitutionTemplateLiteral(r))throw new Error(`${t} must be a string literal.`);return r.text}a(wt,"stringLiteral");function It(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isNumericLiteral(r))throw new Error(`${t} must be a numeric literal.`);return Number(r.text)}a(It,"numericLiteral");function Qr(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(!Z.isArrayLiteralExpression(r))throw new Error(`${t} must be a static array literal.`);return r.elements}a(Qr,"arrayLiteral");function gs(e,t){if(e===void 0)throw new Error(`${t} is missing.`);let r=Oe(e);if(r.kind===Z.SyntaxKind.NullKeyword)return null;if(!Z.isNumericLiteral(r))throw new Error(`${t} must be null or a numeric literal.`);return Number(r.text)}a(gs,"numericOrNullLiteral");function ws(e){return e.parseDiagnostics??[]}a(ws,"parseDiagnostics");function Lt(e,t,r,n){let o=Z.createSourceFile(t,e,Z.ScriptTarget.Latest,true,Z.ScriptKind.TS),s=ws(o);if(s.length>0)throw new Error(`Shader manifest is not valid TypeScript: ${Z.flattenDiagnosticMessageText(s[0]?.messageText??"parse error"," ")}`);let i=o.statements.filter(Z.isExportAssignment).filter(w=>!w.isExportEquals);if(i.length!==1)throw new Error("Shader manifest must contain exactly one default export.");let a$1=yt(gt(i[0]?.expression,"Shader manifest default export"),"Shader manifest"),c=a$1.get("version");if(c===void 0||!Z.isNumericLiteral(Oe(c))||Number(Oe(c).getText(o))!==3)throw new Error("Shader manifest version must be the numeric literal 3.");if(wt(a$1.get("scene"),"Shader manifest scene")!==r)throw new Error(`Shader manifest scene does not match "${r}".`);let l=a$1.get("runtime"),u=(n?.compatibility??(l===void 0?"":wt(yt(gt(l,"Shader manifest runtime"),"Shader manifest runtime").get("id"),"Shader manifest runtime id"))).startsWith("three-webgl-");if(n){if(wt(a$1.get("three"),"Shader manifest Three.js version")!==n.three||wt(a$1.get("threeBlocks"),"Shader manifest Three Blocks version")!==n.threeBlocks)throw new Error("Shader manifest runtime versions do not match its receipt.");let w=yt(gt(a$1.get("runtime"),"Shader manifest runtime"),"Shader manifest runtime");if(wt(w.get("id"),"Shader manifest runtime id")!==n.compatibility||It(w.get("address"),"Shader manifest address schema")!==n.address||It(w.get("recipe"),"Shader manifest recipe schema")!==n.recipe||It(w.get("hydration"),"Shader manifest hydration schema")!==n.hydration)throw new Error("Shader manifest runtime compatibility schemas do not match its receipt.")}let m=yt(gt(a$1.get("entries"),"Shader manifest entries"),"Shader manifest entries");if(m.size===0&&!u||m.size>Zr)throw new Error(`Shader manifest must contain ${u?"0":"1"}...${Zr} entries.`);let p=Qr(a$1.get("modules"),"Shader manifest modules").map((w,b)=>{let x=Oe(w);if(!Z.isStringLiteral(x)&&!Z.isNoSubstitutionTemplateLiteral(x))throw new Error(`Shader manifest module ${b} must be a shader string literal.`);if(x.text.length===0)throw new Error(`Shader manifest module ${b} is empty.`);return x.text}),h=Qr(a$1.get("states"),"Shader manifest states").map((w,b)=>{let x=yt(gt(w,`Shader manifest state ${b}`),`Shader manifest state ${b}`),g=a((O,k)=>{let A=gs(x.get(O),`Shader manifest state ${b} ${O}`);if(A===null)return false;let v=p[A];if(v===void 0||!u&&!v.includes(k))throw new Error(`Shader manifest state ${b} ${O} does not reference a ${k} module.`);return true},"moduleAt"),T=g("vertex","@vertex"),R=g("fragment","@fragment"),C=g("compute","@compute");if(C&&(T||R))throw new Error(`Shader manifest state ${b} mixes render and compute stages.`);if(!C&&!T&&!R)throw new Error(`Shader manifest state ${b} contains no shader stage.`);return {vertex:T,fragment:R,compute:C}}),y={render:0,vertex:0,fragment:0,compute:0};for(let[w,b]of m){if(w.length===0||/[\u0000-\u001f\u007f]/.test(w))throw new Error("Shader manifest contains an invalid entry key.");let x=It(b,`Shader manifest entry "${w}"`),g=h[x];if(g===void 0)throw new Error(`Shader manifest entry "${w}" references an absent state.`);(g.vertex||g.fragment)&&(y.render+=1),g.vertex&&(y.vertex+=1),g.fragment&&(y.fragment+=1),g.compute&&(y.compute+=1);}return y}a(Lt,"inspectPrecompiledManifest");var ks=createRequire(import.meta.url),en,Y=new Proxy({},{get(e,t){return en??=ks("typescript"),Reflect.get(en,t)}}),xs=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),Rs=new Set(["script","style","template"]),tn=2e5,vs={amp:"&",apos:"'",copy:"\xA9",deg:"\xB0",gt:">",hellip:"\u2026",ldquo:"\u201C",lsquo:"\u2018",lt:"<",mdash:"\u2014",nbsp:"\xA0",ndash:"\u2013",quot:'"',rdquo:"\u201D",rsquo:"\u2019"};function Es(e){return e.replace(/&(#x[0-9a-f]+|#[0-9]+|[a-z][a-z0-9]+);/giu,(t,r)=>{if(r.startsWith("#x")||r.startsWith("#X")){let n=Number.parseInt(r.slice(2),16);return bt(n)?String.fromCodePoint(n):t}if(r.startsWith("#")){let n=Number.parseInt(r.slice(1),10);return bt(n)?String.fromCodePoint(n):t}return vs[r.toLowerCase()]??t})}a(Es,"decodeHtmlEntities");function bt(e){return Number.isSafeInteger(e)&&e>=0&&e<=1114111&&!(e>=55296&&e<=57343)}a(bt,"validCodePoint");function nn(e){return bt(e)&&e>=32&&!(e>=127&&e<=159)}a(nn,"renderableCodePoint");function Ts(e){return /(?:^|\s)data-canvas-text(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?(?=\s|\/?>)/iu.test(e)}a(Ts,"hasCanvasTextAttribute");function sr(e){let t=[],r=[],n=e.match(/<!--[\s\S]*?-->|<![^>]*>|<[^>]*>|[^<]+/gu)??[];for(let o of n){if(!o.startsWith("<")){if(r.some(c=>c.synchronized)&&!r.some(c=>c.skipped)){let c=Es(o);c.trim().length>0&&t.push(c);}continue}if(o.startsWith("<!--")||o.startsWith("<!")||o.startsWith("<?"))continue;let s=/^<\s*\//u.test(o),i=/^<\s*\/?\s*([a-z][a-z0-9:-]*)/iu.exec(o)?.[1]?.toLowerCase();if(!i)continue;if(s){let c=r.map(l=>l.tag).lastIndexOf(i);c>=0&&r.splice(c);continue}/\/\s*>$/u.test(o)||xs.has(i)||r.push({tag:i,synchronized:Ts(o),skipped:Rs.has(i)});}return t}a(sr,"extractCanvasTextFromHtml");function Bs(e){let t=new Set,r=new Set;for(let n of e.statements){if(!Y.isImportDeclaration(n)||!Y.isStringLiteral(n.moduleSpecifier)||n.moduleSpecifier.text!=="three-blocks/text")continue;let o=n.importClause?.namedBindings;if(o&&Y.isNamespaceImport(o)&&r.add(o.name.text),o&&Y.isNamedImports(o))for(let s of o.elements)(s.propertyName?.text??s.name.text)==="defineTextContent"&&t.add(s.name.text);}return {named:t,namespaces:r}}a(Bs,"importedTextHelpers");function $s(e,t){return Y.isIdentifier(e)?t.named.has(e.text):Y.isPropertyAccessExpression(e)&&Y.isIdentifier(e.expression)&&t.namespaces.has(e.expression.text)&&e.name.text==="defineTextContent"}a($s,"isDefineTextContentCall");function As(e){let t=e;for(;Y.isParenthesizedExpression(t)||Y.isAsExpression(t)||Y.isSatisfiesExpression(t)||Y.isTypeAssertionExpression(t);)t=t.expression;return t}a(As,"unwrapExpression");function or(e,t,r){let n=As(e);if(Y.isStringLiteral(n)||Y.isNoSubstitutionTemplateLiteral(n)){t.push(n.text);return}if(Y.isArrayLiteralExpression(n)){for(let i of n.elements){if(Y.isSpreadElement(i))throw new Error(`${r}: defineTextContent() cannot use spread elements.`);or(i,t,r);}return}if(Y.isObjectLiteralExpression(n)){for(let i of n.properties){if(!Y.isPropertyAssignment(i))throw new Error(`${r}: defineTextContent() accepts only static property assignments.`);or(i.initializer,t,r);}return}let o=n.getStart(),s=n.getSourceFile().getLineAndCharacterOfPosition(o).line+1;throw new Error(`${r}:${s}: defineTextContent() contains dynamic text; declare a Unicode range or an explicit static string.`)}a(or,"collectStaticStrings");function ar(e,t="content.ts"){let r=Y.createSourceFile(t,e,Y.ScriptTarget.Latest,true,t.endsWith(".tsx")?Y.ScriptKind.TSX:Y.ScriptKind.TS),n=Bs(r),o=[];function s(i){if(Y.isCallExpression(i)&&$s(i.expression,n)){if(i.arguments.length!==1||!i.arguments[0])throw new Error(`${t}: defineTextContent() requires exactly one static argument.`);or(i.arguments[0],o,t);return}Y.forEachChild(i,s);}return a(s,"visit"),s(r),o}a(ar,"extractDefinedTextContent");function Ps(e){let t=[];if(e==="latin"){for(let r=32;r<=126;r++)t.push(r);for(let r of "\u2018\u2019\u201C\u201D\u2013\u2014\u2026\u2022\xB7\xAB\xBB\u2039\u203A\u20AC\xA3\xA5\xB0\xB1\xD7\xF7\xA9\xAE\u2122\xA0"){let n=r.codePointAt(0);n!==void 0&&t.push(n);}}else {for(let r=12353;r<=12438;r++)t.push(r);for(let r=12443;r<=12447;r++)t.push(r);for(let r=12448;r<=12543;r++)t.push(r);for(let r of "\u3000\u3001\u3002\u300C\u300D\u300E\u300F\uFF08\uFF09\u30FB\u30FC\u301C\u3008\u3009\u300A\u300B\u3010\u3011\uFF01\uFF1F\uFF1A\uFF1B\uFF10\uFF11\uFF12\uFF13\uFF14\uFF15\uFF16\uFF17\uFF18\uFF19\uFF05\uFF06"){let n=r.codePointAt(0);n!==void 0&&t.push(n);}}return t}a(Ps,"presetCodePoints");function rn(e,t){for(let r of t.normalize("NFC")){let n=r.codePointAt(0);n!==void 0&&nn(n)&&e.add(n);}}a(rn,"addCharacters");function ir(e,t={}){let r=new Set;for(let a of e)rn(r,a);t.additionalCharacters&&rn(r,t.additionalCharacters);for(let a of t.presets??[])for(let c of Ps(a))r.add(c);let n=0;for(let a of t.ranges??[]){if(!bt(a.start)||!bt(a.end)||a.end<a.start)throw new RangeError("Text Unicode ranges must contain ordered Unicode scalar values.");if(n+=a.end-a.start+1,n>tn)throw new RangeError(`Configured Unicode ranges exceed the ${tn}-code-point safety limit.`);for(let c=a.start;c<=a.end;c++)nn(c)&&r.add(c);}r.add(32),r.add(63),r.add(65533);let o=[...r].sort((a,c)=>a-c),s=o.map(a=>String.fromCodePoint(a)).join(""),i=createHash("sha256").update(s.normalize("NFC")).digest("hex");return {codePoints:o,characters:s,hash:i}}a(ir,"buildGlyphSet");var Ms=createRequire(import.meta.url),on,D=new Proxy({},{get(e,t){return on??=Ms("typescript"),Reflect.get(on,t)}});function Cs(e){let t=e;for(;D.isParenthesizedExpression(t)||D.isAsExpression(t)||D.isSatisfiesExpression(t)||D.isTypeAssertionExpression(t);)t=t.expression;return t}a(Cs,"unwrap");function Os(e,t){if(D.isIdentifier(e)||D.isStringLiteral(e)||D.isNumericLiteral(e))return e.text;throw new Error(`${t}: text configuration property names must be static.`)}a(Os,"propertyName");function jt(e,t){let r=Cs(e);if(D.isStringLiteral(r)||D.isNoSubstitutionTemplateLiteral(r))return r.text;if(D.isNumericLiteral(r))return Number(r.text);if(r.kind===D.SyntaxKind.TrueKeyword)return true;if(r.kind===D.SyntaxKind.FalseKeyword)return false;if(r.kind===D.SyntaxKind.NullKeyword)return null;if(D.isPrefixUnaryExpression(r)&&(r.operator===D.SyntaxKind.MinusToken||r.operator===D.SyntaxKind.PlusToken)){let o=jt(r.operand,t);if(typeof o=="number")return r.operator===D.SyntaxKind.MinusToken?-o:o}if(D.isArrayLiteralExpression(r))return r.elements.map(o=>{if(D.isSpreadElement(o))throw new Error(`${t}: text configuration cannot use spread elements.`);return jt(o,t)});if(D.isObjectLiteralExpression(r)){let o=Object.create(null);for(let s of r.properties){if(!D.isPropertyAssignment(s))throw new Error(`${t}: text configuration accepts only static property assignments.`);let i=Os(s.name,t);if(Object.hasOwn(o,i))throw new Error(`${t}: duplicate text configuration property "${i}".`);o[i]=jt(s.initializer,t);}return o}let n=r.getSourceFile().getLineAndCharacterOfPosition(r.getStart()).line+1;throw new Error(`${t}:${n}: text configuration must be statically inspectable.`)}a(jt,"evaluateStatic");function Fs(e){let t=new Set,r=new Set;for(let n of e.statements){if(!D.isImportDeclaration(n)||!D.isStringLiteral(n.moduleSpecifier)||n.moduleSpecifier.text!=="three-blocks/text")continue;let o=n.importClause?.namedBindings;if(o&&D.isNamespaceImport(o)&&r.add(o.name.text),o&&D.isNamedImports(o))for(let s of o.elements)(s.propertyName?.text??s.name.text)==="defineText"&&t.add(s.name.text);}return {named:t,namespaces:r}}a(Fs,"helperNames");function Is(e,t){return D.isIdentifier(e)?t.named.has(e.text):D.isPropertyAccessExpression(e)&&D.isIdentifier(e.expression)&&t.namespaces.has(e.expression.text)&&e.name.text==="defineText"}a(Is,"isDefineTextCall");function $e(e,t){if(typeof e!="string"||e.trim().length===0)throw new Error(`${t} must be a non-empty string.`);return e}a($e,"requiredString");function Dt(e,t,r=false){if(!Array.isArray(e)||!r&&e.length===0)throw new Error(`${t} must be ${r?"an":"a non-empty"} array of strings.`);return e.map((n,o)=>$e(n,`${t}[${o}]`))}a(Dt,"stringArray");function Nt(e,t){if(e.includes("\\")||F.posix.isAbsolute(e)||F.posix.normalize(e)!==e||e===".."||e.startsWith("../")||/[\u0000-\u001f\u007f]/u.test(e))throw new Error(`${t} must be a safe project-relative path.`);return e}a(Nt,"safeProjectPath");function Ls(e,t){if(!a$1(e))throw new Error(`${t} must be an object.`);let r=Object.keys(e).sort();if(r.length===1&&r[0]==="builtin")return {builtin:$e(e.builtin,`${t}.builtin`)};if(r.length===1&&r[0]==="path")return {path:Nt($e(e.path,`${t}.path`),`${t}.path`)};if(r.join(",")==="checksum,file,package")return {package:$e(e.package,`${t}.package`),file:Nt($e(e.file,`${t}.file`),`${t}.file`),checksum:$e(e.checksum,`${t}.checksum`)};throw new Error(`${t} must select exactly one supported source.`)}a(Ls,"parseFontSource");function dr(e,t){let r=$e(e,t);if(r.includes("\\")||/[\u0000-\u001f\u007f]/u.test(r)||r.split("/").includes(".."))throw new Error(`${t} is unsafe.`);return r}a(dr,"deployedPath");function js(e){if(e===void 0)return {};if(!a$1(e))throw new Error("Text generation options must be an object.");let t=e.presets===void 0?void 0:Dt(e.presets,"Text generation presets",true).map(c=>{if(c!=="latin"&&c!=="japanese-kana")throw new Error(`Unsupported text preset "${c}".`);return c}),r;if(e.ranges!==void 0){if(!Array.isArray(e.ranges))throw new Error("Text generation ranges must be an array.");r=e.ranges.map((c,l)=>{if(!a$1(c)||typeof c.start!="number"||typeof c.end!="number")throw new Error(`Text generation range ${l} is invalid.`);return {start:c.start,end:c.end}});}let n=a(c=>{let l=e[c];if(l!==void 0){if(typeof l!="number"||!Number.isFinite(l))throw new Error(`Text generation ${c} must be finite.`);return l}},"numeric"),o=n("size"),s=n("distanceRange"),i=n("padding"),a$2=n("maxTextureSize");return {...t===void 0?{}:{presets:t},...r===void 0?{}:{ranges:r},...e.additionalCharacters===void 0?{}:{additionalCharacters:$e(e.additionalCharacters,"Text generation additionalCharacters")},...o===void 0?{}:{size:o},...s===void 0?{}:{distanceRange:s},...i===void 0?{}:{padding:i},...a$2===void 0?{}:{maxTextureSize:a$2}}}a(js,"parseGeneration");function Ds(e){if(!a$1(e)||e.schemaVersion!==void 0&&e.schemaVersion!==1)throw new Error("Text configuration must use schemaVersion 1.");let t=Dt(e.content,"Text content inputs").map(o=>Nt(o,"Text content input"));if(!a$1(e.fonts)||Object.keys(e.fonts).length===0)throw new Error("Text fonts must be a non-empty object.");let r={},n=0;for(let[o,s]of Object.entries(e.fonts)){if($e(o,"Text font key"),!a$1(s))throw new Error(`Text font "${o}" must be an object.`);let i=s.default===true;i&&n++,r[o]={source:Ls(s.source,`Text font "${o}" source`),browser:dr(s.browser,`Text font "${o}" browser path`),atlas:dr(s.atlas,`Text font "${o}" atlas path`),metrics:dr(s.metrics,`Text font "${o}" metrics path`),families:Dt(s.families,`Text font "${o}" families`),languages:s.languages===void 0?[]:Dt(s.languages,`Text font "${o}" languages`,true),default:i};}if(Object.keys(r).length>1&&n!==1)throw new Error("Multiple text fonts require exactly one default route.");if(n>1)throw new Error("Text fonts can select only one default route.");return {schemaVersion:1,content:t,fonts:r,generation:js(e.generation)}}a(Ds,"validateConfiguration");function sn(e,t="three-blocks.text.ts"){let r=D.createSourceFile(t,e,D.ScriptTarget.Latest,true,D.ScriptKind.TS),n=Fs(r),o=[];function s(i){if(D.isCallExpression(i)&&Is(i.expression,n)){if(i.arguments.length!==1||!i.arguments[0])throw new Error(`${t}: defineText() requires one static argument.`);o.push(jt(i.arguments[0],t));return}D.forEachChild(i,s);}if(a(s,"visit"),s(r),o.length!==1)throw new Error(`${t} must contain exactly one imported defineText() call.`);return Ds(o[0])}a(sn,"parseTextConfiguration");function cr(e,t){if(typeof e=="string")t.push(e);else if(Array.isArray(e))for(let r of e)cr(r,t);else if(a$1(e))for(let r of Object.values(e))cr(r,t);}a(cr,"jsonStrings");async function Ht(e,t="three-blocks.text.ts"){let r=Nt(t,"Text configuration path"),n=await l(e,F.join(e,r),d$1.semanticInput,"Text configuration");return sn(n.data.toString("utf8"),r)}a(Ht,"readTextConfiguration");async function Vt(e,t){let r=[],n={},o=0;for(let s of t.content){let i=await l(e,F.join(e,s),d$1.semanticInput,"Text content input");if(o+=i.data.byteLength,o>d$1.semanticTotal)throw new Error("Text content inputs exceed the total inspection size limit.");n[s]=f(i.data);let a=i.data.toString("utf8"),c=F.extname(s).toLowerCase();if(c===".html"||c===".htm")r.push(...sr(a));else if([".ts",".tsx",".js",".jsx",".mts",".cts",".mjs",".cjs"].includes(c))r.push(...ar(a,s));else if(c===".json")cr(JSON.parse(a),r);else if(c===".txt"||c===".md")r.push(a);else throw new Error(`Unsupported configured text content type: ${s}.`)}return {values:r,glyphs:ir(r,t.generation),inputs:n}}a(Vt,"discoverTextContent");var yr=1,Rt="1.0.0",da=Object.freeze({"geist-sans":{id:"geist-sans",family:"Geist Sans",version:"1.600",license:"OFL-1.1",licenseFile:"OFL-1.1.txt",sourceFile:"geist-sans/Geist-Variable.ttf",sourceUrl:"https://raw.githubusercontent.com/vercel/geist-font/1.6.0/fonts/Geist/variable/Geist%5Bwght%5D.ttf",sourceBytes:168472,sourceChecksum:"995c579489b33cd28a6732d7aa7ca1b46c2faa832c18b4063933d7652c39932b",browserFile:"geist-sans/Geist-Variable.woff2",browserUrl:"https://raw.githubusercontent.com/vercel/geist-font/449415077ee4ffc191b4e7e557cd35e88b1b98fd/packages/next/dist/fonts/geist-sans/Geist-Variable.woff2",browserBytes:58512,browserChecksum:"46525b05bbf4527d263f8624ca7024c7d0dce3c64430267d30c31c6dd3821e4d"},"noto-sans-jp":{id:"noto-sans-jp",family:"Noto Sans JP",version:"2.004-H2",license:"OFL-1.1",licenseFile:"OFL-1.1.txt",sourceFile:"noto-sans-jp/NotoSansJP[wght].ttf",sourceUrl:"https://raw.githubusercontent.com/google/fonts/295d98a7a0c17c68f1341eaeea354e7960ea70d3/ofl/notosansjp/NotoSansJP%5Bwght%5D.ttf",sourceBytes:9589900,sourceChecksum:"c2f3b4d463500a2ddcd3849cded1fceeb9fd6d1c32e6cbecd568453ba50fc68f",browserFile:"noto-sans-jp/NotoSansJP[wght].woff2",browserUrl:"https://raw.githubusercontent.com/RenaudRohlinger/three-blocks-monorepo/364a50cc5f6f92735a110b50144e8d62404c9d87/packages/three-blocks-devtools/fonts/noto-sans-jp/NotoSansJP%5Bwght%5D.woff2",browserBytes:4350080,browserChecksum:"6fd94964d1990baa2a392cea7a036683d2b80b9dfd590cb3918e8dab98d8e188"}}),ca="THREE_BLOCKS_FONT_CACHE_DIR",la=6e4,Ut=new Map,ua=fileURLToPath(new URL("../fonts/",import.meta.url));function ge(e,t){if(typeof e!="number"||!Number.isFinite(e))throw new Error(`${t} must be finite.`);return e}a(ge,"finiteNumber");function Fe(e,t){let r=ge(e,t);if(!Number.isSafeInteger(r))throw new Error(`${t} must be an integer.`);return r}a(Fe,"integer");function ma(e){if(!a$1(e)||!a$1(e.info)||!a$1(e.common)||!Array.isArray(e.chars))throw new Error("MSDF generator returned invalid BMFont metadata.");let t=e.chars.map((o,s)=>{if(!a$1(o))throw new Error(`BMFont character ${s} is invalid.`);return {id:Fe(o.id,`BMFont character ${s}.id`),x:ge(o.x,`BMFont character ${s}.x`),y:ge(o.y,`BMFont character ${s}.y`),width:ge(o.width,`BMFont character ${s}.width`),height:ge(o.height,`BMFont character ${s}.height`),xoffset:ge(o.xoffset,`BMFont character ${s}.xoffset`),yoffset:ge(o.yoffset,`BMFont character ${s}.yoffset`),xadvance:ge(o.xadvance,`BMFont character ${s}.xadvance`)}}),r=e.kernings===void 0?[]:e.kernings;if(!Array.isArray(r))throw new Error("BMFont kernings are invalid.");let n=r.map((o,s)=>{if(!a$1(o))throw new Error(`BMFont kerning ${s} is invalid.`);return {first:Fe(o.first,`BMFont kerning ${s}.first`),second:Fe(o.second,`BMFont kerning ${s}.second`),amount:ge(o.amount,`BMFont kerning ${s}.amount`)}});return {info:{size:ge(e.info.size,"BMFont info.size"),face:typeof e.info.face=="string"?e.info.face:"Font"},common:{base:ge(e.common.base,"BMFont common.base"),scaleW:Fe(e.common.scaleW,"BMFont common.scaleW"),scaleH:Fe(e.common.scaleH,"BMFont common.scaleH")},chars:t,kernings:n}}a(ma,"parseBMFont");function yn(e){let t=e.generation.size??48,r=e.generation.distanceRange??8,n=e.generation.padding??2,o=e.generation.maxTextureSize??4096;if(!Number.isInteger(t)||t<8||t>256)throw new Error("Text generation size must be an integer from 8 to 256.");if(!Number.isInteger(r)||r<1||r>64)throw new Error("Text generation distanceRange must be an integer from 1 to 64.");if(!Number.isInteger(n)||n<0||n>32)throw new Error("Text generation padding must be an integer from 0 to 32.");if(!Number.isInteger(o)||o<64||o>8192||(o&o-1)!==0)throw new Error("Text generation maxTextureSize must be a power of two from 64 to 8192.");return {size:t,distanceRange:r,padding:n,maxTextureSize:o}}a(yn,"atlasOptions");function gr(e){let t=da[e];if(t===void 0)throw new Error(`Unknown built-in font ${JSON.stringify(e)}.`);return t}a(gr,"builtinFontMetadata");function gn(e){let t=e.cacheDirectory??process.env[ca];return t?F.resolve(t):platform()==="darwin"?F.join(homedir(),"Library","Caches","three-blocks","fonts"):platform()==="win32"?F.join(process.env.LOCALAPPDATA?.trim()||F.join(homedir(),"AppData","Local"),"Three Blocks","Cache","fonts"):F.join(process.env.XDG_CACHE_HOME?.trim()||F.join(homedir(),".cache"),"three-blocks","fonts")}a(gn,"fontCacheRoot");function dn(e,t){return t==="source"?{font:e,kind:t,file:e.sourceFile,url:e.sourceUrl,bytes:e.sourceBytes,checksum:e.sourceChecksum,...e.sourceArchive===void 0?{}:{archive:e.sourceArchive}}:{font:e,kind:t,file:e.browserFile,url:e.browserUrl,bytes:e.browserBytes,checksum:e.browserChecksum}}a(dn,"builtinAsset");function wn(e,t){let r=gr(e),n=t.mapBuiltinFont?.(r)??r;if(n.id!==r.id||n.version!==r.version||n.sourceBytes!==r.sourceBytes||n.sourceChecksum!==r.sourceChecksum||n.browserBytes!==r.browserBytes||n.browserChecksum!==r.browserChecksum)throw new Error(`Runtime metadata for built-in font ${JSON.stringify(e)} changed its pinned identity.`);return n}a(wn,"runtimeBuiltinFontMetadata");function fa(e,t){return F.join(gn(t),e.font.id,e.font.version,e.checksum,F.basename(e.file))}a(fa,"builtinCachePath");async function pa(e$1,t){try{let r=await j(e$1,d$1.texture,`${t.font.id} cached ${t.kind} font`);if(r.data.byteLength===t.bytes&&f(r.data)===t.checksum)return r.data;await rm(e$1,{force:!0});return}catch(r){if(e(r)==="ENOENT")return;throw r}}a(pa,"readCachedFont");async function ha(e$1){try{let t=await j(F.join(ua,e$1.file),e$1.bytes,`${e$1.font.id} packaged ${e$1.kind} font`);return t.data.byteLength===e$1.bytes&&f(t.data)===e$1.checksum?t.data:void 0}catch(t){if(e(t)==="ENOENT")return;throw t}}a(ha,"readPackagedFont");async function ya(e,t){try{let r=await l(e.root,e.filePath,t.bytes,`${t.font.id} existing browser font output`);return r.data.byteLength!==t.bytes||f(r.data)!==t.checksum?void 0:r.data}catch{return}}a(ya,"readBuiltinBrowserSeed");function ga(e,t,r){let n=Math.max(0,e.byteLength-65557),o=-1;for(let l=e.byteLength-22;l>=n;l--)if(e.readUInt32LE(l)===101010256){o=l;break}if(o<0)throw new Error("downloaded ZIP has no end-of-central-directory record");let s=e.readUInt16LE(o+10),i=e.readUInt32LE(o+12),a=e.readUInt32LE(o+16);if(a+i>o)throw new Error("downloaded ZIP central directory is out of bounds");let c=a;for(let l=0;l<s;l++){if(c+46>e.byteLength||e.readUInt32LE(c)!==33639248)throw new Error("downloaded ZIP central directory is invalid");let f=e.readUInt16LE(c+10),u=e.readUInt32LE(c+20),m=e.readUInt32LE(c+24),p=e.readUInt16LE(c+28),h=e.readUInt16LE(c+30),y=e.readUInt16LE(c+32),w=e.readUInt32LE(c+42),b=c+46+p+h+y;if(b>e.byteLength)throw new Error("downloaded ZIP entry metadata is out of bounds");let x=e.subarray(c+46,c+46+p).toString("utf8");if(c=b,x!==t)continue;if(m!==r)throw new Error(`ZIP entry has ${m} bytes; expected ${r}`);if(w+30>e.byteLength||e.readUInt32LE(w)!==67324752)throw new Error("downloaded ZIP local entry is invalid");let g=e.readUInt16LE(w+26),T=e.readUInt16LE(w+28),R=w+30+g+T;if(R+u>e.byteLength)throw new Error("downloaded ZIP entry data is out of bounds");let C=e.subarray(R,R+u);if(f===0)return Buffer.from(C);if(f===8)return xt.inflateRawSync(C,{maxOutputLength:r});throw new Error(`ZIP entry uses unsupported compression method ${f}`)}throw new Error(`downloaded ZIP does not contain ${JSON.stringify(t)}`)}a(ga,"zipEntry");async function wa(e,t){let r=new URL(e.url);if(r.protocol!=="https:")throw new Error(`Built-in font source must use HTTPS: ${e.url}.`);let n;try{n=await t(r,{signal:AbortSignal.timeout(la)});}catch(h){throw new Error(`request failed: ${h instanceof Error?h.message:String(h)}`,{cause:h})}if(!n.ok)throw new Error(`server returned HTTP ${n.status} ${n.statusText}`.trim());let o=e.archive?.bytes??e.bytes,s=e.archive?.checksum??e.checksum,i=n.headers.get("content-length");if(i!==null){let h=Number(i);if(!Number.isSafeInteger(h)||h!==o)throw new Error(`server declared ${i} bytes; expected ${o}`)}if(n.body===null)throw new Error("server returned an empty response body");let a=n.body.getReader(),c=[],l=0;for(;;){let h=await a.read();if(h.done)break;if(l+=h.value.byteLength,l>o||l>d$1.texture)throw await a.cancel(),new Error(`download exceeded the expected ${o}-byte size`);c.push(Buffer.from(h.value.buffer,h.value.byteOffset,h.value.byteLength));}let f$1=Buffer.concat(c,l);if(f$1.byteLength!==o)throw new Error(`downloaded ${f$1.byteLength} bytes; expected ${o}`);let u=f(f$1);if(u!==s)throw new Error(`checksum mismatch: expected ${s}, received ${u}`);let m=e.archive===void 0?f$1:ga(f$1,e.archive.entry,e.bytes);if(m.byteLength!==e.bytes)throw new Error(`resolved ${m.byteLength} bytes; expected ${e.bytes}`);let p=f(m);if(p!==e.checksum)throw new Error(`resolved checksum mismatch: expected ${e.checksum}, received ${p}`);return m}a(wa,"downloadFont");async function ur(e,t){await mkdir(F.dirname(e),{recursive:true});let r=`${e}.${process.pid}.${randomUUID()}.tmp`;try{await writeFile(r,t,{flag:"wx"}),await rename(r,e);}finally{await rm(r,{force:true});}}a(ur,"writeCachedFont");async function cn(e,t,r){let n=fa(e,t),o=Ut.get(n);if(o)return o;let s=(async()=>{let i=await pa(n,e);if(i)return i;if(t.fetch===void 0&&t.mapBuiltinFont===void 0){let a=await ha(e);if(a!==void 0)return await ur(n,a),a}if(r!==void 0){let a=await ya(r,e);if(a!==void 0)return await ur(n,a),a}try{let a=await wa(e,t.fetch??globalThis.fetch);return await ur(n,a),a}catch(a){throw new Error(`Could not download the built-in ${e.font.id} ${e.kind} font from ${e.url}: ${a instanceof Error?a.message:String(a)}. Connect once to prewarm the checksum-keyed cache at ${JSON.stringify(gn(t))}, or configure source.path/source.package for fully offline text generation.`,{cause:a})}})();Ut.set(n,s);try{return await s}finally{Ut.get(n)===s&&Ut.delete(n);}}a(cn,"cachedBuiltinAsset");async function bn(e,t,r){let[n,o]=await Promise.allSettled([cn(dn(e,"source"),t),cn(dn(e,"browser"),t,r)]);if(n.status==="rejected")throw n.reason;if(o.status==="rejected")throw o.reason;return [n.value,o.value]}a(bn,"cachedBuiltinPair");async function ba(e,t={}){let r=wn(e,t);await bn(r,t);}a(ba,"prewarmBuiltinFont");async function Sn(e,t,r){let n=await j(e,d$1.texture,r),o=f(n.data);if(t!=="pending"&&o!==t)throw new Error(`${r} checksum mismatch: expected ${t}, received ${o}.`);return n.data}a(Sn,"checkedExternalFile");function kn(e,t){if(!/^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/iu.test(t))throw new Error("Text font package name is unsafe.");return F.join(e,"node_modules",...t.split("/"))}a(kn,"packageRoot");async function Sa(e,t){if("builtin"in t){let o=gr(t.builtin);return {sourceHash:o.sourceChecksum,browserHash:o.browserChecksum,description:`builtin:${o.id}@${o.version}`,license:o.license}}if("path"in t){let o=await l(e,F.join(e,t.path),d$1.texture,"Text source font");return {sourceHash:f(o.data),browserHash:f(o.data),description:t.path}}let r=F.join(kn(e,t.package),t.file),n=await Sn(r,t.checksum,"Package text source font");return {sourceHash:f(n),browserHash:f(n),description:`${t.package}/${t.file}`}}a(Sa,"resolveFontIdentity");async function ka(e,t,r,n){if("builtin"in t){let a=wn(t.builtin,r),[c,l]=await bn(a,r,n===void 0?void 0:{root:e,filePath:n});return {source:c,sourceHash:a.sourceChecksum,browser:l,browserHash:a.browserChecksum,description:`builtin:${a.id}@${a.version}`,license:a.license}}if("path"in t){let a=await l(e,F.join(e,t.path),d$1.texture,"Text source font"),c=f(a.data);return {source:a.data,sourceHash:c,browser:a.data,browserHash:c,description:t.path}}let o=F.join(kn(e,t.package),t.file),s=await Sn(o,t.checksum,"Package text source font"),i=f(s);return {source:s,sourceHash:i,browser:s,browserHash:i,description:`${t.package}/${t.file}`}}a(ka,"resolveFont");function kt(e,t){let r=t.replace(/^\/+/,""),n=F.resolve(e,"public",r),o=F.resolve(e,"public"),s=F.relative(o,n);if(s===""||s===".."||s.startsWith(`..${F.sep}`)||F.isAbsolute(s))throw new Error(`Deployed text path ${JSON.stringify(t)} escapes public/.`);return n}a(kt,"deployedFile");function hr(e,t){return F.relative(e,t).split(F.sep).join("/")}a(hr,"portablePath");function xn(e){return e.endsWith(".json")?`${e.slice(0,-5)}.meta.json`:`${e}.meta.json`}a(xn,"metadataPath");function Rn(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}a(Rn,"bufferArray");function xa(e,t){return t.filter(r=>r===65533||e.charToGlyphIndex(String.fromCodePoint(r))!==0)}a(xa,"supportedCodePoints");function Ra(e,t,r,n){return new Promise((o,s)=>{aa(e,{filename:r,charset:t.map(i=>String.fromCodePoint(i)),outputType:"json",fieldType:"msdf",fontSize:n.size,distanceRange:n.distanceRange,texturePadding:n.padding,textureSize:[n.maxTextureSize,n.maxTextureSize],smartSize:true,pot:true},(i,a,c)=>{if(i)return s(i);if(a.length!==1||a[0]===void 0)return s(new Error(`Text glyphs require ${a.length} atlas pages; raise maxTextureSize or lower size.`));try{o({png:a[0].texture,data:ma(JSON.parse(c.data))});}catch(l){s(l);}});})}a(Ra,"generateBMFontData");function va(e,t,r){let n=1/e.info.size,o=e.common.base,s=t.unitsPerEm,i=t.tables.hhea;return {name:t.names?.fontFamily?.en??e.info.face,atlas:{type:"msdf",distanceRange:r.distanceRange,size:e.info.size,width:e.common.scaleW,height:e.common.scaleH,yOrigin:"top"},metrics:{emSize:1,lineHeight:(i.ascender-i.descender+i.lineGap)/s,ascender:i.ascender/s,descender:i.descender/s,underlineY:(t.tables.post?.underlinePosition??-s*.1)/s,underlineThickness:(t.tables.post?.underlineThickness??s*.05)/s},glyphs:e.chars.slice().sort((a,c)=>a.id-c.id).map(a=>({unicode:a.id,advance:a.xadvance*n,...a.width>0&&a.height>0?{planeBounds:{left:a.xoffset*n,bottom:(o-a.yoffset-a.height)*n,right:(a.xoffset+a.width)*n,top:(o-a.yoffset)*n},atlasBounds:{left:a.x,top:a.y,right:a.x+a.width,bottom:a.y+a.height}}:{}})),kerning:e.kernings.filter(a=>a.amount!==0).sort((a,c)=>a.first-c.first||a.second-c.second).map(a=>({unicode1:a.first,unicode2:a.second,advance:a.amount*n}))}}a(va,"convertMetrics");function vn(){return xt}a(vn,"zstdFunctions");function Ea(e){let t=PNG.sync.read(e),r=new Uint8Array(t.data.buffer,t.data.byteOffset,t.data.byteLength),o=vn().zstdCompressSync,s=o===void 0?"none":"zstd",i=xt.constants.ZSTD_c_compressionLevel,a$1=o?.(r,i===void 0?{}:{params:{[i]:19}}),c=createDefaultContainer();c.vkFormat=VK_FORMAT_R8G8B8A8_UNORM,c.typeSize=1,c.pixelWidth=t.width,c.pixelHeight=t.height,c.supercompressionScheme=s==="zstd"?KHR_SUPERCOMPRESSION_ZSTD:KHR_SUPERCOMPRESSION_NONE,c.levels=[{levelData:a$1===void 0?r:new Uint8Array(a$1.buffer,a$1.byteOffset,a$1.byteLength),uncompressedByteLength:r.byteLength}];let l=a((u,m)=>({bitOffset:u*8,bitLength:7,channelType:m,samplePosition:[0,0,0,0],sampleLower:0,sampleUpper:255}),"sample");c.dataFormatDescriptor=[{vendorId:KHR_DF_VENDORID_KHRONOS,descriptorType:KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,versionNumber:KHR_DF_VERSION,colorModel:KHR_DF_MODEL_RGBSDA,colorPrimaries:KHR_DF_PRIMARIES_BT709,transferFunction:KHR_DF_TRANSFER_LINEAR,flags:KHR_DF_FLAG_ALPHA_STRAIGHT,texelBlockDimension:[0,0,0,0],bytesPlane:[0,0,0,0,0,0,0,0],samples:[l(0,KHR_DF_CHANNEL_RGBSDA_RED),l(1,KHR_DF_CHANNEL_RGBSDA_GREEN),l(2,KHR_DF_CHANNEL_RGBSDA_BLUE),l(3,KHR_DF_CHANNEL_RGBSDA_ALPHA|KHR_DF_SAMPLE_DATATYPE_LINEAR)]}],c.keyValue.KTXwriter=`three-blocks text ${Rt}`,c.keyValue.KTXorientation="rd";let f=write(c,{keepWriter:true});return En(f,t.width,t.height),{bytes:f,width:t.width,height:t.height,compression:s}}a(Ea,"createKtx2");function En(e,t,r){let n=read(e);if(n.vkFormat!==VK_FORMAT_R8G8B8A8_UNORM)throw new Error("Text atlas must use RGBA8 KTX2.");if(n.pixelWidth<=0||n.pixelHeight<=0||n.levels.length!==1||n.levels[0]===void 0)throw new Error("Text atlas KTX2 dimensions or levels are invalid.");if(t!==void 0&&n.pixelWidth!==t)throw new Error("Text atlas KTX2 width does not match metrics.");if(r!==void 0&&n.pixelHeight!==r)throw new Error("Text atlas KTX2 height does not match metrics.");if(n.keyValue.KTXorientation!=="rd")throw new Error("Text atlas KTX2 orientation must be rd.");let o=n.levels[0],s,i;if(n.supercompressionScheme===KHR_SUPERCOMPRESSION_ZSTD){let c=vn().zstdDecompressSync;if(c===void 0)throw new Error("This Node.js runtime cannot validate Zstandard KTX2 text atlases.");s=c(o.levelData),i="zstd";}else if(n.supercompressionScheme===KHR_SUPERCOMPRESSION_NONE)s=o.levelData,i="none";else throw new Error("Text atlas uses an unsupported KTX2 supercompression scheme.");let a=n.pixelWidth*n.pixelHeight*4;if(s.byteLength!==a||o.uncompressedByteLength!==a)throw new Error("Text atlas KTX2 decoded byte length is invalid.");return {width:n.pixelWidth,height:n.pixelHeight,compression:i}}a(En,"validateKtx2Bytes");function ln(e){return `${JSON.stringify(e)}
2
+ `}a(ln,"stableJson");function mr(e,t,r){return {path:hr(e,t),sha256:f(r),bytes:r.byteLength}}a(mr,"fileReceipt");function Tn(e,t,r,n){return f(JSON.stringify({generator:Rt,fontKey:n,fontHash:e.sourceHash,glyphSetHash:t,options:r}))}a(Tn,"createInputHash");async function Ta(e,t,r,n,o,s,i$1){if(o.length===0)throw new Error(`Text font ${JSON.stringify(t)} covers no required glyphs.`);let a=hn.parse(Rn(n.source)),c=await Ra(n.source,o,t,i$1),l=va(c.data,a,i$1),f=Buffer.from(ln(l)),u=Ea(c.png);if(c.data.common.scaleW!==u.width||c.data.common.scaleH!==u.height)throw new Error(`Text font ${JSON.stringify(t)} metrics and texture dimensions differ.`);let m=kt(e,r.browser),p=kt(e,r.atlas),h=kt(e,r.metrics),y=xn(h),w={schemaVersion:yr,generatorVersion:Rt,font:{key:t,source:n.description,sourceHash:n.sourceHash,...n.license===void 0?{}:{license:n.license}},inputHash:Tn(n,s,i$1,t),glyphSetHash:s,codePoints:o,options:i$1,texture:{format:"RGBA8",orientation:"rd",compression:u.compression,width:u.width,height:u.height},files:{browser:mr(e,m,n.browser),atlas:mr(e,p,u.bytes),metrics:mr(e,h,f)}},b=Buffer.from(ln(w));await i(m,n.browser),await i(p,u.bytes),await i(h,f),await i(y,b);let x=[m,p,h,y].map(g=>hr(e,g));return {font:t,receipt:w,metadataPath:hr(e,y),updatedFiles:x}}a(Ta,"generateRoute");async function Ba(e,t="three-blocks.text.ts",r={}){let n=await Ht(e,t),o=await Vt(e,n),s=yn(n),i=[];for(let[f,u]of Object.entries(n.fonts).sort((m,p)=>m[0].localeCompare(p[0]))){let m=await ka(e,u.source,r,"builtin"in u.source?kt(e,u.browser):void 0),p=hn.parse(Rn(m.source));i.push({key:f,route:u,resolved:m,font:p,codePoints:xa(p,o.glyphs.codePoints)});}let a=new Set(i.flatMap(f=>f.codePoints)),c=o.glyphs.codePoints.filter(f=>!a.has(f));if(c.length>0)throw new Error(`Configured fonts do not cover ${c.length} required glyph(s): ${c.map(f=>String.fromCodePoint(f)).join(" ")}`);let l=[];for(let f of i)l.push(await Ta(e,f.key,f.route,f.resolved,f.codePoints,o.glyphs.hash,s));return {glyphs:o.glyphs.codePoints.length,glyphSetHash:o.glyphs.hash,atlases:l,updatedFiles:l.flatMap(f=>f.updatedFiles)}}a(Ba,"generateTextAtlases");function fr(e,t){if(!a$1(e)||typeof e.path!="string"||typeof e.sha256!="string"||!/^[a-f0-9]{64}$/u.test(e.sha256)||!Number.isSafeInteger(e.bytes)||e.bytes<0)throw new Error(`${t} receipt is invalid.`);return e}a(fr,"parseFileReceipt");function Bn(e){if(!a$1(e)||e.schemaVersion!==yr||e.generatorVersion!==Rt||!a$1(e.font)||typeof e.font.key!="string"||typeof e.font.source!="string"||typeof e.font.sourceHash!="string"||!/^[a-f0-9]{64}$/u.test(e.font.sourceHash)||typeof e.inputHash!="string"||!/^[a-f0-9]{64}$/u.test(e.inputHash)||typeof e.glyphSetHash!="string"||!/^[a-f0-9]{64}$/u.test(e.glyphSetHash)||!Array.isArray(e.codePoints)||!e.codePoints.every(t=>Number.isSafeInteger(t))||!a$1(e.options)||!a$1(e.texture)||!a$1(e.files))throw new Error("Text atlas generation metadata is invalid.");if(e.texture.format!=="RGBA8"||e.texture.orientation!=="rd"||!["zstd","none"].includes(e.texture.compression))throw new Error("Text atlas texture metadata is invalid.");return fr(e.files.browser,"Browser font"),fr(e.files.atlas,"Text atlas"),fr(e.files.metrics,"Text metrics"),e}a(Bn,"parseTextAtlasReceipt");function $a(e){if(!a$1(e)||!a$1(e.atlas)||!Array.isArray(e.glyphs))throw new Error("Text metrics are invalid.");let t=Fe(e.atlas.width,"Text metrics atlas.width"),r=Fe(e.atlas.height,"Text metrics atlas.height"),n=e.glyphs.map((o,s)=>{if(!a$1(o))throw new Error(`Text metrics glyph ${s} is invalid.`);return Fe(o.unicode,`Text metrics glyph ${s}.unicode`)});return {width:t,height:r,codePoints:n}}a($a,"metricsCoverage");async function pr(e,t,r,n){let o=await l(e,F.join(e,t.path),r,n);if(o.data.byteLength!==t.bytes||f(o.data)!==t.sha256)throw new Error(`${n} checksum or byte length differs from generation metadata.`);return o.data}a(pr,"verifyReceiptFile");async function Wt(e,t="three-blocks.text.ts"){let r;try{r=await Ht(e,t);}catch(n){return {state:"invalid",reason:`Text configuration is invalid: ${n instanceof Error?n.message:String(n)}`,missing:[],atlases:[]}}try{let n=await Vt(e,r),o=yn(r),s=[],i=new Set;for(let[c,l$1]of Object.entries(r.fonts).sort((f,u)=>f[0].localeCompare(u[0]))){let f$1=await l(e,xn(kt(e,l$1.metrics)),d$1.metadata,"Text atlas generation metadata"),u=Bn(JSON.parse(f$1.data.toString("utf8")));if(u.font.key!==c)throw new Error(`Text atlas metadata belongs to ${JSON.stringify(u.font.key)}, not ${JSON.stringify(c)}.`);let m=await Sa(e,l$1.source),p=Tn(m,u.glyphSetHash,o,c);if(u.inputHash!==p)return {state:"invalid",reason:`Text atlas ${c} font source or generation options changed.`,missing:[],atlases:[...s,u]};let[h,y,w]=await Promise.all([pr(e,u.files.browser,d$1.texture,"Browser font"),pr(e,u.files.atlas,d$1.texture,"Text atlas"),pr(e,u.files.metrics,d$1.metrics,"Text metrics")]);if(f(h)!==m.browserHash)throw new Error(`Browser font ${c} differs from its resolved source.`);let b=$a(JSON.parse(w.toString("utf8"))),x=En(y,b.width,b.height);if(x.width!==u.texture.width||x.height!==u.texture.height||x.compression!==u.texture.compression)throw new Error(`Text atlas ${c} texture metadata does not match KTX2.`);for(let g of b.codePoints)i.add(g);s.push(u);}let a=n.glyphs.codePoints.filter(c=>!i.has(c));return a.length>0?{state:"missing",reason:`${a.length} required glyph(s) are missing.`,missing:a,atlases:s}:{state:"ready",reason:`${n.glyphs.codePoints.length} required glyphs are covered by ${s.length} atlas(es).`,missing:[],atlases:s}}catch(n){return (typeof n=="object"&&n!==null&&"code"in n?n.code:void 0)==="ENOENT"?{state:"missing",reason:"Text atlas files or generation metadata are absent.",missing:[],atlases:[]}:{state:"invalid",reason:n instanceof Error?n.message:String(n),missing:[],atlases:[]}}}a(Wt,"inspectTextAtlases");var br=[".ts",".tsx",".mts",".cts",".js",".jsx",".mjs",".cjs",".wgsl",".glsl",".vert",".frag",".json",".css"],Sr=new Set(br),wr=/^(?:three-blocks\.shaders\.json|(?:precompile|three-blocks\.shaders)\.config\.(?:cjs|cts|js|mjs|mts|ts))$/u,Pa=/(?:^|\/)scene\.(?:cjs|cts|js|jsx|mjs|mts|ts|tsx)$/u,_a=/\b(?:export\s+)?(?:async\s+)?function\s+createScene\b|\bcreateScene\s*=\s*(?:async\s*)?\(/u,Ma=/\b(?:[A-Za-z_$][\w$]*\.)*(?:shaders|shaderCache|sceneShaders)\s*\.\s*(?:material|pipeline|compute|container)\s*\(/u,Ca=/\b(import|export)(?!\s*\()\s*(type\b\s*)?(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']/gu,Oa=/\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,Fa=/\b(?:import|export)(?!\s*\()\s*(?:[^"'();]*?\bfrom\s*)?["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/gu,Ia=/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,127}$/u,kr=4096,La="./shaders";function Pn(e,t){let r=F.relative(e,t).split(F.sep).join("/");if(r.length===0||/[\u0000-\u001f\u007f]/u.test(r))throw new Error("Semantic input has an unsafe relative path.");return r}a(Pn,"portableRelativePath");function xr(e,t){try{return new TextDecoder("utf-8",{fatal:!0}).decode(e)}catch{throw new Error(`Shader-relevant source ${JSON.stringify(t)} is not valid UTF-8.`)}}a(xr,"sourceText");function vr(e,t){let r="",n="code";for(let o=0;o<e.length;o++){let s=e[o]??"",i=e[o+1]??"";if(n==="code"){if(s==="/"&&i==="/"){r+=" ",n="line-comment",o++;continue}if(s==="/"&&i==="*"){r+=" ",n="block-comment",o++;continue}if(s==="'"||s==='"'||s==="`"){n=s==="'"?"single":s==='"'?"double":"template",r+=t?s:" ";continue}r+=s;continue}if(n==="line-comment"){s===`
3
3
  `?(r+=`
4
4
  `,n="code"):r+=" ";continue}if(n==="block-comment"){s==="*"&&i==="/"?(r+=" ",n="code",o++):r+=s===`
5
5
  `?`
6
6
  `:" ";continue}let a=n==="single"?"'":n==="double"?'"':"`";if(s==="\\"&&i.length>0){r+=t?`${s}${i}`:" ",o++;continue}r+=t?s:s===`
7
7
  `?`
8
- `:" ",s===a&&(n="code");}return r}a(Er,"lexicalSource");function Ia(e){let t=new Set,r=Er(e,true);for(let n of r.matchAll(_a))n[2]===void 0&&n[3]!==void 0&&t.add(n[3]);for(let n of r.matchAll(Ma))n[1]!==void 0&&t.add(n[1]);return [...t].sort()}a(Ia,"importSpecifiers");function La(e){let t=new Set;for(let r of Er(e,true).matchAll(Ca)){let n=r[1]??r[2];n!==void 0&&t.add(n);}return [...t].sort()}a(La,"runtimeSpecifiers");function _n(e){return (e.split(/[?#]/u,1)[0]??e).replaceAll("\\","/")}a(_n,"cleanSpecifier");function ja(e,t,r){let n=_n(t),o;if(n.startsWith("./")||n.startsWith("../"))o=F.posix.normalize(F.posix.join(F.posix.dirname(e),n));else if(n.startsWith("@/"))o=`src/${n.slice(2)}`;else if(n.startsWith("/src/"))o=n.slice(1);else return;if(o===".three-blocks"||o.startsWith(".three-blocks/"))return;let s=F.posix.extname(o).toLowerCase(),i=new Set([o]);if(s.length===0||!kr.has(s)){for(let a of Sr)i.add(`${o}${a}`);for(let a of Sr)i.add(`${o}/index${a}`);}else if([".js",".mjs",".cjs",".jsx"].includes(s)){let a=o.slice(0,-s.length);for(let c of [".ts",".tsx",".mts",".cts"])i.add(`${a}${c}`);}return [...i].find(a=>r.has(a))}a(ja,"resolveProjectImport");function Da(e,t){let r=Er(t,false);return $a.test(e)||Pa.test(r)||Aa.test(r)}a(Da,"isShaderRoot");async function Ie(e,t){let r=await realpath(e);if(t!==void 0){let l$1={},m=0;for(let p of t){let h=await l(r,F.join(r,p),d$1.semanticInput,"Declared shader semantic input");if(m+=h.data.byteLength,m>d$1.semanticTotal)throw new Error("Declared shader semantic inputs exceed the total inspection size limit.");l$1[p]=f(h.data);}return l$1}let n=new Map,o=F.join(r,"src");if(await g(o))for(let l$1 of await m(r,o,m=>kr.has(F.extname(m).toLowerCase()))){let m=await l(r,l$1,d$1.semanticInput,"Shader semantic input");n.set(An(r,l$1),m.data);}for(let l$1 of await readdir(r,{withFileTypes:true})){if(!l$1.isFile()||!br.test(l$1.name)&&!kr.has(F.extname(l$1.name).toLowerCase()))continue;let m=await l(r,F.join(r,l$1.name),d$1.semanticInput,br.test(l$1.name)?"Shader configuration input":"Shader semantic input");n.set(l$1.name,m.data);}if(n.size>xr)throw new Error(`Shader input discovery exceeds the ${xr}-file limit.`);let s=new Set,i=new Map;for(let[l,m]of n){if(!l.includes("/")&&br.test(l)&&s.add(l),!l.startsWith("src/"))continue;let p=Rr(m,l);i.set(l,p),Da(l,p)&&s.add(l);}if(s.size===0)throw new Error("No shader registration or scene source root was found.");let a=new Set,c=[...s].sort();for(;c.length>0;){let l=c.shift();if(l===void 0||a.has(l))continue;let m=n.get(l);if(m===void 0)continue;a.add(l);let p=i.get(l)??Rr(m,l);for(let h of Ia(p)){let y=ja(l,h,n);y!==void 0&&!a.has(y)&&c.push(y);}c.sort();}let u=0,f$1={};for(let l of [...a].sort()){let m=n.get(l);if(m===void 0)throw new Error(`Shader input ${JSON.stringify(l)} disappeared during inspection.`);if(u+=m.byteLength,u>d$1.semanticTotal)throw new Error("Semantic shader inputs exceed the total inspection size limit.");f$1[l]=f(m);}return f$1}a(Ie,"snapshotShaderInputs");function vr(e){if(typeof e=="string")return e;if(a$1(e))return vr(e.import)??vr(e.default)}a(vr,"conditionalImportTarget");async function $n(e,t){let r=e;for(;;){let n=F.join(r,"node_modules",...t.split("/"),"package.json");if(await g(n)){let s=await j(n,d$1.packageJson,`${t} package.json`),i=JSON.parse(s.data.toString("utf8"));if(!a$1(i)||i.name!==t||typeof i.version!="string"||!Oa.test(i.version))throw new Error(`Installed ${t} package metadata is invalid.`);return {root:F.dirname(s.path),manifest:i}}let o=F.dirname(r);if(o===r)break;r=o;}throw new Error(`Cannot verify the installed ${t} package.`)}a($n,"findInstalledPackage");async function Na(e,t){if(!a$1(t.exports))throw new Error("Installed three-blocks package has no public exports map.");let r=vr(t.exports[Fa]);if(r===void 0||!r.startsWith("./"))throw new Error("Installed three-blocks shader export has no import target.");let n=await realpath(e),o=[F.resolve(n,r)],s=new Map,i=0;for(;o.length>0;){let c=o.shift();if(c===void 0)break;let u=await j(c,d$1.semanticInput,"Three Blocks shader runtime module");if(!h(n,u.path)||u.path===n)throw new Error("Three Blocks shader runtime closure escapes its package.");let f$1=An(n,u.path);if(s.has(f$1))continue;if(i+=u.data.byteLength,i>d$1.semanticTotal)throw new Error("Three Blocks shader runtime closure exceeds the inspection limit.");s.set(f$1,f(u.data));let l=Rr(u.data,f$1);for(let m of La(l)){let p=_n(m);if(!p.startsWith("./")&&!p.startsWith("../"))continue;let h$1=F.resolve(F.dirname(u.path),p);if(!h(n,h$1))throw new Error("Three Blocks shader runtime import escapes its package.");o.push(h$1);}if(o.sort(),s.size+o.length>xr)throw new Error("Three Blocks shader runtime closure exceeds the file limit.")}let a=[...s].sort((c,u)=>c[0].localeCompare(u[0])).map(([c,u])=>`${c}\0${u}`).join(`
9
- `);return f(a)}a(Na,"shaderRuntimeClosure");async function Pe(e){let[t,r]=await Promise.all([$n(e,"three"),$n(e,"three-blocks")]);return {three:String(t.manifest.version),threeBlocks:String(r.manifest.version),threeBlocksShaderClosure:await Na(r.root,r.manifest)}}a(Pe,"readInstalledShaderRuntime");function Va(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}a(Va,"sameCoverage");function Ha(e){let t=e.some(n=>n.state==="invalid")?"invalid":e.some(n=>n.state==="missing")?"missing":e.some(n=>n.state==="stale")?"stale":"fresh",r=e.filter(n=>n.state===t);return {state:t,reason:t==="fresh"?`${e.length} configured shader scene${e.length===1?" is":"s are"} fresh.`:r.map(n=>`${n.scene} (${n.backend}): ${n.reason}`).join("; ")}}a(Ha,"classifyMatrix");function Ua(e,t,r){let n=e.tool;if(!n)return "Shader receipt has no public tool compatibility metadata.";if((n.compatibilities?.[r]??n.compatibility)!==t)return "Shader receipt targets a different runtime compatibility contract.";if(n.transform!==B)return "Shader receipt uses a different provider transform version.";if(n.address!==SHADER_ADDRESS_SCHEMA_VERSION||n.recipe!==SHADER_RECIPE_SCHEMA_VERSION||n.hydration!==SHADER_HYDRATION_SCHEMA_VERSION)return "Shader receipt uses incompatible address, recipe, or hydration schemas."}a(Ua,"exactToolCompatibility");function Wa(e,t){let r=Object.keys(t).filter(s=>Object.hasOwn(e,s)&&e[s]!==t[s]),n=Object.keys(t).filter(s=>!Object.hasOwn(e,s)),o=Object.keys(e).filter(s=>!Object.hasOwn(t,s));return {...r.length>0?{changedInputs:r}:{},...n.length>0?{addedInputs:n}:{},...o.length>0?{removedInputs:o}:{}}}a(Wa,"inputChanges");async function Ue(e=process.cwd(),t$1,r$1){let n=await v(e),o$1=await w(n),s=q(r$1??o$1.backend),i=o$1.scenes.flatMap(u=>r(u,s).map(f=>({scene:u,backend:f,key:t(u.key,f)}))),a$1=F.join(n,o),c=a(()=>({schemaVersion:1,root:n,state:"missing",reason:`${o}/meta.json is absent.`,scenes:i.map(({scene:u,backend:f})=>({scene:u.key,backend:f,state:"missing",reason:"No committed shader receipt."}))}),"missing");if(!await g(a$1)||!await g(F.join(a$1,"meta.json")))return c();try{let u=await k(n,a$1,"Shader artifact directory"),f$1=await l(u,F.join(u,"meta.json"),d$1.receipt,"Shader receipt"),l$1=c$1(JSON.parse(f$1.data.toString("utf8"))),m=await K(u,f$1.data),p=t$1??await Pe(n),h=new Set(o$1.scenes.flatMap(S=>r(S,["webgpu","webgl"]).map(B=>t(S.key,B)))),w=Object.keys(l$1.scenes).filter(S=>!h.has(S));if(w.length>0)throw new Error(`Shader receipt contains unconfigured scenes: ${w.join(", ")}.`);let b=l$1.runtime.three!==p.three,k$1=l$1.runtime.threeBlocksShaderClosure!==p.threeBlocksShaderClosure,g=l$1.tool?.version!==A,P=F.join(n,o$1.publicDir??"public"),R=[];for(let{scene:S,backend:B,key:T}of i){let x=l$1.scenes[T];if(!x){R.push({scene:S.key,backend:B,state:"missing",reason:"Scene/backend is absent from the complete receipt matrix."});continue}let O=z(p.three,B),V=Ua(l$1,O,B);if(V)throw new Error(`${T}: ${V}`);let q=await l(u,F.join(u,x.artifact),d$1.manifest,"Shader manifest");if(f(q.data)!==x.artifactHash)throw new Error(`Shader artifact checksum differs for scene "${S.key}".`);if(x.asset!==void 0&&x.assetHash!==void 0){let re=await l(P,F.join(P,x.asset),d$1.manifest,"Static shader manifest");if(f(re.data)!==x.assetHash)throw new Error(`Static shader manifest checksum differs for scene "${S.key}".`)}if(x.bytes!==void 0&&x.bytes!==q.data.byteLength)throw new Error(`Shader artifact byte count differs for scene "${S.key}".`);let z$1=jt(q.data.toString("utf8"),q.path,S.key,{three:l$1.runtime.three,threeBlocks:l$1.runtime.threeBlocks,compatibility:O,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION});if(!Va(z$1,x.coverage))throw new Error(`Shader coverage differs for scene "${S.key}".`);if(B==="webgpu"&&!o$1.allowLiveBuilds&&x.skipped&&x.skipped.render+x.skipped.compute>0)throw new Error(`Scene "${S.key}" contains skipped live builds but allowLiveBuilds is false.`);let v=await Ie(n,S.inputs),M=Wa(x.inputs,v),L=(M.changedInputs?.length??0)+(M.addedInputs?.length??0)+(M.removedInputs?.length??0),U=b||k$1||g||L>0,ee=m?.scenes[T],X=ee===void 0||m===void 0?void 0:{...ee,schemaVersion:m.schemaVersion,measuredAt:m.measuredAt,source:m.source,...m.source==="committed-capture"?{adapter:m.adapter,platform:m.platform}:{}};R.push({scene:S.key,backend:B,state:U?"stale":"fresh",reason:b?"Installed Three.js version differs from the receipt.":k$1?"Installed three-blocks/shaders runtime closure differs from the receipt.":g?`Receipt was generated by @three-blocks/devtools ${l$1.tool?.version??"unknown"}.`:L>0?`${L} semantic shader input${L===1?"":"s"} changed.`:"Manifest, runtime, schemas, transform, and semantic inputs match.",coverage:z$1,...!U&&X!==void 0&&X.builds===z$1.render+z$1.compute?{timing:X}:{},...M});}let _=Ha(R),C=_.state==="fresh"&&m!==void 0&&R.every(S=>S.timing!==void 0)?m:void 0;return {schemaVersion:1,root:n,..._,scenes:R,runtime:p,receipt:l$1,...C===void 0?{}:{timing:C}}}catch(u){let f=u instanceof Error?u.message:String(u);return {schemaVersion:1,root:n,state:"invalid",reason:f,scenes:i.map(({scene:l,backend:m})=>({scene:l.key,backend:m,state:"invalid",reason:f}))}}}a(Ue,"inspectShaderMatrix");var jn=".three-blocks/shaders/pending-capture";function Ka(e){return (e instanceof Error?`${e.name}: ${e.message}`:String(e)).includes("ShaderHydrationError:")}a(Ka,"isShaderHydrationFailure");async function qa(e,t,r){if(t.length===0)return;let n=F.join(e,o,"meta.json"),o$1=await readFile(n);if(f(o$1)!==f(r))throw new Error("Shader receipt changed before failed scenes could be marked for recapture.");let s=c$1(JSON.parse(o$1.toString("utf8"))),i$1=f(r),a=new Set(t),c=c$1({...s,scenes:Object.fromEntries(Object.entries(s.scenes).map(([u,f])=>[u,a.has(u)?{...f,inputs:{...f.inputs,[jn]:i$1}}:f]))});await i(n,`${H(c)}
10
- `);}a(qa,"markShaderScenesForRecapture");function Xa(e,t){return H(e)===H(t)}a(Xa,"equalSnapshot");async function $r(e={}){let t$1=e.root?await realpath(e.root):await v(e.start),r$1=e.config===void 0?await y(t$1):void 0,n=e.config??r$1?.config??await w(t$1),o=e.runtime??await Pe(t$1),s$1=q(e.backend??n.backend),i=q(n.backend),a$1=[...new Set([...i,...s$1])],c=[...s$1].reverse(),u=[...s(n.scenes,c)],f$1,l={},m;if(e.ifStale){let v=await Ue(t$1,o,e.backend??n.backend);if(v.state==="fresh"&&v.scenes.every(M=>M.timing!==void 0))return {schemaVersion:1,root:t$1,skipped:true,reason:v.reason,scenes:[]};if(v.state!=="invalid"&&v.receipt!==void 0){let M=v.state==="fresh";u=u.filter(({scene:L,backend:U})=>{let ee=v.scenes.find(X=>X.scene===L.key&&X.backend===U);return ee?.state!=="fresh"||M&&ee.timing===void 0}),f$1=v.receipt;for(let L of v.scenes){if(L.state!=="fresh"||L.timing===void 0)continue;let{builds:U,liveBuildMs:ee,precompiledBuildMs:X,avoidedBuildMs:re,runs:se,spreadMs:Xe}=L.timing;l[t(L.scene,L.backend)]={builds:U,liveBuildMs:ee,precompiledBuildMs:X,avoidedBuildMs:re,runs:se,spreadMs:Xe},L.timing.source==="committed-capture"&&L.timing.adapter!==void 0&&L.timing.platform!==void 0&&(m={adapter:L.timing.adapter,platform:L.timing.platform});}}}let p=performance.now(),h=f$1!==void 0&&(f$1.runtime.three!==o.three||f$1.runtime.threeBlocksShaderClosure!==o.threeBlocksShaderClosure||f$1.tool?.version!==A)?f(H({runtime:f$1.runtime,tool:f$1.tool})):void 0,y$1=a(async()=>new Map(await Promise.all(n.scenes.map(async v=>[v.key,await Ie(t$1,v.inputs)]))),"snapshotInputs"),w$1=await y$1(),b=a(async()=>{let v=await y$1();for(let M of n.scenes){let L=w$1.get(M.key),U=v.get(M.key);if(L===void 0||U===void 0||!Xa(L,U))throw new Error(`Semantic shader inputs changed during capture for scene "${M.key}"; the current scene was not committed.`)}},"assertInputsUnchanged"),k=e.driver===void 0,g=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await x(t$1):void 0,P=e.serve??g?.serve,R$1=e.driverKind??g?.driverKind??(P===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(R$1==="vite"&&P!==void 0)throw new Error("--serve requires the static shader driver.");if(R$1==="static"&&P===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let _=e.driver===void 0?await import('./shader-browser-523TEBVA.js'):void 0,C=a(()=>e.url!==void 0?_.createAttachedPlaywrightShaderDriver({root:t$1,runtime:o,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):R$1==="static"?_.createStaticPlaywrightShaderDriver({root:t$1,runtime:o,serve:P,...e.headed!==void 0?{headed:e.headed}:{}}):_.createPlaywrightShaderDriver({root:t$1,runtime:o,...e.headed!==void 0?{headed:e.headed}:{}}),"createDriver"),S=new Map,B=a(v=>{if(e.driver!==void 0)return e.driver;let M=S.get(v);return M===void 0&&(M=C(),S.set(v,M)),M},"driverFor"),T=new Map,x$1=[],O=f$1!==void 0&&n.scenes.every(v=>r(v,a$1).every(M=>f$1?.scenes[t(v.key,M)]!==void 0)),V=f$1,q$1,z=e.attempts??2;if(!Number.isSafeInteger(z)||z<1||z>5)throw new Error("Shader capture attempts must be an integer in 1...5.");try{for(let[U,ee]of u.entries()){let{scene:X,backend:re,key:se}=ee,Xe=B(re);e.onSceneStart?.(se,U,u.length);let oe,Ae,ve=0;for(;ve<z;ve++)try{oe=G(await Xe.capture(X,n,re),{scene:X.key,backend:re,runtime:o});let Se=re==="webgl"&&oe.skipped.every(pe=>pe.reason.startsWith("WebGL shader precompilation does not support "));if(oe.skipped.length>0&&!n.allowLiveBuilds&&!Se)throw new Error(`Scene "${X.key}" contains ${oe.skipped.length} unregistered live shader build${oe.skipped.length===1?"":"s"} while allowLiveBuilds is false.`);break}catch(Se){Ae=Se,oe=void 0,ve+1<z&&e.onSceneRetry?.(X.key,ve+2,z,n.timeoutMs,Se);}if(!oe)throw new Error(`Shader capture "${X.key}" failed after ${z} attempts: ${Ae instanceof Error?Ae.message:String(Ae)}`);if(T.set(se,oe),x$1.push({scene:X.key,backend:re,attempts:ve+1,coverage:oe.coverage,skipped:oe.skipped.length,startupBuilds:oe.stats.registeredBuilds,startupBuildMs:oe.stats.buildMs,...oe.timing===void 0?{}:{timing:oe.timing}}),O&&V!==void 0){await b();let Se=new Map(n.scenes.map(pe=>{let ut=r(pe,a$1),_e=pe.key===X.key?w$1.get(pe.key):ut.map(ye=>V?.scenes[t(pe.key,ye)]?.inputs).find(ye=>ye!==void 0);if(_e===void 0)throw new Error(`Shader checkpoint is missing scene "${pe.key}".`);return h!==void 0&&!ut.every(ye=>T.has(t(pe.key,ye)))&&(_e={..._e,[jn]:h}),[pe.key,_e]}));q$1=await R({root:t$1,scenes:n.scenes,backends:a$1,captures:new Map([[se,oe]]),runtime:o,inputs:Se,previousReceipt:V,publicDirectory:n.publicDir??"public"}),V=q$1.receipt;}}await b(),q$1=await R({root:t$1,scenes:n.scenes,backends:a$1,captures:T,runtime:o,inputs:w$1,...f$1===void 0?{}:{previousReceipt:f$1},publicDirectory:n.publicDir??"public"});let v={...l};for(let U of x$1)v[t(U.scene,U.backend)]={builds:U.coverage.render+U.coverage.compute,setupMeasured:!1,liveBuildMs:U.startupBuildMs,precompiledBuildMs:0,avoidedBuildMs:U.startupBuildMs,runs:1,spreadMs:0};if(e.commitTiming===!0){let U=m??{adapter:T.values().next().value?.provenance?.adapter??"WebGPU adapter",platform:`${Gt.platform()}/${Gt.arch()}`},ee=S.values().next().value??e.driver;await Q(t$1,v,await(ee?.timingEnvironment?.()??U));}else await N$1(t$1,v);let M=await readFile(F.join(q$1.directory,"meta.json")),L=await K(q$1.directory,M);return {schemaVersion:1,root:t$1,skipped:!1,reason:`Wrote ${x$1.length} shader scene${x$1.length===1?"":"s"}.`,durationMs:performance.now()-p,scenes:x$1,measurement:{beforeBuilds:x$1.reduce((U,ee)=>U+ee.startupBuilds,0),afterBuilds:0,firstFrameDeltaMs:-x$1.reduce((U,ee)=>U+ee.startupBuildMs,0),source:"capture-build-phase"},...r$1===void 0?{}:{configuration:{created:r$1.created,file:r$1.file}},written:q$1,...L===void 0?{}:{timing:L}}}finally{k&&await Promise.all([...S.values()].map(v=>v.close()));}}a($r,"captureShaders");function Ja(e){return ["workerReady","assetsReady",...e.requiresText?["textReady"]:[],"compileEnd","firstFrame"]}a(Ja,"requiredReadiness");function In(e){if(e.length===0)throw new Error("Cannot take the median of an empty shader timing capture.");let t=[...e].sort((s,i)=>s-i),r=Math.floor(t.length/2),n=t[r];if(n===void 0)throw new Error("Shader timing median is unavailable.");if(t.length%2===1)return n;let o=t[r-1];if(o===void 0)throw new Error("Shader timing median pair is unavailable.");return (o+n)/2}a(In,"median");function Tr(e,t,r,n){if(e.scene!==t.key||e.mode!==r)throw new Error(`Browser observation identity differs for scene "${t.key}".`);if(e.compatibility!==n||e.transform!==B)throw new Error(`Browser observation compatibility differs for scene "${t.key}".`);let o=Ja(t).filter(s=>e.readiness[s]!==true);if(o.length>0)throw new Error(`Scene "${t.key}" ${r} observation is missing readiness bits: ${o.join(", ")}.`);if(e.errors.length>0)throw new Error(`Scene "${t.key}" ${r} browser errors:
8
+ `:" ",s===a&&(n="code");}return r}a(vr,"lexicalSource");function ja(e){let t=new Set,r=vr(e,true);for(let n of r.matchAll(Ca))n[2]===void 0&&n[3]!==void 0&&t.add(n[3]);for(let n of r.matchAll(Oa))n[1]!==void 0&&t.add(n[1]);return [...t].sort()}a(ja,"importSpecifiers");function Da(e){let t=new Set;for(let r of vr(e,true).matchAll(Fa)){let n=r[1]??r[2];n!==void 0&&t.add(n);}return [...t].sort()}a(Da,"runtimeSpecifiers");function _n(e){return (e.split(/[?#]/u,1)[0]??e).replaceAll("\\","/")}a(_n,"cleanSpecifier");function Na(e,t,r){let n=_n(t),o;if(n.startsWith("./")||n.startsWith("../"))o=F.posix.normalize(F.posix.join(F.posix.dirname(e),n));else if(n.startsWith("@/"))o=`src/${n.slice(2)}`;else if(n.startsWith("/src/"))o=n.slice(1);else return;if(o===".three-blocks"||o.startsWith(".three-blocks/"))return;let s=F.posix.extname(o).toLowerCase(),i=new Set([o]);if(s.length===0||!Sr.has(s)){for(let a of br)i.add(`${o}${a}`);for(let a of br)i.add(`${o}/index${a}`);}else if([".js",".mjs",".cjs",".jsx"].includes(s)){let a=o.slice(0,-s.length);for(let c of [".ts",".tsx",".mts",".cts"])i.add(`${a}${c}`);}return [...i].find(a=>r.has(a))}a(Na,"resolveProjectImport");function Ha(e,t){let r=vr(t,false);return Pa.test(e)||_a.test(r)||Ma.test(r)}a(Ha,"isShaderRoot");async function Ie(e,t){let r=await realpath(e);if(t!==void 0){let u={},m=0;for(let p of t){let h=await l(r,F.join(r,p),d$1.semanticInput,"Declared shader semantic input");if(m+=h.data.byteLength,m>d$1.semanticTotal)throw new Error("Declared shader semantic inputs exceed the total inspection size limit.");u[p]=f(h.data);}return u}let n=new Map,o=F.join(r,"src");if(await g(o))for(let u of await m(r,o,m=>Sr.has(F.extname(m).toLowerCase()))){let m=await l(r,u,d$1.semanticInput,"Shader semantic input");n.set(Pn(r,u),m.data);}for(let u of await readdir(r,{withFileTypes:true})){if(!u.isFile()||!wr.test(u.name)&&!Sr.has(F.extname(u.name).toLowerCase()))continue;let m=await l(r,F.join(r,u.name),d$1.semanticInput,wr.test(u.name)?"Shader configuration input":"Shader semantic input");n.set(u.name,m.data);}if(n.size>kr)throw new Error(`Shader input discovery exceeds the ${kr}-file limit.`);let s=new Set,i=new Map;for(let[u,m]of n){if(!u.includes("/")&&wr.test(u)&&s.add(u),!u.startsWith("src/"))continue;let p=xr(m,u);i.set(u,p),Ha(u,p)&&s.add(u);}if(s.size===0)throw new Error("No shader registration or scene source root was found.");let a=new Set,c=[...s].sort();for(;c.length>0;){let u=c.shift();if(u===void 0||a.has(u))continue;let m=n.get(u);if(m===void 0)continue;a.add(u);let p=i.get(u)??xr(m,u);for(let h of ja(p)){let y=Na(u,h,n);y!==void 0&&!a.has(y)&&c.push(y);}c.sort();}let l$1=0,f$1={};for(let u of [...a].sort()){let m=n.get(u);if(m===void 0)throw new Error(`Shader input ${JSON.stringify(u)} disappeared during inspection.`);if(l$1+=m.byteLength,l$1>d$1.semanticTotal)throw new Error("Semantic shader inputs exceed the total inspection size limit.");f$1[u]=f(m);}return f$1}a(Ie,"snapshotShaderInputs");function Rr(e){if(typeof e=="string")return e;if(a$1(e))return Rr(e.import)??Rr(e.default)}a(Rr,"conditionalImportTarget");async function $n(e,t){let r=e;for(;;){let n=F.join(r,"node_modules",...t.split("/"),"package.json");if(await g(n)){let s=await j(n,d$1.packageJson,`${t} package.json`),i=JSON.parse(s.data.toString("utf8"));if(!a$1(i)||i.name!==t||typeof i.version!="string"||!Ia.test(i.version))throw new Error(`Installed ${t} package metadata is invalid.`);return {root:F.dirname(s.path),manifest:i}}let o=F.dirname(r);if(o===r)break;r=o;}throw new Error(`Cannot verify the installed ${t} package.`)}a($n,"findInstalledPackage");async function Va(e,t){if(!a$1(t.exports))throw new Error("Installed three-blocks package has no public exports map.");let r=Rr(t.exports[La]);if(r===void 0||!r.startsWith("./"))throw new Error("Installed three-blocks shader export has no import target.");let n=await realpath(e),o=[F.resolve(n,r)],s=new Map,i=0;for(;o.length>0;){let c=o.shift();if(c===void 0)break;let l=await j(c,d$1.semanticInput,"Three Blocks shader runtime module");if(!h(n,l.path)||l.path===n)throw new Error("Three Blocks shader runtime closure escapes its package.");let f$1=Pn(n,l.path);if(s.has(f$1))continue;if(i+=l.data.byteLength,i>d$1.semanticTotal)throw new Error("Three Blocks shader runtime closure exceeds the inspection limit.");s.set(f$1,f(l.data));let u=xr(l.data,f$1);for(let m of Da(u)){let p=_n(m);if(!p.startsWith("./")&&!p.startsWith("../"))continue;let h$1=F.resolve(F.dirname(l.path),p);if(!h(n,h$1))throw new Error("Three Blocks shader runtime import escapes its package.");o.push(h$1);}if(o.sort(),s.size+o.length>kr)throw new Error("Three Blocks shader runtime closure exceeds the file limit.")}let a=[...s].sort((c,l)=>c[0].localeCompare(l[0])).map(([c,l])=>`${c}\0${l}`).join(`
9
+ `);return f(a)}a(Va,"shaderRuntimeClosure");async function Ae(e){let[t,r]=await Promise.all([$n(e,"three"),$n(e,"three-blocks")]);return {three:String(t.manifest.version),threeBlocks:String(r.manifest.version),threeBlocksShaderClosure:await Va(r.root,r.manifest)}}a(Ae,"readInstalledShaderRuntime");function Ua(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}a(Ua,"sameCoverage");function Wa(e){let t=e.some(n=>n.state==="invalid")?"invalid":e.some(n=>n.state==="missing")?"missing":e.some(n=>n.state==="stale")?"stale":"fresh",r=e.filter(n=>n.state===t);return {state:t,reason:t==="fresh"?`${e.length} configured shader scene${e.length===1?" is":"s are"} fresh.`:r.map(n=>`${n.scene} (${n.backend}): ${n.reason}`).join("; ")}}a(Wa,"classifyMatrix");function za(e,t,r){let n=e.tool;if(!n)return "Shader receipt has no public tool compatibility metadata.";if((n.compatibilities?.[r]??n.compatibility)!==t)return "Shader receipt targets a different runtime compatibility contract.";if(n.transform!==B)return "Shader receipt uses a different provider transform version.";if(n.address!==SHADER_ADDRESS_SCHEMA_VERSION||n.recipe!==SHADER_RECIPE_SCHEMA_VERSION||n.hydration!==SHADER_HYDRATION_SCHEMA_VERSION)return "Shader receipt uses incompatible address, recipe, or hydration schemas."}a(za,"exactToolCompatibility");function Ga(e,t){let r=Object.keys(t).filter(s=>Object.hasOwn(e,s)&&e[s]!==t[s]),n=Object.keys(t).filter(s=>!Object.hasOwn(e,s)),o=Object.keys(e).filter(s=>!Object.hasOwn(t,s));return {...r.length>0?{changedInputs:r}:{},...n.length>0?{addedInputs:n}:{},...o.length>0?{removedInputs:o}:{}}}a(Ga,"inputChanges");async function Ue(e=process.cwd(),t$1,r$1){let n=await v(e),o$1=await w(n),s=q(r$1??o$1.backend),i=o$1.scenes.flatMap(l=>r(l,s).map(f=>({scene:l,backend:f,key:t(l.key,f)}))),a$1=F.join(n,o),c=a(()=>({schemaVersion:1,root:n,state:"missing",reason:`${o}/meta.json is absent.`,scenes:i.map(({scene:l,backend:f})=>({scene:l.key,backend:f,state:"missing",reason:"No committed shader receipt."}))}),"missing");if(!await g(a$1)||!await g(F.join(a$1,"meta.json")))return c();try{let l$1=await k(n,a$1,"Shader artifact directory"),f$1=await l(l$1,F.join(l$1,"meta.json"),d$1.receipt,"Shader receipt"),u=c$1(JSON.parse(f$1.data.toString("utf8"))),m=await K(l$1,f$1.data),p=t$1??await Ae(n),h=new Set(o$1.scenes.flatMap(k=>r(k,["webgpu","webgl"]).map(A=>t(k.key,A)))),w=Object.keys(u.scenes).filter(k=>!h.has(k));if(w.length>0)throw new Error(`Shader receipt contains unconfigured scenes: ${w.join(", ")}.`);let b=u.runtime.three!==p.three,x=u.runtime.threeBlocksShaderClosure!==p.threeBlocksShaderClosure,g=u.tool?.version!==A,T=F.join(n,o$1.publicDir??"public"),R=[];for(let{scene:k,backend:A,key:v}of i){let S=u.scenes[v];if(!S){R.push({scene:k.key,backend:A,state:"missing",reason:"Scene/backend is absent from the complete receipt matrix."});continue}let _=z(p.three,A),H=za(u,_,A);if(H)throw new Error(`${v}: ${H}`);let q=await l(l$1,F.join(l$1,S.artifact),d$1.manifest,"Shader manifest");if(f(q.data)!==S.artifactHash)throw new Error(`Shader artifact checksum differs for scene "${k.key}".`);if(S.asset!==void 0&&S.assetHash!==void 0){let re=await l(T,F.join(T,S.asset),d$1.manifest,"Static shader manifest");if(f(re.data)!==S.assetHash)throw new Error(`Static shader manifest checksum differs for scene "${k.key}".`)}if(S.bytes!==void 0&&S.bytes!==q.data.byteLength)throw new Error(`Shader artifact byte count differs for scene "${k.key}".`);let z$1=Lt(q.data.toString("utf8"),q.path,k.key,{three:u.runtime.three,threeBlocks:u.runtime.threeBlocks,compatibility:_,address:SHADER_ADDRESS_SCHEMA_VERSION,recipe:SHADER_RECIPE_SCHEMA_VERSION,hydration:SHADER_HYDRATION_SCHEMA_VERSION});if(!Ua(z$1,S.coverage))throw new Error(`Shader coverage differs for scene "${k.key}".`);if(A==="webgpu"&&!o$1.allowLiveBuilds&&S.skipped&&S.skipped.render+S.skipped.compute>0)throw new Error(`Scene "${k.key}" contains skipped live builds but allowLiveBuilds is false.`);let E=await Ie(n,k.inputs),M=Ga(S.inputs,E),L=(M.changedInputs?.length??0)+(M.addedInputs?.length??0)+(M.removedInputs?.length??0),U=b||x||g||L>0,ee=m?.scenes[v],X=ee===void 0||m===void 0?void 0:{...ee,schemaVersion:m.schemaVersion,measuredAt:m.measuredAt,source:m.source,...m.source==="committed-capture"?{adapter:m.adapter,platform:m.platform}:{}};R.push({scene:k.key,backend:A,state:U?"stale":"fresh",reason:b?"Installed Three.js version differs from the receipt.":x?"Installed three-blocks/shaders runtime closure differs from the receipt.":g?`Receipt was generated by @three-blocks/devtools ${u.tool?.version??"unknown"}.`:L>0?`${L} semantic shader input${L===1?"":"s"} changed.`:"Manifest, runtime, schemas, transform, and semantic inputs match.",coverage:z$1,...!U&&X!==void 0&&X.builds===z$1.render+z$1.compute?{timing:X}:{},...M});}let C=Wa(R),O=C.state==="fresh"&&m!==void 0&&R.every(k=>k.timing!==void 0)?m:void 0;return {schemaVersion:1,root:n,...C,scenes:R,runtime:p,receipt:u,...O===void 0?{}:{timing:O}}}catch(l){let f=l instanceof Error?l.message:String(l);return {schemaVersion:1,root:n,state:"invalid",reason:f,scenes:i.map(({scene:u,backend:m})=>({scene:u.key,backend:m,state:"invalid",reason:f}))}}}a(Ue,"inspectShaderMatrix");var jn=".three-blocks/shaders/pending-capture";function Xa(e){return (e instanceof Error?`${e.name}: ${e.message}`:String(e)).includes("ShaderHydrationError:")}a(Xa,"isShaderHydrationFailure");async function Ja(e,t,r){if(t.length===0)return;let n=F.join(e,o,"meta.json"),o$1=await readFile(n);if(f(o$1)!==f(r))throw new Error("Shader receipt changed before failed scenes could be marked for recapture.");let s=c$1(JSON.parse(o$1.toString("utf8"))),i$1=f(r),a=new Set(t),c=c$1({...s,scenes:Object.fromEntries(Object.entries(s.scenes).map(([l,f])=>[l,a.has(l)?{...f,inputs:{...f.inputs,[jn]:i$1}}:f]))});await i(n,`${H(c)}
10
+ `);}a(Ja,"markShaderScenesForRecapture");function Za(e,t){return H(e)===H(t)}a(Za,"equalSnapshot");async function Br(e={}){let t$1=e.root?await realpath(e.root):await v(e.start),r$1=e.config===void 0?await y(t$1):void 0,n=e.config??r$1?.config??await w(t$1),o=e.runtime??await Ae(t$1),s$1=q(e.backend??n.backend),i=q(n.backend),a$1=[...new Set([...i,...s$1])],c=[...s$1].reverse(),l=[...s(n.scenes,c)],f$1,u={},m;if(e.ifStale){let E=await Ue(t$1,o,e.backend??n.backend);if(E.state==="fresh"&&E.scenes.every(M=>M.timing!==void 0))return {schemaVersion:1,root:t$1,skipped:true,reason:E.reason,scenes:[]};if(E.state!=="invalid"&&E.receipt!==void 0){let M=E.state==="fresh";l=l.filter(({scene:L,backend:U})=>{let ee=E.scenes.find(X=>X.scene===L.key&&X.backend===U);return ee?.state!=="fresh"||M&&ee.timing===void 0}),f$1=E.receipt;for(let L of E.scenes){if(L.state!=="fresh"||L.timing===void 0)continue;let{builds:U,liveBuildMs:ee,precompiledBuildMs:X,avoidedBuildMs:re,runs:se,spreadMs:Xe}=L.timing;u[t(L.scene,L.backend)]={builds:U,liveBuildMs:ee,precompiledBuildMs:X,avoidedBuildMs:re,runs:se,spreadMs:Xe},L.timing.source==="committed-capture"&&L.timing.adapter!==void 0&&L.timing.platform!==void 0&&(m={adapter:L.timing.adapter,platform:L.timing.platform});}}}let p=performance.now(),h=f$1!==void 0&&(f$1.runtime.three!==o.three||f$1.runtime.threeBlocksShaderClosure!==o.threeBlocksShaderClosure||f$1.tool?.version!==A)?f(H({runtime:f$1.runtime,tool:f$1.tool})):void 0,y$1=a(async()=>new Map(await Promise.all(n.scenes.map(async E=>[E.key,await Ie(t$1,E.inputs)]))),"snapshotInputs"),w$1=await y$1(),b=a(async()=>{let E=await y$1();for(let M of n.scenes){let L=w$1.get(M.key),U=E.get(M.key);if(L===void 0||U===void 0||!Za(L,U))throw new Error(`Semantic shader inputs changed during capture for scene "${M.key}"; the current scene was not committed.`)}},"assertInputsUnchanged"),x$1=e.driver===void 0,g=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await x(t$1):void 0,T=e.serve??g?.serve,R$1=e.driverKind??g?.driverKind??(T===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(R$1==="vite"&&T!==void 0)throw new Error("--serve requires the static shader driver.");if(R$1==="static"&&T===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let C=e.driver===void 0?await import('./shader-browser-523TEBVA.js'):void 0,O=a(()=>e.url!==void 0?C.createAttachedPlaywrightShaderDriver({root:t$1,runtime:o,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):R$1==="static"?C.createStaticPlaywrightShaderDriver({root:t$1,runtime:o,serve:T,...e.headed!==void 0?{headed:e.headed}:{}}):C.createPlaywrightShaderDriver({root:t$1,runtime:o,...e.headed!==void 0?{headed:e.headed}:{}}),"createDriver"),k=new Map,A$1=a(E=>{if(e.driver!==void 0)return e.driver;let M=k.get(E);return M===void 0&&(M=O(),k.set(E,M)),M},"driverFor"),v$1=new Map,S=[],_=f$1!==void 0&&n.scenes.every(E=>r(E,a$1).every(M=>f$1?.scenes[t(E.key,M)]!==void 0)),H$1=f$1,q$1,z=e.attempts??2;if(!Number.isSafeInteger(z)||z<1||z>5)throw new Error("Shader capture attempts must be an integer in 1...5.");try{for(let[U,ee]of l.entries()){let{scene:X,backend:re,key:se}=ee,Xe=A$1(re);e.onSceneStart?.(se,U,l.length);let oe,Pe,ve=0;for(;ve<z;ve++)try{oe=G(await Xe.capture(X,n,re),{scene:X.key,backend:re,runtime:o});let Se=re==="webgl"&&oe.skipped.every(pe=>pe.reason.startsWith("WebGL shader precompilation does not support "));if(oe.skipped.length>0&&!n.allowLiveBuilds&&!Se)throw new Error(`Scene "${X.key}" contains ${oe.skipped.length} unregistered live shader build${oe.skipped.length===1?"":"s"} while allowLiveBuilds is false.`);break}catch(Se){Pe=Se,oe=void 0,ve+1<z&&e.onSceneRetry?.(X.key,ve+2,z,n.timeoutMs,Se);}if(!oe)throw new Error(`Shader capture "${X.key}" failed after ${z} attempts: ${Pe instanceof Error?Pe.message:String(Pe)}`);if(v$1.set(se,oe),S.push({scene:X.key,backend:re,attempts:ve+1,coverage:oe.coverage,skipped:oe.skipped.length,startupBuilds:oe.stats.registeredBuilds,startupBuildMs:oe.stats.buildMs,...oe.timing===void 0?{}:{timing:oe.timing}}),_&&H$1!==void 0){await b();let Se=new Map(n.scenes.map(pe=>{let lt=r(pe,a$1),_e=pe.key===X.key?w$1.get(pe.key):lt.map(ye=>H$1?.scenes[t(pe.key,ye)]?.inputs).find(ye=>ye!==void 0);if(_e===void 0)throw new Error(`Shader checkpoint is missing scene "${pe.key}".`);return h!==void 0&&!lt.every(ye=>v$1.has(t(pe.key,ye)))&&(_e={..._e,[jn]:h}),[pe.key,_e]}));q$1=await R({root:t$1,scenes:n.scenes,backends:a$1,captures:new Map([[se,oe]]),runtime:o,inputs:Se,previousReceipt:H$1,publicDirectory:n.publicDir??"public"}),H$1=q$1.receipt;}}await b(),q$1=await R({root:t$1,scenes:n.scenes,backends:a$1,captures:v$1,runtime:o,inputs:w$1,...f$1===void 0?{}:{previousReceipt:f$1},publicDirectory:n.publicDir??"public"});let E={...u};for(let U of S)E[t(U.scene,U.backend)]={builds:U.coverage.render+U.coverage.compute,setupMeasured:!1,liveBuildMs:U.startupBuildMs,precompiledBuildMs:0,avoidedBuildMs:U.startupBuildMs,runs:1,spreadMs:0};if(e.commitTiming===!0){let U=m??{adapter:v$1.values().next().value?.provenance?.adapter??"WebGPU adapter",platform:`${zt.platform()}/${zt.arch()}`},ee=k.values().next().value??e.driver;await Q(t$1,E,await(ee?.timingEnvironment?.()??U));}else await N$1(t$1,E);let M=await readFile(F.join(q$1.directory,"meta.json")),L=await K(q$1.directory,M);return {schemaVersion:1,root:t$1,skipped:!1,reason:`Wrote ${S.length} shader scene${S.length===1?"":"s"}.`,durationMs:performance.now()-p,scenes:S,measurement:{beforeBuilds:S.reduce((U,ee)=>U+ee.startupBuilds,0),afterBuilds:0,firstFrameDeltaMs:-S.reduce((U,ee)=>U+ee.startupBuildMs,0),source:"capture-build-phase"},...r$1===void 0?{}:{configuration:{created:r$1.created,file:r$1.file}},written:q$1,...L===void 0?{}:{timing:L}}}finally{x$1&&await Promise.all([...k.values()].map(E=>E.close()));}}a(Br,"captureShaders");function Ya(e){return ["workerReady","assetsReady",...e.requiresText?["textReady"]:[],"compileEnd","firstFrame"]}a(Ya,"requiredReadiness");function In(e){if(e.length===0)throw new Error("Cannot take the median of an empty shader timing capture.");let t=[...e].sort((s,i)=>s-i),r=Math.floor(t.length/2),n=t[r];if(n===void 0)throw new Error("Shader timing median is unavailable.");if(t.length%2===1)return n;let o=t[r-1];if(o===void 0)throw new Error("Shader timing median pair is unavailable.");return (o+n)/2}a(In,"median");function Er(e,t,r,n){if(e.scene!==t.key||e.mode!==r)throw new Error(`Browser observation identity differs for scene "${t.key}".`);if(e.compatibility!==n||e.transform!==B)throw new Error(`Browser observation compatibility differs for scene "${t.key}".`);let o=Ya(t).filter(s=>e.readiness[s]!==true);if(o.length>0)throw new Error(`Scene "${t.key}" ${r} observation is missing readiness bits: ${o.join(", ")}.`);if(e.errors.length>0)throw new Error(`Scene "${t.key}" ${r} browser errors:
11
11
  - ${e.errors.join(`
12
12
  - `)}
13
- ${r} demands: ${Br(e.demands)}`)}a(Tr,"assertObservation");async function Za(e,t,r){if(r===void 0)return new Set;try{let n=JSON.parse(await readFile(F.join(e,t.publicDir??"public",r),"utf8"));return new Set(Object.keys(n.fallbacks??{}))}catch{return new Set}}a(Za,"manifestFallbackKeys");function Ya(e,t,r,n,o,s){if(t.render>0&&r.stats.registeredRenderBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered render pipeline.`);if(t.compute>0&&r.stats.registeredComputeBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered compute kernel.`);Dn(e,t,n,o,s,r.demands);}a(Ya,"assertZeroBuild");function Br(e){return !e||e.length===0?"none recorded":e.map(t=>`${String(t.key??"unregistered")}[${String(t.event)}${t.hit===false?":miss":""}|${String(t.target)}${t.object===void 0?"":`@${String(t.object)}`}]`).join(" ").slice(0,4e3)}a(Br,"describeDemands");function Dn(e,t,r,n,o,s){let i=a(()=>`
14
- Precompiled demands: ${Br(r.demands)}`+(s===void 0?"":`
15
- Live demands: ${Br(s)}`),"demandEvidence");if(r.stats.registeredRenderBuilds+r.stats.registeredComputeBuilds>n){let a=r.stats.missedKeys??[];throw new Error(`Scene "${e.key}" injected path performed ${r.stats.registeredRenderBuilds} render and ${r.stats.registeredComputeBuilds} compute registered live builds; capture permits ${n}.`+(a.length>0?` Missed keys: ${a.join(", ")}.`:"")+i())}if(r.stats.buildCalls>n)throw new Error(`Scene "${e.key}" injected path performed ${r.stats.buildCalls} total live NodeBuilder build${r.stats.buildCalls===1?"":"s"}; capture permits ${n} skipped live build${n===1?"":"s"}.`);if(t.render>0&&r.stats.injectedRender===0)throw new Error(`Scene "${e.key}" injected no render entries.`);if(t.compute>0&&r.stats.injectedCompute===0)throw new Error(`Scene "${e.key}" injected no compute entries.`);if(r.stats.missed!==0||r.stats.missedRender!==0||r.stats.missedCompute!==0){let a=r.stats.missedKeys??[],c=a.filter(f=>!o.has(f)),u=a.length>0&&r.stats.missed<=o.size;if(c.length>0||!u)throw new Error(`Scene "${e.key}" injected path reported shader manifest misses.`+(a.length>0?` Missed keys: ${a.join(", ")}.`:"")+(c.length>0&&c.length!==a.length?` Unexpected: ${c.join(", ")}.`:"")+i())}}a(Dn,"assertPrecompiledZeroBuild");async function Qa(e,t,r,n,o){let s=F.join(e,p);if(await g(s)){let a=await lstat(s);if(a.isSymbolicLink()||!a.isDirectory())throw new Error("Shader parity artifact directory is not a real directory.")}else await mkdir(s,{recursive:true});let i=[`${t}.live.png`,`${t}.precompiled.png`,`${t}.diff.png`];return await Promise.all([r,n,o].map(async(a,c)=>{let u=i[c];if(u===void 0)throw new Error("Parity artifact mapping failed.");let f=F.join(s,u);if(await g(f)){let l=await lstat(f);if(l.isSymbolicLink()||!l.isFile())throw new Error(`Shader parity target is not a regular file: ${u}.`)}await writeFile(f,a,{mode:384});})),i.map(a=>`${p}/${a}`)}a(Qa,"writeParityFailure");async function ei(e={}){let t=e.root?await realpath(e.root):await v(e.start),r=e.runtime??await Pe(t),n=e.config??await w(t),o$1=q(e.backend??n.backend),s$1=s(n.scenes,[...o$1].reverse()),i=await Ue(t,r,e.backend??n.backend);if(i.state!=="fresh")throw new Error(`Shader no-GPU validation is ${i.state}: ${i.reason}`);if(e.skipBrowser)return {schemaVersion:1,root:t,noGpu:i,browser:"skipped",scenes:[]};if(e.parityOnly===true&&e.commitTiming===true)throw new Error("Parity-only shader verification cannot commit timing.");let a$1=e.runs??5;if(!Number.isSafeInteger(a$1)||a$1<1||a$1>100)throw new Error("Shader timing runs must be an integer in 1...100.");let c=await readFile(F.join(t,o,"meta.json")),u=c$1(JSON.parse(c.toString("utf8")));if(i.receipt===void 0||H(u)!==H(i.receipt))throw new Error("Shader receipt changed after no-GPU validation; restart browser parity verification.");let f=e.driver===void 0,l=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await x(t):void 0,m=e.serve??l?.serve,p=e.driverKind??l?.driverKind??(m===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(p==="vite"&&m!==void 0)throw new Error("--serve requires the static shader driver.");if(p==="static"&&m===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let h=e.driver===void 0?await import('./shader-browser-523TEBVA.js'):void 0,{compareShaderScreenshots:y}=await import('./shader-parity-QXJWR6OZ.js'),w$1=a(()=>e.url!==void 0?h.createAttachedPlaywrightShaderDriver({root:t,runtime:r,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):p==="static"?h.createStaticPlaywrightShaderDriver({root:t,runtime:r,serve:m,...e.headed!==void 0?{headed:e.headed}:{}}):h.createPlaywrightShaderDriver({root:t,runtime:r,...e.headed!==void 0?{headed:e.headed}:{}}),"createDriver"),b=new Map,k=new Map,g=a((S,B)=>{if(e.driver!==void 0)return e.driver;let T=S.get(B);return T===void 0&&(T=w$1(),S.set(B,T)),T},"driverFor");await P(t,s$1.map(S=>S.key),c);let P$1=[],R={},_=[],C=new Set;try{for(let[B,T]of s$1.entries()){let{scene:x,backend:O$1,key:V}=T;e.onSceneStart?.(V,B,s$1.length);let q=i.scenes.find(te=>te.scene===x.key&&te.backend===O$1);if(!q?.coverage)throw new Error(`Fresh receipt has no coverage for "${V}".`);let z$1=q.coverage;if(z$1.render+z$1.compute===0)continue;let v=z(r.three,O$1),M=i.receipt?.scenes[V]?.skipped,L=(M?.render??0)+(M?.compute??0),U=await Za(t,n,i.receipt?.scenes[V]?.asset),ee=a(async te=>{let H=g(b,O$1),G=g(k,O$1),K=te?"live":"precompiled",ne=te?"precompiled":"live",de=te?H:G,Je=te?G:H,ce=await de.observe(x,K,n,void 0,O$1),j=await Je.observe(x,ne,n,ce.frame,O$1),le=ce.mode==="live"?ce:j,Me=ce.mode==="precompiled"?ce:j;Tr(le,x,"live",v),Tr(Me,x,"precompiled",v),Ya(x,z$1,le,Me,L,U);let Gr=a(async(Vo,Kr,qr)=>{let Ee=y(Kr,qr,n.parity.channelTolerance,x.maxDiffRatio??n.parity.maxDiffRatio);if(Ee.matches)return Ee;let Ho=await Qa(t,V,Kr,qr,Ee.diff),Uo=Ee.nonBlack?`${Ee.differentPixels}/${Ee.totalPixels} pixels differ (${(Ee.diffRatio*100).toFixed(3)}%).`:`rendered output is black (live=${Ee.baselineLuminance.toFixed(4)}, precompiled=${Ee.precompiledLuminance.toFixed(4)}).`;throw new Error(`Shader ${Vo} parity failed for scene "${x.key}" at completed frames live=${le.frame}, precompiled=${Me.frame}: ${Uo} Artifacts: ${Ho.join(", ")}`)},"compare");await Gr("first frame",le.firstFrameScreenshot,Me.firstFrameScreenshot);let No=await Gr("settled",le.screenshot,Me.screenshot);return {live:le,precompiled:Me,parity:No}},"observePair"),X,re,se;if(e.parityOnly===!0)try{X=await ee(!0);}catch(te){Ka(te)&&C.add(V),_.push({scene:V,error:te}),e.onSceneError?.(V,te);continue}else {await ee(!0);let te=[];for(let j=0;j<a$1;j++)te.push(await ee(j%2===0));let H=te[te.length-1];if(H===void 0)throw new Error(`Shader timing produced no runs for scene "${x.key}".`);if(X=H,re=await g(k,O$1).observePublished(x,n,O$1),Tr(re,x,"precompiled",v),Dn(x,z$1,re,L,U),se=x.runtimeMotion?y(re.beforeScreenshot,re.screenshot,n.parity.channelTolerance,1):void 0,se&&se.diffRatio<1e-4)throw new Error(`Published scene "${x.key}" stopped animating during its normal 120-frame soak (changed ${se.differentPixels}/${se.totalPixels} canvas pixels).`);let K=a(j=>j.stats.buildMs+(j.stats.precompiledSetupMs??0)+(j.stats.hydrationMs??0),"observedNodeBuilderMs"),ne=In(te.map(j=>K(j.live))),de=In(te.map(j=>K(j.precompiled))),Je=Math.max(0,ne-de),ce=te.map(j=>Math.max(0,K(j.live)-K(j.precompiled)));R[V]={builds:z$1.render+z$1.compute,setupMeasured:!0,liveBuildMs:ne,precompiledBuildMs:de,avoidedBuildMs:Je,runs:a$1,spreadMs:Math.max(...ce.map(j=>Math.abs(j-Je)))};}let{diff:Xe,...oe}=X.parity,{firstFrameScreenshot:Ae,screenshot:ve,...Se}=X.live,{firstFrameScreenshot:pe,screenshot:ut,..._e}=X.precompiled,ye;if(re!==void 0){let{beforeScreenshot:te,firstFrameScreenshot:H,screenshot:G,...K}=re;ye=K;}P$1.push({scene:x.key,backend:O$1,coverage:z$1,live:Se,precompiled:_e,...ye===void 0?{}:{published:ye},parity:oe,...se===void 0?{}:{runtimeMotion:{differentPixels:se.differentPixels,totalPixels:se.totalPixels,diffRatio:se.diffRatio}}}),await O(t,[V],c);}if(e.parityOnly===!0){if(await qa(t,[...C],c),_.length>0)throw new Error(`Shader parity failed for ${_.length}/${s$1.length} scene/backend pair(s):
16
- `+_.map(B=>{let T=B.error instanceof Error?B.error.message:String(B.error);return ` - ${B.scene}: ${T}`}).join(`
17
- `));return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:P$1}}if(Object.keys(R).length===0)return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:P$1};if(e.commitTiming===!0){let B={adapter:o$1.length===1&&o$1[0]==="webgl"?"WebGL adapter":"WebGPU adapter",platform:`${Gt.platform()}/${Gt.arch()}`},x=await((b.values().next().value??e.driver)?.timingEnvironment?.()??B),O=await Q(t,R,x);return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:P$1,timing:O.local,committedTiming:O.committed}}let S=await N$1(t,R);return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:P$1,timing:S}}finally{f&&await Promise.all([...b.values(),...k.values()].map(S=>S.close()));}}a(ei,"testShaders");function ti(e=process.env,t=process.stdout){if(e.NO_COLOR!==void 0)return 0;if(e.FORCE_COLOR!==void 0){let r=String(e.FORCE_COLOR);return r==="0"||r==="false"?0:r==="3"?24:r==="2"?8:4}return !t||!t.isTTY||e.TERM==="dumb"?0:/^(truecolor|24bit)$/i.test(e.COLORTERM??"")||e.WT_SESSION||e.TERM_PROGRAM==="iTerm.app"||e.TERM_PROGRAM==="vscode"?24:/-256(color)?$/i.test(e.TERM??"")?8:4}a(ti,"resolveColorDepth");function ri(e=process.env,t=process.platform){return t!=="win32"?true:!!(e.WT_SESSION||e.TERM_PROGRAM||e.ConEmuANSI||/-256(color)?$/i.test(e.TERM??""))}a(ri,"resolveUnicode");function ni(e=process.stdout){let t=e?.columns;return typeof t=="number"&&Number.isInteger(t)&&t>0?t:80}a(ni,"termWidth");var Nn={depth:ti(),unicode:ri()},st={logo:{square:[30,84,200]},accent:[86,132,230],gold:[244,174,12],danger:[221,76,51],live:[212,255,71]};function oi(e,t,r){if(Math.max(e,t,r)-Math.min(e,t,r)<12){let o=Math.round((e+t+r)/3);return o<8?16:o>238?231:232+Math.round((o-8)/10)}let n=a(o=>o<48?0:o<115?1:Math.min(5,Math.round((o-35)/40)),"level");return 16+36*n(e)+6*n(t)+n(r)}a(oi,"ansi256");function at(e,t,r){return r>=24?`38;2;${e[0]};${e[1]};${e[2]}`:r>=8?`38;5;${oi(e[0],e[1],e[2])}`:String(t)}a(at,"fgOpen");function si(e=Nn.depth,t=Nn.unicode){let r=e>0?(n,o=39)=>s=>`\x1B[${n}m${String(s)}\x1B[${o}m`:()=>n=>String(n);return {depth:e,unicode:t,accent:r(at(st.accent,94,e)),live:r(at(st.live,92,e)),danger:r(at(st.danger,91,e)),gold:r(at(st.gold,33,e)),deep:r(at(st.logo.square,34,e)),warn:r(at(st.gold,33,e)),dim:r(2,22),bold:r(1,22)}}a(si,"createTheme");function ai(e){let t=e.unicode;return {tick:e.live(t?"\u2713":"\u221A"),cross:e.danger(t?"\u2717":"x"),warn:e.warn(t?"\u25B2":"!"),info:e.accent(t?"\u203A":">"),pointer:e.accent(t?"\u276F":">"),dot:e.dim(t?"\xB7":"."),ring:e.dim(t?"\u25CB":"o"),bar:t?"\u2502":"|",ellipsis:t?"\u2026":"...",mark:t?`${e.gold("\u25B2")} ${e.danger("\u25CF")} ${e.deep("\u25A0")}`:null}}a(ai,"createSymbols");var I=si(),N=ai(I),ii=/\x1b\[[0-9;]*m/g;function di(e){return String(e).replace(ii,"")}a(di,"stripAnsi");function ci(e){return e===8203||e===8205||e>=768&&e<=879||e>=65024&&e<=65039?0:e>=4352&&e<=4447||e>=11904&&e<=42191||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65072&&e<=65103||e>=65280&&e<=65376||e>=65504&&e<=65510||e>=127744&&e<=129791||e>=131072&&e<=262141?2:1}a(ci,"charWidth");function li(e){let t=0;for(let r of di(e))t+=ci(r.codePointAt(0)??0);return t}a(li,"visibleWidth");function Pr(e,t){let r=t-li(String(e));return r>0?String(e)+" ".repeat(r):String(e)}a(Pr,"padEndAnsi");function We(e){return ["fresh","ready","precompiled","passed","captured","verified","first frame","compiled","worker ready","assets ready"].includes(e)?N.tick:["stale","live","generating","fallback","updating","skipped"].includes(e)?N.warn:["missing","starting","not-observed","unobserved"].includes(e)?N.ring:N.cross}a(We,"stateMark");var Xt=".three-blocks/runtime/status.json",Tt=256*1024,qt="three-blocks browser smoke",ui=["three-blocks.json","three-blocks.shaders.json","three-blocks.text.ts"];function Gn(e){return "kind"in e&&e.kind==="adopted"}a(Gn,"isAdoptedProjectStatus");async function Jt(e,t,r,n){let o=await l(e,t,r,n);return JSON.parse(o.data.toString("utf8"))}a(Jt,"readJsonWithin");var mi=["starting","worker ready","assets ready","compiled","first frame","updating","error"],fi=["ready","generating","fallback","missing","invalid"],pi=["WebGPU","WebGL"],hi=["OffscreenCanvas","MainThread"],yi=/^[0-9A-Za-z][0-9A-Za-z._-]{0,63}$/,Hn=16,Un=1e9;function we(e,t,r,n=[]){if(!a$1(e))throw new Error(`${t} must be an object.`);let o=new Set([...r,...n]);for(let s of r)if(!Object.hasOwn(e,s))throw new Error(`${t}.${s} is required.`);for(let s of Object.keys(e))if(!o.has(s))throw new Error(`${t}.${s} is not supported by schema v1.`);return e}a(we,"exactRecord");function Et(e,t,r){if(typeof e!="string"||!t.includes(e))throw new Error(`${r} has an unsupported value.`);return e}a(Et,"enumValue");function ue(e,t){if(typeof e!="boolean")throw new Error(`${t} must be a boolean.`);return e}a(ue,"booleanValue");function Wn(e,t){return e===null?null:ue(e,t)}a(Wn,"nullableBoolean");function ze(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>Un)throw new Error(`${t} must be a non-negative integer no greater than ${Un}.`);return e}a(ze,"boundedCounter");function gi(e){if(typeof e!="string"||e.length>32)throw new Error("Runtime status receipt observedAt must be a bounded ISO timestamp.");let t=Date.parse(e);if(!Number.isFinite(t)||new Date(t).toISOString()!==e)throw new Error("Runtime status receipt observedAt must be an exact ISO timestamp.");return e}a(gi,"observedTimestamp");function wi(e){if(e===null)return null;if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error("Runtime status receipt error must be null or one bounded display-safe line.");return e}a(wi,"receiptError");function bi(e){if(!Array.isArray(e)||e.length>Hn)throw new Error(`Runtime status receipt assets.codecs must contain at most ${Hn} entries.`);let t=e.map((r,n)=>{let o=we(r,`Runtime status receipt assets.codecs[${n}]`,["name","available","decoded"]);if(typeof o.name!="string"||!yi.test(o.name))throw new Error(`Runtime status receipt assets.codecs[${n}].name is invalid.`);let s=ue(o.available,`Runtime status receipt assets.codecs[${n}].available`),i=ue(o.decoded,`Runtime status receipt assets.codecs[${n}].decoded`);if(i&&!s)throw new Error(`Runtime status receipt codec ${JSON.stringify(o.name)} cannot be decoded when unavailable.`);return {name:o.name,available:s,decoded:i}});if(new Set(t.map(r=>r.name)).size!==t.length)throw new Error("Runtime status receipt assets.codecs must have unique names.");return t}a(bi,"parseRuntimeCodecs");function Si(e){if(e.assetsReady&&!e.workerReady)throw new Error("Runtime lifecycle assetsReady requires workerReady.");if(e.compiled&&!e.assetsReady)throw new Error("Runtime lifecycle compiled requires assetsReady.");if(e.firstFrame&&!e.compiled)throw new Error("Runtime lifecycle firstFrame requires compiled.");let t=e.state==="starting"?[false,false,false,false]:e.state==="worker ready"?[true,false,false,false]:e.state==="assets ready"?[true,true,false,false]:e.state==="compiled"?[true,true,true,false]:e.state==="first frame"||e.state==="updating"?[true,true,true,true]:null;if(t!==null&&![e.workerReady,e.assetsReady,e.compiled,e.firstFrame].every((r,n)=>r===t[n]))throw new Error(`Runtime lifecycle flags do not match state ${JSON.stringify(e.state)}.`)}a(Si,"validateLifecycle");function Kn(e){let t=we(e,"Runtime status receipt",["schemaVersion","observedAt","worker","assets","hmr","stats","lifecycle","shaders","error"],["text"]);if(t.schemaVersion!==1)throw new Error("Runtime status receipt must use schemaVersion 1.");let r=we(t.worker,"Runtime status receipt worker",["backend","renderer","protocolVersion"]);if(r.protocolVersion!==1)throw new Error("Runtime status receipt worker.protocolVersion must be 1.");let n=we(t.assets,"Runtime status receipt assets",["codecs","resources"]),o=we(t.hmr,"Runtime status receipt hmr",["capabilities","outcome"]),s=we(o.capabilities,"Runtime status receipt hmr.capabilities",["scene","component","assetManifest","workerRestart"]),i=we(o.outcome,"Runtime status receipt hmr.outcome",["attempted","succeeded","rollbackPreserved","workerRestarted"]),a=ue(i.attempted,"Runtime status receipt hmr.outcome.attempted"),c=Wn(i.succeeded,"Runtime status receipt hmr.outcome.succeeded"),u=Wn(i.rollbackPreserved,"Runtime status receipt hmr.outcome.rollbackPreserved"),f=ue(i.workerRestarted,"Runtime status receipt hmr.outcome.workerRestarted");if(a?c===null||u===null:c!==null||u!==null||f)throw new Error("Runtime status receipt HMR outcome fields are inconsistent with attempted.");let l={scene:ue(s.scene,"Runtime status receipt hmr.capabilities.scene"),component:ue(s.component,"Runtime status receipt hmr.capabilities.component"),assetManifest:ue(s.assetManifest,"Runtime status receipt hmr.capabilities.assetManifest"),workerRestart:ue(s.workerRestart,"Runtime status receipt hmr.capabilities.workerRestart")};if(a&&!l.scene)throw new Error("Runtime status receipt cannot attempt HMR without the scene capability.");if(f&&!l.workerRestart)throw new Error("Runtime status receipt cannot restart a worker without the workerRestart capability.");let m=we(t.stats,"Runtime status receipt stats",["snapshots","textures","workerProfiler","mainPanels"]),p=we(t.lifecycle,"Runtime status receipt lifecycle",["state","workerReady","assetsReady","compiled","firstFrame"]),h={state:Et(p.state,mi,"Runtime status receipt lifecycle.state"),workerReady:ue(p.workerReady,"Runtime status receipt lifecycle.workerReady"),assetsReady:ue(p.assetsReady,"Runtime status receipt lifecycle.assetsReady"),compiled:ue(p.compiled,"Runtime status receipt lifecycle.compiled"),firstFrame:ue(p.firstFrame,"Runtime status receipt lifecycle.firstFrame")};Si(h);let y=we(t.shaders,"Runtime status receipt shaders",["mode","pipelines"]),w=Et(y.mode,["precompiled","live"],"Runtime status receipt shaders.mode"),b=ze(y.pipelines,"Runtime status receipt shaders.pipelines");if(w==="precompiled"&&b===0)throw new Error("A precompiled runtime receipt must observe at least one shader pipeline.");let k;if(t.text!==void 0){let P=we(t.text,"Runtime status receipt text",["state","atlases","glyphs","requiredGlyphs"]);if(k={state:Et(P.state,fi,"Runtime status receipt text.state"),atlases:ze(P.atlases,"Runtime status receipt text.atlases"),glyphs:ze(P.glyphs,"Runtime status receipt text.glyphs"),requiredGlyphs:ze(P.requiredGlyphs,"Runtime status receipt text.requiredGlyphs")},k.state==="ready"&&(k.atlases===0||k.requiredGlyphs===0||k.glyphs<k.requiredGlyphs))throw new Error("A ready text receipt must cover a non-empty required glyph set with at least one atlas.")}let g=wi(t.error);if(h.state==="error"?g===null:g!==null)throw new Error("Runtime status receipt error must be present only when lifecycle.state is error.");return {schemaVersion:1,observedAt:gi(t.observedAt),worker:{backend:Et(r.backend,hi,"Runtime status receipt worker.backend"),renderer:Et(r.renderer,pi,"Runtime status receipt worker.renderer"),protocolVersion:1},assets:{codecs:bi(n.codecs),resources:ze(n.resources,"Runtime status receipt assets.resources")},hmr:{capabilities:l,outcome:{attempted:a,succeeded:c,rollbackPreserved:u,workerRestarted:f}},stats:{snapshots:ze(m.snapshots,"Runtime status receipt stats.snapshots"),textures:ze(m.textures,"Runtime status receipt stats.textures"),workerProfiler:ue(m.workerProfiler,"Runtime status receipt stats.workerProfiler"),mainPanels:ue(m.mainPanels,"Runtime status receipt stats.mainPanels")},lifecycle:h,shaders:{mode:w,pipelines:b},...k===void 0?{}:{text:k},error:g}}a(Kn,"parseRuntimeStatusReceipt");function ki(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}a(ki,"sameCoverage");async function Ar(e=process.cwd()){let t=F.resolve(e);for(;;){if((await Promise.all(ui.map(n=>g(F.join(t,n))))).some(Boolean))return realpath(t);let r=F.dirname(t);if(r===t)return realpath(F.resolve(e));t=r;}}a(Ar,"findProjectRoot");async function xi(e,t){let r=t.template,n=F.join(e,".three-blocks","shaders"),o=F.join(n,"meta.json");if(!await g(n)||!await g(o))return {state:"missing",scene:r,reason:t.artifacts?.shaders==="pending"?"The selected template has no verified shader capture yet.":".three-blocks/shaders/meta.json is absent."};try{let s=await k(e,n,"Shader artifact directory"),i=c$1(await Jt(s,o,d$1.receipt,"Shader receipt")),a=i.scenes[r];if(a===void 0)return {state:"invalid",scene:r,reason:`Shader receipt has no "${r}" scene.`};let c=await l(s,F.join(s,a.artifact),d$1.manifest,"Shader manifest");if(f(c.data)!==a.artifactHash)return {state:"invalid",scene:r,reason:"The selected shader manifest checksum does not match its receipt."};let u=jt(c.data.toString("utf8"),c.path,r);if(!ki(u,a.coverage))return {state:"invalid",scene:r,reason:"Shader receipt coverage does not match the manifest entries.",coverage:u};let{three:f$1,threeBlocks:l$1,threeBlocksShaderClosure:m}=await Pe(e);if(i.runtime.three!==f$1||t.runtime.three!==f$1||t.runtime.threeBlocks!==l$1)return {state:"stale",scene:r,reason:`Installed runtime versions (${f$1}, ${l$1}) do not match the metadata and shader receipt.`,coverage:u};if(i.runtime.threeBlocksShaderClosure!==m)return {state:"stale",scene:r,reason:"The installed three-blocks/shaders runtime closure differs from the capture receipt.",coverage:u};let p=await Ie(e),h=Object.keys(p),y=Object.keys(a.inputs),w=h.filter(g=>!Object.hasOwn(a.inputs,g)),b=y.filter(g=>!Object.hasOwn(p,g)),k$1=h.filter(g=>Object.hasOwn(a.inputs,g)&&a.inputs[g]!==p[g]);return w.length>0||b.length>0||k$1.length>0?{state:"stale",scene:r,reason:`${w.length} added, ${b.length} removed, and ${k$1.length} changed semantic shader inputs.`,coverage:u,...k$1.length>0?{changedInputs:k$1}:{},...w.length>0?{addedInputs:w}:{},...b.length>0?{removedInputs:b}:{}}:{state:"fresh",scene:r,reason:"Manifest, installed shader runtime closure, and the shader-relevant source snapshot match.",coverage:u}}catch(s){return {state:"invalid",scene:r,reason:s instanceof Error?s.message:String(s)}}}a(xi,"inspectShaders");async function Ri(e,t){if(t.artifacts?.text==="pending")return {state:"missing",reason:"The template has no verified text artifacts yet.",atlases:[]};let r=await zt(e);return {state:r.state,reason:r.reason,atlases:r.atlases.map(n=>({name:n.font.key,glyphs:n.codePoints.length,width:n.texture.width,height:n.texture.height}))}}a(Ri,"inspectText");function vi(e,t){if(e.lifecycle.assetsReady&&e.assets.codecs.some(r=>!r.available))throw new Error("Runtime status receipt claims assets ready while a configured codec is unavailable.");if(t.features.text!==(e.text!==void 0))throw new Error("Runtime status receipt text observation does not match three-blocks.json.")}a(vi,"validateRuntimeReceiptForProject");async function Ei(e,t){let r=F.join(e,...Xt.split("/"));if(!await g(r))return {kind:"absent",receipt:null,reason:"No browser observation receipt is available."};try{let n=await k(e,F.dirname(r),"Runtime status receipt directory"),o=Kn(await Jt(n,F.join(n,F.basename(r)),Tt,"Runtime status receipt"));return vi(o,t),{kind:"valid",receipt:o,reason:o.error??`Browser observation captured at ${o.observedAt}.`}}catch(n){return {kind:"invalid",receipt:null,reason:`Runtime status receipt is invalid: ${n instanceof Error?n.message:String(n)}`}}}a(Ei,"inspectRuntimeReceipt");function Ti(){return {scene:false,component:false,assetManifest:false,workerRestart:false}}a(Ti,"emptyCapabilities");function Bi(){return {attempted:false,succeeded:null,rollbackPreserved:null,workerRestarted:false}}a(Bi,"emptyOutcome");function $i(){return []}a($i,"configuredCodecs");function Pi(e,t,r){if(t.state!=="fresh")return "three-blocks shaders capture";if(r!==void 0&&r.state!=="ready")return "three-blocks text generate";let n=e.receipt;return e.kind!=="valid"||n===null||n.lifecycle.state==="error"?qt:n.text!==void 0&&n.text.state!=="ready"?"three-blocks text generate":qt}a(Pi,"recoveryCommand");async function qn(e=process.cwd()){let t=await Ar(e),r=b(await Jt(t,F.join(t,"three-blocks.json"),d$1.metadata,"Project metadata")),n=await xi(t,r),o=r.features.text?await Ri(t,r):void 0,s=await Ei(t,r),i=s.receipt,a=s.kind==="invalid",c=a||i?.lifecycle.state==="error",u=i===null?{state:a?"error":"starting",backend:null,renderer:null,protocolVersion:1}:{state:c?"error":i.lifecycle.workerReady?"worker ready":"starting",backend:i.worker.backend,renderer:i.worker.renderer,protocolVersion:i.worker.protocolVersion},f=i===null?{state:a?"error":"starting",codecs:$i(),resources:0}:{state:c?"error":i.lifecycle.assetsReady?"assets ready":"starting",codecs:i.assets.codecs,resources:i.assets.resources},l=i===null?{state:a?"error":"starting",capabilities:Ti(),outcome:Bi()}:{state:c||i.hmr.outcome.attempted&&(i.hmr.outcome.succeeded!==true||i.hmr.outcome.rollbackPreserved!==true)?"error":i.hmr.outcome.attempted?"first frame":"starting",capabilities:i.hmr.capabilities,outcome:i.hmr.outcome},m=i===null?{state:a?"error":"starting",snapshots:0,textures:0,workerProfiler:false,mainPanels:false}:{state:c?"error":i.stats.snapshots>0&&i.stats.workerProfiler&&i.stats.mainPanels?"first frame":"starting",...i.stats},p=i===null?{state:a?"error":"starting",mode:null,pipelines:0,artifactState:n.state}:{state:c?"error":i.lifecycle.compiled?n.state==="fresh"?i.shaders.mode:n.state:i.lifecycle.state,mode:i.shaders.mode,pipelines:i.shaders.pipelines,artifactState:n.state},h=o===void 0?void 0:i?.text===void 0?{state:a?"error":"starting",atlases:0,glyphs:0,requiredGlyphs:0}:{state:c?"error":o.state==="ready"?i.text.state:o.state,atlases:i.text.atlases,glyphs:i.text.glyphs,requiredGlyphs:i.text.requiredGlyphs};return {schemaVersion:1,root:t,metadata:r,configuration:{worker:u,assets:f,hmr:l,optimization:p,stats:m,...h===void 0?{}:{text:h}},runtime:{state:a?"error":i?.lifecycle.state??"starting",observed:i!==null,observedAt:i?.observedAt??null,reason:s.reason,recovery:Pi(s,n,o),observation:i},shaders:n,...o?{text:o}:{}}}a(qn,"inspectProject");async function zn(e){let[t,r]=await Promise.all([g(F.join(e,"three-blocks.shaders.json")),g(F.join(e,"three-blocks.text.ts"))]),[n,o]=await Promise.all([t?Ue(e):Promise.resolve(void 0),r?zt(e):Promise.resolve(void 0)]);return {schemaVersion:1,root:e,kind:"adopted",markers:{shaders:t,text:r},...n===void 0?{}:{shaders:n},...o===void 0?{}:{text:o}}}a(zn,"inspectAdoptedProject");async function Ai(e=process.cwd()){let t=await Ar(e),r=F.join(t,"three-blocks.json");if(await g(r)){try{b(await Jt(t,r,d$1.metadata,"Project metadata"));}catch{return zn(t)}return qn(t)}return zn(t)}a(Ai,"inspectThreeBlocksStatus");function _i(e){return Gn(e)?(e.markers.shaders||e.markers.text)&&(e.shaders===void 0||e.shaders.state==="fresh")&&(e.text===void 0||e.text.state==="ready"):e.shaders.state==="fresh"&&(e.text===void 0||e.text.state==="ready")&&e.runtime.state!=="error"}a(_i,"threeBlocksStatusIsFresh");function Mi(e){return e==="ktx2"?"KTX2":e==="draco"?"Draco":e==="meshopt"?"Meshopt":e}a(Mi,"codecName");function Ci(e,t=Date.now()){let r=t-Date.parse(e);if(!Number.isFinite(r)||r<0)return e;let n=Math.round(r/1e3);if(n<60)return "just now";let o=Math.round(n/60);if(o<60)return `${o} minute${o===1?"":"s"} ago`;let s=Math.round(o/60);return s<48?`${s} hour${s===1?"":"s"} ago`:`${Math.round(s/24)} days ago`}a(Ci,"relativeTime");function xe(e,t,r){return `${e} ${Pr(t,12)} ${r}`}a(xe,"row");function Le(e,t){return ` ${Pr(I.dim(e),12)} ${I.dim(t)}`}a(Le,"subRow");function Oi(e){return e<100?e.toFixed(1):Math.round(e).toString()}a(Oi,"milliseconds");function Fi(e){return e?`${e.render} render \xB7 ${e.compute} compute`:"no coverage"}a(Fi,"coverageText");function Xn(e){let t=[xe(We(e.state),"shaders",`${e.state==="fresh"?"fresh":I.warn(e.state)} ${N.dot} ${I.dim(e.reason)}`)];for(let r of e.scenes){let n=r.timing,o=n?.source==="committed-capture"?n.adapter??"captured adapter":"this capture",s=n===void 0?"":n.runs>1?`measured median of ${n.runs}`:"single-capture estimate",i=n===void 0?"":`\u2248${Oi(n.avoidedBuildMs)} ms TSL work avoided`,a=n===void 0?r.state==="fresh"?` ${N.dot} ${I.dim("capture again to record a timing estimate")}`:"":` ${N.dot} ${I.dim(`${i} \xB7 ${s} \xB7 ${o}`)}`;t.push(xe(We(r.state),`${r.scene}:${r.backend}`,`${r.state} ${N.dot} ${Fi(r.coverage)}${a}`)),n!==void 0&&n.spreadMs>n.avoidedBuildMs*.4&&t.push(Le("measure",I.warn("noisy measurement \u2014 close other GPU apps and re-run")));let c=[...r.changedInputs??[],...r.addedInputs??[],...r.removedInputs??[]];c.length>0&&t.push(Le("changed",c.join(", ")));}return e.state!=="fresh"&&t.push(`${N.info} ${I.accent("three-blocks shaders capture")}`),t.join(`
18
- `)}a(Xn,"formatShaderMatrixStatus");function Ii(e){let t=e.scene,r=e.coverage,n=r?`${r.render} render \xB7 ${r.compute} compute`:"no coverage";if(e.state==="fresh")return [xe(We("fresh"),t,`fresh ${N.dot} ${n} ${N.dot} ${I.dim("precompiled at runtime")}`)];let o=[xe(We(e.state),t,`${e.state==="missing"?I.dim("missing"):I.warn(e.state)} ${N.dot} ${I.dim(e.reason)}`)],s=[...e.changedInputs??[],...e.addedInputs??[],...e.removedInputs??[]];return s.length>0&&o.push(Le("changed",s.join(", "))),o}a(Ii,"shaderRow");function Jn(e,t=Date.now()){let r=N.mark?`${N.mark} `:"",n=e.metadata.runtime,o=[`${r}${I.bold("three-blocks")} ${I.dim("status")}`,Le("project",e.root),"",I.bold("Project"),xe(N.tick,e.metadata.template,`three ${n.three} ${N.dot} three-blocks ${n.threeBlocks}`),"",I.bold("Shaders"),...Ii(e.shaders)];if(e.text){let a=e.text,c=a.atlases.reduce((u,f)=>u+f.glyphs,0);o.push("",I.bold("Text"),xe(We(a.state),"coverage",a.state==="ready"?`ready ${N.dot} ${c} glyphs ${N.dot} ${a.atlases.length} atlas${a.atlases.length===1?"":"es"}`:`${I.warn(a.state)} ${N.dot} ${I.dim(a.reason)}`),...a.atlases.map(u=>Le("atlas",`${u.name} \xB7 ${u.glyphs} glyphs \xB7 ${u.width}\xD7${u.height}`)));}let s=e.runtime.observation;if(o.push("",I.bold("Browser check")),s!==null&&e.runtime.state!=="error"){let a=s.assets.codecs.map(c=>`${Mi(c.name)}${c.decoded?"":c.available?" (idle)":" (unavailable)"}`).join(" \xB7 ");o.push(xe(N.tick,"verified",`${Ci(s.observedAt,t)} ${N.dot} ${s.worker.renderer} worker ${N.dot} ${s.lifecycle.state} ${N.dot} ${s.shaders.pipelines} pipeline${s.shaders.pipelines===1?"":"s"} ${s.shaders.mode}`),Le("codecs",a||"none configured")),s.hmr.outcome.attempted&&o.push(Le("hmr",s.hmr.outcome.succeeded?`update succeeded${s.hmr.outcome.workerRestarted?" \xB7 worker restarted":""}`:"update failed"));}else e.runtime.state==="error"?o.push(xe(N.cross,"runtime",I.danger(e.runtime.reason))):o.push(xe(N.ring,"unverified",I.dim(`no browser run recorded \u2014 ${qt}`)));return e.shaders.state==="fresh"&&(e.text===void 0||e.text.state==="ready")&&e.runtime.state!=="error"||o.push("",I.bold("Next"),`${N.info} ${I.accent(e.runtime.recovery)}`),o.join(`
19
- `)}a(Jn,"formatStatus");function Li(e,t=Date.now()){if(!Gn(e))return Jn(e,t);let r=N.mark?`${N.mark} `:"",n=e.markers.shaders||e.markers.text,o=[`${r}${I.bold("three-blocks")} ${I.dim("status")}`,Le("project",e.root)];if(!n)return o.push("",`${N.dot} ${I.dim("no Three Blocks project markers found")}`,` ${I.dim("shaders:")} add three-blocks.shaders.json \u2014 /docs/tools/devtools`,` ${I.dim("starter:")} npx three-blocks starter`),o.join(`
13
+ ${r} demands: ${Tr(e.demands)}`)}a(Er,"assertObservation");async function Qa(e,t,r){if(r===void 0)return new Set;try{let n=JSON.parse(await readFile(F.join(e,t.publicDir??"public",r),"utf8"));return new Set(Object.keys(n.fallbacks??{}))}catch{return new Set}}a(Qa,"manifestFallbackKeys");function ei(e,t,r,n,o,s){if(t.render>0&&r.stats.registeredRenderBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered render pipeline.`);if(t.compute>0&&r.stats.registeredComputeBuilds===0)throw new Error(`Scene "${e.key}" live baseline exercised no registered compute kernel.`);Dn(e,t,n,o,s,r.demands);}a(ei,"assertZeroBuild");function Tr(e){return !e||e.length===0?"none recorded":e.map(t=>`${String(t.key??"unregistered")}[${String(t.event)}${t.hit===false?":miss":""}|${String(t.target)}${t.object===void 0?"":`@${String(t.object)}`}]`).join(" ").slice(0,4e3)}a(Tr,"describeDemands");function Dn(e,t,r,n,o,s){let i=a(()=>`
14
+ Precompiled demands: ${Tr(r.demands)}`+(s===void 0?"":`
15
+ Live demands: ${Tr(s)}`),"demandEvidence");if(r.stats.registeredRenderBuilds+r.stats.registeredComputeBuilds>n){let a=r.stats.missedKeys??[];throw new Error(`Scene "${e.key}" injected path performed ${r.stats.registeredRenderBuilds} render and ${r.stats.registeredComputeBuilds} compute registered live builds; capture permits ${n}.`+(a.length>0?` Missed keys: ${a.join(", ")}.`:"")+i())}if(r.stats.buildCalls>n)throw new Error(`Scene "${e.key}" injected path performed ${r.stats.buildCalls} total live NodeBuilder build${r.stats.buildCalls===1?"":"s"}; capture permits ${n} skipped live build${n===1?"":"s"}.`);if(t.render>0&&r.stats.injectedRender===0)throw new Error(`Scene "${e.key}" injected no render entries.`);if(t.compute>0&&r.stats.injectedCompute===0)throw new Error(`Scene "${e.key}" injected no compute entries.`);if(r.stats.missed!==0||r.stats.missedRender!==0||r.stats.missedCompute!==0){let a=r.stats.missedKeys??[],c=a.filter(f=>!o.has(f)),l=a.length>0&&r.stats.missed<=o.size;if(c.length>0||!l)throw new Error(`Scene "${e.key}" injected path reported shader manifest misses.`+(a.length>0?` Missed keys: ${a.join(", ")}.`:"")+(c.length>0&&c.length!==a.length?` Unexpected: ${c.join(", ")}.`:"")+i())}}a(Dn,"assertPrecompiledZeroBuild");async function ti(e,t,r,n,o){let s=F.join(e,p);if(await g(s)){let a=await lstat(s);if(a.isSymbolicLink()||!a.isDirectory())throw new Error("Shader parity artifact directory is not a real directory.")}else await mkdir(s,{recursive:true});let i=[`${t}.live.png`,`${t}.precompiled.png`,`${t}.diff.png`];return await Promise.all([r,n,o].map(async(a,c)=>{let l=i[c];if(l===void 0)throw new Error("Parity artifact mapping failed.");let f=F.join(s,l);if(await g(f)){let u=await lstat(f);if(u.isSymbolicLink()||!u.isFile())throw new Error(`Shader parity target is not a regular file: ${l}.`)}await writeFile(f,a,{mode:384});})),i.map(a=>`${p}/${a}`)}a(ti,"writeParityFailure");async function ri(e={}){let t=e.root?await realpath(e.root):await v(e.start),r=e.runtime??await Ae(t),n=e.config??await w(t),o$1=q(e.backend??n.backend),s$1=s(n.scenes,[...o$1].reverse()),i=await Ue(t,r,e.backend??n.backend);if(i.state!=="fresh")throw new Error(`Shader no-GPU validation is ${i.state}: ${i.reason}`);if(e.skipBrowser)return {schemaVersion:1,root:t,noGpu:i,browser:"skipped",scenes:[]};if(e.parityOnly===true&&e.commitTiming===true)throw new Error("Parity-only shader verification cannot commit timing.");let a$1=e.runs??5;if(!Number.isSafeInteger(a$1)||a$1<1||a$1>100)throw new Error("Shader timing runs must be an integer in 1...100.");let c=await readFile(F.join(t,o,"meta.json")),l=c$1(JSON.parse(c.toString("utf8")));if(i.receipt===void 0||H(l)!==H(i.receipt))throw new Error("Shader receipt changed after no-GPU validation; restart browser parity verification.");let f=e.driver===void 0,u=e.driver===void 0&&e.driverKind===void 0&&e.serve===void 0&&e.url===void 0?await x(t):void 0,m=e.serve??u?.serve,p=e.driverKind??u?.driverKind??(m===void 0?"vite":"static");if(e.url!==void 0&&(e.serve!==void 0||e.driverKind!==void 0))throw new Error("--url cannot be combined with --driver or --serve.");if(p==="vite"&&m!==void 0)throw new Error("--serve requires the static shader driver.");if(p==="static"&&m===void 0&&e.driver===void 0)throw new Error("The static shader driver requires --serve <built-directory>.");let h=e.driver===void 0?await import('./shader-browser-523TEBVA.js'):void 0,{compareShaderScreenshots:y}=await import('./shader-parity-QXJWR6OZ.js'),w$1=a(()=>e.url!==void 0?h.createAttachedPlaywrightShaderDriver({root:t,runtime:r,url:e.url,...e.headed!==void 0?{headed:e.headed}:{}}):p==="static"?h.createStaticPlaywrightShaderDriver({root:t,runtime:r,serve:m,...e.headed!==void 0?{headed:e.headed}:{}}):h.createPlaywrightShaderDriver({root:t,runtime:r,...e.headed!==void 0?{headed:e.headed}:{}}),"createDriver"),b=new Map,x$1=new Map,g=a((k,A)=>{if(e.driver!==void 0)return e.driver;let v=k.get(A);return v===void 0&&(v=w$1(),k.set(A,v)),v},"driverFor");await P(t,s$1.map(k=>k.key),c);let T=[],R={},C=[],O$1=new Set;try{for(let[A,v]of s$1.entries()){let{scene:S,backend:_,key:H}=v;e.onSceneStart?.(H,A,s$1.length);let q=i.scenes.find(te=>te.scene===S.key&&te.backend===_);if(!q?.coverage)throw new Error(`Fresh receipt has no coverage for "${H}".`);let z$1=q.coverage;if(z$1.render+z$1.compute===0)continue;let E=z(r.three,_),M=i.receipt?.scenes[H]?.skipped,L=(M?.render??0)+(M?.compute??0),U=await Qa(t,n,i.receipt?.scenes[H]?.asset),ee=a(async te=>{let V=g(b,_),G=g(x$1,_),K=te?"live":"precompiled",ne=te?"precompiled":"live",de=te?V:G,Je=te?G:V,ce=await de.observe(S,K,n,void 0,_),j=await Je.observe(S,ne,n,ce.frame,_),le=ce.mode==="live"?ce:j,Me=ce.mode==="precompiled"?ce:j;Er(le,S,"live",E),Er(Me,S,"precompiled",E),ei(S,z$1,le,Me,L,U);let Gr=a(async(Uo,Kr,qr)=>{let Ee=y(Kr,qr,n.parity.channelTolerance,S.maxDiffRatio??n.parity.maxDiffRatio);if(Ee.matches)return Ee;let Wo=await ti(t,H,Kr,qr,Ee.diff),zo=Ee.nonBlack?`${Ee.differentPixels}/${Ee.totalPixels} pixels differ (${(Ee.diffRatio*100).toFixed(3)}%).`:`rendered output is black (live=${Ee.baselineLuminance.toFixed(4)}, precompiled=${Ee.precompiledLuminance.toFixed(4)}).`;throw new Error(`Shader ${Uo} parity failed for scene "${S.key}" at completed frames live=${le.frame}, precompiled=${Me.frame}: ${zo} Artifacts: ${Wo.join(", ")}`)},"compare");await Gr("first frame",le.firstFrameScreenshot,Me.firstFrameScreenshot);let Vo=await Gr("settled",le.screenshot,Me.screenshot);return {live:le,precompiled:Me,parity:Vo}},"observePair"),X,re,se;if(e.parityOnly===!0)try{X=await ee(!0);}catch(te){Xa(te)&&O$1.add(H),C.push({scene:H,error:te}),e.onSceneError?.(H,te);continue}else {await ee(!0);let te=[];for(let j=0;j<a$1;j++)te.push(await ee(j%2===0));let V=te[te.length-1];if(V===void 0)throw new Error(`Shader timing produced no runs for scene "${S.key}".`);if(X=V,re=await g(x$1,_).observePublished(S,n,_),Er(re,S,"precompiled",E),Dn(S,z$1,re,L,U),se=S.runtimeMotion?y(re.beforeScreenshot,re.screenshot,n.parity.channelTolerance,1):void 0,se&&se.diffRatio<1e-4)throw new Error(`Published scene "${S.key}" stopped animating during its normal 120-frame soak (changed ${se.differentPixels}/${se.totalPixels} canvas pixels).`);let K=a(j=>j.stats.buildMs+(j.stats.precompiledSetupMs??0)+(j.stats.hydrationMs??0),"observedNodeBuilderMs"),ne=In(te.map(j=>K(j.live))),de=In(te.map(j=>K(j.precompiled))),Je=Math.max(0,ne-de),ce=te.map(j=>Math.max(0,K(j.live)-K(j.precompiled)));R[H]={builds:z$1.render+z$1.compute,setupMeasured:!0,liveBuildMs:ne,precompiledBuildMs:de,avoidedBuildMs:Je,runs:a$1,spreadMs:Math.max(...ce.map(j=>Math.abs(j-Je)))};}let{diff:Xe,...oe}=X.parity,{firstFrameScreenshot:Pe,screenshot:ve,...Se}=X.live,{firstFrameScreenshot:pe,screenshot:lt,..._e}=X.precompiled,ye;if(re!==void 0){let{beforeScreenshot:te,firstFrameScreenshot:V,screenshot:G,...K}=re;ye=K;}T.push({scene:S.key,backend:_,coverage:z$1,live:Se,precompiled:_e,...ye===void 0?{}:{published:ye},parity:oe,...se===void 0?{}:{runtimeMotion:{differentPixels:se.differentPixels,totalPixels:se.totalPixels,diffRatio:se.diffRatio}}}),await O(t,[H],c);}if(e.parityOnly===!0){if(await Ja(t,[...O$1],c),C.length>0)throw new Error(`Shader parity failed for ${C.length}/${s$1.length} scene/backend pair(s):
16
+ `+C.map(A=>{let v=A.error instanceof Error?A.error.message:String(A.error);return ` - ${A.scene}: ${v}`}).join(`
17
+ `));return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:T}}if(Object.keys(R).length===0)return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:T};if(e.commitTiming===!0){let A={adapter:o$1.length===1&&o$1[0]==="webgl"?"WebGL adapter":"WebGPU adapter",platform:`${zt.platform()}/${zt.arch()}`},S=await((b.values().next().value??e.driver)?.timingEnvironment?.()??A),_=await Q(t,R,S);return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:T,timing:_.local,committedTiming:_.committed}}let k=await N$1(t,R);return {schemaVersion:1,root:t,noGpu:i,browser:"passed",scenes:T,timing:k}}finally{f&&await Promise.all([...b.values(),...x$1.values()].map(k=>k.close()));}}a(ri,"testShaders");function ni(e=process.env,t=process.stdout){if(e.NO_COLOR!==void 0)return 0;if(e.FORCE_COLOR!==void 0){let r=String(e.FORCE_COLOR);return r==="0"||r==="false"?0:r==="3"?24:r==="2"?8:4}return !t||!t.isTTY||e.TERM==="dumb"?0:/^(truecolor|24bit)$/i.test(e.COLORTERM??"")||e.WT_SESSION||e.TERM_PROGRAM==="iTerm.app"||e.TERM_PROGRAM==="vscode"?24:/-256(color)?$/i.test(e.TERM??"")?8:4}a(ni,"resolveColorDepth");function oi(e=process.env,t=process.platform){return t!=="win32"?true:!!(e.WT_SESSION||e.TERM_PROGRAM||e.ConEmuANSI||/-256(color)?$/i.test(e.TERM??""))}a(oi,"resolveUnicode");function si(e=process.stdout){let t=e?.columns;return typeof t=="number"&&Number.isInteger(t)&&t>0?t:80}a(si,"termWidth");var Nn={depth:ni(),unicode:oi()},st={logo:{square:[30,84,200]},accent:[86,132,230],gold:[244,174,12],danger:[221,76,51],live:[212,255,71]};function ai(e,t,r){if(Math.max(e,t,r)-Math.min(e,t,r)<12){let o=Math.round((e+t+r)/3);return o<8?16:o>238?231:232+Math.round((o-8)/10)}let n=a(o=>o<48?0:o<115?1:Math.min(5,Math.round((o-35)/40)),"level");return 16+36*n(e)+6*n(t)+n(r)}a(ai,"ansi256");function at(e,t,r){return r>=24?`38;2;${e[0]};${e[1]};${e[2]}`:r>=8?`38;5;${ai(e[0],e[1],e[2])}`:String(t)}a(at,"fgOpen");function ii(e=Nn.depth,t=Nn.unicode){let r=e>0?(n,o=39)=>s=>`\x1B[${n}m${String(s)}\x1B[${o}m`:()=>n=>String(n);return {depth:e,unicode:t,accent:r(at(st.accent,94,e)),live:r(at(st.live,92,e)),danger:r(at(st.danger,91,e)),gold:r(at(st.gold,33,e)),deep:r(at(st.logo.square,34,e)),warn:r(at(st.gold,33,e)),dim:r(2,22),bold:r(1,22)}}a(ii,"createTheme");function di(e){let t=e.unicode;return {tick:e.live(t?"\u2713":"\u221A"),cross:e.danger(t?"\u2717":"x"),warn:e.warn(t?"\u25B2":"!"),info:e.accent(t?"\u203A":">"),pointer:e.accent(t?"\u276F":">"),dot:e.dim(t?"\xB7":"."),ring:e.dim(t?"\u25CB":"o"),bar:t?"\u2502":"|",ellipsis:t?"\u2026":"...",mark:t?`${e.gold("\u25B2")} ${e.danger("\u25CF")} ${e.deep("\u25A0")}`:null}}a(di,"createSymbols");var I=ii(),N=di(I),ci=/\x1b\[[0-9;]*m/g;function li(e){return String(e).replace(ci,"")}a(li,"stripAnsi");function ui(e){return e===8203||e===8205||e>=768&&e<=879||e>=65024&&e<=65039?0:e>=4352&&e<=4447||e>=11904&&e<=42191||e>=44032&&e<=55203||e>=63744&&e<=64255||e>=65072&&e<=65103||e>=65280&&e<=65376||e>=65504&&e<=65510||e>=127744&&e<=129791||e>=131072&&e<=262141?2:1}a(ui,"charWidth");function mi(e){let t=0;for(let r of li(e))t+=ui(r.codePointAt(0)??0);return t}a(mi,"visibleWidth");function $r(e,t){let r=t-mi(String(e));return r>0?String(e)+" ".repeat(r):String(e)}a($r,"padEndAnsi");function We(e){return ["fresh","ready","precompiled","passed","captured","verified","first frame","compiled","worker ready","assets ready"].includes(e)?N.tick:["stale","live","generating","fallback","updating","skipped"].includes(e)?N.warn:["missing","starting","not-observed","unobserved"].includes(e)?N.ring:N.cross}a(We,"stateMark");var qt=".three-blocks/runtime/status.json",Et=256*1024,Kt="three-blocks browser smoke",fi=["three-blocks.json","three-blocks.shaders.json","three-blocks.text.ts"];function Gn(e){return "kind"in e&&e.kind==="adopted"}a(Gn,"isAdoptedProjectStatus");async function Xt(e,t,r,n){let o=await l(e,t,r,n);return JSON.parse(o.data.toString("utf8"))}a(Xt,"readJsonWithin");var pi=["starting","worker ready","assets ready","compiled","first frame","updating","error"],hi=["ready","generating","fallback","missing","invalid"],yi=["WebGPU","WebGL"],gi=["OffscreenCanvas","MainThread"],wi=/^[0-9A-Za-z][0-9A-Za-z._-]{0,63}$/,Vn=16,Un=1e9;function we(e,t,r,n=[]){if(!a$1(e))throw new Error(`${t} must be an object.`);let o=new Set([...r,...n]);for(let s of r)if(!Object.hasOwn(e,s))throw new Error(`${t}.${s} is required.`);for(let s of Object.keys(e))if(!o.has(s))throw new Error(`${t}.${s} is not supported by schema v1.`);return e}a(we,"exactRecord");function vt(e,t,r){if(typeof e!="string"||!t.includes(e))throw new Error(`${r} has an unsupported value.`);return e}a(vt,"enumValue");function ue(e,t){if(typeof e!="boolean")throw new Error(`${t} must be a boolean.`);return e}a(ue,"booleanValue");function Wn(e,t){return e===null?null:ue(e,t)}a(Wn,"nullableBoolean");function ze(e,t){if(typeof e!="number"||!Number.isSafeInteger(e)||e<0||e>Un)throw new Error(`${t} must be a non-negative integer no greater than ${Un}.`);return e}a(ze,"boundedCounter");function bi(e){if(typeof e!="string"||e.length>32)throw new Error("Runtime status receipt observedAt must be a bounded ISO timestamp.");let t=Date.parse(e);if(!Number.isFinite(t)||new Date(t).toISOString()!==e)throw new Error("Runtime status receipt observedAt must be an exact ISO timestamp.");return e}a(bi,"observedTimestamp");function Si(e){if(e===null)return null;if(typeof e!="string"||e.length===0||e.length>2048||/[\u0000-\u001f\u007f]/u.test(e))throw new Error("Runtime status receipt error must be null or one bounded display-safe line.");return e}a(Si,"receiptError");function ki(e){if(!Array.isArray(e)||e.length>Vn)throw new Error(`Runtime status receipt assets.codecs must contain at most ${Vn} entries.`);let t=e.map((r,n)=>{let o=we(r,`Runtime status receipt assets.codecs[${n}]`,["name","available","decoded"]);if(typeof o.name!="string"||!wi.test(o.name))throw new Error(`Runtime status receipt assets.codecs[${n}].name is invalid.`);let s=ue(o.available,`Runtime status receipt assets.codecs[${n}].available`),i=ue(o.decoded,`Runtime status receipt assets.codecs[${n}].decoded`);if(i&&!s)throw new Error(`Runtime status receipt codec ${JSON.stringify(o.name)} cannot be decoded when unavailable.`);return {name:o.name,available:s,decoded:i}});if(new Set(t.map(r=>r.name)).size!==t.length)throw new Error("Runtime status receipt assets.codecs must have unique names.");return t}a(ki,"parseRuntimeCodecs");function xi(e){if(e.assetsReady&&!e.workerReady)throw new Error("Runtime lifecycle assetsReady requires workerReady.");if(e.compiled&&!e.assetsReady)throw new Error("Runtime lifecycle compiled requires assetsReady.");if(e.firstFrame&&!e.compiled)throw new Error("Runtime lifecycle firstFrame requires compiled.");let t=e.state==="starting"?[false,false,false,false]:e.state==="worker ready"?[true,false,false,false]:e.state==="assets ready"?[true,true,false,false]:e.state==="compiled"?[true,true,true,false]:e.state==="first frame"||e.state==="updating"?[true,true,true,true]:null;if(t!==null&&![e.workerReady,e.assetsReady,e.compiled,e.firstFrame].every((r,n)=>r===t[n]))throw new Error(`Runtime lifecycle flags do not match state ${JSON.stringify(e.state)}.`)}a(xi,"validateLifecycle");function Kn(e){let t=we(e,"Runtime status receipt",["schemaVersion","observedAt","worker","assets","hmr","stats","lifecycle","shaders","error"],["text"]);if(t.schemaVersion!==1)throw new Error("Runtime status receipt must use schemaVersion 1.");let r=we(t.worker,"Runtime status receipt worker",["backend","renderer","protocolVersion"]);if(r.protocolVersion!==1)throw new Error("Runtime status receipt worker.protocolVersion must be 1.");let n=we(t.assets,"Runtime status receipt assets",["codecs","resources"]),o=we(t.hmr,"Runtime status receipt hmr",["capabilities","outcome"]),s=we(o.capabilities,"Runtime status receipt hmr.capabilities",["scene","component","assetManifest","workerRestart"]),i=we(o.outcome,"Runtime status receipt hmr.outcome",["attempted","succeeded","rollbackPreserved","workerRestarted"]),a=ue(i.attempted,"Runtime status receipt hmr.outcome.attempted"),c=Wn(i.succeeded,"Runtime status receipt hmr.outcome.succeeded"),l=Wn(i.rollbackPreserved,"Runtime status receipt hmr.outcome.rollbackPreserved"),f=ue(i.workerRestarted,"Runtime status receipt hmr.outcome.workerRestarted");if(a?c===null||l===null:c!==null||l!==null||f)throw new Error("Runtime status receipt HMR outcome fields are inconsistent with attempted.");let u={scene:ue(s.scene,"Runtime status receipt hmr.capabilities.scene"),component:ue(s.component,"Runtime status receipt hmr.capabilities.component"),assetManifest:ue(s.assetManifest,"Runtime status receipt hmr.capabilities.assetManifest"),workerRestart:ue(s.workerRestart,"Runtime status receipt hmr.capabilities.workerRestart")};if(a&&!u.scene)throw new Error("Runtime status receipt cannot attempt HMR without the scene capability.");if(f&&!u.workerRestart)throw new Error("Runtime status receipt cannot restart a worker without the workerRestart capability.");let m=we(t.stats,"Runtime status receipt stats",["snapshots","textures","workerProfiler","mainPanels"]),p=we(t.lifecycle,"Runtime status receipt lifecycle",["state","workerReady","assetsReady","compiled","firstFrame"]),h={state:vt(p.state,pi,"Runtime status receipt lifecycle.state"),workerReady:ue(p.workerReady,"Runtime status receipt lifecycle.workerReady"),assetsReady:ue(p.assetsReady,"Runtime status receipt lifecycle.assetsReady"),compiled:ue(p.compiled,"Runtime status receipt lifecycle.compiled"),firstFrame:ue(p.firstFrame,"Runtime status receipt lifecycle.firstFrame")};xi(h);let y=we(t.shaders,"Runtime status receipt shaders",["mode","pipelines"]),w=vt(y.mode,["precompiled","live"],"Runtime status receipt shaders.mode"),b=ze(y.pipelines,"Runtime status receipt shaders.pipelines");if(w==="precompiled"&&b===0)throw new Error("A precompiled runtime receipt must observe at least one shader pipeline.");let x;if(t.text!==void 0){let T=we(t.text,"Runtime status receipt text",["state","atlases","glyphs","requiredGlyphs"]);if(x={state:vt(T.state,hi,"Runtime status receipt text.state"),atlases:ze(T.atlases,"Runtime status receipt text.atlases"),glyphs:ze(T.glyphs,"Runtime status receipt text.glyphs"),requiredGlyphs:ze(T.requiredGlyphs,"Runtime status receipt text.requiredGlyphs")},x.state==="ready"&&(x.atlases===0||x.requiredGlyphs===0||x.glyphs<x.requiredGlyphs))throw new Error("A ready text receipt must cover a non-empty required glyph set with at least one atlas.")}let g=Si(t.error);if(h.state==="error"?g===null:g!==null)throw new Error("Runtime status receipt error must be present only when lifecycle.state is error.");return {schemaVersion:1,observedAt:bi(t.observedAt),worker:{backend:vt(r.backend,gi,"Runtime status receipt worker.backend"),renderer:vt(r.renderer,yi,"Runtime status receipt worker.renderer"),protocolVersion:1},assets:{codecs:ki(n.codecs),resources:ze(n.resources,"Runtime status receipt assets.resources")},hmr:{capabilities:u,outcome:{attempted:a,succeeded:c,rollbackPreserved:l,workerRestarted:f}},stats:{snapshots:ze(m.snapshots,"Runtime status receipt stats.snapshots"),textures:ze(m.textures,"Runtime status receipt stats.textures"),workerProfiler:ue(m.workerProfiler,"Runtime status receipt stats.workerProfiler"),mainPanels:ue(m.mainPanels,"Runtime status receipt stats.mainPanels")},lifecycle:h,shaders:{mode:w,pipelines:b},...x===void 0?{}:{text:x},error:g}}a(Kn,"parseRuntimeStatusReceipt");function Ri(e,t){return e.render===t.render&&e.vertex===t.vertex&&e.fragment===t.fragment&&e.compute===t.compute}a(Ri,"sameCoverage");async function Ar(e=process.cwd()){let t=F.resolve(e);for(;;){if((await Promise.all(fi.map(n=>g(F.join(t,n))))).some(Boolean))return realpath(t);let r=F.dirname(t);if(r===t)return realpath(F.resolve(e));t=r;}}a(Ar,"findProjectRoot");async function vi(e,t){let r=t.template,n=F.join(e,".three-blocks","shaders"),o=F.join(n,"meta.json");if(!await g(n)||!await g(o))return {state:"missing",scene:r,reason:t.artifacts?.shaders==="pending"?"The selected template has no verified shader capture yet.":".three-blocks/shaders/meta.json is absent."};try{let s=await k(e,n,"Shader artifact directory"),i=c$1(await Xt(s,o,d$1.receipt,"Shader receipt")),a=i.scenes[r];if(a===void 0)return {state:"invalid",scene:r,reason:`Shader receipt has no "${r}" scene.`};let c=await l(s,F.join(s,a.artifact),d$1.manifest,"Shader manifest");if(f(c.data)!==a.artifactHash)return {state:"invalid",scene:r,reason:"The selected shader manifest checksum does not match its receipt."};let l$1=Lt(c.data.toString("utf8"),c.path,r);if(!Ri(l$1,a.coverage))return {state:"invalid",scene:r,reason:"Shader receipt coverage does not match the manifest entries.",coverage:l$1};let{three:f$1,threeBlocks:u,threeBlocksShaderClosure:m}=await Ae(e);if(i.runtime.three!==f$1||t.runtime.three!==f$1||t.runtime.threeBlocks!==u)return {state:"stale",scene:r,reason:`Installed runtime versions (${f$1}, ${u}) do not match the metadata and shader receipt.`,coverage:l$1};if(i.runtime.threeBlocksShaderClosure!==m)return {state:"stale",scene:r,reason:"The installed three-blocks/shaders runtime closure differs from the capture receipt.",coverage:l$1};let p=await Ie(e),h=Object.keys(p),y=Object.keys(a.inputs),w=h.filter(g=>!Object.hasOwn(a.inputs,g)),b=y.filter(g=>!Object.hasOwn(p,g)),x=h.filter(g=>Object.hasOwn(a.inputs,g)&&a.inputs[g]!==p[g]);return w.length>0||b.length>0||x.length>0?{state:"stale",scene:r,reason:`${w.length} added, ${b.length} removed, and ${x.length} changed semantic shader inputs.`,coverage:l$1,...x.length>0?{changedInputs:x}:{},...w.length>0?{addedInputs:w}:{},...b.length>0?{removedInputs:b}:{}}:{state:"fresh",scene:r,reason:"Manifest, installed shader runtime closure, and the shader-relevant source snapshot match.",coverage:l$1}}catch(s){return {state:"invalid",scene:r,reason:s instanceof Error?s.message:String(s)}}}a(vi,"inspectShaders");async function Ei(e,t){if(t.artifacts?.text==="pending")return {state:"missing",reason:"The template has no verified text artifacts yet.",atlases:[]};let r=await Wt(e);return {state:r.state,reason:r.reason,atlases:r.atlases.map(n=>({name:n.font.key,glyphs:n.codePoints.length,width:n.texture.width,height:n.texture.height}))}}a(Ei,"inspectText");function Ti(e,t){if(e.lifecycle.assetsReady&&e.assets.codecs.some(r=>!r.available))throw new Error("Runtime status receipt claims assets ready while a configured codec is unavailable.");if(t.features.text!==(e.text!==void 0))throw new Error("Runtime status receipt text observation does not match three-blocks.json.")}a(Ti,"validateRuntimeReceiptForProject");async function Bi(e,t){let r=F.join(e,...qt.split("/"));if(!await g(r))return {kind:"absent",receipt:null,reason:"No browser observation receipt is available."};try{let n=await k(e,F.dirname(r),"Runtime status receipt directory"),o=Kn(await Xt(n,F.join(n,F.basename(r)),Et,"Runtime status receipt"));return Ti(o,t),{kind:"valid",receipt:o,reason:o.error??`Browser observation captured at ${o.observedAt}.`}}catch(n){return {kind:"invalid",receipt:null,reason:`Runtime status receipt is invalid: ${n instanceof Error?n.message:String(n)}`}}}a(Bi,"inspectRuntimeReceipt");function $i(){return {scene:false,component:false,assetManifest:false,workerRestart:false}}a($i,"emptyCapabilities");function Ai(){return {attempted:false,succeeded:null,rollbackPreserved:null,workerRestarted:false}}a(Ai,"emptyOutcome");function Pi(){return []}a(Pi,"configuredCodecs");function _i(e,t,r){if(t.state!=="fresh")return "three-blocks shaders capture";if(r!==void 0&&r.state!=="ready")return "three-blocks text generate";let n=e.receipt;return e.kind!=="valid"||n===null||n.lifecycle.state==="error"?Kt:n.text!==void 0&&n.text.state!=="ready"?"three-blocks text generate":Kt}a(_i,"recoveryCommand");async function qn(e=process.cwd()){let t=await Ar(e),r=b(await Xt(t,F.join(t,"three-blocks.json"),d$1.metadata,"Project metadata")),n=await vi(t,r),o=r.features.text?await Ei(t,r):void 0,s=await Bi(t,r),i=s.receipt,a=s.kind==="invalid",c=a||i?.lifecycle.state==="error",l=i===null?{state:a?"error":"starting",backend:null,renderer:null,protocolVersion:1}:{state:c?"error":i.lifecycle.workerReady?"worker ready":"starting",backend:i.worker.backend,renderer:i.worker.renderer,protocolVersion:i.worker.protocolVersion},f=i===null?{state:a?"error":"starting",codecs:Pi(),resources:0}:{state:c?"error":i.lifecycle.assetsReady?"assets ready":"starting",codecs:i.assets.codecs,resources:i.assets.resources},u=i===null?{state:a?"error":"starting",capabilities:$i(),outcome:Ai()}:{state:c||i.hmr.outcome.attempted&&(i.hmr.outcome.succeeded!==true||i.hmr.outcome.rollbackPreserved!==true)?"error":i.hmr.outcome.attempted?"first frame":"starting",capabilities:i.hmr.capabilities,outcome:i.hmr.outcome},m=i===null?{state:a?"error":"starting",snapshots:0,textures:0,workerProfiler:false,mainPanels:false}:{state:c?"error":i.stats.snapshots>0&&i.stats.workerProfiler&&i.stats.mainPanels?"first frame":"starting",...i.stats},p=i===null?{state:a?"error":"starting",mode:null,pipelines:0,artifactState:n.state}:{state:c?"error":i.lifecycle.compiled?n.state==="fresh"?i.shaders.mode:n.state:i.lifecycle.state,mode:i.shaders.mode,pipelines:i.shaders.pipelines,artifactState:n.state},h=o===void 0?void 0:i?.text===void 0?{state:a?"error":"starting",atlases:0,glyphs:0,requiredGlyphs:0}:{state:c?"error":o.state==="ready"?i.text.state:o.state,atlases:i.text.atlases,glyphs:i.text.glyphs,requiredGlyphs:i.text.requiredGlyphs};return {schemaVersion:1,root:t,metadata:r,configuration:{worker:l,assets:f,hmr:u,optimization:p,stats:m,...h===void 0?{}:{text:h}},runtime:{state:a?"error":i?.lifecycle.state??"starting",observed:i!==null,observedAt:i?.observedAt??null,reason:s.reason,recovery:_i(s,n,o),observation:i},shaders:n,...o?{text:o}:{}}}a(qn,"inspectProject");async function zn(e){let[t,r]=await Promise.all([g(F.join(e,"three-blocks.shaders.json")),g(F.join(e,"three-blocks.text.ts"))]),[n,o]=await Promise.all([t?Ue(e):Promise.resolve(void 0),r?Wt(e):Promise.resolve(void 0)]);return {schemaVersion:1,root:e,kind:"adopted",markers:{shaders:t,text:r},...n===void 0?{}:{shaders:n},...o===void 0?{}:{text:o}}}a(zn,"inspectAdoptedProject");async function Mi(e=process.cwd()){let t=await Ar(e),r=F.join(t,"three-blocks.json");if(await g(r)){try{b(await Xt(t,r,d$1.metadata,"Project metadata"));}catch{return zn(t)}return qn(t)}return zn(t)}a(Mi,"inspectThreeBlocksStatus");function Ci(e){return Gn(e)?(e.markers.shaders||e.markers.text)&&(e.shaders===void 0||e.shaders.state==="fresh")&&(e.text===void 0||e.text.state==="ready"):e.shaders.state==="fresh"&&(e.text===void 0||e.text.state==="ready")&&e.runtime.state!=="error"}a(Ci,"threeBlocksStatusIsFresh");function Oi(e){return e==="ktx2"?"KTX2":e==="draco"?"Draco":e==="meshopt"?"Meshopt":e}a(Oi,"codecName");function Fi(e,t=Date.now()){let r=t-Date.parse(e);if(!Number.isFinite(r)||r<0)return e;let n=Math.round(r/1e3);if(n<60)return "just now";let o=Math.round(n/60);if(o<60)return `${o} minute${o===1?"":"s"} ago`;let s=Math.round(o/60);return s<48?`${s} hour${s===1?"":"s"} ago`:`${Math.round(s/24)} days ago`}a(Fi,"relativeTime");function xe(e,t,r){return `${e} ${$r(t,12)} ${r}`}a(xe,"row");function Le(e,t){return ` ${$r(I.dim(e),12)} ${I.dim(t)}`}a(Le,"subRow");function Ii(e){return e<100?e.toFixed(1):Math.round(e).toString()}a(Ii,"milliseconds");function Li(e){return e?`${e.render} render \xB7 ${e.compute} compute`:"no coverage"}a(Li,"coverageText");function Xn(e){let t=[xe(We(e.state),"shaders",`${e.state==="fresh"?"fresh":I.warn(e.state)} ${N.dot} ${I.dim(e.reason)}`)];for(let r of e.scenes){let n=r.timing,o=n?.source==="committed-capture"?n.adapter??"captured adapter":"this capture",s=n===void 0?"":n.runs>1?`measured median of ${n.runs}`:"single-capture estimate",i=n===void 0?"":`\u2248${Ii(n.avoidedBuildMs)} ms TSL work avoided`,a=n===void 0?r.state==="fresh"?` ${N.dot} ${I.dim("capture again to record a timing estimate")}`:"":` ${N.dot} ${I.dim(`${i} \xB7 ${s} \xB7 ${o}`)}`;t.push(xe(We(r.state),`${r.scene}:${r.backend}`,`${r.state} ${N.dot} ${Li(r.coverage)}${a}`)),n!==void 0&&n.spreadMs>n.avoidedBuildMs*.4&&t.push(Le("measure",I.warn("noisy measurement \u2014 close other GPU apps and re-run")));let c=[...r.changedInputs??[],...r.addedInputs??[],...r.removedInputs??[]];c.length>0&&t.push(Le("changed",c.join(", ")));}return e.state!=="fresh"&&t.push(`${N.info} ${I.accent("three-blocks shaders capture")}`),t.join(`
18
+ `)}a(Xn,"formatShaderMatrixStatus");function ji(e){let t=e.scene,r=e.coverage,n=r?`${r.render} render \xB7 ${r.compute} compute`:"no coverage";if(e.state==="fresh")return [xe(We("fresh"),t,`fresh ${N.dot} ${n} ${N.dot} ${I.dim("precompiled at runtime")}`)];let o=[xe(We(e.state),t,`${e.state==="missing"?I.dim("missing"):I.warn(e.state)} ${N.dot} ${I.dim(e.reason)}`)],s=[...e.changedInputs??[],...e.addedInputs??[],...e.removedInputs??[]];return s.length>0&&o.push(Le("changed",s.join(", "))),o}a(ji,"shaderRow");function Jn(e,t=Date.now()){let r=N.mark?`${N.mark} `:"",n=e.metadata.runtime,o=[`${r}${I.bold("three-blocks")} ${I.dim("status")}`,Le("project",e.root),"",I.bold("Project"),xe(N.tick,e.metadata.template,`three ${n.three} ${N.dot} three-blocks ${n.threeBlocks}`),"",I.bold("Shaders"),...ji(e.shaders)];if(e.text){let a=e.text,c=a.atlases.reduce((l,f)=>l+f.glyphs,0);o.push("",I.bold("Text"),xe(We(a.state),"coverage",a.state==="ready"?`ready ${N.dot} ${c} glyphs ${N.dot} ${a.atlases.length} atlas${a.atlases.length===1?"":"es"}`:`${I.warn(a.state)} ${N.dot} ${I.dim(a.reason)}`),...a.atlases.map(l=>Le("atlas",`${l.name} \xB7 ${l.glyphs} glyphs \xB7 ${l.width}\xD7${l.height}`)));}let s=e.runtime.observation;if(o.push("",I.bold("Browser check")),s!==null&&e.runtime.state!=="error"){let a=s.assets.codecs.map(c=>`${Oi(c.name)}${c.decoded?"":c.available?" (idle)":" (unavailable)"}`).join(" \xB7 ");o.push(xe(N.tick,"verified",`${Fi(s.observedAt,t)} ${N.dot} ${s.worker.renderer} worker ${N.dot} ${s.lifecycle.state} ${N.dot} ${s.shaders.pipelines} pipeline${s.shaders.pipelines===1?"":"s"} ${s.shaders.mode}`),Le("codecs",a||"none configured")),s.hmr.outcome.attempted&&o.push(Le("hmr",s.hmr.outcome.succeeded?`update succeeded${s.hmr.outcome.workerRestarted?" \xB7 worker restarted":""}`:"update failed"));}else e.runtime.state==="error"?o.push(xe(N.cross,"runtime",I.danger(e.runtime.reason))):o.push(xe(N.ring,"unverified",I.dim(`no browser run recorded \u2014 ${Kt}`)));return e.shaders.state==="fresh"&&(e.text===void 0||e.text.state==="ready")&&e.runtime.state!=="error"||o.push("",I.bold("Next"),`${N.info} ${I.accent(e.runtime.recovery)}`),o.join(`
19
+ `)}a(Jn,"formatStatus");function Di(e,t=Date.now()){if(!Gn(e))return Jn(e,t);let r=N.mark?`${N.mark} `:"",n=e.markers.shaders||e.markers.text,o=[`${r}${I.bold("three-blocks")} ${I.dim("status")}`,Le("project",e.root)];if(!n)return o.push("",`${N.dot} ${I.dim("no Three Blocks project markers found")}`,` ${I.dim("shaders:")} add three-blocks.shaders.json \u2014 /docs/tools/devtools`,` ${I.dim("starter:")} npx three-blocks starter`),o.join(`
20
20
  `);if(e.shaders!==void 0&&o.push("",I.bold("Shaders"),Xn(e.shaders)),e.text!==void 0){let s=e.text.atlases.reduce((i,a)=>i+a.codePoints.length,0);o.push("",I.bold("Text"),xe(We(e.text.state),"coverage",e.text.state==="ready"?`ready ${N.dot} ${s} glyphs ${N.dot} ${e.text.atlases.length} atlas${e.text.atlases.length===1?"":"es"}`:`${I.warn(e.text.state)} ${N.dot} ${I.dim(e.text.reason)}`));}return o.join(`
21
- `)}a(Li,"formatThreeBlocksStatus");var Ir="virtual:three-blocks-devtools/browser-smoke",Zn=`\0${Ir}`,Wi=`/@id/__x00__${Ir}`,to=9e4;async function ro(){try{let[e,t]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,vite:t}}catch(e){throw new Error('Browser smoke and preview require the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(ro,"loadBrowserSmokeTools");function je(e,t,r,n,o){let s=e??o;if(!Number.isSafeInteger(s)||s<r||s>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return s}a(je,"boundedInteger");function no(e,t,r,n,o){let s=e??o;if(!Number.isFinite(s)||s<r||s>n)throw new Error(`${t} must be a finite number in ${r}...${n}.`);return s}a(no,"boundedRatio");function oo(e){let t=e??"/";if(t.length===0||t.length>2048||/[\u0000-\u001f\u007f]/u.test(t))throw new Error("Browser smoke route must be a bounded project URL.");let r=new URL(t,"http://three-blocks.invalid/");if(r.origin!=="http://three-blocks.invalid"||r.hash.length>0)throw new Error("Browser smoke route must stay within the project and have no fragment.");return `${r.pathname}${r.search}`}a(oo,"safeRoute");function it(e,t){return e[t]===true}a(it,"booleanField");function Re(e,t){if(!a$1(e)||!a$1(e.value))return {source:"missing",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:t,textReady:!t,firstFrame:false};let r=e.value,n=e.source==="public";if(n&&r.protocolVersion!==1)return {source:"public",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:t,textReady:!t,firstFrame:false};let o=a$1(r.readiness)?r.readiness:r,s=r.worker,i=n&&a$1(s)?s.offscreenCanvas===true&&s.visible===true:s===true;return {source:n?"public":"legacy",backend:n&&a$1(s)?s.offscreenCanvas===true?"OffscreenCanvas":"MainThread":s===true?"OffscreenCanvas":"unknown",worker:i,workerReady:it(o,"workerReady"),assetsReady:it(o,"assetsReady")||it(o,"loadEnd"),compileEnd:it(o,"compileEnd"),textEnabled:t,textReady:!t||it(o,"textReady"),firstFrame:it(o,"firstFrame")}}a(Re,"parseBrowserSmokeLifecycle");function Zt(e){let t=PNG.sync.read(e),r=Math.floor(t.width*.25),n=Math.floor(t.width*.75),o=Math.floor(t.height*.25),s=Math.floor(t.height*.75),i=0,a=0;for(let c=o;c<s;c+=2)for(let u=r;u<n;u+=2){let f=(c*t.width+u)*4,l=t.data[f],m=t.data[f+1],p=t.data[f+2];l===void 0||m===void 0||p===void 0||(i+=Math.max(l,m,p),a+=1);}return a===0?0:i/a}a(Zt,"screenshotLuminance");function zi(){return `
21
+ `)}a(Di,"formatThreeBlocksStatus");var Fr="virtual:three-blocks-devtools/browser-smoke",Zn=`\0${Fr}`,Gi=`/@id/__x00__${Fr}`,to=9e4;async function ro(){try{let[e,t]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,vite:t}}catch(e){throw new Error('Browser smoke and preview require the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(ro,"loadBrowserSmokeTools");function je(e,t,r,n,o){let s=e??o;if(!Number.isSafeInteger(s)||s<r||s>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return s}a(je,"boundedInteger");function no(e,t,r,n,o){let s=e??o;if(!Number.isFinite(s)||s<r||s>n)throw new Error(`${t} must be a finite number in ${r}...${n}.`);return s}a(no,"boundedRatio");function oo(e){let t=e??"/";if(t.length===0||t.length>2048||/[\u0000-\u001f\u007f]/u.test(t))throw new Error("Browser smoke route must be a bounded project URL.");let r=new URL(t,"http://three-blocks.invalid/");if(r.origin!=="http://three-blocks.invalid"||r.hash.length>0)throw new Error("Browser smoke route must stay within the project and have no fragment.");return `${r.pathname}${r.search}`}a(oo,"safeRoute");function it(e,t){return e[t]===true}a(it,"booleanField");function Re(e,t){if(!a$1(e)||!a$1(e.value))return {source:"missing",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:t,textReady:!t,firstFrame:false};let r=e.value,n=e.source==="public";if(n&&r.protocolVersion!==1)return {source:"public",backend:"unknown",worker:false,workerReady:false,assetsReady:false,compileEnd:false,textEnabled:t,textReady:!t,firstFrame:false};let o=a$1(r.readiness)?r.readiness:r,s=r.worker,i=n&&a$1(s)?s.offscreenCanvas===true&&s.visible===true:s===true;return {source:n?"public":"legacy",backend:n&&a$1(s)?s.offscreenCanvas===true?"OffscreenCanvas":"MainThread":s===true?"OffscreenCanvas":"unknown",worker:i,workerReady:it(o,"workerReady"),assetsReady:it(o,"assetsReady")||it(o,"loadEnd"),compileEnd:it(o,"compileEnd"),textEnabled:t,textReady:!t||it(o,"textReady"),firstFrame:it(o,"firstFrame")}}a(Re,"parseBrowserSmokeLifecycle");function Jt(e){let t=PNG.sync.read(e),r=Math.floor(t.width*.25),n=Math.floor(t.width*.75),o=Math.floor(t.height*.25),s=Math.floor(t.height*.75),i=0,a=0;for(let c=o;c<s;c+=2)for(let l=r;l<n;l+=2){let f=(c*t.width+l)*4,u=t.data[f],m=t.data[f+1],p=t.data[f+2];u===void 0||m===void 0||p===void 0||(i+=Math.max(u,m,p),a+=1);}return a===0?0:i/a}a(Jt,"screenshotLuminance");function Ki(){return `
22
22
  import * as THREE from 'three/webgpu';
23
23
  import { createAssetLoaderRegistry, createAssetManager, createThreeAssetAdapters, defineAssets } from 'three-blocks/assets';
24
24
  import { SceneHotReloader } from 'three-blocks/hmr';
@@ -243,8 +243,8 @@ export async function probe() {
243
243
  codecs,
244
244
  };
245
245
  }
246
- `}a(zi,"browserProbeSource");function Gi(){return {name:"three-blocks:browser-smoke-probe",enforce:"post",resolveId(e){return e===Ir?Zn:void 0},load(e){return e===Zn?zi():void 0}}}a(Gi,"browserProbePlugin");function so(e){let t={console:[],page:[]};return e.on("console",r=>{r.type()!=="error"||b$1(r.text())||t.console.push(r.text());}),e.on("pageerror",r=>{b$1(r.message)||t.page.push(r.message);}),t}a(so,"collectPageErrors");async function Ke(e){return e.evaluate(()=>{let t=globalThis,r=t.__threeBlocksSmoke;if(r!==void 0)return {source:"public",value:r};let n=t.__threeBlocksBrowserTools;if(n&&typeof n=="object"){let o=Reflect.get(n,"smoke");if(o!==void 0)return {source:"public",value:o}}return {source:t.__threeBlocks===void 0?"missing":"legacy",value:t.__threeBlocks??null}})}a(Ke,"readBridge");async function Ki(e){return e.evaluate(()=>{let t=globalThis,r=t.document.querySelector("[data-tb-fatal-code]"),n=r?.getAttribute("data-tb-fatal-code")??"",o=(r?.title||r?.textContent||"")?.replace(/^three-blocks — error:\s*/u,"").replace(/^Uncaught(?:\s+Error)?:\s*/u,"").trim()??"";return {fatalVisible:r!==null&&/^[a-z][a-z0-9-]{0,63}$/u.test(n)&&t.getComputedStyle(r).display!=="none"&&t.getComputedStyle(r).visibility!=="hidden",code:n.length>0?n:null,detail:o.length>0?o:null}})}a(Ki,"readCompatibilityFailure");async function Yn(e){return e.evaluate(()=>{let t=globalThis,r=t.__threeBlocksTextFallbackProbe?.states,n=Array.isArray(r)?r.filter(a=>typeof a=="string").slice(0,32):[],o=n.indexOf("fallback"),s=n.lastIndexOf("ready"),i=[...t.document.querySelectorAll("[data-canvas-text]")];return {states:n,fallbackObserved:o>=0,recovered:o>=0&&s>o,visibleElements:i.filter(a=>a.getAttribute("data-canvas-text-fallback")!=="false").length,totalElements:i.length}})}a(Yn,"readTextFallbackEvidence");async function Yt(e){return e.evaluate(()=>{let t=globalThis,r=t.__threeBlocksSmoke?.diagnostics?.shaderMode;return {snapshots:Math.max(0,Number(t.__threeBlocksSmoke?.stats?.snapshots)||0),textures:Math.max(0,Number(t.__threeBlocksSmoke?.stats?.textures)||0),shaderMode:r==="precompiled"||r==="live"?r:null,mainPanels:t.document.querySelector("[data-three-blocks-stats-mode]")!==null}})}a(Yt,"readBrowserRuntimeObservation");async function qi(e,t){let r=Buffer.from(`${JSON.stringify(t,null,2)}
247
- `,"utf8");if(r.byteLength>Tt)throw new Error(`Runtime status receipt exceeds ${Tt} bytes.`);let n=F.join(e,...Xt.split("/")),o=F.dirname(n);await mkdir(o,{recursive:true});let s=await realpath(o),i=F.relative(e,s);if(i.startsWith("..")||F.isAbsolute(i))throw new Error("Runtime status receipt directory escapes the project root.");let a=F.join(s,`.status.${process.pid}.${randomUUID()}.tmp`);try{await writeFile(a,r,{flag:"wx",mode:384}),await rename(a,n);}finally{await rm(a,{force:true});}}a(qi,"writeRuntimeStatusReceipt");async function Qt(e,t,r){await e.waitForFunction(n=>{let o=globalThis,s=o.__threeBlocksSmoke,i=s!==void 0;if(s===void 0){let l=o.__threeBlocksBrowserTools;l&&typeof l=="object"&&(s=Reflect.get(l,"smoke")),i=s!==void 0;}if(s===void 0&&(s=o.__threeBlocks),!s||typeof s!="object")return false;let a=s;if(i&&a.protocolVersion!==1)return false;let c=a.readiness&&typeof a.readiness=="object"?a.readiness:a,u=a.worker;return (i&&u&&typeof u=="object"?Reflect.get(u,"offscreenCanvas")===true&&Reflect.get(u,"visible")===true:u===true)&&c.workerReady===true&&(c.assetsReady===true||c.loadEnd===true)&&c.compileEnd===true&&c.firstFrame===true&&(!n||c.textReady===true)},t,{timeout:r});}a(Qt,"waitForLifecycle");async function Qn(e,t){await e.waitForFunction(()=>{let n=[...globalThis.document.querySelectorAll("[data-canvas-text]")];return n.length>0&&n.every(o=>o.getAttribute("data-canvas-text-fallback")==="true")},void 0,{timeout:Math.min(t,3e4)});}a(Qn,"waitForTextFallback");async function Mr(e,t,r){await t();let n=250,o=performance.now()+Math.min(r,5e3),s=performance.now(),i=a(()=>{s=performance.now();},"navigated");e.on("framenavigated",i);try{for(;performance.now()-s<n;){if(performance.now()>=o)throw new Error("Timed out waiting for startup navigation to settle.");await e.waitForTimeout(25);}}finally{e.off("framenavigated",i);}await t();}a(Mr,"waitForStableReadiness");async function eo(e,t){return await e(),t()}a(eo,"readAfterInitialReadiness");function Xi(e,t,r){if(!a$1(e)||typeof e.route!="string"||!e.route.startsWith("/")||e.route.length>2048||!Number.isSafeInteger(e.bytes)||Number(e.bytes)<=0||typeof e.contentType!="string"||e.contentType.length>256)throw new Error(`Browser codec ${t} route ${r} is invalid.`);let n=e.route.endsWith(".wasm")?"application/wasm":"javascript";if(!e.contentType.includes(n))throw new Error(`Browser codec route ${e.route} returned unexpected content-type ${JSON.stringify(e.contentType)}.`);return {route:e.route,bytes:Number(e.bytes),contentType:e.contentType}}a(Xi,"parseCodecRoute");function Ge(e,t,r){if(typeof e!="string"||!t.includes(e))throw new Error(`${r} is invalid.`);return e}a(Ge,"literal");function _r(e,t){if(!Number.isSafeInteger(e)||Number(e)<0)throw new Error(`${t} is invalid.`);return Number(e)}a(_r,"nonnegativeInteger");function Ji(e){if(!a$1(e)||e.schemaVersion!==2||!a$1(e.renderer)||!a$1(e.assets)||!a$1(e.shaders)||!a$1(e.stats)||typeof e.output!="string"||e.output.length===0||e.output.length>2048||typeof e.threeVersion!="string"||e.threeVersion.length===0||e.threeVersion.length>128)throw new Error("Browser build receipt is invalid.");if(e.renderer.owner!=="worker"||e.renderer.api!=="WebGPU"||e.renderer.fallback!=="WebGL")throw new Error("Browser build receipt does not declare the worker-owned WebGPU/WebGL renderer contract.");let t=e.text;if(t!==void 0&&(!a$1(t)||!["ready","generating","fallback","missing","invalid"].includes(String(t.state))))throw new Error("Browser build receipt text state is invalid.");return {schemaVersion:2,renderer:{owner:"worker",api:"WebGPU",fallback:"WebGL"},assets:{draco:Ge(e.assets.draco,["ready","disabled"],"Browser build receipt Draco state"),ktx2:Ge(e.assets.ktx2,["ready","disabled"],"Browser build receipt KTX2 state"),meshopt:Ge(e.assets.meshopt,["lazy","disabled"],"Browser build receipt Meshopt state")},shaders:{state:Ge(e.shaders.state,["fresh","stale","invalid","missing"],"Browser build receipt shader state"),mode:Ge(e.shaders.mode,["precompiled","live"],"Browser build receipt shader mode"),pipelines:_r(e.shaders.pipelines,"Browser build receipt shader pipeline count")},...t===void 0?{}:{text:{state:Ge(t.state,["ready","generating","fallback","missing","invalid"],"Browser build receipt text state"),atlases:_r(t.atlases,"Browser build receipt text atlas count"),glyphs:_r(t.glyphs,"Browser build receipt text glyph count")}},stats:{enabled:e.stats.enabled===true,production:e.stats.production===true},output:e.output,threeVersion:e.threeVersion}}a(Ji,"parseBuildReceipt");var Cr=Object.freeze({sceneIdentityReplaced:false,stateRestored:false,assetIdentityPreserved:false,assetReferencesPreserved:false,statsIdentityPreserved:false,statsSequenceAdvanced:false,shaderInvalidated:false,rollbackPreserved:false}),Bt=Object.freeze({requested:false,appIdentityStable:false,contentIdentityStable:false,canvasReplaced:false,workerIdentityChanged:false,generationAdvanced:false,restartCountAdvanced:false,stateReplayed:false,readinessRestored:false,shaderModeStable:false,statsSnapshotsAdvanced:false,statsTextureTransferred:false,statsTextureStopped:false,error:null}),Zi=Object.freeze(["three-blocks/assets","three-blocks/hmr","three-blocks/runtime","three-blocks/shaders","three-blocks/stats","three-blocks/text","three-blocks/worker"]);function Yi(e){if(!a$1(e))throw new Error("Browser HMR evidence is invalid.");let t={...Cr};for(let r of Object.keys(t)){if(e[r]!==true)throw new Error(`Browser HMR evidence ${r} did not pass.`);t[r]=true;}return t}a(Yi,"parseHmrEvidence");function Qi(e){if(!a$1(e)||typeof e.textEnabled!="boolean"||!Array.isArray(e.codecs)||e.codecs.length!==3)throw new Error("Browser codec probe returned an invalid payload.");let t=["draco","ktx2","meshopt"],r=e.codecs.map((n,o)=>{let s=t[o];if(s===void 0||!a$1(n)||n.name!==s||!["ready","disabled","error"].includes(String(n.state))||!Array.isArray(n.routes)||n.error!==null&&typeof n.error!="string")throw new Error(`Browser codec probe entry ${o} is invalid.`);let i=n.state,a=n.routes.map((u,f)=>Xi(u,s,f)),c=Ge(n.evidence,["delivery","decoder-ready","text-atlas-decoded","asset-manager-decoded"],`Browser codec ${s} evidence`);if(typeof n.decoded!="boolean"||n.blocker!==null&&typeof n.blocker!="string")throw new Error(`Browser codec ${s} decode evidence is invalid.`);if(i==="ready"&&s!=="meshopt"&&a.length===0)throw new Error(`Browser codec ${s} exposed no routes.`);if(i==="error"&&(typeof n.error!="string"||n.error.length===0||n.error.length>8192))throw new Error(`Browser codec ${s} has an invalid error.`);return {name:s,state:i,routes:a,decoded:n.decoded,evidence:c,blocker:typeof n.blocker=="string"?n.blocker:null,error:typeof n.error=="string"?n.error:null}});return {textEnabled:e.textEnabled,codecs:r,receipt:Ji(e.receipt),hmrEvidence:Yi(e.hmrEvidence)}}a(Qi,"parseCodecProbe");async function ed(e){let t=await e.evaluate(async r=>{let n=await import(r);if(typeof n.probe!="function")throw new Error("Browser smoke probe module has no probe() export.");return await n.probe()},Wi);return Qi(t)}a(ed,"probeCodecs");function td(e){return e instanceof Error&&/execution context was destroyed|most likely because of a navigation/iu.test(e.message)}a(td,"isNavigationRace");async function rd(e,t,r){for(let n=0;n<3;n++)try{return await ed(e)}catch(o){if(!td(o)||n===2)throw o;await Mr(e,t,r);}throw new Error("Browser codec probe did not complete.")}a(rd,"probeCodecsAfterNavigation");async function Or(e){return e.evaluate(()=>{let t=globalThis,r=0;for(let n of t.document.querySelectorAll("canvas")){if(n.width<=0||n.height<=0)continue;let o=null;try{o=n.getContext("2d");}catch{continue}if(o)try{let s=o.getImageData(0,0,n.width,n.height).data,i=0,a=0;for(let c=0;c+2<s.length;c+=4)i+=Math.max(s[c]??0,s[c+1]??0,s[c+2]??0),a+=1;a>0&&(r=Math.max(r,i/a));}catch{}}return r})}a(Or,"panelLuminance");function nd(e){return e.split(F.sep).join("/")}a(nd,"portablePath");async function od(e){return e.evaluate(()=>{let r=globalThis.__threeBlocksSmokeProbe;if(!r||typeof r!="object")return 0;let n=Reflect.get(r,"after");return typeof n=="number"&&Number.isSafeInteger(n)?n:0})}a(od,"hmrEventCount");async function sd(e,t,r,n,o,s,i){if(n===void 0)return {requested:false,module:null,dispatched:false,acknowledged:false,lifecycleStable:true,sourceUnchanged:true,evidenceSource:"public-runtime-browser-probe",evidence:i,restart:Bt,error:null};let a=nd(n),c=false,u=false,f$1=false,l$1=false;try{let m=await l(r,F.join(r,n),d$1.semanticInput,"HMR scene module"),p=f(m.data),h=e.moduleGraph.getModulesByFile(m.path);if(!h||h.size===0)throw new Error(`HMR scene module ${JSON.stringify(a)} is not in Vite's module graph.`);let y=await od(t);e.watcher.emit("change",m.path),c=!0,await t.waitForFunction(b=>{let g=globalThis.__threeBlocksSmokeProbe;return !!(g&&typeof g=="object"&&Number(Reflect.get(g,"after"))>b)},y,{timeout:Math.min(o,3e4)}),u=!0,await Qt(t,s,Math.min(o,3e4)),f$1=!0;let w=await l(r,m.path,d$1.semanticInput,"HMR scene module");if(l$1=f(w.data)===p,!l$1)throw new Error("HMR scene source changed during the smoke run.");return {requested:!0,module:a,dispatched:c,acknowledged:u,lifecycleStable:f$1,sourceUnchanged:l$1,evidenceSource:"public-runtime-browser-probe",evidence:i,restart:Bt,error:null}}catch(m){return {requested:true,module:a,dispatched:c,acknowledged:u,lifecycleStable:f$1,sourceUnchanged:l$1,evidenceSource:"public-runtime-browser-probe",evidence:i,restart:Bt,error:m instanceof Error?m.message:String(m)}}}a(sd,"exerciseHmr");async function ad(e,t,r,n){let o="stats-baseline";try{let s=await e.evaluate(()=>{let l=globalThis;return new URL(l.location.href).searchParams.get("tbStats")==="1"});s&&(o="stats-query-boot",await e.waitForFunction(()=>globalThis.__threeBlocksSmoke?.stats?.panelVisible===!0,void 0,{timeout:Math.min(t,3e4)}));let i=await e.evaluate(()=>{let l=globalThis;return {panelVisible:l.__threeBlocksSmoke?.stats?.panelVisible,textures:Number(l.__threeBlocksSmoke?.stats?.textures)||0,panelAttached:l.document.querySelector("[data-three-blocks-stats-mode]")!==null}});if(!s&&(i.panelVisible!==!1||i.textures!==0||i.panelAttached))throw new Error("Generated stats panel is not default-off before browser-smoke activation.");o="stats-enable",await e.evaluate(async()=>{let m=globalThis.__threeBlocksSmoke?.stats;if(!m||typeof m.setPanelVisible!="function"||typeof m.setPanelMode!="function")throw new Error("Generated stats panel controls are unavailable.");if(await Reflect.apply(m.setPanelVisible,m,[!0])!==!0)throw new Error("Generated stats panel could not be enabled.");if(await Reflect.apply(m.setPanelMode,m,["expanded"])!==!0)throw new Error("Generated stats panel could not be expanded.")}),o="stats-expanded",await e.waitForFunction(()=>{let l=globalThis;return l.__threeBlocksSmoke?.stats?.panelVisible===!0&&l.document.querySelector('[data-three-blocks-stats-mode="expanded"]')!==null},void 0,{timeout:Math.min(t,3e4)}),o="stats-initial-texture",await e.waitForFunction(l=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)>l,i.textures,{timeout:Math.min(t,3e4)}),o="snapshot";let a=await e.evaluate(()=>{let l=globalThis,m=l.__threeBlocksSmoke,p=l.document.querySelector("#app"),h=l.document.querySelector("#scene"),y=l.document.querySelector("main")??p;if(!m||typeof m.restartWorker!="function"||!p||!h||!y||typeof m.diagnostics?.workerId!="string")throw new Error("Generated worker restart diagnostics are unavailable.");return l.__threeBlocksWorkerRestartProbe={app:p,content:y,canvas:h},{workerId:m.diagnostics.workerId,generation:m.worker.generation,restartCount:m.restart.count,snapshots:m.stats.snapshots,textures:m.stats.textures}});o="restart-call",await e.evaluate(async()=>{let l=globalThis,m=l.__threeBlocksSmoke?.restartWorker;if(typeof m!="function")throw new Error("Generated restartWorker() is unavailable.");await Reflect.apply(m,l.__threeBlocksSmoke,["browser smoke worker restart"]);}),o="restart-readiness",await e.waitForFunction(l=>{let p=globalThis.__threeBlocksSmoke,h=p?.readiness;return typeof p?.diagnostics?.workerId=="string"&&p.diagnostics.workerId!==l.workerId&&Number(p.worker?.generation)>l.generation&&p.restart?.stateReplayed===!0&&h?.workerReady===!0&&h.assetsReady===!0&&h.compileEnd===!0&&h.firstFrame===!0&&(!l.textEnabled||h.textReady===!0)},{workerId:a.workerId,generation:a.generation,textEnabled:r},{timeout:Math.min(t,45e3)}),o="stats-snapshot",await e.waitForFunction(l=>Number(globalThis.__threeBlocksSmoke?.stats?.snapshots)>l,a.snapshots,{timeout:Math.min(t,3e4)}),o="stats-texture",await e.waitForFunction(l=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)>l,a.textures,{timeout:Math.min(t,3e4)});let c=await e.evaluate(l=>{let m=globalThis,p=m.__threeBlocksSmoke,h=m.__threeBlocksWorkerRestartProbe,y=p?.readiness;if(!p||!h||!y)throw new Error("Generated restart evidence disappeared.");return {requested:!0,appIdentityStable:h.app===m.document.querySelector("#app"),contentIdentityStable:h.content===(m.document.querySelector("main")??m.document.querySelector("#app")),canvasReplaced:p.restart.canvasReplaced&&h.canvas!==m.document.querySelector("#scene"),workerIdentityChanged:typeof p.diagnostics?.workerId=="string"&&p.diagnostics.workerId!==l.workerId,generationAdvanced:p.worker.generation===l.generation+1,restartCountAdvanced:p.restart.count===l.restartCount+1,stateReplayed:p.restart.stateReplayed&&p.restart.lastReason==="browser smoke worker restart",readinessRestored:y.workerReady===!0&&y.assetsReady===!0&&y.compileEnd===!0&&y.firstFrame===!0&&(!l.textEnabled||y.textReady===!0),shaderModeStable:p.diagnostics?.shaderMode===l.expectedShaderMode,statsSnapshotsAdvanced:p.stats.snapshots>l.snapshots,statsTextureTransferred:p.stats.textures>l.textures,statsTextureStopped:!1,error:null}},{...a,textEnabled:r,expectedShaderMode:n});o="stats-disable",await e.evaluate(async()=>{let m=globalThis.__threeBlocksSmoke?.stats;if(!m||typeof m.setPanelVisible!="function")throw new Error("Generated stats visibility control disappeared before disable.");if(await Reflect.apply(m.setPanelVisible,m,[!1])!==!0)throw new Error("Generated stats panel could not be disabled.")}),await e.waitForFunction(()=>globalThis.__threeBlocksSmoke?.stats?.panelVisible===!1,void 0,{timeout:Math.min(t,3e4)}),await e.waitForTimeout(750);let u=await e.evaluate(()=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)||0);await e.waitForTimeout(1100);let f=await e.evaluate(()=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)||0);if(f!==u)throw new Error(`Stats textures advanced after disable (${u} -> ${f}).`);return {...c,statsTextureStopped:!0}}catch(s){return {...Bt,requested:true,error:`${o}: ${s instanceof Error?s.message:String(s)}`}}}a(ad,"exerciseWorkerRestart");function dt(e){return [...new Set(e)].sort((t,r)=>t.localeCompare(r))}a(dt,"sortedUnique");function id(e,t,r){let n=dt(e),o=dt(t),s=r?dt([...n,...o].filter(a=>/MSDF atlases are missing code points:/iu.test(a))):[],i=new Set(s);return {console:n.filter(a=>!i.has(a)),page:o.filter(a=>!i.has(a)),resolved:s}}a(id,"classifyRecoveredTextErrors");function dd(e){return e.replace(/\u001b\[[0-?]*[ -/]*[@-~]/gu,"")}a(dd,"stripTerminalControl");function cd(e,t,r){let n=e.config.base.startsWith("/")?e.config.base:"/";return new URL(r.replace(/^\/+/,""),`${t}${n.endsWith("/")?n:`${n}/`}`).href}a(cd,"projectUrl");async function ld(e){let{chromium:t,vite:{createLogger:r,createServer:n}}=await ro();if(e.forceWebgl===true&&e.unsupportedWorker===true)throw new Error("Browser smoke forceWebgl and unsupportedWorker modes are mutually exclusive.");if(e.unsupportedWorker===true&&e.expectTextGenerationFailure===true)throw new Error("Browser smoke unsupportedWorker and expectTextGenerationFailure modes are mutually exclusive.");let o=await realpath(e.root),s=oo(e.route),i=je(e.timeoutMs,"Browser smoke timeoutMs",1e3,15*6e4,to),a$1=je(e.settleMs,"Browser smoke settleMs",0,1e4,1e3),c$1={width:je(e.viewport?.width,"Browser smoke viewport width",64,8192,1024),height:je(e.viewport?.height,"Browser smoke viewport height",64,8192,640)},u=no(e.minimumLuminance,"Browser smoke minimumLuminance",0,255,2),f,l,m,p,h=false,y=Re(void 0,false),w=[],b=null,k=Cr,g={requested:e.hmrModule!==void 0,module:e.hmrModule??null,dispatched:false,acknowledged:false,lifecycleStable:e.hmrModule===void 0,sourceUnchanged:e.hmrModule===void 0,evidenceSource:"public-runtime-browser-probe",evidence:Cr,restart:Bt,error:e.hmrModule===void 0?null:"HMR was not reached."},P=false,R=false,_={fatalVisible:false,code:null,detail:null},C={states:[],fallbackObserved:false,recovered:false,visibleElements:0,totalElements:0},S={snapshots:0,textures:0,shaderMode:null,mainPanels:false},B=[],T=0,x=0,O={console:[],page:[]},V,q=process.env.PATH;process.env.PATH=[F.join(o,"node_modules",".bin"),q].filter(Boolean).join(F.delimiter);try{let G=r("silent");G.warn=ce=>{B.push(dd(ce));},f=await n({root:o,logLevel:"silent",customLogger:G,plugins:[Gi()],optimizeDeps:{force:!0,include:[...Zi]},server:{host:"127.0.0.1",port:0,strictPort:!1}}),await f.listen();let K=f.httpServer?.address();if(!K||typeof K=="string")throw new Error("Vite did not expose an ephemeral TCP address.");let ne=`http://127.0.0.1:${K.port}`;l=await t.launch({headless:d(e.headed===!0),args:[...c()]}),m=await l.newContext({viewport:c$1}),await m.addInitScript({content:`
246
+ `}a(Ki,"browserProbeSource");function qi(){return {name:"three-blocks:browser-smoke-probe",enforce:"post",resolveId(e){return e===Fr?Zn:void 0},load(e){return e===Zn?Ki():void 0}}}a(qi,"browserProbePlugin");function so(e){let t={console:[],page:[]};return e.on("console",r=>{r.type()!=="error"||b$1(r.text())||t.console.push(r.text());}),e.on("pageerror",r=>{b$1(r.message)||t.page.push(r.message);}),t}a(so,"collectPageErrors");async function Ke(e){return e.evaluate(()=>{let t=globalThis,r=t.__threeBlocksSmoke;if(r!==void 0)return {source:"public",value:r};let n=t.__threeBlocksBrowserTools;if(n&&typeof n=="object"){let o=Reflect.get(n,"smoke");if(o!==void 0)return {source:"public",value:o}}return {source:t.__threeBlocks===void 0?"missing":"legacy",value:t.__threeBlocks??null}})}a(Ke,"readBridge");async function Xi(e){return e.evaluate(()=>{let t=globalThis,r=t.document.querySelector("[data-tb-fatal-code]"),n=r?.getAttribute("data-tb-fatal-code")??"",o=(r?.title||r?.textContent||"")?.replace(/^three-blocks — error:\s*/u,"").replace(/^Uncaught(?:\s+Error)?:\s*/u,"").trim()??"";return {fatalVisible:r!==null&&/^[a-z][a-z0-9-]{0,63}$/u.test(n)&&t.getComputedStyle(r).display!=="none"&&t.getComputedStyle(r).visibility!=="hidden",code:n.length>0?n:null,detail:o.length>0?o:null}})}a(Xi,"readCompatibilityFailure");async function Yn(e){return e.evaluate(()=>{let t=globalThis,r=t.__threeBlocksTextFallbackProbe?.states,n=Array.isArray(r)?r.filter(a=>typeof a=="string").slice(0,32):[],o=n.indexOf("fallback"),s=n.lastIndexOf("ready"),i=[...t.document.querySelectorAll("[data-canvas-text]")];return {states:n,fallbackObserved:o>=0,recovered:o>=0&&s>o,visibleElements:i.filter(a=>a.getAttribute("data-canvas-text-fallback")!=="false").length,totalElements:i.length}})}a(Yn,"readTextFallbackEvidence");async function Zt(e){return e.evaluate(()=>{let t=globalThis,r=t.__threeBlocksSmoke?.diagnostics?.shaderMode;return {snapshots:Math.max(0,Number(t.__threeBlocksSmoke?.stats?.snapshots)||0),textures:Math.max(0,Number(t.__threeBlocksSmoke?.stats?.textures)||0),shaderMode:r==="precompiled"||r==="live"?r:null,mainPanels:t.document.querySelector("[data-three-blocks-stats-mode]")!==null}})}a(Zt,"readBrowserRuntimeObservation");async function Ji(e,t){let r=Buffer.from(`${JSON.stringify(t,null,2)}
247
+ `,"utf8");if(r.byteLength>Et)throw new Error(`Runtime status receipt exceeds ${Et} bytes.`);let n=F.join(e,...qt.split("/")),o=F.dirname(n);await mkdir(o,{recursive:true});let s=await realpath(o),i=F.relative(e,s);if(i.startsWith("..")||F.isAbsolute(i))throw new Error("Runtime status receipt directory escapes the project root.");let a=F.join(s,`.status.${process.pid}.${randomUUID()}.tmp`);try{await writeFile(a,r,{flag:"wx",mode:384}),await rename(a,n);}finally{await rm(a,{force:true});}}a(Ji,"writeRuntimeStatusReceipt");async function Yt(e,t,r){await e.waitForFunction(n=>{let o=globalThis,s=o.__threeBlocksSmoke,i=s!==void 0;if(s===void 0){let u=o.__threeBlocksBrowserTools;u&&typeof u=="object"&&(s=Reflect.get(u,"smoke")),i=s!==void 0;}if(s===void 0&&(s=o.__threeBlocks),!s||typeof s!="object")return false;let a=s;if(i&&a.protocolVersion!==1)return false;let c=a.readiness&&typeof a.readiness=="object"?a.readiness:a,l=a.worker;return (i&&l&&typeof l=="object"?Reflect.get(l,"offscreenCanvas")===true&&Reflect.get(l,"visible")===true:l===true)&&c.workerReady===true&&(c.assetsReady===true||c.loadEnd===true)&&c.compileEnd===true&&c.firstFrame===true&&(!n||c.textReady===true)},t,{timeout:r});}a(Yt,"waitForLifecycle");async function Qn(e,t){await e.waitForFunction(()=>{let n=[...globalThis.document.querySelectorAll("[data-canvas-text]")];return n.length>0&&n.every(o=>o.getAttribute("data-canvas-text-fallback")==="true")},void 0,{timeout:Math.min(t,3e4)});}a(Qn,"waitForTextFallback");async function _r(e,t,r){await t();let n=250,o=performance.now()+Math.min(r,5e3),s=performance.now(),i=a(()=>{s=performance.now();},"navigated");e.on("framenavigated",i);try{for(;performance.now()-s<n;){if(performance.now()>=o)throw new Error("Timed out waiting for startup navigation to settle.");await e.waitForTimeout(25);}}finally{e.off("framenavigated",i);}await t();}a(_r,"waitForStableReadiness");async function eo(e,t){return await e(),t()}a(eo,"readAfterInitialReadiness");function Zi(e,t,r){if(!a$1(e)||typeof e.route!="string"||!e.route.startsWith("/")||e.route.length>2048||!Number.isSafeInteger(e.bytes)||Number(e.bytes)<=0||typeof e.contentType!="string"||e.contentType.length>256)throw new Error(`Browser codec ${t} route ${r} is invalid.`);let n=e.route.endsWith(".wasm")?"application/wasm":"javascript";if(!e.contentType.includes(n))throw new Error(`Browser codec route ${e.route} returned unexpected content-type ${JSON.stringify(e.contentType)}.`);return {route:e.route,bytes:Number(e.bytes),contentType:e.contentType}}a(Zi,"parseCodecRoute");function Ge(e,t,r){if(typeof e!="string"||!t.includes(e))throw new Error(`${r} is invalid.`);return e}a(Ge,"literal");function Pr(e,t){if(!Number.isSafeInteger(e)||Number(e)<0)throw new Error(`${t} is invalid.`);return Number(e)}a(Pr,"nonnegativeInteger");function Yi(e){if(!a$1(e)||e.schemaVersion!==2||!a$1(e.renderer)||!a$1(e.assets)||!a$1(e.shaders)||!a$1(e.stats)||typeof e.output!="string"||e.output.length===0||e.output.length>2048||typeof e.threeVersion!="string"||e.threeVersion.length===0||e.threeVersion.length>128)throw new Error("Browser build receipt is invalid.");if(e.renderer.owner!=="worker"||e.renderer.api!=="WebGPU"||e.renderer.fallback!=="WebGL")throw new Error("Browser build receipt does not declare the worker-owned WebGPU/WebGL renderer contract.");let t=e.text;if(t!==void 0&&(!a$1(t)||!["ready","generating","fallback","missing","invalid"].includes(String(t.state))))throw new Error("Browser build receipt text state is invalid.");return {schemaVersion:2,renderer:{owner:"worker",api:"WebGPU",fallback:"WebGL"},assets:{draco:Ge(e.assets.draco,["ready","disabled"],"Browser build receipt Draco state"),ktx2:Ge(e.assets.ktx2,["ready","disabled"],"Browser build receipt KTX2 state"),meshopt:Ge(e.assets.meshopt,["lazy","disabled"],"Browser build receipt Meshopt state")},shaders:{state:Ge(e.shaders.state,["fresh","stale","invalid","missing"],"Browser build receipt shader state"),mode:Ge(e.shaders.mode,["precompiled","live"],"Browser build receipt shader mode"),pipelines:Pr(e.shaders.pipelines,"Browser build receipt shader pipeline count")},...t===void 0?{}:{text:{state:Ge(t.state,["ready","generating","fallback","missing","invalid"],"Browser build receipt text state"),atlases:Pr(t.atlases,"Browser build receipt text atlas count"),glyphs:Pr(t.glyphs,"Browser build receipt text glyph count")}},stats:{enabled:e.stats.enabled===true,production:e.stats.production===true},output:e.output,threeVersion:e.threeVersion}}a(Yi,"parseBuildReceipt");var Mr=Object.freeze({sceneIdentityReplaced:false,stateRestored:false,assetIdentityPreserved:false,assetReferencesPreserved:false,statsIdentityPreserved:false,statsSequenceAdvanced:false,shaderInvalidated:false,rollbackPreserved:false}),Tt=Object.freeze({requested:false,appIdentityStable:false,contentIdentityStable:false,canvasReplaced:false,workerIdentityChanged:false,generationAdvanced:false,restartCountAdvanced:false,stateReplayed:false,readinessRestored:false,shaderModeStable:false,statsSnapshotsAdvanced:false,statsTextureTransferred:false,statsTextureStopped:false,error:null}),Qi=Object.freeze(["three-blocks/assets","three-blocks/hmr","three-blocks/runtime","three-blocks/shaders","three-blocks/stats","three-blocks/text","three-blocks/worker"]);function ed(e){if(!a$1(e))throw new Error("Browser HMR evidence is invalid.");let t={...Mr};for(let r of Object.keys(t)){if(e[r]!==true)throw new Error(`Browser HMR evidence ${r} did not pass.`);t[r]=true;}return t}a(ed,"parseHmrEvidence");function td(e){if(!a$1(e)||typeof e.textEnabled!="boolean"||!Array.isArray(e.codecs)||e.codecs.length!==3)throw new Error("Browser codec probe returned an invalid payload.");let t=["draco","ktx2","meshopt"],r=e.codecs.map((n,o)=>{let s=t[o];if(s===void 0||!a$1(n)||n.name!==s||!["ready","disabled","error"].includes(String(n.state))||!Array.isArray(n.routes)||n.error!==null&&typeof n.error!="string")throw new Error(`Browser codec probe entry ${o} is invalid.`);let i=n.state,a=n.routes.map((l,f)=>Zi(l,s,f)),c=Ge(n.evidence,["delivery","decoder-ready","text-atlas-decoded","asset-manager-decoded"],`Browser codec ${s} evidence`);if(typeof n.decoded!="boolean"||n.blocker!==null&&typeof n.blocker!="string")throw new Error(`Browser codec ${s} decode evidence is invalid.`);if(i==="ready"&&s!=="meshopt"&&a.length===0)throw new Error(`Browser codec ${s} exposed no routes.`);if(i==="error"&&(typeof n.error!="string"||n.error.length===0||n.error.length>8192))throw new Error(`Browser codec ${s} has an invalid error.`);return {name:s,state:i,routes:a,decoded:n.decoded,evidence:c,blocker:typeof n.blocker=="string"?n.blocker:null,error:typeof n.error=="string"?n.error:null}});return {textEnabled:e.textEnabled,codecs:r,receipt:Yi(e.receipt),hmrEvidence:ed(e.hmrEvidence)}}a(td,"parseCodecProbe");async function rd(e){let t=await e.evaluate(async r=>{let n=await import(r);if(typeof n.probe!="function")throw new Error("Browser smoke probe module has no probe() export.");return await n.probe()},Gi);return td(t)}a(rd,"probeCodecs");function nd(e){return e instanceof Error&&/execution context was destroyed|most likely because of a navigation/iu.test(e.message)}a(nd,"isNavigationRace");async function od(e,t,r){for(let n=0;n<3;n++)try{return await rd(e)}catch(o){if(!nd(o)||n===2)throw o;await _r(e,t,r);}throw new Error("Browser codec probe did not complete.")}a(od,"probeCodecsAfterNavigation");async function Cr(e){return e.evaluate(()=>{let t=globalThis,r=0;for(let n of t.document.querySelectorAll("canvas")){if(n.width<=0||n.height<=0)continue;let o=null;try{o=n.getContext("2d");}catch{continue}if(o)try{let s=o.getImageData(0,0,n.width,n.height).data,i=0,a=0;for(let c=0;c+2<s.length;c+=4)i+=Math.max(s[c]??0,s[c+1]??0,s[c+2]??0),a+=1;a>0&&(r=Math.max(r,i/a));}catch{}}return r})}a(Cr,"panelLuminance");function sd(e){return e.split(F.sep).join("/")}a(sd,"portablePath");async function ad(e){return e.evaluate(()=>{let r=globalThis.__threeBlocksSmokeProbe;if(!r||typeof r!="object")return 0;let n=Reflect.get(r,"after");return typeof n=="number"&&Number.isSafeInteger(n)?n:0})}a(ad,"hmrEventCount");async function id(e,t,r,n,o,s,i){if(n===void 0)return {requested:false,module:null,dispatched:false,acknowledged:false,lifecycleStable:true,sourceUnchanged:true,evidenceSource:"public-runtime-browser-probe",evidence:i,restart:Tt,error:null};let a=sd(n),c=false,l$1=false,f$1=false,u=false;try{let m=await l(r,F.join(r,n),d$1.semanticInput,"HMR scene module"),p=f(m.data),h=e.moduleGraph.getModulesByFile(m.path);if(!h||h.size===0)throw new Error(`HMR scene module ${JSON.stringify(a)} is not in Vite's module graph.`);let y=await ad(t);e.watcher.emit("change",m.path),c=!0,await t.waitForFunction(b=>{let g=globalThis.__threeBlocksSmokeProbe;return !!(g&&typeof g=="object"&&Number(Reflect.get(g,"after"))>b)},y,{timeout:Math.min(o,3e4)}),l$1=!0,await Yt(t,s,Math.min(o,3e4)),f$1=!0;let w=await l(r,m.path,d$1.semanticInput,"HMR scene module");if(u=f(w.data)===p,!u)throw new Error("HMR scene source changed during the smoke run.");return {requested:!0,module:a,dispatched:c,acknowledged:l$1,lifecycleStable:f$1,sourceUnchanged:u,evidenceSource:"public-runtime-browser-probe",evidence:i,restart:Tt,error:null}}catch(m){return {requested:true,module:a,dispatched:c,acknowledged:l$1,lifecycleStable:f$1,sourceUnchanged:u,evidenceSource:"public-runtime-browser-probe",evidence:i,restart:Tt,error:m instanceof Error?m.message:String(m)}}}a(id,"exerciseHmr");async function dd(e,t,r,n){let o="stats-baseline";try{let s=await e.evaluate(()=>{let u=globalThis;return new URL(u.location.href).searchParams.get("tbStats")==="1"});s&&(o="stats-query-boot",await e.waitForFunction(()=>globalThis.__threeBlocksSmoke?.stats?.panelVisible===!0,void 0,{timeout:Math.min(t,3e4)}));let i=await e.evaluate(()=>{let u=globalThis;return {panelVisible:u.__threeBlocksSmoke?.stats?.panelVisible,textures:Number(u.__threeBlocksSmoke?.stats?.textures)||0,panelAttached:u.document.querySelector("[data-three-blocks-stats-mode]")!==null}});if(!s&&(i.panelVisible!==!1||i.textures!==0||i.panelAttached))throw new Error("Generated stats panel is not default-off before browser-smoke activation.");o="stats-enable",await e.evaluate(async()=>{let m=globalThis.__threeBlocksSmoke?.stats;if(!m||typeof m.setPanelVisible!="function"||typeof m.setPanelMode!="function")throw new Error("Generated stats panel controls are unavailable.");if(await Reflect.apply(m.setPanelVisible,m,[!0])!==!0)throw new Error("Generated stats panel could not be enabled.");if(await Reflect.apply(m.setPanelMode,m,["expanded"])!==!0)throw new Error("Generated stats panel could not be expanded.")}),o="stats-expanded",await e.waitForFunction(()=>{let u=globalThis;return u.__threeBlocksSmoke?.stats?.panelVisible===!0&&u.document.querySelector('[data-three-blocks-stats-mode="expanded"]')!==null},void 0,{timeout:Math.min(t,3e4)}),o="stats-initial-texture",await e.waitForFunction(u=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)>u,i.textures,{timeout:Math.min(t,3e4)}),o="snapshot";let a=await e.evaluate(()=>{let u=globalThis,m=u.__threeBlocksSmoke,p=u.document.querySelector("#app"),h=u.document.querySelector("#scene"),y=u.document.querySelector("main")??p;if(!m||typeof m.restartWorker!="function"||!p||!h||!y||typeof m.diagnostics?.workerId!="string")throw new Error("Generated worker restart diagnostics are unavailable.");return u.__threeBlocksWorkerRestartProbe={app:p,content:y,canvas:h},{workerId:m.diagnostics.workerId,generation:m.worker.generation,restartCount:m.restart.count,snapshots:m.stats.snapshots,textures:m.stats.textures}});o="restart-call",await e.evaluate(async()=>{let u=globalThis,m=u.__threeBlocksSmoke?.restartWorker;if(typeof m!="function")throw new Error("Generated restartWorker() is unavailable.");await Reflect.apply(m,u.__threeBlocksSmoke,["browser smoke worker restart"]);}),o="restart-readiness",await e.waitForFunction(u=>{let p=globalThis.__threeBlocksSmoke,h=p?.readiness;return typeof p?.diagnostics?.workerId=="string"&&p.diagnostics.workerId!==u.workerId&&Number(p.worker?.generation)>u.generation&&p.restart?.stateReplayed===!0&&h?.workerReady===!0&&h.assetsReady===!0&&h.compileEnd===!0&&h.firstFrame===!0&&(!u.textEnabled||h.textReady===!0)},{workerId:a.workerId,generation:a.generation,textEnabled:r},{timeout:Math.min(t,45e3)}),o="stats-snapshot",await e.waitForFunction(u=>Number(globalThis.__threeBlocksSmoke?.stats?.snapshots)>u,a.snapshots,{timeout:Math.min(t,3e4)}),o="stats-texture",await e.waitForFunction(u=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)>u,a.textures,{timeout:Math.min(t,3e4)});let c=await e.evaluate(u=>{let m=globalThis,p=m.__threeBlocksSmoke,h=m.__threeBlocksWorkerRestartProbe,y=p?.readiness;if(!p||!h||!y)throw new Error("Generated restart evidence disappeared.");return {requested:!0,appIdentityStable:h.app===m.document.querySelector("#app"),contentIdentityStable:h.content===(m.document.querySelector("main")??m.document.querySelector("#app")),canvasReplaced:p.restart.canvasReplaced&&h.canvas!==m.document.querySelector("#scene"),workerIdentityChanged:typeof p.diagnostics?.workerId=="string"&&p.diagnostics.workerId!==u.workerId,generationAdvanced:p.worker.generation===u.generation+1,restartCountAdvanced:p.restart.count===u.restartCount+1,stateReplayed:p.restart.stateReplayed&&p.restart.lastReason==="browser smoke worker restart",readinessRestored:y.workerReady===!0&&y.assetsReady===!0&&y.compileEnd===!0&&y.firstFrame===!0&&(!u.textEnabled||y.textReady===!0),shaderModeStable:p.diagnostics?.shaderMode===u.expectedShaderMode,statsSnapshotsAdvanced:p.stats.snapshots>u.snapshots,statsTextureTransferred:p.stats.textures>u.textures,statsTextureStopped:!1,error:null}},{...a,textEnabled:r,expectedShaderMode:n});o="stats-disable",await e.evaluate(async()=>{let m=globalThis.__threeBlocksSmoke?.stats;if(!m||typeof m.setPanelVisible!="function")throw new Error("Generated stats visibility control disappeared before disable.");if(await Reflect.apply(m.setPanelVisible,m,[!1])!==!0)throw new Error("Generated stats panel could not be disabled.")}),await e.waitForFunction(()=>globalThis.__threeBlocksSmoke?.stats?.panelVisible===!1,void 0,{timeout:Math.min(t,3e4)}),await e.waitForTimeout(750);let l=await e.evaluate(()=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)||0);await e.waitForTimeout(1100);let f=await e.evaluate(()=>Number(globalThis.__threeBlocksSmoke?.stats?.textures)||0);if(f!==l)throw new Error(`Stats textures advanced after disable (${l} -> ${f}).`);return {...c,statsTextureStopped:!0}}catch(s){return {...Tt,requested:true,error:`${o}: ${s instanceof Error?s.message:String(s)}`}}}a(dd,"exerciseWorkerRestart");function dt(e){return [...new Set(e)].sort((t,r)=>t.localeCompare(r))}a(dt,"sortedUnique");function cd(e,t,r){let n=dt(e),o=dt(t),s=r?dt([...n,...o].filter(a=>/MSDF atlases are missing code points:/iu.test(a))):[],i=new Set(s);return {console:n.filter(a=>!i.has(a)),page:o.filter(a=>!i.has(a)),resolved:s}}a(cd,"classifyRecoveredTextErrors");function ld(e){return e.replace(/\u001b\[[0-?]*[ -/]*[@-~]/gu,"")}a(ld,"stripTerminalControl");function ud(e,t,r){let n=e.config.base.startsWith("/")?e.config.base:"/";return new URL(r.replace(/^\/+/,""),`${t}${n.endsWith("/")?n:`${n}/`}`).href}a(ud,"projectUrl");async function md(e){let{chromium:t,vite:{createLogger:r,createServer:n}}=await ro();if(e.forceWebgl===true&&e.unsupportedWorker===true)throw new Error("Browser smoke forceWebgl and unsupportedWorker modes are mutually exclusive.");if(e.unsupportedWorker===true&&e.expectTextGenerationFailure===true)throw new Error("Browser smoke unsupportedWorker and expectTextGenerationFailure modes are mutually exclusive.");let o=await realpath(e.root),s=oo(e.route),i=je(e.timeoutMs,"Browser smoke timeoutMs",1e3,15*6e4,to),a$1=je(e.settleMs,"Browser smoke settleMs",0,1e4,1e3),c$1={width:je(e.viewport?.width,"Browser smoke viewport width",64,8192,1024),height:je(e.viewport?.height,"Browser smoke viewport height",64,8192,640)},l=no(e.minimumLuminance,"Browser smoke minimumLuminance",0,255,2),f,u,m,p,h=false,y=Re(void 0,false),w=[],b=null,x=Mr,g={requested:e.hmrModule!==void 0,module:e.hmrModule??null,dispatched:false,acknowledged:false,lifecycleStable:e.hmrModule===void 0,sourceUnchanged:e.hmrModule===void 0,evidenceSource:"public-runtime-browser-probe",evidence:Mr,restart:Tt,error:e.hmrModule===void 0?null:"HMR was not reached."},T=false,R=false,C={fatalVisible:false,code:null,detail:null},O={states:[],fallbackObserved:false,recovered:false,visibleElements:0,totalElements:0},k={snapshots:0,textures:0,shaderMode:null,mainPanels:false},A=[],v=0,S=0,_={console:[],page:[]},H,q=process.env.PATH;process.env.PATH=[F.join(o,"node_modules",".bin"),q].filter(Boolean).join(F.delimiter);try{let G=r("silent");G.warn=ce=>{A.push(ld(ce));},f=await n({root:o,logLevel:"silent",customLogger:G,plugins:[qi()],optimizeDeps:{force:!0,include:[...Qi]},server:{host:"127.0.0.1",port:0,strictPort:!1}}),await f.listen();let K=f.httpServer?.address();if(!K||typeof K=="string")throw new Error("Vite did not expose an ephemeral TCP address.");let ne=`http://127.0.0.1:${K.port}`;u=await t.launch({headless:d(e.headed===!0),args:[...c()]}),m=await u.newContext({viewport:c$1}),await m.addInitScript({content:`
248
248
  (() => {
249
249
  const key = '__three-blocks-text-fallback-states-v1';
250
250
  let states = [];
@@ -268,12 +268,12 @@ export async function probe() {
268
268
  }
269
269
  } ).observe( document, { subtree: true, childList: true, attributes: true, attributeFilter: [ 'data-three-blocks-text-state' ] } );
270
270
  })();
271
- `}),e.forceWebgl===!0&&await m.addInitScript(()=>{Object.defineProperty(Navigator.prototype,"gpu",{configurable:!0,value:void 0});}),e.unsupportedWorker===!0&&await m.addInitScript(()=>{Object.defineProperty(globalThis,"Worker",{configurable:!0,value:void 0});}),p=await m.newPage();let de=p;if(V=so(p),p.on("console",ce=>{/WebGPU is not available, running under WebGL2 backend/iu.test(ce.text())&&(R=!0);}),await p.goto(cd(f,ne,s),{waitUntil:"domcontentloaded",timeout:i}),e.unsupportedWorker===!0)P=await eo(async()=>{await Mr(de,a(async()=>{await de.waitForFunction(()=>globalThis.document.querySelector("#three-blocks-dev-overlay")?.shadowRoot?.querySelector(".dot")?.dataset.tone==="error",void 0,{timeout:Math.min(i,15e3)});},"waitForFailure"),i);},()=>de.evaluate(()=>"gpu"in navigator&&navigator.gpu!==void 0)),_=await Ki(p),y=Re(await Ke(p),!1);else {let ce=a(()=>e.expectTextGenerationFailure===!0?Qn(de,i):Qt(de,!1,i),"initialReadiness");P=await eo(()=>Mr(de,ce,i),()=>de.evaluate(()=>"gpu"in navigator&&navigator.gpu!==void 0));let j=await rd(p,ce,i);if(h=j.textEnabled,w=j.codecs,b=j.receipt,k=j.hmrEvidence,e.expectTextGenerationFailure===!0){if(!j.textEnabled)throw new Error("Expected text-generation failure mode requires a text-enabled project.");await Qn(p,i);let le=performance.now()+Math.min(i,3e4);for(;!B.some(Me=>/automatic atlas generation failed/iu.test(Me));){if(performance.now()>=le)throw new Error("Timed out waiting for the automatic text-generation failure warning.");await p.waitForTimeout(50);}y=Re(await Ke(p),!0);}else if(await Qt(p,j.textEnabled,i),y=Re(await Ke(p),j.textEnabled),j.textEnabled&&y.textReady&&(w=w.map(le=>le.name==="ktx2"?{...le,decoded:!0,evidence:"text-atlas-decoded",blocker:null}:le)),g=await sd(f,p,o,e.hmrModule,i,j.textEnabled,k),e.hmrModule!==void 0){let le=await ad(p,i,j.textEnabled,j.receipt.shaders.mode);g={...g,restart:le},y=Re(await Ke(p),j.textEnabled);}}a$1>0&&await p.waitForTimeout(a$1),C=await Yn(p),S=await Yt(p);let Je=await p.screenshot({type:"png"});T=Zt(Je),x=await Or(p);}catch(G){if(p!==void 0)try{y=Re(await Ke(p),h),C=await Yn(p),S=await Yt(p);let K=await p.screenshot({type:"png"});T=Zt(K),x=await Or(p);}catch(K){O.page.push(`Failure diagnostics could not be captured: ${K instanceof Error?K.message:String(K)}`);}O.page.push(G instanceof Error?G.message:String(G));}finally{V!==void 0&&(O.console.push(...V.console),O.page.push(...V.page)),await m?.close().catch(ne=>{O.page.push(`Browser context cleanup failed: ${ne instanceof Error?ne.message:String(ne)}`);}),await l?.close().catch(ne=>{O.page.push(`Browser cleanup failed: ${ne instanceof Error?ne.message:String(ne)}`);});let G=f?.httpServer,K=G?Reflect.get(G,"closeAllConnections"):void 0;G&&typeof K=="function"&&Reflect.apply(K,G,[]),await f?.close().catch(ne=>{O.page.push(`Vite cleanup failed: ${ne instanceof Error?ne.message:String(ne)}`);}),q===void 0?delete process.env.PATH:process.env.PATH=q;}let z=Number(T.toFixed(2)),v=Number(x.toFixed(2)),M=T<=u&&x<=u,L=id(O.console,O.page,C.recovered),U=L.console,ee=L.page,X=L.resolved,re=y.worker&&y.workerReady&&y.assetsReady&&y.compileEnd&&y.textReady&&y.firstFrame,se=w.length===3&&w.every(G=>G.state!=="error"),Xe=Object.values(g.evidence).every(Boolean),oe=!g.restart.requested||g.restart.error===null&&[g.restart.appIdentityStable,g.restart.contentIdentityStable,g.restart.canvasReplaced,g.restart.workerIdentityChanged,g.restart.generationAdvanced,g.restart.restartCountAdvanced,g.restart.stateReplayed,g.restart.readinessRestored,g.restart.shaderModeStable,g.restart.statsSnapshotsAdvanced,g.restart.statsTextureTransferred,g.restart.statsTextureStopped].every(Boolean),Ae=!g.requested||g.dispatched&&g.acknowledged&&g.lifecycleStable&&g.sourceUnchanged&&Xe&&oe&&g.error===null,ve=B.filter(G=>/automatic atlas generation failed/iu.test(G)),Se=ve.reduce((G,K)=>G+(K.match(/three-blocks text generate/gu)?.length??0),0),pe=e.expectTextGenerationFailure===true&&h&&C.fallbackObserved&&!C.recovered&&C.totalElements>0&&C.visibleElements===C.totalElements&&ve.length===1&&Se===1,ut=e.unsupportedWorker===true&&_.fatalVisible&&_.code==="render-worker-unavailable"&&!y.workerReady&&!y.compileEnd&&!y.firstFrame,_e=e.unsupportedWorker===true?"unsupported-worker":e.forceWebgl===true?"WebGL-fallback":"WebGPU-first",ye=e.unsupportedWorker===true?"none":re?e.forceWebgl===true||!P?"WebGL":"WebGPU":"unknown",te=y.workerReady&&y.compileEnd&&y.firstFrame,H={schemaVersion:1,command:"browser smoke",passed:e.unsupportedWorker===true?ut:e.expectTextGenerationFailure===true?pe:re&&se&&Ae&&!M&&U.length===0&&ee.length===0,scene:s,lifecycle:y,renderer:{requested:_e,active:ye,navigatorGpu:P,workerOwned:te,fallbackDiagnostic:R},compatibility:{..._,silentMainThreadRenderer:e.unsupportedWorker===true&&(y.compileEnd||y.firstFrame)},receipt:b,textFallback:C,warnings:dt(B),rendering:{luminance:z,panelLuminance:v,threshold:u,blackFrame:M},codecs:w,hmr:g,errors:{console:U,page:ee,resolved:X}};if(H.passed&&e.unsupportedWorker!==true&&e.expectTextGenerationFailure!==true){if(H.receipt===null||H.lifecycle.backend==="unknown"||H.renderer.active!=="WebGPU"&&H.renderer.active!=="WebGL")throw new Error("A successful browser smoke cannot write runtime status without an observed backend and renderer/build receipt.");let G=H.hmr.requested,K=G?Ae:null,ne={schemaVersion:1,observedAt:new Date().toISOString(),worker:{backend:H.lifecycle.backend,renderer:H.renderer.active,protocolVersion:1},assets:{codecs:H.codecs.map(de=>({name:de.name,available:de.state==="ready",decoded:de.decoded})),resources:0},hmr:{capabilities:{scene:true,component:true,assetManifest:true,workerRestart:true},outcome:{attempted:G,succeeded:K,rollbackPreserved:G?H.hmr.evidence.rollbackPreserved:null,workerRestarted:H.hmr.restart.requested&&H.hmr.restart.workerIdentityChanged}},stats:{snapshots:S.snapshots,textures:S.textures,workerProfiler:S.snapshots>0,mainPanels:S.mainPanels},lifecycle:{state:"first frame",workerReady:H.lifecycle.workerReady,assetsReady:H.lifecycle.assetsReady,compiled:H.lifecycle.compileEnd,firstFrame:H.lifecycle.firstFrame},shaders:{mode:S.shaderMode??H.receipt.shaders.mode,pipelines:H.receipt.shaders.pipelines},...H.receipt.text===void 0?{}:{text:{state:H.receipt.text.state,atlases:H.receipt.text.atlases,glyphs:H.receipt.text.glyphs,requiredGlyphs:H.receipt.text.glyphs}},error:null};await qi(o,ne);}return H}a(ld,"runBrowserSmoke");function ud(e){let t=e.lifecycle,r=[`${e.passed?"\u2713":"\u2717"} Browser ${e.scene} \xB7 worker ${t.worker&&t.workerReady?"ready":"failed"} \xB7 assets ${t.assetsReady?"ready":"failed"} \xB7 compile ${t.compileEnd?"ready":"failed"}`,` Renderer ${e.renderer.active} \xB7 ${e.renderer.workerOwned?"worker-owned":e.renderer.requested}`,` Frame ${e.rendering.luminance.toFixed(2)} \xB7 panel ${e.rendering.panelLuminance.toFixed(2)}${e.rendering.blackFrame?" \xB7 black":""}`,` Codecs ${e.codecs.map(n=>`${n.name} ${n.state}${n.decoded?" decoded":""}`).join(" \xB7 ")||"not observed"}`];e.compatibility.fatalVisible&&r.push(` Compatibility ${e.compatibility.detail??"fatal compatibility screen visible"}`),e.textFallback.states.length>0&&r.push(` Text ${e.textFallback.states.join(" \u2192 ")}`),e.hmr.requested&&r.push(` HMR ${e.hmr.acknowledged&&e.hmr.sourceUnchanged&&Object.values(e.hmr.evidence).every(Boolean)?"ready":"failed"} \xB7 ${e.hmr.module??"unknown module"}`),e.hmr.restart.requested&&r.push(` Restart ${e.hmr.restart.error===null&&e.hmr.restart.workerIdentityChanged&&e.hmr.restart.stateReplayed?"ready":"failed"} \xB7 worker/state/stats`);for(let n of e.warnings)r.push(` Warning ${n}`);for(let n of e.errors.console)r.push(` Console ${n}`);for(let n of e.errors.page)r.push(` Page ${n}`);for(let n of e.errors.resolved)r.push(` Recovered ${n}`);e.hmr.error&&r.push(` HMR error ${e.hmr.error}`),e.hmr.restart.error&&r.push(` Restart error ${e.hmr.restart.error}`);for(let n of e.codecs)n.error&&r.push(` ${n.name} error ${n.error}`);return r.join(`
272
- `)}a(ud,"formatBrowserSmokeReport");async function md(e){let{chromium:t,vite:{build:r,preview:n}}=await ro(),o=await realpath(e.root),s=(e.routes===void 0||e.routes.length===0?["/"]:e.routes).map(oo),i=je(e.timeoutMs,"Browser preview timeoutMs",1e3,15*6e4,to),a=je(e.settleMs,"Browser preview settleMs",0,1e4,500),c$1={width:je(e.viewport?.width,"Browser preview viewport width",64,8192,1024),height:je(e.viewport?.height,"Browser preview viewport height",64,8192,640)},u=no(e.minimumLuminance,"Browser preview minimumLuminance",0,255,2),f=e.expectShaders??"precompiled",l=e.text===true,m=[],p,h,y=process.env.PATH;process.env.PATH=[F.join(o,"node_modules",".bin"),y].filter(Boolean).join(F.delimiter);try{await r({root:o,logLevel:"warn",...e.buildMode===void 0?{}:{mode:e.buildMode}}),p=await n({root:o,logLevel:"warn",preview:{host:"127.0.0.1",port:0,strictPort:!1,open:!1}});let w=p.httpServer?.address();if(!w||typeof w=="string")throw new Error("Vite preview did not expose an ephemeral TCP address.");let b=p.config.base.startsWith("/")?p.config.base:"/",k=`http://127.0.0.1:${w.port}${b.endsWith("/")?b:`${b}/`}`;h=await t.launch({headless:d(e.headed===!0),args:[...c()]});for(let g of s){let P=await h.newContext({viewport:c$1}),R=await P.newPage(),_=so(R),C=[],S=Re(void 0,l),B=null,T=0,x=0;try{await R.goto(new URL(g.replace(/^\/+/,""),k).href,{waitUntil:"domcontentloaded",timeout:i}),await Qt(R,l,i),a>0&&await R.waitForTimeout(a),S=Re(await Ke(R),l),B=(await Yt(R)).shaderMode;let v=await R.screenshot({type:"png"});T=Zt(v),x=await Or(R);}catch(v){try{S=Re(await Ke(R),l),B=(await Yt(R)).shaderMode;}catch{}C.push(v instanceof Error?v.message:String(v));}finally{await P.close().catch(v=>{C.push(`Browser context cleanup failed: ${v instanceof Error?v.message:String(v)}`);});}let O=dt(_.console),V=dt([..._.page,...C]),q=S.worker&&S.workerReady&&S.assetsReady&&S.compileEnd&&S.textReady&&S.firstFrame,z=T<=u&&x<=u;m.push({route:g,passed:q&&!z&&B===f&&O.length===0&&V.length===0,lifecycle:S,shaderMode:B,rendering:{luminance:Number(T.toFixed(2)),panelLuminance:Number(x.toFixed(2)),threshold:u,blackFrame:z},errors:{console:O,page:V}});}}finally{await h?.close().catch(()=>{});let w=p?.httpServer,b=w?Reflect.get(w,"closeAllConnections"):void 0;w&&typeof b=="function"&&Reflect.apply(b,w,[]),await p?.close().catch(()=>{}),y===void 0?delete process.env.PATH:process.env.PATH=y;}return {schemaVersion:1,command:"browser preview",passed:m.length>0&&m.every(w=>w.passed),buildMode:e.buildMode??null,expectShaders:f,routes:m}}a(md,"runBrowserPreview");function fd(e){let t=[`${e.passed?"\u2713":"\u2717"} Preview production build${e.buildMode===null?"":` \xB7 --mode ${e.buildMode}`} \xB7 expects shaders ${e.expectShaders}`];for(let r of e.routes){let n=r.lifecycle;t.push(` ${r.passed?"\u2713":"\u2717"} ${r.route} \xB7 worker ${n.worker&&n.workerReady?"ready":"failed"} \xB7 compile ${n.compileEnd?"ready":"failed"} \xB7 shaders ${r.shaderMode??"unobserved"} \xB7 frame ${r.rendering.luminance.toFixed(2)}${r.rendering.blackFrame?" \xB7 black":""}`);for(let o of r.errors.console)t.push(` Console ${o}`);for(let o of r.errors.page)t.push(` Page ${o}`);}return t.join(`
273
- `)}a(fd,"formatBrowserPreviewReport");var go="/__three-blocks/devtools/environment-bake",Sd="/__three-blocks/devtools/environment-bake/upload",Dr="virtual:three-blocks-devtools/environment-bake.ts",co=`\0${Dr}`,kd=`/@id/__x00__${Dr}`,xd="src/assets/environment/room-environment.pmrem.ktx2",Lr=128*1024*1024,Rd=1;async function vd(){try{let[e,t]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,createServer:t.createServer}}catch(e){throw new Error('Environment baking requires the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(vd,"loadEnvironmentBakeBrowserTools");function wo(e,t,r,n,o){let s=e??o;if(!Number.isSafeInteger(s)||s<r||s>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return s}a(wo,"boundedInteger");function Nr(e){let t=wo(e,"Environment cube size",16,1024,256);if((t&t-1)!==0)throw new Error("Environment cube size must be a power of two.");return t}a(Nr,"validateEnvironmentCubeSize");function Ed(){return Rt__default}a(Ed,"zstdFunctions");function Td(e){if(!/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,63}$/u.test(e))throw new Error("Browser reported an invalid Three.js revision.");return e}a(Td,"boundedThreeRevision");function Bd(e){if(e.vkFormat!==VK_FORMAT_R16G16B16A16_SFLOAT)throw new Error("RoomEnvironment bake must be RGBA16F KTX2.");if(e.typeSize!==2)throw new Error("RoomEnvironment RGBA16F KTX2 must use a two-byte component type.");if(e.supercompressionScheme!==KHR_SUPERCOMPRESSION_NONE)throw new Error("Browser RoomEnvironment KTX2 must be uncompressed before deterministic encoding.");if(!Number.isSafeInteger(e.pixelWidth)||e.pixelWidth<=0||e.pixelWidth>8192||!Number.isSafeInteger(e.pixelHeight)||e.pixelHeight<=0||e.pixelHeight>8192||e.pixelDepth!==0||e.layerCount!==0||e.faceCount!==1||e.levels.length!==1||e.levels[0]===void 0)throw new Error("RoomEnvironment KTX2 has invalid CubeUV dimensions or topology.");let t=e.pixelWidth*e.pixelHeight*8;if(!Number.isSafeInteger(t)||t>Lr)throw new Error("RoomEnvironment KTX2 decoded payload exceeds the safety limit.");let r=e.levels[0],n=t+e.pixelHeight*256;if(r.levelData.byteLength<t||r.levelData.byteLength>n||r.levelData.byteLength%8!==0||r.uncompressedByteLength!==r.levelData.byteLength)throw new Error(`RoomEnvironment KTX2 level byte count ${r.levelData.byteLength} is outside the bounded RGBA16F CubeUV layout.`);return e.levels.map(o=>new Uint8Array(o.levelData))}a(Bd,"validateRawContainer");function $d(e,t){return e.byteLength===t.byteLength&&Buffer.from(e).equals(Buffer.from(t))}a($d,"sameBytes");function bo(e,t){let r=Nr(t.cubeSize),n=Td(t.threeRevision);if(e.byteLength===0||e.byteLength>d$1.texture)throw new Error("RoomEnvironment KTX2 input exceeds the bounded texture size.");let o=read(e),s=Bd(o),i=t.compression??"zstd",a=Ed(),c=Rt__default.constants.ZSTD_c_compressionLevel;if(i==="zstd"&&(a.zstdCompressSync===void 0||a.zstdDecompressSync===void 0||c===void 0))throw new Error("This Node.js runtime does not provide deterministic Zstandard support; use --no-zstd explicitly to opt out.");if(o.supercompressionScheme=i==="zstd"?KHR_SUPERCOMPRESSION_ZSTD:KHR_SUPERCOMPRESSION_NONE,o.levelCount=s.length,o.levels=s.map(m=>{let p=i==="zstd"?a.zstdCompressSync?.(m,{params:{[c]:19}}):void 0;return {levelData:p===void 0?m:new Uint8Array(p.buffer,p.byteOffset,p.byteLength),uncompressedByteLength:m.byteLength}}),i==="zstd")for(let m of o.dataFormatDescriptor)m.bytesPlane=[0,0,0,0,0,0,0,0];o.keyValue={KTXorientation:"rd",KTXwriter:`three-blocks RoomEnvironment \xB7 three r${n}`};let u=write(o,{keepWriter:true});if(u.byteLength===0||u.byteLength>d$1.texture)throw new Error("Encoded RoomEnvironment KTX2 exceeds the bounded texture size.");let f$1=read(u);if(f$1.vkFormat!==VK_FORMAT_R16G16B16A16_SFLOAT||f$1.pixelWidth!==o.pixelWidth||f$1.pixelHeight!==o.pixelHeight||f$1.supercompressionScheme!==o.supercompressionScheme||f$1.keyValue.KTXorientation!=="rd"||f$1.levels.length!==s.length)throw new Error("RoomEnvironment KTX2 header failed round-trip validation.");for(let m=0;m<f$1.levels.length;m+=1){let p=f$1.levels[m],h=s[m];if(p===void 0||h===void 0)throw new Error(`RoomEnvironment KTX2 level ${m} is missing after round-trip.`);let y=i==="zstd"?a.zstdDecompressSync?.(p.levelData):p.levelData;if(y===void 0||p.uncompressedByteLength!==h.byteLength||!$d(y,h))throw new Error(`RoomEnvironment KTX2 level ${m} failed byte-for-byte round-trip validation.`)}let l=s.reduce((m,p)=>m+p.byteLength,0);return {bytes:u,metadata:{compression:i,cubeSize:r,format:"RGBA16F CubeUVReflectionMapping",height:f$1.pixelHeight,rawBytes:l,sha256:f(u),three:n,version:Rd,width:f$1.pixelWidth}}}a(bo,"encodeRoomEnvironmentKtx2");var jr=class{static{a(this,"BakeInbox");}promise;#n=a(()=>{},"#resolve");#e=a(()=>{},"#reject");#t=false;constructor(){this.promise=new Promise((t,r)=>{this.#n=t,this.#e=r;});}receive(t){return this.#t?false:(this.#t=true,this.#n(t),true)}reject(t){this.#t||(this.#t=true,this.#e(t));}};function Pd(e){if(e.url!==void 0)try{return new URL(e.url,"http://three-blocks.invalid").pathname}catch{return}}a(Pd,"requestPath");function qe(e,t,r=""){e.statusCode=t,e.setHeader("Content-Type",r.startsWith("<!")?"text/html; charset=utf-8":"text/plain; charset=utf-8"),e.setHeader("Cache-Control","no-store"),e.end(r);}a(qe,"respond");function Ad(e,t){return {name:"three-blocks:environment-bake",enforce:"post",resolveId(r){return r===Dr?co:void 0},load(r){return r===co?t:void 0},configureServer(r){r.middlewares.use((n,o,s)=>{let i=Pd(n);if(i===go&&(n.method==="GET"||n.method==="HEAD")){let m=n.method==="HEAD"?"":`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Three Blocks environment bake</title></head><body><canvas id="three-blocks-environment-baker" width="1" height="1"></canvas><script type="module" src="${kd}"></script></body></html>`;qe(o,200,m);return}if(i!==Sd)return s();if(n.method!=="POST"){qe(o,405,"POST required");return}let a=n.headers["content-type"];if(typeof a!="string"||!a.toLowerCase().startsWith("image/ktx2")){qe(o,415,"image/ktx2 required");return}let c=Number(n.headers["content-length"]??0);if(Number.isFinite(c)&&c>Lr){qe(o,413,"Bake payload exceeds 128 MiB");return}let u=[],f=0,l=false;n.on("data",m=>{f+=m.byteLength,f>Lr?l=true:u.push(m);}),n.on("error",m=>e.reject(m)),n.on("end",()=>{if(l){qe(o,413,"Bake payload exceeds 128 MiB"),e.reject(new Error("RoomEnvironment bake upload exceeded 128 MiB."));return}let m=n.headers["x-three-revision"];if(typeof m!="string"){qe(o,400,"x-three-revision required"),e.reject(new Error("RoomEnvironment upload omitted the Three.js revision."));return}let p=e.receive({bytes:new Uint8Array(Buffer.concat(u)),threeRevision:m});qe(o,p?204:409,p?"":"Bake upload already received");});});}}}a(Ad,"bakePlugin");async function _d(){let e=F.dirname(fileURLToPath(import.meta.url)),t=[F.join(e,"browser","environment-bake.js"),F.join(e,"browser","environment-bake.ts")];for(let r of t)if(await g(r))return (await j(r,d$1.semanticInput,"Environment bake browser entry")).data.toString("utf8");throw new Error("The separately built environment bake browser entry is missing.")}a(_d,"browserEntrySource");function Md(e){return new Promise((t,r)=>{e.on("pageerror",n=>{b$1(n.message)||r(n);}),e.on("console",n=>{n.type()==="error"&&!b$1(n.text())&&r(new Error(n.text()));});})}a(Md,"pageFailure");async function Cd(e,t){await e.waitForFunction(()=>globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__!==void 0,void 0,{timeout:Math.min(t,3e4)});let r=await e.evaluate(()=>globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__);if(!r||typeof r!="object"||Reflect.get(r,"ok")!==true){let n=r&&typeof r=="object"?Reflect.get(r,"error"):void 0;throw new Error(typeof n=="string"?n:"Browser RoomEnvironment bake did not report success.")}}a(Cd,"readBrowserBakeResult");var So=a(async e=>{let{chromium:t,createServer:r}=await vd(),n=new jr,o,s,i,a,c$1=false;try{let u=await _d();o=await r({root:e.root,configFile:!1,logLevel:"silent",optimizeDeps:{noDiscovery:!0},plugins:[Ad(n,u)],server:{host:"127.0.0.1",port:0,strictPort:!1}}),await o.listen();let f=o.httpServer?.address();if(!f||typeof f=="string")throw new Error("Environment bake Vite server has no ephemeral TCP address.");s=await t.launch({headless:d(e.headed),args:[...c()]}),i=await s.newContext({viewport:{width:320,height:240}});let l=await i.newPage(),m=Md(l),p=new Promise((y,w)=>{a=setTimeout(()=>w(new Error(`RoomEnvironment bake timed out after ${e.timeoutMs}ms.`)),e.timeoutMs),a.unref();});await l.goto(`http://127.0.0.1:${f.port}${go}?size=${e.size}`,{waitUntil:"domcontentloaded",timeout:Math.min(e.timeoutMs,3e4)});let h=await Promise.race([n.promise,m,p]);return await Cd(l,e.timeoutMs),h}catch(u){throw c$1=true,n.reject(u instanceof Error?u:new Error(String(u))),await n.promise.catch(()=>{}),u}finally{a&&clearTimeout(a);let u=[];if(await i?.close().catch(f=>u.push(`context: ${f instanceof Error?f.message:String(f)}`)),await s?.close().catch(f=>u.push(`browser: ${f instanceof Error?f.message:String(f)}`)),await o?.close().catch(f=>u.push(`Vite: ${f instanceof Error?f.message:String(f)}`)),!c$1&&u.length>0)throw new Error(`RoomEnvironment cleanup failed (${u.join("; ")}).`)}},"captureRoomEnvironment");function Od(e,t){let r=t??xd;if(F.isAbsolute(r)||r.length===0||r.length>2048||/[\u0000-\u001f\u007f]/u.test(r)||!r.endsWith(".ktx2"))throw new Error("Environment output must be a bounded project-relative .ktx2 path.");let n=F.resolve(e,r);if(!h(e,n)||n===e)throw new Error("Environment output escapes the project root.");return {asset:n,metadata:`${n.slice(0,-5)}.json`}}a(Od,"outputPaths");async function Fd(e,t){let r=F.relative(e,t);if(r==="")return;let n=e;for(let s of r.split(F.sep)){n=F.join(n,s),await g(n)||await mkdir(n);let i=await lstat(n);if(i.isSymbolicLink()||!i.isDirectory())throw new Error(`Environment output parent is not a real directory: ${n}.`)}let o=await realpath(t);if(!h(e,o))throw new Error("Environment output parent resolves outside the project root.")}a(Fd,"ensureSafeParent");async function lo(e){if(!await g(e))return;let t=await lstat(e);if(t.isSymbolicLink()||!t.isFile())throw new Error(`Environment output target must be a regular file: ${e}.`)}a(lo,"validateOutputTarget");async function Id(e,t,r,n){await Promise.all([lo(e),lo(r)]);let o=`${process.pid}-${randomUUID()}`,s=F.join(F.dirname(e),`.${F.basename(e)}.${o}.tmp`),i=F.join(F.dirname(r),`.${F.basename(r)}.${o}.tmp`),a=`${s}.backup`,c=`${i}.backup`,u=false,f=false,l=false,m=false;try{await Promise.all([writeFile(s,t,{flag:"wx"}),writeFile(i,n,{encoding:"utf8",flag:"wx"})]),await g(e)&&(await rename(e,a),u=!0),await g(r)&&(await rename(r,c),f=!0),await rename(s,e),l=!0,await rename(i,r),m=!0,await Promise.all([rm(a,{force:!0}),rm(c,{force:!0})]);}catch(p){throw m&&await rm(r,{force:true}),l&&await rm(e,{force:true}),f&&await rename(c,r),u&&await rename(a,e),p}finally{await Promise.all([rm(s,{force:true}),rm(i,{force:true}),rm(a,{force:true}),rm(c,{force:true})]);}}a(Id,"writeAtomicPair");function uo(e,t){return F.relative(e,t).split(F.sep).join("/")}a(uo,"portableRelative");async function Ld(e){let t=await realpath(e.root),r=Nr(e.size??256),n=wo(e.timeoutMs,"Environment bake timeoutMs",1e3,15*6e4,24e4),o=Od(t,e.output);await Fd(t,F.dirname(o.asset));let i=await(e.capture??So)({root:t,size:r,timeoutMs:n,headed:e.headed===true}),a=bo(i.bytes,{cubeSize:r,threeRevision:i.threeRevision,compression:e.compression??"zstd"}),c=`${JSON.stringify(a.metadata,null,2)}
274
- `;await Id(o.asset,a.bytes,o.metadata,c);let u=await readFile(o.asset);if(f(u)!==a.metadata.sha256)throw new Error("Committed RoomEnvironment checksum does not match metadata.");return {schemaVersion:1,command:"environment bake",output:uo(t,o.asset),metadataOutput:uo(t,o.metadata),bytes:a.bytes.byteLength,metadata:a.metadata}}a(Ld,"bakeRoomEnvironment");function jd(e){if(e<1e3)return `${e} B`;let t=e/1e3;return `${t>=100?Math.round(t):t.toFixed(1)} kB`}a(jd,"formatBytes");function Dd(e){return [`\u2713 Environment ${e.metadata.width}\xD7${e.metadata.height} \xB7 CubeUV ${e.metadata.cubeSize}px \xB7 RGBA16F ${e.metadata.compression}`,` Output ${e.output} \xB7 ${jd(e.bytes)}`,` Checksum ${e.metadata.sha256}`].join(`
275
- `)}a(Dd,"formatEnvironmentBakeReport");var er=class{static{a(this,"ShaderWatchQueue");}#n;#e;#t;#r;#o;#s=false;#a=false;constructor(t){if(this.#n=t.capture,this.#e=t.debounceMs??200,this.#t=t.onError??(()=>{}),!Number.isSafeInteger(this.#e)||this.#e<0||this.#e>6e4)throw new Error("Shader watch debounce must be an integer in 0...60000ms.")}notify(){this.#a||(this.#s=true,!this.#o&&(this.#r&&clearTimeout(this.#r),this.#r=setTimeout(()=>{this.#r=void 0,this.#i();},this.#e)));}#i(){this.#a||this.#o||!this.#s||(this.#s=false,this.#o=this.#n().catch(t=>{this.#t(t instanceof Error?t:new Error(String(t)));}).finally(()=>{this.#o=void 0,this.#s&&!this.#a&&this.notify();}));}async close(){this.#a=true,this.#s=false,this.#r&&clearTimeout(this.#r),this.#r=void 0,await this.#o;}};function Hd(e){let t=e.split(F.sep).join("/");return t===""||t.startsWith("node_modules/")||t.startsWith(".git/")||t.startsWith("dist/")||t===".three-blocks"||t.startsWith(".three-blocks/")}a(Hd,"ignored");async function Ud(e={}){let t=e.root??await v(e.start),r,n=new Promise(c=>{r=c;}),o=new er({...e.debounceMs!==void 0?{debounceMs:e.debounceMs}:{},...e.onError?{onError:e.onError}:{},capture:a(async()=>{let c=await $r({root:t,...e.config?{config:e.config}:{},...e.driver?{driver:e.driver}:{},...e.driverKind?{driverKind:e.driverKind}:{},...e.serve?{serve:e.serve}:{},...e.url?{url:e.url}:{},...e.headed!==void 0?{headed:e.headed}:{},...e.attempts!==void 0?{attempts:e.attempts}:{}});e.onResult?.(c);},"capture")}),s,i=false,a$1=a(async()=>{i||(i=true,s?.close(),await o.close(),r?.());},"close");return s=watch(t,{recursive:true},(c,u)=>{Hd(u??"")||o.notify();}),s.on("error",c=>e.onError?.(c)),e.signal&&(e.signal.aborted?await a$1():e.signal.addEventListener("abort",()=>{a$1();},{once:true})),e.initial!==false&&o.notify(),{root:t,done:n,close:a$1}}a(Ud,"watchShaders");var Pt=1,Ao="ktx2-encoder@0.6.0",Ur=F.join(".three-blocks","assets"),Wr=F.join(Ur,"meta.json"),Gd=F.join(Ur,"cache"),Kd=256*1024*1024,qd=64*1024*1024,Ro=115e5,vo=64,Xd=163,Jd=166,Zd=167,Yd=1000066e3,_o=1,Mo=2,Qd=/baseColor|emissive|diffuse|sheenColor|specularColor/u,ec=/normal/iu,tc=/(?:^|[_\-.])(?:normal|nrm|nor)(?:[_\-.]|map|$)/iu,rc=/(?:rough|metal|orm\b|occlusion|ambient|[_\-.]ao(?:[_\-.]|$)|height|disp|thick|mask)/iu;function Co(e){return e.some(t=>ec.test(t))?"normal":e.some(t=>Qd.test(t))||e.length===0?"color":"data"}a(Co,"presetForTextureSlots");function Oo(e){let t=F.basename(e);return tc.test(t)?"normal":rc.test(t)?"data":"color"}a(Oo,"presetForImageName");function zr(e){let t=F.extname(e).toLowerCase();return t===".glb"?"glb":t===".png"||t===".jpg"||t===".jpeg"||t===".webp"?"image":t===".hdr"?"hdr":null}a(zr,"assetKindFor");function $t(e,t){let r=F.relative(e,t);return (r!==""&&!r.startsWith("..")&&!F.isAbsolute(r)?r:t).split(F.sep).join("/")}a($t,"portable");var Eo;function Fo(){return Eo??=Promise.all([import('ktx2-encoder'),import('sharp')]).then(([e,t])=>({encodeToKTX2:e.encodeToKTX2,sharp:t.default})),Eo}a(Fo,"loadEncoderTools");function Io(e,t){let r=t.quality==="high";return e==="hdr"?{mode:"uastc-hdr",options:{isHDR:true,imageType:"hdr",isUASTC:true,isYFlip:true,generateMipmap:true,needSupercompression:true,hdrQualityLevel:r?2:1}}:e==="color"&&!r?{mode:"etc1s",options:{isUASTC:false,qualityLevel:160,compressionLevel:2,isPerceptual:true,isSRGB:true,generateMipmap:true}}:{mode:"uastc",options:{isUASTC:true,uastcLDRQualityLevel:r?2:1,enableRDO:true,rdoQualityLevel:1,generateMipmap:true,needSupercompression:true,isPerceptual:e==="color",isSRGB:e==="color",isNormalMap:e==="normal"}}}a(Io,"encoderOptionsFor");function nc(e,t){let r=read(e),n=r.dataFormatDescriptor[0];if(n===void 0)return e;let o=t==="color"?Mo:_o;return n.transferFunction===o&&(t!=="color"||n.colorPrimaries===KHR_DF_PRIMARIES_BT709)?e:(n.transferFunction=o,t==="color"&&(n.colorPrimaries=KHR_DF_PRIMARIES_BT709),write(r,{keepWriter:true}))}a(nc,"normalizeDfdTransfer");function Lo(e,t,r,n){let o=read(e),s=o.dataFormatDescriptor[0];if(s===void 0)throw new Error(`${n} produced a KTX2 container without a data format descriptor.`);if(t==="hdr"){if(o.vkFormat!==Yd||s.colorModel!==Zd)throw new Error(`${n} is not a UASTC HDR container (vkFormat ${o.vkFormat}, color model ${s.colorModel}).`)}else {let c=r==="etc1s"?Xd:Jd;if(o.vkFormat!==0||s.colorModel!==c)throw new Error(`${n} is not a ${r} container (vkFormat ${o.vkFormat}, color model ${s.colorModel}).`)}let i=t==="color",a=s.transferFunction;if(i&&a!==Mo)throw new Error(`${n} must carry the sRGB transfer function; found ${a}.`);if(!i&&a!==_o)throw new Error(`${n} must carry the linear transfer function; found ${a}.`);if(Math.max(o.pixelWidth,o.pixelHeight)>=8&&o.levels.length<2)throw new Error(`${n} is missing its mip chain.`);return {width:o.pixelWidth,height:o.pixelHeight}}a(Lo,"verifyKtx2");async function jo(e,t,r,n){let{encodeToKTX2:o,sharp:s}=await Fo(),i=r.maxDimension,{mode:a$1,options:c}=Io(t,r),u=performance.now(),l=nc(await o(e,{...c,imageDecoder:a(async h=>{let y=s(h),w=await y.metadata(),b=w.width??0,k=w.height??0;if(b<1||k<1)throw new Error(`${n} has no decodable dimensions.`);let g=Math.min(1,i/Math.max(b,k));b*g*k*g>Ro&&(g=Math.sqrt(Ro/(b*k)));let P=g<1,R=P?Math.max(4,Math.floor(b*g/4)*4):b,_=P?Math.max(4,Math.floor(k*g/4)*4):k,C=P?y.resize(R,_,{fit:"fill",kernel:"lanczos3"}):y,{data:S,info:B}=await C.ensureAlpha().raw().toBuffer({resolveWithObject:true});return {data:new Uint8Array(S.buffer,S.byteOffset,S.byteLength),width:B.width,height:B.height}},"decode")}),t),{width:m,height:p}=Lo(l,t,a$1,n);return {bytes:l,width:m,height:p,mode:a$1,durationMs:performance.now()-u}}a(jo,"encodeLdrTexture");function oc(e,t){let r=new TextDecoder("latin1").decode(e.subarray(0,Math.min(e.byteLength,4096))),n=/-Y\s+(\d+)\s+\+X\s+(\d+)/u.exec(r);if(n?.[1]===void 0||n[2]===void 0)throw new Error(`${t} is not a supported Radiance .hdr file (missing "-Y <h> +X <w>" resolution).`);return {width:Number(n[2]),height:Number(n[1])}}a(oc,"hdrDimensions");async function sc(e,t,r){let n=oc(e,r);if(Math.max(n.width,n.height)>t.hdrMaxDimension)throw new Error(`${r} is ${n.width}x${n.height}, above the ${t.hdrMaxDimension}px HDR cap; resize the source (HDR resize is not supported yet).`);let{encodeToKTX2:o}=await Fo(),{mode:s,options:i}=Io("hdr",t),a=performance.now(),c=await o(e,i),{width:u,height:f}=Lo(c,"hdr",s,r);return {bytes:c,width:u,height:f,mode:s,durationMs:performance.now()-a}}a(sc,"encodeHdrTexture");function lt(e,t,r){let n=e*t*1.3333333333333333;return Math.round(r==="source-hdr"?n*8:r==="source-ldr"?n*4:n*(r==="etc1s"?.5:1))}a(lt,"textureVram");async function ac(e,t,r){let n=r.preset??Oo(t),o=`Image ${JSON.stringify(F.basename(t))}`,s=await jo(e,n,r,o),i=[`preset ${n} (${r.preset===null?"from filename":"explicit"})`];return n!=="color"&&i.push("linear DFD: consumers must treat this texture as non-color data"),i.push("compressed textures never flip: sample with glTF-style (flipY=false) UVs"),{bytes:s.bytes,metadata:{vramBytesIn:lt(s.width,s.height,"source-ldr"),vramBytesOut:lt(s.width,s.height,s.mode),textures:[{name:F.basename(t),slots:[],preset:n,mode:s.mode,width:s.width,height:s.height,bytesIn:e.byteLength,bytesOut:s.bytes.byteLength,durationMs:Math.round(s.durationMs)}],notes:i}}}a(ac,"buildImageAsset");async function ic(e,t,r){let n=`Environment ${JSON.stringify(F.basename(t))}`,o=await sc(e,r,n);return {bytes:o.bytes,metadata:{vramBytesIn:lt(o.width,o.height,"source-hdr"),vramBytesOut:lt(o.width,o.height,o.mode),textures:[{name:F.basename(t),slots:["equirectangular"],preset:"hdr",mode:o.mode,width:o.width,height:o.height,bytesIn:e.byteLength,bytesOut:o.bytes.byteLength,durationMs:Math.round(o.durationMs)}],notes:["BC6H on BC-capable devices; transcodes to RGBA16F elsewhere"]}}}a(ic,"buildHdrAsset");async function dc(e,t,r,n){let[{Logger:o,NodeIO:s},{ALL_EXTENSIONS:i,KHRTextureBasisu:a},{dedup:c,listTextureSlots:u,meshopt:f,prune:l,weld:m},{MeshoptDecoder:p,MeshoptEncoder:h}]=await Promise.all([import('@gltf-transform/core'),import('@gltf-transform/extensions'),import('@gltf-transform/functions'),import('meshoptimizer')]);await h.ready,await p.ready;let y=new s().registerExtensions(i).registerDependencies({"meshopt.encoder":h,"meshopt.decoder":p}),w=`GLB ${JSON.stringify(F.basename(t))}`;y.setLogger(new o(o.Verbosity.SILENT));let b=await y.readBinary(e);b.setLogger(new o(o.Verbosity.SILENT));let k=b.getRoot().listTextures();if(k.length>0&&k.every(T=>T.getMimeType()==="image/ktx2")&&b.getRoot().listExtensionsUsed().some(T=>T.extensionName==="EXT_meshopt_compression"))return {bytes:e,metadata:{vramBytesIn:0,vramBytesOut:0,textures:[],notes:["already optimized (KTX2 + meshopt); copied unchanged"]}};n?.("optimizing geometry"),await b.transform(c(),l({keepAttributes:true,keepExtras:true,keepSolidTextures:true}),m(),f({encoder:h,level:"medium"}));let P=[],R=[],_=0,C=0,S=0;for(let T of k){let x=T.getName()||T.getURI()||`texture-${P.length}`,O=T.getImage(),V=T.getMimeType();if(O===null||O.byteLength===0)continue;if(V==="image/ktx2"){R.push(`${x}: already KTX2, kept`);continue}if(!/^image\/(?:png|jpeg|webp)$/u.test(V)){R.push(`${x}: unsupported ${V}, kept`);continue}let q=T.getSize();if(q!==null&&Math.max(q[0],q[1])<vo){R.push(`${x}: below ${vo}px, kept`);continue}let z=u(T),v=Co(z);n?.(`encoding ${x} (${v})`);let M=await jo(new Uint8Array(O),v,r,`${w} texture ${JSON.stringify(x)}`);T.setImage(M.bytes).setMimeType("image/ktx2");let L=T.getURI();L!==""&&T.setURI(L.replace(/\.(?:png|jpe?g|webp)$/iu,".ktx2")),S+=1,_+=lt(M.width,M.height,"source-ldr"),C+=lt(M.width,M.height,M.mode),P.push({name:x,slots:z,preset:v,mode:M.mode,width:M.width,height:M.height,bytesIn:O.byteLength,bytesOut:M.bytes.byteLength,durationMs:Math.round(M.durationMs)});}S>0&&b.createExtension(a).setRequired(true);let B=await y.writeBinary(b);return await y.readBinary(B),S>0&&R.push("requires a KTX2-wired loader (three-blocks/assets or GLTFLoader.setKTX2Loader)"),{bytes:B,metadata:{vramBytesIn:_,vramBytesOut:C,textures:P,notes:R}}}a(dc,"buildGlbAsset");function cc(e,t,r){let n=F.basename(e,F.extname(e));if(t==="glb"){let o=r===null?F.join(F.dirname(e),`${n}.tb.glb`):F.join(r,`${n}.glb`);if(F.resolve(o)===F.resolve(e))throw new Error(`Output would overwrite the input: ${JSON.stringify(e)}. Pass a different output directory.`);return o}return F.join(r??F.dirname(e),`${n}.ktx2`)}a(cc,"outputPathFor");async function Do(e$1){let t={schemaVersion:Pt,tool:{name:"three-blocks-devtools",assetOptimizeVersion:Pt,encoder:Ao},assets:{}},r;try{r=await readFile(e$1,"utf8");}catch(n){if(e(n)==="ENOENT")return t;throw n}if(r.length>d$1.receipt)return t;try{let n=JSON.parse(r);if(typeof n!="object"||n===null)return t;let o=n;return o.schemaVersion!==Pt||typeof o.assets!="object"||o.assets===null?t:{...t,assets:{...o.assets}}}catch{return t}}a(Do,"readReceipt");async function lc(e){let t=[];for(let r of e){let n=F.resolve(r);if((await lstat(n)).isDirectory()){let s=(await readdir(n,{withFileTypes:true})).sort((i,a)=>i.name.localeCompare(a.name));for(let i of s)i.isFile()&&zr(i.name)!==null&&t.push(F.join(n,i.name));}else t.push(n);}if(t.length===0)throw new Error("No optimizable inputs found (.glb, .png, .jpg, .webp, .hdr).");return t}a(lc,"expandInputs");async function uc(e){let t=await realpath(e.root),r={maxDimension:To(e.maxDimension,2048),hdrMaxDimension:To(e.hdrMaxDimension,4096),quality:e.quality??"default",preset:e.preset??null},n=e.outDir===void 0?null:F.resolve(t,e.outDir);n!==null&&await mkdir(n,{recursive:true});let o=F.join(t,Gd),s=F.join(t,Wr),i$1=f(H({version:Pt,encoder:Ao,...r})),a$1=await lc(e.inputs),c=[],u=[],f$1=await Do(s);for(let[l,m]of a$1.entries()){let p=zr(m);try{if(p===null)throw new Error(`Unsupported asset type ${JSON.stringify(F.extname(m))}; expected .glb, .png, .jpg, .webp, or .hdr (EXR sources are not supported yet \u2014 convert environments to .hdr).`);e.onProgress?.(`${F.basename(m)} (${l+1}/${a$1.length})`);let h=p==="glb"?Kd:p==="hdr"?qd:d$1.texture,y=await j(m,h,"Asset input"),w=y.path,b=f(y.data),k=f(`${b}\0${i$1}`),g$1=p==="glb"?"glb":"ktx2",P=F.join(o,`${k}.${g$1}`),R=F.join(o,`${k}.json`),_,C,S=!1;if(e.force!==!0&&await g(P)&&await g(R))_=(await j(P,h,"Cached asset")).data,C=JSON.parse((await j(R,d$1.metadata,"Cached asset metadata")).data.toString("utf8")),S=!0;else {let x=a(V=>e.onProgress?.(`${F.basename(m)}: ${V}`),"progress"),O=p==="glb"?await dc(y.data,w,r,x):p==="hdr"?await ic(y.data,w,r):await ac(y.data,w,r);_=O.bytes,C=O.metadata,await i(P,_),await i(R,`${JSON.stringify(C,null," ")}
276
- `);}let B=cc(w,p,n);await mkdir(F.dirname(B),{recursive:!0}),await i(B,_);let T=f(_);f$1.assets[$t(t,w)]={kind:p,inputSha256:b,output:$t(t,B),outputSha256:T,settingsSha256:i$1,bytesIn:y.data.byteLength,bytesOut:_.byteLength},c.push({input:$t(t,w),output:$t(t,B),kind:p,cached:S,bytesIn:y.data.byteLength,bytesOut:_.byteLength,vramBytesIn:C.vramBytesIn,vramBytesOut:C.vramBytesOut,textures:C.textures,notes:C.notes});}catch(h){u.push({input:$t(t,m),error:h instanceof Error?h.message:String(h)});}}return c.length>0&&await i(s,`${JSON.stringify(f$1,null," ")}
277
- `),{schemaVersion:1,command:"assets optimize",root:t,results:c,failed:u,bytesIn:c.reduce((l,m)=>l+m.bytesIn,0),bytesOut:c.reduce((l,m)=>l+m.bytesOut,0)}}a(uc,"optimizeAssets");function To(e,t){if(e===void 0)return t;if(!Number.isInteger(e)||e<64||e>16384)throw new Error("Texture dimension caps must be integers between 64 and 16384.");return e}a(To,"boundedDimension");function Ne(e){if(e<1e3)return `${e} B`;if(e<1e6){let r=e/1e3;return `${r>=100?Math.round(r):r.toFixed(1)} kB`}let t=e/1e6;return `${t>=100?Math.round(t):t.toFixed(2)} MB`}a(Ne,"formatBytes");function Bo(e,t){if(e===0)return "";let r=Math.round((t-e)/e*100);return r===0?"":` (${r>0?"+":""}${r}%)`}a(Bo,"percentDelta");function mc(e){let t=[];for(let r of e.results){let n=r.cached?" \xB7 cached":"";t.push(`${r.input} -> ${r.output}`),t.push(` ${Ne(r.bytesIn)} -> ${Ne(r.bytesOut)}${Bo(r.bytesIn,r.bytesOut)}${n}`),r.vramBytesOut>0&&t.push(` VRAM \u2248 ${Ne(r.vramBytesIn)} -> ${Ne(r.vramBytesOut)}`);for(let o of r.textures){let s=o.slots.length>0?` [${o.slots.join(", ")}]`:"";t.push(` ${o.name}${s} ${o.preset}/${o.mode} ${o.width}x${o.height} ${Ne(o.bytesIn)} -> ${Ne(o.bytesOut)}`);}for(let o of r.notes)t.push(` note: ${o}`);}for(let r of e.failed)t.push(`failed ${r.input}: ${r.error}`);return e.results.length>1&&t.push(`total ${Ne(e.bytesIn)} -> ${Ne(e.bytesOut)}${Bo(e.bytesIn,e.bytesOut)}`),t.join(`
278
- `)}a(mc,"formatAssetOptimizeReport");async function fc(e,t){let r=await realpath(e),n=F.resolve(r,t);if(!await g(n))return [];let o=[],s=[n],i=0;for(;s.length>0;){let a=s.shift();if(a===void 0)break;let c=(await readdir(a,{withFileTypes:true})).sort((u,f)=>u.name.localeCompare(f.name));for(let u of c){if(i+=1,i>8192)throw new Error("Public asset discovery exceeds the 8192-entry limit.");if(u.isSymbolicLink()||u.name.startsWith("."))continue;let f=F.join(a,u.name);if(u.isDirectory()){if(a===n&&u.name==="three-blocks")continue;s.push(f);continue}if(!u.isFile()||u.name.endsWith(".tb.glb"))continue;let l=zr(u.name);(l==="glb"||l==="hdr")&&o.push(f);}}return o.sort()}a(fc,"discoverPublicAssets");async function pc(e){let t=await realpath(e),r=await Do(F.join(t,Wr)),n=[];for(let[o,s]of Object.entries(r.assets).sort(([i],[a])=>i.localeCompare(a))){let i=F.resolve(t,o),a=F.resolve(t,s.output),c="fresh";if(!await g(i))c="missing-input";else if(!await g(a))c="missing-output";else {let[u,f$1]=await Promise.all([readFile(i),readFile(a)]);(f(u)!==s.inputSha256||f(f$1)!==s.outputSha256)&&(c="stale");}n.push({input:o,output:s.output,kind:s.kind,state:c});}return {schemaVersion:1,command:"assets status",root:t,state:n.length===0?"empty":n.every(o=>o.state==="fresh")?"fresh":"stale",entries:n}}a(pc,"inspectAssets");function hc(e){if(e.state==="empty")return "No optimized assets recorded. Run `assets optimize <file|directory>` first.";let t=e.entries.map(r=>`${r.state==="fresh"?"fresh ":r.state.padEnd(14)} ${r.input} -> ${r.output}`);return e.state==="stale"&&t.push("Some assets moved or changed; re-run `assets optimize` on the stale inputs."),t.join(`
279
- `)}a(hc,"formatAssetStatusReport");export{Pt as ASSET_OPTIMIZE_VERSION,Ur as ASSET_RECEIPT_DIRECTORY,Wr as ASSET_RECEIPT_FILE,Tt as RUNTIME_STATUS_RECEIPT_MAX_BYTES,Xt as RUNTIME_STATUS_RECEIPT_PATH,qt as RUNTIME_STATUS_RECOVERY,er as ShaderWatchQueue,vt as TEXT_ATLAS_GENERATOR_VERSION,gr as TEXT_ATLAS_SCHEMA_VERSION,Ld as bakeRoomEnvironment,dr as buildGlyphSet,wr as builtinFontMetadata,So as captureRoomEnvironment,$r as captureShaders,fc as discoverPublicAssets,Ut as discoverTextContent,bo as encodeRoomEnvironmentKtx2,ar as extractCanvasTextFromHtml,ir as extractDefinedTextContent,Ar as findProjectRoot,mc as formatAssetOptimizeReport,hc as formatAssetStatusReport,fd as formatBrowserPreviewReport,ud as formatBrowserSmokeReport,Dd as formatEnvironmentBakeReport,Xn as formatShaderMatrixStatus,Jn as formatStatus,Li as formatThreeBlocksStatus,Ea as generateTextAtlases,pc as inspectAssets,qn as inspectProject,Ue as inspectShaderMatrix,zt as inspectTextAtlases,Ai as inspectThreeBlocksStatus,uc as optimizeAssets,Re as parseBrowserSmokeLifecycle,Kn as parseRuntimeStatusReceipt,Bn as parseTextAtlasReceipt,sn as parseTextConfiguration,Oo as presetForImageName,Co as presetForTextureSlots,ga as prewarmBuiltinFont,Pe as readInstalledShaderRuntime,Ht as readTextConfiguration,md as runBrowserPreview,ld as runBrowserSmoke,Zt as screenshotLuminance,Ie as snapshotShaderInputs,ei as testShaders,_i as threeBlocksStatusIsFresh,Nr as validateEnvironmentCubeSize,Ud as watchShaders};
271
+ `}),e.forceWebgl===!0&&await m.addInitScript(()=>{Object.defineProperty(Navigator.prototype,"gpu",{configurable:!0,value:void 0});}),e.unsupportedWorker===!0&&await m.addInitScript(()=>{Object.defineProperty(globalThis,"Worker",{configurable:!0,value:void 0});}),p=await m.newPage();let de=p;if(H=so(p),p.on("console",ce=>{/WebGPU is not available, running under WebGL2 backend/iu.test(ce.text())&&(R=!0);}),await p.goto(ud(f,ne,s),{waitUntil:"domcontentloaded",timeout:i}),e.unsupportedWorker===!0)T=await eo(async()=>{await _r(de,a(async()=>{await de.waitForFunction(()=>globalThis.document.querySelector("#three-blocks-dev-overlay")?.shadowRoot?.querySelector(".dot")?.dataset.tone==="error",void 0,{timeout:Math.min(i,15e3)});},"waitForFailure"),i);},()=>de.evaluate(()=>"gpu"in navigator&&navigator.gpu!==void 0)),C=await Xi(p),y=Re(await Ke(p),!1);else {let ce=a(()=>e.expectTextGenerationFailure===!0?Qn(de,i):Yt(de,!1,i),"initialReadiness");T=await eo(()=>_r(de,ce,i),()=>de.evaluate(()=>"gpu"in navigator&&navigator.gpu!==void 0));let j=await od(p,ce,i);if(h=j.textEnabled,w=j.codecs,b=j.receipt,x=j.hmrEvidence,e.expectTextGenerationFailure===!0){if(!j.textEnabled)throw new Error("Expected text-generation failure mode requires a text-enabled project.");await Qn(p,i);let le=performance.now()+Math.min(i,3e4);for(;!A.some(Me=>/automatic atlas generation failed/iu.test(Me));){if(performance.now()>=le)throw new Error("Timed out waiting for the automatic text-generation failure warning.");await p.waitForTimeout(50);}y=Re(await Ke(p),!0);}else if(await Yt(p,j.textEnabled,i),y=Re(await Ke(p),j.textEnabled),j.textEnabled&&y.textReady&&(w=w.map(le=>le.name==="ktx2"?{...le,decoded:!0,evidence:"text-atlas-decoded",blocker:null}:le)),g=await id(f,p,o,e.hmrModule,i,j.textEnabled,x),e.hmrModule!==void 0){let le=await dd(p,i,j.textEnabled,j.receipt.shaders.mode);g={...g,restart:le},y=Re(await Ke(p),j.textEnabled);}}a$1>0&&await p.waitForTimeout(a$1),O=await Yn(p),k=await Zt(p);let Je=await p.screenshot({type:"png"});v=Jt(Je),S=await Cr(p);}catch(G){if(p!==void 0)try{y=Re(await Ke(p),h),O=await Yn(p),k=await Zt(p);let K=await p.screenshot({type:"png"});v=Jt(K),S=await Cr(p);}catch(K){_.page.push(`Failure diagnostics could not be captured: ${K instanceof Error?K.message:String(K)}`);}_.page.push(G instanceof Error?G.message:String(G));}finally{H!==void 0&&(_.console.push(...H.console),_.page.push(...H.page)),await m?.close().catch(ne=>{_.page.push(`Browser context cleanup failed: ${ne instanceof Error?ne.message:String(ne)}`);}),await u?.close().catch(ne=>{_.page.push(`Browser cleanup failed: ${ne instanceof Error?ne.message:String(ne)}`);});let G=f?.httpServer,K=G?Reflect.get(G,"closeAllConnections"):void 0;G&&typeof K=="function"&&Reflect.apply(K,G,[]),await f?.close().catch(ne=>{_.page.push(`Vite cleanup failed: ${ne instanceof Error?ne.message:String(ne)}`);}),q===void 0?delete process.env.PATH:process.env.PATH=q;}let z=Number(v.toFixed(2)),E=Number(S.toFixed(2)),M=v<=l&&S<=l,L=cd(_.console,_.page,O.recovered),U=L.console,ee=L.page,X=L.resolved,re=y.worker&&y.workerReady&&y.assetsReady&&y.compileEnd&&y.textReady&&y.firstFrame,se=w.length===3&&w.every(G=>G.state!=="error"),Xe=Object.values(g.evidence).every(Boolean),oe=!g.restart.requested||g.restart.error===null&&[g.restart.appIdentityStable,g.restart.contentIdentityStable,g.restart.canvasReplaced,g.restart.workerIdentityChanged,g.restart.generationAdvanced,g.restart.restartCountAdvanced,g.restart.stateReplayed,g.restart.readinessRestored,g.restart.shaderModeStable,g.restart.statsSnapshotsAdvanced,g.restart.statsTextureTransferred,g.restart.statsTextureStopped].every(Boolean),Pe=!g.requested||g.dispatched&&g.acknowledged&&g.lifecycleStable&&g.sourceUnchanged&&Xe&&oe&&g.error===null,ve=A.filter(G=>/automatic atlas generation failed/iu.test(G)),Se=ve.reduce((G,K)=>G+(K.match(/three-blocks text generate/gu)?.length??0),0),pe=e.expectTextGenerationFailure===true&&h&&O.fallbackObserved&&!O.recovered&&O.totalElements>0&&O.visibleElements===O.totalElements&&ve.length===1&&Se===1,lt=e.unsupportedWorker===true&&C.fatalVisible&&C.code==="render-worker-unavailable"&&!y.workerReady&&!y.compileEnd&&!y.firstFrame,_e=e.unsupportedWorker===true?"unsupported-worker":e.forceWebgl===true?"WebGL-fallback":"WebGPU-first",ye=e.unsupportedWorker===true?"none":re?e.forceWebgl===true||!T?"WebGL":"WebGPU":"unknown",te=y.workerReady&&y.compileEnd&&y.firstFrame,V={schemaVersion:1,command:"browser smoke",passed:e.unsupportedWorker===true?lt:e.expectTextGenerationFailure===true?pe:re&&se&&Pe&&!M&&U.length===0&&ee.length===0,scene:s,lifecycle:y,renderer:{requested:_e,active:ye,navigatorGpu:T,workerOwned:te,fallbackDiagnostic:R},compatibility:{...C,silentMainThreadRenderer:e.unsupportedWorker===true&&(y.compileEnd||y.firstFrame)},receipt:b,textFallback:O,warnings:dt(A),rendering:{luminance:z,panelLuminance:E,threshold:l,blackFrame:M},codecs:w,hmr:g,errors:{console:U,page:ee,resolved:X}};if(V.passed&&e.unsupportedWorker!==true&&e.expectTextGenerationFailure!==true){if(V.receipt===null||V.lifecycle.backend==="unknown"||V.renderer.active!=="WebGPU"&&V.renderer.active!=="WebGL")throw new Error("A successful browser smoke cannot write runtime status without an observed backend and renderer/build receipt.");let G=V.hmr.requested,K=G?Pe:null,ne={schemaVersion:1,observedAt:new Date().toISOString(),worker:{backend:V.lifecycle.backend,renderer:V.renderer.active,protocolVersion:1},assets:{codecs:V.codecs.map(de=>({name:de.name,available:de.state==="ready",decoded:de.decoded})),resources:0},hmr:{capabilities:{scene:true,component:true,assetManifest:true,workerRestart:true},outcome:{attempted:G,succeeded:K,rollbackPreserved:G?V.hmr.evidence.rollbackPreserved:null,workerRestarted:V.hmr.restart.requested&&V.hmr.restart.workerIdentityChanged}},stats:{snapshots:k.snapshots,textures:k.textures,workerProfiler:k.snapshots>0,mainPanels:k.mainPanels},lifecycle:{state:"first frame",workerReady:V.lifecycle.workerReady,assetsReady:V.lifecycle.assetsReady,compiled:V.lifecycle.compileEnd,firstFrame:V.lifecycle.firstFrame},shaders:{mode:k.shaderMode??V.receipt.shaders.mode,pipelines:V.receipt.shaders.pipelines},...V.receipt.text===void 0?{}:{text:{state:V.receipt.text.state,atlases:V.receipt.text.atlases,glyphs:V.receipt.text.glyphs,requiredGlyphs:V.receipt.text.glyphs}},error:null};await Ji(o,ne);}return V}a(md,"runBrowserSmoke");function fd(e){let t=e.lifecycle,r=[`${e.passed?"\u2713":"\u2717"} Browser ${e.scene} \xB7 worker ${t.worker&&t.workerReady?"ready":"failed"} \xB7 assets ${t.assetsReady?"ready":"failed"} \xB7 compile ${t.compileEnd?"ready":"failed"}`,` Renderer ${e.renderer.active} \xB7 ${e.renderer.workerOwned?"worker-owned":e.renderer.requested}`,` Frame ${e.rendering.luminance.toFixed(2)} \xB7 panel ${e.rendering.panelLuminance.toFixed(2)}${e.rendering.blackFrame?" \xB7 black":""}`,` Codecs ${e.codecs.map(n=>`${n.name} ${n.state}${n.decoded?" decoded":""}`).join(" \xB7 ")||"not observed"}`];e.compatibility.fatalVisible&&r.push(` Compatibility ${e.compatibility.detail??"fatal compatibility screen visible"}`),e.textFallback.states.length>0&&r.push(` Text ${e.textFallback.states.join(" \u2192 ")}`),e.hmr.requested&&r.push(` HMR ${e.hmr.acknowledged&&e.hmr.sourceUnchanged&&Object.values(e.hmr.evidence).every(Boolean)?"ready":"failed"} \xB7 ${e.hmr.module??"unknown module"}`),e.hmr.restart.requested&&r.push(` Restart ${e.hmr.restart.error===null&&e.hmr.restart.workerIdentityChanged&&e.hmr.restart.stateReplayed?"ready":"failed"} \xB7 worker/state/stats`);for(let n of e.warnings)r.push(` Warning ${n}`);for(let n of e.errors.console)r.push(` Console ${n}`);for(let n of e.errors.page)r.push(` Page ${n}`);for(let n of e.errors.resolved)r.push(` Recovered ${n}`);e.hmr.error&&r.push(` HMR error ${e.hmr.error}`),e.hmr.restart.error&&r.push(` Restart error ${e.hmr.restart.error}`);for(let n of e.codecs)n.error&&r.push(` ${n.name} error ${n.error}`);return r.join(`
272
+ `)}a(fd,"formatBrowserSmokeReport");async function pd(e){let{chromium:t,vite:{build:r,preview:n}}=await ro(),o=await realpath(e.root),s=(e.routes===void 0||e.routes.length===0?["/"]:e.routes).map(oo),i=je(e.timeoutMs,"Browser preview timeoutMs",1e3,15*6e4,to),a=je(e.settleMs,"Browser preview settleMs",0,1e4,500),c$1={width:je(e.viewport?.width,"Browser preview viewport width",64,8192,1024),height:je(e.viewport?.height,"Browser preview viewport height",64,8192,640)},l=no(e.minimumLuminance,"Browser preview minimumLuminance",0,255,2),f=e.expectShaders??"precompiled",u=e.text===true,m=[],p,h,y=process.env.PATH;process.env.PATH=[F.join(o,"node_modules",".bin"),y].filter(Boolean).join(F.delimiter);try{await r({root:o,logLevel:"warn",...e.buildMode===void 0?{}:{mode:e.buildMode}}),p=await n({root:o,logLevel:"warn",preview:{host:"127.0.0.1",port:0,strictPort:!1,open:!1}});let w=p.httpServer?.address();if(!w||typeof w=="string")throw new Error("Vite preview did not expose an ephemeral TCP address.");let b=p.config.base.startsWith("/")?p.config.base:"/",x=`http://127.0.0.1:${w.port}${b.endsWith("/")?b:`${b}/`}`;h=await t.launch({headless:d(e.headed===!0),args:[...c()]});for(let g of s){let T=await h.newContext({viewport:c$1}),R=await T.newPage(),C=so(R),O=[],k=Re(void 0,u),A=null,v=0,S=0;try{await R.goto(new URL(g.replace(/^\/+/,""),x).href,{waitUntil:"domcontentloaded",timeout:i}),await Yt(R,u,i),a>0&&await R.waitForTimeout(a),k=Re(await Ke(R),u),A=(await Zt(R)).shaderMode;let E=await R.screenshot({type:"png"});v=Jt(E),S=await Cr(R);}catch(E){try{k=Re(await Ke(R),u),A=(await Zt(R)).shaderMode;}catch{}O.push(E instanceof Error?E.message:String(E));}finally{await T.close().catch(E=>{O.push(`Browser context cleanup failed: ${E instanceof Error?E.message:String(E)}`);});}let _=dt(C.console),H=dt([...C.page,...O]),q=k.worker&&k.workerReady&&k.assetsReady&&k.compileEnd&&k.textReady&&k.firstFrame,z=v<=l&&S<=l;m.push({route:g,passed:q&&!z&&A===f&&_.length===0&&H.length===0,lifecycle:k,shaderMode:A,rendering:{luminance:Number(v.toFixed(2)),panelLuminance:Number(S.toFixed(2)),threshold:l,blackFrame:z},errors:{console:_,page:H}});}}finally{await h?.close().catch(()=>{});let w=p?.httpServer,b=w?Reflect.get(w,"closeAllConnections"):void 0;w&&typeof b=="function"&&Reflect.apply(b,w,[]),await p?.close().catch(()=>{}),y===void 0?delete process.env.PATH:process.env.PATH=y;}return {schemaVersion:1,command:"browser preview",passed:m.length>0&&m.every(w=>w.passed),buildMode:e.buildMode??null,expectShaders:f,routes:m}}a(pd,"runBrowserPreview");function hd(e){let t=[`${e.passed?"\u2713":"\u2717"} Preview production build${e.buildMode===null?"":` \xB7 --mode ${e.buildMode}`} \xB7 expects shaders ${e.expectShaders}`];for(let r of e.routes){let n=r.lifecycle;t.push(` ${r.passed?"\u2713":"\u2717"} ${r.route} \xB7 worker ${n.worker&&n.workerReady?"ready":"failed"} \xB7 compile ${n.compileEnd?"ready":"failed"} \xB7 shaders ${r.shaderMode??"unobserved"} \xB7 frame ${r.rendering.luminance.toFixed(2)}${r.rendering.blackFrame?" \xB7 black":""}`);for(let o of r.errors.console)t.push(` Console ${o}`);for(let o of r.errors.page)t.push(` Page ${o}`);}return t.join(`
273
+ `)}a(hd,"formatBrowserPreviewReport");var go="/__three-blocks/devtools/environment-bake",xd="/__three-blocks/devtools/environment-bake/upload",jr="virtual:three-blocks-devtools/environment-bake.ts",co=`\0${jr}`,Rd=`/@id/__x00__${jr}`,vd="src/assets/environment/room-environment.pmrem.ktx2",Ir=128*1024*1024,Ed=1;async function Td(){try{let[e,t]=await Promise.all([import('playwright'),import('vite')]);return {chromium:e.chromium,createServer:t.createServer}}catch(e){throw new Error('Environment baking requires the optional "playwright" and "vite" packages. Install both in the project and run `npx playwright install chromium`.',{cause:e})}}a(Td,"loadEnvironmentBakeBrowserTools");function wo(e,t,r,n,o){let s=e??o;if(!Number.isSafeInteger(s)||s<r||s>n)throw new Error(`${t} must be an integer in ${r}...${n}.`);return s}a(wo,"boundedInteger");function Dr(e){let t=wo(e,"Environment cube size",16,1024,256);if((t&t-1)!==0)throw new Error("Environment cube size must be a power of two.");return t}a(Dr,"validateEnvironmentCubeSize");function Bd(){return xt__default}a(Bd,"zstdFunctions");function $d(e){if(!/^[0-9A-Za-z][0-9A-Za-z.+_-]{0,63}$/u.test(e))throw new Error("Browser reported an invalid Three.js revision.");return e}a($d,"boundedThreeRevision");function Ad(e){if(e.vkFormat!==VK_FORMAT_R16G16B16A16_SFLOAT)throw new Error("RoomEnvironment bake must be RGBA16F KTX2.");if(e.typeSize!==2)throw new Error("RoomEnvironment RGBA16F KTX2 must use a two-byte component type.");if(e.supercompressionScheme!==KHR_SUPERCOMPRESSION_NONE)throw new Error("Browser RoomEnvironment KTX2 must be uncompressed before deterministic encoding.");if(!Number.isSafeInteger(e.pixelWidth)||e.pixelWidth<=0||e.pixelWidth>8192||!Number.isSafeInteger(e.pixelHeight)||e.pixelHeight<=0||e.pixelHeight>8192||e.pixelDepth!==0||e.layerCount!==0||e.faceCount!==1||e.levels.length!==1||e.levels[0]===void 0)throw new Error("RoomEnvironment KTX2 has invalid CubeUV dimensions or topology.");let t=e.pixelWidth*e.pixelHeight*8;if(!Number.isSafeInteger(t)||t>Ir)throw new Error("RoomEnvironment KTX2 decoded payload exceeds the safety limit.");let r=e.levels[0],n=t+e.pixelHeight*256;if(r.levelData.byteLength<t||r.levelData.byteLength>n||r.levelData.byteLength%8!==0||r.uncompressedByteLength!==r.levelData.byteLength)throw new Error(`RoomEnvironment KTX2 level byte count ${r.levelData.byteLength} is outside the bounded RGBA16F CubeUV layout.`);return e.levels.map(o=>new Uint8Array(o.levelData))}a(Ad,"validateRawContainer");function Pd(e,t){return e.byteLength===t.byteLength&&Buffer.from(e).equals(Buffer.from(t))}a(Pd,"sameBytes");function bo(e,t){let r=Dr(t.cubeSize),n=$d(t.threeRevision);if(e.byteLength===0||e.byteLength>d$1.texture)throw new Error("RoomEnvironment KTX2 input exceeds the bounded texture size.");let o=read(e),s=Ad(o),i=t.compression??"zstd",a=Bd(),c=xt__default.constants.ZSTD_c_compressionLevel;if(i==="zstd"&&(a.zstdCompressSync===void 0||a.zstdDecompressSync===void 0||c===void 0))throw new Error("This Node.js runtime does not provide deterministic Zstandard support; use --no-zstd explicitly to opt out.");if(o.supercompressionScheme=i==="zstd"?KHR_SUPERCOMPRESSION_ZSTD:KHR_SUPERCOMPRESSION_NONE,o.levelCount=s.length,o.levels=s.map(m=>{let p=i==="zstd"?a.zstdCompressSync?.(m,{params:{[c]:19}}):void 0;return {levelData:p===void 0?m:new Uint8Array(p.buffer,p.byteOffset,p.byteLength),uncompressedByteLength:m.byteLength}}),i==="zstd")for(let m of o.dataFormatDescriptor)m.bytesPlane=[0,0,0,0,0,0,0,0];o.keyValue={KTXorientation:"rd",KTXwriter:`three-blocks RoomEnvironment \xB7 three r${n}`};let l=write(o,{keepWriter:true});if(l.byteLength===0||l.byteLength>d$1.texture)throw new Error("Encoded RoomEnvironment KTX2 exceeds the bounded texture size.");let f$1=read(l);if(f$1.vkFormat!==VK_FORMAT_R16G16B16A16_SFLOAT||f$1.pixelWidth!==o.pixelWidth||f$1.pixelHeight!==o.pixelHeight||f$1.supercompressionScheme!==o.supercompressionScheme||f$1.keyValue.KTXorientation!=="rd"||f$1.levels.length!==s.length)throw new Error("RoomEnvironment KTX2 header failed round-trip validation.");for(let m=0;m<f$1.levels.length;m+=1){let p=f$1.levels[m],h=s[m];if(p===void 0||h===void 0)throw new Error(`RoomEnvironment KTX2 level ${m} is missing after round-trip.`);let y=i==="zstd"?a.zstdDecompressSync?.(p.levelData):p.levelData;if(y===void 0||p.uncompressedByteLength!==h.byteLength||!Pd(y,h))throw new Error(`RoomEnvironment KTX2 level ${m} failed byte-for-byte round-trip validation.`)}let u=s.reduce((m,p)=>m+p.byteLength,0);return {bytes:l,metadata:{compression:i,cubeSize:r,format:"RGBA16F CubeUVReflectionMapping",height:f$1.pixelHeight,rawBytes:u,sha256:f(l),three:n,version:Ed,width:f$1.pixelWidth}}}a(bo,"encodeRoomEnvironmentKtx2");var Lr=class{static{a(this,"BakeInbox");}promise;#n=a(()=>{},"#resolve");#e=a(()=>{},"#reject");#t=false;constructor(){this.promise=new Promise((t,r)=>{this.#n=t,this.#e=r;});}receive(t){return this.#t?false:(this.#t=true,this.#n(t),true)}reject(t){this.#t||(this.#t=true,this.#e(t));}};function _d(e){if(e.url!==void 0)try{return new URL(e.url,"http://three-blocks.invalid").pathname}catch{return}}a(_d,"requestPath");function qe(e,t,r=""){e.statusCode=t,e.setHeader("Content-Type",r.startsWith("<!")?"text/html; charset=utf-8":"text/plain; charset=utf-8"),e.setHeader("Cache-Control","no-store"),e.end(r);}a(qe,"respond");function Md(e,t){return {name:"three-blocks:environment-bake",enforce:"post",resolveId(r){return r===jr?co:void 0},load(r){return r===co?t:void 0},configureServer(r){r.middlewares.use((n,o,s)=>{let i=_d(n);if(i===go&&(n.method==="GET"||n.method==="HEAD")){let m=n.method==="HEAD"?"":`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Three Blocks environment bake</title></head><body><canvas id="three-blocks-environment-baker" width="1" height="1"></canvas><script type="module" src="${Rd}"></script></body></html>`;qe(o,200,m);return}if(i!==xd)return s();if(n.method!=="POST"){qe(o,405,"POST required");return}let a=n.headers["content-type"];if(typeof a!="string"||!a.toLowerCase().startsWith("image/ktx2")){qe(o,415,"image/ktx2 required");return}let c=Number(n.headers["content-length"]??0);if(Number.isFinite(c)&&c>Ir){qe(o,413,"Bake payload exceeds 128 MiB");return}let l=[],f=0,u=false;n.on("data",m=>{f+=m.byteLength,f>Ir?u=true:l.push(m);}),n.on("error",m=>e.reject(m)),n.on("end",()=>{if(u){qe(o,413,"Bake payload exceeds 128 MiB"),e.reject(new Error("RoomEnvironment bake upload exceeded 128 MiB."));return}let m=n.headers["x-three-revision"];if(typeof m!="string"){qe(o,400,"x-three-revision required"),e.reject(new Error("RoomEnvironment upload omitted the Three.js revision."));return}let p=e.receive({bytes:new Uint8Array(Buffer.concat(l)),threeRevision:m});qe(o,p?204:409,p?"":"Bake upload already received");});});}}}a(Md,"bakePlugin");async function Cd(){let e=F.dirname(fileURLToPath(import.meta.url)),t=[F.join(e,"browser","environment-bake.js"),F.join(e,"browser","environment-bake.ts")];for(let r of t)if(await g(r))return (await j(r,d$1.semanticInput,"Environment bake browser entry")).data.toString("utf8");throw new Error("The separately built environment bake browser entry is missing.")}a(Cd,"browserEntrySource");function Od(e){return new Promise((t,r)=>{e.on("pageerror",n=>{b$1(n.message)||r(n);}),e.on("console",n=>{n.type()==="error"&&!b$1(n.text())&&r(new Error(n.text()));});})}a(Od,"pageFailure");async function Fd(e,t){await e.waitForFunction(()=>globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__!==void 0,void 0,{timeout:Math.min(t,3e4)});let r=await e.evaluate(()=>globalThis.__THREE_BLOCKS_ROOM_ENVIRONMENT_BAKE__);if(!r||typeof r!="object"||Reflect.get(r,"ok")!==true){let n=r&&typeof r=="object"?Reflect.get(r,"error"):void 0;throw new Error(typeof n=="string"?n:"Browser RoomEnvironment bake did not report success.")}}a(Fd,"readBrowserBakeResult");var So=a(async e=>{let{chromium:t,createServer:r}=await Td(),n=new Lr,o,s,i,a,c$1=false;try{let l=await Cd();o=await r({root:e.root,configFile:!1,logLevel:"silent",optimizeDeps:{noDiscovery:!0},plugins:[Md(n,l)],server:{host:"127.0.0.1",port:0,strictPort:!1}}),await o.listen();let f=o.httpServer?.address();if(!f||typeof f=="string")throw new Error("Environment bake Vite server has no ephemeral TCP address.");s=await t.launch({headless:d(e.headed),args:[...c()]}),i=await s.newContext({viewport:{width:320,height:240}});let u=await i.newPage(),m=Od(u),p=new Promise((y,w)=>{a=setTimeout(()=>w(new Error(`RoomEnvironment bake timed out after ${e.timeoutMs}ms.`)),e.timeoutMs),a.unref();});await u.goto(`http://127.0.0.1:${f.port}${go}?size=${e.size}`,{waitUntil:"domcontentloaded",timeout:Math.min(e.timeoutMs,3e4)});let h=await Promise.race([n.promise,m,p]);return await Fd(u,e.timeoutMs),h}catch(l){throw c$1=true,n.reject(l instanceof Error?l:new Error(String(l))),await n.promise.catch(()=>{}),l}finally{a&&clearTimeout(a);let l=[];if(await i?.close().catch(f=>l.push(`context: ${f instanceof Error?f.message:String(f)}`)),await s?.close().catch(f=>l.push(`browser: ${f instanceof Error?f.message:String(f)}`)),await o?.close().catch(f=>l.push(`Vite: ${f instanceof Error?f.message:String(f)}`)),!c$1&&l.length>0)throw new Error(`RoomEnvironment cleanup failed (${l.join("; ")}).`)}},"captureRoomEnvironment");function Id(e,t){let r=t??vd;if(F.isAbsolute(r)||r.length===0||r.length>2048||/[\u0000-\u001f\u007f]/u.test(r)||!r.endsWith(".ktx2"))throw new Error("Environment output must be a bounded project-relative .ktx2 path.");let n=F.resolve(e,r);if(!h(e,n)||n===e)throw new Error("Environment output escapes the project root.");return {asset:n,metadata:`${n.slice(0,-5)}.json`}}a(Id,"outputPaths");async function Ld(e,t){let r=F.relative(e,t);if(r==="")return;let n=e;for(let s of r.split(F.sep)){n=F.join(n,s),await g(n)||await mkdir(n);let i=await lstat(n);if(i.isSymbolicLink()||!i.isDirectory())throw new Error(`Environment output parent is not a real directory: ${n}.`)}let o=await realpath(t);if(!h(e,o))throw new Error("Environment output parent resolves outside the project root.")}a(Ld,"ensureSafeParent");async function lo(e){if(!await g(e))return;let t=await lstat(e);if(t.isSymbolicLink()||!t.isFile())throw new Error(`Environment output target must be a regular file: ${e}.`)}a(lo,"validateOutputTarget");async function jd(e,t,r,n){await Promise.all([lo(e),lo(r)]);let o=`${process.pid}-${randomUUID()}`,s=F.join(F.dirname(e),`.${F.basename(e)}.${o}.tmp`),i=F.join(F.dirname(r),`.${F.basename(r)}.${o}.tmp`),a=`${s}.backup`,c=`${i}.backup`,l=false,f=false,u=false,m=false;try{await Promise.all([writeFile(s,t,{flag:"wx"}),writeFile(i,n,{encoding:"utf8",flag:"wx"})]),await g(e)&&(await rename(e,a),l=!0),await g(r)&&(await rename(r,c),f=!0),await rename(s,e),u=!0,await rename(i,r),m=!0,await Promise.all([rm(a,{force:!0}),rm(c,{force:!0})]);}catch(p){throw m&&await rm(r,{force:true}),u&&await rm(e,{force:true}),f&&await rename(c,r),l&&await rename(a,e),p}finally{await Promise.all([rm(s,{force:true}),rm(i,{force:true}),rm(a,{force:true}),rm(c,{force:true})]);}}a(jd,"writeAtomicPair");function uo(e,t){return F.relative(e,t).split(F.sep).join("/")}a(uo,"portableRelative");async function Dd(e){let t=await realpath(e.root),r=Dr(e.size??256),n=wo(e.timeoutMs,"Environment bake timeoutMs",1e3,15*6e4,24e4),o=Id(t,e.output);await Ld(t,F.dirname(o.asset));let i=await(e.capture??So)({root:t,size:r,timeoutMs:n,headed:e.headed===true}),a=bo(i.bytes,{cubeSize:r,threeRevision:i.threeRevision,compression:e.compression??"zstd"}),c=`${JSON.stringify(a.metadata,null,2)}
274
+ `;await jd(o.asset,a.bytes,o.metadata,c);let l=await readFile(o.asset);if(f(l)!==a.metadata.sha256)throw new Error("Committed RoomEnvironment checksum does not match metadata.");return {schemaVersion:1,command:"environment bake",output:uo(t,o.asset),metadataOutput:uo(t,o.metadata),bytes:a.bytes.byteLength,metadata:a.metadata}}a(Dd,"bakeRoomEnvironment");function Nd(e){if(e<1e3)return `${e} B`;let t=e/1e3;return `${t>=100?Math.round(t):t.toFixed(1)} kB`}a(Nd,"formatBytes");function Hd(e){return [`\u2713 Environment ${e.metadata.width}\xD7${e.metadata.height} \xB7 CubeUV ${e.metadata.cubeSize}px \xB7 RGBA16F ${e.metadata.compression}`,` Output ${e.output} \xB7 ${Nd(e.bytes)}`,` Checksum ${e.metadata.sha256}`].join(`
275
+ `)}a(Hd,"formatEnvironmentBakeReport");var Qt=class{static{a(this,"ShaderWatchQueue");}#n;#e;#t;#r;#o;#s=false;#a=false;constructor(t){if(this.#n=t.capture,this.#e=t.debounceMs??200,this.#t=t.onError??(()=>{}),!Number.isSafeInteger(this.#e)||this.#e<0||this.#e>6e4)throw new Error("Shader watch debounce must be an integer in 0...60000ms.")}notify(){this.#a||(this.#s=true,!this.#o&&(this.#r&&clearTimeout(this.#r),this.#r=setTimeout(()=>{this.#r=void 0,this.#i();},this.#e)));}#i(){this.#a||this.#o||!this.#s||(this.#s=false,this.#o=this.#n().catch(t=>{this.#t(t instanceof Error?t:new Error(String(t)));}).finally(()=>{this.#o=void 0,this.#s&&!this.#a&&this.notify();}));}async close(){this.#a=true,this.#s=false,this.#r&&clearTimeout(this.#r),this.#r=void 0,await this.#o;}};function Wd(e){let t=e.split(F.sep).join("/");return t===""||t.startsWith("node_modules/")||t.startsWith(".git/")||t.startsWith("dist/")||t===".three-blocks"||t.startsWith(".three-blocks/")}a(Wd,"ignored");async function zd(e={}){let t=e.root??await v(e.start),r,n=new Promise(c=>{r=c;}),o=new Qt({...e.debounceMs!==void 0?{debounceMs:e.debounceMs}:{},...e.onError?{onError:e.onError}:{},capture:a(async()=>{let c=await Br({root:t,...e.config?{config:e.config}:{},...e.driver?{driver:e.driver}:{},...e.driverKind?{driverKind:e.driverKind}:{},...e.serve?{serve:e.serve}:{},...e.url?{url:e.url}:{},...e.headed!==void 0?{headed:e.headed}:{},...e.attempts!==void 0?{attempts:e.attempts}:{}});e.onResult?.(c);},"capture")}),s,i=false,a$1=a(async()=>{i||(i=true,s?.close(),await o.close(),r?.());},"close");return s=watch(t,{recursive:true},(c,l)=>{Wd(l??"")||o.notify();}),s.on("error",c=>e.onError?.(c)),e.signal&&(e.signal.aborted?await a$1():e.signal.addEventListener("abort",()=>{a$1();},{once:true})),e.initial!==false&&o.notify(),{root:t,done:n,close:a$1}}a(zd,"watchShaders");var $t=2,Po="ktx2-encoder@0.6.0",Vr=F.join(".three-blocks","assets"),Ur=F.join(Vr,"meta.json"),qd=F.join(Vr,"cache"),Xd=256*1024*1024,Jd=64*1024*1024,Ro=115e5,vo=64,Zd=163,Yd=166,Qd=167,ec=1000066e3,_o=1,Mo=2,tc=/baseColor|emissive|diffuse|sheenColor|specularColor/u,rc=/normal/iu,nc=/(?:^|[_\-.])(?:normal|nrm|nor)(?:[_\-.]|map|$)/iu,oc=/(?:rough|metal|orm\b|occlusion|ambient|[_\-.]ao(?:[_\-.]|$)|height|disp|thick|mask)/iu;function Co(e){return e.some(t=>rc.test(t))?"normal":e.some(t=>tc.test(t))||e.length===0?"color":"data"}a(Co,"presetForTextureSlots");function Oo(e){let t=F.basename(e);return nc.test(t)?"normal":oc.test(t)?"data":"color"}a(Oo,"presetForImageName");function Wr(e){let t=F.extname(e).toLowerCase();return t===".glb"?"glb":t===".png"||t===".jpg"||t===".jpeg"||t===".webp"?"image":t===".hdr"?"hdr":null}a(Wr,"assetKindFor");function Bt(e,t){let r=F.relative(e,t);return (r!==""&&!r.startsWith("..")&&!F.isAbsolute(r)?r:t).split(F.sep).join("/")}a(Bt,"portable");var Eo;function Fo(){return Eo??=Promise.all([import('ktx2-encoder'),import('sharp')]).then(([e,t])=>({encodeToKTX2:e.encodeToKTX2,sharp:t.default})),Eo}a(Fo,"loadEncoderTools");function Io(e,t){let r=t.quality==="high";return e==="hdr"?{mode:"uastc-hdr",options:{isHDR:true,imageType:"hdr",isUASTC:true,isYFlip:true,generateMipmap:true,needSupercompression:true,hdrQualityLevel:r?2:1}}:e==="color"&&!r?{mode:"etc1s",options:{isUASTC:false,qualityLevel:160,compressionLevel:2,isPerceptual:true,isSRGB:true,generateMipmap:true}}:{mode:"uastc",options:{isUASTC:true,uastcLDRQualityLevel:r?2:1,enableRDO:true,rdoQualityLevel:1,generateMipmap:true,needSupercompression:true,isPerceptual:e==="color",isSRGB:e==="color",isNormalMap:e==="normal"}}}a(Io,"encoderOptionsFor");function sc(e,t){let r=read(e),n=r.dataFormatDescriptor[0];if(n===void 0)return e;let o=t==="color"?Mo:_o;return n.transferFunction===o&&(t!=="color"||n.colorPrimaries===KHR_DF_PRIMARIES_BT709)?e:(n.transferFunction=o,t==="color"&&(n.colorPrimaries=KHR_DF_PRIMARIES_BT709),write(r,{keepWriter:true}))}a(sc,"normalizeDfdTransfer");function Lo(e,t,r,n){let o=read(e),s=o.dataFormatDescriptor[0];if(s===void 0)throw new Error(`${n} produced a KTX2 container without a data format descriptor.`);if(t==="hdr"){if(o.vkFormat!==ec||s.colorModel!==Qd)throw new Error(`${n} is not a UASTC HDR container (vkFormat ${o.vkFormat}, color model ${s.colorModel}).`)}else {let c=r==="etc1s"?Zd:Yd;if(o.vkFormat!==0||s.colorModel!==c)throw new Error(`${n} is not a ${r} container (vkFormat ${o.vkFormat}, color model ${s.colorModel}).`)}let i=t==="color",a=s.transferFunction;if(i&&a!==Mo)throw new Error(`${n} must carry the sRGB transfer function; found ${a}.`);if(!i&&a!==_o)throw new Error(`${n} must carry the linear transfer function; found ${a}.`);if(Math.max(o.pixelWidth,o.pixelHeight)>=8&&o.levels.length<2)throw new Error(`${n} is missing its mip chain.`);return {width:o.pixelWidth,height:o.pixelHeight,levels:o.levels.length}}a(Lo,"verifyKtx2");async function jo(e,t,r,n){let{encodeToKTX2:o,sharp:s}=await Fo(),i=r.maxDimension,{mode:a$1,options:c}=Io(t,r),l=performance.now(),f=false,m=sc(await o(e,{...c,imageDecoder:a(async w=>{let b=s(w),x=await b.metadata(),g=x.width??0,T=x.height??0;if(g<1||T<1)throw new Error(`${n} has no decodable dimensions.`);let R=Math.min(1,i/Math.max(g,T));g*R*T*R>Ro&&(R=Math.sqrt(Ro/(g*T)));let C=R<1,O=C?Math.max(4,Math.floor(g*R/4)*4):g,k=C?Math.max(4,Math.floor(T*R/4)*4):T,A=C?b.resize(O,k,{fit:"fill",kernel:"lanczos3"}):b,{data:v,info:S}=await A.ensureAlpha().raw().toBuffer({resolveWithObject:true});for(let _=3;_<v.byteLength;_+=4)if(v[_]!==255){f=true;break}return {data:new Uint8Array(v.buffer,v.byteOffset,v.byteLength),width:S.width,height:S.height}},"decode")}),t),{width:p,height:h,levels:y}=Lo(m,t,a$1,n);return {bytes:m,width:p,height:h,levels:y,hasAlpha:f,mode:a$1,durationMs:performance.now()-l}}a(jo,"encodeLdrTexture");function ac(e,t){let r=new TextDecoder("latin1").decode(e.subarray(0,Math.min(e.byteLength,4096))),n=/-Y\s+(\d+)\s+\+X\s+(\d+)/u.exec(r);if(n?.[1]===void 0||n[2]===void 0)throw new Error(`${t} is not a supported Radiance .hdr file (missing "-Y <h> +X <w>" resolution).`);return {width:Number(n[2]),height:Number(n[1])}}a(ac,"hdrDimensions");async function ic(e,t,r){let n=ac(e,r);if(Math.max(n.width,n.height)>t.hdrMaxDimension)throw new Error(`${r} is ${n.width}x${n.height}, above the ${t.hdrMaxDimension}px HDR cap; resize the source (HDR resize is not supported yet).`);let{encodeToKTX2:o}=await Fo(),{mode:s,options:i}=Io("hdr",t),a=performance.now(),c=await o(e,i),{width:l,height:f,levels:u}=Lo(c,"hdr",s,r);return {bytes:c,width:l,height:f,levels:u,hasAlpha:false,mode:s,durationMs:performance.now()-a}}a(ic,"encodeHdrTexture");function Do(e,t,r,n){let o=0,s=e,i=t;for(let a=0;a<r;a+=1)o+=s*i*n,s=Math.max(1,s>>1),i=Math.max(1,i>>1);return o}a(Do,"uncompressedMipBytes");function zr(e,t,r,n){let o=0,s=e,i=t;for(let a=0;a<r;a+=1)o+=Math.ceil(s/4)*Math.ceil(i/4)*n,s=Math.max(1,s>>1),i=Math.max(1,i>>1);return o}a(zr,"compressedMipBytes");function No(e,t){return e==="etc1s"&&!t?8:16}a(No,"transcodedBlockBytes");async function dc(e,t,r){let n=r.preset??Oo(t),o=`Image ${JSON.stringify(F.basename(t))}`,s=await jo(e,n,r,o),i=[`preset ${n} (${r.preset===null?"from filename":"explicit"})`];return n!=="color"&&i.push("linear DFD: consumers must treat this texture as non-color data"),i.push("compressed textures never flip: sample with glTF-style (flipY=false) UVs"),{bytes:s.bytes,metadata:{vramBytesIn:Do(s.width,s.height,s.levels,4),vramBytesOut:zr(s.width,s.height,s.levels,No(s.mode,s.hasAlpha)),textures:[{name:F.basename(t),slots:[],preset:n,mode:s.mode,width:s.width,height:s.height,bytesIn:e.byteLength,bytesOut:s.bytes.byteLength,durationMs:Math.round(s.durationMs)}],notes:i}}}a(dc,"buildImageAsset");async function cc(e,t,r){let n=`Environment ${JSON.stringify(F.basename(t))}`,o=await ic(e,r,n);return {bytes:o.bytes,metadata:{vramBytesIn:o.width*o.height*8,vramBytesOut:zr(o.width,o.height,o.levels,16),textures:[{name:F.basename(t),slots:["equirectangular"],preset:"hdr",mode:o.mode,width:o.width,height:o.height,bytesIn:e.byteLength,bytesOut:o.bytes.byteLength,durationMs:Math.round(o.durationMs)}],notes:["BC6H on BC-capable devices; transcodes to RGBA16F elsewhere"]}}}a(cc,"buildHdrAsset");async function lc(e,t,r,n){let[{Logger:o,NodeIO:s},{ALL_EXTENSIONS:i,KHRTextureBasisu:a},{dedup:c,listTextureSlots:l,meshopt:f,prune:u,weld:m},{MeshoptDecoder:p,MeshoptEncoder:h}]=await Promise.all([import('@gltf-transform/core'),import('@gltf-transform/extensions'),import('@gltf-transform/functions'),import('meshoptimizer')]);await h.ready,await p.ready;let y=new s().registerExtensions(i).registerDependencies({"meshopt.encoder":h,"meshopt.decoder":p}),w=`GLB ${JSON.stringify(F.basename(t))}`;y.setLogger(new o(o.Verbosity.SILENT));let b=await y.readBinary(e);b.setLogger(new o(o.Verbosity.SILENT));let x=b.getRoot().listTextures();if(x.length>0&&x.every(v=>v.getMimeType()==="image/ktx2")&&b.getRoot().listExtensionsUsed().some(v=>v.extensionName==="EXT_meshopt_compression"))return {bytes:e,metadata:{vramBytesIn:0,vramBytesOut:0,textures:[],notes:["already optimized (KTX2 + meshopt); copied unchanged"]}};n?.("optimizing geometry"),await b.transform(c(),u({keepAttributes:true,keepExtras:true,keepSolidTextures:true}),m(),f({encoder:h,level:"medium"}));let T=[],R=[],C=0,O=0,k=0;for(let v of x){let S=v.getName()||v.getURI()||`texture-${T.length}`,_=v.getImage(),H=v.getMimeType();if(_===null||_.byteLength===0)continue;if(H==="image/ktx2"){R.push(`${S}: already KTX2, kept`);continue}if(!/^image\/(?:png|jpeg|webp)$/u.test(H)){R.push(`${S}: unsupported ${H}, kept`);continue}let q=v.getSize();if(q!==null&&Math.max(q[0],q[1])<vo){R.push(`${S}: below ${vo}px, kept`);continue}let z=l(v),E=Co(z);n?.(`encoding ${S} (${E})`);let M=await jo(new Uint8Array(_),E,r,`${w} texture ${JSON.stringify(S)}`);v.setImage(M.bytes).setMimeType("image/ktx2");let L=v.getURI();L!==""&&v.setURI(L.replace(/\.(?:png|jpe?g|webp)$/iu,".ktx2")),k+=1,C+=Do(M.width,M.height,M.levels,4),O+=zr(M.width,M.height,M.levels,No(M.mode,M.hasAlpha)),T.push({name:S,slots:z,preset:E,mode:M.mode,width:M.width,height:M.height,bytesIn:_.byteLength,bytesOut:M.bytes.byteLength,durationMs:Math.round(M.durationMs)});}k>0&&b.createExtension(a).setRequired(true);let A=await y.writeBinary(b);return await y.readBinary(A),k>0&&R.push("requires a KTX2-wired loader (three-blocks/assets or GLTFLoader.setKTX2Loader)"),{bytes:A,metadata:{vramBytesIn:C,vramBytesOut:O,textures:T,notes:R}}}a(lc,"buildGlbAsset");function uc(e,t,r){let n=F.basename(e,F.extname(e));if(t==="glb"){let o=r===null?F.join(F.dirname(e),`${n}.tb.glb`):F.join(r,`${n}.glb`);if(F.resolve(o)===F.resolve(e))throw new Error(`Output would overwrite the input: ${JSON.stringify(e)}. Pass a different output directory.`);return o}return F.join(r??F.dirname(e),`${n}.ktx2`)}a(uc,"outputPathFor");async function Ho(e$1){let t={schemaVersion:$t,tool:{name:"three-blocks-devtools",assetOptimizeVersion:$t,encoder:Po},assets:{}},r;try{r=await readFile(e$1,"utf8");}catch(n){if(e(n)==="ENOENT")return t;throw n}if(r.length>d$1.receipt)return t;try{let n=JSON.parse(r);if(typeof n!="object"||n===null)return t;let o=n;return o.schemaVersion!==$t||typeof o.assets!="object"||o.assets===null?t:{...t,assets:{...o.assets}}}catch{return t}}a(Ho,"readReceipt");async function mc(e){let t=[];for(let r of e){let n=F.resolve(r);if((await lstat(n)).isDirectory()){let s=[n],i=0;for(;s.length>0;){let a=s.shift();if(a===void 0)break;let c=(await readdir(a,{withFileTypes:true})).sort((l,f)=>l.name.localeCompare(f.name));for(let l of c){if(i+=1,i>8192)throw new Error("Input directory expansion exceeds the 8192-entry limit.");if(l.isSymbolicLink()||l.name.startsWith("."))continue;let f=F.join(a,l.name);if(l.isDirectory()){l.name!=="three-blocks"&&s.push(f);continue}l.isFile()&&!l.name.endsWith(".tb.glb")&&Wr(l.name)!==null&&t.push(f);}}}else t.push(n);}if(t.length===0)throw new Error("No optimizable inputs found (.glb, .png, .jpg, .webp, .hdr).");return t}a(mc,"expandInputs");async function fc(e){let t=await realpath(e.root),r={maxDimension:To(e.maxDimension,2048),hdrMaxDimension:To(e.hdrMaxDimension,4096),quality:e.quality??"default",preset:e.preset??null},n=e.outDir===void 0?null:F.resolve(t,e.outDir);n!==null&&await mkdir(n,{recursive:true});let o=F.join(t,qd),s=F.join(t,Ur),i$1=f(H({version:$t,encoder:Po,...r})),a$1=await mc(e.inputs),c=[],l=[],f$1=await Ho(s);for(let[u,m]of a$1.entries()){let p=Wr(m);try{if(p===null)throw new Error(`Unsupported asset type ${JSON.stringify(F.extname(m))}; expected .glb, .png, .jpg, .webp, or .hdr (EXR sources are not supported yet \u2014 convert environments to .hdr).`);e.onProgress?.(`${F.basename(m)} (${u+1}/${a$1.length})`);let h=p==="glb"?Xd:p==="hdr"?Jd:d$1.texture,y=await j(m,h,"Asset input"),w=y.path,b=f(y.data),x=f(`${b}\0${i$1}`),g$1=p==="glb"?"glb":"ktx2",T=F.join(o,`${x}.${g$1}`),R=F.join(o,`${x}.json`),C,O,k=!1;if(e.force!==!0&&await g(T)&&await g(R))C=(await j(T,h,"Cached asset")).data,O=JSON.parse((await j(R,d$1.metadata,"Cached asset metadata")).data.toString("utf8")),k=!0;else {let S=a(H=>e.onProgress?.(`${F.basename(m)}: ${H}`),"progress"),_=p==="glb"?await lc(y.data,w,r,S):p==="hdr"?await cc(y.data,w,r):await dc(y.data,w,r);C=_.bytes,O=_.metadata,await i(T,C),await i(R,`${JSON.stringify(O,null," ")}
276
+ `);}let A=uc(w,p,n);await mkdir(F.dirname(A),{recursive:!0}),await i(A,C);let v=f(C);f$1.assets[Bt(t,w)]={kind:p,inputSha256:b,output:Bt(t,A),outputSha256:v,settingsSha256:i$1,bytesIn:y.data.byteLength,bytesOut:C.byteLength,vramBytesIn:O.vramBytesIn,vramBytesOut:O.vramBytesOut},c.push({input:Bt(t,w),output:Bt(t,A),kind:p,cached:k,bytesIn:y.data.byteLength,bytesOut:C.byteLength,vramBytesIn:O.vramBytesIn,vramBytesOut:O.vramBytesOut,textures:O.textures,notes:O.notes});}catch(h){l.push({input:Bt(t,m),error:h instanceof Error?h.message:String(h)});}}return c.length>0&&await i(s,`${JSON.stringify(f$1,null," ")}
277
+ `),{schemaVersion:1,command:"assets optimize",root:t,results:c,failed:l,bytesIn:c.reduce((u,m)=>u+m.bytesIn,0),bytesOut:c.reduce((u,m)=>u+m.bytesOut,0)}}a(fc,"optimizeAssets");function To(e,t){if(e===void 0)return t;if(!Number.isInteger(e)||e<64||e>16384)throw new Error("Texture dimension caps must be integers between 64 and 16384.");return e}a(To,"boundedDimension");function Ne(e){if(e<1e3)return `${e} B`;if(e<1e6){let r=e/1e3;return `${r>=100?Math.round(r):r.toFixed(1)} kB`}let t=e/1e6;return `${t>=100?Math.round(t):t.toFixed(2)} MB`}a(Ne,"formatBytes");function Bo(e,t){if(e===0)return "";let r=Math.round((t-e)/e*100);return r===0?"":` (${r>0?"+":""}${r}%)`}a(Bo,"percentDelta");function pc(e){let t=[];for(let r of e.results){let n=r.cached?" \xB7 cached":"";t.push(`${r.input} -> ${r.output}`),t.push(` ${Ne(r.bytesIn)} -> ${Ne(r.bytesOut)}${Bo(r.bytesIn,r.bytesOut)}${n}`),r.vramBytesOut>0&&t.push(` VRAM \u2248 ${Ne(r.vramBytesIn)} -> ${Ne(r.vramBytesOut)}`);for(let o of r.textures){let s=o.slots.length>0?` [${o.slots.join(", ")}]`:"";t.push(` ${o.name}${s} ${o.preset}/${o.mode} ${o.width}x${o.height} ${Ne(o.bytesIn)} -> ${Ne(o.bytesOut)}`);}for(let o of r.notes)t.push(` note: ${o}`);}for(let r of e.failed)t.push(`failed ${r.input}: ${r.error}`);return e.results.length>1&&t.push(`total ${Ne(e.bytesIn)} -> ${Ne(e.bytesOut)}${Bo(e.bytesIn,e.bytesOut)}`),t.join(`
278
+ `)}a(pc,"formatAssetOptimizeReport");async function hc(e,t){let r=await realpath(e),n=F.resolve(r,t);if(!await g(n))return [];let o=[],s=[n],i=0;for(;s.length>0;){let a=s.shift();if(a===void 0)break;let c=(await readdir(a,{withFileTypes:true})).sort((l,f)=>l.name.localeCompare(f.name));for(let l of c){if(i+=1,i>8192)throw new Error("Public asset discovery exceeds the 8192-entry limit.");if(l.isSymbolicLink()||l.name.startsWith("."))continue;let f=F.join(a,l.name);if(l.isDirectory()){if(a===n&&l.name==="three-blocks")continue;s.push(f);continue}if(!l.isFile()||l.name.endsWith(".tb.glb"))continue;let u=Wr(l.name);(u==="glb"||u==="hdr")&&o.push(f);}}return o.sort()}a(hc,"discoverPublicAssets");async function yc(e){let t=await realpath(e),r=await Ho(F.join(t,Ur)),n=[];for(let[o,s]of Object.entries(r.assets).sort(([i],[a])=>i.localeCompare(a))){let i=F.resolve(t,o),a=F.resolve(t,s.output),c="fresh";if(!await g(i))c="missing-input";else if(!await g(a))c="missing-output";else {let[l,f$1]=await Promise.all([readFile(i),readFile(a)]);(f(l)!==s.inputSha256||f(f$1)!==s.outputSha256)&&(c="stale");}n.push({input:o,output:s.output,kind:s.kind,state:c});}return {schemaVersion:1,command:"assets status",root:t,state:n.length===0?"empty":n.every(o=>o.state==="fresh")?"fresh":"stale",entries:n}}a(yc,"inspectAssets");function gc(e){if(e.state==="empty")return "No optimized assets recorded. Run `assets optimize <file|directory>` first.";let t=e.entries.map(r=>`${r.state==="fresh"?"fresh ":r.state.padEnd(14)} ${r.input} -> ${r.output}`);return e.state==="stale"&&t.push("Some assets moved or changed; re-run `assets optimize` on the stale inputs."),t.join(`
279
+ `)}a(gc,"formatAssetStatusReport");export{$t as ASSET_OPTIMIZE_VERSION,Vr as ASSET_RECEIPT_DIRECTORY,Ur as ASSET_RECEIPT_FILE,Et as RUNTIME_STATUS_RECEIPT_MAX_BYTES,qt as RUNTIME_STATUS_RECEIPT_PATH,Kt as RUNTIME_STATUS_RECOVERY,Qt as ShaderWatchQueue,Rt as TEXT_ATLAS_GENERATOR_VERSION,yr as TEXT_ATLAS_SCHEMA_VERSION,Dd as bakeRoomEnvironment,ir as buildGlyphSet,gr as builtinFontMetadata,So as captureRoomEnvironment,Br as captureShaders,hc as discoverPublicAssets,Vt as discoverTextContent,bo as encodeRoomEnvironmentKtx2,sr as extractCanvasTextFromHtml,ar as extractDefinedTextContent,Ar as findProjectRoot,pc as formatAssetOptimizeReport,gc as formatAssetStatusReport,hd as formatBrowserPreviewReport,fd as formatBrowserSmokeReport,Hd as formatEnvironmentBakeReport,Xn as formatShaderMatrixStatus,Jn as formatStatus,Di as formatThreeBlocksStatus,Ba as generateTextAtlases,yc as inspectAssets,qn as inspectProject,Ue as inspectShaderMatrix,Wt as inspectTextAtlases,Mi as inspectThreeBlocksStatus,fc as optimizeAssets,Re as parseBrowserSmokeLifecycle,Kn as parseRuntimeStatusReceipt,Bn as parseTextAtlasReceipt,sn as parseTextConfiguration,Oo as presetForImageName,Co as presetForTextureSlots,ba as prewarmBuiltinFont,Ae as readInstalledShaderRuntime,Ht as readTextConfiguration,pd as runBrowserPreview,md as runBrowserSmoke,Jt as screenshotLuminance,Ie as snapshotShaderInputs,ri as testShaders,Ci as threeBlocksStatusIsFresh,Dr as validateEnvironmentCubeSize,zd as watchShaders};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@three-blocks/devtools",
3
- "version": "4.0.0",
3
+ "version": "5.0.0-alpha.320.g7e6e67cd7214",
4
4
  "description": "Three Blocks devtools command engine for npx three-blocks; the runtime lives in three-blocks/devtools and the Vite plugin",
5
5
  "keywords": [
6
6
  "three",
@@ -85,7 +85,7 @@
85
85
  "@types/three": "0.185.0",
86
86
  "create-vite": "9.1.1",
87
87
  "playwright": "^1.61.1",
88
- "three-blocks": "0.5.0",
88
+ "three-blocks": "0.6.0-alpha.320.g7e6e67cd7214",
89
89
  "tsup": "^8.0.0",
90
90
  "typescript": "^5.9.3",
91
91
  "vite": "^7.2.2",
@@ -97,7 +97,7 @@
97
97
  "peerDependencies": {
98
98
  "playwright": "^1.61.1",
99
99
  "three": ">=0.185.0",
100
- "three-blocks": ">=0.5.0 <0.6.0",
100
+ "three-blocks": "0.6.0-alpha.320.g7e6e67cd7214",
101
101
  "typescript": ">=5.9.3 <7.0.0",
102
102
  "vite": ">=7.2.2 <9.0.0"
103
103
  },
@@ -111,5 +111,9 @@
111
111
  "vite": {
112
112
  "optional": true
113
113
  }
114
+ },
115
+ "threeBlocks": {
116
+ "channel": "alpha",
117
+ "site": "https://preprod.threejs-blocks.com"
114
118
  }
115
119
  }
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
- import {d}from'./chunk-EE64MV27.js';import'./chunk-ZT6T2W4B.js';import'./chunk-NPLE7PPF.js';import'./chunk-65VEJRRT.js';import {b,a as a$1,c,h,d as d$1,f}from'./chunk-5L2VS3BN.js';import {a}from'./chunk-HOZDD6PW.js';import {readFile,lstat,readdir,realpath,mkdir}from'fs/promises';import i from'path';import {read,KHR_DF_PRIMARIES_BT709,write}from'ktx-parse';var z=1,ie="ktx2-encoder@0.6.0",ae=i.join(".three-blocks","assets"),de=i.join(ae,"meta.json"),be=i.join(ae,"cache"),xe=256*1024*1024,we=64*1024*1024,ee=115e5,te=64,Te=163,Ae=166,Ee=167,Re=1000066e3,ue=1,ce=2,$e=/baseColor|emissive|diffuse|sheenColor|specularColor/u,Se=/normal/iu,Oe=/(?:^|[_\-.])(?:normal|nrm|nor)(?:[_\-.]|map|$)/iu,Me=/(?:rough|metal|orm\b|occlusion|ambient|[_\-.]ao(?:[_\-.]|$)|height|disp|thick|mask)/iu;function ve(t){return t.some(e=>Se.test(e))?"normal":t.some(e=>$e.test(e))||t.length===0?"color":"data"}a(ve,"presetForTextureSlots");function _e(t){let e=i.basename(t);return Oe.test(e)?"normal":Me.test(e)?"data":"color"}a(_e,"presetForImageName");function q(t){let e=i.extname(t).toLowerCase();return e===".glb"?"glb":e===".png"||e===".jpg"||e===".jpeg"||e===".webp"?"image":e===".hdr"?"hdr":null}a(q,"assetKindFor");function k(t,e){let r=i.relative(t,e);return (r!==""&&!r.startsWith("..")&&!i.isAbsolute(r)?r:e).split(i.sep).join("/")}a(k,"portable");var V;function le(){return V??=Promise.all([import('ktx2-encoder'),import('sharp')]).then(([t,e])=>({encodeToKTX2:t.encodeToKTX2,sharp:e.default})),V}a(le,"loadEncoderTools");function me(t,e){let r=e.quality==="high";return t==="hdr"?{mode:"uastc-hdr",options:{isHDR:true,imageType:"hdr",isUASTC:true,isYFlip:true,generateMipmap:true,needSupercompression:true,hdrQualityLevel:r?2:1}}:t==="color"&&!r?{mode:"etc1s",options:{isUASTC:false,qualityLevel:160,compressionLevel:2,isPerceptual:true,isSRGB:true,generateMipmap:true}}:{mode:"uastc",options:{isUASTC:true,uastcLDRQualityLevel:r?2:1,enableRDO:true,rdoQualityLevel:1,generateMipmap:true,needSupercompression:true,isPerceptual:t==="color",isSRGB:t==="color",isNormalMap:t==="normal"}}}a(me,"encoderOptionsFor");function Ie(t,e){let r=read(t),n=r.dataFormatDescriptor[0];if(n===void 0)return t;let s=e==="color"?ce:ue;return n.transferFunction===s&&(e!=="color"||n.colorPrimaries===KHR_DF_PRIMARIES_BT709)?t:(n.transferFunction=s,e==="color"&&(n.colorPrimaries=KHR_DF_PRIMARIES_BT709),write(r,{keepWriter:true}))}a(Ie,"normalizeDfdTransfer");function he(t,e,r,n){let s=read(t),o=s.dataFormatDescriptor[0];if(o===void 0)throw new Error(`${n} produced a KTX2 container without a data format descriptor.`);if(e==="hdr"){if(s.vkFormat!==Re||o.colorModel!==Ee)throw new Error(`${n} is not a UASTC HDR container (vkFormat ${s.vkFormat}, color model ${o.colorModel}).`)}else {let c=r==="etc1s"?Te:Ae;if(s.vkFormat!==0||o.colorModel!==c)throw new Error(`${n} is not a ${r} container (vkFormat ${s.vkFormat}, color model ${o.colorModel}).`)}let d=e==="color",u=o.transferFunction;if(d&&u!==ce)throw new Error(`${n} must carry the sRGB transfer function; found ${u}.`);if(!d&&u!==ue)throw new Error(`${n} must carry the linear transfer function; found ${u}.`);if(Math.max(s.pixelWidth,s.pixelHeight)>=8&&s.levels.length<2)throw new Error(`${n} is missing its mip chain.`);return {width:s.pixelWidth,height:s.pixelHeight}}a(he,"verifyKtx2");async function ye(t,e,r,n){let{encodeToKTX2:s,sharp:o}=await le(),d=r.maxDimension,{mode:u,options:c}=me(e,r),l=performance.now(),b=Ie(await s(t,{...c,imageDecoder:a(async w=>{let m=o(w),E=await m.metadata(),h=E.width??0,x=E.height??0;if(h<1||x<1)throw new Error(`${n} has no decodable dimensions.`);let v=Math.min(1,d/Math.max(h,x));h*v*x*v>ee&&(v=Math.sqrt(ee/(h*x)));let R=v<1,$=R?Math.max(4,Math.floor(h*v/4)*4):h,T=R?Math.max(4,Math.floor(x*v/4)*4):x,A=R?m.resize($,T,{fit:"fill",kernel:"lanczos3"}):m,{data:O,info:M}=await A.ensureAlpha().raw().toBuffer({resolveWithObject:true});return {data:new Uint8Array(O.buffer,O.byteOffset,O.byteLength),width:M.width,height:M.height}},"decode")}),e),{width:f,height:g}=he(b,e,u,n);return {bytes:b,width:f,height:g,mode:u,durationMs:performance.now()-l}}a(ye,"encodeLdrTexture");function De(t,e){let r=new TextDecoder("latin1").decode(t.subarray(0,Math.min(t.byteLength,4096))),n=/-Y\s+(\d+)\s+\+X\s+(\d+)/u.exec(r);if(n?.[1]===void 0||n[2]===void 0)throw new Error(`${e} is not a supported Radiance .hdr file (missing "-Y <h> +X <w>" resolution).`);return {width:Number(n[2]),height:Number(n[1])}}a(De,"hdrDimensions");async function Le(t,e,r){let n=De(t,r);if(Math.max(n.width,n.height)>e.hdrMaxDimension)throw new Error(`${r} is ${n.width}x${n.height}, above the ${e.hdrMaxDimension}px HDR cap; resize the source (HDR resize is not supported yet).`);let{encodeToKTX2:s}=await le(),{mode:o,options:d}=me("hdr",e),u=performance.now(),c=await s(t,d),{width:l,height:p}=he(c,"hdr",o,r);return {bytes:c,width:l,height:p,mode:o,durationMs:performance.now()-u}}a(Le,"encodeHdrTexture");function B(t,e,r){let n=t*e*1.3333333333333333;return Math.round(r==="source-hdr"?n*8:r==="source-ldr"?n*4:n*(r==="etc1s"?.5:1))}a(B,"textureVram");async function Fe(t,e,r){let n=r.preset??_e(e),s=`Image ${JSON.stringify(i.basename(e))}`,o=await ye(t,n,r,s),d=[`preset ${n} (${r.preset===null?"from filename":"explicit"})`];return n!=="color"&&d.push("linear DFD: consumers must treat this texture as non-color data"),d.push("compressed textures never flip: sample with glTF-style (flipY=false) UVs"),{bytes:o.bytes,metadata:{vramBytesIn:B(o.width,o.height,"source-ldr"),vramBytesOut:B(o.width,o.height,o.mode),textures:[{name:i.basename(e),slots:[],preset:n,mode:o.mode,width:o.width,height:o.height,bytesIn:t.byteLength,bytesOut:o.bytes.byteLength,durationMs:Math.round(o.durationMs)}],notes:d}}}a(Fe,"buildImageAsset");async function Be(t,e,r){let n=`Environment ${JSON.stringify(i.basename(e))}`,s=await Le(t,r,n);return {bytes:s.bytes,metadata:{vramBytesIn:B(s.width,s.height,"source-hdr"),vramBytesOut:B(s.width,s.height,s.mode),textures:[{name:i.basename(e),slots:["equirectangular"],preset:"hdr",mode:s.mode,width:s.width,height:s.height,bytesIn:t.byteLength,bytesOut:s.bytes.byteLength,durationMs:Math.round(s.durationMs)}],notes:["BC6H on BC-capable devices; transcodes to RGBA16F elsewhere"]}}}a(Be,"buildHdrAsset");async function Ne(t,e,r,n){let[{Logger:s,NodeIO:o},{ALL_EXTENSIONS:d,KHRTextureBasisu:u},{dedup:c,listTextureSlots:l,meshopt:p,prune:b,weld:f},{MeshoptDecoder:g,MeshoptEncoder:w}]=await Promise.all([import('@gltf-transform/core'),import('@gltf-transform/extensions'),import('@gltf-transform/functions'),import('meshoptimizer')]);await w.ready,await g.ready;let m=new o().registerExtensions(d).registerDependencies({"meshopt.encoder":w,"meshopt.decoder":g}),E=`GLB ${JSON.stringify(i.basename(e))}`;m.setLogger(new s(s.Verbosity.SILENT));let h=await m.readBinary(t);h.setLogger(new s(s.Verbosity.SILENT));let x=h.getRoot().listTextures();if(x.length>0&&x.every(y=>y.getMimeType()==="image/ktx2")&&h.getRoot().listExtensionsUsed().some(y=>y.extensionName==="EXT_meshopt_compression"))return {bytes:t,metadata:{vramBytesIn:0,vramBytesOut:0,textures:[],notes:["already optimized (KTX2 + meshopt); copied unchanged"]}};n?.("optimizing geometry"),await h.transform(c(),b({keepAttributes:true,keepExtras:true,keepSolidTextures:true}),f(),p({encoder:w,level:"medium"}));let R=[],$=[],T=0,A=0,O=0;for(let y of x){let _=y.getName()||y.getURI()||`texture-${R.length}`,D=y.getImage(),N=y.getMimeType();if(D===null||D.byteLength===0)continue;if(N==="image/ktx2"){$.push(`${_}: already KTX2, kept`);continue}if(!/^image\/(?:png|jpeg|webp)$/u.test(N)){$.push(`${_}: unsupported ${N}, kept`);continue}let j=y.getSize();if(j!==null&&Math.max(j[0],j[1])<te){$.push(`${_}: below ${te}px, kept`);continue}let G=l(y),K=ve(G);n?.(`encoding ${_} (${K})`);let S=await ye(new Uint8Array(D),K,r,`${E} texture ${JSON.stringify(_)}`);y.setImage(S.bytes).setMimeType("image/ktx2");let J=y.getURI();J!==""&&y.setURI(J.replace(/\.(?:png|jpe?g|webp)$/iu,".ktx2")),O+=1,T+=B(S.width,S.height,"source-ldr"),A+=B(S.width,S.height,S.mode),R.push({name:_,slots:G,preset:K,mode:S.mode,width:S.width,height:S.height,bytesIn:D.byteLength,bytesOut:S.bytes.byteLength,durationMs:Math.round(S.durationMs)});}O>0&&h.createExtension(u).setRequired(true);let M=await m.writeBinary(h);return await m.readBinary(M),O>0&&$.push("requires a KTX2-wired loader (three-blocks/assets or GLTFLoader.setKTX2Loader)"),{bytes:M,metadata:{vramBytesIn:T,vramBytesOut:A,textures:R,notes:$}}}a(Ne,"buildGlbAsset");function Pe(t,e,r){let n=i.basename(t,i.extname(t));if(e==="glb"){let s=r===null?i.join(i.dirname(t),`${n}.tb.glb`):i.join(r,`${n}.glb`);if(i.resolve(s)===i.resolve(t))throw new Error(`Output would overwrite the input: ${JSON.stringify(t)}. Pass a different output directory.`);return s}return i.join(r??i.dirname(t),`${n}.ktx2`)}a(Pe,"outputPathFor");async function pe(t){let e={schemaVersion:z,tool:{name:"three-blocks-devtools",assetOptimizeVersion:z,encoder:ie},assets:{}},r;try{r=await readFile(t,"utf8");}catch(n){if(b(n)==="ENOENT")return e;throw n}if(r.length>a$1.receipt)return e;try{let n=JSON.parse(r);if(typeof n!="object"||n===null)return e;let s=n;return s.schemaVersion!==z||typeof s.assets!="object"||s.assets===null?e:{...e,assets:{...s.assets}}}catch{return e}}a(pe,"readReceipt");async function ke(t){let e=[];for(let r of t){let n=i.resolve(r);if((await lstat(n)).isDirectory()){let o=(await readdir(n,{withFileTypes:true})).sort((d,u)=>d.name.localeCompare(u.name));for(let d of o)d.isFile()&&q(d.name)!==null&&e.push(i.join(n,d.name));}else e.push(n);}if(e.length===0)throw new Error("No optimizable inputs found (.glb, .png, .jpg, .webp, .hdr).");return e}a(ke,"expandInputs");async function Xe(t){let e=await realpath(t.root),r={maxDimension:re(t.maxDimension,2048),hdrMaxDimension:re(t.hdrMaxDimension,4096),quality:t.quality??"default",preset:t.preset??null},n=t.outDir===void 0?null:i.resolve(e,t.outDir);n!==null&&await mkdir(n,{recursive:true});let s=i.join(e,be),o=i.join(e,de),d$2=c(d({version:z,encoder:ie,...r})),u=await ke(t.inputs),c$1=[],l=[],p=await pe(o);for(let[b,f$1]of u.entries()){let g=q(f$1);try{if(g===null)throw new Error(`Unsupported asset type ${JSON.stringify(i.extname(f$1))}; expected .glb, .png, .jpg, .webp, or .hdr (EXR sources are not supported yet \u2014 convert environments to .hdr).`);t.onProgress?.(`${i.basename(f$1)} (${b+1}/${u.length})`);let w=g==="glb"?xe:g==="hdr"?we:a$1.texture,m=await h(f$1,w,"Asset input"),E=m.path,h$1=c(m.data),x=c(`${h$1}\0${d$2}`),v=g==="glb"?"glb":"ktx2",R=i.join(s,`${x}.${v}`),$=i.join(s,`${x}.json`),T,A,O=!1;if(t.force!==!0&&await d$1(R)&&await d$1($))T=(await h(R,w,"Cached asset")).data,A=JSON.parse((await h($,a$1.metadata,"Cached asset metadata")).data.toString("utf8")),O=!0;else {let _=a(N=>t.onProgress?.(`${i.basename(f$1)}: ${N}`),"progress"),D=g==="glb"?await Ne(m.data,E,r,_):g==="hdr"?await Be(m.data,E,r):await Fe(m.data,E,r);T=D.bytes,A=D.metadata,await f(R,T),await f($,`${JSON.stringify(A,null," ")}
3
- `);}let M=Pe(E,g,n);await mkdir(i.dirname(M),{recursive:!0}),await f(M,T);let y=c(T);p.assets[k(e,E)]={kind:g,inputSha256:h$1,output:k(e,M),outputSha256:y,settingsSha256:d$2,bytesIn:m.data.byteLength,bytesOut:T.byteLength},c$1.push({input:k(e,E),output:k(e,M),kind:g,cached:O,bytesIn:m.data.byteLength,bytesOut:T.byteLength,vramBytesIn:A.vramBytesIn,vramBytesOut:A.vramBytesOut,textures:A.textures,notes:A.notes});}catch(w){l.push({input:k(e,f$1),error:w instanceof Error?w.message:String(w)});}}return c$1.length>0&&await f(o,`${JSON.stringify(p,null," ")}
4
- `),{schemaVersion:1,command:"assets optimize",root:e,results:c$1,failed:l,bytesIn:c$1.reduce((b,f)=>b+f.bytesIn,0),bytesOut:c$1.reduce((b,f)=>b+f.bytesOut,0)}}a(Xe,"optimizeAssets");function re(t,e){if(t===void 0)return e;if(!Number.isInteger(t)||t<64||t>16384)throw new Error("Texture dimension caps must be integers between 64 and 16384.");return t}a(re,"boundedDimension");function I(t){if(t<1e3)return `${t} B`;if(t<1e6){let r=t/1e3;return `${r>=100?Math.round(r):r.toFixed(1)} kB`}let e=t/1e6;return `${e>=100?Math.round(e):e.toFixed(2)} MB`}a(I,"formatBytes");function ne(t,e){if(t===0)return "";let r=Math.round((e-t)/t*100);return r===0?"":` (${r>0?"+":""}${r}%)`}a(ne,"percentDelta");function Ve(t){let e=[];for(let r of t.results){let n=r.cached?" \xB7 cached":"";e.push(`${r.input} -> ${r.output}`),e.push(` ${I(r.bytesIn)} -> ${I(r.bytesOut)}${ne(r.bytesIn,r.bytesOut)}${n}`),r.vramBytesOut>0&&e.push(` VRAM \u2248 ${I(r.vramBytesIn)} -> ${I(r.vramBytesOut)}`);for(let s of r.textures){let o=s.slots.length>0?` [${s.slots.join(", ")}]`:"";e.push(` ${s.name}${o} ${s.preset}/${s.mode} ${s.width}x${s.height} ${I(s.bytesIn)} -> ${I(s.bytesOut)}`);}for(let s of r.notes)e.push(` note: ${s}`);}for(let r of t.failed)e.push(`failed ${r.input}: ${r.error}`);return t.results.length>1&&e.push(`total ${I(t.bytesIn)} -> ${I(t.bytesOut)}${ne(t.bytesIn,t.bytesOut)}`),e.join(`
5
- `)}a(Ve,"formatAssetOptimizeReport");async function He(t,e){let r=await realpath(t),n=i.resolve(r,e);if(!await d$1(n))return [];let s=[],o=[n],d=0;for(;o.length>0;){let u=o.shift();if(u===void 0)break;let c=(await readdir(u,{withFileTypes:true})).sort((l,p)=>l.name.localeCompare(p.name));for(let l of c){if(d+=1,d>8192)throw new Error("Public asset discovery exceeds the 8192-entry limit.");if(l.isSymbolicLink()||l.name.startsWith("."))continue;let p=i.join(u,l.name);if(l.isDirectory()){if(u===n&&l.name==="three-blocks")continue;o.push(p);continue}if(!l.isFile()||l.name.endsWith(".tb.glb"))continue;let b=q(l.name);(b==="glb"||b==="hdr")&&s.push(p);}}return s.sort()}a(He,"discoverPublicAssets");async function qe(t){let e=await realpath(t),r=await pe(i.join(e,de)),n=[];for(let[s,o]of Object.entries(r.assets).sort(([d],[u])=>d.localeCompare(u))){let d=i.resolve(e,s),u=i.resolve(e,o.output),c$1="fresh";if(!await d$1(d))c$1="missing-input";else if(!await d$1(u))c$1="missing-output";else {let[l,p]=await Promise.all([readFile(d),readFile(u)]);(c(l)!==o.inputSha256||c(p)!==o.outputSha256)&&(c$1="stale");}n.push({input:s,output:o.output,kind:o.kind,state:c$1});}return {schemaVersion:1,command:"assets status",root:e,state:n.length===0?"empty":n.every(s=>s.state==="fresh")?"fresh":"stale",entries:n}}a(qe,"inspectAssets");function Ge(t){if(t.state==="empty")return "No optimized assets recorded. Run `assets optimize <file|directory>` first.";let e=t.entries.map(r=>`${r.state==="fresh"?"fresh ":r.state.padEnd(14)} ${r.input} -> ${r.output}`);return t.state==="stale"&&e.push("Some assets moved or changed; re-run `assets optimize` on the stale inputs."),e.join(`
6
- `)}a(Ge,"formatAssetStatusReport");function Je(){V=void 0;}a(Je,"resetAssetOptimizeToolsForTests");export{z as ASSET_OPTIMIZE_VERSION,ae as ASSET_RECEIPT_DIRECTORY,de as ASSET_RECEIPT_FILE,He as discoverPublicAssets,Ve as formatAssetOptimizeReport,Ge as formatAssetStatusReport,qe as inspectAssets,Xe as optimizeAssets,_e as presetForImageName,ve as presetForTextureSlots,Je as resetAssetOptimizeToolsForTests};