@vitreajs/vitrea 0.1.0
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/LICENSE +202 -0
- package/NOTICE +36 -0
- package/README.md +359 -0
- package/dist/chunk-ST6GFEQT.js +502 -0
- package/dist/chunk-ST6GFEQT.js.map +1 -0
- package/dist/dist-FGJI5LQM.js +3573 -0
- package/dist/dist-FGJI5LQM.js.map +1 -0
- package/dist/index.d.ts +2450 -0
- package/dist/index.js +1001 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../renderer-webgpu/src/wgsl/analysis.ts","../../renderer-webgpu/src/color.ts","../../renderer-webgpu/src/material.ts","../../renderer-webgpu/src/analysis.ts","../../renderer-webgpu/src/errors.ts","../../renderer-webgpu/src/backdrop.ts","../../renderer-webgpu/src/device.ts","../../renderer-webgpu/src/governor.ts","../../renderer-webgpu/src/pipeline-cache.ts","../../renderer-webgpu/src/texture-pool.ts","../../renderer-webgpu/src/gpu-context.ts","../../renderer-webgpu/src/render-model.ts","../../renderer-webgpu/src/instances.ts","../../renderer-webgpu/src/timing.ts","../../renderer-webgpu/src/wgsl/cross-check.ts","../../renderer-webgpu/src/wgsl/backdrop.ts","../../renderer-webgpu/src/wgsl/field.ts","../../renderer-webgpu/src/wgsl/highlight.ts","../../renderer-webgpu/src/wgsl/optics.ts","../../renderer-webgpu/src/wgsl/prelude.ts","../../renderer-webgpu/src/wgsl/index.ts","../../renderer-webgpu/src/passes.ts","../../renderer-webgpu/src/pyramid-plan.ts","../../renderer-webgpu/src/rebuild-ledger.ts","../../renderer-webgpu/src/pyramid.ts","../../renderer-webgpu/src/renderer.ts"],"names":["smoothstep","shape","level"],"mappings":";;;AAkCO,IAAM,kBAAA,GAAqB;AAC3B,IAAM,aAAA,GAAgB;AAGtB,IAAM,qBAAA,GAAwB;AAE9B,IAAM,kBAAA,GAAqB,CAAA;;;;;;;;;;;;0CAYQ,kBAAkB,CAAA;0CAClB,kBAAkB,CAAA;0CAClB,kBAAkB,CAAA;;;;;;;;;;2BAUjC,kBAAkB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;cAwB/B,kBAAkB,CAAA;;;;;;;;uBAQT,kBAAkB,CAAA;iBACxB,kBAAkB,CAAA;;;;;;;;;;;;;;;;;;;;;;;AC1D5B,IAAM,qBAAA,GAAwB,CAAC,MAAA,EAAQ,YAAY;AAKnD,IAAM,oBAAA,GAAuB,CAAC,eAAA,EAAiB,iBAAA,EAAmB,QAAQ;AAK1E,IAAM,sBAAA,GAA2C;AAGjD,IAAM,qBAAA,GAA0C;AAEvD,IAAM,kBAAA,GAAqB,QAAA;AAC3B,IAAM,mBAAA,GAAsB,OAAA;AAC5B,IAAM,UAAA,GAAa,KAAA;AACnB,IAAM,UAAA,GAAa,KAAA;AACnB,IAAM,WAAA,GAAc,KAAA;AACpB,IAAM,UAAA,GAAa,GAAA;AAGb,SAAU,oBAAoB,CAAA,EAAS;AAC3C,EAAA,IAAI,CAAA,IAAK,mBAAA;AAAqB,IAAA,OAAO,CAAA,GAAI,UAAA;AACzC,EAAA,OAAO,IAAA,CAAK,GAAA,CAAA,CAAK,CAAA,GAAI,WAAA,IAAe,YAAY,UAAU,CAAA;AAC5D;AAGM,SAAU,oBAAoB,CAAA,EAAS;AAC3C,EAAA,IAAI,CAAA,IAAK,kBAAA;AAAoB,IAAA,OAAO,CAAA,GAAI,UAAA;AACxC,EAAA,OAAO,aAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAA,GAAI,UAAU,CAAA,GAAI,WAAA;AACpD;AAIO,IAAM,YAAA,GAAe,CAAC,CAAA,KAAgB;EAC3C,mBAAA,CAAoB,CAAA,CAAE,CAAC,CAAC,CAAA;EACxB,mBAAA,CAAoB,CAAA,CAAE,CAAC,CAAC,CAAA;EACxB,mBAAA,CAAoB,CAAA,CAAE,CAAC,CAAC;;AAGnB,IAAM,YAAA,GAAe,CAAC,CAAA,KAAgB;EAC3C,mBAAA,CAAoB,CAAA,CAAE,CAAC,CAAC,CAAA;EACxB,mBAAA,CAAoB,CAAA,CAAE,CAAC,CAAC,CAAA;EACxB,mBAAA,CAAoB,CAAA,CAAE,CAAC,CAAC;;AAWnB,IAAM,iBAAA,GAAyB,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAEvD,SAAU,kBAAkB,MAAA,EAAW;AAC3C,EAAA,OACE,OAAO,CAAC,CAAA,GAAI,iBAAA,CAAkB,CAAC,IAC/B,MAAA,CAAO,CAAC,CAAA,GAAI,iBAAA,CAAkB,CAAC,CAAA,GAC/B,MAAA,CAAO,CAAC,CAAA,GAAI,kBAAkB,CAAC,CAAA;AAEnC;AAUA,IAAM,UAAA,GAA6B;EACjC,CAAC,iBAAA,EAAmB,oBAAoB,CAAC,CAAA;EACzC,CAAC,kBAAA,EAAoB,mBAAmB,CAAC,CAAA;EACzC,CAAC,kBAAA,EAAoB,oBAAoB,iBAAiB;;AAGtD,SAAU,sBAAsB,QAAA,EAAa;AACjD,EAAA,MAAM,MAAgB,EAAA;AACtB,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,IAAA,GAAA,CAAI,IAAA,CACF,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,GAAA,CAAI,CAAC,CAAA,GAAI,QAAA,CAAS,CAAC,CAAA,GAAI,IAAI,CAAC,CAAA,GAAI,QAAA,CAAS,CAAC,CAAA,GAAI,GAAA,CAAI,CAAC,CAAA,GAAI,QAAA,CAAS,CAAC,CAAC,CAAC,CAAC,CAAA;AAEhG,EAAA;AACA,EAAA,OAAO,CAAC,IAAI,CAAC,CAAA,EAAa,IAAI,CAAC,CAAA,EAAa,GAAA,CAAI,CAAC,CAAW,CAAA;AAC9D;AASM,SAAU,kBAAkB,KAAA,EAAyB;AACzD,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,OAAO,IAAI,YAAA,CAAa,CAAC,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AACrD,EAAA;AACA,EAAA,MAAM,IAAA,GAAO,UAAA;AACb,EAAA,OAAO,IAAI,YAAA,CAAa;AACtB,IAAA,GAAI,KAAK,CAAC,CAAA;AACV,IAAA,GAAI,KAAK,CAAC,CAAA;AACV,IAAA,GAAI,KAAK,CAAC;AACX,GAAA,CAAA;AACH;AASM,SAAU,uBAAuB,IAAA,EAAuB;AAC5D,EAAA,QAAQ,IAAA;IACN,KAAK,eAAA;AACH,MAAA,OAAO,CAAA;IACT,KAAK,iBAAA;AACH,MAAA,OAAO,CAAA;IACT,KAAK,QAAA;AACH,MAAA,OAAO,CAAA;AACX;AACF;AAMM,SAAU,YAAA,CAAa,QAAa,KAAA,EAAa;AACrD,EAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAC,CAAA;AACxC,EAAA,MAAM,OAAA,GAAU,aAAa,MAAM,CAAA;AACnC,EAAA,OAAO,CAAC,OAAA,CAAQ,CAAC,CAAA,GAAI,CAAA,EAAG,OAAA,CAAQ,CAAC,CAAA,GAAI,CAAA,EAAG,OAAA,CAAQ,CAAC,CAAA,GAAI,GAAG,CAAC,CAAA;AAC3D;AAGM,SAAU,iBAAA,CAAkB,QAAa,KAAA,EAAa;AAC1D,EAAA,OAAO,aAAa,MAAA,EAAQ,KAAK,EAAE,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,CAAA,GAAI,GAAG,CAAC,CAAA;AAC7F;;;ACpJO,IAAM,iBAAA,GAAoB,CAAC,MAAA,EAAQ,aAAA,EAAe,MAAM;AAIzD,SAAU,eAAe,OAAA,EAA0B;AACvD,EAAA,OAAO,iBAAA,CAAkB,QAAQ,OAAO,CAAA;AAC1C;AAiBM,SAAU,2BAA2B,MAAA,EAA0B;AACnE,EAAA,QAAQ,OAAO,UAAA;IACb,KAAK,SAAA;AACH,MAAA,OAAO,MAAA;IACT,KAAK,SAAA;AACH,MAAA,OAAO,aAAA;IACT,KAAK,MAAA;AACH,MAAA,OAAO,MAAA;AACX;AACF;AAGM,SAAU,mBAAA,CAAoB,GAAsB,CAAA,EAAoB;AAC5E,EAAA,OAAO,eAAe,CAAC,CAAA,IAAK,cAAA,CAAe,CAAC,IAAI,CAAA,GAAI,CAAA;AACtD;AAGO,IAAM,iBAAA,GAAoB,CAAC,SAAA,EAAW,OAAO;AAoIpD,IAAM,eAAA,GAAuB,CAAC,CAAA,EAAG,CAAA,EAAG,CAAC,CAAA;AAM9B,IAAM,wBAAA,GAA2B;AAMlC,SAAU,yBAAA,CACd,OAAA,EACA,SAAA,EACA,IAAA,GAAe,wBAAA,EAAwB;AAEvC,EAAA,QAAQ,SAAA;IACN,KAAK,SAAA;AACH,MAAA,OAAO,OAAA;IACT,KAAK,WAAA;AACH,MAAA,OAAO,OAAA,GAAU,QAAQ,CAAA,GAAI,OAAA,CAAA;IAC/B,KAAK,QAAA;AACH,MAAA,OAAO,CAAA;AACX;AACF;AAEO,IAAM,wBAAA,GAA4C;EACvD,MAAA,EAAQ;;;;IAIN,OAAA,EAAS;MACP,SAAA,EAAW,CAAA;AACX,MAAA,IAAA,EAAM,aAAa,eAAe,CAAA;;;;;;;;;;MAUlC,SAAA,EAAW,IAAA;MACX,QAAA,EAAU,GAAA;MACV,QAAA,EAAU,IAAA;MACV,aAAA,EAAe,CAAA;MACf,YAAA,EAAc,IAAA;MACd,WAAA,EAAa,IAAA;MACb,WAAA,EAAa,IAAA;AACb,MAAA,SAAA,EAAW,aAAa,eAAe;;;IAGzC,KAAA,EAAO;MACL,SAAA,EAAW,CAAA;AACX,MAAA,IAAA,EAAM,aAAa,eAAe,CAAA;MAClC,SAAA,EAAW,GAAA;MACX,QAAA,EAAU,IAAA;MACV,QAAA,EAAU,IAAA;MACV,aAAA,EAAe,CAAA;MACf,YAAA,EAAc,IAAA;MACd,WAAA,EAAa,IAAA;MACb,WAAA,EAAa,GAAA;AACb,MAAA,SAAA,EAAW,aAAa,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6B3C,EAAA,gBAAA,EAAkB,aAAa,eAAe,CAAA;AAC9C,EAAA,iBAAA,EAAmB,aAAa,eAAe,CAAA;EAC/C,oBAAA,EAAsB,IAAA;EACtB,qBAAA,EAAuB,IAAA;EAEvB,eAAA,EAAiB;IACf,IAAA,EAAM,CAAA;IACN,WAAA,EAAa,IAAA;IACb,IAAA,EAAM;;EAGR,WAAA,EAAa,EAAA;EACb,WAAA,EAAa,GAAA;EACb,eAAA,EAAiB,GAAA;EAEjB,gBAAA,EAAkB,IAAA;EAClB,cAAA,EAAgB,GAAA;EAEhB,wBAAA,EAA0B,IAAA;EAC1B,sBAAA,EAAwB,wBAAA;AACxB,EAAA,eAAA,EAAiB,EAAE,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,IAAA,EAAI;EAC9C,qBAAA,EAAuB,IAAA;EAEvB,cAAA,EAAgB,CAAC,SAAS,OAAO,CAAA;EACjC,gBAAA,EAAkB,IAAA;EAClB,aAAA,EAAe,EAAA;EACf,QAAA,EAAU,GAAA;EACV,SAAA,EAAW;;AAMN,IAAM,mBAAmB,wBAAA,CAAyB;AAClD,IAAM,kBAAkB,wBAAA,CAAyB;AACjD,IAAM,qBAAqB,wBAAA,CAAyB;AACpD,IAAM,sBAAsB,wBAAA,CAAyB;AACrD,IAAM,yBAAyB,wBAAA,CAAyB;AACxD,IAAM,0BAA0B,wBAAA,CAAyB;AACzD,IAAM,gBAAgB,wBAAA,CAAyB;AAC/C,IAAM,gBAAgB,wBAAA,CAAyB;AAC/C,IAAM,qBAAqB,wBAAA,CAAyB;AACpD,IAAM,uBAAuB,wBAAA,CAAyB;AACtD,IAAM,oBAAoB,wBAAA,CAAyB;AAwCpD,SAAU,qBAAA,CACd,MACA,KAAA,EAA2B;AAE3B,EAAA,MAAM,SAAS,EAAA;AACf,EAAA,KAAA,MAAW,WAAW,iBAAA,EAAmB;AACvC,IAAA,MAAA,CAAO,OAAO,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,EAAG,GAAG,KAAA,CAAM,MAAA,GAAS,OAAO,CAAA,EAAC;AACzE,EAAA;AAEA,EAAA,MAAM,kBAAkB,EAAA;AACxB,EAAA,KAAA,MAAW,QAAQ,iBAAA,EAAmB;AACpC,IAAA,eAAA,CAAgB,IAAI,IAAI,KAAA,CAAM,eAAA,GAAkB,IAAI,CAAA,IAAK,IAAA,CAAK,gBAAgB,IAAI,CAAA;AACpF,EAAA;AAEA,EAAA,OAAO;AACL,IAAA,MAAA;IACA,gBAAA,EAAkB,KAAA,CAAM,oBAAoB,IAAA,CAAK,gBAAA;IACjD,iBAAA,EAAmB,KAAA,CAAM,qBAAqB,IAAA,CAAK,iBAAA;IACnD,oBAAA,EAAsB,KAAA,CAAM,wBAAwB,IAAA,CAAK,oBAAA;IACzD,qBAAA,EAAuB,KAAA,CAAM,yBAAyB,IAAA,CAAK,qBAAA;AAC3D,IAAA,eAAA;IACA,WAAA,EAAa,KAAA,CAAM,eAAe,IAAA,CAAK,WAAA;IACvC,WAAA,EAAa,KAAA,CAAM,eAAe,IAAA,CAAK,WAAA;IACvC,eAAA,EAAiB,KAAA,CAAM,mBAAmB,IAAA,CAAK,eAAA;IAC/C,gBAAA,EAAkB,KAAA,CAAM,oBAAoB,IAAA,CAAK,gBAAA;IACjD,cAAA,EAAgB,KAAA,CAAM,kBAAkB,IAAA,CAAK,cAAA;IAC7C,wBAAA,EAA0B,KAAA,CAAM,4BAA4B,IAAA,CAAK,wBAAA;IACjE,sBAAA,EAAwB,KAAA,CAAM,0BAA0B,IAAA,CAAK,sBAAA;AAC7D,IAAA,eAAA,EAAiB,EAAE,GAAG,IAAA,CAAK,eAAA,EAAiB,GAAG,MAAM,eAAA,EAAe;IACpE,qBAAA,EAAuB,KAAA,CAAM,yBAAyB,IAAA,CAAK,qBAAA;IAC3D,cAAA,EAAgB,KAAA,CAAM,kBAAkB,IAAA,CAAK,cAAA;IAC7C,gBAAA,EAAkB,KAAA,CAAM,oBAAoB,IAAA,CAAK,gBAAA;IACjD,aAAA,EAAe,KAAA,CAAM,iBAAiB,IAAA,CAAK,aAAA;IAC3C,QAAA,EAAU,KAAA,CAAM,YAAY,IAAA,CAAK,QAAA;IACjC,SAAA,EAAW,KAAA,CAAM,aAAa,IAAA,CAAK;;AAEvC;AASM,SAAU,iBAAA,CACd,MAAA,EACA,MAAA,EACA,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,IAAI,IAAA,GAAO,MAAA;AAEX,EAAA,IAAI,MAAA,CAAO,UAAU,WAAA,EAAa;AAChC,IAAA,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,WAAW,IAAA,CAAK,SAAA,GAAY,QAAQ,wBAAA,EAAwB;EAChF,CAAA,MAAA,IAAW,MAAA,CAAO,UAAU,MAAA,EAAQ;AAClC,IAAA,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,SAAA,EAAW,CAAA,EAAC;AAChC,EAAA;AAEA,EAAA,IAAA,GAAO;IACL,GAAG,IAAA;AACH,IAAA,SAAA,EAAW,0BACT,IAAA,CAAK,SAAA,EACL,MAAA,CAAO,SAAA,EACP,QAAQ,sBAAsB;;AAIlC,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA;AAAU,IAAA,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,GAAG,QAAQ,eAAA,EAAe;AAE5E,EAAA,OAAO,IAAA;AACT;AAGM,SAAU,kBAAA,CACd,MAAA,EACA,aAAA,EACA,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,IAAI,CAAC,aAAA;AAAe,IAAA,OAAO,CAAA;AAC3B,EAAA,QAAQ,OAAO,WAAA;IACb,KAAK,SAAA;AACH,MAAA,OAAO,CAAA;IACT,KAAK,SAAA;AACH,MAAA,OAAO,OAAA,CAAQ,qBAAA;IACjB,KAAK,MAAA;AACH,MAAA,OAAO,CAAA;AACX;AACF;AAEA,IAAM,UAAA,GAAa,CAAC,KAAA,EAAe,KAAA,EAAe,CAAA,KAAqB;AACrE,EAAA,IAAI,KAAA,IAAS,KAAA;AAAO,IAAA,OAAO,CAAA,GAAI,QAAQ,CAAA,GAAI,CAAA;AAC3C,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAA,CAAI,CAAA,GAAI,KAAA,KAAU,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA;AAChE,EAAA,OAAO,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,CAAA,GAAI,CAAA,CAAA;AAC1B,CAAA;AAGM,SAAU,YAAA,CACd,MAAA,EACA,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,OACE,CAAA,GAAA,CACC,QAAQ,eAAA,GAAkB,CAAA,IACzB,WAAW,OAAA,CAAQ,WAAA,EAAa,OAAA,CAAQ,WAAA,EAAa,MAAM,CAAA;AAEjE;AAEM,SAAU,WAAA,CACd,WAAA,EACA,MAAA,EACA,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,MAAM,IAAA,GAAO,YAAA,CAAa,MAAA,EAAQ,OAAO,CAAA;AACzC,EAAA,OAAO,IAAA,CAAK,IAAI,IAAA,CAAK,GAAA,CAAI,aAAa,CAAC,CAAA,GAAI,IAAA,EAAM,MAAA,GAAS,GAAG,CAAA;AAC/D;AAGM,SAAU,OAAA,CACd,SAAA,EACA,MAAA,EACA,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,OAAO,IAAA,CAAK,IAAI,IAAA,CAAK,GAAA,CAAI,YAAY,OAAA,CAAQ,gBAAA,EAAkB,CAAC,CAAA,EAAG,MAAM,CAAA;AAC3E;;;ACvcO,IAAM,UAAA,GAA4B;EACvC,SAAA,EAAW,CAAA;EACX,QAAA,EAAU,CAAA;EACV,WAAA,EAAa,CAAA;EACb,WAAA,EAAa;;AAGT,SAAU,gBAAgB,MAAA,EAAyB;AACvD,EAAA,OAAO;IACL,SAAA,EAAW,MAAA,CAAO,CAAC,CAAA,IAAK,CAAA;IACxB,QAAA,EAAU,MAAA,CAAO,CAAC,CAAA,IAAK,CAAA;IACvB,WAAA,EAAa,MAAA,CAAO,CAAC,CAAA,IAAK,CAAA;IAC1B,WAAA,EAAa,MAAA,CAAO,CAAC,CAAA,IAAK;;AAE9B;AAWA,IAAM,gBAAA,GAAmB;EACvB,IAAA,EAAM,qBAAA;EACN,cAAA,EAAgB,GAAA;EAChB,UAAA,EAAY,IAAA;EACZ,YAAA,EAAc;;AAGhB,IAAM,eAAA,GAAkB,EAAE,GAAG,gBAAA,EAAkB,YAAY,IAAA,EAAI;AAC/D,IAAM,WAAA,GAAc,EAAE,GAAG,gBAAA,EAAkB,YAAY,IAAA,EAAI;AAuB3D,IAAMA,WAAAA,GAAa,CAAC,KAAA,EAAe,KAAA,EAAe,CAAA,KAAqB;AACrE,EAAA,IAAI,KAAA,IAAS,KAAA;AAAO,IAAA,OAAO,CAAA,GAAI,QAAQ,CAAA,GAAI,CAAA;AAC3C,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAA,CAAI,CAAA,GAAI,KAAA,KAAU,KAAA,GAAQ,KAAA,CAAM,CAAC,CAAA;AAChE,EAAA,OAAO,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,CAAA,GAAI,CAAA,CAAA;AAC1B,CAAA;AAYM,SAAU,YAAA,CACd,SAAA,EACA,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,MAAM,OAAO,OAAA,CAAQ,gBAAA;AACrB,EAAA,MAAM,QAAQ,OAAA,CAAQ,iBAAA;AACtB,EAAA,MAAM,IAAIA,WAAAA,CAAW,OAAA,CAAQ,oBAAA,EAAsB,OAAA,CAAQ,uBAAuB,SAAS,CAAA;AAC3F,EAAA,OAAO;AACL,IAAA,IAAA,CAAK,CAAC,CAAA,GAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA;AACjC,IAAA,IAAA,CAAK,CAAC,CAAA,GAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA;AACjC,IAAA,IAAA,CAAK,CAAC,CAAA,GAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,IAAK;;AAErC;AAEM,SAAU,qBAAA,CACd,OAAA,GAAyB,UAAA,EACzB,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,MAAM,SAAA,GAAY,IAAI,uBAAA,CAAwB,gBAAA,EAAkB,QAAQ,SAAS,CAAA;AACjF,EAAA,MAAM,QAAA,GAAW,IAAI,uBAAA,CAAwB,eAAA,EAAiB,QAAQ,QAAQ,CAAA;AAC9E,EAAA,MAAM,IAAA,GAAO,IAAI,uBAAA,CAAwB,WAAA,EAAa,QAAQ,WAAW,CAAA;AACzE,EAAA,IAAI,QAAA,GAAW,QAAQ,WAAA,GAAc,CAAA;AAErC,EAAA,OAAO;AACL,IAAA,OAAA,CAAQ,KAAA,EAAK;AACX,MAAA,IAAI,MAAM,WAAA,IAAe,CAAA;AAAG,QAAA;AAC5B,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,SAAA,CAAU,QAAA,CAAS,MAAM,SAAS,CAAA;AAClC,MAAA,QAAA,CAAS,QAAA,CAAS,MAAM,QAAQ,CAAA;AAChC,MAAA,IAAA,CAAK,QAAA,CAAS,MAAM,WAAW,CAAA;AACjC,IAAA,CAAA;AAEA,IAAA,OAAA,CAAQ,OAAA,EAAO;AACb,MAAA,SAAA,CAAU,QAAQ,OAAO,CAAA;AACzB,MAAA,QAAA,CAAS,QAAQ,OAAO,CAAA;AACxB,MAAA,IAAA,CAAK,QAAQ,OAAO,CAAA;AACtB,IAAA,CAAA;AAEA,IAAA,KAAA,CAAM,KAAA,EAAK;AACT,MAAA,QAAA,GAAW,MAAM,WAAA,GAAc,CAAA;AAC/B,MAAA,SAAA,CAAU,MAAA,CAAO,MAAM,SAAS,CAAA;AAChC,MAAA,QAAA,CAAS,MAAA,CAAO,MAAM,QAAQ,CAAA;AAC9B,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,WAAW,CAAA;AAC/B,IAAA,CAAA;AAEA,IAAA,IAAI,MAAA,GAAM;AACR,MAAA,OAAO;AACL,QAAA,SAAA,EAAW,SAAA,CAAU,KAAA;AACrB,QAAA,QAAA,EAAU,QAAA,CAAS,KAAA;AACnB,QAAA,WAAA,EAAa,IAAA,CAAK,KAAA;QAClB,IAAA,EAAM,YAAA,CAAa,SAAA,CAAU,KAAA,EAAO,OAAO,CAAA;AAC3C,QAAA;;AAEJ,IAAA,CAAA;AAEA,IAAA,IAAI,OAAA,GAAO;AACT,MAAA,OAAO,SAAA,CAAU,OAAA,IAAW,QAAA,CAAS,OAAA,IAAW,IAAA,CAAK,OAAA;AACvD,IAAA;;AAEJ;AAUM,SAAU,WAAA,CACd,QAAA,EACA,KAAA,EACA,SAAA,EAAiB;AAEjB,EAAA,IAAI,SAAA,IAAa,CAAA;AAAG,IAAA,OAAO,KAAA;AAC3B,EAAA,IAAI,QAAA,KAAa,MAAA;AAAW,IAAA,OAAO,IAAA;AACnC,EAAA,OAAO,KAAA,GAAQ,YAAY,GAAA,GAAO,SAAA;AACpC;;;ACjLO,IAAM,oBAAA,GAAuB;;AAElC,EAAA,eAAA;;AAEA,EAAA,gBAAA;;AAEA,EAAA,mBAAA;;AAEA,EAAA,cAAA;;AAEA,EAAA,iBAAA;;AAEA,EAAA,oBAAA;;AAEA,EAAA,oBAAA;;AAEA,EAAA,gBAAA;;AAEA,EAAA;;AAKI,IAAO,aAAA,GAAP,cAA6B,KAAA,CAAK;AAC7B,EAAA,IAAA;;AAEA,EAAA,OAAA;EAET,WAAA,CAAY,IAAA,EAAyB,SAAiB,OAAA,EAAgB;AACpE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACjB,EAAA;;AAGI,SAAU,aAAA,CACd,IAAA,EACA,OAAA,EACA,OAAA,EAAgB;AAEhB,EAAA,OAAO,IAAI,aAAA,CAAc,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA;AACjD;;;ACMO,IAAM,cAAA,GAAiB;AAC5B,EAAA,OAAA;AACA,EAAA,OAAA;AACA,EAAA,QAAA;AACA,EAAA,UAAA;AACA,EAAA;;AAwEK,IAAM,6BAAA,GAA6D;AACxE,EAAA,YAAA;AACA,EAAA,iBAAA;AACA,EAAA,YAAA;AACA,EAAA,iBAAA;AACA,EAAA,aAAA;AACA,EAAA;;AAYF,IAAM,YAAY,MAChB,eAAA,CAAgB,eAAA,GAAkB,eAAA,CAAgB,WAAW,eAAA,CAAgB,iBAAA;AAQ/E,SAAS,SAAA,CAAU,OAAA,EAAsB,KAAA,EAAe,MAAA,EAAc;AACpE,EAAA,IAAI,OAAA,CAAQ,KAAA,KAAU,KAAA,IAAS,OAAA,CAAQ,MAAA,KAAW,MAAA;AAAQ,IAAA;AAC1D,EAAA,OAAA,CAAQ,KAAA,GAAQ,KAAA;AAChB,EAAA,OAAA,CAAQ,MAAA,GAAS,MAAA;AACjB,EAAA,OAAA,CAAQ,KAAA,IAAS,CAAA;AACnB;AAiCM,SAAU,mBAAmB,OAAA,EAA4B;AAC7D,EAAA,IAAI,SAAS,OAAA,CAAQ,MAAA;AACrB,EAAA,MAAM,IAAA,GAAO,EAAE,KAAA,EAAO,CAAA,EAAG,OAAO,OAAA,CAAQ,KAAA,EAAO,MAAA,EAAQ,OAAA,CAAQ,MAAA,EAAM;AACrE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,IAAA,KAAS,QAAA;AAC9C,EAAA,IAAI,KAAA,GAAQ,IAAA;AACZ,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,UAAA,GAAa,QAAQ,UAAA,IAAc,CAAA;AAEvC,EAAA,MAAM,gBAAgB,MAAiB;AACrC,IAAA,IAAI,OAAA,KAAY,UAAa,OAAA,CAAQ,KAAA,KAAU,KAAK,KAAA,IAAS,OAAA,CAAQ,MAAA,KAAW,IAAA,CAAK,MAAA,EAAQ;AAC3F,MAAA,OAAO,OAAA;AACT,IAAA;AACA,IAAA,OAAA,EAAS,OAAA,EAAO;AAChB,IAAA,OAAA,GAAU,OAAO,aAAA,CAAc;MAC7B,KAAA,EAAO,CAAA,gBAAA,EAAmB,QAAQ,EAAE,CAAA,OAAA,CAAA;MACpC,IAAA,EAAM,EAAE,OAAO,IAAA,CAAK,KAAA,EAAO,QAAQ,IAAA,CAAK,MAAA,EAAQ,oBAAoB,CAAA,EAAC;;;MAGrE,MAAA,EAAQ,YAAA;AACR,MAAA,KAAA,EAAO,SAAA;AACR,KAAA,CAAA;AACD,IAAA,OAAO,OAAA;AACT,EAAA,CAAA;AAEA,EAAA,OAAO;AACL,IAAA,EAAA,EAAI,OAAA,CAAQ,EAAA;AACZ,IAAA,IAAA,EAAM,OAAA,CAAQ,IAAA;AAEd,IAAA,IAAI,UAAA,GAAU;AACZ,MAAA,OAAO,UAAA;AACT,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,OAAO,KAAA,IAAS,IAAA;AAClB,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,IAAI,IAAA,CAAK,KAAA,IAAS,CAAA,IAAK,IAAA,CAAK,UAAU,CAAA,EAAG;AACvC,QAAA,MAAM,aAAA,CACJ,oBAAA,EACA,CAAA,UAAA,EAAa,OAAA,CAAQ,EAAE,CAAA,qBAAA,EAAwB,IAAA,CAAK,KAAK,CAAA,IAAA,EAAI,IAAA,CAAK,MAAM,CAAA,iCAAA,CAAA,EACxE,QAAQ,EAAE,CAAA;AAEd,MAAA;AACA,MAAA,MAAM,SAAS,aAAA,EAAa;AAC5B,MAAA,IAAI,SAAS,IAAA,EAAM;AACjB,QAAA,MAAA,CAAO,KAAA,CAAM,2BACX,EAAE,MAAA,EAAQ,QAAQ,MAAA,EAAQ,KAAA,EAAO,OAAK,EACtC;UACE,OAAA,EAAS,MAAA;AACT,UAAA,UAAA,EAAY,QAAQ,UAAA,IAAc,MAAA;;;;UAIlC,kBAAA,EAAoB;AAEtB,SAAA,EAAA,EAAE,OAAO,IAAA,CAAK,KAAA,EAAO,MAAA,EAAQ,IAAA,CAAK,QAAQ,CAAA;AAE9C,MAAA;AACA,MAAA,OAAO;AACL,QAAA,QAAA,EAAU,OAAA,CAAQ,EAAA;AAClB,QAAA,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,MAAA,CAAO,YAAU,EAAE;AACrD,QAAA,KAAA,EAAO,IAAA,CAAK,KAAA;AACZ,QAAA,MAAA,EAAQ,IAAA,CAAK,MAAA;AACb,QAAA,SAAA,EAAW,IAAA,CAAK,KAAA;AAChB,QAAA,UAAA,EAAY,QAAQ,UAAA,IAAc,MAAA;QAClC,SAAA,EAAW,eAAA;QACX,OAAA,EAAS;;AAEb,IAAA,CAAA;IAEA,OAAA,GAAO;AAGP,IAAA,CAAA;IAEA,YAAA,GAAY;AACV,MAAA,KAAA,GAAQ,KAAA;AACV,IAAA,CAAA;AAEA,IAAA,UAAA,CAAW,MAAM,UAAA,EAAU;AACzB,MAAA,UAAA,GAAa,IAAA;AACb,MAAA,MAAA,GAAS,UAAA;AAIT,MAAA,OAAA,EAAS,OAAA,EAAO;AAChB,MAAA,OAAA,GAAU,MAAA;AACV,MAAA,KAAA,GAAQ,IAAA;AACV,IAAA,CAAA;AAEA,IAAA,MAAA,CAAO,OAAO,MAAA,EAAM;AAClB,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,KAAU,KAAA,IAAS,KAAK,MAAA,KAAW,MAAA;AACxD,MAAA,SAAA,CAAU,IAAA,EAAM,OAAO,MAAM,CAAA;AAC7B,MAAA,IAAI,OAAA;AAAS,QAAA,KAAA,GAAQ,IAAA;AACvB,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,OAAA,EAAS,OAAA,EAAO;AAChB,MAAA,OAAA,GAAU,MAAA;AACZ,IAAA;;AAEJ;AAsBM,SAAU,oBAAoB,OAAA,EAA6B;AAC/D,EAAA,IAAI,SAAS,OAAA,CAAQ,MAAA;AACrB,EAAA,MAAM,OAAO,EAAE,KAAA,EAAO,GAAG,KAAA,EAAO,CAAA,EAAG,QAAQ,CAAA,EAAC;AAC5C,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,UAAA,GAAa,QAAQ,UAAA,IAAc,CAAA;AAEvC,EAAA,OAAO;AACL,IAAA,EAAA,EAAI,OAAA,CAAQ,EAAA;IACZ,IAAA,EAAM,OAAA;AAEN,IAAA,IAAI,UAAA,GAAU;AACZ,MAAA,OAAO,UAAA;AACT,IAAA,CAAA;IAEA,OAAA,GAAO;AAGL,MAAA,OAAO,IAAA;AACT,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,MAAM,cACJ,gBAAA,EACA,CAAA,UAAA,EAAa,QAAQ,EAAE,CAAA,qGAAA,CAAA,EACvB,QAAQ,EAAE,CAAA;AAEd,MAAA;AAEA,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI,OAAA,CAAQ,MAAA,CAAO,IAAA,KAAS,SAAA,EAAW;AACrC,QAAA,MAAM,OAAA,GAAU,QAAQ,MAAA,CAAO,OAAA;AAC/B,QAAA,IAAI,OAAA,CAAQ,UAAA,GAAa,CAAA,IAAK,OAAA,CAAQ,eAAe,CAAA,EAAG;AACtD,UAAA,MAAM,aAAA,CACJ,oBAAA,EACA,CAAA,UAAA,EAAa,OAAA,CAAQ,EAAE,sDAAsD,OAAA,CAAQ,UAAU,CAAA,4GAAA,CAAA,EAC/F,OAAA,CAAQ,EAAE,CAAA;AAEd,QAAA;AACA,QAAA,SAAA,CAAU,IAAA,EAAM,OAAA,CAAQ,UAAA,EAAY,OAAA,CAAQ,WAAW,CAAA;AACvD,QAAA,MAAA,GAAS,OAAA;MACX,CAAA,MAAO;AACL,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,IAAA,EAAI;AACjC,QAAA,IAAI,UAAU,MAAA,EAAW;AACvB,UAAA,MAAM,cACJ,oBAAA,EACA,CAAA,UAAA,EAAa,QAAQ,EAAE,CAAA,wCAAA,CAAA,EACvB,QAAQ,EAAE,CAAA;AAEd,QAAA;AACA,QAAA,UAAA,GAAa,KAAA;AACb,QAAA,SAAA,CAAU,IAAA,EAAM,KAAA,CAAM,YAAA,EAAc,KAAA,CAAM,aAAa,CAAA;AACvD,QAAA,MAAA,GAAS,KAAA;AACX,MAAA;AAEA,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AACF,QAAA,OAAA,GAAU,OAAO,qBAAA,CAAsB;UACrC,KAAA,EAAO,CAAA,gBAAA,EAAmB,QAAQ,EAAE,CAAA,SAAA,CAAA;AACpC,UAAA,MAAA;UACA,UAAA,EAAY;AACb,SAAA,CAAA;AACH,MAAA,CAAA,CAAA,OAAS,KAAA,EAAO;AAMd,QAAA,UAAA,EAAY,KAAA,EAAK;AACjB,QAAA,UAAA,GAAa,MAAA;AACb,QAAA,MAAM,KAAA;AACR,MAAA;AACA,MAAA,QAAA,GAAW,IAAA;AAEX,MAAA,OAAO;AACL,QAAA,QAAA,EAAU,OAAA,CAAQ,EAAA;QAClB,OAAA,EAAS,EAAE,IAAA,EAAM,UAAA,EAAY,OAAA,EAAO;AACpC,QAAA,KAAA,EAAO,IAAA,CAAK,KAAA;AACZ,QAAA,MAAA,EAAQ,IAAA,CAAK,MAAA;AACb,QAAA,SAAA,EAAW,IAAA,CAAK,KAAA;AAChB,QAAA,UAAA,EAAY,QAAQ,UAAA,IAAc,MAAA;;QAElC,SAAA,EAAW,iBAAA;QACX,OAAA,EAAS;;AAEb,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,QAAA,GAAW,KAAA;AAEX,MAAA,UAAA,EAAY,KAAA,EAAK;AACjB,MAAA,UAAA,GAAa,MAAA;AACf,IAAA,CAAA;IAEA,YAAA,GAAY;AAEZ,IAAA,CAAA;AAEA,IAAA,UAAA,CAAW,MAAM,UAAA,EAAU;AACzB,MAAA,UAAA,GAAa,IAAA;AACb,MAAA,MAAA,GAAS,UAAA;AAIT,MAAA,UAAA,EAAY,KAAA,EAAK;AACjB,MAAA,UAAA,GAAa,MAAA;AACb,MAAA,QAAA,GAAW,KAAA;AACb,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,UAAA,EAAY,KAAA,EAAK;AACjB,MAAA,UAAA,GAAa,MAAA;AACb,MAAA,QAAA,GAAW,KAAA;AACb,IAAA;;AAEJ;AAoCM,SAAU,uBAAuB,OAAA,EAAgC;AACrE,EAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,SAAS,EAAE,CAAA;AAC7C,EAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,UAAU,EAAE,CAAA;AAC/C,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,IAAa,CAAC,GAAG,CAAC,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,OAAA,CAAQ,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,MAAA,GAAS,EAAE,MAAM,CAAA;AAEnE,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,cACJ,oBAAA,EACA,CAAA,mBAAA,EAAsB,QAAQ,EAAE,CAAA,eAAA,CAAA,EAChC,QAAQ,EAAE,CAAA;AAEd,EAAA;AAEA,EAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAW,KAAA,GAAQ,SAAS,CAAC,CAAA;AAChD,EAAA,MAAM,UAAA,GAAa,KAAK,KAAA,CAAM,SAAA,CAAU,CAAC,CAAA,EAAG,SAAA,CAAU,CAAC,CAAC,CAAA,IAAK,CAAA;AAC7D,EAAA,MAAM,EAAA,GAAK,SAAA,CAAU,CAAC,CAAA,GAAI,UAAA;AAC1B,EAAA,MAAM,EAAA,GAAK,SAAA,CAAU,CAAC,CAAA,GAAI,UAAA;AAE1B,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAwD;AACtE,IAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,CAAA;AAC1C,IAAA,IAAI,KAAA,GAAQ,MAAM,CAAC,CAAA;AACnB,IAAA,IAAI,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AAClC,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAM,MAAA,GAAS,CAAA,EAAG,KAAK,CAAA,EAAG;AAC5C,MAAA,MAAM,CAAA,GAAI,MAAM,CAAC,CAAA;AACjB,MAAA,MAAM,CAAA,GAAI,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA;AACrB,MAAA,IAAI,OAAA,IAAW,CAAA,CAAE,MAAA,IAAU,OAAA,IAAW,EAAE,MAAA,EAAQ;AAC9C,QAAA,KAAA,GAAQ,CAAA;AACR,QAAA,KAAA,GAAQ,CAAA;AACR,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,MAAA,GAAS,KAAA,CAAM,MAAA;AAClC,IAAA,MAAM,QAAQ,IAAA,IAAQ,CAAA,GAAI,CAAA,GAAA,CAAK,OAAA,GAAU,MAAM,MAAA,IAAU,IAAA;AACzD,IAAA,MAAM,MAAM,CAAC,IAAA,EAAc,EAAA,KAAuB,IAAA,GAAA,CAAQ,KAAK,IAAA,IAAQ,KAAA;AAMvE,IAAA,MAAM,UAAU,CAAC,KAAA,KACf,mBAAA,CACE,GAAA,CAAI,oBAAoB,KAAA,CAAM,KAAA,CAAM,KAAK,CAAC,GAAG,mBAAA,CAAoB,KAAA,CAAM,MAAM,KAAK,CAAC,CAAC,CAAC,CAAA;AAEzF,IAAA,OAAO,CAAC,OAAA,CAAQ,CAAC,GAAG,OAAA,CAAQ,CAAC,GAAG,OAAA,CAAQ,CAAC,GAAG,GAAA,CAAI,KAAA,CAAM,MAAM,CAAC,CAAA,EAAG,MAAM,KAAA,CAAM,CAAC,CAAC,CAAC,CAAA;AACjF,EAAA,CAAA;AAEA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,EAAQ,KAAK,CAAA,EAAG;AAClC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,KAAK,CAAA,EAAG;AACjC,MAAA,MAAM,CAAA,GAAI,KAAA,KAAU,CAAA,GAAI,CAAA,GAAI,KAAK,KAAA,GAAQ,CAAA,CAAA;AACzC,MAAA,MAAM,CAAA,GAAI,MAAA,KAAW,CAAA,GAAI,CAAA,GAAI,KAAK,MAAA,GAAS,CAAA,CAAA;AAG3C,MAAA,MAAM,CAAA,GAAA,CAAK,CAAA,GAAI,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,KAAK,GAAA,CAAI,CAAA,EAAG,CAAC,EAAE,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,EAAG,CAAC,EAAE,CAAA,KAAM,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,IAAK,CAAA,CAAA;AACpG,MAAA,MAAM,CAAC,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA;AAC7B,MAAA,MAAM,KAAA,GAAA,CAAS,CAAA,GAAI,KAAA,GAAQ,CAAA,IAAK,CAAA;AAChC,MAAA,MAAA,CAAO,KAAA,GAAQ,CAAC,CAAA,GAAI,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,IAAI,GAAG,CAAA;AAChE,MAAA,MAAA,CAAO,KAAA,GAAQ,CAAC,CAAA,GAAI,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,IAAI,GAAG,CAAA;AAChE,MAAA,MAAA,CAAO,KAAA,GAAQ,CAAC,CAAA,GAAI,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,IAAI,GAAG,CAAA;AAChE,MAAA,MAAA,CAAO,KAAA,GAAQ,CAAC,CAAA,GAAI,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,IAAI,GAAG,CAAA;AAClE,IAAA;AACF,EAAA;AAEA,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,SAAS,OAAA,CAAQ,MAAA;AACrB,EAAA,IAAI,UAAA,GAAa,QAAQ,UAAA,IAAc,CAAA;AAEvC,EAAA,OAAO;AACL,IAAA,EAAA,EAAI,OAAA,CAAQ,EAAA;IACZ,IAAA,EAAM,UAAA;AAEN,IAAA,IAAI,UAAA,GAAU;AACZ,MAAA,OAAO,UAAA;AACT,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,OAAO,CAAC,QAAA;AACV,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,OAAA,KAAY,OAAO,aAAA,CAAc;QAC/B,KAAA,EAAO,CAAA,gBAAA,EAAmB,QAAQ,EAAE,CAAA,SAAA,CAAA;AACpC,QAAA,IAAA,EAAM,EAAE,KAAA,EAAO,MAAA,EAAQ,kBAAA,EAAoB,CAAA,EAAC;QAC5C,MAAA,EAAQ,YAAA;AACR,QAAA,KAAA,EAAO,SAAA;AACR,OAAA,CAAA;AACD,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,MAAA,CAAO,MAAM,YAAA,CACX,EAAE,OAAA,EAAO,EACT,QACA,EAAE,WAAA,EAAa,KAAA,GAAQ,CAAA,EAAG,cAAc,MAAA,EAAM,EAC9C,EAAE,KAAA,EAAO,QAAQ,CAAA;AAErB,MAAA;AACA,MAAA,OAAO;AACL,QAAA,QAAA,EAAU,OAAA,CAAQ,EAAA;AAClB,QAAA,OAAA,EAAS,EAAE,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,OAAA,CAAQ,YAAU,EAAE;AACtD,QAAA,KAAA;AACA,QAAA,MAAA;QACA,SAAA,EAAW,CAAA;QACX,UAAA,EAAY,MAAA;QACZ,SAAA,EAAW,eAAA;QACX,OAAA,EAAS;;AAEb,IAAA,CAAA;IAEA,OAAA,GAAO;AAEP,IAAA,CAAA;IAEA,YAAA,GAAY;AACV,MAAA,QAAA,GAAW,IAAA;AACb,IAAA,CAAA;AAEA,IAAA,UAAA,CAAW,MAAM,UAAA,EAAU;AACzB,MAAA,UAAA,GAAa,IAAA;AACb,MAAA,MAAA,GAAS,UAAA;AAKT,MAAA,OAAA,EAAS,OAAA,EAAO;AAChB,MAAA,OAAA,GAAU,MAAA;AACV,MAAA,QAAA,GAAW,KAAA;AACb,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,OAAA,EAAS,OAAA,EAAO;AAChB,MAAA,OAAA,GAAU,MAAA;AACV,MAAA,QAAA,GAAW,KAAA;AACb,IAAA;;AAEJ;AAGM,SAAU,mBAAA,CACd,MACA,EAAA,EAAqC;AAErC,EAAA,MAAM,SAAS,CAAC,CAAA,KACd,CAAC,mBAAA,CAAoB,CAAA,CAAE,CAAC,CAAC,CAAA,EAAG,oBAAoB,CAAA,CAAE,CAAC,CAAC,CAAA,EAAG,mBAAA,CAAoB,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;AACrF,EAAA,OAAO;AACL,IAAA,EAAE,MAAA,EAAQ,CAAA,EAAG,KAAA,EAAO,MAAA,CAAO,IAAI,CAAA,EAAC;AAChC,IAAA,EAAE,MAAA,EAAQ,CAAA,EAAG,KAAA,EAAO,MAAA,CAAO,EAAE,CAAA;;AAEjC;AAoCM,SAAU,kBAAA,CACd,OAAA,EACA,MAAA,EACA,OAAA,EAAe;AAEf,EAAA,IAAI,OAAA,CAAQ,cAAc,IAAA,EAAM;AAC9B,IAAA,MAAM,aAAA,CACJ,qBACA,CAAA,UAAA,EAAa,OAAO,gBAAgB,OAAA,CAAQ,SAAS,oGACrD,OAAO,CAAA;AAEX,EAAA;AACA,EAAA,IAAI,OAAA,CAAQ,uBAAuB,CAAA,EAAG;AACpC,IAAA,MAAM,aAAA,CACJ,qBACA,CAAA,UAAA,EAAa,OAAO,6BAA6B,OAAA,CAAQ,kBAAkB,4CAC3E,OAAO,CAAA;AAEX,EAAA;AACA,EAAA,IAAA,CAAK,OAAA,CAAQ,KAAA,GAAQ,eAAA,CAAgB,eAAA,MAAqB,CAAA,EAAG;AAC3D,IAAA,MAAM,aAAA,CACJ,eAAA,EACA,CAAA,UAAA,EAAa,OAAO,yJACpB,OAAO,CAAA;AAEX,EAAA;AACA,EAAA,IAAI,CAAC,6BAAA,CAA8B,QAAA,CAAS,OAAA,CAAQ,MAAM,CAAA,EAAG;AAC3D,IAAA,MAAM,aAAA,CACJ,gBAAA,EACA,CAAA,UAAA,EAAa,OAAO,CAAA,cAAA,EAAiB,OAAA,CAAQ,MAAM,CAAA,iCAAA,EAAoC,6BAAA,CAA8B,IAAA,CAAK,IAAI,CAAC,KAC/H,OAAO,CAAA;AAEX,EAAA;AACA,EAAA,IAAI,OAAA,CAAQ,KAAA,IAAS,CAAA,IAAK,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC7C,IAAA,MAAM,aAAA,CACJ,cAAA,EACA,CAAA,UAAA,EAAa,OAAO,CAAA,aAAA,EAAgB,OAAA,CAAQ,KAAK,CAAA,IAAA,EAAI,OAAA,CAAQ,MAAM,CAAA,SAAA,CAAA,EACnE,OAAO,CAAA;AAEX,EAAA;AACA,EAAA,MAAM,MAAM,MAAA,CAAO,qBAAA;AACnB,EAAA,IAAI,OAAA,CAAQ,KAAA,GAAQ,GAAA,IAAO,OAAA,CAAQ,SAAS,GAAA,EAAK;AAC/C,IAAA,MAAM,aAAA,CACJ,cAAA,EACA,CAAA,UAAA,EAAa,OAAO,CAAA,aAAA,EAAgB,OAAA,CAAQ,KAAK,CAAA,IAAA,EAAI,OAAA,CAAQ,MAAM,CAAA,uDAAA,EAA0D,GAAG,KAChI,OAAO,CAAA;AAEX,EAAA;AACF;AAEM,SAAU,yBAAyB,OAAA,EAAkC;AAGzE,EAAA,kBAAA,CAAmB,QAAQ,OAAA,EAAS,OAAA,CAAQ,MAAA,CAAO,MAAA,EAAQ,QAAQ,EAAE,CAAA;AAErE,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,CAAC,QAAQ,OAAA,CAAQ,MAAA,CAAO,SAAS,OAAO,CAAA;AAC3E,EAAA,MAAM,IAAA,GAAO;IACX,KAAA,EAAO,CAAA;AACP,IAAA,KAAA,EAAO,QAAQ,OAAA,CAAQ,KAAA;AACvB,IAAA,MAAA,EAAQ,QAAQ,OAAA,CAAQ;;AAG1B,EAAA,MAAM,eAAA,GAAkB,QAAQ,UAAA,IAAc,CAAA;AAC9C,EAAA,IAAI,UAAA,GAAa,eAAA;AAEjB,EAAA,OAAO;AACL,IAAA,EAAA,EAAI,OAAA,CAAQ,EAAA;IACZ,IAAA,EAAM,kBAAA;AAEN,IAAA,IAAI,UAAA,GAAU;AACZ,MAAA,OAAO,UAAA;AACT,IAAA,CAAA;IAEA,OAAA,GAAO;AAIL,MAAA,OAAO,IAAA;AACT,IAAA,CAAA;IAEA,OAAA,GAAO;AAOL,MAAA,IAAI,eAAe,eAAA,EAAiB;AAClC,QAAA,MAAM,aAAA,CACJ,oBAAA,EACA,CAAA,UAAA,EAAa,OAAA,CAAQ,EAAE,CAAA,4CAAA,EAA+C,eAAe,CAAA,wCAAA,EAA2C,UAAU,CAAA,yIAAA,CAAA,EAC1I,OAAA,CAAQ,EAAE,CAAA;AAEd,MAAA;AACA,MAAA,OAAO;AACL,QAAA,QAAA,EAAU,OAAA,CAAQ,EAAA;QAClB,OAAA,EAAS;UACP,IAAA,EAAM,SAAA;AACN,UAAA,IAAA,EAAM,OAAA,CAAQ,IAAA,IAAQ,OAAA,CAAQ,OAAA,CAAQ,UAAA;;AAExC,QAAA,KAAA,EAAO,IAAA,CAAK,KAAA;AACZ,QAAA,MAAA,EAAQ,IAAA,CAAK,MAAA;AACb,QAAA,SAAA,EAAW,IAAA,CAAK,KAAA;AAChB,QAAA,UAAA,EAAY,QAAQ,UAAA,IAAc,MAAA;AAClC,QAAA,SAAA,EAAW,QAAQ,SAAA,IAAa,eAAA;AAChC,QAAA;;AAEJ,IAAA,CAAA;IAEA,OAAA,GAAO;AAEP,IAAA,CAAA;IAEA,YAAA,GAAY;AAEZ,IAAA,CAAA;AAEA,IAAA,UAAA,CAAW,IAAA,EAAI;AAIb,MAAA,UAAA,GAAa,IAAA;AACf,IAAA,CAAA;IAEA,OAAA,GAAO;AAGP,IAAA;;AAEJ;;;ACtrBM,SAAU,gBAAA,CAAiB,OAAA,GAA6B,EAAA,EAAE;AAC9D,EAAA,IAAI,MAAA,GAA+B;IACjC,MAAA,EAAQ,eAAA;IACR,YAAA,EAAc,IAAA;IACd,SAAA,EAAW,QAAA;IACX,MAAA,EAAQ,MAAA;IACR,UAAA,EAAY,CAAA;IACZ,kBAAA,EAAoB;;AAEtB,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAG;AACrB,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,QAAA;AAEJ,EAAA,MAAM,OAAA,GAAU,CAAC,IAAA,KAAoC;AACnD,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,IAAI,CAAC,SAAA;AAAW,MAAA,OAAA,CAAQ,iBAAiB,MAAM,CAAA;AACjD,EAAA,CAAA;AAEA,EAAA,MAAM,cAAc,MAAW;AAG7B,IAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,GAAG,KAAK,CAAA,EAAG;AAC7B,MAAA,IAAI;AACF,QAAA,IAAA,EAAI;MACN,CAAA,CAAA,MAAQ;AAER,MAAA;AACF,IAAA;AACF,EAAA,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,MAAA,EAAmB,UAAA,KAA4B;AAChE,IAAA,KAAK,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,CAAC,IAAA,KAAQ;AAE7B,MAAA,IAAI,SAAA,IAAa,OAAO,UAAA,KAAe,UAAA;AAAY,QAAA;AAEnD,MAAA,WAAA,EAAW;AACX,MAAA,MAAM,YAAY,MAAA,CAAO,SAAA;AACzB,MAAA,OAAA,CAAQ;QACN,MAAA,EAAQ,WAAA;QACR,YAAA,EAAc,MAAA;AACd,QAAA,SAAA;QACA,MAAA,EAAQ,MAAA;AACR,QAAA,UAAA;AACA,QAAA,kBAAA,EAAoB,SAAA,KAAc,KAAA;QAClC,iBAAA,EAAmB;AACpB,OAAA,CAAA;AAED,MAAA,IAAI,KAAK,MAAA,KAAW,WAAA;AAAa,QAAA;AAEjC,MAAA,IAAI,cAAc,KAAA,EAAO;AACvB,QAAA,OAAA,CAAQ,mBAAA,IAAqB;AAC7B,QAAA;AACF,MAAA;AAEA,MAAA,MAAM,YAAY,OAAA,CAAQ,SAAA;AAC1B,MAAA,IAAI,SAAA,KAAc,MAAA;AAAW,QAAA;AAC7B,MAAA,QAAA,GAAA,CAAY,YAAW;AACrB,QAAA,MAAM,WAAA,GAAc,MAAM,SAAA,EAAS;AAMnC,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,WAAA,EAAa,OAAA,EAAO;AACpB,UAAA;AACF,QAAA;AACA,QAAA,IAAI,WAAA,KAAgB,MAAA;AAAW,UAAA;AAC/B,QAAA,MAAA,CAAO,aAAa,QAAQ,CAAA;MAC9B,CAAA,GAAE;IACJ,CAAC,CAAA;AACH,EAAA,CAAA;AAEA,EAAA,SAAS,MAAA,CAAO,QAAmB,SAAA,EAA0B;AAC3D,IAAA,MAAM,UAAA,GAAa,OAAO,UAAA,GAAa,CAAA;AACvC,IAAA,OAAA,CAAQ;MACN,MAAA,EAAQ,WAAA;MACR,YAAA,EAAc,IAAA;AACd,MAAA,SAAA;AACA,MAAA,MAAA;AACA,MAAA,UAAA;MACA,kBAAA,EAAoB;AACrB,KAAA,CAAA;AACD,IAAA,SAAA,CAAU,QAAQ,UAAU,CAAA;AAC9B,EAAA;AAEA,EAAA,OAAO;AACL,IAAA,IAAI,MAAA,GAAM;AACR,MAAA,OAAO,MAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,eAAA,GAAe;AACjB,MAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAQ,YAAA,EAAc,OAAO,YAAA,EAAY;AACnE,IAAA,CAAA;IAEA,aAAA,GAAa;AACX,MAAA,MAAM,EAAE,QAAM,GAAK,MAAA;AACnB,MAAA,IAAI,WAAW,MAAA,EAAW;AACxB,QAAA,MAAM,aAAA,CACJ,oBAAA,EACA,MAAA,CAAO,kBAAA,GACH,mKACA,0HAA0H,CAAA;AAElI,MAAA;AACA,MAAA,OAAO,MAAA;AACT,IAAA,CAAA;AAEA,IAAA,MAAA;AAEA,IAAA,aAAA,CAAc,MAAA,EAAM;AAClB,MAAA,MAAA,CAAO,MAAA,EAAQ,OAAO,SAAS,CAAA;AACjC,IAAA,CAAA;AAEA,IAAA,eAAA,CAAgB,MAAA,EAAM;AACpB,MAAA,OAAA,CAAQ;QACN,GAAG,MAAA;QACH,MAAA,EAAQ,aAAA;QACR,MAAA,EAAQ,MAAA;QACR,iBAAA,EAAmB;AACpB,OAAA,CAAA;AACH,IAAA,CAAA;AAEA,IAAA,eAAA,CAAgB,IAAA,EAAI;AAClB,MAAA,KAAA,CAAM,IAAI,IAAI,CAAA;AACd,MAAA,OAAO,MAAM,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AAChC,IAAA,CAAA;AAEA,IAAA,MAAM,OAAA,GAAO;AACX,MAAA,MAAM,QAAA;AACR,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,WAAA,EAAW;AAEX,MAAA,IAAI,OAAO,SAAA,KAAc,QAAA;AAAU,QAAA,MAAA,CAAO,QAAQ,OAAA,EAAO;AACzD,MAAA,KAAA,CAAM,KAAA,EAAK;AACX,MAAA,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAS;AACzC,IAAA;;AAEJ;;;ACnLO,IAAM,gBAAA,GAAkC;EAC7C,WAAA,EAAa,OAAA;EACb,yBAAA,EAA2B,CAAA;EAC3B,mBAAA,EAAqB;;AAOhB,IAAM,eAAA,GAA4C;AACvD,EAAA,gBAAA;AACA,EAAA,EAAE,WAAA,EAAa,MAAA,EAAQ,yBAAA,EAA2B,CAAA,EAAG,qBAAqB,EAAA,EAAE;AAC5E,EAAA,EAAE,WAAA,EAAa,MAAA,EAAQ,yBAAA,EAA2B,IAAA,EAAM,qBAAqB,GAAA,EAAG;AAChF,EAAA,EAAE,WAAA,EAAa,MAAA,EAAQ,yBAAA,EAA2B,GAAA,EAAK,qBAAqB,CAAA;;AAwBvE,IAAM,oBAAA,GAAuB;EAClC,GAAA,EAAK,IAAA;EACL,OAAA,EAAS,eAAA;EACT,MAAA,EAAQ,IAAA;EACR,YAAA,EAAc,OAAA;EACd,OAAA,EAAS;;AAyBX,IAAM,UAAA,GAAa,CAAC,CAAA,KAAsB,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,CAAC,CAAC,CAAA;AAElE,SAAU,cAAA,CAAe,OAAA,GAA2B,EAAA,EAAE;AAC1D,EAAA,IAAI,KAAA,GAAQ,gBAAA;AACZ,EAAA,IAAI,QAAA,GAAW,OAAA,CAAQ,eAAA,IAAmB,oBAAA,CAAqB,GAAA;AAE/D,EAAA,MAAM,KAAA,GAAQ,CAAC,IAAA,KAAsC;AACnD,IAAA,MAAM,SAAsB,IAAA,CAAK,WAAA,KAAgB,UAAU,CAAC,QAAA,GAAW,UAAU,IAAA,CAAK,WAAA;AACtF,IAAA,KAAA,GAAQ;MACN,WAAA,EAAa,MAAA;MACb,yBAAA,EAA2B,UAAA,CAAW,KAAK,yBAAyB,CAAA;AACpE,MAAA,mBAAA,EAAqB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,mBAAmB;;AAE3D,IAAA,OAAA,CAAQ,WAAW,KAAK,CAAA;AACxB,IAAA,OAAO,KAAA;AACT,EAAA,CAAA;AAEA,EAAA,OAAO;AACL,IAAA,IAAI,KAAA,GAAK;AACP,MAAA,OAAO,KAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,eAAA,GAAe;AACjB,MAAA,OAAO,QAAA;AACT,IAAA,CAAA;AAEA,IAAA,GAAA,CAAI,KAAA,EAAK;AACP,MAAA,OAAO,MAAM,EAAE,GAAG,KAAA,EAAO,GAAG,OAAO,CAAA;AACrC,IAAA,CAAA;AAEA,IAAA,QAAA,CAAS,KAAA,EAAK;AACZ,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,eAAA,CAAgB,MAAA,GAAS,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAC,CAAA;AACjF,MAAA,OAAO,KAAA,CAAM,eAAA,CAAgB,KAAK,CAAkB,CAAA;AACtD,IAAA,CAAA;IAEA,KAAA,GAAK;AACH,MAAA,OAAO,MAAM,gBAAgB,CAAA;AAC/B,IAAA,CAAA;IAEA,qBAAA,GAAqB;AACnB,MAAA,QAAA,GAAW,IAAA;AACb,IAAA;;AAEJ;;;AClIM,SAAU,oBAAoB,OAAA,EAAwB;AAC1D,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAG;AACvB,EAAA,MAAM,eAAA,uBAAsB,GAAA,EAAG;AAC/B,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAG;AAChC,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,MAAA,GAAS,CAAA;AAEb,EAAA,SAAS,IAAA,CAAQ,KAAA,EAAuB,GAAA,EAAa,IAAA,EAAa;AAChE,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC9B,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,IAAA,IAAQ,CAAA;AACR,MAAA,OAAO,QAAA;AACT,IAAA;AACA,IAAA,MAAA,IAAU,CAAA;AACV,IAAA,MAAM,OAAO,IAAA,EAAI;AACjB,IAAA,KAAA,CAAM,GAAA,CAAI,KAAK,IAAI,CAAA;AACnB,IAAA,OAAO,IAAA;AACT,EAAA;AAEA,EAAA,OAAO;AACL,IAAA,IAAI,KAAA,GAAK;AACP,MAAA,OAAO;AACL,QAAA,OAAA,EAAS,OAAA,CAAQ,IAAA;AACjB,QAAA,eAAA,EAAiB,eAAA,CAAgB,IAAA;AACjC,QAAA,gBAAA,EAAkB,gBAAA,CAAiB,IAAA;AACnC,QAAA,IAAA;AACA,QAAA;;AAEJ,IAAA,CAAA;AAEA,IAAA,MAAA,CAAO,KAAK,MAAA,EAAM;AAChB,MAAA,OAAO,IAAA,CAAK,OAAA,EAAS,GAAA,EAAK,MAAM,OAAA,CAAQ,kBAAA,CAAmB,EAAE,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM,MAAA,EAAM,EAAI,CAAC,CAAA;AAC5F,IAAA,CAAA;AAEA,IAAA,cAAA,CAAe,KAAK,QAAA,EAAQ;AAC1B,MAAA,OAAO,IAAA,CAAK,iBAAiB,GAAA,EAAK,MAAM,QAAQ,oBAAA,CAAqB,QAAA,EAAU,CAAC,CAAA;AAClF,IAAA,CAAA;AAEA,IAAA,eAAA,CAAgB,KAAK,QAAA,EAAQ;AAC3B,MAAA,OAAO,IAAA,CAAK,kBAAkB,GAAA,EAAK,MAAM,QAAQ,qBAAA,CAAsB,QAAA,EAAU,CAAC,CAAA;AACpF,IAAA,CAAA;IAEA,KAAA,GAAK;AAKH,MAAA,OAAA,CAAQ,KAAA,EAAK;AACb,MAAA,eAAA,CAAgB,KAAA,EAAK;AACrB,MAAA,gBAAA,CAAiB,KAAA,EAAK;AACxB,IAAA;;AAEJ;AAGO,IAAM,WAAA,GAAc;AACzB,EAAA,KAAA,EAAO,CAAC,MAAA,EAAgB,MAAA,KAAqC,CAAA,MAAA,EAAS,MAAM,IAAI,MAAM,CAAA,CAAA;AACtF,EAAA,MAAA,EAAQ,CAAC,IAAA,EAAc,MAAA,KAAqC,CAAA,OAAA,EAAU,IAAI,IAAI,MAAM,CAAA,CAAA;AACpF,EAAA,KAAA,EAAO,CAAC,KAAA,EAAe,MAAA,KAAqC,CAAA,MAAA,EAAS,KAAK,IAAI,MAAM,CAAA,CAAA;AACpF,EAAA,QAAA,EAAU,MAAc,UAAA;AACxB,EAAA,MAAA,EAAQ,CAAC,MAAA,EAA0B,KAAA,KAA0B,CAAA,OAAA,EAAU,MAAM,IAAI,KAAK,CAAA,CAAA;AACtF,EAAA,SAAA,EAAW,CAAC,MAAA,EAA0B,KAAA,KAA0B,CAAA,UAAA,EAAa,MAAM,IAAI,KAAK,CAAA;;;;AClC9F,IAAM,SAAA,GAAY,CAAC,CAAA,EAAmB,CAAA,KACpC,CAAA,CAAE,UAAU,CAAA,CAAE,KAAA,IACd,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,IACf,EAAE,MAAA,KAAW,CAAA,CAAE,MAAA,IACf,CAAA,CAAE,KAAA,KAAU,CAAA,CAAE,UACb,CAAA,CAAE,aAAA,IAAiB,CAAA,OAAQ,CAAA,CAAE,aAAA,IAAiB,CAAA,CAAA;AAE3C,SAAU,kBAAkB,SAAA,EAA2B;AAC3D,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAG;AACvB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,MAAA,GAAS,CAAA;AAEb,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KAA0B;AACzC,IAAA,KAAA,CAAM,QAAQ,OAAA,EAAO;AACrB,IAAA,SAAA,IAAa,CAAA;AACf,EAAA,CAAA;AAEA,EAAA,OAAO;AACL,IAAA,IAAI,SAAA,GAAS;AACX,MAAA,OAAO,KAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,KAAA,GAAK;AACP,MAAA,OAAO,EAAE,IAAA,EAAM,OAAA,CAAQ,MAAM,OAAA,EAAS,SAAA,EAAW,QAAQ,KAAA,EAAK;AAChE,IAAA,CAAA;AAEA,IAAA,OAAA,CAAQ,KAAK,OAAA,EAAO;AAClB,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAChC,MAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,QAAA,IAAI,SAAS,KAAA,KAAU,KAAA,IAAS,UAAU,QAAA,CAAS,OAAA,EAAS,OAAO,CAAA,EAAG;AACpE,UAAA,MAAA,IAAU,CAAA;AACV,UAAA,OAAO,QAAA,CAAS,OAAA;AAClB,QAAA;AACA,QAAA,OAAA,CAAQ,QAAQ,CAAA;AAClB,MAAA;AAEA,MAAA,MAAM,OAAA,GAAU,UAAU,aAAA,CAAc;QACtC,IAAA,EAAM;AACJ,UAAA,KAAA,EAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAC,CAAA;AAC5C,UAAA,MAAA,EAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAC,CAAA;UAC9C,kBAAA,EAAoB;;AAEtB,QAAA,MAAA,EAAQ,OAAA,CAAQ,MAAA;AAChB,QAAA,KAAA,EAAO,OAAA,CAAQ,KAAA;AACf,QAAA,aAAA,EAAe,QAAQ,aAAA,IAAiB,CAAA;QACxC,GAAI,OAAA,CAAQ,UAAU,MAAA,GAAY,KAAK,EAAE,KAAA,EAAO,QAAQ,KAAA;AACzD,OAAA,CAAA;AACD,MAAA,OAAA,IAAW,CAAA;AACX,MAAA,OAAA,CAAQ,IAAI,GAAA,EAAK,EAAE,OAAA,EAAS,OAAA,EAAS,OAAO,CAAA;AAC5C,MAAA,OAAO,OAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAA,CAAK,GAAA,EAAG;AACN,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,EAAG,OAAA;AAC3B,IAAA,CAAA;AAEA,IAAA,OAAA,CAAQ,GAAA,EAAG;AACT,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAC7B,MAAA,IAAI,KAAA,KAAU,MAAA;AAAW,QAAA;AACzB,MAAA,OAAA,CAAQ,KAAK,CAAA;AACb,MAAA,OAAA,CAAQ,OAAO,GAAG,CAAA;AACpB,IAAA,CAAA;IAEA,aAAA,GAAa;AACX,MAAA,KAAA,IAAS,CAAA;AACT,MAAA,OAAO,KAAA;AACT,IAAA,CAAA;IAEA,KAAA,GAAK;AACH,MAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,MAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,CAAC,GAAG,OAAO,CAAA,EAAG;AACvC,QAAA,IAAI,MAAM,KAAA,KAAU,KAAA;AAAO,UAAA;AAC3B,QAAA,OAAA,CAAQ,KAAK,CAAA;AACb,QAAA,OAAA,CAAQ,OAAO,GAAG,CAAA;AAClB,QAAA,KAAA,IAAS,CAAA;AACX,MAAA;AACA,MAAA,OAAO,KAAA;AACT,IAAA,CAAA;IAEA,KAAA,GAAK;AACH,MAAA,KAAA,MAAW,KAAA,IAAS,QAAQ,MAAA,EAAM;AAAI,QAAA,OAAA,CAAQ,KAAK,CAAA;AACnD,MAAA,OAAA,CAAQ,KAAA,EAAK;AACf,IAAA;;AAEJ;AAGO,IAAM,OAAA,GAAU;EACrB,cAAA,EAAgB,CAAC,QAAA,KAA6B,CAAA,SAAA,EAAY,QAAQ,CAAA,OAAA,CAAA;EAClE,aAAA,EAAe,CAAC,QAAA,KAA6B,CAAA,SAAA,EAAY,QAAQ,CAAA,MAAA,CAAA;AACjE,EAAA,oBAAA,EAAsB,CAAC,QAAA,EAAkB,KAAA,KACvC,CAAA,SAAA,EAAY,QAAQ,kBAAkB,KAAK,CAAA,CAAA;EAC7C,YAAA,EAAc,CAAC,QAAA,KAA6B,CAAA,SAAA,EAAY,QAAQ,CAAA,KAAA,CAAA;EAChE,mBAAA,EAAqB,CAAC,QAAA,KAA6B,CAAA,SAAA,EAAY,QAAQ,CAAA,aAAA,CAAA;EACvE,cAAA,EAAgB,CAAC,QAAA,KAA6B,CAAA,SAAA,EAAY,QAAQ,CAAA,OAAA,CAAA;EAClE,UAAA,EAAY,CAAC,OAAA,KAA4B,CAAA,MAAA,EAAS,OAAO,CAAA,MAAA,CAAA;EACzD,QAAA,EAAU,CAAC,OAAA,KAA4B,CAAA,MAAA,EAAS,OAAO,CAAA,IAAA;;;;AC/InD,SAAU,gBAAA,CAAiB,QAAmB,UAAA,EAAkB;AACpE,EAAA,MAAM,IAAA,GAAO,kBAAkB,MAAM,CAAA;AACrC,EAAA,MAAM,KAAA,GAAQ,oBAAoB,MAAM,CAAA;AAKxC,EAAA,MAAM,YAAA,GAAe,OAAO,aAAA,CAAc;IACxC,KAAA,EAAO,sBAAA;IACP,SAAA,EAAW,QAAA;IACX,SAAA,EAAW,QAAA;IACX,YAAA,EAAc,QAAA;IACd,YAAA,EAAc,eAAA;IACd,YAAA,EAAc;AACf,GAAA,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,OAAO,aAAA,CAAc;IACvC,KAAA,EAAO,qBAAA;IACP,SAAA,EAAW,QAAA;IACX,SAAA,EAAW,QAAA;IACX,YAAA,EAAc,eAAA;IACd,YAAA,EAAc;AACf,GAAA,CAAA;AAED,EAAA,OAAO;AACL,IAAA,MAAA;AACA,IAAA,UAAA;AACA,IAAA,IAAA;AACA,IAAA,KAAA;AACA,IAAA,YAAA;AACA,IAAA,WAAA;IACA,OAAA,GAAO;AACL,MAAA,IAAA,CAAK,KAAA,EAAK;AACV,MAAA,KAAA,CAAM,KAAA,EAAK;AACb,IAAA;;AAEJ;AASM,SAAU,iBAAA,CACd,MAAA,EACA,MAAA,EACA,KAAA,EAAa;AAKb,EAAA,MAAM,OAAO,IAAA,CAAK,IAAA,CAAM,MAAA,GAAS,CAAA,GAAK,EAAE,CAAA,GAAI,EAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,OAAO,YAAA,CAAa;AACjC,IAAA,KAAA;AACA,IAAA,IAAA;IACA,KAAA,EAAO,cAAA,CAAe,UAAU,cAAA,CAAe;AAChD,GAAA,CAAA;AACD,EAAA,MAAM,IAAA,GAAO,IAAI,YAAA,CAAa,IAAA,GAAO,CAAC,CAAA;AACtC,EAAA,OAAO;AACL,IAAA,MAAA;AACA,IAAA,IAAA;IACA,KAAA,GAAK;AACH,MAAA,MAAA,CAAO,KAAA,CAAM,YAAY,MAAA,EAAQ,CAAA,EAAG,KAAK,MAAA,EAAQ,IAAA,CAAK,UAAA,EAAY,IAAA,CAAK,UAAU,CAAA;AACnF,IAAA;;AAEJ;AAUM,SAAU,iBAAA,CACd,MAAA,EACA,YAAA,EACA,KAAA,EAAa;AAEb,EAAA,IAAI,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,GAAG,CAAA;AACzC,EAAA,IAAI,MAAA,GAAS,OAAO,YAAA,CAAa;AAC/B,IAAA,KAAA;IACA,IAAA,EAAM,QAAA;IACN,KAAA,EAAO,cAAA,CAAe,UAAU,cAAA,CAAe;AAChD,GAAA,CAAA;AAED,EAAA,OAAO;AACL,IAAA,IAAI,MAAA,GAAM;AACR,MAAA,OAAO,MAAA;AACT,IAAA,CAAA;AACA,IAAA,MAAA,CAAO,UAAA,EAAU;AACf,MAAA,IAAI,UAAA,IAAc,QAAA;AAAU,QAAA,OAAO,MAAA;AACnC,MAAA,MAAA,CAAO,OAAA,EAAO;AAGd,MAAA,QAAA,GAAW,KAAK,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,UAAU,CAAC,CAAA;AAC/C,MAAA,MAAA,GAAS,OAAO,YAAA,CAAa;AAC3B,QAAA,KAAA;QACA,IAAA,EAAM,QAAA;QACN,KAAA,EAAO,cAAA,CAAe,UAAU,cAAA,CAAe;AAChD,OAAA,CAAA;AACD,MAAA,OAAO,MAAA;AACT,IAAA,CAAA;AACA,IAAA,KAAA,CAAM,MAAM,UAAA,EAAU;AACpB,MAAA,MAAA,CAAO,KAAA,CAAM,YAAY,MAAA,EAAQ,CAAA,EAAG,KAAK,MAAA,EAAQ,IAAA,CAAK,UAAA,EAAY,UAAA,GAAa,CAAC,CAAA;AAClF,IAAA,CAAA;IACA,OAAA,GAAO;AACL,MAAA,MAAA,CAAO,OAAA,EAAO;AAChB,IAAA;;AAEJ;;;AC9EO,IAAM,aAAA,GAAiC;EAC5C,KAAA,EAAO,CAAA;EACP,IAAA,EAAM,CAAA;EACN,KAAA,EAAO,CAAA;EACP,YAAA,EAAc;;;;AClBT,IAAM,eAAA,GAAkB;AACxB,IAAM,iBAAiB,eAAA,GAAkB;AAiBhD,IAAM,UAAA,GAAa,CAAC,KAAA,MAA0C;EAC5D,GAAG,aAAA;AACH,EAAA,GAAG,KAAA,CAAM;;AAIX,SAAS,kBAAA,CAAmB,OAAsB,KAAA,EAAa;AAC7D,EAAA,IAAI,KAAA,IAAS,CAAA;AAAG,IAAA,OAAO,KAAA;AACvB,EAAA,MAAM,KAAA,GAAQ,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAC,CAAA,GAAI,sBAAA,CAAuB,qBAAA;AAC3E,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,IAAA,EAAM,CAAC,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,GAAI,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,GAAI,KAAK,CAAA,EAAC;AACzE;AAOM,SAAU,eAAA,CACd,KAAA,EACA,MAAA,EACA,OAAA,GAA2B,wBAAA,EAAwB;AAEnD,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAG;AACpB,EAAA,KAAA,MAAW,OAAA,IAAW,MAAM,QAAA,EAAU;AACpC,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA,EAAG;AAC5B,MAAA,MAAM,aAAA,CACJ,iBAAA,EACA,CAAA,OAAA,EAAU,KAAA,CAAM,OAAO,oBAAoB,OAAA,CAAQ,MAAM,CAAA,QAAA,CAAA,EACzD,OAAA,CAAQ,MAAM,CAAA;AAElB,IAAA;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,MAAA,EAAQ,OAAO,CAAA;AAClC,EAAA;AAEA,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAG;AAC9B,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAG;AACzB,EAAA,MAAM,cAAA,GAAiB,CAAC,OAAA,KAAwC;AAC9D,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA;AAChD,IAAA,IAAI,MAAA,KAAW,MAAA;AAAW,MAAA,OAAO,MAAA;AACjC,IAAA,IAAI,SAAA,CAAU,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjC,MAAA,MAAM,aAAA,CACJ,YAAA,EACA,CAAA,8BAAA,EAAiC,KAAA,CAAM,OAAO,2BAA2B,OAAA,CAAQ,MAAM,CAAA,6DAAA,CAAA,EACvF,OAAA,CAAQ,MAAM,CAAA;AAElB,IAAA;AACA,IAAA,SAAA,CAAU,GAAA,CAAI,QAAQ,MAAM,CAAA;AAE5B,IAAA,MAAM,QAAA,GAAW,WAAW,OAAO,CAAA;AACnC,IAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,kBAAA;AAEvC,IAAA,IAAI,OAAA,CAAQ,iBAAiB,MAAA,EAAW;AACtC,MAAA,MAAMC,MAAAA,GAAQ,mBAAA,CACZ,kBAAA,CAAmB,OAAA,CAAQ,OAAO,QAAA,CAAS,KAAK,CAAA,EAChD,SAAA,EACA,OAAA,CAAQ,MAAA,EACR,EAAE,OAAA,EAAS,OAAO,CAAA;AAEpB,MAAA,cAAA,CAAe,GAAA,CAAI,OAAA,CAAQ,MAAA,EAAQA,MAAK,CAAA;AACxC,MAAA,SAAA,CAAU,MAAA,CAAO,QAAQ,MAAM,CAAA;AAC/B,MAAA,OAAOA,MAAAA;AACT,IAAA;AAEA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,aAAa,MAAM,CAAA;AACxD,IAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,MAAA,MAAM,aAAA,CACJ,YAAA,EACA,CAAA,SAAA,EAAY,OAAA,CAAQ,MAAM,CAAA,oBAAA,EAAuB,OAAA,CAAQ,YAAA,CAAa,MAAM,CAAA,mCAAA,EAAsC,KAAA,CAAM,OAAO,CAAA,8HAAA,CAAA,EAC/H,QAAQ,MAAM,CAAA;AAElB,IAAA;AAGA,IAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,cAAA,CAAe,WAAW,CAAA,EAAG;AAC3D,MAAA,KAAA,EAAO,QAAQ,YAAA,CAAa;KAC7B,CAAA,CAAE,KAAA;AACH,IAAA,cAAA,CAAe,GAAA,CAAI,OAAA,CAAQ,MAAA,EAAQ,KAAK,CAAA;AACxC,IAAA,SAAA,CAAU,MAAA,CAAO,QAAQ,MAAM,CAAA;AAC/B,IAAA,OAAO,KAAA;AACT,EAAA,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KACjB,MAAA,KAAW,SAAS,mBAAA,CAAoB,KAAK,CAAA,GAAI,WAAA,CAAY,KAAK,CAAA;AAIpE,EAAA,OAAO,KAAA,CAAM,QAAA,CACV,MAAA,CAAO,CAAC,OAAA,KAAY,OAAA,CAAQ,kBAAA,KAAuB,IAAI,CAAA,CACvD,GAAA,CAAI,CAAC,OAAA,KAA4B;AAClC,IAAA,MAAM,QAAA,GAAW,WAAW,OAAO,CAAA;AACnC,IAAA,MAAM,KAAA,GAAQ,eAAe,OAAO,CAAA;AAEpC,IAAA,MAAM,WAAA,GACJ,OAAA,CAAQ,YAAA,KAAiB,MAAA,GACrB,KAAA,GACA,cAAA,CAAe,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,YAAA,CAAa,MAAM,CAAiB,CAAA;AAC1E,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,YAAA,EAAc,KAAA,IAAS,CAAA;AAE7C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,CAAC,CAAC,CAAA;AACtE,IAAA,OAAO;AACL,MAAA,MAAA,EAAQ,OAAA,CAAQ,MAAA;AAChB,MAAA,KAAA;AACA,MAAA,KAAA,EAAO,UAAU,WAAW,CAAA;AAC5B,MAAA,KAAA;MACA,MAAA,EAAQ,CAAC,WAAA,CAAY,QAAA,CAAS,MAAA,CAAO,CAAC,GAAG,WAAA,CAAY,QAAA,CAAS,MAAA,CAAO,CAAC,CAAC,CAAA;AACvE,MAAA,QAAA;AACA,MAAA,MAAA;AACA,MAAA,WAAA,EAAa,WAAA,CAAY,KAAA,CAAM,QAAA,CAAS,SAAA,EAAW,QAAQ,OAAO;;EAEtE,CAAC,CAAA;AACH;AAUM,SAAU,cAAA,CACd,QAAA,EACA,KAAA,GAA0B,mBAAA,EAC1B,aAAa,CAAA,EAAC;AAEd,EAAA,IAAI,SAAS,MAAA,KAAW,CAAA;AAAG,IAAA,OAAO,EAAE,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,KAAA,EAAO,CAAA,EAAG,QAAQ,CAAA,EAAC;AAEnE,EAAA,IAAI,OAAO,MAAA,CAAO,iBAAA;AAClB,EAAA,IAAI,OAAO,MAAA,CAAO,iBAAA;AAClB,EAAA,IAAI,OAAO,MAAA,CAAO,iBAAA;AAClB,EAAA,IAAI,OAAO,MAAA,CAAO,iBAAA;AAElB,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,MAAM,CAAC,EAAA,EAAI,EAAE,CAAA,GAAI,OAAA,CAAQ,MAAM,QAAA,CAAS,MAAA;AACxC,IAAA,MAAM,CAAC,CAAA,EAAG,CAAC,CAAA,GAAI,OAAA,CAAQ,MAAM,QAAA,CAAS,IAAA;AACtC,IAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,EAAA,GAAK,IAAI,CAAC,CAAA;AAChC,IAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,EAAA,GAAK,IAAI,CAAC,CAAA;AAChC,IAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,EAAA,GAAK,IAAI,CAAC,CAAA;AAChC,IAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,EAAA,GAAK,IAAI,CAAC,CAAA;AAClC,EAAA;AAEA,EAAA,MAAM,GAAA,GAAM,UAAA,GAAa,KAAA,CAAM,QAAA,GAAW,CAAA;AAC1C,EAAA,OAAO;AACL,IAAA,CAAA,EAAG,IAAA,GAAO,GAAA;AACV,IAAA,CAAA,EAAG,IAAA,GAAO,GAAA;IACV,KAAA,EAAO,IAAA,GAAO,OAAO,CAAA,GAAI,GAAA;IACzB,MAAA,EAAQ,IAAA,GAAO,OAAO,CAAA,GAAI;;AAE9B;AA8BM,SAAU,qBAAA,CACd,OAAA,EACA,gBAAA,EACA,YAAA,EAAuC;AAEvC,EAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,CAAQ,CAAA,GAAI,gBAAgB,CAAC,CAAA;AACjE,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,OAAA,CAAQ,CAAA,GAAI,gBAAgB,CAAC,CAAA;AAChE,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CACjB,YAAA,CAAa,CAAC,CAAA,EACd,IAAA,CAAK,KAAA,CAAA,CAAO,OAAA,CAAQ,CAAA,GAAI,OAAA,CAAQ,KAAA,IAAS,gBAAgB,CAAC,CAAA;AAE5D,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAClB,YAAA,CAAa,CAAC,CAAA,EACd,IAAA,CAAK,KAAA,CAAA,CAAO,OAAA,CAAQ,CAAA,GAAI,OAAA,CAAQ,MAAA,IAAU,gBAAgB,CAAC,CAAA;AAE7D,EAAA,IAAI,KAAA,IAAS,QAAQ,MAAA,IAAU,GAAA;AAAK,IAAA,OAAO,MAAA;AAC3C,EAAA,OAAO,EAAE,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,GAAA,EAAK,OAAO,KAAA,GAAQ,IAAA,EAAM,MAAA,EAAQ,MAAA,GAAS,GAAA,EAAG;AACrE;AAGM,SAAU,sBAAA,CAAuB,MAAY,gBAAA,EAAwB;AACzE,EAAA,MAAM,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,CAAA,GAAI,gBAAgB,CAAA,GAAI,gBAAA;AAClD,EAAA,MAAM,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,CAAA,GAAI,gBAAgB,CAAA,GAAI,gBAAA;AAClD,EAAA,MAAM,KAAA,GAAQ,KAAK,IAAA,CAAA,CAAM,IAAA,CAAK,IAAI,IAAA,CAAK,KAAA,IAAS,gBAAgB,CAAA,GAAI,gBAAA;AACpE,EAAA,MAAM,MAAA,GAAS,KAAK,IAAA,CAAA,CAAM,IAAA,CAAK,IAAI,IAAA,CAAK,MAAA,IAAU,gBAAgB,CAAA,GAAI,gBAAA;AACtE,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,KAAA,EAAO,IAAA,CAAK,IAAI,KAAA,GAAQ,CAAA,EAAG,CAAC,CAAA,EAAG,QAAQ,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,CAAA,EAAG,CAAC,CAAA,EAAC;AAC/E;AAQM,SAAU,aAAA,CACd,QAAA,EACA,MAAA,EACA,IAAA,EAAmB;AAEnB,EAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,MAAA,EAAQ,CAAC,CAAA,GAAI,eAAA;AAC9C,EAAA,MAAM,IAAA,GACJ,SAAS,MAAA,IAAa,IAAA,CAAK,UAAU,MAAA,GAAS,IAAA,GAAO,IAAI,YAAA,CAAa,MAAM,CAAA;AAE9E,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,MAAA,EAAQ,KAAK,CAAA,EAAG;AAC3C,IAAA,MAAM,CAAA,GAAI,SAAS,CAAC,CAAA;AACpB,IAAA,MAAM,IAAI,CAAA,GAAI,eAAA;AACd,IAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,CAAE,OAAO,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA;AACpC,IAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,CAAE,OAAO,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA;AACpC,IAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,KAAA;AACtB,IAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,KAAA;AACtB,IAAA,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,KAAA;AACtB,IAAA,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,EAAE,CAAC,CAAA;AACzB,IAAA,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,EAAE,CAAC,CAAA;AACzB,IAAA,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,EAAE,CAAC,CAAA;AACzB,IAAA,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,EAAE,CAAC,CAAA;AACzB,IAAA,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI,CAAA,CAAE,KAAA,CAAM,EAAE,CAAC,CAAA;AACzB,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,KAAA;AACjB,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,MAAM,QAAA,CAAS,SAAA;AAChC,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,KAAA;AAC1B,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,IAAA;AAI1B,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA,CAAE,cAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAA,CAAE,QAAA,CAAS,YAAY,CAAC,CAAA;AAC/E,IAAA,IAAA,CAAK,CAAA,GAAI,EAAE,CAAA,GAAI,CAAA;AACjB,EAAA;AAEA,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,QAAA,CAAS,MAAA,EAAM;AACvC;;;ACxQM,SAAU,mBAAmB,MAAA,EAAiB;AAClD,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,iBAAiB,CAAA;AAC9C;AAEM,SAAU,qBAAA,CAAsB,MAAA,EAAmB,QAAA,GAAW,EAAA,EAAE;AACpE,EAAA,MAAM,QAAA,GAAW,OAAO,cAAA,CAAe;IACrC,KAAA,EAAO,eAAA;IACP,IAAA,EAAM,WAAA;AACN,IAAA,KAAA,EAAO,QAAA,GAAW;AACnB,GAAA,CAAA;AACD,EAAA,MAAM,UAAA,GAAa,WAAW,CAAA,GAAI,CAAA;AAClC,EAAA,MAAM,aAAA,GAAgB,OAAO,YAAA,CAAa;IACxC,KAAA,EAAO,uBAAA;IACP,IAAA,EAAM,UAAA;IACN,KAAA,EAAO,cAAA,CAAe,gBAAgB,cAAA,CAAe;AACtD,GAAA,CAAA;AACD,EAAA,MAAM,OAAA,GAAU,OAAO,YAAA,CAAa;IAClC,KAAA,EAAO,uBAAA;IACP,IAAA,EAAM,UAAA;IACN,KAAA,EAAO,cAAA,CAAe,WAAW,cAAA,CAAe;AACjD,GAAA,CAAA;AAED,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,MAAM,SAAmB,EAAA;AAEzB,EAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAA6D;AACzE,IAAA,IAAI,IAAA,IAAQ,QAAA;AAAU,MAAA,OAAO,MAAA;AAC7B,IAAA,MAAM,KAAA,GAAQ,IAAA;AACd,IAAA,IAAA,IAAQ,CAAA;AACR,IAAA,MAAA,CAAO,KAAK,CAAA,GAAI,KAAA;AAChB,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,GAAQ,GAAG,GAAA,EAAK,KAAA,GAAQ,IAAI,CAAA,EAAC;AAC/C,EAAA,CAAA;AAEA,EAAA,OAAO;AACL,IAAA,QAAA;AACA,IAAA,IAAI,IAAA,GAAI;AACN,MAAA,OAAO,IAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,SAAA,GAAS;AACX,MAAA,OAAO,SAAA;AACT,IAAA,CAAA;AAEA,IAAA,UAAA,CAAW,KAAA,EAAK;AACd,MAAA,MAAM,IAAA,GAAO,KAAK,KAAK,CAAA;AACvB,MAAA,IAAI,IAAA,KAAS,MAAA;AAAW,QAAA,OAAO,MAAA;AAC/B,MAAA,OAAO;AACL,QAAA,QAAA;AACA,QAAA,yBAAA,EAA2B,IAAA,CAAK,KAAA;AAChC,QAAA,mBAAA,EAAqB,IAAA,CAAK;;AAE9B,IAAA,CAAA;AAEA,IAAA,WAAA,CAAY,KAAA,EAAK;AACf,MAAA,MAAM,IAAA,GAAO,KAAK,KAAK,CAAA;AACvB,MAAA,IAAI,IAAA,KAAS,MAAA;AAAW,QAAA,OAAO,MAAA;AAC/B,MAAA,OAAO;AACL,QAAA,QAAA;AACA,QAAA,yBAAA,EAA2B,IAAA,CAAK,KAAA;AAChC,QAAA,mBAAA,EAAqB,IAAA,CAAK;;AAE9B,IAAA,CAAA;AAEA,IAAA,OAAA,CAAQ,OAAA,EAAO;AACb,MAAA,IAAI,IAAA,KAAS,CAAA;AAAG,QAAA;AAChB,MAAA,OAAA,CAAQ,gBAAgB,QAAA,EAAU,CAAA,EAAG,IAAA,GAAO,CAAA,EAAG,eAAe,CAAC,CAAA;AAC/D,MAAA,OAAA,CAAQ,mBAAmB,aAAA,EAAe,CAAA,EAAG,SAAS,CAAA,EAAG,IAAA,GAAO,IAAI,CAAC,CAAA;AACvE,IAAA,CAAA;AAEA,IAAA,MAAM,IAAA,GAAI;AACR,MAAA,MAAM,GAAA,uBAAU,GAAA,EAAG;AACnB,MAAA,IAAI,IAAA,KAAS,CAAA;AAAG,QAAA,OAAO,GAAA;AACvB,MAAA,MAAM,QAAQ,QAAA,CAAS,UAAA,CAAW,MAAM,CAAA,EAAG,IAAA,GAAO,IAAI,CAAC,CAAA;AACvD,MAAA,MAAM,IAAA,GAAO,IAAI,aAAA,CAAc,OAAA,CAAQ,cAAA,CAAe,CAAA,EAAG,IAAA,GAAO,CAAA,GAAI,CAAC,CAAA,CAAE,KAAA,CAAM,CAAC,CAAC,CAAA;AAC/E,MAAA,OAAA,CAAQ,KAAA,EAAK;AACb,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,EAAM,KAAK,CAAA,EAAG;AAChC,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAC7B,QAAA,MAAM,GAAA,GAAM,IAAA,CAAK,CAAA,GAAI,CAAA,GAAI,CAAC,CAAA,IAAK,EAAA;AAC/B,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,CAAC,CAAA,IAAK,QAAQ,CAAC,CAAA,CAAA;AACpC,QAAA,MAAM,OAAA,GAAU,MAAA,CAAO,GAAA,GAAM,KAAK,CAAA;AAMlC,QAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,OAAO,CAAA,IAAK,UAAU,CAAA,IAAM,KAAA,KAAU,EAAA,IAAM,GAAA,KAAQ,EAAA,EAAK;AAC5E,UAAA,SAAA,IAAa,CAAA;AACb,UAAA;AACF,QAAA;AAIA,QAAA,GAAA,CAAI,IAAI,KAAA,EAAA,CAAQ,GAAA,CAAI,IAAI,KAAK,CAAA,IAAK,KAAK,OAAO,CAAA;AAChD,MAAA;AACA,MAAA,OAAO,GAAA;AACT,IAAA,CAAA;IAEA,KAAA,GAAK;AACH,MAAA,IAAA,GAAO,CAAA;AACP,MAAA,MAAA,CAAO,MAAA,GAAS,CAAA;AAClB,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,QAAA,CAAS,OAAA,EAAO;AAChB,MAAA,aAAA,CAAc,OAAA,EAAO;AACrB,MAAA,OAAA,CAAQ,OAAA,EAAO;AACjB,IAAA;;AAEJ;AAGO,IAAM,UAAA,GAAa;EACxB,MAAA,EAAQ,iBAAA;EACR,KAAA,EAAO,YAAA;EACP,QAAA,EAAU,WAAA;EACV,QAAA,EAAU,UAAA;EACV,KAAA,EAAO,aAAA;EACP,MAAA,EAAQ,QAAA;EACR,SAAA,EAAW;;;;ACnJN,IAAM,wBAAA,GAA2B;AACjC,IAAM,qBAAA,GAAwB;AAE9B,IAAM,qBAAA,GAAwB,CAAA;;;;;;;;;;;;;;;;;;;;2BAoBV,qBAAqB,CAAA;;;;;;;;;;;;;;;ACMzC,IAAM,gBAAA,GAAmB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8C1B,SAAU,iBAAiB,IAAA,EAA4B;AAC3D,EAAA,MAAM,IAAA,GAAO,IAAA,KAAS,UAAA,GAAa,kBAAA,GAAqB,iBAAA;AACxD,EAAA,MAAM,IAAA,GACJ,IAAA,KAAS,UAAA,GACL,0DAAA,GACA,qDAAA;AACN,EAAA,OAAO,iBAAiB,OAAA,CAAQ,kBAAA,EAAoB,IAAI,CAAA,CAAE,OAAA,CAAQ,mBAAmB,IAAI,CAAA;AAC3F;AAMO,IAAM,oBAAA,GAAuB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxD7B,IAAM,oBAAA,GAAuB,CAAA;;;;;;;;;;;;;;;;AAkB7B,IAAM,iBAAA,GAAoB,CAAA;;;;AAgB1B,IAAM,eAAA,GAAkB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgGxB,IAAM,cAAA,GAAiB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDvB,IAAM,iBAAA,GAAoB,CAAA;;;;;;;;;;;;;;;;;AA+B1B,IAAM,eAAA,GAAkB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsFzB,SAAU,gBAAgB,MAAA,EAAwB;AACtD,EAAA,MAAM,OAAA,GAAU,WAAW,OAAA,GAAU,CAAC,YAAY,eAAe,CAAA,GAAI,CAAC,SAAA,EAAW,cAAc,CAAA;AAC/F,EAAA,MAAM,EAAA,GAAK,MAAA,KAAW,OAAA,GAAU,eAAA,GAAkB,cAAA;AAClD,EAAA,OAAO;AACL,IAAA,oBAAA;AACA,IAAA,iBAAA;IACA,GAAG,OAAA;AACH,IAAA,iBAAA;IACA,eAAA,CAAgB,OAAA,CAAQ,YAAY,EAAE;AACtC,GAAA,CAAA,IAAA,CAAK,MAAM,CAAA;AACf;AAWO,IAAM,kBAAA,GAAqB;AAChC,EAAA,oBAAA;AACA,EAAA,iBAAA;AACA,EAAA,UAAA;AACA,EAAA,SAAA;AACA,EAAA,eAAA;AACA,EAAA,cAAA;AACA,EAAA;AACA,CAAA,CAAA,IAAA,CAAK,MAAM;;;AC9VN,IAAM,mBAAA,GAAsB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACoB5B,IAAM,gBAAA,GAAmB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxCzB,IAAM,YAAA,GAAe,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACgB5B,IAAM,WAAA,GAAc,CAAC,IAAA,KAAyB,CAAA,EAAG,YAAY;EAAK,IAAI;;AAI/D,IAAM,cAAc,CAAC,MAAA,KAAgC,WAAA,CAAY,eAAA,CAAgB,MAAM,CAAC;AAExF,IAAM,eAAe,CAAC,IAAA,KAC3B,WAAA,CAAY,gBAAA,CAAiB,IAAI,CAAC;AAE7B,IAAM,WAAA,GAAc,MAAc,WAAA,CAAY,oBAAoB;AAElE,IAAM,cAAA,GAAiB,MAAc,WAAA,CAAY,kBAAkB;AAEnE,IAAM,YAAA,GAAe,MAAc,WAAA,CAAY,gBAAgB;AAE/D,IAAM,eAAA,GAAkB,MAAc,WAAA,CAAY,mBAAmB;AASrE,IAAM,sBAAA,GAAyB,MACpC,WAAA,CAAY,CAAC,oBAAoB,qBAAqB,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC;AAShE,SAAU,eAAA,GAAe;AAC7B,EAAA,OAAO;AACL,IAAA,YAAA;AACA,IAAA,eAAA,CAAgB,OAAO,CAAA;AACvB,IAAA,eAAA,CAAgB,MAAM,CAAA;AACtB,IAAA,gBAAA,CAAiB,SAAS,CAAA;AAC1B,IAAA,gBAAA,CAAiB,UAAU,CAAA;AAC3B,IAAA,oBAAA;AACA,IAAA,kBAAA;AACA,IAAA,gBAAA;AACA,IAAA;AACA,GAAA,CAAA,IAAA,CAAK,MAAM,CAAA;AACf;;;ACpCA,IAAM,UAAA,GAAa,MACjB,eAAA,CAAgB,iBAAA,GAAoB,eAAA,CAAgB,eAAA;AAGtD,IAAM,kBAAA,GAAoC;AACxC,EAAA,KAAA,EAAO,EAAE,SAAA,EAAW,KAAA,EAAO,SAAA,EAAW,qBAAA,EAAuB,WAAW,KAAA,EAAK;AAC7E,EAAA,KAAA,EAAO,EAAE,SAAA,EAAW,KAAA,EAAO,SAAA,EAAW,qBAAA,EAAuB,WAAW,KAAA;;AA4GpE,SAAU,iBAAiB,OAAA,EAAmB;AAClD,EAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAK,GAAK,OAAA;AAChC,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAG;AACxB,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAG;AAKxB,EAAA,MAAM,cAAA,GAAiB,IAAA;AAEvB,EAAA,MAAM,WAAA,GAAc,OAAO,aAAA,CAAc;IACvC,KAAA,EAAO,oBAAA;AACP,IAAA,IAAA,EAAM,EAAE,KAAA,EAAO,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAG,oBAAoB,CAAA,EAAC;IAClD,MAAA,EAAQ,sBAAA;AACR,IAAA,KAAA,EAAO,UAAA;AACR,GAAA,CAAA;AAED,EAAA,MAAM,WAAA,GAAc,CAAC,GAAA,EAAa,MAAA,KAA+B;AAC/D,IAAA,IAAI,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA;AAC3B,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,IAAA,GAAO,iBAAA,CAAkB,MAAA,EAAQ,MAAA,EAAQ,CAAA,eAAA,EAAkB,GAAG,CAAA,CAAE,CAAA;AAChE,MAAA,QAAA,CAAS,GAAA,CAAI,KAAK,IAAI,CAAA;AACxB,IAAA;AACA,IAAA,OAAO,IAAA;AACT,EAAA,CAAA;AAEA,EAAA,MAAM,WAAA,GAAc,CAAC,GAAA,KAA4B;AAC/C,IAAA,IAAI,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA;AAC3B,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,IAAA,GAAO,kBAAkB,MAAA,EAAQ,CAAA,GAAI,cAAA,EAAgB,CAAA,iBAAA,EAAoB,GAAG,CAAA,CAAE,CAAA;AAC9E,MAAA,QAAA,CAAS,GAAA,CAAI,KAAK,IAAI,CAAA;AACxB,IAAA;AACA,IAAA,OAAO,IAAA;AACT,EAAA,CAAA;AAEA,EAAA,MAAM,aAAA,GAAgB,CAAC,MAAA,KACrB,KAAA,CAAM,cAAA,CAAe,YAAY,KAAA,CAAM,MAAA,EAAQ,sBAAsB,CAAA,EAAG,MAAK;AAC3E,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,CAAA,aAAA,EAAgB,MAAM,CAAA,CAAA,EAAI,MAAM,WAAA,CAAY,MAAM,CAAC,CAAA;AAC/E,IAAA,OAAO;AACL,MAAA,KAAA,EAAO,yBAAyB,MAAM,CAAA,CAAA;MACtC,MAAA,EAAQ,MAAA;MACR,MAAA,EAAQ,EAAE,MAAA,EAAQ,UAAA,EAAY,eAAA,EAAe;MAC7C,QAAA,EAAU;AACR,QAAA,MAAA;QACA,UAAA,EAAY,UAAA;QACZ,OAAA,EAAS,CAAC,EAAE,MAAA,EAAQ,sBAAA,IAA0B,EAAE,MAAA,EAAQ,wBAAwB;;MAElF,SAAA,EAAW,EAAE,UAAU,eAAA;;EAE3B,CAAC,CAAA;AAEH,EAAA,MAAM,cAAA,GAAiB,CAAC,MAAA,KACtB,KAAA,CAAM,cAAA,CAAe,YAAY,MAAA,CAAO,MAAA,EAAQ,oBAAoB,CAAA,EAAG,MAAK;AAC1E,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,eAAA,EAAiB,YAAY,CAAA;AACzD,IAAA,OAAO;MACL,KAAA,EAAO,wBAAA;MACP,MAAA,EAAQ,MAAA;MACR,MAAA,EAAQ,EAAE,MAAA,EAAQ,UAAA,EAAY,eAAA,EAAe;MAC7C,QAAA,EAAU;AACR,QAAA,MAAA;QACA,UAAA,EAAY,WAAA;AACZ,QAAA,OAAA,EAAS,CAAC,EAAE,MAAA,EAAQ,KAAA,EAAO,oBAAoB;;MAEjD,SAAA,EAAW,EAAE,UAAU,eAAA;;EAE3B,CAAC,CAAA;AAEH,EAAA,MAAM,iBAAA,GAAoB,CAAC,MAAA,KACzB,KAAA,CAAM,cAAA,CAAe,YAAY,SAAA,CAAU,MAAA,EAAQ,oBAAoB,CAAA,EAAG,MAAK;AAC7E,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,kBAAA,EAAoB,eAAe,CAAA;AAC/D,IAAA,OAAO;MACL,KAAA,EAAO,2BAAA;MACP,MAAA,EAAQ,MAAA;MACR,MAAA,EAAQ,EAAE,MAAA,EAAQ,UAAA,EAAY,eAAA,EAAe;MAC7C,QAAA,EAAU;AACR,QAAA,MAAA;QACA,UAAA,EAAY,cAAA;AACZ,QAAA,OAAA,EAAS,CAAC,EAAE,MAAA,EAAQ,KAAA,EAAO,oBAAoB;;MAEjD,SAAA,EAAW,EAAE,UAAU,eAAA;;EAE3B,CAAC,CAAA;AAEH,EAAA,MAAM,MAAA,GAAS,CACb,IAAA,EACA,IAAA,KACQ;AACR,IAAA,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,CAAA,EAAG,IAAA,CAAK,CAAA,EAAG,KAAK,KAAA,EAAO,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAG,CAAC,CAAA;AAG9D,IAAA,IAAA,CAAK,cAAA,CAAe,KAAK,CAAA,EAAG,IAAA,CAAK,GAAG,IAAA,CAAK,KAAA,EAAO,KAAK,MAAM,CAAA;AAC7D,EAAA,CAAA;AAEA,EAAA,MAAM,eAAA,GAAkB,YAAY,UAAA,EAAU;AAC9C,EAAA,IAAI,QAAA;AAGJ,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,KAAqE;AAClF,IAAA,MAAM,IAAA,GAAO,QAAA,EAAU,UAAA,CAAW,KAAK,CAAA;AACvC,IAAA,OAAO,SAAS,MAAA,GAAY,EAAA,GAAK,EAAE,iBAAiB,IAAA,EAAI;AAC1D,EAAA,CAAA;AAEA,EAAA,OAAO;AACL,IAAA,eAAA;AAEA,IAAA,SAAA,CAAU,SAAS,IAAA,EAAI;AAIrB,MAAA,MAAM,SAAA,GAAY,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,KAAK,CAAC,CAAA;AAC/D,MAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAM,CAAC,CAAA;AACjE,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,KAAA,GAAQ,IAAA,CAAK,WAAW,CAAC,CAAA;AAC9E,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAA,GAAS,IAAA,CAAK,WAAW,CAAC,CAAA;AAEhF,MAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,QAAQ,UAAA,CAAW,IAAA,CAAK,OAAO,CAAA,EAAG;AAC3D,QAAA,KAAA;AACA,QAAA,MAAA;QACA,MAAA,EAAQ,sBAAA;AACR,QAAA,KAAA,EAAO,UAAA,EAAU;QACjB,KAAA,EAAO,CAAA,aAAA,EAAgB,KAAK,OAAO,CAAA,MAAA;AACpC,OAAA,CAAA;AACD,MAAA,MAAM,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAQ,QAAA,CAAS,IAAA,CAAK,OAAO,CAAA,EAAG;AACvD,QAAA,KAAA;AACA,QAAA,MAAA;QACA,MAAA,EAAQ,sBAAA;AACR,QAAA,KAAA,EAAO,UAAA,EAAU;QACjB,KAAA,EAAO,CAAA,aAAA,EAAgB,KAAK,OAAO,CAAA,IAAA;AACpC,OAAA,CAAA;AAUD,MAAA,MAAM,OAAO,WAAA,CAAY,CAAA,MAAA,EAAS,IAAA,CAAK,OAAO,IAAI,EAAE,CAAA;AACpD,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,SAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,UAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,YAAA;AAGpB,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,mBAAmB,SAAA,GAAY,KAAA,CAAA;AACnD,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,SAAA;AAC1B,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,QAAA;AAC1B,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,mBAAA;AAC1B,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AAGf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAChB,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAChB,MAAA,IAAI,WAAA,CAAY,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,IAAA,CAAK,UAAA,GAAa,EAAA,EAAI,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,aAAA;AAC1E,MAAA,IAAA,CAAK,KAAA,EAAK;AAEV,MAAA,MAAM,SAAA,GAAY,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA;AAC1C,MAAA,SAAA,CAAU,OAAO,IAAA,CAAK,GAAA,CAAI,KAAK,aAAA,EAAe,CAAC,IAAI,cAAc,CAAA;AACjE,MAAA,SAAA,CAAU,KAAA,CAAM,IAAA,CAAK,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,KAAK,aAAA,EAAe,CAAC,CAAA,IAAK,cAAA,GAAiB,CAAA,CAAE,CAAA;AAEtF,MAAA,MAAM,QAAA,GAAW,aAAA,CAAc,IAAA,CAAK,MAAM,CAAA;AAC1C,MAAA,MAAM,IAAA,GAAO,QAAQ,eAAA,CAAgB;QACnC,KAAA,EAAO,CAAA,kBAAA,EAAqB,KAAK,OAAO,CAAA,CAAA;QACxC,GAAG,KAAA,CAAM,WAAW,KAAK,CAAA;QACzB,gBAAA,EAAkB;AAChB,UAAA;AACE,YAAA,IAAA,EAAM,MAAM,UAAA,EAAU;YACtB,MAAA,EAAQ,OAAA;YACR,OAAA,EAAS,OAAA;YACT,UAAA,EAAY,EAAE,GAAG,cAAA,EAAgB,CAAA,EAAG,GAAG,CAAA,EAAG,EAAA,EAAI,GAAG,CAAA;;AAEnD,UAAA;AACE,YAAA,IAAA,EAAM,IAAI,UAAA,EAAU;YACpB,MAAA,EAAQ,OAAA;YACR,OAAA,EAAS,OAAA;YACT,UAAA,EAAY,EAAE,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA;;;AAGxC,OAAA,CAAA;AACD,MAAA,IAAA,CAAK,YAAY,QAAQ,CAAA;AACzB,MAAA,IAAA,CAAK,YAAA,CACH,CAAA,EACA,MAAA,CAAO,eAAA,CAAgB;QACrB,MAAA,EAAQ,QAAA,CAAS,mBAAmB,CAAC,CAAA;QACrC,OAAA,EAAS;AACP,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAM,EAAE;AAC/C,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,SAAA,CAAU,QAAM;;OAErD,CAAC,CAAA;AAEJ,MAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,MAAA,IAAA,CAAK,GAAA,EAAG;AAER,MAAA,OAAO;AACL,QAAA,KAAA;AACA,QAAA,GAAA;AACA,QAAA,KAAA;AACA,QAAA,MAAA;QACA,SAAA,EAAW,KAAA,KAAU,aAAa,MAAA,KAAW;;AAEjD,IAAA,CAAA;AAEA,IAAA,UAAA,CAAW,SAAS,IAAA,EAAI;AACtB,MAAA,MAAM,OAAO,WAAA,CAAY,CAAA,OAAA,EAAU,IAAA,CAAK,OAAO,IAAI,EAAE,CAAA;AACrD,MAAA,MAAM,IAAI,IAAA,CAAK,IAAA;AACf,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA;AAC5B,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA;AAC5B,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,YAAA;AACZ,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,eAAA;AACZ,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AACjB,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AACjB,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AACjB,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AACjB,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,eAAA;AACZ,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,YAAA;AACZ,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,UAAA;AACb,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,WAAA;AACb,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACnB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACnB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACnB,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,SAAA;AACb,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA;AACxB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA;AACxB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA;AACxB,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,aAAA;AACb,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,QAAA;AACb,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,QAAA;AACb,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,aAAA;AACb,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,YAAA;AACb,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA;AAC7B,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA;AAC7B,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,WAAA;AACb,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,WAAA;AACb,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,QAAA,KAAa,SAAY,CAAA,GAAI,CAAA;AAC1C,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,KAAA;AACpB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA;AACpB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA,GAAI,CAAA;AACpC,MAAA,IAAA,CAAK,KAAA,EAAK;AAEV,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,QAAA,EAAU,KAAA,IAAS,eAAA;AACtC,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,EAAU,IAAA,IAAQ,eAAA;AAEpC,MAAA,MAAM,QAAA,GAAW,cAAA,CAAe,IAAA,CAAK,YAAY,CAAA;AACjD,MAAA,MAAM,IAAA,GAAO,QAAQ,eAAA,CAAgB;QACnC,KAAA,EAAO,CAAA,mBAAA,EAAsB,KAAK,OAAO,CAAA,CAAA;QACzC,GAAG,KAAA,CAAM,WAAW,MAAM,CAAA;QAC1B,gBAAA,EAAkB,CAAC,EAAE,IAAA,EAAM,IAAA,CAAK,QAAQ,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAS;AAC3E,OAAA,CAAA;AACD,MAAA,IAAA,CAAK,YAAY,QAAQ,CAAA;AACzB,MAAA,MAAA,CAAO,IAAA,EAAM,KAAK,UAAU,CAAA;AAC5B,MAAA,IAAA,CAAK,YAAA,CACH,CAAA,EACA,MAAA,CAAO,eAAA,CAAgB;QACrB,MAAA,EAAQ,QAAA,CAAS,mBAAmB,CAAC,CAAA;QACrC,OAAA,EAAS;AACP,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAM,EAAE;AAC/C,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,KAAK,MAAA,CAAO,KAAA,CAAM,YAAU,EAAE;AACtD,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,KAAK,MAAA,CAAO,GAAA,CAAI,YAAU,EAAE;AACpD,UAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,OAAA,CAAQ,YAAA,EAAY;UAC5C,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,KAAA,EAAK;UAC7B,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,IAAA,EAAI;;;AAG5B,UAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,OAAA,CAAQ,WAAA;;OAEnC,CAAC,CAAA;AAEJ,MAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,MAAA,IAAA,CAAK,GAAA,EAAG;AACV,IAAA,CAAA;AAEA,IAAA,aAAA,CAAc,SAAS,IAAA,EAAI;AACzB,MAAA,MAAM,OAAO,WAAA,CAAY,CAAA,UAAA,EAAa,IAAA,CAAK,OAAO,IAAI,EAAE,CAAA;AACxD,MAAA,MAAM,IAAI,IAAA,CAAK,IAAA;AACf,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA;AAC5B,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,cAAA,CAAe,CAAC,CAAA;AAC5B,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,YAAA;AACZ,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA;AACP,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,KAAA;AACZ,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,gBAAA;AACZ,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,SAAA;AACZ,MAAA,CAAA,CAAE,CAAC,IAAI,IAAA,CAAK,QAAA;AACZ,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,aAAA,CAAc,CAAC,CAAA;AAC3B,MAAA,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA,CAAK,aAAA,CAAc,CAAC,CAAA;AAC3B,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,aAAA;AACb,MAAA,CAAA,CAAE,EAAE,IAAI,IAAA,CAAK,QAAA;AACb,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACrB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACrB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACrB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,CAAA;AACR,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,KAAA;AACpB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,MAAA;AACpB,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA,GAAI,CAAA;AACpC,MAAA,CAAA,CAAE,EAAE,CAAA,GAAI,CAAA;AACR,MAAA,IAAA,CAAK,KAAA,EAAK;AAEV,MAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,IAAA,CAAK,YAAY,CAAA;AACpD,MAAA,MAAM,IAAA,GAAO,QAAQ,eAAA,CAAgB;QACnC,KAAA,EAAO,CAAA,sBAAA,EAAyB,KAAK,OAAO,CAAA,CAAA;QAC5C,GAAG,KAAA,CAAM,WAAW,SAAS,CAAA;QAC7B,gBAAA,EAAkB,CAAC,EAAE,IAAA,EAAM,IAAA,CAAK,QAAQ,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAS;AAC3E,OAAA,CAAA;AACD,MAAA,IAAA,CAAK,YAAY,QAAQ,CAAA;AACzB,MAAA,MAAA,CAAO,IAAA,EAAM,KAAK,UAAU,CAAA;AAC5B,MAAA,IAAA,CAAK,YAAA,CACH,CAAA,EACA,MAAA,CAAO,eAAA,CAAgB;QACrB,MAAA,EAAQ,QAAA,CAAS,mBAAmB,CAAC,CAAA;QACrC,OAAA,EAAS;AACP,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAM,EAAE;AAC/C,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,KAAK,MAAA,CAAO,KAAA,CAAM,YAAU,EAAE;AACtD,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,KAAK,MAAA,CAAO,GAAA,CAAI,YAAU,EAAE;AACpD,UAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,OAAA,CAAQ,WAAA;;OAEnC,CAAC,CAAA;AAEJ,MAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,MAAA,IAAA,CAAK,GAAA,EAAG;AACV,IAAA,CAAA;AAEA,IAAA,SAAA,CAAU,SAAS,MAAA,EAAM;AAKvB,MAAA,MAAM,IAAA,GAAO,QAAQ,eAAA,CAAgB;QACnC,KAAA,EAAO,mBAAA;QACP,gBAAA,EAAkB;AAChB,UAAA;YACE,IAAA,EAAM,MAAA;YACN,MAAA,EAAQ,OAAA;YACR,OAAA,EAAS,OAAA;YACT,UAAA,EAAY,EAAE,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA;;;AAGxC,OAAA,CAAA;AACD,MAAA,IAAA,CAAK,GAAA,EAAG;AACV,IAAA,CAAA;AAEA,IAAA,WAAA,CAAY,IAAA,EAAI;AACd,MAAA,QAAA,GAAW,IAAA;AACb,IAAA,CAAA;AAEA,IAAA,MAAA,CAAO,OAAA,EAAO;AACZ,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,UAAA,CAAW,OAAO,CAAC,CAAA;AACxC,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAC,CAAA;AACtC,MAAA,QAAA,CAAS,GAAA,CAAI,OAAO,CAAA,EAAG,OAAA,EAAO;AAC9B,MAAA,QAAA,CAAS,OAAO,OAAO,CAAA;AACvB,MAAA,KAAA,MAAW,GAAA,IAAO,CAAC,CAAA,MAAA,EAAS,OAAO,CAAA,CAAA,EAAI,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA,EAAI,CAAA,UAAA,EAAa,OAAO,CAAA,CAAE,CAAA,EAAG;AACnF,QAAA,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA,EAAG,MAAA,CAAO,OAAA,EAAO;AACjC,QAAA,QAAA,CAAS,OAAO,GAAG,CAAA;AACrB,MAAA;AACF,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,KAAA,MAAW,IAAA,IAAQ,SAAS,MAAA,EAAM;AAAI,QAAA,IAAA,CAAK,OAAO,OAAA,EAAO;AACzD,MAAA,QAAA,CAAS,KAAA,EAAK;AACd,MAAA,KAAA,MAAW,IAAA,IAAQ,SAAS,MAAA,EAAM;AAAI,QAAA,IAAA,CAAK,OAAA,EAAO;AAClD,MAAA,QAAA,CAAS,KAAA,EAAK;AACd,MAAA,WAAA,CAAY,OAAA,EAAO;AACrB,IAAA;;AAEJ;AAGO,IAAM,aAAA,GAAgB;;;ACretB,IAAM,gBAAA,GAAmB;AACzB,IAAM,gBAAA,GAAmB;AAEzB,IAAM,sBAAA,GAAyB;AAoBhC,SAAU,WAAA,CACd,WAAA,EACA,YAAA,EACA,MAAA,EAA4B;AAE5B,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,OAAO,IAAI,CAAA;AACzC,EAAA,IAAI,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,WAAA,GAAc,KAAK,CAAC,CAAA;AACvD,EAAA,IAAI,MAAA,GAAS,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,YAAA,GAAe,KAAK,CAAC,CAAA;AAEzD,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,CAAI,gBAAA,EAAkB,KAAK,KAAA,CAAM,MAAA,CAAO,YAAY,CAAC,CAAA;AACtE,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,MAAM,CAAA;AACtC,EAAA,IAAI,UAAU,GAAA,EAAK;AACjB,IAAA,MAAM,SAAS,GAAA,GAAM,OAAA;AACrB,IAAA,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,KAAA,GAAQ,MAAM,CAAC,CAAA;AAC9C,IAAA,MAAA,GAAS,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,MAAA,GAAS,MAAM,CAAC,CAAA;AAClD,EAAA;AAEA,EAAA,MAAM,MAAA,GAA8C,CAAC,EAAE,KAAA,EAAO,QAAQ,CAAA;AACtE,EAAA,OAAO,MAAA,CAAO,SAAS,gBAAA,EAAkB;AACvC,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AACzC,IAAA,MAAM,IAAA,GAAO;AACX,MAAA,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAA,CAAS,SAAS,CAAC,CAAA;AACtC,MAAA,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAA,CAAS,UAAU,CAAC;;AAE1C,IAAA,IAAI,KAAK,GAAA,CAAI,IAAA,CAAK,KAAA,EAAO,IAAA,CAAK,MAAM,CAAA,GAAI,gBAAA;AAAkB,MAAA;AAC1D,IAAA,IAAI,KAAK,KAAA,KAAU,QAAA,CAAS,KAAA,IAAS,IAAA,CAAK,WAAW,QAAA,CAAS,MAAA;AAAQ,MAAA;AACtE,IAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAClB,EAAA;AAIA,EAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,EAAA,IAAI,eAAe,MAAA,CAAO,iBAAA;AAC1B,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,MAAA,EAAQ,KAAK,CAAA,EAAG;AACzC,IAAA,MAAM,KAAA,GAAQ,OAAO,CAAC,CAAA;AACtB,IAAA,MAAM,UAAU,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,KAAA,EAAO,MAAM,MAAM,CAAA;AAClD,IAAA,MAAM,WAAW,IAAA,CAAK,GAAA,CAAI,KAAK,IAAA,CAAK,OAAA,GAAU,sBAAsB,CAAC,CAAA;AACrE,IAAA,IAAI,WAAW,YAAA,EAAc;AAC3B,MAAA,YAAA,GAAe,QAAA;AACf,MAAA,aAAA,GAAgB,CAAA;AAClB,IAAA;AACF,EAAA;AAEA,EAAA,OAAO;AACL,IAAA,KAAA;AACA,IAAA,MAAA;AACA,IAAA,UAAA,EAAY,MAAA,CAAO,MAAA;AACnB,IAAA,MAAA,EAAQ,OAAO,MAAA,GAAS,CAAA;AACxB,IAAA,aAAA;AACA,IAAA;;AAEJ;AAWO,IAAM,sBAAA,GAAyB;AAEhC,SAAU,YAAA,CACd,SACA,IAAA,EAAiB;AAEjB,EAAA,IAAI,OAAA,IAAW,CAAA;AAAG,IAAA,OAAO,EAAE,KAAA,EAAO,CAAA,EAAG,mBAAA,EAAqB,CAAA,EAAC;AAG3D,EAAA,MAAM,OAAA,GAAU,CAACC,MAAAA,KACfA,MAAAA,KAAU,CAAA,GAAI,CAAA,GAAI,sBAAA,GAAyB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAGA,MAAAA,GAAQ,CAAC,CAAA;AAElE,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,UAAA,EAAY,KAAK,CAAA,EAAG;AAC3C,IAAA,IAAI,OAAA,CAAQ,CAAC,CAAA,GAAI,OAAA;AAAS,MAAA;AAC1B,IAAA,KAAA,GAAQ,CAAA;AACV,EAAA;AAGA,EAAA,MAAM,OAAA,GAAU,QAAQ,KAAK,CAAA;AAC7B,EAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,UAAU,OAAA,GAAU,OAAA,GAAU,OAAA,EAAS,CAAC,CAAC,CAAA;AACnF,EAAA,OAAO,EAAE,OAAO,mBAAA,EAAqB,cAAA,GAAiB,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAA,EAAC;AAC1E;;;AC1FM,SAAU,mBAAA,GAAmB;AACjC,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAG;AACxB,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,IAAA,GAAO,CAAA;AAEX,EAAA,OAAO;AACL,IAAA,UAAA,CAAW,IAAA,EAAI;AASb,MAAA,IAAI,OAAA,KAAY,IAAA;AAAM,QAAA;AACtB,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,QAAA,CAAS,KAAA,EAAK;AAChB,IAAA,CAAA;AAEA,IAAA,IAAI,OAAA,GAAO;AACT,MAAA,OAAO,OAAA;AACT,IAAA,CAAA;AAEA,IAAA,KAAA,CAAM,QAAA,EAAQ;AACZ,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA,IAAK,CAAA;AAC1C,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,OAAA,IAAW,CAAA;AACX,QAAA,OAAO,KAAA;AACT,MAAA;AACA,MAAA,MAAM,QAAQ,OAAA,GAAU,CAAA;AACxB,MAAA,QAAA,CAAS,GAAA,CAAI,UAAU,KAAK,CAAA;AAC5B,MAAA,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,KAAK,CAAA;AAC3B,MAAA,QAAA,IAAY,CAAA;AACZ,MAAA,OAAO,IAAA;AACT,IAAA,CAAA;IAEA,WAAA,GAAW;AACT,MAAA,KAAA,IAAS,CAAA;AACX,IAAA,CAAA;AAEA,IAAA,YAAA,CAAa,QAAA,EAAQ;AACnB,MAAA,OAAO,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA,IAAK,CAAA;AACnC,IAAA,CAAA;AAEA,IAAA,IAAI,QAAA,GAAQ;AACV,MAAA,OAAO,QAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,iBAAA,GAAiB;AACnB,MAAA,OAAO,OAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,YAAA,GAAY;AACd,MAAA,OAAO,KAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,qBAAA,GAAqB;AACvB,MAAA,OAAO,IAAA;AACT,IAAA;;AAEJ;;;AC/DA,IAAM,UAAA,GAAa,MACjB,eAAA,CAAgB,iBAAA,GAAoB,eAAA,CAAgB,eAAA;AAoGhD,SAAU,mBAAmB,OAAA,EAAmB;AACpD,EAAA,MAAM,EAAE,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAK,GAAK,OAAA;AAEhC,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAG;AACzB,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAG;AACxB,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAG;AACzB,EAAA,MAAM,iBAAqC,EAAA;AAC3C,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAAG;AAE5B,EAAA,MAAM,cAAwB,EAAA;AAE9B,EAAA,IAAI,QAAA;AACJ,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAqE;AACxF,IAAA,MAAM,IAAA,GAAO,QAAA,EAAU,UAAA,CAAW,KAAK,CAAA;AACvC,IAAA,OAAO,SAAS,MAAA,GAAY,EAAA,GAAK,EAAE,iBAAiB,IAAA,EAAI;AAC1D,EAAA,CAAA;AACA,EAAA,MAAM,YAAA,GAAe,CAAC,KAAA,KAAsE;AAC1F,IAAA,MAAM,IAAA,GAAO,QAAA,EAAU,WAAA,CAAY,KAAK,CAAA;AACxC,IAAA,OAAO,SAAS,MAAA,GAAY,EAAA,GAAK,EAAE,iBAAiB,IAAA,EAAI;AAC1D,EAAA,CAAA;AAEA,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,EAAA,MAAM,SAAwB,mBAAA,EAAmB;AAEjD,EAAA,MAAM,WAAA,GAAc,CAAC,GAAA,EAAa,MAAA,KAA+B;AAC/D,IAAA,IAAI,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA;AAC3B,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,IAAA,GAAO,iBAAA,CAAkB,MAAA,EAAQ,MAAA,EAAQ,CAAA,eAAA,EAAkB,GAAG,CAAA,CAAE,CAAA;AAChE,MAAA,QAAA,CAAS,GAAA,CAAI,KAAK,IAAI,CAAA;AACxB,IAAA;AACA,IAAA,OAAO,IAAA;AACT,EAAA,CAAA;AAEA,EAAA,MAAM,cAAA,GAAiB,CAAC,IAAA,KACtB,KAAA,CAAM,cAAA,CAAe,YAAY,MAAA,CAAO,IAAA,EAAM,sBAAsB,CAAA,EAAG,OAAO;AAC5E,IAAA,KAAA,EAAO,0BAA0B,IAAI,CAAA,CAAA;IACrC,MAAA,EAAQ,MAAA;IACR,MAAA,EAAQ;MACN,MAAA,EAAQ,KAAA,CAAM,OAAO,CAAA,cAAA,EAAiB,IAAI,IAAI,MAAM,YAAA,CAAa,IAAI,CAAC,CAAA;MACtE,UAAA,EAAY;;IAEd,QAAA,EAAU;MACR,MAAA,EAAQ,KAAA,CAAM,OAAO,CAAA,cAAA,EAAiB,IAAI,IAAI,MAAM,YAAA,CAAa,IAAI,CAAC,CAAA;MACtE,UAAA,EAAY,WAAA;AACZ,MAAA,OAAA,EAAS,CAAC,EAAE,MAAA,EAAQ,sBAAA,EAAwB;;IAE9C,SAAA,EAAW,EAAE,UAAU,eAAA;AACvB,GAAA,CAAA,CAAA;AAEJ,EAAA,MAAM,aAAA,GAAgB,CAAC,KAAA,KACrB,KAAA,CAAM,cAAA,CAAe,YAAY,KAAA,CAAM,KAAA,EAAO,sBAAsB,CAAA,EAAG,OAAO;AAC5E,IAAA,KAAA,EAAO,yBAAyB,KAAK,CAAA,CAAA;IACrC,MAAA,EAAQ,MAAA;IACR,MAAA,EAAQ;MACN,MAAA,EAAQ,KAAA,CAAM,MAAA,CAAO,cAAA,EAAgB,WAAW,CAAA;MAChD,UAAA,EAAY;;IAEd,QAAA,EAAU;MACR,MAAA,EAAQ,KAAA,CAAM,MAAA,CAAO,cAAA,EAAgB,WAAW,CAAA;MAChD,UAAA,EAAY,KAAA;AACZ,MAAA,OAAA,EAAS,CAAC,EAAE,MAAA,EAAQ,sBAAA,EAAwB;;IAE9C,SAAA,EAAW,EAAE,UAAU,eAAA;AACvB,GAAA,CAAA,CAAA;AAEJ,EAAA,MAAM,mBAAmB,MACvB,KAAA,CAAM,gBAAgB,WAAA,CAAY,QAAA,IAAY,OAAO;IACnD,KAAA,EAAO,0BAAA;IACP,MAAA,EAAQ,MAAA;IACR,OAAA,EAAS;MACP,MAAA,EAAQ,KAAA,CAAM,MAAA,CAAO,iBAAA,EAAmB,cAAc,CAAA;MACtD,UAAA,EAAY;;AAEd,GAAA,CAAA,CAAA;AAcJ,EAAA,MAAM,aAAA,GAAgB,CAAC,QAAA,KAAkD;AACvE,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AACrC,IAAA,IAAI,MAAA,KAAW,MAAA;AAAW,MAAA,OAAO,MAAA;AACjC,IAAA,IAAI,KAAK,IAAA,CAAK,OAAA,CAAQ,cAAc,QAAQ,CAAC,MAAM,MAAA,CAAO,KAAA;AAAO,MAAA,OAAO,MAAA;AACxE,IAAA,IAAI,KAAK,IAAA,CAAK,OAAA,CAAQ,aAAa,QAAQ,CAAC,MAAM,MAAA,CAAO,IAAA;AAAM,MAAA,OAAO,MAAA;AACtE,IAAA,OAAO,MAAA;AACT,EAAA,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,OAAA,EAAqB,KAAA,KACpC,OAAA,CAAQ,UAAA,CAAW,EAAE,YAAA,EAAc,KAAA,EAAO,aAAA,EAAe,CAAA,EAAG,SAAA,EAAW,MAAM,CAAA;AAE/E,EAAA,SAAS,QAAA,CACP,QAAA,EACA,IAAA,EACA,SAAA,EACA,WACA,UAAA,EAAkB;AAElB,IAAA,MAAM,QAAA,GAAW,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AACvC,IAAA,MAAM,SAAA,GAAA,CAAa,KAAK,MAAA,CAAO,SAAS,KAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAwC,KAAA;AAClG,IAAA,MAAM,UAAA,GAAA,CAAc,KAAK,MAAA,CAAO,SAAS,KAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,EAAwC,MAAA;AAEnG,IAAA,MAAM,QAAQ,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,aAAA,CAAc,QAAQ,CAAA,EAAG;AAC1D,MAAA,KAAA,EAAO,IAAA,CAAK,KAAA;AACZ,MAAA,MAAA,EAAQ,IAAA,CAAK,MAAA;MACb,MAAA,EAAQ,sBAAA;AACR,MAAA,KAAA,EAAO,UAAA,EAAU;AACjB,MAAA,aAAA,EAAe,IAAA,CAAK,UAAA;AACpB,MAAA,KAAA,EAAO,kBAAkB,QAAQ,CAAA,MAAA;AAClC,KAAA,CAAA;AACD,IAAA,MAAM,OAAO,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,YAAA,CAAa,QAAQ,CAAA,EAAG;MACxD,KAAA,EAAO,SAAA;MACP,MAAA,EAAQ,UAAA;MACR,MAAA,EAAQ,sBAAA;AACR,MAAA,KAAA,EAAO,UAAA,EAAU;AACjB,MAAA,KAAA,EAAO,kBAAkB,QAAQ,CAAA,KAAA;AAClC,KAAA,CAAA;AAED,IAAA,IAAI,QAAQ,QAAA,EAAU,KAAA;AACtB,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,KAAA,GAAQ,OAAO,YAAA,CAAa;AAC1B,QAAA,KAAA,EAAO,kBAAkB,QAAQ,CAAA,MAAA,CAAA;AACjC,QAAA,IAAA,EAAM,qBAAA,GAAwB,CAAA;QAC9B,KAAA,EAAO,cAAA,CAAe,UAAU,cAAA,CAAe;AAChD,OAAA,CAAA;AACH,IAAA;AAEA,IAAA,IAAI,aAAa,MAAA,IAAa,QAAA,CAAS,UAAU,KAAA,IAAS,QAAA,CAAS,SAAS,IAAA,EAAM;AAChF,MAAA,aAAA,IAAiB,CAAA;AACnB,IAAA;AAEA,IAAA,MAAM,IAAA,GAAyB;AAC7B,MAAA,QAAA;AACA,MAAA,IAAA;AACA,MAAA,KAAA;AACA,MAAA,IAAA;AACA,MAAA,KAAA;AACA,MAAA,SAAA;AACA,MAAA;;AAEF,IAAA,SAAA,CAAU,GAAA,CAAI,UAAU,IAAI,CAAA;AAC5B,IAAA,OAAO,IAAA;AACT,EAAA;AAEA,EAAA,SAAS,SAAA,CACP,OAAA,EACA,QAAA,EACA,KAAA,EACA,KAAA,EAAiB;AAEjB,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,IAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,eAAe,IAAI,CAAA;AACpC,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,CAAA,OAAA,EAAU,QAAQ,IAAI,EAAE,CAAA;AACjD,IAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,KAAA,CAAM,UAAU,CAAA;AAEjD,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,KAAA,CAAM,UAAU,CAAA,GAAI,CAAA;AACnC,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,sBAAA,CAAuB,MAAM,SAAS,CAAA;AACrD,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACvB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,MAAA,CAAO,CAAC,CAAA;AACxB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAIhB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAChB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAChB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAChB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,GAAI,CAAA;AAChB,IAAA,IAAA,CAAK,KAAA,EAAK;AAEV,IAAA,MAAM,OAAA,GAA+B;AACnC,MAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAM,EAAE;AAC/C,MAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,OAAA,CAAQ,WAAA,EAAW;AAC3C,MAAA;QACE,OAAA,EAAS,CAAA;QACT,QAAA,EACE,KAAA,CAAM,QAAQ,IAAA,KAAS,UAAA,GAAa,MAAM,OAAA,CAAQ,OAAA,GAAU,MAAM,OAAA,CAAQ;;;AAIhF,IAAA,MAAM,IAAA,GAAO,QAAQ,eAAA,CAAgB;AACnC,MAAA,KAAA,EAAO,sBAAsB,QAAQ,CAAA,CAAA;MACrC,GAAG,WAAA,CAAY,WAAW,MAAM,CAAA;MAChC,gBAAA,EAAkB;AAChB,QAAA,EAAE,MAAM,OAAA,CAAQ,KAAA,EAAO,CAAC,CAAA,EAAG,MAAA,EAAQ,SAAS,OAAA,EAAS,OAAA,EAAS,YAAY,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAC;;AAErG,KAAA,CAAA;AACD,IAAA,IAAA,CAAK,YAAY,QAAQ,CAAA;AACzB,IAAA,IAAA,CAAK,YAAA,CAAa,CAAA,EAAG,MAAA,CAAO,eAAA,CAAgB,EAAE,MAAA,EAAQ,QAAA,CAAS,kBAAA,CAAmB,CAAC,CAAA,EAAG,OAAA,EAAS,CAAC,CAAA;AAChG,IAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,IAAA,IAAA,CAAK,GAAA,EAAG;AACV,EAAA;AAEA,EAAA,SAAS,QAAA,CACP,OAAA,EACA,QAAA,EACA,IAAA,EACA,KAAA,EAAiB;AAEjB,IAAA,MAAM,QAAA,GAAW,cAAc,eAAe,CAAA;AAC9C,IAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,IAAA,CAAK,UAAA,EAAY,SAAS,CAAA,EAAG;AACvD,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,KAAA,GAAQ,CAAC,CAAA;AACpC,MAAA,MAAM,OAAO,WAAA,CAAY,CAAA,MAAA,EAAS,QAAQ,CAAA,CAAA,EAAI,KAAK,IAAI,CAAC,CAAA;AACxD,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,GAAI,MAAA,CAAO,KAAA;AAC1B,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,GAAI,MAAA,CAAO,MAAA;AAC1B,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,KAAA,EAAK;AAEV,MAAA,MAAM,IAAA,GAAO,QAAQ,eAAA,CAAgB;QACnC,KAAA,EAAO,CAAA,uBAAA,EAA0B,QAAQ,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA;QAClD,GAAG,WAAA,CAAY,WAAW,KAAK,CAAA;QAC/B,gBAAA,EAAkB;AAChB,UAAA,EAAE,MAAM,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA,EAAG,MAAA,EAAQ,SAAS,OAAA,EAAS,OAAA,EAAS,YAAY,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAC;;AAEzG,OAAA,CAAA;AACD,MAAA,IAAA,CAAK,YAAY,QAAQ,CAAA;AACzB,MAAA,IAAA,CAAK,YAAA,CACH,CAAA,EACA,MAAA,CAAO,eAAA,CAAgB;QACrB,MAAA,EAAQ,QAAA,CAAS,mBAAmB,CAAC,CAAA;QACrC,OAAA,EAAS;AACP,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAM,EAAE;AAC/C,UAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,OAAA,CAAQ,WAAA,EAAW;AAC3C,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,QAAQ,KAAA,EAAO,KAAA,GAAQ,CAAC,CAAA;;OAEnD,CAAC,CAAA;AAEJ,MAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,MAAA,IAAA,CAAK,GAAA,EAAG;AACV,IAAA;AACF,EAAA;AAEA,EAAA,SAAS,YACP,OAAA,EACA,QAAA,EACA,MACA,KAAA,EACA,IAAA,EACA,OACA,mBAAA,EAA2B;AAE3B,IAAA,MAAM,QAAA,GAAW,cAAc,SAAS,CAAA;AACxC,IAAA,MAAM,OAAO,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,IAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AACjD,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,mBAAA,CAAoB,QAAQ,CAAA,EAAG;AAClE,MAAA,KAAA,EAAO,IAAA,CAAK,KAAA;AACZ,MAAA,MAAA,EAAQ,IAAA,CAAK,MAAA;MACb,MAAA,EAAQ,sBAAA;AACR,MAAA,KAAA,EAAO,UAAA,EAAU;AACjB,MAAA,KAAA,EAAO,kBAAkB,QAAQ,CAAA,aAAA;AAClC,KAAA,CAAA;AAED,IAAA,MAAM,MAAA,GAA+F;AACnG,MAAA,EAAE,MAAA,EAAQ,OAAA,EAAS,MAAA,EAAQ,OAAA,CAAQ,KAAA,EAAO,KAAK,CAAA,EAAG,GAAA,EAAK,CAAC,CAAA,EAAG,CAAC,CAAA,EAAG,KAAK,GAAA,EAAG;AACvE,MAAA,EAAE,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,OAAA,CAAQ,UAAA,EAAU,EAAI,GAAA,EAAK,CAAC,CAAA,EAAG,CAAC,CAAA,EAAG,GAAA,EAAK,GAAA;;AAGlE,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,MAAM,IAAA,GAAO,YAAY,CAAA,KAAA,EAAQ,QAAQ,IAAI,KAAA,CAAM,GAAG,IAAI,CAAC,CAAA;AAC3D,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,GAAI,IAAA,CAAK,KAAA;AACxB,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,GAAI,IAAA,CAAK,MAAA;AACxB,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,mBAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,KAAA,CAAM,IAAI,CAAC,CAAA;AAC1B,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,KAAA,CAAM,IAAI,CAAC,CAAA;AAC1B,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,MAAA,IAAA,CAAK,KAAA,EAAK;AAEV,MAAA,MAAM,IAAA,GAAO,QAAQ,eAAA,CAAgB;AACnC,QAAA,KAAA,EAAO,CAAA,sBAAA,EAAyB,KAAA,CAAM,GAAG,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA;QACrD,GAAG,WAAA,CAAY,WAAW,QAAQ,CAAA;QAClC,gBAAA,EAAkB;AAChB,UAAA,EAAE,MAAM,KAAA,CAAM,MAAA,CAAO,YAAU,EAAI,MAAA,EAAQ,SAAS,OAAA,EAAS,OAAA,EAAS,YAAY,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAC;;AAE7G,OAAA,CAAA;AACD,MAAA,IAAA,CAAK,YAAY,QAAQ,CAAA;AACzB,MAAA,IAAA,CAAK,YAAA,CACH,CAAA,EACA,MAAA,CAAO,eAAA,CAAgB;QACrB,MAAA,EAAQ,QAAA,CAAS,mBAAmB,CAAC,CAAA;QACrC,OAAA,EAAS;AACP,UAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAM,EAAE;AAC/C,UAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,OAAA,CAAQ,WAAA,EAAW;AAC3C,UAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,KAAA,CAAM,MAAA;;OAEjC,CAAC,CAAA;AAEJ,MAAA,IAAA,CAAK,KAAK,CAAC,CAAA;AACX,MAAA,IAAA,CAAK,GAAA,EAAG;AACV,IAAA;AACF,EAAA;AAEA,EAAA,SAAS,WAAA,CACP,OAAA,EACA,QAAA,EACA,IAAA,EACA,OACA,KAAA,EAAgB;AAEhB,IAAA,MAAM,WAAW,gBAAA,EAAgB;AACjC,IAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,IAAM,IAAA,CAAK,OAAO,CAAC,CAAA;AAC/D,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,CAAA,SAAA,EAAY,QAAQ,IAAI,CAAC,CAAA;AAClD,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,aAAA;AACf,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,aAAA;AACf,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,aAAA;AACpB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,IAAK,aAAA,GAAgB,CAAA,CAAA;AACpC,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,GAAI,KAAA,CAAM,KAAA;AACzB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA,GAAI,KAAA,CAAM,MAAA;AACzB,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AACf,IAAA,IAAA,CAAK,KAAA,EAAK;AAEV,IAAA,MAAM,IAAA,GAAO,QAAQ,gBAAA,CAAiB;AACpC,MAAA,KAAA,EAAO,wBAAwB,QAAQ,CAAA,CAAA;MACvC,GAAG,YAAA,CAAa,WAAW,QAAQ;AACpC,KAAA,CAAA;AACD,IAAA,IAAA,CAAK,YAAY,QAAQ,CAAA;AACzB,IAAA,IAAA,CAAK,YAAA,CACH,CAAA,EACA,MAAA,CAAO,eAAA,CAAgB;MACrB,MAAA,EAAQ,QAAA,CAAS,mBAAmB,CAAC,CAAA;MACrC,OAAA,EAAS;AACP,QAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,IAAA,CAAK,QAAM,EAAE;AAC/C,QAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,OAAA,CAAQ,WAAA,EAAW;AAC3C,QAAA,EAAE,OAAA,EAAS,CAAA,EAAG,QAAA,EAAU,KAAA,CAAM,YAAU,EAAE;AAC1C,QAAA,EAAE,SAAS,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,EAAQ,OAAK;;KAE1C,CAAC,CAAA;AAIJ,IAAA,IAAA,CAAK,mBAAmB,CAAC,CAAA;AACzB,IAAA,IAAA,CAAK,GAAA,EAAG;AACV,EAAA;AAEA,EAAA,OAAO;IACL,eAAA,EAAiB;AACf,MAAA,IAAI,QAAA,GAAQ;AACV,QAAA,OAAO,MAAA,CAAO,QAAA;AAChB,MAAA,CAAA;AACA,MAAA,IAAI,iBAAA,GAAiB;AACnB,QAAA,OAAO,MAAA,CAAO,iBAAA;AAChB,MAAA,CAAA;AACA,MAAA,IAAI,YAAA,GAAY;AACd,QAAA,OAAO,MAAA,CAAO,YAAA;AAChB,MAAA,CAAA;AACA,MAAA,IAAI,aAAA,GAAa;AACf,QAAA,OAAO,aAAA;AACT,MAAA,CAAA;AACA,MAAA,eAAA,CAAgB,QAAA,EAAQ;AACtB,QAAA,OAAO,MAAA,CAAO,aAAa,QAAQ,CAAA;AACrC,MAAA,CAAA;AACA,MAAA,IAAI,6BAAA,GAA6B;AAC/B,QAAA,OAAO,MAAA,CAAO,qBAAA;AAChB,MAAA;;;AAIF,IAAA,MAAA;AAEA,IAAA,UAAA,CAAW,IAAA,EAAI;AACb,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,MAAA,CAAO,WAAW,IAAI,CAAA;AACxB,IAAA,CAAA;AAEA,IAAA,WAAA,CAAY,IAAA,EAAI;AACd,MAAA,QAAA,GAAW,IAAA;AACb,IAAA,CAAA;IAEA,KAAA,CAAM,OAAA,EAAS,UAAU,OAAA,EAAO;AAK9B,MAAA,MAAM,QAAA,GAAW,aAAA,CAAc,OAAA,CAAQ,QAAQ,CAAA;AAC/C,MAAA,IACE,QAAA,KAAa,UACb,QAAA,CAAS,UAAA,IAAc,QAAQ,KAAA,IAC/B,CAAC,QAAA,CAAS,OAAA,EAAO,EACjB;AACA,QAAA,MAAA,CAAO,WAAA,EAAW;AAClB,QAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,SAAA,EAAW,QAAA,EAAQ;AAC/C,MAAA;AAIA,MAAA,IAAI,CAAC,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACnC,QAAA,OAAO,EAAE,QAAQ,WAAA,EAAW;AAC9B,MAAA;AAEA,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQ,SAAS,OAAA,CAAQ,EAAE,IAAI,OAAA,EAAS,MAAA,EAAQ,GAAG,CAAA;AACrD,MAAA,CAAA,CAAA,OAAS,KAAA,EAAO;AACd,QAAA,OAAO;UACL,MAAA,EAAQ,aAAA;AACR,UAAA,MAAA,EAAQ,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK;;AAEjE,MAAA;AACA,MAAA,cAAA,CAAe,KAAK,QAAQ,CAAA;AAE5B,MAAA,MAAM,OAAO,WAAA,CAAY,KAAA,CAAM,OAAO,KAAA,CAAM,MAAA,EAAQ,QAAQ,UAAU,CAAA;AAItE,MAAA,MAAM,CAAC,SAAA,EAAW,SAAS,CAAA,GAAI,OAAA,CAAQ,WAAA;AACvC,MAAA,MAAM,KAAA,GACJ,SAAA,GAAY,CAAA,IAAK,SAAA,GAAY,CAAA,GACzB,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,KAAA,GAAQ,SAAA,EAAW,KAAA,CAAM,MAAA,GAAS,SAAS,CAAA,GAC1D,CAAA;AACN,MAAA,MAAM,YAAY,KAAA,CAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,KAAA,GAAQ,MAAM,KAAA,GAAQ,CAAA;AAC/D,MAAA,MAAM,WAAW,YAAA,CAAa,OAAA,CAAQ,YAAA,GAAe,KAAA,GAAQ,WAAW,IAAI,CAAA;AAC5E,MAAA,MAAM,MAAA,GAAS,QAAA,CACb,OAAA,CAAQ,QAAA,EACR,IAAA,EACA,SAAS,KAAA,EACT,KAAA,CAAM,SAAA,EACN,OAAA,CAAQ,KAAK,CAAA;AAGf,MAAA,SAAA,CAAU,OAAA,EAAS,OAAA,CAAQ,QAAA,EAAU,KAAA,EAAO,OAAO,KAAK,CAAA;AACxD,MAAA,QAAA,CAAS,OAAA,EAAS,OAAA,CAAQ,QAAA,EAAU,IAAA,EAAM,OAAO,KAAK,CAAA;AACtD,MAAA,WAAA,CACE,OAAA,EACA,OAAA,CAAQ,QAAA,EACR,IAAA,EACA,MAAA,CAAO,KAAA,EACP,MAAA,CAAO,IAAA,EACP,QAAA,CAAS,KAAA,EACT,QAAA,CAAS,mBAAmB,CAAA;AAE9B,MAAA,WAAA,CAAY,SAAS,OAAA,CAAQ,QAAA,EAAU,MAAM,MAAA,CAAO,KAAA,EAAO,OAAO,KAAK,CAAA;AAEvE,MAAA,QAAA,CAAS,YAAA,EAAY;AACrB,MAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,SAAA,EAAW,MAAA,EAAM;AAC7C,IAAA,CAAA;IAEA,eAAA,GAAe;AAGb,MAAA,OAAO,cAAA,CAAe,SAAS,CAAA,EAAG;AAChC,QAAA,MAAM,QAAA,GAAW,eAAe,KAAA,EAAK;AACrC,QAAA,IAAI;AACF,UAAA,QAAA,EAAU,OAAA,EAAO;QACnB,CAAA,CAAA,MAAQ;AAER,QAAA;AACF,MAAA;AACF,IAAA,CAAA;IAEA,WAAA,GAAW;AAET,MAAA,OAAO,WAAA,CAAY,SAAS,CAAA,EAAG;AAC7B,QAAA,MAAM,QAAA,GAAW,YAAY,KAAA,EAAK;AAClC,QAAA,IAAI,QAAA,KAAa,MAAA;AAAW,UAAA;AAC5B,QAAA,MAAM,IAAA,GAAO,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AACnC,QAAA,IAAI,IAAA,KAAS,MAAA;AAAW,UAAA;AACxB,QAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,QAAA,YAAA,CAAa,GAAA,CACX,WACC,YAAW;AACV,UAAA,IAAI;AACF,YAAA,MAAM,OAAA,CAAQ,QAAA,CAAS,UAAA,CAAW,IAAI,CAAA;AACtC,YAAA,MAAM,MAAA,GAAS,IAAI,YAAA,CAAa,OAAA,CAAQ,gBAAc,CAAG,KAAA,CAAM,CAAC,CAAC,CAAA;AACjE,YAAA,OAAA,CAAQ,KAAA,EAAK;AACb,YAAA,OAAO,gBAAgB,MAAM,CAAA;UAC/B,CAAA,CAAA,MAAQ;AACN,YAAA,OAAO,MAAA;AACT,UAAA,CAAA,SAAA;AACE,YAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AAClB,UAAA;AACF,QAAA,CAAA,GAAI,CAAA;AAER,MAAA;AACF,IAAA,CAAA;AAEA,IAAA,SAAA,CAAU,QAAA,EAAQ;AAChB,MAAA,OAAO,cAAc,QAAQ,CAAA;AAC/B,IAAA,CAAA;AAEA,IAAA,YAAA,CAAa,UAAU,OAAA,EAAO;AAC5B,MAAA,MAAM,MAAA,GAAS,cAAc,QAAQ,CAAA;AACrC,MAAA,IAAI,MAAA,KAAW,MAAA;AAAW,QAAA,OAAO,KAAA;AAEjC,MAAA,IAAI,QAAA,GAAW,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AACrC,MAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,QAAA,QAAA,GAAW;AACT,UAAA,OAAA,EAAS,OAAO,YAAA,CAAa;AAC3B,YAAA,KAAA,EAAO,kBAAkB,QAAQ,CAAA,cAAA,CAAA;AACjC,YAAA,IAAA,EAAM,qBAAA,GAAwB,CAAA;YAC9B,KAAA,EAAO,cAAA,CAAe,WAAW,cAAA,CAAe;AACjD,WAAA,CAAA;UACD,QAAA,EAAU;;AAEZ,QAAA,SAAA,CAAU,GAAA,CAAI,UAAU,QAAQ,CAAA;AAClC,MAAA;AAKA,MAAA,IAAI,QAAA,CAAS,QAAA;AAAU,QAAA,OAAO,KAAA;AAE9B,MAAA,OAAA,CAAQ,kBAAA,CAAmB,OAAO,KAAA,EAAO,CAAA,EAAG,SAAS,OAAA,EAAS,CAAA,EAAG,wBAAwB,CAAC,CAAA;AAC1F,MAAA,QAAA,CAAS,QAAA,GAAW,IAAA;AAMpB,MAAA,WAAA,CAAY,KAAK,QAAQ,CAAA;AACzB,MAAA,OAAO,IAAA;AACT,IAAA,CAAA;AAEA,IAAA,MAAM,YAAA,GAAY;AAChB,MAAA,MAAM,GAAA,uBAAU,GAAA,EAAG;AACnB,MAAA,MAAM,OAAA,GAAU,CAAC,GAAG,YAAY,CAAA;AAChC,MAAA,YAAA,CAAa,KAAA,EAAK;AAClB,MAAA,KAAA,MAAW,CAAC,QAAA,EAAU,OAAO,CAAA,IAAK,OAAA,EAAS;AACzC,QAAA,MAAM,QAAQ,MAAM,OAAA;AACpB,QAAA,IAAI,KAAA,KAAU,MAAA;AAAW,UAAA,GAAA,CAAI,GAAA,CAAI,UAAU,KAAK,CAAA;AAClD,MAAA;AACA,MAAA,OAAO,GAAA;AACT,IAAA,CAAA;AAEA,IAAA,MAAA,CAAO,QAAA,EAAQ;AACb,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,aAAA,CAAc,QAAQ,CAAC,CAAA;AAC5C,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,YAAA,CAAa,QAAQ,CAAC,CAAA;AAC3C,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,mBAAA,CAAoB,QAAQ,CAAC,CAAA;AAClD,MAAA,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA,EAAG,KAAA,CAAM,OAAA,EAAO;AACtC,MAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AACzB,MAAA,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA,EAAG,OAAA,CAAQ,OAAA,EAAO;AACxC,MAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AACzB,MAAA,YAAA,CAAa,OAAO,QAAQ,CAAA;AAC5B,MAAA,MAAM,MAAA,GAAS,WAAA,CAAY,OAAA,CAAQ,QAAQ,CAAA;AAC3C,MAAA,IAAI,MAAA,IAAU,CAAA;AAAG,QAAA,WAAA,CAAY,MAAA,CAAO,QAAQ,CAAC,CAAA;AAC/C,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,KAAA,MAAW,QAAA,IAAY,CAAC,GAAG,SAAA,CAAU,MAAM,CAAA;AAAG,QAAA,IAAA,CAAK,OAAO,QAAQ,CAAA;AAClE,MAAA,KAAA,MAAW,IAAA,IAAQ,SAAS,MAAA,EAAM;AAAI,QAAA,IAAA,CAAK,OAAO,OAAA,EAAO;AACzD,MAAA,QAAA,CAAS,KAAA,EAAK;AACd,MAAA,cAAA,CAAe,MAAA,GAAS,CAAA;AACxB,MAAA,WAAA,CAAY,MAAA,GAAS,CAAA;AACvB,IAAA;;AAEJ;AAGO,IAAM,iBAAA,GAAoB,EAAE,aAAA,EAAe,kBAAA,EAAoB,YAAY,CAAA;;;ACrnB3E,IAAM,cAAA,GAAiB;AACvB,IAAM,iBAAA,GAAoB;AAC1B,IAAM,aAAA,GAAgB;AACtB,IAAM,gBAAA,GAAmB;AACzB,IAAM,gBAAA,GAAmB;AAEzB,IAAM,iBAAA,GAAoB;AAC/B,EAAA,gBAAA;AACA,EAAA,gBAAA;AACA,EAAA,aAAA;AACA,EAAA,cAAA;AACA,EAAA;;AAIK,IAAM,uBAAA,GAA8C;EACzD,KAAA,EAAO,UAAA;EACP,KAAA,EAAO,SAAA;EACP,UAAA,EAAY,SAAA;EACZ,SAAA,EAAW,SAAA;EACX,MAAA,EAAQ,SAAA;EACR,WAAA,EAAa,SAAA;EACb,UAAA,EAAY;;AAyIR,SAAU,oBAAA,CAAqB,OAAA,GAAiC,EAAA,EAAE;AACtE,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAG;AACzB,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAG;AACtB,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAG;AAC1B,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAG;AAE9B,EAAA,IAAI,aAAA,GAAoC,uBAAA;AACxC,EAAA,IAAI,WAA4B,qBAAA,CAC9B,wBAAA,EACA,OAAA,CAAQ,eAAA,IAAmB,EAAE,CAAA;AAE/B,EAAA,IAAI,QAAA,GAA0B,QAAQ,QAAA,IAAY;IAChD,QAAA,EAAU,CAAA;IACV,SAAA,EAAW,CAAA;IACX,gBAAA,EAAkB;;AAEpB,EAAA,IAAI,OAAA;AAOJ,EAAA,IAAI,eAAA;AACJ,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,eAAA;AACJ,EAAA,IAAI,OAAA;AAGJ,EAAA,IAAI,cAAA;AACJ,EAAA,IAAI,eAAA,GAAkB,CAAA;AACtB,EAAA,IAAI,iBAA2B,EAAA;AAC/B,EAAA,IAAI,cAAA;AAUJ,EAAA,MAAM,aAAA,GAAgB,CAAC,OAAA,EAAiB,GAAA,KAAgC;AACtE,IAAA,IAAI,mBAAmB,OAAA,EAAS;AAC9B,MAAA,cAAA,GAAiB,OAAA;AACjB,MAAA,cAAA,GAAiB,EAAA;AACnB,IAAA;AACA,IAAA,KAAA,MAAW,EAAA,IAAM,GAAA;AAAK,MAAA,IAAI,CAAC,cAAA,CAAe,QAAA,CAAS,EAAE,CAAA;AAAG,QAAA,cAAA,CAAe,KAAK,EAAE,CAAA;AAChF,EAAA,CAAA;AAEA,EAAA,MAAM,WAAW,cAAA,CAAe;IAC9B,GAAI,OAAA,CAAQ,oBAAoB,MAAA,GAAY,KAAK,EAAE,eAAA,EAAiB,QAAQ,eAAA;AAC7E,GAAA,CAAA;AAED,EAAA,MAAM,cAAc,MAAW;AAC7B,IAAA,KAAA,EAAO,OAAA,EAAO;AACd,IAAA,MAAA,EAAQ,OAAA,EAAO;AACf,IAAA,OAAA,EAAS,OAAA,EAAO;AAChB,IAAA,KAAA,GAAQ,MAAA;AACR,IAAA,MAAA,GAAS,MAAA;AACT,IAAA,OAAA,GAAU,MAAA;AACV,IAAA,cAAA,GAAiB,MAAA;AACnB,EAAA,CAAA;AAEA,EAAA,MAAM,OAAmB,gBAAA,CAAiB;IACxC,GAAI,OAAA,CAAQ,cAAc,MAAA,GAAY,KAAK,EAAE,SAAA,EAAW,QAAQ,SAAA,EAAS;IACzE,GAAI,OAAA,CAAQ,wBAAwB,MAAA,GAChC,KACA,EAAE,mBAAA,EAAqB,QAAQ,mBAAA,EAAmB;AACtD,IAAA,cAAA,EAAgB,CAAC,MAAA,KAAU;AACzB,MAAA,IAAI,OAAO,UAAA,KAAe,WAAA;AAAa,QAAA,WAAA,GAAc,MAAA,CAAO,UAAA;AAC5D,MAAA,OAAA,CAAQ,uBAAuB,MAAM,CAAA;AACvC,IAAA;AACD,GAAA,CAAA;AAKD,EAAA,IAAA,CAAK,gBAAgB,MAAK;AACxB,IAAA,WAAA,EAAW;AACX,IAAA,UAAA,CAAW,KAAA,EAAK;AAChB,IAAA,cAAA,CAAe,KAAA,EAAK;EACtB,CAAC,CAAA;AAED,EAAA,MAAM,gBAAgB,MAAuE;AAC3F,IAAA,MAAM,MAAA,GAAS,KAAK,aAAA,EAAa;AACjC,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,UAAA;AAC/B,IAAA,IAAI,OAAA,KAAY,MAAA,IAAa,OAAA,CAAQ,UAAA,KAAe,UAAA,EAAY;AAC9D,MAAA,MAAM,UAAA,GAAa,eAAA;AACnB,MAAA,WAAA,EAAW;AACX,MAAA,OAAA,GAAU,gBAAA,CAAiB,QAAQ,UAAU,CAAA;AAC7C,MAAA,eAAA,GAAkB,UAAA;AAClB,MAAA,KAAA,GAAQ,mBAAmB,OAAO,CAAA;AAClC,MAAA,MAAA,GAAS,iBAAiB,OAAO,CAAA;AAUjC,MAAA,IAAI,UAAA,KAAe,MAAA,IAAa,UAAA,KAAe,UAAA,EAAY;AACzD,QAAA,KAAA,MAAW,QAAA,IAAY,SAAA,CAAU,MAAA,EAAM,EAAI;AACzC,UAAA,IAAI,SAAS,UAAA,KAAe,UAAA;AAAY,YAAA,QAAA,CAAS,UAAA,CAAW,YAAY,MAAM,CAAA;AAChF,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA,OAAO;AACL,MAAA,OAAA;AACA,MAAA,KAAA;AACA,MAAA;;AAEJ,EAAA,CAAA;AAEA,EAAA,MAAM,aAAA,GAAgB,CAAC,QAAA,KAAqC;AAC1D,IAAA,IAAI,KAAA,GAAQ,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AACnC,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,KAAA,GAAQ,qBAAA,CAAsB,QAAW,QAAQ,CAAA;AACjD,MAAA,UAAA,CAAW,GAAA,CAAI,UAAU,KAAK,CAAA;AAChC,IAAA;AACA,IAAA,OAAO,KAAA;AACT,EAAA,CAAA;AAOA,EAAA,MAAM,QAAA,GAAW,CACf,WAAA,EACA,YAAA,KAC6C;AAC7C,IAAA,MAAM,iBACJ,QAAA,CAAS,SAAA,GAAY,IAAI,QAAA,CAAS,QAAA,GAAW,SAAS,SAAA,GAAY,CAAA;AACpE,IAAA,MAAM,YAAA,GAAe,YAAA,GAAe,CAAA,GAAI,WAAA,GAAc,YAAA,GAAe,CAAA;AACrE,IAAA,IAAI,eAAe,cAAA,EAAgB;AACjC,MAAA,MAAM,SAAS,cAAA,GAAiB,YAAA;AAChC,MAAA,OAAO,CAAC,MAAA,EAAQ,CAAA,EAAA,CAAI,CAAA,GAAI,MAAA,IAAU,GAAG,CAAC,CAAA;AACxC,IAAA;AACA,IAAA,MAAM,SAAS,YAAA,GAAe,cAAA;AAC9B,IAAA,OAAO,CAAC,CAAA,EAAG,MAAA,EAAQ,CAAA,EAAA,CAAI,CAAA,GAAI,UAAU,CAAC,CAAA;AACxC,EAAA,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KACf,KAAA,CAAM,KAAA,IAAS,mBAAA;AAEjB,EAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAA6C,KAAA,CAAM,OAAA,IAAW,SAAA;AAEjF,EAAA,MAAM,OAAA,GAAU,CACd,KAAA,EACA,UAAA,KAC0E;AAC1E,IAAA,MAAM,QAAA,GAAW,YAAY,MAAA,CAAO,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,CAAM,OAAA,KAAY,KAAA,CAAM,OAAO,CAAA;AACnF,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,OAAO,EAAE,UAAA,EAAY,KAAA,CAAM,UAAA,EAAY,aAAA,EAAe,MAAM,aAAA,EAAa;AAC3E,IAAA;AACA,IAAA,OAAO;AACL,MAAA,UAAA,EAAY,SAAS,KAAA,CAAM,UAAA;MAC3B,aAAA,EAAe,QAAA,CAAS,MAAM,QAAA,KAAa;;AAE/C,EAAA,CAAA;AAEA,EAAA,SAAS,gBAAgB,QAAA,EAAmD;AAC1E,IAAA,IAAI,QAAA,KAAa,MAAA;AAAW,MAAA,OAAO,QAAA;AAEnC,IAAA,MAAM,OAAA,uBAAc,GAAA,EAAG;AACvB,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,EAAM,EAAI;AACnC,MAAA,MAAM,EAAA,GAAK,MAAM,KAAA,CAAM,gBAAA;AACvB,MAAA,IAAI,EAAA,KAAO,MAAA;AAAW,QAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AACtC,IAAA;AACA,IAAA,MAAM,WAAiC,EAAA;AACvC,IAAA,KAAA,MAAW,YAAY,OAAA,EAAS;AAC9B,MAAA,MAAM,QAAA,GAAW,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AACvC,MAAA,IAAI,QAAA,KAAa,MAAA,IAAa,CAAC,QAAA,CAAS,OAAA,EAAO;AAAI,QAAA;AACnD,MAAA,QAAA,CAAS,IAAA,CAAK;AACZ,QAAA,QAAA;;;;AAIA,QAAA,KAAA,EAAO,WAAA,GAAc,CAAA;AACrB,QAAA,UAAA,EAAY,EAAE,KAAA,EAAO,CAAA,EAAG,YAAA,EAAc,IAAA,EAAI;AAC1C,QAAA,QAAA,EAAU,CAAC,GAAG,MAAA,CAAO,QAAQ,CAAA,CAC1B,OAAO,CAAC,KAAA,KAAU,MAAM,KAAA,CAAM,gBAAA,KAAqB,QAAQ,CAAA,CAC3D,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,MAAM,OAAO;AACtC,OAAA,CAAA;AACH,IAAA;AACA,IAAA,OAAO,QAAA;AACT,EAAA;AAEA,EAAA,SAAS,WAAA,CACP,OAAA,EACA,QAAA,EACA,WAAA,EAAmB;AAEnB,IAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAQ,GAAK,aAAA,EAAa;AACzC,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,MAAM,UAAoB,EAAA;AAE1B,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,MAAM,QAAA,GAAW,SAAA,CAAU,GAAA,CAAI,OAAA,CAAQ,QAAQ,CAAA;AAC/C,MAAA,IAAI,aAAa,MAAA,EAAW;AAI1B,QAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,QAAQ,CAAA;AAC7B,QAAA;AACF,MAAA;AAEA,MAAA,MAAM,OAAA,GAAU,SAAA,CACd,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,IAAA,CACnB,CAAC,KAAA,KAAU,KAAA,CAAM,KAAA,CAAM,gBAAA,KAAqB,OAAA,CAAQ,QAAQ,CAAA,EAC3D,KAAA,IAAS,EAAqE,CAAE,CAAA;AAErF,MAAA,MAAM,SAAS,iBAAA,CAAkB,QAAA,CAAS,OAAO,OAAO,CAAA,EAAG,eAAe,QAAQ,CAAA;AAElF,MAAA,MAAM,OAAA,GAAU,SAAS,KAAA,CACvB;AACE,QAAA,QAAA,EAAU,OAAA,CAAQ,QAAA;AAClB,QAAA,KAAA,EAAO,OAAA,CAAQ,KAAA;AACf,QAAA,UAAA,EAAY,OAAA,CAAQ,UAAA;AACpB,QAAA,YAAA,EAAc,MAAA,CAAO,SAAA;AACrB,QAAA,WAAA,EAAa,CAAC,QAAA,CAAS,QAAA,EAAU,QAAA,CAAS,SAAS;AAErD,OAAA,EAAA,QAAA,EACA,OAAO,CAAA;AAET,MAAA,IAAI,QAAQ,MAAA,KAAW,OAAA;AAAS,QAAA,KAAA,IAAS,CAAA;AAIhC,WAAA,IAAA,OAAA,CAAQ,MAAA,KAAW,aAAA;AAAe,QAAA,OAAA,CAAQ,IAAA,CAAK,QAAQ,QAAQ,CAAA;AAC1E,IAAA;AAKA,IAAA,MAAM,OAAA,GAAU,SAAS,KAAA,CAAM,mBAAA;AAC/B,IAAA,KAAA,MAAW,QAAA,IAAY,SAAA,CAAU,IAAA,EAAI,EAAI;AACvC,MAAA,IAAI,QAAA,CAAS,SAAA,CAAU,QAAQ,CAAA,KAAM,MAAA;AAAW,QAAA;AAChD,MAAA,IAAI,CAAC,WAAA,CAAY,cAAA,CAAe,IAAI,QAAQ,CAAA,EAAG,aAAa,OAAO,CAAA;AAAG,QAAA;AACtE,MAAA,IAAI,QAAA,CAAS,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAAG,QAAA,cAAA,CAAe,GAAA,CAAI,UAAU,WAAW,CAAA;AACxF,IAAA;AAEA,IAAA,OAAO,EAAE,OAAO,OAAA,EAAO;AACzB,EAAA;AAEA,EAAA,SAAS,UAAA,CACP,SACA,UAAA,EAA2C;AAE3C,IAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,MAAA,KAAW,aAAA,EAAa;AACzD,IAAA,MAAM,MAAA,GAAS,OAAA;AACf,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,MAAM,aAAA,CACJ,cACA,2FAA2F,CAAA;AAE/F,IAAA;AAEA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,kBAAkB,IAAI,CAAA;AACpD,IAAA,MAAM,eAAe,CAAA,GAAI,GAAA;AACzB,IAAA,MAAM,cAAA,GAA4C;AAChD,MAAA,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,MAAM,QAAA,CAAS,QAAA,GAAW,GAAG,CAAC,CAAA;AAC/C,MAAA,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,MAAM,QAAA,CAAS,SAAA,GAAY,GAAG,CAAC;;AAGlD,IAAA,MAAM,UAAiD,EAAA;AACvD,IAAA,IAAI,KAAA,GAAQ,CAAA;AAEZ,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,EAAM,EAAI;AACnC,MAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,MAAA,IAAI,KAAA,CAAM,SAAS,MAAA,KAAW,CAAA;AAAG,QAAA;AAEjC,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AACF,QAAA,QAAA,GAAW,eAAA,CAAgB,KAAA,EAAO,QAAA,CAAS,KAAA,CAAM,aAAa,QAAQ,CAAA;AACxE,MAAA,CAAA,CAAA,OAAS,KAAA,EAAO;AACd,QAAA,OAAA,CAAQ,IAAA,CAAK;AACX,UAAA,OAAA,EAAS,KAAA,CAAM,OAAA;AACf,UAAA,MAAA,EAAQ,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK;AAC9D,SAAA,CAAA;AACD,QAAA;AACF,MAAA;AAEA,MAAA,MAAM,KAAA,GAAQ,QAAQ,KAAK,CAAA;AA0B3B,MAAA,MAAM,UAAU,sBAAA,CAAuB,cAAA,CAAe,QAAA,EAAU,KAAK,GAAG,GAAG,CAAA;AAC3E,MAAA,MAAM,UAAA,GAAqC,qBAAA,CAAsB,OAAA,EAAS,GAAA,EAAK,cAAc,CAAA;AAC7F,MAAA,IAAI,UAAA,KAAe,MAAA;AAAW,QAAA;AAE9B,MAAA,MAAM,MAAA,GAAS,cAAc,QAAA,EAAU;AACrC,QAAA,UAAA,CAAW,CAAA,GAAI,YAAA;AACf,QAAA,UAAA,CAAW,CAAA,GAAI;AAChB,OAAA,CAAA;AACD,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS;AACvC,QAAA,OAAA,EAAS,KAAA,CAAM,OAAA;AACf,QAAA,MAAA,EAAQ,SAAS,KAAA,CAAM,WAAA;AACvB,QAAA,UAAA;AACA,QAAA,YAAA;QACA,eAAA,EAAiB,YAAA;;;AAGjB,QAAA,WAAA,EAAa,SAAS,KAAA,CAAM,yBAAA;AAC5B,QAAA,SAAA,EAAW,MAAA,CAAO,IAAA;AAClB,QAAA,aAAA,EAAe,MAAA,CAAO,KAAA;AACtB,QAAA;AACD,OAAA,CAAA;AAED,MAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,EAAO,UAAU,CAAA;AACvC,MAAA,MAAM,MAAA,GAAS,UAAA,EAAY,aAAA,CAAc,QAAA,IAAY,aAAA;AACrD,MAAA,MAAM,OAAA,GAAU,UAAU,KAAK,CAAA;AAC/B,MAAA,MAAM,SAAS,iBAAA,CAAkB,QAAA,CAAS,OAAO,OAAO,CAAA,EAAG,QAAQ,QAAQ,CAAA;AAG3E,MAAA,MAAM,aAAa,mBAAA,CACjB,0BAAA,CAA2B,MAAM,CAAA,EACjC,MAAM,UAAU,CAAA;AAElB,MAAA,MAAM,eAAA,GAAkB,QAAA,CAAS,eAAA,CAAgB,UAAU,CAAA;AAE3D,MAAA,MAAM,WAAW,KAAA,CAAM,gBAAA;AACvB,MAAA,MAAM,UAAU,QAAA,KAAa,MAAA,GAAY,MAAA,GAAY,QAAA,CAAS,UAAU,QAAQ,CAAA;AAChF,MAAA,MAAM,QACJ,QAAA,KAAa,MAAA,GAAY,MAAA,GAAY,aAAA,CAAc,QAAQ,CAAA,CAAE,MAAA;AAE/D,MAAA,MAAA,CAAO,WAAW,OAAA,EAAS;AACzB,QAAA,OAAA,EAAS,KAAA,CAAM,OAAA;AACf,QAAA,MAAA,EAAQ,MAAA,CAAO,MAAA;AACf,QAAA,YAAA,EAAc,MAAA,CAAO,MAAA;AACrB,QAAA,UAAA;AACA,QAAA,MAAA;AACA,QAAA,cAAA;AACA,QAAA,YAAA;QACA,eAAA,EAAiB,YAAA;AACjB,QAAA,GAAA,EACE,OAAA,KAAY,MAAA,GACR,CAAC,CAAA,EAAG,GAAG,CAAA,EAAG,CAAC,CAAA,GACX,QAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,OAAA,CAAQ,KAAK,MAAM,CAAA;AACtD,QAAA,eAAA;AACA,QAAA,YAAA,EAAc,QAAA,CAAS,gBAAA;AACvB,QAAA,UAAA,EAAY,QAAA,CAAS,cAAA;QACrB,WAAA,EAAa,OAAA,EAAS,KAAK,MAAA,IAAU,CAAA;AACrC,QAAA,IAAA,EAAM,MAAA,CAAO,IAAA;AACb,QAAA,SAAA,EAAW,MAAA,CAAO,SAAA;QAClB,SAAA,EAAW,KAAA,EAAO,QAAQ,MAAA,CAAO,IAAA;QACjC,aAAA,EACE,KAAA,EAAO,aAAa,IAAA,GAChB,kBAAA,CAAmB,QAAQ,KAAA,CAAM,aAAA,EAAe,QAAQ,CAAA,GACxD,CAAA;AACN,QAAA,QAAA,EAAU,MAAA,CAAO,QAAA;AACjB,QAAA,QAAA,EAAU,MAAA,CAAO,QAAA;AACjB,QAAA,aAAA,EAAe,MAAA,CAAO,aAAA;AACtB,QAAA,YAAA,EAAc,MAAA,CAAO,YAAA;AACrB,QAAA,cAAA,EAAgB,QAAA,CAAS,cAAA;AACzB,QAAA,WAAA,EAAa,MAAA,CAAO,WAAA;AACpB,QAAA,WAAA,EAAa,MAAA,CAAO,WAAA;AACpB,QAAA,QAAA,EACE,OAAA,KAAY,MAAA,IAAa,MAAA,CAAO,KAAA,KAAU,SACtC,MAAA,GACA;UACE,KAAA,EAAO,OAAA,CAAQ,MAAM,UAAA,EAAU;UAC/B,IAAA,EAAM,OAAA,CAAQ,KAAK,UAAA;;AAE5B,OAAA,CAAA;AAED,MAAA,IAAI,MAAA,CAAO,cAAc,MAAA,EAAW;AAIlC,QAAA,MAAM,OAAO,QAAA,CAAS,MAAA,CACpB,CAAC,IAAA,EAAM,YAAa,OAAA,CAAQ,QAAA,CAAS,IAAA,GAAO,IAAA,CAAK,SAAS,IAAA,GAAO,OAAA,GAAU,IAAA,EAC3E,QAAA,CAAS,CAAC,CAAoB,CAAA;AAEhC,QAAA,MAAA,CAAO,cAAc,OAAA,EAAS;AAC5B,UAAA,OAAA,EAAS,KAAA,CAAM,OAAA;AACf,UAAA,MAAA,EAAQ,MAAA,CAAO,SAAA;AACf,UAAA,YAAA,EAAc,MAAA,CAAO,MAAA;AACrB,UAAA,UAAA;AACA,UAAA,MAAA;AACA,UAAA,cAAA;AACA,UAAA,YAAA;AACA,UAAA,KAAA,EAAO,KAAK,QAAA,CAAS,KAAA;AACrB,UAAA,gBAAA,EAAkB,QAAA,CAAS,gBAAA;;AAE3B,UAAA,SAAA,EAAW,MAAA,CAAO,KAAA,KAAU,MAAA,GAAS,CAAA,GAAI,QAAA,CAAS,SAAA;AAClD,UAAA,QAAA,EAAU,MAAA,CAAO,QAAA;UACjB,aAAA,EAAe,IAAA,CAAK,QAAA,CAAS,UAAA,IAAc,IAAA,CAAK,MAAA;AAChD,UAAA,aAAA,EAAe,QAAA,CAAS,aAAA;AACxB,UAAA,QAAA,EAAU,QAAA,CAAS,QAAA;AACnB,UAAA,MAAA,EAAQ,MAAA,CAAO;AAChB,SAAA,CAAA;AACH,MAAA;AAEA,MAAA,KAAA,IAAS,CAAA;AACX,IAAA;AAEA,IAAA,OAAO,EAAE,WAAA,EAAa,KAAA,EAAO,QAAA,EAAU,eAAA,EAAiB,SAAS,OAAA,EAAS,CAAC,GAAG,cAAc,CAAA,EAAC;AAC/F,EAAA;AAEA,EAAA,OAAO;IACL,OAAA,EAAS,QAAA;AAET,IAAA,IAAI,KAAA,GAAK;AACP,MAAA,OAAO,KAAK,MAAA,CAAO,MAAA,KAAW,MAAA,IAAa,IAAA,CAAK,OAAO,YAAA,KAAiB,IAAA;AAC1E,IAAA,CAAA;IAEA,MAAA,EAAQ,iBAAA;AACR,IAAA,YAAA,EAAc,eAAA,EAAe;AAE7B,IAAA,IAAI,YAAA,GAAY;AACd,MAAA,OAAO,IAAA,CAAK,MAAA;AACd,IAAA,CAAA;AAEA,IAAA,IAAI,eAAA,GAAe;AACjB,MAAA,OAAO,IAAA,CAAK,eAAA;AACd,IAAA,CAAA;AAEA,IAAA,QAAA;AAEA,IAAA,IAAI,cAAA,GAAc;AAChB,MAAA,OAAO,cAAA;AACT,IAAA,CAAA;AAEA,IAAA,IAAI,eAAA,GAAe;AACjB,MAAA,MAAM,IAAA,GAAO,SAAS,IAAA,CAAK,KAAA;AAC3B,MAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,CAAM,KAAA;AAC7B,MAAA,OAAO;AACL,QAAA,OAAA,EACE,OAAO,eAAA,IAAmB;UACxB,QAAA,EAAU,CAAA;UACV,iBAAA,EAAmB,CAAA;UACnB,YAAA,EAAc,CAAA;UACd,aAAA,EAAe,CAAA;AACf,UAAA,eAAA,EAAiB,MAAM,CAAA;UACvB,6BAAA,EAA+B;;QAEnC,WAAA,EAAa;AACX,UAAA,IAAA,EAAM,MAAM,IAAA,IAAQ,CAAA;AACpB,UAAA,OAAA,EAAS,MAAM,OAAA,IAAW,CAAA;AAC1B,UAAA,SAAA,EAAW,MAAM,SAAA,IAAa;;QAEhC,SAAA,EAAW;AACT,UAAA,eAAA,EAAiB,OAAO,eAAA,IAAmB,CAAA;AAC3C,UAAA,gBAAA,EAAkB,OAAO,gBAAA,IAAoB;;AAE/C,QAAA,WAAA;QACA,iBAAA,EAAmB;;AAEvB,IAAA,CAAA;AAEA,IAAA,YAAA,CAAa,QAAQ,SAAA,EAAS;AAC5B,MAAA,IAAA,CAAK,MAAA,CAAO,QAAQ,SAAA,IAAa,OAAA,CAAQ,cAAc,OAAA,CAAQ,MAAA,KAAW,MAAA,GAAS,KAAA,GAAQ,QAAA,CAAS,CAAA;AACtG,IAAA,CAAA;AAEA,IAAA,aAAA,CAAc,MAAA,EAAM;AAClB,MAAA,IAAA,CAAK,cAAc,MAAM,CAAA;AAC3B,IAAA,CAAA;AAEA,IAAA,qBAAA,CAAsB,MAAA,EAAM;AAC1B,MAAA,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAC7B,IAAA,CAAA;AAEA,IAAA,gBAAA,CAAiB,QAAA,EAAQ;AACvB,MAAA,IAAI,SAAA,CAAU,GAAA,CAAI,QAAA,CAAS,EAAE,CAAA,EAAG;AAC9B,QAAA,MAAM,cACJ,iBAAA,EACA,CAAA,iBAAA,EAAoB,SAAS,EAAE,CAAA,yFAAA,CAAA,EAC/B,SAAS,EAAE,CAAA;AAEf,MAAA;AACA,MAAA,SAAA,CAAU,GAAA,CAAI,QAAA,CAAS,EAAA,EAAI,QAAQ,CAAA;AACrC,IAAA,CAAA;AAEA,IAAA,kBAAA,CAAmB,QAAA,EAAQ;AACzB,MAAA,MAAM,QAAA,GAAW,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AACvC,MAAA,IAAI,QAAA,KAAa,MAAA;AAAW,QAAA;AAC5B,MAAA,QAAA,CAAS,OAAA,EAAO;AAChB,MAAA,SAAA,CAAU,OAAO,QAAQ,CAAA;AACzB,MAAA,KAAA,EAAO,OAAO,QAAQ,CAAA;AACtB,MAAA,UAAA,CAAW,OAAO,QAAQ,CAAA;AAC1B,MAAA,cAAA,CAAe,OAAO,QAAQ,CAAA;AAChC,IAAA,CAAA;AAEA,IAAA,QAAA,CAAS,QAAA,EAAQ;AACf,MAAA,OAAO,SAAA,CAAU,IAAI,QAAQ,CAAA;AAC/B,IAAA,CAAA;AAEA,IAAA,WAAA,CAAY,IAAA,EAAI;AACd,MAAA,MAAM,OAAA,GACJ,IAAA,CAAK,QAAA,KAAa,QAAA,CAAS,QAAA,IAC3B,IAAA,CAAK,SAAA,KAAc,QAAA,CAAS,SAAA,IAC5B,IAAA,CAAK,gBAAA,KAAqB,QAAA,CAAS,gBAAA;AACrC,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,IAAI,CAAC,OAAA;AAAS,QAAA;AAYd,MAAA,OAAA,EAAS,KAAK,aAAA,EAAa;AAC7B,IAAA,CAAA;AAEA,IAAA,IAAI,QAAA,GAAQ;AACV,MAAA,OAAO,QAAA;AACT,IAAA,CAAA;AAEA,IAAA,QAAA,CAAS,KAAA,EAAK;AACZ,MAAA,MAAA,CAAO,GAAA,CAAI,KAAA,CAAM,OAAA,EAAS,EAAE,OAAO,CAAA;AACrC,IAAA,CAAA;AAEA,IAAA,WAAA,CAAY,OAAA,EAAO;AACjB,MAAA,MAAA,CAAO,OAAO,OAAO,CAAA;AACrB,MAAA,MAAA,EAAQ,OAAO,OAAO,CAAA;AACxB,IAAA,CAAA;AAEA,IAAA,gBAAA,CAAiB,MAAA,EAAM;AACrB,MAAA,aAAA,GAAgB,MAAA;AAClB,IAAA,CAAA;AAEA,IAAA,kBAAA,CAAmB,KAAA,EAAK;AACtB,MAAA,QAAA,GAAW,qBAAA,CAAsB,0BAA0B,KAAK,CAAA;AAKhE,MAAA,UAAA,CAAW,KAAA,EAAK;AAClB,IAAA,CAAA;AAEA,IAAA,IAAI,eAAA,GAAe;AACjB,MAAA,OAAO,QAAA;AACT,IAAA,CAAA;AAEA,IAAA,UAAA,CAAW,IAAA,EAAI;AACb,MAAA,OAAA,GAAU;AACR,QAAA,MAAA,EAAQ,IAAA,CAAK,MAAA;QACb,GAAI,IAAA,CAAK,cAAc,MAAA,GAAY,KAAK,EAAE,SAAA,EAAW,KAAK,SAAA,EAAS;AACnE,QAAA,MAAA,EAAQ,KAAK,MAAA,IAAU;;AAE3B,IAAA,CAAA;AAEA,IAAA,SAAA,CAAU,IAAA,EAAI;AACZ,MAAA,MAAM,EAAE,SAAS,GAAA,EAAK,KAAA,EAAO,UAAU,MAAA,EAAQ,MAAA,KAAW,aAAA,EAAa;AACvE,MAAA,OAAA,GAAU;AACR,QAAA,MAAA,EAAQ,IAAA,CAAK,MAAA;QACb,GAAI,IAAA,CAAK,cAAc,MAAA,GAAY,KAAK,EAAE,SAAA,EAAW,KAAK,SAAA,EAAS;AACnE,QAAA,MAAA,EAAQ,KAAK,MAAA,IAAU;;AAGzB,MAAA,QAAA,CAAS,UAAA,CAAW,IAAA,CAAK,KAAA,CAAM,EAAE,CAAA;AACjC,MAAA,QAAA,CAAS,WAAA,CAAY,KAAK,MAAM,CAAA;AAChC,MAAA,MAAA,CAAO,WAAA,CAAY,KAAK,MAAM,CAAA;AAE9B,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,MAAA,CAAO,oBAAA,CAAqB;QAC9C,KAAA,EAAO,CAAA,aAAA,EAAgB,IAAA,CAAK,KAAA,CAAM,EAAE,CAAA;AACrC,OAAA,CAAA;AAED,MAAA,IAAI,MAAA;AACJ,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,YAAY,OAAA,EAAS,eAAA,CAAgB,KAAK,OAAO,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AACrF,QAAA,eAAA,GAAkB,OAAA,CAAQ,KAAA;AAC1B,QAAA,aAAA,CAAc,IAAA,CAAK,KAAA,CAAM,EAAA,EAAI,OAAA,CAAQ,OAAO,CAAA;AAE5C,QAAA,IAAI,IAAA,CAAK,UAAU,KAAA,EAAO;AACxB,UAAA,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS,IAAA,CAAK,MAAM,CAAA;AACrC,UAAA,IAAI,KAAK,SAAA,KAAc,KAAA,CAAA;AAAW,YAAA,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS,IAAA,CAAK,SAAS,CAAA;AAC5E,QAAA;AAEA,QAAA,MAAA,GAAS,UAAA,CAAW,OAAA,EAAS,IAAA,CAAK,UAAU,CAAA;AAE5C,QAAA,IAAA,CAAK,MAAA,EAAQ,QAAQ,OAAO,CAAA;AAC5B,QAAA,GAAA,CAAI,OAAO,KAAA,CAAM,MAAA,CAAO,CAAC,OAAA,CAAQ,MAAA,EAAQ,CAAC,CAAA;AAG1C,QAAA,QAAA,CAAS,WAAA,EAAW;AACtB,MAAA,CAAA,SAAA;AAKE,QAAA,QAAA,CAAS,eAAA,EAAe;AAC1B,MAAA;AAKA,MAAA,MAAM,QAAQ,eAAA,KAAoB,MAAA,GAAY,CAAA,GAAI,IAAA,CAAK,MAAM,MAAA,GAAS,eAAA;AACtE,MAAA,eAAA,GAAkB,KAAK,KAAA,CAAM,MAAA;AAC7B,MAAA,IAAI,QAAQ,CAAA,EAAG;AACb,QAAA,KAAA,MAAW,KAAA,IAAS,WAAW,MAAA,EAAM;AAAI,UAAA,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC9D,MAAA;AAEA,MAAA,WAAA,IAAe,CAAA;AACf,MAAA,QAAA,CAAS,YAAY,MAAS,CAAA;AAC9B,MAAA,MAAA,CAAO,YAAY,MAAS,CAAA;AAC5B,MAAA,OAAO,MAAA;AACT,IAAA,CAAA;IAEA,gBAAA,GAAgB;AACd,MAAA,OAAO;QACL,EAAA,EAAI,wBAAA;AAEJ,QAAA,KAAA,EAAO,CAAC,YAAA,KAAkC;AACxC,UAAA,IAAI,KAAK,MAAA,CAAO,MAAA,KAAW,MAAA,IAAa,IAAA,CAAK,OAAO,YAAA,KAAiB,IAAA;AAAM,YAAA;AAC3E,UAAA,MAAM,EAAE,SAAS,GAAA,EAAK,KAAA,EAAO,UAAU,MAAA,EAAQ,MAAA,KAAW,aAAA,EAAa;AAEvE,UAAA,QAAA,CAAS,UAAA,CAAW,YAAA,CAAa,KAAA,CAAM,EAAE,CAAA;AACzC,UAAA,QAAA,CAAS,YAAY,MAAS,CAAA;AAC9B,UAAA,MAAA,CAAO,YAAY,MAAS,CAAA;AAE5B,UAAA,cAAA,GAAiB,GAAA,CAAI,OAAO,oBAAA,CAAqB;YAC/C,KAAA,EAAO,CAAA,aAAA,EAAgB,YAAA,CAAa,KAAA,CAAM,EAAE,CAAA;AAC7C,WAAA,CAAA;AAID,UAAA,IAAI;AACF,YAAA,MAAM,OAAA,GAAU,YACd,cAAA,EACA,YAAA,CAAa,6BAA2B,EACxC,YAAA,CAAa,MAAM,MAAM,CAAA;AAE3B,YAAA,eAAA,GAAkB,OAAA,CAAQ,KAAA;AAC1B,YAAA,aAAA,CAAc,YAAA,CAAa,KAAA,CAAM,EAAA,EAAI,OAAA,CAAQ,OAAO,CAAA;AACtD,UAAA,CAAA,CAAA,OAAS,KAAA,EAAO;AAGd,YAAA,cAAA,GAAiB,MAAA;AACjB,YAAA,QAAA,CAAS,eAAA,EAAe;AACxB,YAAA,MAAM,KAAA;AACR,UAAA;AACF,QAAA,CAAA;AAEA,QAAA,MAAA,EAAQ,CAAC,YAAA,KAAkC;AACzC,UAAA,MAAM,OAAA,GAAU,cAAA;AAChB,UAAA,cAAA,GAAiB,MAAA;AACjB,UAAA,IAAI,OAAA,KAAY,UAAa,OAAA,KAAY,MAAA;AAAW,YAAA;AACpD,UAAA,MAAM,MAAA,GAAS,MAAA;AACf,UAAA,MAAM,QAAA,GAAW,KAAA;AAEjB,UAAA,IAAI;AACF,YAAA,IAAI,YAAY,KAAA,CAAA,EAAW;AACzB,cAAA,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS,OAAA,CAAQ,MAAM,CAAA;AACxC,cAAA,IAAI,QAAQ,SAAA,KAAc,KAAA,CAAA;AAAW,gBAAA,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS,OAAA,CAAQ,SAAS,CAAA;AAChF,cAAA,UAAA,CAAW,OAAA,EAAS,aAAa,UAAU,CAAA;AAC7C,YAAA;AAEA,YAAA,OAAA,CAAQ,OAAO,KAAA,CAAM,MAAA,CAAO,CAAC,OAAA,CAAQ,MAAA,EAAQ,CAAC,CAAA;AAC9C,YAAA,QAAA,CAAS,WAAA,EAAW;AACtB,UAAA,CAAA,SAAA;AACE,YAAA,QAAA,CAAS,eAAA,EAAe;AAC1B,UAAA;AAEA,UAAA,MAAM,QACJ,eAAA,KAAoB,MAAA,GAAY,CAAA,GAAI,YAAA,CAAa,MAAM,MAAA,GAAS,eAAA;AAClE,UAAA,eAAA,GAAkB,aAAa,KAAA,CAAM,MAAA;AACrC,UAAA,IAAI,QAAQ,CAAA,EAAG;AACb,YAAA,KAAA,MAAW,KAAA,IAAS,WAAW,MAAA,EAAM;AAAI,cAAA,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC9D,UAAA;AACA,UAAA,WAAA,IAAe,CAAA;AACjB,QAAA;;AAEJ,IAAA,CAAA;AAEA,IAAA,MAAM,iBAAA,GAAiB;AACrB,MAAA,IAAI,KAAA,KAAU,MAAA;AAAW,QAAA,OAAO,CAAA;AAChC,MAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,YAAA,EAAY;AACtC,MAAA,KAAA,MAAW,CAAC,QAAA,EAAU,KAAK,CAAA,IAAK,KAAA,EAAO;AACrC,QAAA,MAAM,KAAA,GAAQ,cAAc,QAAQ,CAAA;AAIpC,QAAA,IAAI,MAAM,MAAA,CAAO,QAAA;AAAU,UAAA,KAAA,CAAM,QAAQ,KAAK,CAAA;;AACzC,UAAA,KAAA,CAAM,MAAM,KAAK,CAAA;AACxB,MAAA;AACA,MAAA,OAAO,KAAA,CAAM,IAAA;AACf,IAAA,CAAA;IAEA,OAAA,GAAO;AACL,MAAA,KAAA,MAAW,QAAA,IAAY,UAAU,MAAA,EAAM;AAAI,QAAA,QAAA,CAAS,OAAA,EAAO;AAC3D,MAAA,SAAA,CAAU,KAAA,EAAK;AACf,MAAA,MAAA,CAAO,KAAA,EAAK;AACZ,MAAA,UAAA,CAAW,KAAA,EAAK;AAChB,MAAA,cAAA,CAAe,KAAA,EAAK;AACpB,MAAA,cAAA,GAAiB,EAAA;AACjB,MAAA,cAAA,GAAiB,MAAA;AACjB,MAAA,eAAA,GAAkB,MAAA;AAClB,MAAA,WAAA,EAAW;AACX,MAAA,IAAA,CAAK,OAAA,EAAO;AACd,IAAA;;AAEJ","file":"dist-FGJI5LQM.js","sourcesContent":["/**\n * The analysis reduction: luminance, variance and edge density off the blur\n * pyramid, into a four-float stats buffer per backdrop source.\n *\n * This is what `analysis: \"exact\"` means in X2 — a real reduction over the real\n * pixels, not an estimate. It runs once per pyramid rebuild, which by the §Core\n * model invariant is at most once per dirty source per frame.\n *\n * ## Why one workgroup\n *\n * The reduction reads a fixed 64×64 grid of bilinear samples off a chosen chain\n * level, whatever that level's real size is. That makes the pass's cost constant\n * — 4096 samples, one workgroup, one dispatch — instead of proportional to the\n * backdrop's resolution, and it makes the result independent of the resolution\n * policy, so raising or lowering `scale` does not move the tint. A grid rather\n * than every texel is the right trade because the values feed a tint and a\n * light/dark decision, both of which are already low-passed in time.\n *\n * ## Edge density\n *\n * Central differences of luminance on the same grid, averaged. Read off a\n * mid-chain level rather than the coarsest: the coarsest level has had every edge\n * blurred out of it, so an edge measurement there would report the same small\n * number for a photograph and for a solid colour. The level choice lives on the\n * CPU (`pyramid-plan.ts`) where the sizes are known.\n *\n * ## Variance\n *\n * Accumulated as the mean of squares and folded at the end, which is the\n * numerically shakier of the two standard routes — but the inputs are luminances\n * in [0, ~1] over 4096 samples, so the cancellation is nowhere near f32's\n * resolution, and it costs one accumulator instead of two passes.\n */\n\nexport const ANALYSIS_WORKGROUP = 64;\nexport const ANALYSIS_GRID = 64;\n\n/** `stats` layout: mean luminance, variance, edge density, sample count. */\nexport const ANALYSIS_STATS_FLOATS = 4;\n\nexport const WGSL_ANALYSIS_PASS = `struct AnalysisUniforms {\n /// grid.xy = sample grid size, grid.z = source level, grid.w = 1/(grid-1)\n grid : vec4f,\n /// texel.xy = one texel of the sampled level, in uv\n texel : vec4f,\n};\n\n@group(0) @binding(0) var<uniform> au : AnalysisUniforms;\n@group(0) @binding(1) var analysisSampler : sampler;\n@group(0) @binding(2) var analysisTexture : texture_2d<f32>;\n@group(0) @binding(3) var<storage, read_write> stats : array<f32>;\n\nvar<workgroup> partialLum : array<f32, ${ANALYSIS_WORKGROUP}>;\nvar<workgroup> partialSq : array<f32, ${ANALYSIS_WORKGROUP}>;\nvar<workgroup> partialEdge : array<f32, ${ANALYSIS_WORKGROUP}>;\n\nfn lum_at(uv : vec2f) -> f32 {\n let s = textureSampleLevel(analysisTexture, analysisSampler, uv, au.grid.z);\n // Level 0 onwards is premultiplied linear; unpremultiplying keeps a\n // transparent backdrop region from reading as black rather than as absent.\n let colour = s.rgb / max(s.a, 1e-6);\n return luminance(colour);\n}\n\n@compute @workgroup_size(${ANALYSIS_WORKGROUP})\nfn cs_analysis(@builtin(local_invocation_index) lane : u32) {\n let total = u32(au.grid.x * au.grid.y);\n var sumLum = 0.0;\n var sumSq = 0.0;\n var sumEdge = 0.0;\n var n = 0.0;\n\n var i = lane;\n loop {\n if (i >= total) { break; }\n let gx = f32(i % u32(au.grid.x));\n let gy = f32(i / u32(au.grid.x));\n let uv = vec2f(gx, gy) * au.grid.w;\n\n let c = lum_at(uv);\n let dx = lum_at(uv + vec2f(au.texel.x, 0.0)) - lum_at(uv - vec2f(au.texel.x, 0.0));\n let dy = lum_at(uv + vec2f(0.0, au.texel.y)) - lum_at(uv - vec2f(0.0, au.texel.y));\n\n sumLum = sumLum + c;\n sumSq = sumSq + c * c;\n sumEdge = sumEdge + length(vec2f(dx, dy)) * 0.5;\n n = n + 1.0;\n\n i = i + ${ANALYSIS_WORKGROUP}u;\n }\n\n partialLum[lane] = sumLum;\n partialSq[lane] = sumSq;\n partialEdge[lane] = sumEdge;\n workgroupBarrier();\n\n // Tree reduction. ${ANALYSIS_WORKGROUP} is a power of two, so no tail case.\n var stride = ${ANALYSIS_WORKGROUP}u / 2u;\n loop {\n if (stride == 0u) { break; }\n if (lane < stride) {\n partialLum[lane] = partialLum[lane] + partialLum[lane + stride];\n partialSq[lane] = partialSq[lane] + partialSq[lane + stride];\n partialEdge[lane] = partialEdge[lane] + partialEdge[lane + stride];\n }\n workgroupBarrier();\n stride = stride / 2u;\n }\n\n if (lane == 0u) {\n let count = max(f32(total), 1.0);\n let mean = partialLum[0] / count;\n stats[0] = mean;\n stats[1] = max(partialSq[0] / count - mean * mean, 0.0);\n stats[2] = partialEdge[0] / count;\n stats[3] = count;\n }\n}`;\n","/**\n * X5 — the colour pipeline, CPU side.\n *\n * The contract in one line: **internal optical maths in linear light,\n * compositing premultiplied, output sRGB, v1 locked to the sRGB gamut.** Without\n * that lock golden images destabilise across GPUs and browsers and blur energy\n * drifts from the reference, which is the whole reason §Color pipeline exists.\n *\n * Three concrete consequences the rest of the renderer leans on:\n *\n * 1. **Every internal texture is `rgba16float` and holds linear light.** 8-bit\n * linear would band visibly in a blur pyramid; `rgba16float` is renderable and\n * filterable everywhere WebGPU is, so no adapter feature is required.\n * 2. **Alpha is normalised at import** (X3). `copyExternalImageToTexture`\n * delivers premultiplied; `importExternalTexture` delivers unpremultiplied.\n * Whichever arrives, level 0 of the pyramid is premultiplied linear — one\n * invariant, checked once at import, instead of an alpha mode threaded\n * through every downstream pass.\n * 3. **Output is encoded once, at the end of the last pass.** The optics and\n * highlight canvases are configured `alphaMode: \"premultiplied\"` in a plain\n * (non-`-srgb`) 8-bit format, and the browser composites those bytes as sRGB.\n * So the final step is `encode(linear)` and then `* alpha` — premultiplying in\n * the *encoded* space, which is what canvas compositing expects. Premultiplying\n * in linear and then encoding would darken every edge pixel.\n *\n * The transfer functions here are the exact piecewise sRGB curve, not the 2.2\n * approximation: the WGSL uses the same piecewise form, and a test asserts the\n * two agree, so a golden regenerated on one and asserted on the other cannot\n * drift by a code unit.\n */\n\n/**\n * The colour spaces v1 accepts on an imported backdrop.\n *\n * `display-p3` is *accepted and tagged*, never silently treated as sRGB — but v1\n * converts it into the sRGB working space rather than carrying a wide gamut\n * through the pipeline (§Color pipeline: \"Display-P3 and HDR/extended-range are\n * future profiles\"). Tagging it is what makes the future profile a data change.\n */\nexport const BACKDROP_COLOR_SPACES = [\"srgb\", \"display-p3\"] as const;\n\nexport type BackdropColorSpace = (typeof BACKDROP_COLOR_SPACES)[number];\n\n/** How a provider's pixels arrive. Normalised to `premultiplied` at import. */\nexport const BACKDROP_ALPHA_MODES = [\"premultiplied\", \"unpremultiplied\", \"opaque\"] as const;\n\nexport type BackdropAlphaMode = (typeof BACKDROP_ALPHA_MODES)[number];\n\n/** The one internal pixel format. See consequence 1 above. */\nexport const WORKING_TEXTURE_FORMAT: GPUTextureFormat = \"rgba16float\";\n\n/** The presentation format for the plane canvases and for golden readback. */\nexport const OUTPUT_TEXTURE_FORMAT: GPUTextureFormat = \"rgba8unorm\";\n\nconst SRGB_LINEAR_CUTOFF = 0.0031308;\nconst SRGB_ENCODED_CUTOFF = 0.04045;\nconst SRGB_SLOPE = 12.92;\nconst SRGB_ALPHA = 1.055;\nconst SRGB_OFFSET = 0.055;\nconst SRGB_GAMMA = 2.4;\n\n/** One channel, sRGB-encoded [0,1] → linear-light [0,1]. */\nexport function srgbToLinearChannel(c: number): number {\n if (c <= SRGB_ENCODED_CUTOFF) return c / SRGB_SLOPE;\n return Math.pow((c + SRGB_OFFSET) / SRGB_ALPHA, SRGB_GAMMA);\n}\n\n/** One channel, linear-light [0,1] → sRGB-encoded [0,1]. */\nexport function linearToSrgbChannel(c: number): number {\n if (c <= SRGB_LINEAR_CUTOFF) return c * SRGB_SLOPE;\n return SRGB_ALPHA * Math.pow(c, 1 / SRGB_GAMMA) - SRGB_OFFSET;\n}\n\nexport type Rgb = readonly [r: number, g: number, b: number];\n\nexport const srgbToLinear = (c: Rgb): Rgb => [\n srgbToLinearChannel(c[0]),\n srgbToLinearChannel(c[1]),\n srgbToLinearChannel(c[2]),\n];\n\nexport const linearToSrgb = (c: Rgb): Rgb => [\n linearToSrgbChannel(c[0]),\n linearToSrgbChannel(c[1]),\n linearToSrgbChannel(c[2]),\n];\n\n/**\n * Rec.709 luminance weights, applied to **linear** light.\n *\n * Stated explicitly because the common mistake is to weight sRGB-encoded values\n * — which gives a number that tracks perceived lightness loosely and blur energy\n * not at all. The analysis pass reduces linear luminance for the same reason the\n * blur runs in linear light: both are energy integrals.\n */\nexport const LUMINANCE_WEIGHTS: Rgb = [0.2126, 0.7152, 0.0722];\n\nexport function relativeLuminance(linear: Rgb): number {\n return (\n linear[0] * LUMINANCE_WEIGHTS[0] +\n linear[1] * LUMINANCE_WEIGHTS[1] +\n linear[2] * LUMINANCE_WEIGHTS[2]\n );\n}\n\n/**\n * Display-P3 → sRGB (linear light, both ends).\n *\n * The 3×3 is the product of P3-to-XYZ and XYZ-to-sRGB under D65. Out-of-gamut\n * results are clamped, which loses saturation on very saturated P3 content — the\n * honest v1 behaviour, and the reason the colour space is *tagged* rather than\n * assumed (a P3 profile can then convert differently without touching a shader).\n */\nconst P3_TO_SRGB: readonly Rgb[] = [\n [1.224940176280559, -0.224940176280559, 0],\n [-0.042056973821316, 1.042056973821316, 0],\n [-0.019637554590334, -0.078636046901105, 1.098273601491439],\n];\n\nexport function displayP3ToSrgbLinear(linearP3: Rgb): Rgb {\n const out: number[] = [];\n for (const row of P3_TO_SRGB) {\n out.push(\n Math.min(1, Math.max(0, row[0] * linearP3[0] + row[1] * linearP3[1] + row[2] * linearP3[2])),\n );\n }\n return [out[0] as number, out[1] as number, out[2] as number];\n}\n\n/**\n * The colour-space conversion the import pass must apply, as data.\n *\n * Returned as a matrix (row-major 3×3) so the shader takes one uniform and has\n * no branch on colour space. Identity for sRGB — the overwhelmingly common case\n * costs three dot products, which is cheaper than the branch would be.\n */\nexport function importColorMatrix(space: BackdropColorSpace): Float32Array {\n if (space === \"srgb\") {\n return new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);\n }\n const rows = P3_TO_SRGB;\n return new Float32Array([\n ...(rows[0] as Rgb),\n ...(rows[1] as Rgb),\n ...(rows[2] as Rgb),\n ]);\n}\n\n/**\n * The alpha normalisation the import pass must apply, as a scalar flag.\n *\n * `0` = already premultiplied, `1` = divide the colour by alpha first, `2` =\n * force alpha to 1. Three modes and one uniform, resolved on the CPU where the\n * provider's contract is known, so no shader ever guesses (X3).\n */\nexport function alphaNormalisationMode(mode: BackdropAlphaMode): number {\n switch (mode) {\n case \"premultiplied\":\n return 0;\n case \"unpremultiplied\":\n return 1;\n case \"opaque\":\n return 2;\n }\n}\n\n/**\n * Encode a linear-light colour and its alpha the way the output pass does, for\n * tests and for golden-image expectations computed on the CPU.\n */\nexport function encodeOutput(linear: Rgb, alpha: number): readonly [number, number, number, number] {\n const a = Math.min(1, Math.max(0, alpha));\n const encoded = linearToSrgb(linear);\n return [encoded[0] * a, encoded[1] * a, encoded[2] * a, a];\n}\n\n/** The same, quantised to the 8-bit bytes a golden PNG holds. */\nexport function encodeOutputBytes(linear: Rgb, alpha: number): readonly number[] {\n return encodeOutput(linear, alpha).map((c) => Math.round(Math.min(1, Math.max(0, c)) * 255));\n}\n","/**\n * The optical constants, and the two foldings that decide what the shader\n * actually gets: the dual cap, and the size-parameterised lens.\n *\n * **Every number here is advisory and calibration-delegated (C7).** They are\n * chosen so the material is coherent out of the box — a plausible glass, not a\n * measured one — and §Calibration names exactly this kind of value as a delegated\n * unknown. They live in one profile object (`MaterialProfile`) so replacing them\n * with fitted values is a data change (`withMaterialOverrides`), and no shader\n * carries a literal of its own. The named constants below are re-exports of that\n * profile's defaults, kept because a reader wants a name for σ = 8 more often\n * than a whole profile.\n *\n * ## The dual cap (Decision Log #19)\n *\n * Two independent things cap refraction: the accessibility policy's regime\n * (`nominal | reduced | none`) and the group's resolved capability state\n * (`true | approximate | none` — what the sampling backend can actually deliver).\n * **The lower of the two wins**, and this module folds them into one scalar before\n * anything reaches a uniform, so the shader has no way to honour the wrong one.\n *\n * The ordering mirrors `platform-web`'s `REFRACTION_LADDER`, which serves the CSS\n * tier. It is restated rather than imported because this package sits *below*\n * core in the dependency graph and platform-web sits above it. That the two\n * copies must agree is a real (if small) seam — see the note in the C6 report.\n */\n\nimport type { Rgb } from \"./color\";\nimport { srgbToLinear } from \"./color\";\n\n/** X2's `RefractionQuality`, restated. Weakest first — the declaration order IS the ladder. */\nexport const REFRACTION_LADDER = [\"none\", \"approximate\", \"true\"] as const;\n\nexport type RefractionQuality = (typeof REFRACTION_LADDER)[number];\n\nexport function refractionRank(quality: RefractionQuality): number {\n return REFRACTION_LADDER.indexOf(quality);\n}\n\n/**\n * The slice of core's `ResolvedAccessibilityPolicy[\"material\"]` the renderer\n * reads. core's type is assignable to this; a test pins that.\n */\nexport interface MaterialPolicyView {\n readonly glass: \"material\" | \"none\";\n readonly frost: \"nominal\" | \"increased\" | \"none\";\n readonly refraction: \"nominal\" | \"reduced\" | \"none\";\n readonly occlusion: \"nominal\" | \"increased\" | \"opaque\";\n readonly border: \"nominal\" | \"strong\";\n readonly ambientTint: \"nominal\" | \"reduced\" | \"none\";\n readonly foreground: \"adaptive\" | \"near-monochrome\";\n}\n\n/** The accessibility regime as a rung on the same ladder. */\nexport function accessibilityRefractionCap(policy: MaterialPolicyView): RefractionQuality {\n switch (policy.refraction) {\n case \"nominal\":\n return \"true\";\n case \"reduced\":\n return \"approximate\";\n case \"none\":\n return \"none\";\n }\n}\n\n/** The lower of two caps. Symmetric — neither argument is privileged. */\nexport function effectiveRefraction(a: RefractionQuality, b: RefractionQuality): RefractionQuality {\n return refractionRank(a) <= refractionRank(b) ? a : b;\n}\n\n/** The two variants, declared as data so a profile merge can walk them. */\nexport const MATERIAL_VARIANTS = [\"regular\", \"clear\"] as const;\n\nexport type MaterialVariant = (typeof MATERIAL_VARIANTS)[number];\n\nexport interface MaterialOptics {\n /** Body blur σ in CSS px. Matches `platform-web`'s `MATERIAL_OPTICS.blurRadius`. */\n readonly blurSigma: number;\n /** Tint over the blurred backdrop, linear light. */\n readonly tint: Rgb;\n readonly tintAlpha: number;\n /** Rim band half-width in CSS px, and its ambient brightness. */\n readonly rimWidth: number;\n readonly rimAlpha: number;\n /** Specular exponent and gain on the rim. */\n readonly specularPower: number;\n readonly specularGain: number;\n /** Inner-shadow depth (0..1) and how much of it is applied. */\n readonly shadowDepth: number;\n readonly shadowAlpha: number;\n /** Highlight colour for the sweep and press glow, linear light. */\n readonly highlight: Rgb;\n}\n\n/** The rim a `border: \"strong\"` policy substitutes, whatever the variant asked for. */\nexport interface MaterialRim {\n readonly rimWidth: number;\n readonly rimAlpha: number;\n}\n\n/**\n * Every number the material runs on, in one place.\n *\n * The same seam `@vitrea/motion`'s `MotionProfile` opens for the drivers, for the\n * optics: C7's harness measures these against `apple-macos-26.5-*` fixtures and\n * replaces what is here, so nothing downstream may hard-code an optical constant\n * of its own. A profile overrides every one of them (`withMaterialOverrides`),\n * which makes landing a calibrated set a data change rather than a code change.\n *\n * Units: CSS px for distance, linear light for colour, viewport coordinates with\n * y pointing down for direction.\n */\nexport interface MaterialProfile {\n /** Per-variant optics. `clear` is persistently more transparent than `regular`. */\n readonly optics: Readonly<Record<MaterialVariant, MaterialOptics>>;\n\n /** The two ends of adaptation: what the tint becomes over a dark and a light backdrop. */\n readonly adaptiveTintDark: Rgb;\n readonly adaptiveTintLight: Rgb;\n /** Luminance band the tint crosses over. Hysteresis in time is the driver's job. */\n readonly adaptiveLuminanceLow: number;\n readonly adaptiveLuminanceHigh: number;\n\n /**\n * How much of the lens the shader is allowed to apply, per rung.\n *\n * `approximate` is not \"half of true\": it is the rim-lensing approximation, a\n * shallower bend confined nearer the edge, which is what a group sampling a CSS\n * proxy can honestly claim. Reduced transparency lands here too, which is the\n * point of the ladder having three rungs and not two.\n */\n readonly refractionScale: Readonly<Record<RefractionQuality, number>>;\n\n /**\n * The size-parameterised lens depth — parent acceptance #2's mechanism.\n *\n * Below `lensSpanMin` a surface gets its authored thickness and nothing more;\n * above `lensSpanMax` it gets `lensSizeGainMax` times it. The final clamp to the\n * shorter *half* extent is what keeps a small control from being all lens: a\n * 24 px-tall button cannot bend more than 12 px of backdrop however thick it is\n * authored.\n *\n * A smoothstep rather than a straight ratio, so two surfaces of nearly the same\n * size never read as differently thick, and so the gain saturates instead of\n * growing without bound on a full-width platter.\n */\n readonly lensSpanMin: number;\n readonly lensSpanMax: number;\n readonly lensSizeGainMax: number;\n\n /** Chain LOD per CSS px of lens depth, and how much sharper the rim samples. */\n readonly lensBodyLodPerPx: number;\n readonly lensRimLodBias: number;\n\n /**\n * What each accessibility regime does to the numbers above. The multipliers\n * match `platform-web`'s CSS tier so the two renderers degrade the same way\n * under the same preference.\n */\n readonly reducedTransparencyFrost: number;\n /**\n * How much of the *remaining* transparency reduced transparency closes.\n *\n * **Relative, not absolute (Decision Log #32(d)).** This was\n * `increasedOcclusionAlpha`, an absolute floor of 0.62 applied as\n * `Math.max(nominal, floor)` — a real lift while nominal was the advisory 0.28,\n * and a no-op from the moment C9a measured nominal at 0.62. The policy died\n * without being touched and nothing noticed for a whole child. A fraction of the\n * headroom cannot die that way: it lifts strictly for every nominal below 1,\n * whatever a later tuning pass moves nominal to.\n *\n * The fraction is the pre-C9a lift, restored rather than invented:\n * (0.62 − 0.28) / (1 − 0.28) = 0.4722, which reproduces the old floor exactly at\n * the old nominal. At today's nominal it reads 0.62 → 0.799.\n *\n * Mirrored by `@vitrea/platform-web`'s `INCREASED_OCCLUSION_LIFT`, and pinned in\n * both directions by `packages/calibration/test/tier-coherence.test.ts`.\n */\n readonly increasedOcclusionLift: number;\n readonly strongBorderRim: MaterialRim;\n readonly reducedTintAdaptation: number;\n\n /**\n * Advisory light direction, in viewport coordinates with y pointing down: a\n * little left of straight overhead, which is where Apple's material reads its\n * specular from.\n */\n readonly lightDirection: readonly [number, number];\n /** Specular sweep band width in radians, and the press glow's reach in CSS px. */\n readonly sweepBandRadians: number;\n readonly glowRadiusCss: number;\n readonly glowGain: number;\n readonly sweepGain: number;\n}\n\n/*\n * There is no longer a dark counterpart to this constant. The old\n * `SRGB_DARK_TINT` ([0.09, 0.09, 0.1]) existed only as the light-backdrop end of\n * the adaptive crossover, and C9a measured that the reference does not invert its\n * tint against the backdrop at all — see `adaptiveTintLight` below. The\n * dark-SCHEME tint is a different quantity and lives with the profile that\n * carries it: packages/calibration/profiles/apple-macos-26.5-1x-dark-standard.json.\n */\nconst SRGB_WHITE_TINT: Rgb = [1, 1, 1];\n\n/**\n * The pre-C9a lift, expressed as the fraction of the remaining transparency it\n * closed: (0.62 − 0.28) / (1 − 0.28). See `MaterialProfile.increasedOcclusionLift`.\n */\nexport const INCREASED_OCCLUSION_LIFT = 0.4722;\n\n/**\n * The occlusion alpha a resolved policy asks for, given whatever nominal the\n * material carries. Mirrors `@vitrea/platform-web`'s `occlusionAlphaUnderPolicy`.\n */\nexport function occlusionAlphaUnderPolicy(\n nominal: number,\n occlusion: MaterialPolicyView[\"occlusion\"],\n lift: number = INCREASED_OCCLUSION_LIFT,\n): number {\n switch (occlusion) {\n case \"nominal\":\n return nominal;\n case \"increased\":\n return nominal + lift * (1 - nominal);\n case \"opaque\":\n return 1;\n }\n}\n\nexport const DEFAULT_MATERIAL_PROFILE: MaterialProfile = {\n optics: {\n // σ = 8 for the regular variant, which keeps this package's blur and\n // `platform-web`'s CSS-tier blur on the same number — and makes core's 24 px\n // `samplingPadding` advisory exactly the 3σ S1 measured.\n regular: {\n blurSigma: 8,\n tint: srgbToLinear(SRGB_WHITE_TINT),\n // MEASURED (C9a), against apple-macos-26.5-1x-light-standard. The advisory\n // 0.28 made vitrea's regular material roughly half as opaque as the\n // reference: regressing interior level against backdrop level across the\n // calibration scenes puts Apple's transmission at 0.26 of the backdrop\n // where vitrea's was 0.70. 0.62 is the minimiser of the declared tuning\n // objective; see docs/doperpowers/specs/c9a-fidelity-claims.md, and note\n // that no single value can be right for every size — Apple's opacity falls\n // with surface span (0.88 at 32 px to 0.56 at 96 px) and this renderer has\n // no size term on the tint.\n tintAlpha: 0.62,\n rimWidth: 1.5,\n rimAlpha: 0.18,\n specularPower: 6,\n specularGain: 0.55,\n shadowDepth: 0.35,\n shadowAlpha: 0.55,\n highlight: srgbToLinear(SRGB_WHITE_TINT),\n },\n // Persistently more transparent, so it frosts less and tints less.\n clear: {\n blurSigma: 4,\n tint: srgbToLinear(SRGB_WHITE_TINT),\n tintAlpha: 0.1,\n rimWidth: 1.25,\n rimAlpha: 0.14,\n specularPower: 8,\n specularGain: 0.45,\n shadowDepth: 0.22,\n shadowAlpha: 0.4,\n highlight: srgbToLinear(SRGB_WHITE_TINT),\n },\n },\n\n /*\n * MEASURED (C9a): both ends are the same tint, which makes the crossover inert\n * by default. That is a finding, not a shortcut.\n *\n * The two ends used to straddle the backdrop — white over a dark backdrop,\n * near-black over a light one — so the material always contrasted with what was\n * behind it. Apple's Regular material does not do that. Its interior rises\n * monotonically with the backdrop across the whole canonical range (0.680 at a\n * backdrop of 0.003, 0.932 at 0.891, light scheme), which is a fixed tint at\n * partial transmission. What it keys on instead is the COLOUR SCHEME: over the\n * same bright checkerboard the reference sits at 0.809 in light and 0.055 in\n * dark. Leaving the inversion on cost more than the whole tint tune was worth —\n * it drove the light-scheme error from 0.348 to 0.449 on the interior-level\n * term alone.\n *\n * So the scheme picks the tint, and the calibration profiles carry one set of\n * numbers per scheme (packages/calibration/profiles/). The crossover mechanism\n * is untouched and still available to a profile that wants it; the default\n * simply no longer claims a behaviour the reference does not have.\n *\n * Two limits worth naming. The ends are global rather than per-variant, so the\n * clear variant inherits this — and clear has no calibration scenes at all, so\n * it is uncalibrated either way. And nothing yet selects a profile from the\n * scheme; that is C9a's parent-impact item.\n */\n adaptiveTintDark: srgbToLinear(SRGB_WHITE_TINT),\n adaptiveTintLight: srgbToLinear(SRGB_WHITE_TINT),\n adaptiveLuminanceLow: 0.12,\n adaptiveLuminanceHigh: 0.42,\n\n refractionScale: {\n none: 0,\n approximate: 0.45,\n true: 1,\n },\n\n lensSpanMin: 28,\n lensSpanMax: 420,\n lensSizeGainMax: 2.6,\n\n lensBodyLodPerPx: 0.16,\n lensRimLodBias: 2.5,\n\n reducedTransparencyFrost: 1.75,\n increasedOcclusionLift: INCREASED_OCCLUSION_LIFT,\n strongBorderRim: { rimWidth: 2, rimAlpha: 0.95 },\n reducedTintAdaptation: 0.35,\n\n lightDirection: [-0.3714, -0.9285],\n sweepBandRadians: 0.55,\n glowRadiusCss: 44,\n glowGain: 0.6,\n sweepGain: 0.85,\n};\n\n// The default profile's numbers, under the names the rest of the package and its\n// tests already know them by. Derived rather than duplicated: a re-tuned default\n// moves both at once, and there is no second place for the two to disagree.\nexport const REFRACTION_SCALE = DEFAULT_MATERIAL_PROFILE.refractionScale;\nexport const MATERIAL_OPTICS = DEFAULT_MATERIAL_PROFILE.optics;\nexport const ADAPTIVE_TINT_DARK = DEFAULT_MATERIAL_PROFILE.adaptiveTintDark;\nexport const ADAPTIVE_TINT_LIGHT = DEFAULT_MATERIAL_PROFILE.adaptiveTintLight;\nexport const ADAPTIVE_LUMINANCE_LOW = DEFAULT_MATERIAL_PROFILE.adaptiveLuminanceLow;\nexport const ADAPTIVE_LUMINANCE_HIGH = DEFAULT_MATERIAL_PROFILE.adaptiveLuminanceHigh;\nexport const LENS_SPAN_MIN = DEFAULT_MATERIAL_PROFILE.lensSpanMin;\nexport const LENS_SPAN_MAX = DEFAULT_MATERIAL_PROFILE.lensSpanMax;\nexport const LENS_SIZE_GAIN_MAX = DEFAULT_MATERIAL_PROFILE.lensSizeGainMax;\nexport const LENS_BODY_LOD_PER_PX = DEFAULT_MATERIAL_PROFILE.lensBodyLodPerPx;\nexport const LENS_RIM_LOD_BIAS = DEFAULT_MATERIAL_PROFILE.lensRimLodBias;\n\n/**\n * A profile patch: any subset, to any depth, of what a profile holds.\n *\n * A colour is one leaf, not three: patching a tint means naming the whole triple,\n * because two channels of a fitted colour and one of the default is not a colour\n * anybody measured.\n */\nexport interface MaterialProfilePatch {\n readonly optics?: Readonly<Partial<Record<MaterialVariant, Readonly<Partial<MaterialOptics>>>>>;\n readonly adaptiveTintDark?: Rgb;\n readonly adaptiveTintLight?: Rgb;\n readonly adaptiveLuminanceLow?: number;\n readonly adaptiveLuminanceHigh?: number;\n readonly refractionScale?: Readonly<Partial<Record<RefractionQuality, number>>>;\n readonly lensSpanMin?: number;\n readonly lensSpanMax?: number;\n readonly lensSizeGainMax?: number;\n readonly lensBodyLodPerPx?: number;\n readonly lensRimLodBias?: number;\n readonly reducedTransparencyFrost?: number;\n readonly increasedOcclusionLift?: number;\n readonly strongBorderRim?: Readonly<Partial<MaterialRim>>;\n readonly reducedTintAdaptation?: number;\n readonly lightDirection?: readonly [number, number];\n readonly sweepBandRadians?: number;\n readonly glowRadiusCss?: number;\n readonly glowGain?: number;\n readonly sweepGain?: number;\n}\n\n/**\n * Apply a patch. This is how a calibration profile lands: C7 emits the measured\n * numbers, the host passes them here, and every constant above is replaceable\n * without touching this file.\n *\n * The nested records merge per field and per rung, so a patch naming one tint\n * alpha keeps that variant's blur, rim and specular rather than dropping them.\n */\nexport function withMaterialOverrides(\n base: MaterialProfile,\n patch: MaterialProfilePatch,\n): MaterialProfile {\n const optics = {} as Record<MaterialVariant, MaterialOptics>;\n for (const variant of MATERIAL_VARIANTS) {\n optics[variant] = { ...base.optics[variant], ...patch.optics?.[variant] };\n }\n\n const refractionScale = {} as Record<RefractionQuality, number>;\n for (const rung of REFRACTION_LADDER) {\n refractionScale[rung] = patch.refractionScale?.[rung] ?? base.refractionScale[rung];\n }\n\n return {\n optics,\n adaptiveTintDark: patch.adaptiveTintDark ?? base.adaptiveTintDark,\n adaptiveTintLight: patch.adaptiveTintLight ?? base.adaptiveTintLight,\n adaptiveLuminanceLow: patch.adaptiveLuminanceLow ?? base.adaptiveLuminanceLow,\n adaptiveLuminanceHigh: patch.adaptiveLuminanceHigh ?? base.adaptiveLuminanceHigh,\n refractionScale,\n lensSpanMin: patch.lensSpanMin ?? base.lensSpanMin,\n lensSpanMax: patch.lensSpanMax ?? base.lensSpanMax,\n lensSizeGainMax: patch.lensSizeGainMax ?? base.lensSizeGainMax,\n lensBodyLodPerPx: patch.lensBodyLodPerPx ?? base.lensBodyLodPerPx,\n lensRimLodBias: patch.lensRimLodBias ?? base.lensRimLodBias,\n reducedTransparencyFrost: patch.reducedTransparencyFrost ?? base.reducedTransparencyFrost,\n increasedOcclusionLift: patch.increasedOcclusionLift ?? base.increasedOcclusionLift,\n strongBorderRim: { ...base.strongBorderRim, ...patch.strongBorderRim },\n reducedTintAdaptation: patch.reducedTintAdaptation ?? base.reducedTintAdaptation,\n lightDirection: patch.lightDirection ?? base.lightDirection,\n sweepBandRadians: patch.sweepBandRadians ?? base.sweepBandRadians,\n glowRadiusCss: patch.glowRadiusCss ?? base.glowRadiusCss,\n glowGain: patch.glowGain ?? base.glowGain,\n sweepGain: patch.sweepGain ?? base.sweepGain,\n };\n}\n\n/**\n * Fold core's resolved material *regime* onto this package's numbers.\n *\n * core decides which regime applies and nothing here re-decides it. One branch\n * per axis of `MaterialPolicyView`, so a new axis in core surfaces as a missing\n * branch here rather than as silence.\n */\nexport function opticsUnderPolicy(\n optics: MaterialOptics,\n policy: MaterialPolicyView,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): MaterialOptics {\n let next = optics;\n\n if (policy.frost === \"increased\") {\n next = { ...next, blurSigma: next.blurSigma * profile.reducedTransparencyFrost };\n } else if (policy.frost === \"none\") {\n next = { ...next, blurSigma: 0 };\n }\n\n next = {\n ...next,\n tintAlpha: occlusionAlphaUnderPolicy(\n next.tintAlpha,\n policy.occlusion,\n profile.increasedOcclusionLift,\n ),\n };\n\n if (policy.border === \"strong\") next = { ...next, ...profile.strongBorderRim };\n\n return next;\n}\n\n/** How much of the analysis-driven tint is applied, under the contrast regime. */\nexport function adaptationStrength(\n policy: MaterialPolicyView,\n analysisExact: boolean,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n if (!analysisExact) return 0;\n switch (policy.ambientTint) {\n case \"nominal\":\n return 1;\n case \"reduced\":\n return profile.reducedTintAdaptation;\n case \"none\":\n return 0;\n }\n}\n\nconst smoothstep = (edge0: number, edge1: number, x: number): number => {\n if (edge1 <= edge0) return x < edge0 ? 0 : 1;\n const t = Math.min(1, Math.max(0, (x - edge0) / (edge1 - edge0)));\n return t * t * (3 - 2 * t);\n};\n\n/** The lens's size gain — see `MaterialProfile.lensSpanMin` for what it is for. */\nexport function lensSizeGain(\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return (\n 1 +\n (profile.lensSizeGainMax - 1) *\n smoothstep(profile.lensSpanMin, profile.lensSpanMax, spanPx)\n );\n}\n\nexport function lensDepthPx(\n thicknessPx: number,\n spanPx: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n const gain = lensSizeGain(spanPx, profile);\n return Math.min(Math.max(thicknessPx, 0) * gain, spanPx * 0.5);\n}\n\n/** Body blur LOD on the chain for a given lens depth — thicker glass diffuses more. */\nexport function bodyLod(\n lensDepth: number,\n maxLod: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): number {\n return Math.min(Math.max(lensDepth * profile.lensBodyLodPerPx, 0), maxLod);\n}\n","/**\n * Backdrop analysis on the CPU side: the stats a reduction produced, and the\n * temporal hysteresis that makes them usable.\n *\n * §Motion binds `backdrop-adaptation values` to the *exponential low-pass +\n * hysteresis* driver, and §Motion also puts every driver on the CPU. So the shape\n * is: the GPU reduces (exactly — X2's `analysis: \"exact\"`), the result is read\n * back at a low rate, and `LowPassHysteresisDriver` from `@vitrea/motion` — the\n * same class the rest of the runtime uses, not a reimplementation — smooths it.\n * The shader reads the driver's output as a uniform and never sees the raw stat.\n *\n * ## Why the readback is not a per-frame cost\n *\n * §Foreground adaptation caps the readback at an advisory 15 Hz (Decision Log\n * #19), and the governor lowers it further. That is not a performance\n * concession — it is what keeps the adaptation honest. A per-frame readback would\n * either stall the pipeline waiting for the map, or produce a value two frames old\n * and pretend it was current. At 15 Hz with a 500 ms low-pass the staleness is far\n * inside the filter's own time constant, so it is invisible in the output.\n *\n * ## The band is on the input, not the output\n *\n * `LowPassHysteresisDriver` commits a new observation only once it departs the\n * *committed* value by more than the band, then low-passes the committed\n * staircase. Measuring against the moving output instead would let a slow drift\n * leak through one small step at a time, which is exactly the foreground pumping\n * §Foreground adaptation rules out. That property is the driver's, and it is the\n * reason to use the driver rather than an `exp()` here.\n */\n\nimport { LowPassHysteresisDriver } from \"@vitrea/motion\";\n\nimport { DEFAULT_MATERIAL_PROFILE, type MaterialProfile } from \"./material\";\nimport type { Rgb } from \"./color\";\n\n/** The four floats the reduction writes. */\nexport interface BackdropStats {\n /** Mean linear luminance, 0..1-ish (an HDR-ish source can exceed 1). */\n readonly luminance: number;\n /** Variance of linear luminance. */\n readonly variance: number;\n /** Mean luminance-gradient magnitude per texel — the edge-density measure. */\n readonly edgeDensity: number;\n /** Samples the reduction actually took. 0 means \"never reduced\". */\n readonly sampleCount: number;\n}\n\nexport const ZERO_STATS: BackdropStats = {\n luminance: 0,\n variance: 0,\n edgeDensity: 0,\n sampleCount: 0,\n};\n\nexport function statsFromBuffer(values: ArrayLike<number>): BackdropStats {\n return {\n luminance: values[0] ?? 0,\n variance: values[1] ?? 0,\n edgeDensity: values[2] ?? 0,\n sampleCount: values[3] ?? 0,\n };\n}\n\n/**\n * Driver configuration for the three adaptation channels.\n *\n * The time constant and band are §Motion's `backdropAdaptation` defaults — a long\n * constant and a wide band so scrolling past a contrast edge cannot pump the\n * material. Restated as a literal rather than read off `DEFAULT_MOTION_PROFILE`\n * because `edgeDensity` and `variance` live on different scales from luminance and\n * want their own bands; the *shape* is motion's, the widths are this package's.\n */\nconst LUMINANCE_CONFIG = {\n kind: \"low-pass-hysteresis\",\n timeConstantMs: 500,\n hysteresis: 0.04,\n restDistance: 1e-3,\n} as const;\n\nconst VARIANCE_CONFIG = { ...LUMINANCE_CONFIG, hysteresis: 0.01 } as const;\nconst EDGE_CONFIG = { ...LUMINANCE_CONFIG, hysteresis: 0.01 } as const;\n\nexport interface AdaptationValues {\n readonly luminance: number;\n readonly variance: number;\n readonly edgeDensity: number;\n /** The tint the optics pass should mix toward, in linear light. */\n readonly tint: Rgb;\n /** True once at least one reduction has been observed. */\n readonly observed: boolean;\n}\n\nexport interface AdaptationState {\n /** Commit a fresh reduction. Cheap — the band may reject it outright. */\n observe(stats: BackdropStats): void;\n /** Advance the filters by a frame delta in ms. */\n advance(deltaMs: number): void;\n /** Jump the filters to a reduction with no transient. Used on the first frame. */\n reset(stats: BackdropStats): void;\n readonly values: AdaptationValues;\n readonly settled: boolean;\n}\n\nconst smoothstep = (edge0: number, edge1: number, x: number): number => {\n if (edge1 <= edge0) return x < edge0 ? 0 : 1;\n const t = Math.min(1, Math.max(0, (x - edge0) / (edge1 - edge0)));\n return t * t * (3 - 2 * t);\n};\n\n/**\n * The adaptive tint: a crossfade between the dark-backdrop and light-backdrop\n * tints across a luminance band.\n *\n * The crossfade is deliberately not a hard threshold. §Motion gives the\n * *foreground* light/dark decision a threshold-plus-crossfade driver because it\n * feeds a DOM `color`, which is discrete; the material's own tint is continuous\n * and can simply follow the smoothed luminance, so it does. One fewer driver, and\n * no risk of the tint and the foreground disagreeing at the threshold.\n */\nexport function adaptiveTint(\n luminance: number,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): Rgb {\n const dark = profile.adaptiveTintDark;\n const light = profile.adaptiveTintLight;\n const t = smoothstep(profile.adaptiveLuminanceLow, profile.adaptiveLuminanceHigh, luminance);\n return [\n dark[0] + (light[0] - dark[0]) * t,\n dark[1] + (light[1] - dark[1]) * t,\n dark[2] + (light[2] - dark[2]) * t,\n ];\n}\n\nexport function createAdaptationState(\n initial: BackdropStats = ZERO_STATS,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): AdaptationState {\n const luminance = new LowPassHysteresisDriver(LUMINANCE_CONFIG, initial.luminance);\n const variance = new LowPassHysteresisDriver(VARIANCE_CONFIG, initial.variance);\n const edge = new LowPassHysteresisDriver(EDGE_CONFIG, initial.edgeDensity);\n let observed = initial.sampleCount > 0;\n\n return {\n observe(stats) {\n if (stats.sampleCount <= 0) return;\n observed = true;\n luminance.retarget(stats.luminance);\n variance.retarget(stats.variance);\n edge.retarget(stats.edgeDensity);\n },\n\n advance(deltaMs) {\n luminance.advance(deltaMs);\n variance.advance(deltaMs);\n edge.advance(deltaMs);\n },\n\n reset(stats) {\n observed = stats.sampleCount > 0;\n luminance.jumpTo(stats.luminance);\n variance.jumpTo(stats.variance);\n edge.jumpTo(stats.edgeDensity);\n },\n\n get values() {\n return {\n luminance: luminance.value,\n variance: variance.value,\n edgeDensity: edge.value,\n tint: adaptiveTint(luminance.value, profile),\n observed,\n };\n },\n\n get settled() {\n return luminance.settled && variance.settled && edge.settled;\n },\n };\n}\n\n/**\n * Whether a readback is due, given the governor's cadence.\n *\n * A single-slot gate rather than a queue: if the previous map has not resolved the\n * next one is simply skipped. Queueing readbacks under pressure is how a renderer\n * ends up with a backlog of stale buffers and a growing memory footprint, and the\n * consumer here cannot use two answers from the same frame anyway.\n */\nexport function readbackDue(\n lastAtMs: number | undefined,\n nowMs: number,\n cadenceHz: number,\n): boolean {\n if (cadenceHz <= 0) return false;\n if (lastAtMs === undefined) return true;\n return nowMs - lastAtMs >= 1000 / cadenceHz;\n}\n","/**\n * The renderer's typed failures.\n *\n * X3 asks for one specific behaviour and this class exists to deliver it:\n * \"App-supplied views must satisfy declared usage/format/dimension requirements\n * — **validated at registration with a typed error, never discovered at draw\n * time**.\" So every provider validates its descriptor before it touches the\n * device, and every rejection carries a code a caller can branch on plus a\n * message that says which requirement failed and what to pass instead.\n *\n * The split from core's diagnostics channel is deliberate and mirrors the one\n * `scene.ts` draws: a structural mistake — a view of the wrong format, a\n * duplicate source id, a draw against a torn-down device — throws, because\n * continuing leaves the resource graph describing textures that are not there.\n * Recoverable, per-frame findings are not errors: those travel as\n * `demotionReason`s through core's state model, which is the honest place for\n * \"this still renders, just less\".\n */\n\nexport const RENDERER_ERROR_CODES = [\n /** A `GPUTextureView`'s backing texture lacks a required usage flag. */\n \"texture-usage\",\n /** Format outside the set the sampling path can read. */\n \"texture-format\",\n /** Wrong view dimension, or a depth/array layer count the pass cannot bind. */\n \"texture-dimension\",\n /** Zero or absurd extent, or a size that exceeds the device's limits. */\n \"texture-size\",\n /** A source id registered twice, or an unknown id referenced. */\n \"source-identity\",\n /** The provider was asked for a frame it cannot produce (closed video, detached canvas). */\n \"source-unavailable\",\n /** No device is attached, or the attached one is lost. */\n \"device-unavailable\",\n /** A frame was acquired twice without a release, or released without an acquire. */\n \"frame-protocol\",\n /** A pass was asked to draw something the current resources cannot express. */\n \"pass-input\",\n] as const;\n\nexport type RendererErrorCode = (typeof RENDERER_ERROR_CODES)[number];\n\nexport class RendererError extends Error {\n readonly code: RendererErrorCode;\n /** The source, group or node the failure is about, when there is one. */\n readonly subject: string | undefined;\n\n constructor(code: RendererErrorCode, message: string, subject?: string) {\n super(message);\n this.name = \"RendererError\";\n this.code = code;\n this.subject = subject;\n }\n}\n\nexport function rendererError(\n code: RendererErrorCode,\n message: string,\n subject?: string,\n): RendererError {\n return new RendererError(code, message, subject);\n}\n","/**\n * X3 — the BackdropFrame acquisition protocol, and a provider for every source\n * kind §Backdrop contracts names.\n *\n * The spec calls this contract \"operational, not aspirational\", and the reason is\n * a hard WebGPU fact: **there is no cross-device texture sharing.** So every\n * source, however it arrives, is normalised through one protocol —\n * `acquire(frame)` at frame start, `release()` after submit — and the frame\n * carries the four things a consumer cannot infer: the binding, the size epoch,\n * the colour space, and the alpha mode.\n *\n * ## The five kinds, and what is actually different about each\n *\n * | kind | mechanism | alpha | re-acquired |\n * | --- | --- | --- | --- |\n * | `image` | `copyExternalImageToTexture` | premultiplied | only when dirty |\n * | `video` | `importExternalTexture` | **unpremultiplied** | **every sampling frame** |\n * | `canvas` | `copyExternalImageToTexture` | premultiplied | every frame by default |\n * | `gradient` | `queue.writeTexture` of CPU-generated texels | opaque | never |\n * | `app-texture-view` | the app's own `GPUTexture` | declared by the app | every frame |\n *\n * Two of those cells are WebGPU semantics rather than choices, and §Surprises\n * records them as such: `importExternalTexture` handles **expire at task end**, so\n * a video must be re-imported on every frame that samples it; and imported video\n * arrives **unpremultiplied** while copied images arrive premultiplied. The import\n * pass normalises both to premultiplied linear, so nothing downstream branches on\n * either fact.\n *\n * ## VideoFrame ownership\n *\n * X3: \"`VideoFrame` close ownership held by the provider.\" When the app hands in a\n * `VideoFrame`, this provider closes it in `release()` — after submit, because an\n * imported external texture must outlive the submission that samples it. When the\n * app hands in an `HTMLVideoElement` the browser owns the frames and the provider\n * closes nothing. Getting that backwards leaks decoder buffers until playback\n * stalls, which is why the two cases are separate provider inputs rather than one\n * permissive union.\n *\n * ## Device generations\n *\n * The same WebGPU fact has a second consequence, and it is the one easiest to get\n * wrong: a provider closes over the device it was built with, so when that device\n * dies the provider holds storage nothing can bind and a texture handle nothing\n * will complain about. `invalidate(generation, device)` is how a provider crosses\n * that boundary — new device adopted, old storage dropped, re-import armed — and\n * `generation` is the tag that says which side of it the provider is on. The\n * app-texture provider is the exception on purpose: the renderer cannot re-make\n * someone else's texture, so it refuses rather than binding a foreign-device view\n * that would render nothing and report nothing.\n *\n * ## Validation at registration\n *\n * Also X3: app-supplied views \"must satisfy declared usage/format/dimension\n * requirements — validated at registration with a typed error, never discovered at\n * draw time.\" `registerAppTexture` therefore takes the `GPUTexture`, not just a\n * view: a `GPUTextureView` exposes none of its own properties, so a contract that\n * accepted only a view could not be checked at all.\n */\n\nimport {\n type BackdropAlphaMode,\n type BackdropColorSpace,\n linearToSrgbChannel,\n srgbToLinearChannel,\n} from \"./color\";\nimport { rendererError } from \"./errors\";\n\nexport const BACKDROP_KINDS = [\n \"image\",\n \"video\",\n \"canvas\",\n \"gradient\",\n \"app-texture-view\",\n] as const;\n\nexport type BackdropKind = (typeof BACKDROP_KINDS)[number];\n\n/** How the import pass binds the source. `external` needs its own pipeline. */\nexport type BackdropBinding =\n | { readonly kind: \"sampled\"; readonly view: GPUTextureView }\n | { readonly kind: \"external\"; readonly texture: GPUExternalTexture };\n\nexport interface BackdropFrame {\n readonly sourceId: string;\n readonly binding: BackdropBinding;\n /** Source extent in texture px. */\n readonly width: number;\n readonly height: number;\n /** Bumped when the extent changes; invalidates every dependent allocation. */\n readonly sizeEpoch: number;\n readonly colorSpace: BackdropColorSpace;\n readonly alphaMode: BackdropAlphaMode;\n /** True when the sampled values are sRGB-encoded rather than linear. */\n readonly encoded: boolean;\n}\n\n/** The frame facts a provider is handed. Matches core's `FrameInfo`. */\nexport interface FrameInfoView {\n readonly id: number;\n readonly timeMs: number;\n}\n\nexport interface BackdropProvider {\n readonly id: string;\n readonly kind: BackdropKind;\n /**\n * The device generation this provider's storage belongs to (`device.ts`'s\n * counter). A provider built under one generation holds nothing a later\n * generation can bind, and the failure is silent — so the number is here to be\n * compared, cheaply, before anything of the provider's is used.\n */\n readonly generation: number;\n /** True when content may have changed since the last successful import. */\n isDirty(): boolean;\n /** X3: at frame start. Throws `source-unavailable` if the source cannot serve. */\n acquire(frame: FrameInfoView): BackdropFrame;\n /** X3: after submit. Releases whatever the acquire took ownership of. */\n release(): void;\n /** Called once the import pass has consumed the frame's pixels. */\n markImported(): void;\n /**\n * Adopt `device` at `generation`: the device that built this provider's storage\n * is gone.\n *\n * Every provider closes over the device it was built with, so a reset that only\n * cleared the dirty flags would re-import onto the dead device and hand the new\n * one a foreign texture. Hence the device travels with the call.\n *\n * A provider whose storage the renderer allocated drops it and arms a\n * re-import, so recovery flows through the ordinary dirty path. A provider\n * wrapping the *app's* own texture cannot be re-pointed at all — WebGPU has no\n * cross-device sharing, and the app owns the texture — so it refuses every\n * later `acquire` with a typed error instead of binding a foreign-device view.\n */\n invalidate(generation: number, device: BackdropDevice): void;\n /**\n * Re-declare the source's extent. Implemented where the renderer allocates the\n * storage (image, canvas); absent where the source declares its own size.\n */\n resize?(width: number, height: number): void;\n destroy(): void;\n}\n\n/** Formats the sampling path can read. Everything else is refused at registration. */\nexport const SUPPORTED_APP_TEXTURE_FORMATS: readonly GPUTextureFormat[] = [\n \"rgba8unorm\",\n \"rgba8unorm-srgb\",\n \"bgra8unorm\",\n \"bgra8unorm-srgb\",\n \"rgba16float\",\n \"rgba32float\",\n];\n\n/** The slice of `GPUDevice` the providers need. `GPUDevice` satisfies it as-is. */\nexport interface BackdropDevice {\n readonly queue: GPUQueue;\n readonly limits: GPUSupportedLimits;\n createTexture(descriptor: GPUTextureDescriptor): GPUTexture;\n importExternalTexture(descriptor: GPUExternalTextureDescriptor): GPUExternalTexture;\n}\n\n/** Computed on first use, not at module scope — see the note in `passes.ts`. */\nconst copyUsage = (): GPUTextureUsageFlags =>\n GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT;\n\ninterface SizeTracker {\n epoch: number;\n width: number;\n height: number;\n}\n\nfunction trackSize(tracker: SizeTracker, width: number, height: number): void {\n if (tracker.width === width && tracker.height === height) return;\n tracker.width = width;\n tracker.height = height;\n tracker.epoch += 1;\n}\n\n// ---------------------------------------------------------------------------\n// image and canvas — copyExternalImageToTexture\n// ---------------------------------------------------------------------------\n\n/** Anything `copyExternalImageToTexture` accepts as a source. */\nexport type CopyableSource =\n | ImageBitmap\n | HTMLImageElement\n | HTMLCanvasElement\n | OffscreenCanvas\n | ImageData\n | VideoFrame;\n\nexport interface CopyProviderOptions {\n readonly id: string;\n readonly kind: \"image\" | \"canvas\";\n readonly device: BackdropDevice;\n readonly source: CopyableSource;\n readonly width: number;\n readonly height: number;\n readonly colorSpace?: BackdropColorSpace;\n /**\n * Whether content changes every frame. `true` for a live canvas, `false` for a\n * decoded image — which is what makes a static backdrop rebuild nothing at all\n * (§Core model invariant).\n */\n readonly live?: boolean;\n /** The device generation this provider is being built under. See `BackdropProvider.generation`. */\n readonly generation?: number;\n}\n\nexport function createCopyProvider(options: CopyProviderOptions): BackdropProvider {\n let device = options.device;\n const size = { epoch: 0, width: options.width, height: options.height };\n const live = options.live ?? options.kind === \"canvas\";\n let dirty = true;\n let texture: GPUTexture | undefined;\n let generation = options.generation ?? 0;\n\n const ensureTexture = (): GPUTexture => {\n if (texture !== undefined && texture.width === size.width && texture.height === size.height) {\n return texture;\n }\n texture?.destroy();\n texture = device.createTexture({\n label: `vitrea:backdrop:${options.id}:upload`,\n size: { width: size.width, height: size.height, depthOrArrayLayers: 1 },\n // 8-bit is the honest storage for an image or a canvas: both are 8-bit\n // sources, and the import pass promotes to float on the way into level 0.\n format: \"rgba8unorm\",\n usage: copyUsage(),\n });\n return texture;\n };\n\n return {\n id: options.id,\n kind: options.kind,\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n return dirty || live;\n },\n\n acquire() {\n if (size.width <= 0 || size.height <= 0) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" has a zero extent (${size.width}×${size.height}); nothing can be copied from it.`,\n options.id,\n );\n }\n const target = ensureTexture();\n if (dirty || live) {\n device.queue.copyExternalImageToTexture(\n { source: options.source, flipY: false },\n {\n texture: target,\n colorSpace: options.colorSpace ?? \"srgb\",\n // X3: copied images arrive premultiplied. Declaring it here is what\n // makes that true rather than assumed — the copy performs the multiply\n // when the source is not already premultiplied.\n premultipliedAlpha: true,\n },\n { width: size.width, height: size.height },\n );\n }\n return {\n sourceId: options.id,\n binding: { kind: \"sampled\", view: target.createView() },\n width: size.width,\n height: size.height,\n sizeEpoch: size.epoch,\n colorSpace: options.colorSpace ?? \"srgb\",\n alphaMode: \"premultiplied\",\n encoded: true,\n };\n },\n\n release() {\n // Nothing to release: the destination texture is this provider's own and\n // outlives the frame.\n },\n\n markImported() {\n dirty = false;\n },\n\n invalidate(next, nextDevice) {\n generation = next;\n device = nextDevice;\n // The upload texture belonged to the dead device. Dropping it and arming\n // the dirty flag is the whole recovery: the next acquire allocates on the\n // new device and re-copies, through the same path a content change takes.\n texture?.destroy();\n texture = undefined;\n dirty = true;\n },\n\n resize(width, height) {\n const changed = size.width !== width || size.height !== height;\n trackSize(size, width, height);\n if (changed) dirty = true;\n },\n\n destroy() {\n texture?.destroy();\n texture = undefined;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// video — importExternalTexture\n// ---------------------------------------------------------------------------\n\nexport interface VideoProviderOptions {\n readonly id: string;\n readonly device: BackdropDevice;\n /**\n * Either a live element the browser keeps frames for, or a callback producing a\n * `VideoFrame` this provider then owns and closes. The two are separate because\n * their ownership rules are opposite — see the module note.\n */\n readonly source:\n | { readonly kind: \"element\"; readonly element: HTMLVideoElement }\n | { readonly kind: \"frames\"; readonly next: () => VideoFrame | undefined };\n readonly colorSpace?: BackdropColorSpace;\n /** The device generation this provider is being built under. See `BackdropProvider.generation`. */\n readonly generation?: number;\n}\n\nexport function createVideoProvider(options: VideoProviderOptions): BackdropProvider {\n let device = options.device;\n const size = { epoch: 0, width: 0, height: 0 };\n let ownedFrame: VideoFrame | undefined;\n let acquired = false;\n let generation = options.generation ?? 0;\n\n return {\n id: options.id,\n kind: \"video\",\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n // `importExternalTexture` handles expire at task end, so a video is dirty\n // on every frame that samples it. That is a WebGPU semantic, not a policy.\n return true;\n },\n\n acquire() {\n if (acquired) {\n throw rendererError(\n \"frame-protocol\",\n `Backdrop \"${options.id}\" was acquired twice without a release. X3 pairs one acquire per frame with one release after submit.`,\n options.id,\n );\n }\n\n let source: HTMLVideoElement | VideoFrame;\n if (options.source.kind === \"element\") {\n const element = options.source.element;\n if (element.readyState < 2 || element.videoWidth === 0) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" is a video with no decoded frame yet (readyState ${element.readyState}). Wait for \"loadeddata\" before registering it, or let the group render without a backdrop until it arrives.`,\n options.id,\n );\n }\n trackSize(size, element.videoWidth, element.videoHeight);\n source = element;\n } else {\n const frame = options.source.next();\n if (frame === undefined) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" produced no VideoFrame for this frame.`,\n options.id,\n );\n }\n ownedFrame = frame;\n trackSize(size, frame.displayWidth, frame.displayHeight);\n source = frame;\n }\n\n let texture: GPUExternalTexture;\n try {\n texture = device.importExternalTexture({\n label: `vitrea:backdrop:${options.id}:external`,\n source,\n colorSpace: \"srgb\",\n });\n } catch (error) {\n // The frame is already this provider's to close, and a throw here leaves\n // `acquired` false — so no release is queued and the next acquire would\n // overwrite `ownedFrame`, leaking one decoder buffer per failure until\n // playback stalls. Closing before the rethrow keeps the ownership rule\n // (\"close ownership held by the provider\") true on the failure path too.\n ownedFrame?.close();\n ownedFrame = undefined;\n throw error;\n }\n acquired = true;\n\n return {\n sourceId: options.id,\n binding: { kind: \"external\", texture },\n width: size.width,\n height: size.height,\n sizeEpoch: size.epoch,\n colorSpace: options.colorSpace ?? \"srgb\",\n // X3: imported video arrives UNPREMULTIPLIED.\n alphaMode: \"unpremultiplied\",\n encoded: true,\n };\n },\n\n release() {\n acquired = false;\n // After submit, and only for a frame this provider owns.\n ownedFrame?.close();\n ownedFrame = undefined;\n },\n\n markImported() {\n // A video is dirty again immediately; nothing to record.\n },\n\n invalidate(next, nextDevice) {\n generation = next;\n device = nextDevice;\n // An external texture from the dead device is already gone — imports expire\n // at task end — so all that is owed here is the frame this provider holds\n // and the acquire/release pairing, which the loss interrupted mid-flight.\n ownedFrame?.close();\n ownedFrame = undefined;\n acquired = false;\n },\n\n destroy() {\n ownedFrame?.close();\n ownedFrame = undefined;\n acquired = false;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// gradient — procedural, generated once on the CPU\n// ---------------------------------------------------------------------------\n\nexport interface GradientStop {\n /** 0..1 along the gradient axis. */\n readonly offset: number;\n /** sRGB-encoded 0..1, plus alpha. */\n readonly color: readonly [number, number, number, number];\n}\n\nexport interface GradientProviderOptions {\n readonly id: string;\n readonly device: BackdropDevice;\n readonly stops: readonly GradientStop[];\n /** Gradient direction in the source's own uv space. Defaults to top-to-bottom. */\n readonly direction?: readonly [number, number];\n readonly width?: number;\n readonly height?: number;\n /** The device generation this provider is being built under. See `BackdropProvider.generation`. */\n readonly generation?: number;\n}\n\n/**\n * Generated on the CPU and uploaded once, rather than rendered with a pipeline of\n * its own.\n *\n * A procedural gradient is static by definition, so it rebuilds nothing after the\n * first frame and a whole render pipeline for it would be dead weight in the\n * pipeline cache. Interpolation is in **linear light** and the result is\n * re-encoded, because a gradient interpolated in sRGB has a visible dark band\n * through its middle — the one place where doing the maths in the wrong space is\n * obvious to the eye rather than to a metric.\n */\nexport function createGradientProvider(options: GradientProviderOptions): BackdropProvider {\n const width = Math.max(1, options.width ?? 64);\n const height = Math.max(1, options.height ?? 64);\n const direction = options.direction ?? [0, 1];\n const stops = [...options.stops].sort((a, b) => a.offset - b.offset);\n\n if (stops.length === 0) {\n throw rendererError(\n \"source-unavailable\",\n `Gradient backdrop \"${options.id}\" has no stops.`,\n options.id,\n );\n }\n\n const texels = new Uint8Array(width * height * 4);\n const axisLength = Math.hypot(direction[0], direction[1]) || 1;\n const ax = direction[0] / axisLength;\n const ay = direction[1] / axisLength;\n\n const sample = (t: number): readonly [number, number, number, number] => {\n const clamped = Math.min(1, Math.max(0, t));\n let lower = stops[0] as GradientStop;\n let upper = stops[stops.length - 1] as GradientStop;\n for (let i = 0; i < stops.length - 1; i += 1) {\n const a = stops[i] as GradientStop;\n const b = stops[i + 1] as GradientStop;\n if (clamped >= a.offset && clamped <= b.offset) {\n lower = a;\n upper = b;\n break;\n }\n }\n const span = upper.offset - lower.offset;\n const local = span <= 0 ? 0 : (clamped - lower.offset) / span;\n const mix = (from: number, to: number): number => from + (to - from) * local;\n // Colour channels are decoded, mixed, and re-encoded; alpha is already\n // linear and is mixed as-is. Mixing the encoded values instead puts a\n // visible dark band through the middle of every gradient — the one place\n // where working in the wrong space is obvious to the eye rather than to a\n // metric.\n const channel = (index: 0 | 1 | 2): number =>\n linearToSrgbChannel(\n mix(srgbToLinearChannel(lower.color[index]), srgbToLinearChannel(upper.color[index])),\n );\n return [channel(0), channel(1), channel(2), mix(lower.color[3], upper.color[3])];\n };\n\n for (let y = 0; y < height; y += 1) {\n for (let x = 0; x < width; x += 1) {\n const u = width === 1 ? 0 : x / (width - 1);\n const v = height === 1 ? 0 : y / (height - 1);\n // Project onto the axis and rescale so the endpoints of the projected\n // range land on stops 0 and 1 whatever the direction.\n const t = (u * ax + v * ay + Math.max(0, -ax) + Math.max(0, -ay)) / (Math.abs(ax) + Math.abs(ay) || 1);\n const [r, g, b, a] = sample(t);\n const index = (y * width + x) * 4;\n texels[index + 0] = Math.round(Math.min(1, Math.max(0, r)) * 255);\n texels[index + 1] = Math.round(Math.min(1, Math.max(0, g)) * 255);\n texels[index + 2] = Math.round(Math.min(1, Math.max(0, b)) * 255);\n texels[index + 3] = Math.round(Math.min(1, Math.max(0, a)) * 255);\n }\n }\n\n let texture: GPUTexture | undefined;\n let uploaded = false;\n let device = options.device;\n let generation = options.generation ?? 0;\n\n return {\n id: options.id,\n kind: \"gradient\",\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n return !uploaded;\n },\n\n acquire() {\n texture ??= device.createTexture({\n label: `vitrea:backdrop:${options.id}:gradient`,\n size: { width, height, depthOrArrayLayers: 1 },\n format: \"rgba8unorm\",\n usage: copyUsage(),\n });\n if (!uploaded) {\n device.queue.writeTexture(\n { texture },\n texels,\n { bytesPerRow: width * 4, rowsPerImage: height },\n { width, height },\n );\n }\n return {\n sourceId: options.id,\n binding: { kind: \"sampled\", view: texture.createView() },\n width,\n height,\n sizeEpoch: 0,\n colorSpace: \"srgb\",\n alphaMode: \"premultiplied\",\n encoded: true,\n };\n },\n\n release() {\n // Nothing acquired that needs releasing.\n },\n\n markImported() {\n uploaded = true;\n },\n\n invalidate(next, nextDevice) {\n generation = next;\n device = nextDevice;\n // A gradient is static, so `uploaded` is the only thing standing between it\n // and a silent black backdrop after a loss: without the reset the next\n // acquire hands out a view of a texture the dead device made and never\n // writes the texels again. The pixels themselves are CPU-side and survive.\n texture?.destroy();\n texture = undefined;\n uploaded = false;\n },\n\n destroy() {\n texture?.destroy();\n texture = undefined;\n uploaded = false;\n },\n };\n}\n\n/** Two-stop convenience, in linear light, for tests and for the golden scenes. */\nexport function linearGradientStops(\n from: readonly [number, number, number],\n to: readonly [number, number, number],\n): readonly GradientStop[] {\n const encode = (c: readonly [number, number, number]): readonly [number, number, number, number] =>\n [linearToSrgbChannel(c[0]), linearToSrgbChannel(c[1]), linearToSrgbChannel(c[2]), 1];\n return [\n { offset: 0, color: encode(from) },\n { offset: 1, color: encode(to) },\n ];\n}\n\n// ---------------------------------------------------------------------------\n// app-texture-view — validated at registration\n// ---------------------------------------------------------------------------\n\nexport interface AppTextureProviderOptions {\n readonly id: string;\n readonly device: BackdropDevice;\n /**\n * The app's texture. Required rather than a bare view because a\n * `GPUTextureView` exposes none of its own properties, so a view-only contract\n * could not be validated at all — and X3 requires validation at registration.\n */\n readonly texture: GPUTexture;\n /** Optional pre-made view. One is created per acquire when absent. */\n readonly view?: GPUTextureView;\n readonly colorSpace?: BackdropColorSpace;\n readonly alphaMode?: BackdropAlphaMode;\n /** Whether the app's values are sRGB-encoded. A float target is usually linear. */\n readonly encoded?: boolean;\n /**\n * The device generation the app's texture belongs to. See\n * `BackdropProvider.generation` — this is the number `acquire` refuses against\n * once the renderer has moved on to a later device.\n */\n readonly generation?: number;\n}\n\n/**\n * Validate an app-supplied texture against the sampling path's requirements.\n *\n * Exported separately so a host can check before it registers, and so the checks\n * are testable without a device — every one of them reads only the texture's own\n * declared properties.\n */\nexport function validateAppTexture(\n texture: Pick<GPUTexture, \"width\" | \"height\" | \"format\" | \"usage\" | \"dimension\" | \"depthOrArrayLayers\">,\n limits: Pick<GPUSupportedLimits, \"maxTextureDimension2D\">,\n subject: string,\n): void {\n if (texture.dimension !== \"2d\") {\n throw rendererError(\n \"texture-dimension\",\n `Backdrop \"${subject}\" supplied a ${texture.dimension} texture. The sampling path binds a 2d texture; register a 2d texture or a 2d view of one slice.`,\n subject,\n );\n }\n if (texture.depthOrArrayLayers !== 1) {\n throw rendererError(\n \"texture-dimension\",\n `Backdrop \"${subject}\" supplied a texture with ${texture.depthOrArrayLayers} array layers. Bind a single-layer view.`,\n subject,\n );\n }\n if ((texture.usage & GPUTextureUsage.TEXTURE_BINDING) === 0) {\n throw rendererError(\n \"texture-usage\",\n `Backdrop \"${subject}\" supplied a texture without GPUTextureUsage.TEXTURE_BINDING, so it cannot be sampled. Add TEXTURE_BINDING to the texture's usage when you create it.`,\n subject,\n );\n }\n if (!SUPPORTED_APP_TEXTURE_FORMATS.includes(texture.format)) {\n throw rendererError(\n \"texture-format\",\n `Backdrop \"${subject}\" supplied a \"${texture.format}\" texture. Supported formats are ${SUPPORTED_APP_TEXTURE_FORMATS.join(\", \")}.`,\n subject,\n );\n }\n if (texture.width <= 0 || texture.height <= 0) {\n throw rendererError(\n \"texture-size\",\n `Backdrop \"${subject}\" supplied a ${texture.width}×${texture.height} texture.`,\n subject,\n );\n }\n const max = limits.maxTextureDimension2D;\n if (texture.width > max || texture.height > max) {\n throw rendererError(\n \"texture-size\",\n `Backdrop \"${subject}\" supplied a ${texture.width}×${texture.height} texture, past this adapter's maxTextureDimension2D of ${max}.`,\n subject,\n );\n }\n}\n\nexport function createAppTextureProvider(options: AppTextureProviderOptions): BackdropProvider {\n // Registration-time validation. Throwing here — not at draw time — is the whole\n // point of X3's sentence about app-supplied views.\n validateAppTexture(options.texture, options.device.limits, options.id);\n\n const encoded = options.encoded ?? !options.texture.format.includes(\"float\");\n const size = {\n epoch: 0,\n width: options.texture.width,\n height: options.texture.height,\n };\n\n const builtGeneration = options.generation ?? 0;\n let generation = builtGeneration;\n\n return {\n id: options.id,\n kind: \"app-texture-view\",\n\n get generation() {\n return generation;\n },\n\n isDirty() {\n // The app may redraw into its own texture at any time and the renderer has\n // no way to know. Assuming dirty is the honest default; an app that knows\n // better re-registers with a static source.\n return true;\n },\n\n acquire() {\n // One integer compare, which is the only check available: a\n // `GPUTextureView` carries no evidence of the device that made it, and\n // binding one from a superseded device produces no error the renderer can\n // see — only a pass that quietly renders nothing. X3's \"never discovered at\n // draw time\" cuts the other way here, so the refusal is loud and names the\n // handshake that clears it.\n if (generation !== builtGeneration) {\n throw rendererError(\n \"source-unavailable\",\n `Backdrop \"${options.id}\" wraps a GPUTexture from device generation ${builtGeneration}, and the renderer is now on generation ${generation}. WebGPU has no cross-device texture sharing: unregister this source and register the replacement texture the app made on the new device.`,\n options.id,\n );\n }\n return {\n sourceId: options.id,\n binding: {\n kind: \"sampled\",\n view: options.view ?? options.texture.createView(),\n },\n width: size.width,\n height: size.height,\n sizeEpoch: size.epoch,\n colorSpace: options.colorSpace ?? \"srgb\",\n alphaMode: options.alphaMode ?? \"premultiplied\",\n encoded,\n };\n },\n\n release() {\n // The app owns the texture; the renderer releases nothing.\n },\n\n markImported() {\n // Nothing to record.\n },\n\n invalidate(next) {\n // Nothing to drop and nothing to re-point: the texture is the app's, made\n // on a device this provider does not own. Recording the generation is what\n // turns the next acquire into a refusal.\n generation = next;\n },\n\n destroy() {\n // The app owns the texture; destroying it here would be taking ownership we\n // were never given.\n },\n };\n}\n","/**\n * Device ownership, loss teardown, and rebuild (§GPU device ownership).\n *\n * `platform-web` owns the *browser* half of the story — is there an adapter, get\n * a device, notice when it goes away. This module owns the *resource* half: what\n * has to be thrown away when a device dies, when it is safe to build again, and\n * what core's capability inputs should read while that is in flight.\n *\n * ## The two ownership modes, and why they are not symmetric\n *\n * - **vitrea-owned** — this module can re-request a device by itself, so loss is\n * a transient it recovers from: tear down, re-request, re-attach, rebuild.\n * Every backdrop source is re-imported on the next frame because loss marks\n * them all dirty, which routes recovery through the same\n * one-rebuild-per-dirty-source-per-frame path a content change takes rather\n * than through a special case.\n * - **app-owned** — the app owns the resources that would have to be\n * re-registered, so this module reports the loss, raises\n * `replacementPending`, and **waits**. Groups stay demoted until\n * `replaceDevice` arrives and the re-registration handshake completes. Inventing\n * a device the app did not give us would break the one guarantee app-ownership\n * exists for: that every texture the renderer samples came from the app's own\n * device, because WebGPU has no cross-device sharing.\n *\n * `info.reason === \"destroyed\"` is our own teardown and is not recovered from —\n * re-requesting there would resurrect a renderer the host just destroyed.\n *\n * ## Generations\n *\n * Every attach bumps a generation counter, and every GPU object this package\n * holds is tagged with the generation it was made under. A resource from a lost\n * device is unusable forever, and the failure mode is silent — bindings simply\n * produce nothing — so \"is this from the current device\" has to be a cheap\n * integer comparison somewhere. It is here.\n */\n\nimport { rendererError } from \"./errors\";\n\n/**\n * Structurally identical to `vitrea`'s `WebGPUAvailability` (X2's K1\n * amendment, Decision Log #21c). Declared here rather than imported because this\n * package sits *below* core in the dependency graph — core reaches the renderer\n * through a dynamic import, so an import back would close a cycle. A test pins\n * the two unions to the same members.\n */\nexport type WebGPUAvailability = \"not-requested\" | \"unavailable\" | \"available\";\n\nexport type DeviceOwnership = \"vitrea\" | \"app\";\n\nexport interface RendererDeviceStatus {\n /** Feeds core's `PlatformProbe.webgpu` unchanged. */\n readonly webgpu: WebGPUAvailability;\n readonly deviceHealth: \"ok\" | \"lost\";\n readonly ownership: DeviceOwnership;\n readonly device: GPUDevice | undefined;\n /** Bumped on every attach. Tags every resource built under it. */\n readonly generation: number;\n /** True while an app-owned device is lost and no replacement has arrived. */\n readonly replacementPending: boolean;\n /** Why there is no device, when there is a reason worth reporting. */\n readonly unavailableReason?: \"no-adapter\" | \"device-request-failed\" | \"lost\";\n}\n\n/** The capability facts a host folds into core's `PlatformProbe`. */\nexport interface DeviceCapabilityInput {\n readonly webgpu: WebGPUAvailability;\n readonly deviceHealth: \"ok\" | \"lost\";\n}\n\n/** Run on loss and on teardown. Must be idempotent and must not touch the device. */\nexport type TeardownHook = () => void;\n\nexport interface DeviceHostOptions {\n readonly onStatusChange?: (status: RendererDeviceStatus) => void;\n /** Raised when an app-owned device is lost and only the app can replace it. */\n readonly onReplacementNeeded?: () => void;\n /**\n * Re-request a vitrea-owned device. Absent means \"no automatic recovery\",\n * which is the honest configuration when the host owns the adapter handshake.\n */\n readonly reacquire?: () => Promise<GPUDevice | undefined>;\n}\n\nexport interface DeviceHost {\n readonly status: RendererDeviceStatus;\n readonly capabilityInput: DeviceCapabilityInput;\n /** The current device, or a thrown `device-unavailable` if there is none. */\n requireDevice(): GPUDevice;\n attach(device: GPUDevice, ownership: DeviceOwnership): void;\n /** Hand in a replacement for a lost device. Also clears `replacementPending`. */\n replaceDevice(device: GPUDevice): void;\n /**\n * Record that WebGPU *was* asked for and could not be had. Moves `webgpu` off\n * `\"not-requested\"`, which is the difference K1 exists to preserve.\n */\n markUnavailable(reason: \"no-adapter\" | \"device-request-failed\"): void;\n addTeardownHook(hook: TeardownHook): () => void;\n /** Awaits the in-flight recovery, if any. Test and shutdown seam. */\n settled(): Promise<void>;\n destroy(): void;\n}\n\nexport function createDeviceHost(options: DeviceHostOptions = {}): DeviceHost {\n let status: RendererDeviceStatus = {\n webgpu: \"not-requested\",\n deviceHealth: \"ok\",\n ownership: \"vitrea\",\n device: undefined,\n generation: 0,\n replacementPending: false,\n };\n const hooks = new Set<TeardownHook>();\n let destroyed = false;\n let recovery: Promise<void> | undefined;\n\n const publish = (next: RendererDeviceStatus): void => {\n status = next;\n if (!destroyed) options.onStatusChange?.(status);\n };\n\n const runTeardown = (): void => {\n // A hook that throws must not stop the others: half-torn-down state after a\n // device loss is the one condition from which nothing can recover.\n for (const hook of [...hooks]) {\n try {\n hook();\n } catch {\n // Deliberately swallowed — see above.\n }\n }\n };\n\n const watchLoss = (device: GPUDevice, generation: number): void => {\n void device.lost.then((info) => {\n // A loss from a superseded device is not this device's loss.\n if (destroyed || status.generation !== generation) return;\n\n runTeardown();\n const ownership = status.ownership;\n publish({\n webgpu: \"available\",\n deviceHealth: \"lost\",\n ownership,\n device: undefined,\n generation,\n replacementPending: ownership === \"app\",\n unavailableReason: \"lost\",\n });\n\n if (info.reason === \"destroyed\") return;\n\n if (ownership === \"app\") {\n options.onReplacementNeeded?.();\n return;\n }\n\n const reacquire = options.reacquire;\n if (reacquire === undefined) return;\n recovery = (async () => {\n const replacement = await reacquire();\n // A `destroy()` that lands while the re-request is in flight still has to\n // account for what the re-request produced. Returning without destroying\n // it leaks a whole GPUDevice on the one path where this module IS the\n // owner — the host has no handle to it, because it never learned the\n // reacquire had finished.\n if (destroyed) {\n replacement?.destroy();\n return;\n }\n if (replacement === undefined) return;\n attach(replacement, \"vitrea\");\n })();\n });\n };\n\n function attach(device: GPUDevice, ownership: DeviceOwnership): void {\n const generation = status.generation + 1;\n publish({\n webgpu: \"available\",\n deviceHealth: \"ok\",\n ownership,\n device,\n generation,\n replacementPending: false,\n });\n watchLoss(device, generation);\n }\n\n return {\n get status() {\n return status;\n },\n\n get capabilityInput() {\n return { webgpu: status.webgpu, deviceHealth: status.deviceHealth };\n },\n\n requireDevice() {\n const { device } = status;\n if (device === undefined) {\n throw rendererError(\n \"device-unavailable\",\n status.replacementPending\n ? \"The app-owned GPUDevice was lost and no replacement has been handed in yet. Call replaceDevice() and re-register the app's texture views before drawing again.\"\n : \"No GPUDevice is attached. Attach one (platform-web's WebGPU lifecycle produces it) before building resources or drawing.\",\n );\n }\n return device;\n },\n\n attach,\n\n replaceDevice(device) {\n attach(device, status.ownership);\n },\n\n markUnavailable(reason) {\n publish({\n ...status,\n webgpu: \"unavailable\",\n device: undefined,\n unavailableReason: reason,\n });\n },\n\n addTeardownHook(hook) {\n hooks.add(hook);\n return () => hooks.delete(hook);\n },\n\n async settled() {\n await recovery;\n },\n\n destroy() {\n destroyed = true;\n runTeardown();\n // Only a device this renderer owns is ours to destroy.\n if (status.ownership === \"vitrea\") status.device?.destroy();\n hooks.clear();\n status = { ...status, device: undefined };\n },\n };\n}\n","/**\n * The governor's knobs.\n *\n * §Performance envelope: \"The governor degrades **within** a tier first\n * (refraction resolution, adaptation cadence, edge analysis) and switches tiers\n * only with long hysteresis and cooldown.\" Decision Log #19 adds that intra-tier\n * degradation is **not a state change** — a group under `degrade-in-tier`\n * pressure keeps `activeRenderer: \"webgpu\"` and its whole resolved state.\n *\n * So the split is: **the policy lives in core, the knobs live here.** This module\n * exposes what can be turned and publishes a suggested ladder as *data*; it never\n * decides to turn anything, never reads a clock, and never applies hysteresis.\n * A governor that lived in the renderer would be a governor that could not see\n * the scene it is governing.\n *\n * ## The three knobs, weakest cost first\n *\n * 1. **`fieldFamily`** — `rsupn` → `rsup`. S2 priced this at 29% of the field's\n * cost for a bound that degrades from 0.170 px / 2.91° to 0.574 px / 4.26°.\n * It is the *first* step because it is one uniform and one pipeline: no\n * resolution change, so nothing resamples and nothing shimmers as it engages.\n * **Conditional on the f32 cross-check** (Decision Log #20) — and the check\n * has now been run, so the condition is met. See `FAMILY_C_CROSS_CHECK`.\n * 2. **`refractionResolutionScale`** — the group's **field** targets are\n * rasterised at a fraction of device resolution, and the optics and highlight\n * passes filter them instead of indexing them (`passes.ts`, and the\n * `fieldUpsampled` flag both shaders branch on). Quadratic saving on the pass\n * that evaluates the pseudo-SDF union per pixel per member, and the most\n * visible step, so it comes second.\n *\n * What it does **not** yet do is shrink the optics and highlight passes\n * themselves: those still render at full device resolution into the plane\n * canvases, because rendering them smaller means an offscreen target and a\n * resolve pass rather than a change of extent. So rungs 2 and 3 deliver the\n * field's quadratic saving and the cadence saving, not the full quadratic\n * saving on both heavy passes. Recorded here rather than implied, because a\n * ladder whose rungs are priced for savings they do not deliver is a ladder\n * core's policy will walk too far down.\n * 3. **`adaptationCadenceHz`** — how often analysis is reduced and read back.\n * Cheapest of the three in visual terms because the values it feeds are\n * already low-passed over hundreds of milliseconds; dropping the cadence\n * mostly changes how quickly a scroll's new backdrop is noticed.\n */\n\nexport type FieldFamily = \"rsupn\" | \"rsup\";\n\nexport interface GovernorKnobs {\n /** Which pseudo-SDF family the field pass compiles. */\n readonly fieldFamily: FieldFamily;\n /**\n * Device-resolution fraction the group's field targets are rasterised at,\n * 0 < s <= 1. The optics and highlight passes upsample what they read. See the\n * module note for what this does and does not save.\n */\n readonly refractionResolutionScale: number;\n /** Analysis reduction + readback rate. 0 disables adaptation entirely. */\n readonly adaptationCadenceHz: number;\n}\n\n/**\n * Full fidelity. `adaptationCadenceHz` is core's advisory 15 Hz readback ceiling\n * (Decision Log #19) — the analysis pass has no reason to run faster than the\n * values it produces can be consumed.\n */\nexport const NOMINAL_GOVERNOR: GovernorKnobs = {\n fieldFamily: \"rsupn\",\n refractionResolutionScale: 1,\n adaptationCadenceHz: 15,\n};\n\n/**\n * The suggested intra-tier ladder, as data for core's policy to walk. Each step\n * is cumulative on the one before it, weakest visual cost first.\n */\nexport const GOVERNOR_LADDER: readonly GovernorKnobs[] = [\n NOMINAL_GOVERNOR,\n { fieldFamily: \"rsup\", refractionResolutionScale: 1, adaptationCadenceHz: 15 },\n { fieldFamily: \"rsup\", refractionResolutionScale: 0.75, adaptationCadenceHz: 7.5 },\n { fieldFamily: \"rsup\", refractionResolutionScale: 0.5, adaptationCadenceHz: 4 },\n];\n\n/**\n * Decision Log #20's condition, and its answer.\n *\n * The spec makes family C's shipping \"conditional on C6 running the f32\n * cross-check on its WGSL\". C6 ran it, twice and independently:\n *\n * - **On hardware** (`e2e/gpu/cross-check.spec.ts`, apple/metal-3): the shipped\n * `sd_rsup` kernel against `@vitrea/geometry`'s f64 `rsupField` over 5535\n * points on and around three shapes' contours — **3.042e-5 px max, 0.0053% of\n * the declared 0.574 px bound.** The same run measured family D at 4.073e-5 px\n * / 0.0240%, reproducing S2's own 4.08e-5 / 0.024% on that adapter class,\n * which is what makes the two runs comparable at all.\n * - **In the unit suite** (`test/f32-cross-check.test.ts`): the same arithmetic\n * emulated in f32 through `Math.fround`, so the answer exists on a machine\n * with no adapter. 3.523e-5 px, the same order.\n *\n * So the gate is open by default, and the option below is the opt-out rather than\n * the opt-in. What keeps that honest is that both checks run in CI and that\n * `@vitrea/geometry` fingerprints the kernel strings: editing `sd_rsup` trips the\n * fingerprint test, which says in as many words to re-run the cross-check.\n */\nexport const FAMILY_C_CROSS_CHECK = {\n ran: true,\n adapter: \"apple/metal-3\",\n points: 5535,\n maxAbsDiffPx: 3.042e-5,\n boundPx: 0.574,\n} as const;\n\nexport interface GovernorOptions {\n /**\n * Whether family C's WGSL has been through the f32 cross-check (Decision Log\n * #20). Defaults to `FAMILY_C_CROSS_CHECK.ran` — see above. Pass `false` to\n * hold the governor to family D regardless.\n */\n readonly familyCVerified?: boolean;\n readonly onChange?: (knobs: GovernorKnobs) => void;\n}\n\nexport interface Governor {\n readonly knobs: GovernorKnobs;\n /** True when `fieldFamily: \"rsup\"` is permitted to engage. */\n readonly familyCVerified: boolean;\n set(patch: Partial<GovernorKnobs>): GovernorKnobs;\n /** Move to a rung of the suggested ladder. Out-of-range clamps to the ends. */\n setLevel(level: number): GovernorKnobs;\n reset(): GovernorKnobs;\n /** Record that the cross-check passed, unlocking family C. */\n recordFamilyCVerified(): void;\n}\n\nconst clampScale = (s: number): number => Math.min(1, Math.max(0.125, s));\n\nexport function createGovernor(options: GovernorOptions = {}): Governor {\n let knobs = NOMINAL_GOVERNOR;\n let verified = options.familyCVerified ?? FAMILY_C_CROSS_CHECK.ran;\n\n const apply = (next: GovernorKnobs): GovernorKnobs => {\n const family: FieldFamily = next.fieldFamily === \"rsup\" && !verified ? \"rsupn\" : next.fieldFamily;\n knobs = {\n fieldFamily: family,\n refractionResolutionScale: clampScale(next.refractionResolutionScale),\n adaptationCadenceHz: Math.max(0, next.adaptationCadenceHz),\n };\n options.onChange?.(knobs);\n return knobs;\n };\n\n return {\n get knobs() {\n return knobs;\n },\n\n get familyCVerified() {\n return verified;\n },\n\n set(patch) {\n return apply({ ...knobs, ...patch });\n },\n\n setLevel(level) {\n const index = Math.min(GOVERNOR_LADDER.length - 1, Math.max(0, Math.round(level)));\n return apply(GOVERNOR_LADDER[index] as GovernorKnobs);\n },\n\n reset() {\n return apply(NOMINAL_GOVERNOR);\n },\n\n recordFamilyCVerified() {\n verified = true;\n },\n };\n}\n","/**\n * Shader-module and pipeline caches.\n *\n * Pipeline creation is the single most expensive thing a WebGPU renderer can do\n * per frame, and this renderer's pipeline set is small and fixed: two field\n * families, two import kinds, the chain, the analysis reduction, optics,\n * highlight. So the cache is a plain memo keyed by a descriptor string, and the\n * only interesting part is what goes into that key.\n *\n * Two rules about keys, both learned the same way — a cache that returns a\n * pipeline compiled against a different target format fails at draw time with an\n * error that names neither the format nor the cache:\n *\n * - **Every property that changes the compiled artefact is in the key.** Target\n * format, blend state, and the entry points, not just the shader name.\n * - **Nothing else is.** Uniform *values* never are; they travel in buffers. A\n * key that grew a tint colour would make the cache a leak.\n *\n * Like the texture pool, this is written over the narrow slice of `GPUDevice` it\n * uses, so eviction and key discipline are testable without an adapter.\n */\n\n/** The slice of `GPUDevice` the caches need. `GPUDevice` satisfies it as-is. */\nexport interface PipelineFactory {\n createShaderModule(descriptor: GPUShaderModuleDescriptor): GPUShaderModule;\n createRenderPipeline(descriptor: GPURenderPipelineDescriptor): GPURenderPipeline;\n createComputePipeline(descriptor: GPUComputePipelineDescriptor): GPUComputePipeline;\n}\n\nexport interface PipelineCacheStats {\n readonly modules: number;\n readonly renderPipelines: number;\n readonly computePipelines: number;\n readonly hits: number;\n readonly misses: number;\n}\n\nexport interface PipelineCache {\n readonly stats: PipelineCacheStats;\n module(key: string, source: () => string): GPUShaderModule;\n renderPipeline(key: string, describe: () => GPURenderPipelineDescriptor): GPURenderPipeline;\n computePipeline(key: string, describe: () => GPUComputePipelineDescriptor): GPUComputePipeline;\n clear(): void;\n}\n\nexport function createPipelineCache(factory: PipelineFactory): PipelineCache {\n const modules = new Map<string, GPUShaderModule>();\n const renderPipelines = new Map<string, GPURenderPipeline>();\n const computePipelines = new Map<string, GPUComputePipeline>();\n let hits = 0;\n let misses = 0;\n\n function memo<T>(store: Map<string, T>, key: string, make: () => T): T {\n const existing = store.get(key);\n if (existing !== undefined) {\n hits += 1;\n return existing;\n }\n misses += 1;\n const made = make();\n store.set(key, made);\n return made;\n }\n\n return {\n get stats() {\n return {\n modules: modules.size,\n renderPipelines: renderPipelines.size,\n computePipelines: computePipelines.size,\n hits,\n misses,\n };\n },\n\n module(key, source) {\n return memo(modules, key, () => factory.createShaderModule({ label: key, code: source() }));\n },\n\n renderPipeline(key, describe) {\n return memo(renderPipelines, key, () => factory.createRenderPipeline(describe()));\n },\n\n computePipeline(key, describe) {\n return memo(computePipelines, key, () => factory.createComputePipeline(describe()));\n },\n\n clear() {\n // GPU pipelines and modules have no explicit destroy: dropping the last\n // reference is the release. Clearing the maps IS the teardown, and it has to\n // happen on device loss because objects from a lost device stay unusable\n // forever.\n modules.clear();\n renderPipelines.clear();\n computePipelines.clear();\n },\n };\n}\n\n/** Pipeline keys, so the \"everything that changes the artefact\" rule is visible. */\nexport const pipelineKey = {\n field: (family: string, format: GPUTextureFormat): string => `field:${family}:${format}`,\n import: (kind: string, format: GPUTextureFormat): string => `import:${kind}:${format}`,\n chain: (entry: string, format: GPUTextureFormat): string => `chain:${entry}:${format}`,\n analysis: (): string => \"analysis\",\n optics: (format: GPUTextureFormat, blend: string): string => `optics:${format}:${blend}`,\n highlight: (format: GPUTextureFormat, blend: string): string => `highlight:${format}:${blend}`,\n} as const;\n","/**\n * The texture pool, with size-epoch invalidation.\n *\n * §GPU device ownership: \"Resizes bump a size epoch that invalidates dependent\n * pyramid allocations.\" Two properties follow from taking that literally, and\n * both are what the pool exists for:\n *\n * - **A texture is keyed by purpose, not by shape.** Callers ask for\n * `\"pyramid:bg-video:level-2\"`, not for \"a 512×256 rgba16float\". So a resize\n * replaces an allocation in place rather than leaking a second one beside it,\n * and the leak is impossible rather than unlikely.\n * - **The epoch is compared, not the size.** A texture allocated under an older\n * epoch is destroyed even when its dimensions happen to match, because a size\n * epoch also covers DPR changes and resolution-policy changes that leave the\n * pixel count alone. Comparing sizes would silently keep a texture whose\n * *meaning* changed.\n *\n * The pool is written over a two-method `TextureAllocator` rather than against\n * `GPUDevice` directly. That is not indirection for its own sake: it makes the\n * keying, the epoch sweep, and the destroy-exactly-once accounting testable\n * without a GPU, which is the half of this file most likely to harbour a leak.\n */\n\nexport interface TextureRequest {\n readonly width: number;\n readonly height: number;\n readonly format: GPUTextureFormat;\n readonly usage: GPUTextureUsageFlags;\n /** Mip levels. The blur chain is the only caller that asks for more than one. */\n readonly mipLevelCount?: number;\n readonly label?: string;\n}\n\n/** The slice of `GPUDevice` the pool needs. `GPUDevice` satisfies it as-is. */\nexport interface TextureAllocator {\n createTexture(descriptor: GPUTextureDescriptor): GPUTexture;\n}\n\ninterface PoolEntry {\n readonly texture: GPUTexture;\n readonly request: TextureRequest;\n readonly epoch: number;\n}\n\nexport interface TexturePoolStats {\n readonly live: number;\n readonly created: number;\n readonly destroyed: number;\n readonly reused: number;\n readonly epoch: number;\n}\n\nexport interface TexturePool {\n readonly sizeEpoch: number;\n readonly stats: TexturePoolStats;\n /**\n * The texture for `key` at the current epoch, allocating or reallocating as\n * needed. Two calls with the same key and the same request in one epoch return\n * the same texture.\n */\n acquire(key: string, request: TextureRequest): GPUTexture;\n /** The texture for `key`, or undefined if nothing is allocated under it. */\n peek(key: string): GPUTexture | undefined;\n release(key: string): void;\n /** Bump the size epoch. Nothing is destroyed until the next `acquire` or `sweep`. */\n bumpSizeEpoch(): number;\n /** Destroy everything allocated under an older epoch. */\n sweep(): number;\n /** Destroy everything. Used by device-loss teardown and by `destroy`. */\n clear(): void;\n}\n\nconst sameShape = (a: TextureRequest, b: TextureRequest): boolean =>\n a.width === b.width &&\n a.height === b.height &&\n a.format === b.format &&\n a.usage === b.usage &&\n (a.mipLevelCount ?? 1) === (b.mipLevelCount ?? 1);\n\nexport function createTexturePool(allocator: TextureAllocator): TexturePool {\n const entries = new Map<string, PoolEntry>();\n let epoch = 0;\n let created = 0;\n let destroyed = 0;\n let reused = 0;\n\n const destroy = (entry: PoolEntry): void => {\n entry.texture.destroy();\n destroyed += 1;\n };\n\n return {\n get sizeEpoch() {\n return epoch;\n },\n\n get stats() {\n return { live: entries.size, created, destroyed, reused, epoch };\n },\n\n acquire(key, request) {\n const existing = entries.get(key);\n if (existing !== undefined) {\n if (existing.epoch === epoch && sameShape(existing.request, request)) {\n reused += 1;\n return existing.texture;\n }\n destroy(existing);\n }\n\n const texture = allocator.createTexture({\n size: {\n width: Math.max(1, Math.floor(request.width)),\n height: Math.max(1, Math.floor(request.height)),\n depthOrArrayLayers: 1,\n },\n format: request.format,\n usage: request.usage,\n mipLevelCount: request.mipLevelCount ?? 1,\n ...(request.label === undefined ? {} : { label: request.label }),\n });\n created += 1;\n entries.set(key, { texture, request, epoch });\n return texture;\n },\n\n peek(key) {\n return entries.get(key)?.texture;\n },\n\n release(key) {\n const entry = entries.get(key);\n if (entry === undefined) return;\n destroy(entry);\n entries.delete(key);\n },\n\n bumpSizeEpoch() {\n epoch += 1;\n return epoch;\n },\n\n sweep() {\n let swept = 0;\n for (const [key, entry] of [...entries]) {\n if (entry.epoch === epoch) continue;\n destroy(entry);\n entries.delete(key);\n swept += 1;\n }\n return swept;\n },\n\n clear() {\n for (const entry of entries.values()) destroy(entry);\n entries.clear();\n },\n };\n}\n\n/** Pool keys, in one place so a typo is a compile error rather than a leak. */\nexport const poolKey = {\n backdropLevel0: (sourceId: string): string => `backdrop:${sourceId}:level0`,\n backdropChain: (sourceId: string): string => `backdrop:${sourceId}:chain`,\n backdropChainScratch: (sourceId: string, level: number): string =>\n `backdrop:${sourceId}:chain-scratch:${level}`,\n backdropBody: (sourceId: string): string => `backdrop:${sourceId}:body`,\n backdropBodyScratch: (sourceId: string): string => `backdrop:${sourceId}:body-scratch`,\n backdropUpload: (sourceId: string): string => `backdrop:${sourceId}:upload`,\n groupField: (groupId: string): string => `group:${groupId}:field`,\n groupAux: (groupId: string): string => `group:${groupId}:aux`,\n} as const;\n","/**\n * Everything that belongs to one device generation, in one object.\n *\n * A device loss makes every GPU object made from that device permanently\n * unusable, and the failure is *silent* — bindings simply stop producing pixels.\n * So the pool, the pipeline cache, the samplers and the uniform buffers are held\n * together with the generation they were made under, and recovery replaces the\n * whole context rather than reaching into it. That makes \"did I just bind a\n * resource from a dead device\" impossible to get wrong instead of merely unlikely.\n */\n\nimport { createPipelineCache, type PipelineCache } from \"./pipeline-cache\";\nimport { createTexturePool, type TexturePool } from \"./texture-pool\";\n\nexport interface GpuContext {\n readonly device: GPUDevice;\n /** The device generation this context belongs to. */\n readonly generation: number;\n readonly pool: TexturePool;\n readonly cache: PipelineCache;\n /** Linear min/mag with linear mip filtering — the pyramid's sampler. */\n readonly chainSampler: GPUSampler;\n /** Linear min/mag, no mips — the body blur and import samplers. */\n readonly flatSampler: GPUSampler;\n destroy(): void;\n}\n\nexport function createGpuContext(device: GPUDevice, generation: number): GpuContext {\n const pool = createTexturePool(device);\n const cache = createPipelineCache(device);\n\n // Clamp-to-edge on every axis. A repeating pyramid would wrap the backdrop\n // across the refraction offset at a group's edge, which reads as a hard seam\n // exactly where the lens is strongest.\n const chainSampler = device.createSampler({\n label: \"vitrea:sampler:chain\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n mipmapFilter: \"linear\",\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n });\n\n const flatSampler = device.createSampler({\n label: \"vitrea:sampler:flat\",\n magFilter: \"linear\",\n minFilter: \"linear\",\n addressModeU: \"clamp-to-edge\",\n addressModeV: \"clamp-to-edge\",\n });\n\n return {\n device,\n generation,\n pool,\n cache,\n chainSampler,\n flatSampler,\n destroy() {\n pool.clear();\n cache.clear();\n },\n };\n}\n\n/** A uniform buffer sized to a fixed float count, reused across frames. */\nexport interface UniformSlot {\n readonly buffer: GPUBuffer;\n readonly data: Float32Array;\n write(): void;\n}\n\nexport function createUniformSlot(\n device: GPUDevice,\n floats: number,\n label: string,\n): UniformSlot {\n // Uniform buffers must be a multiple of 16 bytes, and every struct in this\n // package is laid out as vec4 rows precisely so this rounding never silently\n // truncates a member.\n const size = Math.ceil((floats * 4) / 16) * 16;\n const buffer = device.createBuffer({\n label,\n size,\n usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,\n });\n const data = new Float32Array(size / 4);\n return {\n buffer,\n data,\n write() {\n device.queue.writeBuffer(buffer, 0, data.buffer, data.byteOffset, data.byteLength);\n },\n };\n}\n\n/** A storage buffer that grows in place when the instance count outgrows it. */\nexport interface StorageSlot {\n readonly buffer: GPUBuffer;\n ensure(byteLength: number): GPUBuffer;\n write(data: Float32Array, floatCount: number): void;\n destroy(): void;\n}\n\nexport function createStorageSlot(\n device: GPUDevice,\n initialBytes: number,\n label: string,\n): StorageSlot {\n let capacity = Math.max(initialBytes, 256);\n let buffer = device.createBuffer({\n label,\n size: capacity,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n });\n\n return {\n get buffer() {\n return buffer;\n },\n ensure(byteLength) {\n if (byteLength <= capacity) return buffer;\n buffer.destroy();\n // Grow in powers of two: a group that gains one surface per frame during a\n // morph would otherwise reallocate every frame.\n capacity = 1 << Math.ceil(Math.log2(byteLength));\n buffer = device.createBuffer({\n label,\n size: capacity,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,\n });\n return buffer;\n },\n write(data, floatCount) {\n device.queue.writeBuffer(buffer, 0, data.buffer, data.byteOffset, floatCount * 4);\n },\n destroy() {\n buffer.destroy();\n },\n };\n}\n","/**\n * What the renderer consumes each frame, and why it is declared here rather than\n * imported from `vitrea`.\n *\n * The renderer sits **below** core in the dependency graph: core reaches it\n * through a dynamic import (X7's lazy seam), so importing core back would close a\n * cycle that neither `pnpm -r build` nor `tsc` can order. The types below are\n * therefore declared as the *minimal structural contract* the renderer reads, and\n * core's own types satisfy them without an adapter — `SceneResolution`,\n * `FrameContext` and `FrameParticipant` are assignable to the views here, which\n * `test/core-contract.test.ts` asserts against core's real modules.\n *\n * Two things genuinely do not come from core, and both are flagged as\n * parent-impact rather than papered over:\n *\n * - **The corner reference.** `GlassNodeDescriptor` carries `shapeFamily` and\n * the X8 channel vector but not which of the two corner references the shape\n * is fit against (Decision Log #22a made those two separate references, not\n * one axis). It defaults to `\"apple-continuous\"`, which is what the public\n * `profile: \"continuous\"` — the default — resolves to.\n * - **The concentric parent link.** X8 rider 2 binds the renderer to draw a\n * concentric child as a level set *of its parent's field*, which needs to know\n * which surface the parent is. core's node descriptor has no parent edge, so it\n * arrives as a render input.\n *\n * Interaction values arrive as **numbers**, never as time. §Motion puts the\n * drivers on the CPU and the spec is explicit that this package consumes their\n * outputs; there is no clock anywhere in this package for the same reason there is\n * none in core.\n */\n\nimport type {\n CornerReference,\n GroupUnionParams,\n ShapeChannels,\n ShapeFamily,\n} from \"@vitrea/geometry\";\n\nimport type { MaterialPolicyView, MaterialVariant, RefractionQuality } from \"./material\";\n\n/** Viewport-space rectangle in CSS px. Matches core's `Rect`. */\nexport interface Rect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/** Motion-driver outputs for one surface. Every one is a value, never a time. */\nexport interface SurfaceChannels {\n /** `pressCompression`, 0..1. Scaled by motion's `pressCompressionScale`. */\n readonly press: number;\n /** `glow`, 0..1, from the fast-attack / slow-decay driver. */\n readonly glow: number;\n /** Specular sweep position, 0..1 around the contour. */\n readonly sweep: number;\n /** `lensStrength`, 0..1. Multiplies the resolved refraction scale. */\n readonly lensStrength: number;\n /** Press point in viewport CSS px. Defaults to the surface's centre. */\n readonly pressPoint?: readonly [number, number];\n}\n\nexport const IDLE_CHANNELS: SurfaceChannels = {\n press: 0,\n glow: 0,\n sweep: 0,\n lensStrength: 1,\n};\n\nexport interface SurfaceInput {\n readonly nodeId: string;\n readonly family: ShapeFamily;\n /** X8, in viewport CSS px. `centre` is the surface's centre, `size` its full extent. */\n readonly shape: ShapeChannels;\n /** Defaults to `\"apple-continuous\"` — see the module note. */\n readonly reference?: CornerReference;\n readonly variant?: MaterialVariant;\n readonly channels?: Partial<SurfaceChannels>;\n /**\n * X8 rider 2. When present this surface renders as `parentField + inset`, and\n * the parent must be declared in the same group — as a member, or as a\n * `fieldReferenceOnly` shape.\n */\n readonly concentricOf?: { readonly nodeId: string; readonly inset: number };\n /**\n * Declared so a concentric child can be a level set of it, but not itself\n * drawn.\n *\n * This exists because of what a union is: a concentric child's field is its\n * parent's plus a positive inset, so inside the parent the child is always the\n * larger value and `min` discards it. A child nested in the same union as its\n * parent is therefore invisible *by construction* — correct, and not what an\n * inset indicator inside a segmented control's track wants. There, the track\n * and the indicator are separate surfaces with separate material, and the\n * indicator's group needs the track's geometry only as the field its own\n * contour is offset from.\n */\n readonly fieldReferenceOnly?: boolean;\n}\n\nexport interface GroupRenderInput {\n readonly groupId: string;\n readonly surfaces: readonly SurfaceInput[];\n /** The backdrop source to sample. Absent means the group draws with no backdrop. */\n readonly backdropSourceId?: string;\n /** X2's resolved refraction quality for this group. Half of the dual cap. */\n readonly refraction: RefractionQuality;\n /** True where X2 resolved `analysis: \"exact\"`; gates adaptive tint. */\n readonly analysisExact: boolean;\n readonly variant?: MaterialVariant;\n /** Overrides the calibration-delegated union defaults. */\n readonly union?: GroupUnionParams;\n}\n\n/** The whole frame's render input. */\nexport interface FrameRenderInput {\n readonly groups: readonly GroupRenderInput[];\n /** The other half of the dual cap. Defaults to the nominal policy. */\n readonly accessibility?: MaterialPolicyView;\n}\n\n/**\n * The structural view of core's `SceneResolution` the renderer reads, so a host\n * can hand core's own object straight through.\n */\nexport interface SceneResolutionView {\n readonly groups: readonly {\n readonly groupId: string;\n readonly state: {\n readonly refraction: RefractionQuality;\n readonly analysis: \"exact\" | \"hint\" | \"none\";\n readonly samplingBackend: \"gpu-texture\" | \"css-backdrop\" | \"none\";\n };\n }[];\n readonly accessibility: { readonly material: MaterialPolicyView };\n}\n\n/** The structural view of core's `BackdropRebuildRequest`. */\nexport interface RebuildRequestView {\n readonly sourceId: string;\n readonly epoch: number;\n readonly resolution: { readonly scale: number; readonly maxDimension: number };\n readonly groupIds: readonly string[];\n}\n\n/** The structural view of core's `FrameContext`. */\nexport interface FrameContextView {\n readonly frame: { readonly id: number; readonly timeMs: number };\n readonly phase: \"collect\" | \"read\" | \"update\" | \"write\" | \"render\";\n readonly resolution?: SceneResolutionView;\n consumeDirtyBackdropSources(): readonly RebuildRequestView[];\n}\n\n/** The structural view of core's `FrameParticipant`. */\nexport interface FrameParticipantView {\n readonly id: string;\n readonly write?: (context: FrameContextView) => void;\n readonly render?: (context: FrameContextView) => void;\n}\n","/**\n * Instance packing: X8's channel vector plus the six derived floats, into the\n * storage buffer the field pass walks.\n *\n * ## X8 rider 2, made unavoidable\n *\n * The rider (tightened at C3's landing, Decision Log #22b) says a renderer MUST\n * draw a concentric child as a **level set of the parent's field**, because\n * instantiating the child as its own resolved shape adds an offset-approximation\n * error that grows with inset — 0.326 px at 8 px, past the field's own declared\n * bound, and dominant past about 4 px.\n *\n * The way that is honoured here is not a check: a concentric surface is packed\n * with its **parent's** `half/re/k` and its own `inset`, and the shader's only\n * expression is `field(p; those params) + inset`. There is no instantiated-shape\n * path to take, so no future caller can take it by accident. `resolveConcentric`\n * — geometry's other path — is still the right answer for bounds and hit-testing,\n * and this module uses it for exactly that and nothing else.\n *\n * ## Press compression\n *\n * §Motion: \"The `pressCompression` channel runs 0…1; this is what 1 means, so the\n * renderer needs no constant of its own.\" So the scale comes from\n * `DEFAULT_MOTION_PROFILE.pressCompressionScale` rather than from a literal here,\n * and it is applied to `size` before the corner is derived — which matters,\n * because the corner budget is a function of size, so a compressed surface must\n * re-derive its corner rather than scale a corner derived at rest.\n */\n\nimport {\n DEFAULT_GROUP_UNION,\n type FieldParams,\n fieldParams,\n governorFieldParams,\n type GroupUnionParams,\n resolveConcentric,\n resolveFromChannels,\n type ResolvedShape,\n type ShapeChannels,\n} from \"@vitrea/geometry\";\nimport { DEFAULT_MOTION_PROFILE } from \"@vitrea/motion\";\n\nimport { rendererError } from \"./errors\";\nimport type { FieldFamily } from \"./governor\";\nimport { DEFAULT_MATERIAL_PROFILE, lensDepthPx, type MaterialProfile } from \"./material\";\nimport { IDLE_CHANNELS, type GroupRenderInput, type Rect, type SurfaceChannels, type SurfaceInput } from \"./render-model\";\n\n/** 16 floats, 64 bytes, matching `WGSL_INSTANCE_STRUCT`. */\nexport const INSTANCE_FLOATS = 16;\nexport const INSTANCE_BYTES = INSTANCE_FLOATS * 4;\n\nexport interface ResolvedSurface {\n readonly nodeId: string;\n /** The surface's own resolved shape — bounds, hit-testing, and the rim's scale. */\n readonly shape: ResolvedShape;\n /** The field parameters actually packed: the parent's, for a concentric child. */\n readonly field: FieldParams;\n /** Level-set offset. 0 for an ordinary surface. */\n readonly inset: number;\n readonly centre: readonly [number, number];\n readonly channels: SurfaceChannels;\n /** Shorter extent in CSS px — what the lens's size gain is a function of. */\n readonly spanPx: number;\n readonly lensDepthPx: number;\n}\n\nconst channelsOf = (input: SurfaceInput): SurfaceChannels => ({\n ...IDLE_CHANNELS,\n ...input.channels,\n});\n\n/** `size` after press compression, which the corner is then derived from. */\nfunction compressedChannels(shape: ShapeChannels, press: number): ShapeChannels {\n if (press <= 0) return shape;\n const scale = 1 - Math.min(1, Math.max(0, press)) * DEFAULT_MOTION_PROFILE.pressCompressionScale;\n return { ...shape, size: [shape.size[0] * scale, shape.size[1] * scale] };\n}\n\n/**\n * Resolve one group's surfaces, ordered so that a concentric child always follows\n * its parent. The order matters only for the resolution pass, not for the union —\n * `smoothUnion2` is commutative, which `union.ts` asserts rather than assumes.\n */\nexport function resolveSurfaces(\n group: GroupRenderInput,\n family: FieldFamily,\n profile: MaterialProfile = DEFAULT_MATERIAL_PROFILE,\n): readonly ResolvedSurface[] {\n const byId = new Map<string, SurfaceInput>();\n for (const surface of group.surfaces) {\n if (byId.has(surface.nodeId)) {\n throw rendererError(\n \"source-identity\",\n `Group \"${group.groupId}\" lists surface \"${surface.nodeId}\" twice.`,\n surface.nodeId,\n );\n }\n byId.set(surface.nodeId, surface);\n }\n\n const resolvedShapes = new Map<string, ResolvedShape>();\n const resolving = new Set<string>();\n const resolveShapeOf = (surface: SurfaceInput): ResolvedShape => {\n const cached = resolvedShapes.get(surface.nodeId);\n if (cached !== undefined) return cached;\n if (resolving.has(surface.nodeId)) {\n throw rendererError(\n \"pass-input\",\n `Concentric surfaces in group \"${group.groupId}\" form a cycle through \"${surface.nodeId}\". A level set needs a parent field that resolves without it.`,\n surface.nodeId,\n );\n }\n resolving.add(surface.nodeId);\n\n const channels = channelsOf(surface);\n const reference = surface.reference ?? \"apple-continuous\";\n\n if (surface.concentricOf === undefined) {\n const shape = resolveFromChannels(\n compressedChannels(surface.shape, channels.press),\n reference,\n surface.family,\n { devMode: false },\n );\n resolvedShapes.set(surface.nodeId, shape);\n resolving.delete(surface.nodeId);\n return shape;\n }\n\n const parentInput = byId.get(surface.concentricOf.nodeId);\n if (parentInput === undefined) {\n throw rendererError(\n \"pass-input\",\n `Surface \"${surface.nodeId}\" is concentric to \"${surface.concentricOf.nodeId}\", which is not a member of group \"${group.groupId}\". X8 rider 2 renders a concentric child as a level set of its parent's field, so the parent has to be in the same field pass.`,\n surface.nodeId,\n );\n }\n // The child's OWN resolved shape, for bounds and hit-testing only. What gets\n // packed is the parent's field plus the inset — see the module note.\n const shape = resolveConcentric(resolveShapeOf(parentInput), {\n inset: surface.concentricOf.inset,\n }).shape;\n resolvedShapes.set(surface.nodeId, shape);\n resolving.delete(surface.nodeId);\n return shape;\n };\n\n const paramsFor = (shape: ResolvedShape): FieldParams =>\n family === \"rsup\" ? governorFieldParams(shape) : fieldParams(shape);\n\n // Reference shapes are resolved (a child needs its parent's field) and then\n // dropped: they contribute no instance, no bounds, and no coverage.\n return group.surfaces\n .filter((surface) => surface.fieldReferenceOnly !== true)\n .map((surface): ResolvedSurface => {\n const channels = channelsOf(surface);\n const shape = resolveShapeOf(surface);\n\n const fieldSource =\n surface.concentricOf === undefined\n ? shape\n : resolveShapeOf(byId.get(surface.concentricOf.nodeId) as SurfaceInput);\n const inset = surface.concentricOf?.inset ?? 0;\n\n const spanPx = Math.min(shape.channels.size[0], shape.channels.size[1]);\n return {\n nodeId: surface.nodeId,\n shape,\n field: paramsFor(fieldSource),\n inset,\n centre: [fieldSource.channels.center[0], fieldSource.channels.center[1]],\n channels,\n spanPx,\n lensDepthPx: lensDepthPx(shape.channels.thickness, spanPx, profile),\n };\n });\n}\n\n/**\n * The group's field-pass rect, in viewport CSS px.\n *\n * Padded by whatever can reach beyond a surface's own contour: the rim band, the\n * union's bulge cap, and one coverage pixel. Not padded by the lens depth — the\n * lens displaces where the backdrop is *sampled from*, not where the material is\n * *drawn*, so paying for it here would widen every group's field pass for nothing.\n */\nexport function groupFieldRect(\n surfaces: readonly ResolvedSurface[],\n union: GroupUnionParams = DEFAULT_GROUP_UNION,\n rimWidthPx = 2,\n): Rect {\n if (surfaces.length === 0) return { x: 0, y: 0, width: 0, height: 0 };\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n\n for (const surface of surfaces) {\n const [cx, cy] = surface.shape.channels.center;\n const [w, h] = surface.shape.channels.size;\n minX = Math.min(minX, cx - w / 2);\n minY = Math.min(minY, cy - h / 2);\n maxX = Math.max(maxX, cx + w / 2);\n maxY = Math.max(maxY, cy + h / 2);\n }\n\n const pad = rimWidthPx + union.maxBulge + 1;\n return {\n x: minX - pad,\n y: minY - pad,\n width: maxX - minX + 2 * pad,\n height: maxY - minY + 2 * pad,\n };\n}\n\n/** A rectangle in whole device pixels: what a viewport and a scissor take. */\nexport interface DevicePixelRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * A group's field rect in device pixels, clipped to the plane canvas.\n *\n * `groupFieldRect` grows the surface union by the rim and bulge margin, so a\n * surface within a few CSS px of the viewport's top or left edge produces a rect\n * with a negative origin. The optics and highlight passes set that rect as the\n * canvas viewport *and* scissor, and `setScissorRect` takes unsigned values, so an\n * unclipped rect is a hard `RangeError` out of the WebGPU binding rather than a\n * clipped draw. A toolbar pinned to the left edge is enough to reach it.\n *\n * Returns `undefined` where nothing of the rect is on the canvas, which is the\n * caller's signal to skip the group entirely.\n *\n * The caller must derive the instance frame from the returned rect rather than\n * from the CSS rect it passed in. The field texture is allocated at this size and\n * `fs_optics` reads it by `uv` over the viewport, so a viewport that moved without\n * the texture and the instance origin moving with it would stretch the glass\n * instead of clipping it. What clipping costs is the part of the field outside the\n * canvas, which is the part nothing can see.\n */\nexport function clipFieldRectToCanvas(\n snapped: Rect,\n devicePixelRatio: number,\n canvasDevice: readonly [number, number],\n): DevicePixelRect | undefined {\n const left = Math.max(0, Math.round(snapped.x * devicePixelRatio));\n const top = Math.max(0, Math.round(snapped.y * devicePixelRatio));\n const right = Math.min(\n canvasDevice[0],\n Math.round((snapped.x + snapped.width) * devicePixelRatio),\n );\n const bottom = Math.min(\n canvasDevice[1],\n Math.round((snapped.y + snapped.height) * devicePixelRatio),\n );\n if (right <= left || bottom <= top) return undefined;\n return { x: left, y: top, width: right - left, height: bottom - top };\n}\n\n/** The same rect snapped outward to whole device pixels. */\nexport function snapRectToDevicePixels(rect: Rect, devicePixelRatio: number): Rect {\n const x = Math.floor(rect.x * devicePixelRatio) / devicePixelRatio;\n const y = Math.floor(rect.y * devicePixelRatio) / devicePixelRatio;\n const right = Math.ceil((rect.x + rect.width) * devicePixelRatio) / devicePixelRatio;\n const bottom = Math.ceil((rect.y + rect.height) * devicePixelRatio) / devicePixelRatio;\n return { x, y, width: Math.max(right - x, 0), height: Math.max(bottom - y, 0) };\n}\n\n/**\n * Pack resolved surfaces into the storage buffer, with centres made relative to\n * the group's rect so the shader's coordinates stay small however far down a long\n * page the group sits — f32 loses resolution at large magnitudes, and a field\n * evaluated at y = 40000 would quantise its own corner.\n */\nexport function packInstances(\n surfaces: readonly ResolvedSurface[],\n origin: readonly [number, number],\n into?: Float32Array,\n): { readonly data: Float32Array; readonly count: number } {\n const needed = Math.max(surfaces.length, 1) * INSTANCE_FLOATS;\n const data =\n into !== undefined && into.length >= needed ? into : new Float32Array(needed);\n\n for (let i = 0; i < surfaces.length; i += 1) {\n const s = surfaces[i] as ResolvedSurface;\n const o = i * INSTANCE_FLOATS;\n data[o + 0] = s.centre[0] - origin[0];\n data[o + 1] = s.centre[1] - origin[1];\n data[o + 2] = s.field.halfW;\n data[o + 3] = s.field.halfH;\n data[o + 4] = s.field.reach;\n data[o + 5] = s.field.k[0];\n data[o + 6] = s.field.k[1];\n data[o + 7] = s.field.k[2];\n data[o + 8] = s.field.k[3];\n data[o + 9] = s.field.k[4];\n data[o + 10] = s.inset;\n data[o + 11] = s.shape.channels.thickness;\n data[o + 12] = s.channels.press;\n data[o + 13] = s.channels.glow;\n // The shader's `lensDepth` slot: the size-parameterised depth from\n // `material.ts`, already scaled by the `lensStrength` motion channel, so the\n // fragment stage multiplies nothing it could get wrong.\n data[o + 14] = s.lensDepthPx * Math.min(1, Math.max(0, s.channels.lensStrength));\n data[o + 15] = 0;\n }\n\n return { data, count: surfaces.length };\n}\n","/**\n * Pass-by-pass timing, for the benchmark §Performance envelope pins the ~2 ms\n * hypothesis to.\n *\n * The spec asks for the budget to be \"measured per pass (backdrop import, blur,\n * analysis, body, highlight, composite) alongside browser end-to-end frame time\",\n * which needs GPU-side timestamps: wall-clock around `submit()` measures the\n * queue, not the work. WebGPU's only timestamp mechanism is `timestampWrites` on\n * a pass descriptor — `encoder.writeTimestamp` was removed from the spec — so the\n * timeline hands out begin/end query indices by label and each pass spreads them\n * into its descriptor.\n *\n * Where `timestamp-query` is unavailable the timeline is simply absent and the\n * benchmark falls back to wall-clock totals, reported as such. A number labelled\n * as a GPU pass time that was actually a CPU submit time would be worse than no\n * number, and §Risks already names timestamp-query availability as an engine\n * variance to record rather than to assume.\n *\n * One caveat worth stating because it changes how the results read: Chrome\n * quantises timestamp results to 100 µs by default, so a single short pass reads\n * as 0. The benchmark works around it the way S2's harness did — by launching with\n * `--disable-dawn-features=timestamp_quantization`, and by measuring many\n * repetitions when it cannot.\n */\n\nexport interface PassTimeline {\n /** Query indices for a render pass, or undefined when timing is off. */\n renderSlot(label: string): GPURenderPassTimestampWrites | undefined;\n computeSlot(label: string): GPUComputePassTimestampWrites | undefined;\n}\n\nexport interface TimingCollector extends PassTimeline {\n readonly capacity: number;\n readonly used: number;\n /** Queue the resolve + copy. Call once, after the last pass of the frame. */\n resolve(encoder: GPUCommandEncoder): void;\n /** Read the resolved timings. Labels map to elapsed nanoseconds. */\n read(): Promise<ReadonlyMap<string, number>>;\n /**\n * Slots whose resolved pair was not a positive duration, since the collector\n * was created. A non-zero count means some number reported here is missing a\n * pass, and saying so is better than quietly averaging it in.\n */\n readonly anomalies: number;\n reset(): void;\n destroy(): void;\n}\n\nexport function supportsTimestamps(device: GPUDevice): boolean {\n return device.features.has(\"timestamp-query\");\n}\n\nexport function createTimingCollector(device: GPUDevice, capacity = 64): TimingCollector {\n const querySet = device.createQuerySet({\n label: \"vitrea:timing\",\n type: \"timestamp\",\n count: capacity * 2,\n });\n const byteLength = capacity * 2 * 8;\n const resolveBuffer = device.createBuffer({\n label: \"vitrea:timing:resolve\",\n size: byteLength,\n usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC,\n });\n const staging = device.createBuffer({\n label: \"vitrea:timing:staging\",\n size: byteLength,\n usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\n });\n\n let used = 0;\n let anomalies = 0;\n const labels: string[] = [];\n\n const take = (label: string): { begin: number; end: number } | undefined => {\n if (used >= capacity) return undefined;\n const index = used;\n used += 1;\n labels[index] = label;\n return { begin: index * 2, end: index * 2 + 1 };\n };\n\n return {\n capacity,\n get used() {\n return used;\n },\n\n get anomalies() {\n return anomalies;\n },\n\n renderSlot(label) {\n const slot = take(label);\n if (slot === undefined) return undefined;\n return {\n querySet,\n beginningOfPassWriteIndex: slot.begin,\n endOfPassWriteIndex: slot.end,\n };\n },\n\n computeSlot(label) {\n const slot = take(label);\n if (slot === undefined) return undefined;\n return {\n querySet,\n beginningOfPassWriteIndex: slot.begin,\n endOfPassWriteIndex: slot.end,\n };\n },\n\n resolve(encoder) {\n if (used === 0) return;\n encoder.resolveQuerySet(querySet, 0, used * 2, resolveBuffer, 0);\n encoder.copyBufferToBuffer(resolveBuffer, 0, staging, 0, used * 2 * 8);\n },\n\n async read() {\n const out = new Map<string, number>();\n if (used === 0) return out;\n await staging.mapAsync(GPUMapMode.READ, 0, used * 2 * 8);\n const view = new BigInt64Array(staging.getMappedRange(0, used * 2 * 8).slice(0));\n staging.unmap();\n for (let i = 0; i < used; i += 1) {\n const begin = view[i * 2] ?? 0n;\n const end = view[i * 2 + 1] ?? 0n;\n const label = labels[i] ?? `pass-${i}`;\n const elapsed = Number(end - begin);\n // Zero IS a legitimate duration — a clear-only pass with no draw really\n // does take no measurable time. What is not legitimate is a *negative*\n // one, or a pair where both endpoints are zero: WebGPU leaves a slot\n // unspecified when its pass did not run, and averaging that in would\n // corrupt every number in the report. Those are dropped and counted.\n if (!Number.isFinite(elapsed) || elapsed < 0 || (begin === 0n && end === 0n)) {\n anomalies += 1;\n continue;\n }\n // Several passes share a label (one per group, one per pyramid level), and\n // the interesting number is the total the budget is spent on, so labels\n // accumulate rather than overwrite.\n out.set(label, (out.get(label) ?? 0) + elapsed);\n }\n return out;\n },\n\n reset() {\n used = 0;\n labels.length = 0;\n },\n\n destroy() {\n querySet.destroy();\n resolveBuffer.destroy();\n staging.destroy();\n },\n };\n}\n\n/** Pass labels, so the benchmark's report and the passes agree on the names. */\nexport const PASS_LABEL = {\n import: \"backdrop-import\",\n chain: \"blur-chain\",\n bodyBlur: \"body-blur\",\n analysis: \"analysis\",\n field: \"group-field\",\n optics: \"optics\",\n highlight: \"highlight\",\n} as const;\n","/**\n * The f32 cross-check pass (Decision Log #20's obligation on C6).\n *\n * S2 measured family D's WGSL against an f64 evaluation of the same arithmetic and\n * got 4.08e-5 px — 0.024% of the declared 0.170 px bound. Family C, the quality\n * governor's first within-tier step, was priced but only inspection-verified, and\n * the spec makes its shipping conditional on it going through the same check.\n *\n * The reason this pass lives in `src/` rather than in a test harness is the point\n * of the whole exercise: it compiles **the same kernel strings the renderer\n * ships** — `WGSL_FIELD_KERNELS`, the constants `fieldPassSource` is assembled\n * from — over a caller-supplied point set. A check that compiled a separate copy\n * of the algebra would prove something about the copy.\n *\n * It is a compute pass rather than a render pass because the output is numbers:\n * a render target would quantise them at whatever the attachment format is, and\n * `rgba16float` has ten mantissa bits, which is coarser than the difference being\n * measured by three orders of magnitude.\n */\n\nexport const CROSS_CHECK_SHAPE_FLOATS = 12;\nexport const CROSS_CHECK_WORKGROUP = 64;\n\nexport const WGSL_CROSS_CHECK_PASS = `struct CheckShape {\n centre : vec2f,\n half : vec2f,\n re : f32,\n k0 : f32,\n k1 : f32,\n k2 : f32,\n k3 : f32,\n k4 : f32,\n _pad0 : f32,\n _pad1 : f32,\n};\n\n/// point.xy = shape-local coordinates, point.z = shape index, point.w unused\n@group(0) @binding(0) var<storage, read> checkShapes : array<CheckShape>;\n@group(0) @binding(1) var<storage, read> checkPoints : array<vec4f>;\n@group(0) @binding(2) var<storage, read_write> outRsupn : array<f32>;\n@group(0) @binding(3) var<storage, read_write> outRsup : array<f32>;\n@group(0) @binding(4) var<uniform> checkCount : vec4u;\n\n@compute @workgroup_size(${CROSS_CHECK_WORKGROUP})\nfn cs_cross_check(@builtin(global_invocation_id) gid : vec3u) {\n let i = gid.x;\n if (i >= checkCount.x) { return; }\n\n let p = checkPoints[i];\n let s = checkShapes[u32(p.z)];\n let k = vec4f(s.k0, s.k1, s.k2, s.k3);\n let local = p.xy - s.centre;\n\n outRsupn[i] = sd_rsupn(local, s.half, s.re, k, s.k4);\n outRsup[i] = sd_rsup(local, s.half, s.re, k, s.k4);\n}`;\n","/**\n * Backdrop import and the blur pyramid.\n *\n * ## Import (X3, X5)\n *\n * One pass normalises every source kind into level 0 of the pyramid:\n * **premultiplied, linear-light, sRGB-primaries `rgba16float`**. The three\n * things that differ between providers — encoding, alpha mode, colour space —\n * arrive as uniforms resolved on the CPU, where the provider's contract is\n * known, so no shader ever guesses at them. That is what X3's \"the compositor\n * normalizes at import\" means operationally: imported video is unpremultiplied\n * and copied images are premultiplied, and after this pass neither fact is\n * visible downstream.\n *\n * The unpremultiply happens *before* the transfer-function decode and the\n * re-premultiply *after* it. Decoding a premultiplied value is meaningless — the\n * curve is not linear, so `decode(c·a) != decode(c)·a` — and getting that order\n * wrong shows up as dark fringes on every soft edge.\n *\n * ## The chain\n *\n * Progressive downsample, 13 taps per level, sampled bilinearly so the 13 taps\n * cover a 4×4 footprint. This is the standard bloom-pyramid filter, and it is\n * here for the reason it exists there: it is the cheapest filter whose repeated\n * application does not produce the boxy, aliasing-prone result a naive 2×2 average\n * gives, and it is one pass per level rather than the three a\n * downsample-then-separable-blur chain needs.\n *\n * With `mipmapFilter: \"linear\"` on the sampler, `textureSampleLevel(chain, s, uv,\n * lod)` is then a continuously variable blur — which is exactly what the optics\n * pass needs for \"LOD by thickness/size\".\n *\n * ## The body blur\n *\n * The chain gives blur in powers of two. The material's own σ is not a power of\n * two, so the body — the large, flat region of frost behind a surface — gets one\n * dedicated separable Gaussian at the residual σ on top of the nearest chain\n * level. Two passes for the whole scene, not two per level: the refraction path\n * has no use for it, because a rim sample wants the sharpest level it can get.\n */\n\n/**\n * `srcEncoded`: 1 when the sampled values are sRGB-encoded (every 8-bit copy and\n * every external video texture), 0 when they are already linear (an app-supplied\n * float view can be either, so the provider declares it).\n *\n * `alphaMode`: 0 premultiplied, 1 unpremultiplied, 2 opaque — the enumeration\n * `alphaNormalisationMode` in `color.ts` produces.\n */\nexport const WGSL_IMPORT_PASS = `struct ImportUniforms {\n m0 : vec4f, // colour matrix row 0 (xyz), srcEncoded (w)\n m1 : vec4f, // row 1 (xyz), alphaMode (w)\n m2 : vec4f, // row 2 (xyz), unused (w)\n fit : vec4f, // uv scale (xy), uv offset (zw) — the source's fit into the target\n};\n\n@group(0) @binding(0) var<uniform> iu : ImportUniforms;\n@group(0) @binding(1) var srcSampler : sampler;\n@group(0) @binding(2) var srcTexture : SRC_TEXTURE_TYPE;\n\nfn sample_src(uv : vec2f) -> vec4f {\n return SRC_SAMPLE_EXPR;\n}\n\n@fragment\nfn fs_import(in : FullscreenOut) -> @location(0) vec4f {\n let uv = in.uv * iu.fit.xy + iu.fit.zw;\n var raw = sample_src(clamp(uv, vec2f(0.0), vec2f(1.0)));\n\n let alphaMode = iu.m1.w;\n var alpha = raw.a;\n var colour = raw.rgb;\n\n if (alphaMode > 1.5) {\n alpha = 1.0;\n } else if (alphaMode > 0.5) {\n // Already unpremultiplied: nothing to undo.\n } else {\n // Premultiplied input — undo it before the non-linear decode. A fully\n // transparent texel carries zero colour, so the floored divide returns zero\n // there without a branch.\n colour = colour / max(alpha, 1e-6);\n }\n\n if (iu.m0.w > 0.5) {\n colour = srgb_to_linear(clamp(colour, vec3f(0.0), vec3f(1.0)));\n }\n\n // Colour-space conversion in linear light. Identity for sRGB sources.\n colour = vec3f(dot(iu.m0.xyz, colour), dot(iu.m1.xyz, colour), dot(iu.m2.xyz, colour));\n\n return vec4f(max(colour, vec3f(0.0)) * alpha, alpha);\n}`;\n\n/** `SRC_TEXTURE_TYPE`/`SRC_SAMPLE_EXPR` per source kind. */\nexport function importPassSource(kind: \"sampled\" | \"external\"): string {\n const type = kind === \"external\" ? \"texture_external\" : \"texture_2d<f32>\";\n const expr =\n kind === \"external\"\n ? \"textureSampleBaseClampToEdge(srcTexture, srcSampler, uv)\"\n : \"textureSampleLevel(srcTexture, srcSampler, uv, 0.0)\";\n return WGSL_IMPORT_PASS.replace(\"SRC_TEXTURE_TYPE\", type).replace(\"SRC_SAMPLE_EXPR\", expr);\n}\n\n/**\n * 13-tap progressive downsample. Offsets are in the SOURCE level's texels; the\n * caller passes `1 / srcSize` so the pass needs no texture-dimension query.\n */\nexport const WGSL_DOWNSAMPLE_PASS = `struct ChainUniforms {\n texel : vec4f, // 1/srcSize (xy), unused (zw)\n params : vec4f, // sigma in texels (x), direction (yz), unused (w)\n};\n\n@group(0) @binding(0) var<uniform> cu : ChainUniforms;\n@group(0) @binding(1) var chainSampler : sampler;\n@group(0) @binding(2) var chainTexture : texture_2d<f32>;\n\nfn tap(uv : vec2f, o : vec2f) -> vec4f {\n return textureSampleLevel(chainTexture, chainSampler, uv + o * cu.texel.xy, 0.0);\n}\n\n@fragment\nfn fs_downsample(in : FullscreenOut) -> @location(0) vec4f {\n let uv = in.uv;\n\n let a = tap(uv, vec2f(-2.0, 2.0));\n let b = tap(uv, vec2f( 0.0, 2.0));\n let c = tap(uv, vec2f( 2.0, 2.0));\n let d = tap(uv, vec2f(-2.0, 0.0));\n let e = tap(uv, vec2f( 0.0, 0.0));\n let f = tap(uv, vec2f( 2.0, 0.0));\n let g = tap(uv, vec2f(-2.0, -2.0));\n let h = tap(uv, vec2f( 0.0, -2.0));\n let i = tap(uv, vec2f( 2.0, -2.0));\n let j = tap(uv, vec2f(-1.0, 1.0));\n let k = tap(uv, vec2f( 1.0, 1.0));\n let l = tap(uv, vec2f(-1.0, -1.0));\n let m = tap(uv, vec2f( 1.0, -1.0));\n\n // Weights: the centre cross carries 0.5 across four inner taps, the corners\n // and edges the remaining 0.5. Sums to exactly 1, so the chain neither gains\n // nor loses energy — which is what keeps the analysis pass's luminance honest\n // however many levels it reads through.\n var out = (j + k + l + m) * 0.5 * 0.25;\n out = out + (a + b + d + e) * 0.125 * 0.25;\n out = out + (b + c + e + f) * 0.125 * 0.25;\n out = out + (d + e + g + h) * 0.125 * 0.25;\n out = out + (e + f + h + i) * 0.125 * 0.25;\n return out;\n}\n\n/// Separable Gaussian, nine taps, run once horizontally and once vertically to\n/// take the nearest chain level up to the material's exact sigma.\n@fragment\nfn fs_blur(in : FullscreenOut) -> @location(0) vec4f {\n let dir = cu.params.yz;\n let sigma = max(cu.params.x, 1e-4);\n let inv = -0.5 / (sigma * sigma);\n\n var sum = vec4f(0.0);\n var weight = 0.0;\n for (var t = -4; t <= 4; t = t + 1) {\n let ft = f32(t);\n let w = exp(ft * ft * inv);\n sum = sum + textureSampleLevel(chainTexture, chainSampler, in.uv + dir * ft * cu.texel.xy, 0.0) * w;\n weight = weight + w;\n }\n return sum / weight;\n}`;\n","/**\n * The group field pass (§Geometry: \"instances → group SDF/coverage field → one\n * optical pass\").\n *\n * Three contract points are structural here rather than conventional, which is\n * the only way a shader can be held to them:\n *\n * 1. **X8 rider 2 — a concentric child renders as a LEVEL SET of its parent's\n * field.** There is no second path. `Instance` carries the *parent's*\n * `half/re/k` plus its own `inset`, and the evaluator always computes\n * `field(p; parent params) + inset`. For an ordinary surface `inset` is 0 and\n * the expression is the surface's own field. So the instantiated-shape path —\n * whose offset error grows with inset and dominates the declared bound past\n * about 4 px — is not expressible in this shader at all.\n * 2. **The families come from `@vitrea/geometry` verbatim.** `sd_rsupn` and\n * `sd_rsup` are the fingerprinted strings that package owns, spliced in\n * unchanged, so the cost figures and the f32 result transfer with them. What\n * this module adds is their gradients and the union, which S2 did not price and\n * which are therefore written to be as close to free as the algebra allows.\n * 3. **The gradient is analytic and costs no extra field evaluations.**\n * `sd_rsupn_grad` is a port of `rsupnFieldAndGradient` — the ≤2.92° normal at\n * the free normal's price. Family C's normal is the closed-form level-set\n * normal (≤4.26°), which is the honest pairing: taking family C means taking\n * family C's gradient too. Being a port, it moves when the value moves:\n * `sd_rsupn` anchors its normalization at the contour radius, so this selects\n * the same arm and differentiates the arm it selected. `test/wgsl-contract.test.ts`\n * pins that pairing, because a normal computed from the unanchored form on top\n * of an anchored depth is exactly the kind of half-applied edit no fingerprint\n * would notice.\n *\n * The union mirrors `union.ts` exactly on the value — the same bulge cap applied\n * to `k`, the same separation gate, the same single clamp at the end of the fold.\n * `union_blend` returns that value **and the blend weight `h`**, because the pass\n * has more than a distance to fold: the gradient and the four per-surface optical\n * scalars have to travel through the same seam, and doing it with the same `h`\n * keeps one copy of the union's algebra instead of four. Blending the gradient by\n * `h` drops the union's term in `dk`, which makes it exact wherever `h` saturates\n * — everywhere except inside a real seam.\n */\n\nimport { WGSL_RSUP, WGSL_RSUPN } from \"@vitrea/geometry\";\n\n/**\n * Instance layout — `@vitrea/geometry`'s `Shape` struct widened by the render\n * channels, 64 bytes, every member 4- or 8-byte aligned so the CPU packing is a\n * flat `Float32Array` with a 16-float stride.\n *\n * `centre/half/re/k0..k4` are the X8 channel vector's geometric half plus the\n * six derived floats. `inset` is rider 2's level-set offset. The rest are motion\n * driver outputs, sampled by the host and handed in as data (§Motion: this\n * package consumes driver outputs, never time).\n */\nexport const WGSL_INSTANCE_STRUCT = `struct Instance {\n centre : vec2f, // 0 group-local CSS px\n half : vec2f, // 8 half-extents of the field's OWN shape (the parent's, for a concentric child)\n re : f32, // 16 corner reach\n k0 : f32, // 20\n k1 : f32, // 24\n k2 : f32, // 28\n k3 : f32, // 32\n k4 : f32, // 36\n inset : f32, // 40 X8 rider 2: level-set offset. 0 for an ordinary surface.\n thick : f32, // 44 material thickness, CSS px\n press : f32, // 48 interaction channel value, 0..1\n glow : f32, // 52 interaction channel value, 0..1\n lensDepth : f32, // 56 CPU-resolved lens depth in CSS px (material.ts), already scaled by the lensStrength channel\n _pad : f32, // 60\n};`;\n\n/** `FieldSample` mirrors geometry's, minus `kink`: the shader has no use for it. */\nexport const WGSL_FIELD_SAMPLE = `struct FieldSample {\n d : f32,\n g : vec2f,\n};`;\n\n/**\n * Family D's value and exact gradient in one pass — the port of\n * `rsupnFieldAndGradient`.\n *\n * The masks at the end are what extend the corner-sector chain rule to every\n * region: `mx`/`my` gate the clamped-coordinate terms, and the box-branch term\n * carries the derivative where `max(qx, qy) <= 0`. The `<=` there is not a\n * typo — at `m == 0` both clamped terms are masked off, so the box term has to\n * fire or the gradient reads (0, 0) on the corner-sector boundary. C3 found and\n * fixed exactly that bug while deriving this.\n */\nexport const WGSL_RSUPN_GRAD = `fn sd_rsupn_grad(p : vec2f, half : vec2f, re : f32, k : vec4f, k4 : f32) -> FieldSample {\n let q = abs(p) - half + vec2f(re, re);\n let c = max(q, vec2f(0.0, 0.0));\n let r2 = max(dot(c, c), 1e-20);\n let inv = 1.0 / r2;\n let rho = sqrt(r2);\n let s2 = 2.0 * c.x * c.y * inv;\n let c2 = (c.x * c.x - c.y * c.y) * inv;\n\n // A = sum k_i s2^i, B = sum (i+2) k_i s2^i, C = sum (i+1)(i+2) k_i s2^i.\n var accA = k4;\n accA = accA * s2 + k.w;\n accA = accA * s2 + k.z;\n accA = accA * s2 + k.y;\n accA = accA * s2 + k.x;\n\n var accB = 6.0 * k4;\n accB = accB * s2 + 5.0 * k.w;\n accB = accB * s2 + 4.0 * k.z;\n accB = accB * s2 + 3.0 * k.y;\n accB = accB * s2 + 2.0 * k.x;\n\n var accC = 30.0 * k4;\n accC = accC * s2 + 20.0 * k.w;\n accC = accC * s2 + 12.0 * k.z;\n accC = accC * s2 + 6.0 * k.y;\n accC = accC * s2 + 2.0 * k.x;\n\n let R = re * (1.0 + s2 * s2 * accA);\n let dRds2 = re * s2 * accB;\n let d2Rds2 = re * accC;\n let dRdt = dRds2 * (2.0 * c2);\n\n let mm = min(max(q.x, q.y), 0.0);\n let base = rho + mm - R;\n // Anchored at the contour radius, mirroring sd_rsupn: the normalization's\n // slope is read at the foot of the Newton step, never at a sample radius\n // inside the contour. See geometry's field.ts, \"The normalization\".\n let atRho = rho >= R;\n let w = select(R, rho, atRho);\n let g = select(dRdt / R, dRdt * inv * rho, atRho);\n let norm = sqrt(1.0 + g * g);\n let n = 1.0 / norm;\n\n let ds2dcx = -2.0 * c.y * c2 * inv;\n let ds2dcy = 2.0 * c.x * c2 * inv;\n let dc2dcx = 2.0 * c.x * inv * (1.0 - c2);\n let dc2dcy = -2.0 * c.y * inv * (1.0 + c2);\n\n let drhodcx = c.x / rho;\n let drhodcy = c.y / rho;\n\n let dRdcx = dRds2 * ds2dcx;\n let dRdcy = dRds2 * ds2dcy;\n\n let dTermdcx = 2.0 * (d2Rds2 * ds2dcx * c2 + dRds2 * dc2dcx);\n let dTermdcy = 2.0 * (d2Rds2 * ds2dcy * c2 + dRds2 * dc2dcy);\n\n // w's derivative follows whichever of rho and R is larger. Exact across the\n // switch because the switch locus is rho == R, the contour, where base == 0\n // kills the only term the jump lives in.\n let dwdcx = select(dRdcx, drhodcx, atRho);\n let dwdcy = select(dRdcy, drhodcy, atRho);\n\n let dgdcx = dTermdcx / w - (dRdt * dwdcx) / (w * w);\n let dgdcy = dTermdcy / w - (dRdt * dwdcy) / (w * w);\n\n let n3 = n * n * n;\n let dddcx = (drhodcx - dRdcx) * n + base * (-g * n3 * dgdcx);\n let dddcy = (drhodcy - dRdcy) * n + base * (-g * n3 * dgdcy);\n\n let mx = select(0.0, 1.0, q.x > 0.0);\n let my = select(0.0, 1.0, q.y > 0.0);\n let inBox = max(q.x, q.y) <= 0.0;\n let dmmdqx = select(0.0, 1.0, inBox && q.x >= q.y);\n let dmmdqy = select(0.0, 1.0, inBox && q.y > q.x);\n\n let sx = select(1.0, -1.0, p.x < 0.0);\n let sy = select(1.0, -1.0, p.y < 0.0);\n\n var out : FieldSample;\n out.d = base * n;\n out.g = vec2f((dddcx * mx + n * dmmdqx) * sx, (dddcy * my + n * dmmdqy) * sy);\n return out;\n}`;\n\n/**\n * Family C's value and its closed-form level-set normal.\n *\n * The value is `sd_rsup` verbatim; the normal is\n * `normalize(rhoHat - (R'/rho) * thetaHat)`, which is free because every term is\n * already computed. It is identical to family D's gradient *on* the contour to\n * four decimal places — the normalization moves level sets only away from the\n * zero set — so rim lighting is indifferent between them and only refraction at\n * depth pays the 1.5–1.7× difference.\n */\nexport const WGSL_RSUP_GRAD = `fn sd_rsup_grad(p : vec2f, half : vec2f, re : f32, k : vec4f, k4 : f32) -> FieldSample {\n let q = abs(p) - half + vec2f(re, re);\n let c = max(q, vec2f(0.0, 0.0));\n let r2 = max(dot(c, c), 1e-20);\n let rho = sqrt(r2);\n let s2 = 2.0 * c.x * c.y / r2;\n\n var accA = k4;\n accA = accA * s2 + k.w;\n accA = accA * s2 + k.z;\n accA = accA * s2 + k.y;\n accA = accA * s2 + k.x;\n\n var accB = 6.0 * k4;\n accB = accB * s2 + 5.0 * k.w;\n accB = accB * s2 + 4.0 * k.z;\n accB = accB * s2 + 3.0 * k.y;\n accB = accB * s2 + 2.0 * k.x;\n\n let c2 = (c.x * c.x - c.y * c.y) / r2;\n let R = re * (1.0 + s2 * s2 * accA);\n\n let sx = select(1.0, -1.0, p.x < 0.0);\n let sy = select(1.0, -1.0, p.y < 0.0);\n\n var out : FieldSample;\n out.d = rho + min(max(q.x, q.y), 0.0) - R;\n\n if (c.x <= 0.0 && c.y <= 0.0) {\n // Straight-edge and deep-interior: the normal is the axis the box branch is\n // measuring along.\n out.g = select(vec2f(0.0, sy), vec2f(sx, 0.0), q.x > q.y);\n return out;\n }\n\n let dRdt = re * s2 * accB * (2.0 * c2);\n let rhoHat = c / rho;\n let gg = dRdt / rho;\n let nx = rhoHat.x + gg * rhoHat.y;\n let ny = rhoHat.y - gg * rhoHat.x;\n let len = max(length(vec2f(nx, ny)), 1e-20);\n out.g = vec2f(sx * nx / len, sy * ny / len);\n return out;\n}`;\n\n/**\n * The bounded smooth union of `union.ts`, value for value.\n *\n * `separation * 0.5` is floored away from zero because WGSL's `smoothstep` is\n * undefined when its two edges coincide, where the TypeScript's own `smoothstep`\n * degrades to a step. A group configured with no separation threshold therefore\n * blends everywhere, which is the same thing the TypeScript does.\n */\nexport const WGSL_SMOOTH_UNION = `fn union_blend(a : f32, b : f32, u : vec3f) -> vec2f {\n let neck = u.x;\n let maxBulge = u.y;\n let sep = max(u.z * 0.5, 1e-6);\n\n let nearest = min(a, b);\n let capped = min(neck, 4.0 * maxBulge);\n let gate = 1.0 - smoothstep(0.0, sep, max(nearest, 0.0));\n let k = capped * gate;\n\n if (k <= 0.0) {\n return vec2f(nearest, select(0.0, 1.0, a <= b));\n }\n\n let h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);\n return vec2f(b + h * (a - b) - k * h * (1.0 - h), h);\n}`;\n\n/**\n * The pass itself.\n *\n * Scoped to the group's bounds, never fullscreen: the target IS the group rect,\n * so the fullscreen triangle covers exactly the pixels the group can touch.\n * §Performance envelope prices the field at ~5% of the mobile budget on that\n * assumption, and a fullscreen field pass per group would multiply it by the\n * ratio of viewport area to group area.\n *\n * The output is one `rgba16float` texel per device pixel: signed field in CSS\n * px, the unit normal, and analytic coverage. Everything downstream — optics,\n * highlight, and any future pass — reads this and never re-evaluates the field.\n */\nexport const WGSL_FIELD_PASS = `struct FieldUniforms {\n /// screen.xy = target size in device px, screen.z = CSS px per device px,\n /// screen.w = coverage ramp width in CSS px\n screen : vec4f,\n /// neckWidth, maxBulge, separationThreshold, unused\n unionP : vec4f,\n counts : vec4u,\n};\n\n// Per-surface optical scalars ride through the union in 'aux': the group is one\n// field but its members are not one size, and carrying them per pixel is what\n// lets a 40 px button and a 320 px platter share a field pass and still lens by\n// their own depth — parent acceptance #2 inside a GlassEffectContainer.\n// aux = (lensDepthPx, glow, thicknessPx, press)\n\n@group(0) @binding(0) var<uniform> fu : FieldUniforms;\n@group(0) @binding(1) var<storage, read> instances : array<Instance>;\n\nstruct Member {\n d : f32,\n g : vec2f,\n aux : vec4f,\n};\n\nfn eval_instance(i : u32, p : vec2f) -> Member {\n let s = instances[i];\n let k = vec4f(s.k0, s.k1, s.k2, s.k3);\n // X8 rider 2 in one line: the child is the parent's field, shifted. There is\n // no branch and no second path, so no caller can opt into the instantiated\n // shape whose offset error the rider rules out.\n let f = FIELD_FN(p - s.centre, s.half, s.re, k, s.k4);\n var m : Member;\n m.d = f.d + s.inset;\n m.g = f.g;\n m.aux = vec4f(s.lensDepth, s.glow, s.thick, s.press);\n return m;\n}\n\nstruct FieldOut {\n @location(0) field : vec4f,\n @location(1) aux : vec4f,\n};\n\n@fragment\nfn fs_field(in : FullscreenOut) -> FieldOut {\n // GROUP-LOCAL CSS px. The instance buffer's centres were already made relative\n // to the group's rect on the CPU (f32 loses resolution at large magnitudes, so\n // a field evaluated at viewport y = 40000 would quantise its own corner), and\n // adding the origin back here would offset every shape by it twice.\n let p = in.uv * fu.screen.xy * fu.screen.z;\n\n var out : FieldOut;\n let count = fu.counts.x;\n if (count == 0u) {\n // Large but FINITE: rgba16float overflows to +Inf past ~65504, and NaN\n // coverage downstream is not reliably zero.\n out.field = vec4f(65000.0, 0.0, -1.0, 0.0);\n out.aux = vec4f(0.0);\n return out;\n }\n\n var acc = eval_instance(0u, p);\n var nearest = acc.d;\n for (var i = 1u; i < count; i = i + 1u) {\n let s = eval_instance(i, p);\n let blend = union_blend(acc.d, s.d, fu.unionP.xyz);\n let h = blend.y;\n acc.d = blend.x;\n acc.g = mix(s.g, acc.g, h);\n acc.aux = mix(s.aux, acc.aux, h);\n nearest = min(nearest, s.d);\n }\n // One clamp at the end of the fold, so |union - min| <= maxBulge holds for any\n // member count and any order rather than per blend step.\n acc.d = max(acc.d, nearest - fu.unionP.y);\n\n let len = max(length(acc.g), 1e-6);\n let normal = acc.g / len;\n let coverage = clamp(0.5 - acc.d / max(fu.screen.w, 1e-6), 0.0, 1.0);\n\n out.field = vec4f(acc.d, normal.x, normal.y, coverage);\n out.aux = acc.aux;\n return out;\n}`;\n\n/** The field module for one family. `FIELD_FN` is bound at assembly time. */\nexport function fieldPassSource(family: \"rsupn\" | \"rsup\"): string {\n const kernels = family === \"rsupn\" ? [WGSL_RSUPN, WGSL_RSUPN_GRAD] : [WGSL_RSUP, WGSL_RSUP_GRAD];\n const fn = family === \"rsupn\" ? \"sd_rsupn_grad\" : \"sd_rsup_grad\";\n return [\n WGSL_INSTANCE_STRUCT,\n WGSL_FIELD_SAMPLE,\n ...kernels,\n WGSL_SMOOTH_UNION,\n WGSL_FIELD_PASS.replace(\"FIELD_FN\", fn),\n ].join(\"\\n\\n\");\n}\n\n/**\n * Both families' value kernels plus both gradients, with no pass around them.\n *\n * This is what the f32 cross-check compiles: Decision Log #20 makes family C's\n * shipping conditional on its WGSL going through the same check family D passed,\n * and a check that compiled a *different* string from the one the renderer ships\n * would prove nothing. So the pass source above and the harness below are both\n * assembled from these same constants.\n */\nexport const WGSL_FIELD_KERNELS = [\n WGSL_INSTANCE_STRUCT,\n WGSL_FIELD_SAMPLE,\n WGSL_RSUPN,\n WGSL_RSUP,\n WGSL_RSUPN_GRAD,\n WGSL_RSUP_GRAD,\n WGSL_SMOOTH_UNION,\n].join(\"\\n\\n\");\n","/**\n * The highlight pass: specular sweep and press glow.\n *\n * X1 puts this canvas **above** the semantic host DOM, which is the whole reason\n * it is a separate pass and not three more lines in the optics shader: a\n * highlight has to fall across the label, and the label is real DOM sitting\n * between the two canvases. Nothing else about the material does.\n *\n * Both effects are driven by motion-driver *outputs*, never by time (§Motion —\n * the renderer consumes driver values as data):\n *\n * - **`sweep`** ∈ [0, 1] is the shimmer's position along the rim. The band is a\n * Gaussian in the angular coordinate of the gradient, so it travels around the\n * contour rather than sliding across a bounding box, and it exists only where\n * the rim exists. Reduced Motion sets `shimmer: \"none\"`, which the CPU turns\n * into a zero gain — the band is not drawn stationary, it is not drawn.\n * - **`glow`** ∈ [0, 1] is the press illumination, from the fast-attack /\n * slow-decay driver. It arrives **per pixel**, unioned through the field pass,\n * multiplied by a radial falloff around the press point and clipped to the\n * surface's coverage so it never leaks past the material's edge.\n *\n * The sweep phase and the press *point* are per group rather than per surface:\n * there is one pointer, and a sweep travelling around a `GlassEffectContainer`'s\n * unioned contour is the behaviour the container exists to produce. v1's\n * components never register two simultaneous presses inside one group.\n *\n * Output is additive over the page: premultiplied with the glow's own alpha, so a\n * zero-intensity highlight writes nothing at all rather than a transparent black\n * that a wrong blend state could darken with.\n */\n\nexport const WGSL_HIGHLIGHT_PASS = `struct HighlightUniforms {\n /// viewport size in device px (xy), CSS px per device px (z), unused (w)\n screen : vec4f,\n /// sweep position 0..1 (x), band width in radians (y), sweep gain (z), rim width px (w)\n sweep : vec4f,\n /// press point in viewport CSS px (xy), glow radius px (z), glow gain (w)\n glow : vec4f,\n /// highlight colour, linear light (xyz), unused (w)\n colour : vec4f,\n /// fieldSize.xy, fieldUpsampled (z), unused (w)\n flags : vec4f,\n};\n\n@group(0) @binding(0) var<uniform> hu : HighlightUniforms;\n@group(0) @binding(1) var fieldTexture : texture_2d<f32>;\n@group(0) @binding(2) var auxTexture : texture_2d<f32>;\n@group(0) @binding(3) var fieldSampler : sampler;\n\nconst TAU = 6.283185307179586;\n\n/// Shortest angular distance, so the band wraps continuously past the seam\n/// instead of stalling there for one revolution.\nfn angle_delta(a : f32, b : f32) -> f32 {\n let raw = abs(a - b);\n return min(raw, TAU - raw);\n}\n\n@fragment\nfn fs_highlight(in : FullscreenOut) -> @location(0) vec4f {\n // Exact load nominally; filtered when the governor's resolution knob had the\n // field rasterised below the group's rect. The sweep rides the rim, which is\n // the one place a nearest read of a coarse field would show its grid.\n var field : vec4f;\n var aux : vec4f;\n if (hu.flags.z > 0.5) {\n field = textureSampleLevel(fieldTexture, fieldSampler, in.uv, 0.0);\n aux = textureSampleLevel(auxTexture, fieldSampler, in.uv, 0.0);\n } else {\n let texel = vec2i(in.uv * hu.flags.xy);\n field = textureLoad(fieldTexture, texel, 0);\n aux = textureLoad(auxTexture, texel, 0);\n }\n let d = field.x;\n let normal = field.yz;\n let coverage = field.w;\n\n if (coverage <= 0.0) {\n return vec4f(0.0);\n }\n\n // Specular sweep: a travelling band in the rim's angular coordinate.\n let rim = clamp(1.0 - abs(d) / max(hu.sweep.w, 1e-4), 0.0, 1.0);\n let theta = atan2(normal.y, normal.x) + TAU * 0.5;\n let centre = hu.sweep.x * TAU;\n let width = max(hu.sweep.y, 1e-4);\n let band = exp(-pow(angle_delta(theta, centre) / width, 2.0));\n let sweep = rim * rim * band * hu.sweep.z;\n\n // Press glow: radial, in CSS px, clipped by coverage so it cannot leak past\n // the material's edge.\n let posCss = in.position.xy * hu.screen.z;\n let dist = length(posCss - hu.glow.xy);\n let radial = clamp(1.0 - dist / max(hu.glow.z, 1e-4), 0.0, 1.0);\n // 'aux.y' is the per-pixel glow channel, unioned in the field pass, so a group\n // whose members glow independently does not need a pass each.\n let press = radial * radial * hu.glow.w * aux.y;\n\n let intensity = clamp(sweep + press, 0.0, 1.0) * coverage;\n if (intensity <= 0.0) {\n return vec4f(0.0);\n }\n return encode_output(hu.colour.rgb, intensity);\n}`;\n","/**\n * The optics pass: refraction, adaptive tint, inner shadow, rim and specular —\n * the glass body.\n *\n * Reads the group's two field targets (value + unit normal + coverage, and the\n * per-surface optical scalars) and the backdrop pyramid; writes premultiplied sRGB\n * into the optics canvas over the group's rect. Everything optical happens in\n * linear light and is encoded exactly once, on the way out (X5).\n *\n * The pass is scoped, not fullscreen: the render pass sets its viewport *and* its\n * scissor to the group's device-pixel rect, so `in.uv` runs 0..1 over the group\n * and indexes the group's own field textures one-to-one, while `in.position.xy`\n * stays in canvas device pixels and gives the backdrop coordinate. Nothing outside\n * the group's bounds is touched — §Performance envelope prices the field and\n * optics passes on exactly that assumption.\n *\n * ## Refraction, and why it scales with size\n *\n * Parent acceptance #2 asks for the *mechanism*, not a look: \"a larger surface\n * shows deeper shadow and stronger lensing than a small button over the same\n * backdrop.\" Apple's material is size-parameterised, so lens depth is not the\n * authored thickness alone — `material.ts` resolves\n *\n * ```\n * lensDepthPx = min(thickness * sizeGain(span), span / 2)\n * ```\n *\n * per surface, and the field pass carries the result **per pixel** through the\n * union. That is what lets a 40 px button and a 320 px platter share one group's\n * field pass and still lens by their own depth. The clamp is what keeps a small\n * control from being all lens: a 24 px-tall button cannot bend more than 12 px of\n * backdrop however thick it is authored.\n *\n * The displacement is the normal times a profile that peaks at the rim and dies in\n * the interior, where the glass is flat and shows the backdrop straight through.\n * **Sampling LOD follows the same profile and the same depth**: the body sits at\n * `lensDepth * bodyLodPerPx` — thicker glass diffuses more — and the rim is biased\n * sharper, because a compressed backdrop reads as detail. That is the inverse of\n * the naive \"blur more at the edge\", and it is most of what makes an edge read as\n * glass rather than as a smudge.\n *\n * Every coefficient is advisory and calibration-delegated (C7), named on the CPU.\n *\n * ## The dual cap\n *\n * `refractionScale` arrives as one number the CPU already resolved through\n * `effectiveRefraction(accessibilityCap, stateQuality)` — Decision Log #19's rule\n * that renderers honour the lower of the two caps. The shader never sees them\n * separately, so it cannot honour the wrong one.\n */\n\nexport const WGSL_OPTICS_PASS = `struct OpticsUniforms {\n /// viewport size in device px (xy), CSS px per device px (z), coverage ramp px (w)\n screen : vec4f,\n /// backdrop uv transform on viewport-normalised coords: scale (xy), offset (zw)\n fit : vec4f,\n /// refractionScale, bodyLodPerPx, rimLodBias, chainMaxLod\n lens : vec4f,\n /// fixed tint colour, linear light (xyz), tint alpha (w)\n tint : vec4f,\n /// adapted tint colour, linear light (xyz), adaptation strength (w)\n adapt : vec4f,\n /// rimWidthPx, rimAlpha, specularPower, specularGain\n rim : vec4f,\n /// light direction, unit (xy), shadowDepth (z), shadowAlpha (w)\n light : vec4f,\n /// hasBackdrop, fieldSize.xy, fieldUpsampled\n flags : vec4f,\n};\n\n@group(0) @binding(0) var<uniform> ou : OpticsUniforms;\n@group(0) @binding(1) var fieldTexture : texture_2d<f32>;\n@group(0) @binding(2) var auxTexture : texture_2d<f32>;\n@group(0) @binding(3) var backdropSampler : sampler;\n@group(0) @binding(4) var backdropChain : texture_2d<f32>;\n@group(0) @binding(5) var backdropBody : texture_2d<f32>;\n@group(0) @binding(6) var fieldSampler : sampler;\n\n/// Rim proximity: 1 exactly on the contour, falling to 0 by 'width' on either\n/// side. Symmetric, so the rim is a band on the boundary rather than a plateau\n/// that keeps burning outward where coverage has already faded.\nfn rim_weight(d : f32, width : f32) -> f32 {\n let t = clamp(1.0 - abs(d) / max(width, 1e-4), 0.0, 1.0);\n return t * t;\n}\n\n@fragment\nfn fs_optics(in : FullscreenOut) -> @location(0) vec4f {\n // Nominally the field is one texel per device pixel, so the read is an exact\n // load and no filter touches the distance or the normal. Under the governor's\n // 'refractionResolutionScale' the field was rasterised smaller than the group's\n // rect, and then it has to be filtered: a nearest read would quantise the\n // contour to the coarse grid and the rim would step along it.\n var field : vec4f;\n var aux : vec4f;\n if (ou.flags.w > 0.5) {\n field = textureSampleLevel(fieldTexture, fieldSampler, in.uv, 0.0);\n aux = textureSampleLevel(auxTexture, fieldSampler, in.uv, 0.0);\n } else {\n let texel = vec2i(in.uv * ou.flags.yz);\n field = textureLoad(fieldTexture, texel, 0);\n aux = textureLoad(auxTexture, texel, 0);\n }\n\n let d = field.x;\n let normal = field.yz;\n let coverage = field.w;\n if (coverage <= 0.0) {\n return vec4f(0.0);\n }\n\n let viewport01 = in.position.xy / ou.screen.xy;\n let viewportCss = ou.screen.xy * ou.screen.z;\n\n // Per-pixel, unioned through the field pass. See the module note.\n let lensDepth = max(aux.x, 1e-4);\n // '-d' is depth inside the surface, so the profile runs 1 at the contour to 0\n // at 'lensDepth' inward, and the square makes the falloff read as curvature\n // rather than as a linear ramp.\n let depth = clamp(-d / lensDepth, 0.0, 1.0);\n let profile = (1.0 - depth) * (1.0 - depth);\n\n let displaceCss = -normal * lensDepth * profile * ou.lens.x;\n let refracted01 = viewport01 + displaceCss / viewportCss;\n\n let straightUv = clamp(viewport01 * ou.fit.xy + ou.fit.zw, vec2f(0.0), vec2f(1.0));\n let refractedUv = clamp(refracted01 * ou.fit.xy + ou.fit.zw, vec2f(0.0), vec2f(1.0));\n\n let bodyLod = clamp(lensDepth * ou.lens.y, 0.0, ou.lens.w);\n let lod = clamp(bodyLod - ou.lens.z * profile, 0.0, ou.lens.w);\n\n var backdrop = vec3f(0.0);\n if (ou.flags.x > 0.5) {\n let lensSample = textureSampleLevel(backdropChain, backdropSampler, refractedUv, lod);\n let bodySample = textureSampleLevel(backdropBody, backdropSampler, straightUv, 0.0);\n // Premultiplied linear in, straight colour out: the material composites over\n // whatever is behind it, so a partially transparent backdrop must not darken\n // the glass.\n let lensColour = lensSample.rgb / max(lensSample.a, 1e-6);\n let bodyColour = bodySample.rgb / max(bodySample.a, 1e-6);\n backdrop = mix(bodyColour, lensColour, profile);\n }\n\n // Adaptive tint. 'adapt.w' is the strength the accessibility policy and the\n // group's analysis quality already agreed on; at 0 the fixed tint stands, which\n // is what a 'hint' or 'none' group gets.\n let tintColour = mix(ou.tint.rgb, ou.adapt.rgb, ou.adapt.w);\n var colour = mix(backdrop, tintColour, ou.tint.w);\n\n // Inner shadow: the material's own occlusion, deepest where the lens is\n // strongest, which is what makes a thicker surface read as heavier.\n colour = colour * (1.0 - profile * ou.light.z * ou.light.w);\n\n // Rim and specular from the gradient. The rim is unlit ambient edge brightness;\n // the specular term is the same edge lit from 'light.xy'.\n let rw = rim_weight(d, ou.rim.x);\n let facing = dot(normal, ou.light.xy);\n let spec = pow(clamp(facing, 0.0, 1.0), max(ou.rim.z, 1e-3)) * ou.rim.w;\n colour = colour + vec3f(rw * (ou.rim.y + spec));\n\n return encode_output(max(colour, vec3f(0.0)), coverage);\n}`;\n","/**\n * Shared WGSL: the colour pipeline (X5) and the fullscreen-triangle vertex stage\n * every pass here uses.\n *\n * The marker comment on the first line is load-bearing beyond documentation:\n * `packages/core/test/bundle-shape.test.ts` greps built chunks for it to prove\n * that WGSL reaches exactly one lazily-imported chunk and never core's entry\n * chunk (X7). Keep it in a module every pass pulls in, and keep it spelled\n * exactly as it is.\n */\n\nexport const WGSL_PRELUDE = `// vitrea:wgsl-marker\n// ---------------------------------------------------------------------------\n// X5 colour pipeline. Piecewise sRGB, matching color.ts channel for channel:\n// a golden regenerated against one and asserted against the other must not\n// drift by a code unit, so the 2.2-gamma approximation is not used anywhere.\n// ---------------------------------------------------------------------------\n\nfn srgb_to_linear(c : vec3f) -> vec3f {\n let lo = c / 12.92;\n let hi = pow((c + vec3f(0.055)) / 1.055, vec3f(2.4));\n return select(hi, lo, c <= vec3f(0.04045));\n}\n\nfn linear_to_srgb(c : vec3f) -> vec3f {\n let lo = c * 12.92;\n let hi = 1.055 * pow(max(c, vec3f(0.0)), vec3f(1.0 / 2.4)) - vec3f(0.055);\n return select(hi, lo, c <= vec3f(0.0031308));\n}\n\n/// Rec.709 weights on LINEAR light. Weighting encoded values would make the\n/// analysis pass measure something that is not energy.\nfn luminance(linear : vec3f) -> f32 {\n return dot(linear, vec3f(0.2126, 0.7152, 0.0722));\n}\n\n/// The one output encoding: encode, then premultiply in the ENCODED space,\n/// because that is the space the browser composites a canvas in. Premultiplying\n/// in linear and encoding afterwards darkens every partially covered pixel.\nfn encode_output(linear : vec3f, alpha : f32) -> vec4f {\n let a = clamp(alpha, 0.0, 1.0);\n return vec4f(linear_to_srgb(linear) * a, a);\n}\n\n// ---------------------------------------------------------------------------\n// Fullscreen triangle. Three vertices, no vertex buffer, no index buffer: the\n// oversized triangle is clipped to the target and costs one fewer primitive\n// than a quad, and every pass here writes exactly one screen-space region.\n// ---------------------------------------------------------------------------\n\nstruct FullscreenOut {\n @builtin(position) position : vec4f,\n @location(0) uv : vec2f,\n};\n\n@vertex\nfn vs_fullscreen(@builtin(vertex_index) index : u32) -> FullscreenOut {\n // (-1,-1) (3,-1) (-1,3) in clip space; uv follows with y flipped so (0,0) is\n // the target's top-left, matching texture and viewport conventions.\n let x = f32((index << 1u) & 2u) * 2.0 - 1.0;\n let y = f32(index & 2u) * 2.0 - 1.0;\n var out : FullscreenOut;\n out.position = vec4f(x, y, 0.0, 1.0);\n out.uv = vec2f((x + 1.0) * 0.5, (1.0 - y) * 0.5);\n return out;\n}\n`;\n","/**\n * Shader-module assembly.\n *\n * Every module is `prelude + pass`, so the colour pipeline and the fullscreen\n * vertex stage are defined once and there is no way for a pass to acquire its own\n * private transfer function. Assembly is a plain string concatenation performed\n * on demand and cached by the pipeline cache — no build step, no bundler plugin,\n * and the WGSL stays greppable in the built artifact, which is what core's X7\n * bundle test relies on.\n */\n\nimport { WGSL_ANALYSIS_PASS } from \"./analysis\";\nimport { WGSL_CROSS_CHECK_PASS } from \"./cross-check\";\nimport { importPassSource, WGSL_DOWNSAMPLE_PASS } from \"./backdrop\";\nimport { fieldPassSource, WGSL_FIELD_KERNELS } from \"./field\";\nimport { WGSL_HIGHLIGHT_PASS } from \"./highlight\";\nimport { WGSL_OPTICS_PASS } from \"./optics\";\nimport { WGSL_PRELUDE } from \"./prelude\";\n\nexport * from \"./analysis\";\nexport * from \"./cross-check\";\nexport * from \"./backdrop\";\nexport * from \"./field\";\nexport * from \"./highlight\";\nexport * from \"./optics\";\nexport * from \"./prelude\";\n\nconst withPrelude = (pass: string): string => `${WGSL_PRELUDE}\\n${pass}\\n`;\n\nexport type FieldFamily = \"rsupn\" | \"rsup\";\n\nexport const fieldModule = (family: FieldFamily): string => withPrelude(fieldPassSource(family));\n\nexport const importModule = (kind: \"sampled\" | \"external\"): string =>\n withPrelude(importPassSource(kind));\n\nexport const chainModule = (): string => withPrelude(WGSL_DOWNSAMPLE_PASS);\n\nexport const analysisModule = (): string => withPrelude(WGSL_ANALYSIS_PASS);\n\nexport const opticsModule = (): string => withPrelude(WGSL_OPTICS_PASS);\n\nexport const highlightModule = (): string => withPrelude(WGSL_HIGHLIGHT_PASS);\n\n/**\n * The kernel-only module the f32 cross-check compiles (Decision Log #20).\n *\n * It is assembled from the same constants the field pass is, which is the point:\n * a check that compiled a different string from the one the renderer ships would\n * prove nothing about the shipped shader.\n */\nexport const crossCheckKernelModule = (): string =>\n withPrelude([WGSL_FIELD_KERNELS, WGSL_CROSS_CHECK_PASS].join(\"\\n\\n\"));\n\n/**\n * Every shader this package can compile, concatenated.\n *\n * Exposed as `GlassRenderer.shaderSource` — the seam's honest answer to \"what\n * WGSL does this renderer carry\", and the string core's bundle-shape test finds\n * the marker in.\n */\nexport function allShaderSource(): string {\n return [\n WGSL_PRELUDE,\n fieldPassSource(\"rsupn\"),\n fieldPassSource(\"rsup\"),\n importPassSource(\"sampled\"),\n importPassSource(\"external\"),\n WGSL_DOWNSAMPLE_PASS,\n WGSL_ANALYSIS_PASS,\n WGSL_OPTICS_PASS,\n WGSL_HIGHLIGHT_PASS,\n ].join(\"\\n\\n\");\n}\n","/**\n * The three drawing passes, as GPU work: field, optics, highlight.\n *\n * Each is scoped to the group's device-pixel rect. The field pass renders *into*\n * a group-sized pair of textures; the optics and highlight passes render into the\n * plane canvases with the viewport and the scissor both set to that rect, so the\n * fullscreen triangle's `uv` indexes the field textures one-to-one and\n * `position.xy` stays in canvas coordinates. X1 forbids two glass surfaces\n * overlapping inside one plane, so those rects are disjoint and the scissor is\n * enough — no depth, no stencil, no sorting.\n *\n * Blending is premultiplied source-over on both canvas passes. Against a cleared\n * canvas it is indistinguishable from no blending, and the reason to have it is\n * the case that is not that: an overlay-plane surface drawn over a base-plane one\n * during a cross-plane morph, where the promotion moves the surface as a unit but\n * the frame in flight can still hold both.\n */\n\nimport { OUTPUT_TEXTURE_FORMAT, WORKING_TEXTURE_FORMAT } from \"./color\";\nimport { type GpuContext, createUniformSlot, createStorageSlot, type StorageSlot, type UniformSlot } from \"./gpu-context\";\nimport type { FieldFamily } from \"./governor\";\nimport { INSTANCE_BYTES } from \"./instances\";\nimport { pipelineKey } from \"./pipeline-cache\";\nimport { poolKey } from \"./texture-pool\";\nimport { PASS_LABEL, type PassTimeline } from \"./timing\";\nimport { fieldModule, highlightModule, opticsModule } from \"./wgsl\";\n\n/**\n * Usage masks are computed on FIRST USE, never at module scope.\n *\n * `GPUTextureUsage` is a browser global, and this module is imported outside a\n * browser: `vitrea`'s lazy seam resolves this package in Node to check the\n * renderer's shape (`packages/core/test/renderer-seam.test.ts`). A mask evaluated\n * at module scope makes the whole package throw on import there — a\n * `ReferenceError` from a file that never intended to run, in a test that only\n * wanted to read `backend` and `ready`.\n */\nconst fieldUsage = (): GPUTextureUsageFlags =>\n GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING;\n\n/** Premultiplied source-over. See the module note. */\nconst PREMULTIPLIED_OVER: GPUBlendState = {\n color: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n alpha: { srcFactor: \"one\", dstFactor: \"one-minus-src-alpha\", operation: \"add\" },\n};\n\n/** A rect in device pixels. Integers by construction — see `snapRectToDevicePixels`. */\nexport interface DeviceRect {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n}\n\nexport interface FieldPassArgs {\n readonly groupId: string;\n readonly family: FieldFamily;\n readonly rectDevice: DeviceRect;\n /** CSS px per device px. */\n readonly cssPerDevice: number;\n /** Coverage ramp width in CSS px. One device pixel, unless the governor widens it. */\n readonly coverageRampCss: number;\n /**\n * The governor's `refractionResolutionScale`, 0 < s <= 1. The field targets are\n * allocated at `rectDevice * s` and the optics and highlight passes upsample\n * them; the *rect* is unchanged, so the group still covers the same pixels.\n * `1` is the nominal path and takes exactly the arithmetic it took before the\n * knob existed.\n */\n readonly renderScale: number;\n readonly instances: Float32Array;\n readonly instanceCount: number;\n readonly union: { readonly neckWidth: number; readonly maxBulge: number; readonly separationThreshold: number };\n}\n\nexport interface FieldTargets {\n readonly field: GPUTexture;\n readonly aux: GPUTexture;\n /** The field textures' extent in texels — the group's rect times `renderScale`. */\n readonly width: number;\n readonly height: number;\n /**\n * True when that extent is smaller than the group's rect, so a reader has to\n * filter rather than index. False on the nominal path, where one texel is one\n * device pixel and the read is an exact `textureLoad`.\n */\n readonly upsampled: boolean;\n}\n\nexport interface OpticsPassArgs {\n readonly groupId: string;\n readonly target: GPUTextureView;\n readonly targetFormat: GPUTextureFormat;\n readonly rectDevice: DeviceRect;\n readonly fields: FieldTargets;\n /** Viewport in device px, and CSS px per device px. */\n readonly viewportDevice: readonly [number, number];\n readonly cssPerDevice: number;\n readonly coverageRampCss: number;\n /** Backdrop uv transform on viewport-normalised coordinates. */\n readonly fit: readonly [number, number, number, number];\n readonly refractionScale: number;\n readonly bodyLodPerPx: number;\n readonly rimLodBias: number;\n readonly chainMaxLod: number;\n readonly tint: readonly [number, number, number];\n readonly tintAlpha: number;\n readonly adaptTint: readonly [number, number, number];\n readonly adaptStrength: number;\n readonly rimWidth: number;\n readonly rimAlpha: number;\n readonly specularPower: number;\n readonly specularGain: number;\n readonly lightDirection: readonly [number, number];\n readonly shadowDepth: number;\n readonly shadowAlpha: number;\n readonly backdrop: { readonly chain: GPUTextureView; readonly body: GPUTextureView } | undefined;\n}\n\nexport interface HighlightPassArgs {\n readonly groupId: string;\n readonly target: GPUTextureView;\n readonly targetFormat: GPUTextureFormat;\n readonly rectDevice: DeviceRect;\n readonly fields: FieldTargets;\n readonly viewportDevice: readonly [number, number];\n readonly cssPerDevice: number;\n readonly sweep: number;\n readonly sweepBandRadians: number;\n readonly sweepGain: number;\n readonly rimWidth: number;\n readonly pressPointCss: readonly [number, number];\n readonly glowRadiusCss: number;\n readonly glowGain: number;\n readonly colour: readonly [number, number, number];\n}\n\nexport interface PassRunner {\n fieldPass(encoder: GPUCommandEncoder, args: FieldPassArgs): FieldTargets;\n opticsPass(encoder: GPUCommandEncoder, args: OpticsPassArgs): void;\n highlightPass(encoder: GPUCommandEncoder, args: HighlightPassArgs): void;\n /** A 1×1 transparent texture, for binding a backdrop that is not there. */\n readonly placeholderView: GPUTextureView;\n /** Clear a plane canvas before the group passes, which load rather than clear. */\n clearPass(encoder: GPUCommandEncoder, target: GPUTextureView): void;\n /** Attach a timing collector for this frame, or `undefined` to time nothing. */\n setTimeline(timeline: PassTimeline | undefined): void;\n forget(groupId: string): void;\n destroy(): void;\n}\n\nexport function createPassRunner(context: GpuContext): PassRunner {\n const { device, pool, cache } = context;\n const uniforms = new Map<string, UniformSlot>();\n const storages = new Map<string, StorageSlot>();\n\n // `rgba16float` tops out near 65504, so the \"no surface here\" distance is a\n // large FINITE value: an overflow to +Inf would make every later arithmetic on\n // it a NaN, and NaN coverage is not reliably zero.\n const EMPTY_DISTANCE = 65000;\n\n const placeholder = device.createTexture({\n label: \"vitrea:placeholder\",\n size: { width: 1, height: 1, depthOrArrayLayers: 1 },\n format: WORKING_TEXTURE_FORMAT,\n usage: fieldUsage(),\n });\n\n const uniformSlot = (key: string, floats: number): UniformSlot => {\n let slot = uniforms.get(key);\n if (slot === undefined) {\n slot = createUniformSlot(device, floats, `vitrea:uniform:${key}`);\n uniforms.set(key, slot);\n }\n return slot;\n };\n\n const storageSlot = (key: string): StorageSlot => {\n let slot = storages.get(key);\n if (slot === undefined) {\n slot = createStorageSlot(device, 8 * INSTANCE_BYTES, `vitrea:instances:${key}`);\n storages.set(key, slot);\n }\n return slot;\n };\n\n const fieldPipeline = (family: FieldFamily): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.field(family, WORKING_TEXTURE_FORMAT), () => {\n const module = cache.module(`module:field:${family}`, () => fieldModule(family));\n return {\n label: `vitrea:pipeline:field:${family}`,\n layout: \"auto\",\n vertex: { module, entryPoint: \"vs_fullscreen\" },\n fragment: {\n module,\n entryPoint: \"fs_field\",\n targets: [{ format: WORKING_TEXTURE_FORMAT }, { format: WORKING_TEXTURE_FORMAT }],\n },\n primitive: { topology: \"triangle-list\" },\n };\n });\n\n const opticsPipeline = (format: GPUTextureFormat): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.optics(format, \"premultiplied-over\"), () => {\n const module = cache.module(\"module:optics\", opticsModule);\n return {\n label: \"vitrea:pipeline:optics\",\n layout: \"auto\",\n vertex: { module, entryPoint: \"vs_fullscreen\" },\n fragment: {\n module,\n entryPoint: \"fs_optics\",\n targets: [{ format, blend: PREMULTIPLIED_OVER }],\n },\n primitive: { topology: \"triangle-list\" },\n };\n });\n\n const highlightPipeline = (format: GPUTextureFormat): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.highlight(format, \"premultiplied-over\"), () => {\n const module = cache.module(\"module:highlight\", highlightModule);\n return {\n label: \"vitrea:pipeline:highlight\",\n layout: \"auto\",\n vertex: { module, entryPoint: \"vs_fullscreen\" },\n fragment: {\n module,\n entryPoint: \"fs_highlight\",\n targets: [{ format, blend: PREMULTIPLIED_OVER }],\n },\n primitive: { topology: \"triangle-list\" },\n };\n });\n\n const scoped = (\n pass: GPURenderPassEncoder,\n rect: DeviceRect,\n ): void => {\n pass.setViewport(rect.x, rect.y, rect.width, rect.height, 0, 1);\n // The oversized fullscreen triangle reaches past the viewport; the scissor is\n // what stops it writing another group's pixels.\n pass.setScissorRect(rect.x, rect.y, rect.width, rect.height);\n };\n\n const placeholderView = placeholder.createView();\n let timeline: PassTimeline | undefined;\n\n /** `timestampWrites` is only legal when the device enabled `timestamp-query`. */\n const timed = (label: string): { timestampWrites?: GPURenderPassTimestampWrites } => {\n const slot = timeline?.renderSlot(label);\n return slot === undefined ? {} : { timestampWrites: slot };\n };\n\n return {\n placeholderView,\n\n fieldPass(encoder, args) {\n // The rect the group occupies on the canvas, and the extent the field is\n // rasterised at. They differ only under the governor's resolution knob, and\n // at scale 1 the second is the first — `Math.round(w * 1)` on an integer.\n const rectWidth = Math.max(1, Math.round(args.rectDevice.width));\n const rectHeight = Math.max(1, Math.round(args.rectDevice.height));\n const width = Math.max(1, Math.round(args.rectDevice.width * args.renderScale));\n const height = Math.max(1, Math.round(args.rectDevice.height * args.renderScale));\n\n const field = pool.acquire(poolKey.groupField(args.groupId), {\n width,\n height,\n format: WORKING_TEXTURE_FORMAT,\n usage: fieldUsage(),\n label: `vitrea:group:${args.groupId}:field`,\n });\n const aux = pool.acquire(poolKey.groupAux(args.groupId), {\n width,\n height,\n format: WORKING_TEXTURE_FORMAT,\n usage: fieldUsage(),\n label: `vitrea:group:${args.groupId}:aux`,\n });\n\n // Twelve floats: screen, unionP, counts. The group's origin is deliberately\n // absent — instance centres are packed relative to it, so the shader works\n // in group-local coordinates and never adds it back.\n //\n // `screen.xy` is the group's extent in DEVICE px, not the target's, because\n // the shader multiplies it by `screen.z` to recover group-local CSS. Under\n // the resolution knob the target shrinks while the group does not, and it\n // is the group the geometry is expressed in.\n const slot = uniformSlot(`field:${args.groupId}`, 12);\n slot.data[0] = rectWidth;\n slot.data[1] = rectHeight;\n slot.data[2] = args.cssPerDevice;\n // One TARGET pixel wide, so the analytic coverage stays one texel of\n // antialiasing however coarse the target is. At scale 1 the ratio is 1.\n slot.data[3] = args.coverageRampCss * (rectWidth / width);\n slot.data[4] = args.union.neckWidth;\n slot.data[5] = args.union.maxBulge;\n slot.data[6] = args.union.separationThreshold;\n slot.data[7] = 0;\n // `counts` is a vec4u in the shader; a Float32Array cannot write a u32, so\n // the count goes through a Uint32 view of the same words.\n slot.data[9] = 0;\n slot.data[10] = 0;\n slot.data[11] = 0;\n new Uint32Array(slot.data.buffer, slot.data.byteOffset + 32, 1)[0] = args.instanceCount;\n slot.write();\n\n const instances = storageSlot(args.groupId);\n instances.ensure(Math.max(args.instanceCount, 1) * INSTANCE_BYTES);\n instances.write(args.instances, Math.max(args.instanceCount, 1) * (INSTANCE_BYTES / 4));\n\n const pipeline = fieldPipeline(args.family);\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:field:${args.groupId}`,\n ...timed(PASS_LABEL.field),\n colorAttachments: [\n {\n view: field.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: EMPTY_DISTANCE, g: 0, b: -1, a: 0 },\n },\n {\n view: aux.createView(),\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: { buffer: instances.buffer } },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n\n return {\n field,\n aux,\n width,\n height,\n upsampled: width !== rectWidth || height !== rectHeight,\n };\n },\n\n opticsPass(encoder, args) {\n const slot = uniformSlot(`optics:${args.groupId}`, 32);\n const d = slot.data;\n d[0] = args.viewportDevice[0];\n d[1] = args.viewportDevice[1];\n d[2] = args.cssPerDevice;\n d[3] = args.coverageRampCss;\n d[4] = args.fit[0];\n d[5] = args.fit[1];\n d[6] = args.fit[2];\n d[7] = args.fit[3];\n d[8] = args.refractionScale;\n d[9] = args.bodyLodPerPx;\n d[10] = args.rimLodBias;\n d[11] = args.chainMaxLod;\n d[12] = args.tint[0];\n d[13] = args.tint[1];\n d[14] = args.tint[2];\n d[15] = args.tintAlpha;\n d[16] = args.adaptTint[0];\n d[17] = args.adaptTint[1];\n d[18] = args.adaptTint[2];\n d[19] = args.adaptStrength;\n d[20] = args.rimWidth;\n d[21] = args.rimAlpha;\n d[22] = args.specularPower;\n d[23] = args.specularGain;\n d[24] = args.lightDirection[0];\n d[25] = args.lightDirection[1];\n d[26] = args.shadowDepth;\n d[27] = args.shadowAlpha;\n d[28] = args.backdrop === undefined ? 0 : 1;\n d[29] = args.fields.width;\n d[30] = args.fields.height;\n d[31] = args.fields.upsampled ? 1 : 0;\n slot.write();\n\n const chain = args.backdrop?.chain ?? placeholderView;\n const body = args.backdrop?.body ?? placeholderView;\n\n const pipeline = opticsPipeline(args.targetFormat);\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:optics:${args.groupId}`,\n ...timed(PASS_LABEL.optics),\n colorAttachments: [{ view: args.target, loadOp: \"load\", storeOp: \"store\" }],\n });\n pass.setPipeline(pipeline);\n scoped(pass, args.rectDevice);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: args.fields.field.createView() },\n { binding: 2, resource: args.fields.aux.createView() },\n { binding: 3, resource: context.chainSampler },\n { binding: 4, resource: chain },\n { binding: 5, resource: body },\n // Linear, no mips: the field targets have one level, and this is only\n // read at all when the governor shrank them below the group's rect.\n { binding: 6, resource: context.flatSampler },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n },\n\n highlightPass(encoder, args) {\n const slot = uniformSlot(`highlight:${args.groupId}`, 20);\n const d = slot.data;\n d[0] = args.viewportDevice[0];\n d[1] = args.viewportDevice[1];\n d[2] = args.cssPerDevice;\n d[3] = 0;\n d[4] = args.sweep;\n d[5] = args.sweepBandRadians;\n d[6] = args.sweepGain;\n d[7] = args.rimWidth;\n d[8] = args.pressPointCss[0];\n d[9] = args.pressPointCss[1];\n d[10] = args.glowRadiusCss;\n d[11] = args.glowGain;\n d[12] = args.colour[0];\n d[13] = args.colour[1];\n d[14] = args.colour[2];\n d[15] = 0;\n d[16] = args.fields.width;\n d[17] = args.fields.height;\n d[18] = args.fields.upsampled ? 1 : 0;\n d[19] = 0;\n slot.write();\n\n const pipeline = highlightPipeline(args.targetFormat);\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:highlight:${args.groupId}`,\n ...timed(PASS_LABEL.highlight),\n colorAttachments: [{ view: args.target, loadOp: \"load\", storeOp: \"store\" }],\n });\n pass.setPipeline(pipeline);\n scoped(pass, args.rectDevice);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: args.fields.field.createView() },\n { binding: 2, resource: args.fields.aux.createView() },\n { binding: 3, resource: context.flatSampler },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n },\n\n clearPass(encoder, target) {\n // Deliberately untimed. A render pass with no draw commands is resolved by\n // the driver without ever writing its timestamp pair, so a slot taken here\n // comes back as (0, 0) — indistinguishable from a query that failed. Leaving\n // it out is what lets a non-zero anomaly count mean something.\n const pass = encoder.beginRenderPass({\n label: \"vitrea:pass:clear\",\n colorAttachments: [\n {\n view: target,\n loadOp: \"clear\",\n storeOp: \"store\",\n clearValue: { r: 0, g: 0, b: 0, a: 0 },\n },\n ],\n });\n pass.end();\n },\n\n setTimeline(next) {\n timeline = next;\n },\n\n forget(groupId) {\n pool.release(poolKey.groupField(groupId));\n pool.release(poolKey.groupAux(groupId));\n storages.get(groupId)?.destroy();\n storages.delete(groupId);\n for (const key of [`field:${groupId}`, `optics:${groupId}`, `highlight:${groupId}`]) {\n uniforms.get(key)?.buffer.destroy();\n uniforms.delete(key);\n }\n },\n\n destroy() {\n for (const slot of uniforms.values()) slot.buffer.destroy();\n uniforms.clear();\n for (const slot of storages.values()) slot.destroy();\n storages.clear();\n placeholder.destroy();\n },\n };\n}\n\n/** The output format the plane canvases and the golden readback both use (X5). */\nexport const CANVAS_FORMAT = OUTPUT_TEXTURE_FORMAT;\n","/**\n * How large a backdrop's pyramid is, and which level each consumer reads —\n * decided on the CPU, in one pure function, before any texture exists.\n *\n * §Performance envelope: \"Effect-texture resolution is decoupled from DOM DPR.\"\n * That decoupling lives here: level 0 is the *source's* size scaled by the\n * resolution policy and capped by `maxDimension`, never the viewport's device\n * pixel count. A 4K video behind a 390-px-wide phone viewport does not get a 4K\n * pyramid, and a governor that halves `scale` halves the whole chain's cost\n * without touching a shader.\n *\n * ## Level count\n *\n * The chain stops when the shorter side would fall below `MIN_LEVEL_EXTENT`. Below\n * about 8 px a level carries no usable structure and the bilinear taps of the\n * 13-tap downsample start reading mostly clamped edge, so the levels past that\n * point cost bandwidth and add nothing. That also bounds the maximum LOD the\n * optics pass may ask for, which is why `maxLod` is part of the plan rather than\n * computed in the shader.\n *\n * ## The analysis level\n *\n * Not the coarsest: the coarsest level has had every edge blurred out of it, so an\n * edge-density measurement there would report the same small number for a\n * photograph and for a flat colour. The plan picks the level nearest\n * `ANALYSIS_TARGET_EXTENT`, which keeps the measurement's spatial frequency band\n * fixed as the source's resolution changes — a stat that moved when the\n * resolution policy moved would make the governor's own degradation look like a\n * change in the backdrop.\n */\n\nexport const MIN_LEVEL_EXTENT = 8;\nexport const MAX_CHAIN_LEVELS = 12;\n/** Shorter-side extent the analysis level aims for. */\nexport const ANALYSIS_TARGET_EXTENT = 96;\n\nexport interface PyramidPlan {\n /** Level 0 size in texture px. */\n readonly width: number;\n readonly height: number;\n readonly levelCount: number;\n /** The highest LOD the optics pass may sample: `levelCount - 1`. */\n readonly maxLod: number;\n /** Which level the analysis reduction reads. */\n readonly analysisLevel: number;\n /** Per-level sizes, index 0 = level 0. */\n readonly levels: readonly { readonly width: number; readonly height: number }[];\n}\n\nexport interface ResolutionPolicyView {\n readonly scale: number;\n readonly maxDimension: number;\n}\n\nexport function planPyramid(\n sourceWidth: number,\n sourceHeight: number,\n policy: ResolutionPolicyView,\n): PyramidPlan {\n const scale = Math.max(policy.scale, 1e-3);\n let width = Math.max(1, Math.round(sourceWidth * scale));\n let height = Math.max(1, Math.round(sourceHeight * scale));\n\n const cap = Math.max(MIN_LEVEL_EXTENT, Math.floor(policy.maxDimension));\n const longest = Math.max(width, height);\n if (longest > cap) {\n const shrink = cap / longest;\n width = Math.max(1, Math.round(width * shrink));\n height = Math.max(1, Math.round(height * shrink));\n }\n\n const levels: { width: number; height: number }[] = [{ width, height }];\n while (levels.length < MAX_CHAIN_LEVELS) {\n const previous = levels[levels.length - 1] as { width: number; height: number };\n const next = {\n width: Math.max(1, previous.width >> 1),\n height: Math.max(1, previous.height >> 1),\n };\n if (Math.min(next.width, next.height) < MIN_LEVEL_EXTENT) break;\n if (next.width === previous.width && next.height === previous.height) break;\n levels.push(next);\n }\n\n // Nearest level to the analysis target on the shorter side, in log space so\n // \"nearest\" means nearest by octave rather than by pixel count.\n let analysisLevel = 0;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (let i = 0; i < levels.length; i += 1) {\n const level = levels[i] as { width: number; height: number };\n const shorter = Math.min(level.width, level.height);\n const distance = Math.abs(Math.log2(shorter / ANALYSIS_TARGET_EXTENT));\n if (distance < bestDistance) {\n bestDistance = distance;\n analysisLevel = i;\n }\n }\n\n return {\n width,\n height,\n levelCount: levels.length,\n maxLod: levels.length - 1,\n analysisLevel,\n levels,\n };\n}\n\n/**\n * The chain LOD whose blur is nearest σ, and the residual σ the separable pass\n * still has to apply on top of it.\n *\n * The 13-tap downsample's effective σ roughly doubles per level and is about 1.2\n * source texels at level 1; the constant is advisory (calibration-delegated like\n * every other optical number here) and exists so the body blur lands on the\n * material's σ rather than on the nearest power of two.\n */\nexport const CHAIN_SIGMA_AT_LEVEL_1 = 1.2;\n\nexport function bodyBlurPlan(\n sigmaPx: number,\n plan: PyramidPlan,\n): { readonly level: number; readonly residualSigmaTexels: number } {\n if (sigmaPx <= 0) return { level: 0, residualSigmaTexels: 0 };\n\n // Level n's sigma in level-0 texels.\n const sigmaAt = (level: number): number =>\n level === 0 ? 0 : CHAIN_SIGMA_AT_LEVEL_1 * Math.pow(2, level - 1);\n\n let level = 0;\n for (let i = 1; i < plan.levelCount; i += 1) {\n if (sigmaAt(i) > sigmaPx) break;\n level = i;\n }\n\n // The residual is applied at the chosen level's own resolution, so convert.\n const covered = sigmaAt(level);\n const residualLevel0 = Math.sqrt(Math.max(sigmaPx * sigmaPx - covered * covered, 0));\n return { level, residualSigmaTexels: residualLevel0 / Math.pow(2, level) };\n}\n","/**\n * The §Core model invariant, as a testable object.\n *\n * > blur/analysis pyramids belong to `BackdropSource`, rebuilt **at most once per\n * > dirty source per frame** — never per group.\n *\n * core enforces one half of that: `consumeDirtyBackdropSources(frameId)` hands out\n * one pass over the dirty set per frame id, so a second caller in the same frame\n * gets nothing. What core cannot see is the renderer's side — a renderer that also\n * rebuilt lazily on first draw, or that rebuilt once per group from a single\n * request, would satisfy core's guard and still violate the invariant.\n *\n * So the ledger lives here, apart from the GPU work it guards, for one reason: it\n * makes the invariant assertable against core's real scheduler with no adapter and\n * no device. `pyramid.ts` claims through it before it encodes a single pass, and\n * `test/dirty-epoch.test.ts` drives core's own scene and scheduler over this same\n * object. An invariant tested only through a GPU is an invariant tested only where\n * a GPU exists.\n */\n\nexport interface RebuildLedger {\n /**\n * Begin a frame. Clears the per-frame tally — unless `frameId` is the frame\n * already being recorded, which is not a new frame and must not reopen the\n * tally. The renderer draws one plane per call with the same `FrameInfo`, so\n * that case is the ordinary one rather than the exception.\n */\n beginFrame(frameId: number): void;\n readonly frameId: number | undefined;\n /**\n * Claim the one rebuild this source is allowed this frame. `false` means it has\n * already had it — the caller must not encode a second one.\n */\n claim(sourceId: string): boolean;\n /** Record that a claim did no work because the source was clean. */\n recordClean(): void;\n /** Rebuilds recorded for `sourceId` in the frame being recorded. */\n countInFrame(sourceId: string): number;\n readonly rebuilds: number;\n readonly refusedDuplicates: number;\n readonly skippedClean: number;\n /**\n * Highest per-source rebuild count seen in any single frame. The invariant is\n * exactly the statement that this never exceeds 1.\n */\n readonly peakPerSourcePerFrame: number;\n}\n\nexport function createRebuildLedger(): RebuildLedger {\n const perFrame = new Map<string, number>();\n let frameId: number | undefined;\n let rebuilds = 0;\n let refused = 0;\n let clean = 0;\n let peak = 0;\n\n return {\n beginFrame(next) {\n // Repeating a frame id is not a new frame, and clearing the tally for one\n // would quietly hand every source a second rebuild. The renderer calls\n // `drawFrame` once per PLANE with the same `FrameInfo`, so this is the\n // ordinary case rather than a defensive one: without the guard the\n // \"at most once per dirty source per frame\" invariant is unguarded across\n // planes, and `countInFrame` reports 0 for a frame that rebuilt.\n // `FrameInfo.id` is contractually monotonic (core/src/frame.ts), so\n // equality is the whole test.\n if (frameId === next) return;\n frameId = next;\n perFrame.clear();\n },\n\n get frameId() {\n return frameId;\n },\n\n claim(sourceId) {\n const already = perFrame.get(sourceId) ?? 0;\n if (already > 0) {\n refused += 1;\n return false;\n }\n const count = already + 1;\n perFrame.set(sourceId, count);\n peak = Math.max(peak, count);\n rebuilds += 1;\n return true;\n },\n\n recordClean() {\n clean += 1;\n },\n\n countInFrame(sourceId) {\n return perFrame.get(sourceId) ?? 0;\n },\n\n get rebuilds() {\n return rebuilds;\n },\n\n get refusedDuplicates() {\n return refused;\n },\n\n get skippedClean() {\n return clean;\n },\n\n get peakPerSourcePerFrame() {\n return peak;\n },\n };\n}\n","/**\n * The blur/analysis pyramid, one per `BackdropSource`, and the ledger that proves\n * the §Core model invariant.\n *\n * > **Invariant:** blur/analysis pyramids belong to `BackdropSource`, rebuilt **at\n * > most once per dirty source per frame** — never per group. Static backdrops\n * > rebuild nothing.\n *\n * core enforces half of that already: `consumeDirtyBackdropSources(frameId)`\n * hands out one pass over the dirty set per frame id, so however many\n * participants ask, the second call returns nothing. What core *cannot* see is\n * this side of the wire — a renderer that also rebuilt lazily on first draw, or\n * that rebuilt once per group from one request, would satisfy core's guard and\n * violate the invariant. So the ledger here counts rebuilds per source per frame\n * on the renderer's own books, refuses a second one, and exposes the counters.\n * That is what makes the invariant *instrumented* rather than asserted.\n *\n * ## Pass structure per rebuild\n *\n * ```\n * import provider frame -> chain mip 0 (premultiplied linear, X5)\n * downsample mip n-1 -> chain mip n (13-tap, one pass per level)\n * blur x2 chain[bodyLvl] -> body (separable, residual sigma)\n * analysis chain[anaLvl] -> stats buffer (compute, one workgroup)\n * ```\n *\n * Reading mip n-1 while rendering into mip n is legal because they are distinct\n * subresources, and every view here is created with an explicit\n * `baseMipLevel`/`mipLevelCount: 1` so that is true by construction rather than by\n * the driver's interpretation of a full-texture view.\n */\n\nimport { ANALYSIS_STATS_FLOATS, ANALYSIS_GRID, ANALYSIS_WORKGROUP } from \"./wgsl/analysis\";\nimport {\n alphaNormalisationMode,\n importColorMatrix,\n WORKING_TEXTURE_FORMAT,\n} from \"./color\";\nimport { statsFromBuffer, type BackdropStats } from \"./analysis\";\nimport type { BackdropFrame, BackdropProvider } from \"./backdrop\";\nimport { type GpuContext, createUniformSlot, type UniformSlot } from \"./gpu-context\";\nimport { pipelineKey } from \"./pipeline-cache\";\nimport { bodyBlurPlan, planPyramid, type PyramidPlan, type ResolutionPolicyView } from \"./pyramid-plan\";\nimport { createRebuildLedger, type RebuildLedger } from \"./rebuild-ledger\";\nimport { poolKey } from \"./texture-pool\";\nimport { PASS_LABEL, type PassTimeline } from \"./timing\";\nimport { analysisModule, chainModule, importModule } from \"./wgsl\";\n\n/** Computed on first use, not at module scope — see the note in `passes.ts`. */\nconst chainUsage = (): GPUTextureUsageFlags =>\n GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING;\n\nexport interface PyramidResources {\n readonly sourceId: string;\n readonly plan: PyramidPlan;\n readonly chain: GPUTexture;\n readonly body: GPUTexture;\n readonly stats: GPUBuffer;\n /** Source size epoch this allocation was made for. */\n readonly sizeEpoch: number;\n /** The dirty epoch the last successful rebuild satisfied. */\n readonly builtEpoch: number;\n}\n\nexport interface PyramidInstrumentation {\n /** Successful rebuilds since the store was created. */\n readonly rebuilds: number;\n /** Rebuild attempts refused because the source had already rebuilt this frame. */\n readonly refusedDuplicates: number;\n /** Rebuilds skipped because the source was clean. */\n readonly skippedClean: number;\n readonly reallocations: number;\n /** Rebuild count for one source within the frame currently being recorded. */\n rebuildsInFrame(sourceId: string): number;\n /** Highest per-source rebuild count seen in any single frame. Must stay <= 1. */\n readonly peakRebuildsPerSourcePerFrame: number;\n}\n\nexport interface PyramidBuildRequest {\n readonly sourceId: string;\n readonly epoch: number;\n readonly resolution: ResolutionPolicyView;\n /**\n * The material's body blur, in **CSS px**, with the viewport it is measured\n * against.\n *\n * Not in source texels, because the conversion between the two is a property of\n * the frame that has not been acquired yet: a 3840-wide video behind a 390 px\n * viewport packs ten source texels into every CSS px, so a σ of 8 texels would\n * be a σ of 0.8 CSS px on screen — a tenth of the frost the material asked for.\n * The build resolves it once the frame's real extent is known.\n */\n readonly bodySigmaCss: number;\n readonly viewportCss: readonly [number, number];\n}\n\nexport type PyramidBuildOutcome =\n | { readonly status: \"built\"; readonly resources: PyramidResources }\n | { readonly status: \"duplicate\" }\n | { readonly status: \"clean\"; readonly resources: PyramidResources }\n | { readonly status: \"unavailable\"; readonly reason: string };\n\nexport interface PyramidStore {\n readonly instrumentation: PyramidInstrumentation;\n /** The invariant's ledger, exposed so a test can drive it without a device. */\n readonly ledger: RebuildLedger;\n /** Start recording a new frame. Clears the per-frame rebuild tally. */\n beginFrame(frameId: number): void;\n /** Attach a timing collector for this frame, or `undefined` to time nothing. */\n setTimeline(timeline: PassTimeline | undefined): void;\n build(\n request: PyramidBuildRequest,\n provider: BackdropProvider,\n encoder: GPUCommandEncoder,\n ): PyramidBuildOutcome;\n /**\n * Release every provider acquired this frame.\n *\n * Split from `afterSubmit` because the two halves have opposite failure rules.\n * A release is owed whether or not the frame reached the queue — an acquired\n * `VideoFrame` held across a frame stalls decoding — so this belongs in a\n * `finally` around the whole encode/submit. Call it after `queue.submit` on the\n * success path: an imported external texture must outlive the submission that\n * samples it.\n */\n releaseAcquired(): void;\n /**\n * Start the analysis readback maps. **Success path only**: `mapAsync` makes a\n * buffer unavailable to submits from the moment it is called, so starting a map\n * for a copy that was never submitted is its own bug — see `requestStats`.\n */\n afterSubmit(): void;\n /**\n * The source's pyramid, or `undefined` when it has none the pool still owns.\n * A caller may bind what this returns without checking anything further.\n */\n resources(sourceId: string): PyramidResources | undefined;\n /** Copy a source's stats into a staging buffer and map it. Cadence-gated by the caller. */\n requestStats(sourceId: string, encoder: GPUCommandEncoder): boolean;\n /** Resolve any completed stats readbacks. Returns what arrived. */\n collectStats(): Promise<ReadonlyMap<string, BackdropStats>>;\n forget(sourceId: string): void;\n destroy(): void;\n}\n\ninterface StatsReadback {\n readonly staging: GPUBuffer;\n inFlight: boolean;\n}\n\nexport function createPyramidStore(context: GpuContext): PyramidStore {\n const { device, pool, cache } = context;\n\n const resources = new Map<string, PyramidResources>();\n const uniforms = new Map<string, UniformSlot>();\n const readbacks = new Map<string, StatsReadback>();\n const pendingRelease: BackdropProvider[] = [];\n const pendingStats = new Map<string, Promise<BackdropStats | undefined>>();\n /** Readbacks whose copy is encoded but whose map must wait for the submit. */\n const pendingMaps: string[] = [];\n\n let timeline: PassTimeline | undefined;\n const timedRender = (label: string): { timestampWrites?: GPURenderPassTimestampWrites } => {\n const slot = timeline?.renderSlot(label);\n return slot === undefined ? {} : { timestampWrites: slot };\n };\n const timedCompute = (label: string): { timestampWrites?: GPUComputePassTimestampWrites } => {\n const slot = timeline?.computeSlot(label);\n return slot === undefined ? {} : { timestampWrites: slot };\n };\n\n let frameId = -1;\n let reallocations = 0;\n const ledger: RebuildLedger = createRebuildLedger();\n\n const uniformSlot = (key: string, floats: number): UniformSlot => {\n let slot = uniforms.get(key);\n if (slot === undefined) {\n slot = createUniformSlot(device, floats, `vitrea:uniform:${key}`);\n uniforms.set(key, slot);\n }\n return slot;\n };\n\n const importPipeline = (kind: \"sampled\" | \"external\"): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.import(kind, WORKING_TEXTURE_FORMAT), () => ({\n label: `vitrea:pipeline:import:${kind}`,\n layout: \"auto\",\n vertex: {\n module: cache.module(`module:import:${kind}`, () => importModule(kind)),\n entryPoint: \"vs_fullscreen\",\n },\n fragment: {\n module: cache.module(`module:import:${kind}`, () => importModule(kind)),\n entryPoint: \"fs_import\",\n targets: [{ format: WORKING_TEXTURE_FORMAT }],\n },\n primitive: { topology: \"triangle-list\" },\n }));\n\n const chainPipeline = (entry: \"fs_downsample\" | \"fs_blur\"): GPURenderPipeline =>\n cache.renderPipeline(pipelineKey.chain(entry, WORKING_TEXTURE_FORMAT), () => ({\n label: `vitrea:pipeline:chain:${entry}`,\n layout: \"auto\",\n vertex: {\n module: cache.module(\"module:chain\", chainModule),\n entryPoint: \"vs_fullscreen\",\n },\n fragment: {\n module: cache.module(\"module:chain\", chainModule),\n entryPoint: entry,\n targets: [{ format: WORKING_TEXTURE_FORMAT }],\n },\n primitive: { topology: \"triangle-list\" },\n }));\n\n const analysisPipeline = (): GPUComputePipeline =>\n cache.computePipeline(pipelineKey.analysis(), () => ({\n label: \"vitrea:pipeline:analysis\",\n layout: \"auto\",\n compute: {\n module: cache.module(\"module:analysis\", analysisModule),\n entryPoint: \"cs_analysis\",\n },\n }));\n\n /**\n * The source's resources, or `undefined` when the handles it recorded are no\n * longer the pool's.\n *\n * The pool owns the lifetime of both textures and can destroy them without this\n * store hearing about it — a size-epoch sweep, a device-loss `clear()`. The\n * recorded handles then name destroyed textures, and binding one is a WebGPU\n * validation error that takes the whole plane's encoder down with it. Two\n * identity compares turn that into \"there is no backdrop this frame\", which the\n * optics pass already has a placeholder for: unrefracted glass for a frame,\n * rather than a dropped one.\n */\n const liveResources = (sourceId: string): PyramidResources | undefined => {\n const target = resources.get(sourceId);\n if (target === undefined) return undefined;\n if (pool.peek(poolKey.backdropChain(sourceId)) !== target.chain) return undefined;\n if (pool.peek(poolKey.backdropBody(sourceId)) !== target.body) return undefined;\n return target;\n };\n\n const mipView = (texture: GPUTexture, level: number): GPUTextureView =>\n texture.createView({ baseMipLevel: level, mipLevelCount: 1, dimension: \"2d\" });\n\n function allocate(\n sourceId: string,\n plan: PyramidPlan,\n bodyLevel: number,\n sizeEpoch: number,\n builtEpoch: number,\n ): PyramidResources {\n const existing = resources.get(sourceId);\n const bodyWidth = (plan.levels[bodyLevel] ?? plan.levels[0] as { width: number; height: number }).width;\n const bodyHeight = (plan.levels[bodyLevel] ?? plan.levels[0] as { width: number; height: number }).height;\n\n const chain = pool.acquire(poolKey.backdropChain(sourceId), {\n width: plan.width,\n height: plan.height,\n format: WORKING_TEXTURE_FORMAT,\n usage: chainUsage(),\n mipLevelCount: plan.levelCount,\n label: `vitrea:pyramid:${sourceId}:chain`,\n });\n const body = pool.acquire(poolKey.backdropBody(sourceId), {\n width: bodyWidth,\n height: bodyHeight,\n format: WORKING_TEXTURE_FORMAT,\n usage: chainUsage(),\n label: `vitrea:pyramid:${sourceId}:body`,\n });\n\n let stats = existing?.stats;\n if (stats === undefined) {\n stats = device.createBuffer({\n label: `vitrea:pyramid:${sourceId}:stats`,\n size: ANALYSIS_STATS_FLOATS * 4,\n usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,\n });\n }\n\n if (existing === undefined || existing.chain !== chain || existing.body !== body) {\n reallocations += 1;\n }\n\n const next: PyramidResources = {\n sourceId,\n plan,\n chain,\n body,\n stats,\n sizeEpoch,\n builtEpoch,\n };\n resources.set(sourceId, next);\n return next;\n }\n\n function runImport(\n encoder: GPUCommandEncoder,\n sourceId: string,\n frame: BackdropFrame,\n chain: GPUTexture,\n ): void {\n const kind = frame.binding.kind;\n const pipeline = importPipeline(kind);\n const slot = uniformSlot(`import:${sourceId}`, 16);\n const matrix = importColorMatrix(frame.colorSpace);\n\n slot.data[0] = matrix[0] as number;\n slot.data[1] = matrix[1] as number;\n slot.data[2] = matrix[2] as number;\n slot.data[3] = frame.encoded ? 1 : 0;\n slot.data[4] = matrix[3] as number;\n slot.data[5] = matrix[4] as number;\n slot.data[6] = matrix[5] as number;\n slot.data[7] = alphaNormalisationMode(frame.alphaMode);\n slot.data[8] = matrix[6] as number;\n slot.data[9] = matrix[7] as number;\n slot.data[10] = matrix[8] as number;\n slot.data[11] = 0;\n // Stretch fit: level 0 IS the source, resampled to the planned extent, so the\n // uv transform is the identity. A group's own framing of the backdrop happens\n // in the optics pass, where the viewport is known.\n slot.data[12] = 1;\n slot.data[13] = 1;\n slot.data[14] = 0;\n slot.data[15] = 0;\n slot.write();\n\n const entries: GPUBindGroupEntry[] = [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n {\n binding: 2,\n resource:\n frame.binding.kind === \"external\" ? frame.binding.texture : frame.binding.view,\n },\n ];\n\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:import:${sourceId}`,\n ...timedRender(PASS_LABEL.import),\n colorAttachments: [\n { view: mipView(chain, 0), loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(0, device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries }));\n pass.draw(3);\n pass.end();\n }\n\n function runChain(\n encoder: GPUCommandEncoder,\n sourceId: string,\n plan: PyramidPlan,\n chain: GPUTexture,\n ): void {\n const pipeline = chainPipeline(\"fs_downsample\");\n for (let level = 1; level < plan.levelCount; level += 1) {\n const source = plan.levels[level - 1] as { width: number; height: number };\n const slot = uniformSlot(`chain:${sourceId}:${level}`, 8);\n slot.data[0] = 1 / source.width;\n slot.data[1] = 1 / source.height;\n slot.data[2] = 0;\n slot.data[3] = 0;\n slot.data[4] = 0;\n slot.data[5] = 0;\n slot.data[6] = 0;\n slot.data[7] = 0;\n slot.write();\n\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:downsample:${sourceId}:${level}`,\n ...timedRender(PASS_LABEL.chain),\n colorAttachments: [\n { view: mipView(chain, level), loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n { binding: 2, resource: mipView(chain, level - 1) },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n }\n }\n\n function runBodyBlur(\n encoder: GPUCommandEncoder,\n sourceId: string,\n plan: PyramidPlan,\n chain: GPUTexture,\n body: GPUTexture,\n level: number,\n residualSigmaTexels: number,\n ): void {\n const pipeline = chainPipeline(\"fs_blur\");\n const size = plan.levels[level] ?? (plan.levels[0] as { width: number; height: number });\n const scratch = pool.acquire(poolKey.backdropBodyScratch(sourceId), {\n width: size.width,\n height: size.height,\n format: WORKING_TEXTURE_FORMAT,\n usage: chainUsage(),\n label: `vitrea:pyramid:${sourceId}:body-scratch`,\n });\n\n const stages: { target: GPUTexture; source: GPUTextureView; dir: [number, number]; tag: string }[] = [\n { target: scratch, source: mipView(chain, level), dir: [1, 0], tag: \"h\" },\n { target: body, source: scratch.createView(), dir: [0, 1], tag: \"v\" },\n ];\n\n for (const stage of stages) {\n const slot = uniformSlot(`body:${sourceId}:${stage.tag}`, 8);\n slot.data[0] = 1 / size.width;\n slot.data[1] = 1 / size.height;\n slot.data[2] = 0;\n slot.data[3] = 0;\n slot.data[4] = residualSigmaTexels;\n slot.data[5] = stage.dir[0];\n slot.data[6] = stage.dir[1];\n slot.data[7] = 0;\n slot.write();\n\n const pass = encoder.beginRenderPass({\n label: `vitrea:pass:body-blur-${stage.tag}:${sourceId}`,\n ...timedRender(PASS_LABEL.bodyBlur),\n colorAttachments: [\n { view: stage.target.createView(), loadOp: \"clear\", storeOp: \"store\", clearValue: { r: 0, g: 0, b: 0, a: 0 } },\n ],\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n { binding: 2, resource: stage.source },\n ],\n }),\n );\n pass.draw(3);\n pass.end();\n }\n }\n\n function runAnalysis(\n encoder: GPUCommandEncoder,\n sourceId: string,\n plan: PyramidPlan,\n chain: GPUTexture,\n stats: GPUBuffer,\n ): void {\n const pipeline = analysisPipeline();\n const level = plan.levels[plan.analysisLevel] ?? (plan.levels[0] as { width: number; height: number });\n const slot = uniformSlot(`analysis:${sourceId}`, 8);\n slot.data[0] = ANALYSIS_GRID;\n slot.data[1] = ANALYSIS_GRID;\n slot.data[2] = plan.analysisLevel;\n slot.data[3] = 1 / (ANALYSIS_GRID - 1);\n slot.data[4] = 1 / level.width;\n slot.data[5] = 1 / level.height;\n slot.data[6] = 0;\n slot.data[7] = 0;\n slot.write();\n\n const pass = encoder.beginComputePass({\n label: `vitrea:pass:analysis:${sourceId}`,\n ...timedCompute(PASS_LABEL.analysis),\n });\n pass.setPipeline(pipeline);\n pass.setBindGroup(\n 0,\n device.createBindGroup({\n layout: pipeline.getBindGroupLayout(0),\n entries: [\n { binding: 0, resource: { buffer: slot.buffer } },\n { binding: 1, resource: context.flatSampler },\n { binding: 2, resource: chain.createView() },\n { binding: 3, resource: { buffer: stats } },\n ],\n }),\n );\n // One workgroup: the reduction reads a fixed grid, so its cost does not\n // follow the backdrop's resolution. See wgsl/analysis.ts.\n pass.dispatchWorkgroups(1);\n pass.end();\n }\n\n return {\n instrumentation: {\n get rebuilds() {\n return ledger.rebuilds;\n },\n get refusedDuplicates() {\n return ledger.refusedDuplicates;\n },\n get skippedClean() {\n return ledger.skippedClean;\n },\n get reallocations() {\n return reallocations;\n },\n rebuildsInFrame(sourceId) {\n return ledger.countInFrame(sourceId);\n },\n get peakRebuildsPerSourcePerFrame() {\n return ledger.peakPerSourcePerFrame;\n },\n },\n\n /** The ledger the invariant is asserted against. See `rebuild-ledger.ts`. */\n ledger,\n\n beginFrame(next) {\n frameId = next;\n ledger.beginFrame(next);\n },\n\n setTimeline(next) {\n timeline = next;\n },\n\n build(request, provider, encoder) {\n // The LIVE resources, not merely the recorded ones: a clean-skip against a\n // handle the pool has already destroyed would leave the source with no\n // usable pyramid and no way back — the skip is exactly what stops the\n // reallocation that would heal it.\n const existing = liveResources(request.sourceId);\n if (\n existing !== undefined &&\n existing.builtEpoch >= request.epoch &&\n !provider.isDirty()\n ) {\n ledger.recordClean();\n return { status: \"clean\", resources: existing };\n }\n\n // Claimed BEFORE any pass is encoded: the ledger is the guard, not a\n // counter kept alongside one.\n if (!ledger.claim(request.sourceId)) {\n return { status: \"duplicate\" };\n }\n\n let frame: BackdropFrame;\n try {\n frame = provider.acquire({ id: frameId, timeMs: 0 });\n } catch (error) {\n return {\n status: \"unavailable\",\n reason: error instanceof Error ? error.message : String(error),\n };\n }\n pendingRelease.push(provider);\n\n const plan = planPyramid(frame.width, frame.height, request.resolution);\n // Source texels per CSS px, under the same cover fit the optics pass\n // samples with, times the downscale the plan actually applied (which\n // includes `maxDimension`, not just the policy's `scale`).\n const [viewportW, viewportH] = request.viewportCss;\n const cover =\n viewportW > 0 && viewportH > 0\n ? Math.max(frame.width / viewportW, frame.height / viewportH)\n : 1;\n const planScale = frame.width > 0 ? plan.width / frame.width : 1;\n const bodyPlan = bodyBlurPlan(request.bodySigmaCss * cover * planScale, plan);\n const target = allocate(\n request.sourceId,\n plan,\n bodyPlan.level,\n frame.sizeEpoch,\n request.epoch,\n );\n\n runImport(encoder, request.sourceId, frame, target.chain);\n runChain(encoder, request.sourceId, plan, target.chain);\n runBodyBlur(\n encoder,\n request.sourceId,\n plan,\n target.chain,\n target.body,\n bodyPlan.level,\n bodyPlan.residualSigmaTexels,\n );\n runAnalysis(encoder, request.sourceId, plan, target.chain, target.stats);\n\n provider.markImported();\n return { status: \"built\", resources: target };\n },\n\n releaseAcquired() {\n // In acquisition order. A provider that throws on release must not strand\n // the others — a leaked VideoFrame stalls decoding.\n while (pendingRelease.length > 0) {\n const provider = pendingRelease.shift();\n try {\n provider?.release();\n } catch {\n // Deliberately swallowed; see above.\n }\n }\n },\n\n afterSubmit() {\n // The readback maps, now that the copies they read are in the queue.\n while (pendingMaps.length > 0) {\n const sourceId = pendingMaps.shift();\n if (sourceId === undefined) continue;\n const slot = readbacks.get(sourceId);\n if (slot === undefined) continue;\n const staging = slot.staging;\n pendingStats.set(\n sourceId,\n (async () => {\n try {\n await staging.mapAsync(GPUMapMode.READ);\n const values = new Float32Array(staging.getMappedRange().slice(0));\n staging.unmap();\n return statsFromBuffer(values);\n } catch {\n return undefined;\n } finally {\n slot.inFlight = false;\n }\n })(),\n );\n }\n },\n\n resources(sourceId) {\n return liveResources(sourceId);\n },\n\n requestStats(sourceId, encoder) {\n const target = liveResources(sourceId);\n if (target === undefined) return false;\n\n let readback = readbacks.get(sourceId);\n if (readback === undefined) {\n readback = {\n staging: device.createBuffer({\n label: `vitrea:pyramid:${sourceId}:stats-staging`,\n size: ANALYSIS_STATS_FLOATS * 4,\n usage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST,\n }),\n inFlight: false,\n };\n readbacks.set(sourceId, readback);\n }\n // Single slot, no queue: if the previous map has not resolved, this frame's\n // readback is simply skipped. Queueing them is how a renderer under pressure\n // accumulates stale buffers, and two answers from the same frame are no more\n // useful than one.\n if (readback.inFlight) return false;\n\n encoder.copyBufferToBuffer(target.stats, 0, readback.staging, 0, ANALYSIS_STATS_FLOATS * 4);\n readback.inFlight = true;\n // The map is NOT started here. `mapAsync` makes a buffer unavailable to\n // submits from the moment it is called, and the copy just encoded has not\n // been submitted yet — starting the map now makes this frame's own submit\n // invalid with \"used in submit while mapped\". So the map is deferred to\n // `afterSubmit`.\n pendingMaps.push(sourceId);\n return true;\n },\n\n async collectStats() {\n const out = new Map<string, BackdropStats>();\n const entries = [...pendingStats];\n pendingStats.clear();\n for (const [sourceId, promise] of entries) {\n const stats = await promise;\n if (stats !== undefined) out.set(sourceId, stats);\n }\n return out;\n },\n\n forget(sourceId) {\n pool.release(poolKey.backdropChain(sourceId));\n pool.release(poolKey.backdropBody(sourceId));\n pool.release(poolKey.backdropBodyScratch(sourceId));\n resources.get(sourceId)?.stats.destroy();\n resources.delete(sourceId);\n readbacks.get(sourceId)?.staging.destroy();\n readbacks.delete(sourceId);\n pendingStats.delete(sourceId);\n const queued = pendingMaps.indexOf(sourceId);\n if (queued >= 0) pendingMaps.splice(queued, 1);\n },\n\n destroy() {\n for (const sourceId of [...resources.keys()]) this.forget(sourceId);\n for (const slot of uniforms.values()) slot.buffer.destroy();\n uniforms.clear();\n pendingRelease.length = 0;\n pendingMaps.length = 0;\n },\n };\n}\n\n/** Exposed so a test can assert the workgroup size the reduction was written for. */\nexport const ANALYSIS_DISPATCH = { workgroupSize: ANALYSIS_WORKGROUP, workgroups: 1 } as const;\n","/**\n * The renderer: device, resources, and the frame.\n *\n * Two entry points, deliberately:\n *\n * - **`drawFrame`** — draw one frame into two texture views. No scene, no\n * scheduler, no DOM. This is what the golden suite and the benchmark drive, and\n * what makes the optical maths testable without standing up the whole runtime.\n * - **`frameParticipant`** — the same work split across core's `write` and\n * `render` phases, so `vitrea`'s scheduler drives it alongside\n * platform-web's DOM participant. Pyramid rebuilds land in `write` because that\n * is the phase core hands them out in; drawing lands in `render`, with the graph\n * frozen.\n *\n * The participant reads the frame's `resolution` when core supplies one, and\n * prefers it over the group input's own `refraction`/`analysis` — core is the\n * authority on resolved state (X2), and it is the frame's resolution that has been\n * through the whole transition table. The group input's copies are the fallback for\n * `drawFrame`, where there is no core.\n *\n * ## Device generations\n *\n * Everything GPU-shaped hangs off a `GpuContext` tagged with the device generation\n * that made it. On loss the context is dropped whole, and the first frame on the\n * replacement re-points every registered provider at the new device and marks it\n * for re-import — so recovery flows through the ordinary\n * one-rebuild-per-dirty-source-per-frame path instead of a special case, which\n * means the recovery path is exercised by the same tests as the steady state.\n *\n * `ensureContext` is where that happens rather than the loss teardown, and the\n * reason is timing: the teardown runs while there is no device to adopt, and this\n * is the one place that knows both that a generation was superseded and what\n * replaced it. It also runs before anything acquires on the new device, which the\n * teardown cannot promise.\n *\n * The one provider that cannot be re-pointed is a backdrop over the *app's* own\n * texture: WebGPU has no cross-device sharing and the renderer does not own the\n * texture, so that provider refuses instead, and the refused rebuild is reported\n * through `unbuiltSources` for the host to act on.\n */\n\nimport { DEFAULT_GROUP_UNION, type GroupUnionParams } from \"@vitrea/geometry\";\n\nimport { createAdaptationState, readbackDue, type AdaptationState } from \"./analysis\";\nimport type { BackdropProvider } from \"./backdrop\";\nimport { OUTPUT_TEXTURE_FORMAT } from \"./color\";\nimport {\n createDeviceHost,\n type DeviceCapabilityInput,\n type DeviceHost,\n type DeviceOwnership,\n type RendererDeviceStatus,\n} from \"./device\";\nimport { rendererError } from \"./errors\";\nimport { createGpuContext, type GpuContext } from \"./gpu-context\";\nimport { createGovernor, type Governor } from \"./governor\";\nimport {\n clipFieldRectToCanvas,\n groupFieldRect,\n packInstances,\n resolveSurfaces,\n snapRectToDevicePixels,\n type ResolvedSurface,\n} from \"./instances\";\nimport {\n accessibilityRefractionCap,\n adaptationStrength,\n DEFAULT_MATERIAL_PROFILE,\n effectiveRefraction,\n opticsUnderPolicy,\n withMaterialOverrides,\n type MaterialPolicyView,\n type MaterialProfile,\n type MaterialProfilePatch,\n type MaterialVariant,\n} from \"./material\";\nimport { createPassRunner, type DeviceRect, type PassRunner } from \"./passes\";\nimport { createPyramidStore, type PyramidStore } from \"./pyramid\";\nimport type {\n FrameContextView,\n FrameParticipantView,\n GroupRenderInput,\n RebuildRequestView,\n SceneResolutionView,\n} from \"./render-model\";\nimport type { TimingCollector } from \"./timing\";\nimport { allShaderSource } from \"./wgsl\";\n\nexport const OPTICS_PASS_ID = \"vitrea.optics\";\nexport const HIGHLIGHT_PASS_ID = \"vitrea.highlight\";\nexport const FIELD_PASS_ID = \"vitrea.field\";\nexport const BACKDROP_PASS_ID = \"vitrea.backdrop\";\nexport const ANALYSIS_PASS_ID = \"vitrea.analysis\";\n\nexport const RENDERER_PASS_IDS = [\n BACKDROP_PASS_ID,\n ANALYSIS_PASS_ID,\n FIELD_PASS_ID,\n OPTICS_PASS_ID,\n HIGHLIGHT_PASS_ID,\n] as const;\n\n/** Nominal accessibility material policy — nothing capped. Mirrors core's. */\nexport const NOMINAL_MATERIAL_POLICY: MaterialPolicyView = {\n glass: \"material\",\n frost: \"nominal\",\n refraction: \"nominal\",\n occlusion: \"nominal\",\n border: \"nominal\",\n ambientTint: \"nominal\",\n foreground: \"adaptive\",\n};\n\nexport interface ViewportState {\n /** Viewport size in CSS px. */\n readonly widthCss: number;\n readonly heightCss: number;\n readonly devicePixelRatio: number;\n}\n\nexport interface RendererInstrumentation {\n readonly pyramid: PyramidStore[\"instrumentation\"];\n readonly texturePool: { readonly live: number; readonly created: number; readonly destroyed: number };\n readonly pipelines: { readonly renderPipelines: number; readonly computePipelines: number };\n readonly framesDrawn: number;\n readonly deviceGenerations: number;\n}\n\nexport interface DrawFrameArgs {\n readonly frame: { readonly id: number; readonly timeMs: number };\n /** The optics canvas' current texture view. */\n readonly optics: GPUTextureView;\n /** The highlight canvas' view. Omit to skip the highlight pass entirely. */\n readonly highlight?: GPUTextureView;\n readonly format?: GPUTextureFormat;\n /**\n * The rebuild requests core handed out. Omitted means \"ask every registered\n * provider whether it is dirty\", which is what `drawFrame` does standalone.\n */\n readonly rebuild?: readonly RebuildRequestView[];\n /** Core's resolved state for this frame. Overrides the group inputs' copies. */\n readonly resolution?: SceneResolutionView;\n readonly timing?: TimingCollector;\n /** Clear the targets first. Default true. */\n readonly clear?: boolean;\n}\n\nexport interface DrawFrameResult {\n readonly groupsDrawn: number;\n readonly rebuilds: number;\n readonly skipped: readonly { readonly groupId: string; readonly reason: string }[];\n /**\n * Source ids core handed out a rebuild for that this frame did **not** build.\n * The same list as `GlassRenderer.unbuiltSources` — see it for what a caller\n * owes.\n */\n readonly unbuilt: readonly string[];\n}\n\nexport interface WebGPURendererOptions {\n /** An app-owned device. Given one, the renderer never requests its own. */\n readonly device?: GPUDevice;\n readonly ownership?: DeviceOwnership;\n /** Re-request a vitrea-owned device after loss. */\n readonly reacquire?: () => Promise<GPUDevice | undefined>;\n readonly onReplacementNeeded?: () => void;\n readonly onDeviceStatusChange?: (status: RendererDeviceStatus) => void;\n /** Whether family C's f32 cross-check has passed (Decision Log #20). */\n readonly familyCVerified?: boolean;\n readonly viewport?: ViewportState;\n /**\n * Optical tunables to override, on top of `DEFAULT_MATERIAL_PROFILE`. This is\n * where a calibrated set lands (C7): a patch, not a whole profile, so a host\n * naming one tint alpha inherits every number it did not measure.\n */\n readonly materialProfile?: MaterialProfilePatch;\n}\n\nexport interface GlassRenderer {\n readonly backend: \"webgpu\";\n /** True only with a live, unlost device attached. */\n readonly ready: boolean;\n readonly passes: readonly string[];\n readonly shaderSource: string;\n readonly deviceStatus: RendererDeviceStatus;\n /** The facts a host folds into core's `PlatformProbe`. */\n readonly capabilityInput: DeviceCapabilityInput;\n readonly governor: Governor;\n readonly instrumentation: RendererInstrumentation;\n /**\n * The source ids the most recent frame was handed a rebuild for and did not\n * build — because no provider is registered under the id, or because the\n * provider could not serve a frame.\n *\n * This exists because core commits `builtEpoch` when it *hands out* the\n * request, not when the renderer finishes: a request dropped here is a claim\n * spent on nothing, and the source would sit clean at an epoch whose pixels\n * were never imported. Core has no view of this side of the wire, so the\n * renderer names the losses and the platform layer re-dirties them — one frame\n * of latency, and no new core surface.\n *\n * Accumulated across the frame's planes, not per `drawFrame` call: a host draws\n * one plane per call with the same frame id and hands the dirty set to the\n * first of them only, so a later plane's empty answer must not erase what the\n * first one found. Read after the frame's last plane, or after the\n * participant's `render` phase. Empty on every ordinary frame.\n */\n readonly unbuiltSources: readonly string[];\n\n attachDevice(device: GPUDevice, ownership?: DeviceOwnership): void;\n replaceDevice(device: GPUDevice): void;\n markWebGPUUnavailable(reason: \"no-adapter\" | \"device-request-failed\"): void;\n\n registerBackdrop(provider: BackdropProvider): void;\n unregisterBackdrop(sourceId: string): void;\n backdrop(sourceId: string): BackdropProvider | undefined;\n\n setViewport(viewport: ViewportState): void;\n readonly viewport: ViewportState;\n\n setGroup(input: GroupRenderInput): void;\n removeGroup(groupId: string): void;\n setAccessibility(policy: MaterialPolicyView): void;\n /**\n * Replace the optical tunables. The patch is applied to\n * `DEFAULT_MATERIAL_PROFILE`, never to the profile currently in force, so two\n * calls do not compound — a profile is a set of measurements, and half of one\n * measurement set over half of another describes no material.\n */\n setMaterialProfile(patch: MaterialProfilePatch): void;\n /** The tunables in force. Read-only; `setMaterialProfile` is the way in. */\n readonly materialProfile: MaterialProfile;\n\n drawFrame(args: DrawFrameArgs): DrawFrameResult;\n /** Targets for the participant path, where core drives the phases. */\n setTargets(targets: { readonly optics: GPUTextureView; readonly highlight?: GPUTextureView; readonly format?: GPUTextureFormat }): void;\n frameParticipant(): FrameParticipantView;\n\n /** Resolve any completed analysis readbacks into the adaptation drivers. */\n collectAdaptation(): Promise<number>;\n destroy(): void;\n}\n\ninterface GroupEntry {\n readonly input: GroupRenderInput;\n}\n\nexport function createWebGPURenderer(options: WebGPURendererOptions = {}): GlassRenderer {\n const providers = new Map<string, BackdropProvider>();\n const groups = new Map<string, GroupEntry>();\n const adaptation = new Map<string, AdaptationState>();\n const lastReadbackAt = new Map<string, number>();\n\n let accessibility: MaterialPolicyView = NOMINAL_MATERIAL_POLICY;\n let material: MaterialProfile = withMaterialOverrides(\n DEFAULT_MATERIAL_PROFILE,\n options.materialProfile ?? {},\n );\n let viewport: ViewportState = options.viewport ?? {\n widthCss: 0,\n heightCss: 0,\n devicePixelRatio: 1,\n };\n let context: GpuContext | undefined;\n /**\n * The last device generation a context was built for. Kept apart from\n * `context` because it has to survive `dropContext()` — the loss teardown runs\n * long before the replacement arrives, and \"which generation did the providers\n * build against\" is the question the replacement has to answer.\n */\n let builtGeneration: number | undefined;\n let store: PyramidStore | undefined;\n let runner: PassRunner | undefined;\n let framesDrawn = 0;\n let generations = 0;\n let lastFrameTimeMs: number | undefined;\n let targets:\n | { optics: GPUTextureView; highlight?: GPUTextureView; format: GPUTextureFormat }\n | undefined;\n let pendingEncoder: GPUCommandEncoder | undefined;\n let pendingRebuilds = 0;\n let pendingUnbuilt: string[] = [];\n let unbuiltFrameId: number | undefined;\n\n /**\n * Accumulate the frame's unbuilt sources, across planes.\n *\n * A host draws one plane per `drawFrame` with the same frame id and hands the\n * dirty set to the first of them only, so the later planes' empty lists must\n * not erase what the first one found. Same rule as the rebuild ledger's, for\n * the same reason: a repeated frame id is one frame.\n */\n const recordUnbuilt = (frameId: number, ids: readonly string[]): void => {\n if (unbuiltFrameId !== frameId) {\n unbuiltFrameId = frameId;\n pendingUnbuilt = [];\n }\n for (const id of ids) if (!pendingUnbuilt.includes(id)) pendingUnbuilt.push(id);\n };\n\n const governor = createGovernor({\n ...(options.familyCVerified === undefined ? {} : { familyCVerified: options.familyCVerified }),\n });\n\n const dropContext = (): void => {\n store?.destroy();\n runner?.destroy();\n context?.destroy();\n store = undefined;\n runner = undefined;\n context = undefined;\n pendingEncoder = undefined;\n };\n\n const host: DeviceHost = createDeviceHost({\n ...(options.reacquire === undefined ? {} : { reacquire: options.reacquire }),\n ...(options.onReplacementNeeded === undefined\n ? {}\n : { onReplacementNeeded: options.onReplacementNeeded }),\n onStatusChange: (status) => {\n if (status.generation !== generations) generations = status.generation;\n options.onDeviceStatusChange?.(status);\n },\n });\n\n // Loss teardown: drop every resource, and mark every backdrop for re-import so\n // recovery uses the ordinary dirty path. Registered once — the hook survives\n // every generation, because the host outlives the contexts.\n host.addTeardownHook(() => {\n dropContext();\n adaptation.clear();\n lastReadbackAt.clear();\n });\n\n const ensureContext = (): { context: GpuContext; store: PyramidStore; runner: PassRunner } => {\n const device = host.requireDevice();\n const generation = host.status.generation;\n if (context === undefined || context.generation !== generation) {\n const superseded = builtGeneration;\n dropContext();\n context = createGpuContext(device, generation);\n builtGeneration = generation;\n store = createPyramidStore(context);\n runner = createPassRunner(context);\n // The providers outlive the context, and every one of them closes over the\n // device it was built with. Re-pointing them here — rather than in the loss\n // teardown — is what makes the timing right: this is the one place that\n // knows both that a device generation was superseded and what replaced it,\n // and it runs before any provider is acquired on the new device.\n //\n // Only a real transition invalidates. A provider registered before any\n // device existed has built nothing to throw away, and one already tagged\n // with this generation was built for this device.\n if (superseded !== undefined && superseded !== generation) {\n for (const provider of providers.values()) {\n if (provider.generation !== generation) provider.invalidate(generation, device);\n }\n }\n }\n return {\n context,\n store: store as PyramidStore,\n runner: runner as PassRunner,\n };\n };\n\n const adaptationFor = (sourceId: string): AdaptationState => {\n let state = adaptation.get(sourceId);\n if (state === undefined) {\n state = createAdaptationState(undefined, material);\n adaptation.set(sourceId, state);\n }\n return state;\n };\n\n /**\n * Cover fit: the backdrop fills the viewport and the overflow is cropped\n * symmetrically. Returned as a scale/offset on viewport-normalised coordinates,\n * which is the form the optics shader applies.\n */\n const coverFit = (\n sourceWidth: number,\n sourceHeight: number,\n ): readonly [number, number, number, number] => {\n const viewportAspect =\n viewport.heightCss > 0 ? viewport.widthCss / viewport.heightCss : 1;\n const sourceAspect = sourceHeight > 0 ? sourceWidth / sourceHeight : 1;\n if (sourceAspect > viewportAspect) {\n const scaleX = viewportAspect / sourceAspect;\n return [scaleX, 1, (1 - scaleX) / 2, 0];\n }\n const scaleY = sourceAspect / viewportAspect;\n return [1, scaleY, 0, (1 - scaleY) / 2];\n };\n\n const unionOf = (input: GroupRenderInput): GroupUnionParams =>\n input.union ?? DEFAULT_GROUP_UNION;\n\n const variantOf = (input: GroupRenderInput): MaterialVariant => input.variant ?? \"regular\";\n\n const stateOf = (\n input: GroupRenderInput,\n resolution: SceneResolutionView | undefined,\n ): { refraction: GroupRenderInput[\"refraction\"]; analysisExact: boolean } => {\n const resolved = resolution?.groups.find((group) => group.groupId === input.groupId);\n if (resolved === undefined) {\n return { refraction: input.refraction, analysisExact: input.analysisExact };\n }\n return {\n refraction: resolved.state.refraction,\n analysisExact: resolved.state.analysis === \"exact\",\n };\n };\n\n function rebuildRequests(explicit: readonly RebuildRequestView[] | undefined): readonly RebuildRequestView[] {\n if (explicit !== undefined) return explicit;\n // Standalone path: ask each provider a group actually samples.\n const sampled = new Set<string>();\n for (const entry of groups.values()) {\n const id = entry.input.backdropSourceId;\n if (id !== undefined) sampled.add(id);\n }\n const requests: RebuildRequestView[] = [];\n for (const sourceId of sampled) {\n const provider = providers.get(sourceId);\n if (provider === undefined || !provider.isDirty()) continue;\n requests.push({\n sourceId,\n // Standalone, every dirty acquire is its own epoch: there is no core\n // keeping the books, so a monotonically rising number is the honest\n // stand-in and it keeps `build`'s clean-skip from firing spuriously.\n epoch: framesDrawn + 1,\n resolution: { scale: 1, maxDimension: 2048 },\n groupIds: [...groups.values()]\n .filter((entry) => entry.input.backdropSourceId === sourceId)\n .map((entry) => entry.input.groupId),\n });\n }\n return requests;\n }\n\n function runRebuilds(\n encoder: GPUCommandEncoder,\n requests: readonly RebuildRequestView[],\n frameTimeMs: number,\n ): { built: number; unbuilt: readonly string[] } {\n const { store: pyramids } = ensureContext();\n let built = 0;\n const unbuilt: string[] = [];\n\n for (const request of requests) {\n const provider = providers.get(request.sourceId);\n if (provider === undefined) {\n // Core spent the claim on a source this renderer has never heard of — a\n // group registered ahead of its backdrop, or a source unregistered\n // between the hand-out and here.\n unbuilt.push(request.sourceId);\n continue;\n }\n\n const variant = variantOf(\n [...groups.values()].find(\n (entry) => entry.input.backdropSourceId === request.sourceId,\n )?.input ?? { groupId: \"\", surfaces: [], refraction: \"none\", analysisExact: false },\n );\n const optics = opticsUnderPolicy(material.optics[variant], accessibility, material);\n\n const outcome = pyramids.build(\n {\n sourceId: request.sourceId,\n epoch: request.epoch,\n resolution: request.resolution,\n bodySigmaCss: optics.blurSigma,\n viewportCss: [viewport.widthCss, viewport.heightCss],\n },\n provider,\n encoder,\n );\n if (outcome.status === \"built\") built += 1;\n // \"clean\" and \"duplicate\" are both honest answers — the source already has\n // the pixels this epoch asked for. \"unavailable\" is not: the claim is spent\n // and nothing was imported.\n else if (outcome.status === \"unavailable\") unbuilt.push(request.sourceId);\n }\n\n // Analysis readback, cadence-gated by the governor. Every source with a\n // pyramid is eligible, whether or not it rebuilt this frame — a static\n // backdrop still needs its stats read once.\n const cadence = governor.knobs.adaptationCadenceHz;\n for (const sourceId of providers.keys()) {\n if (pyramids.resources(sourceId) === undefined) continue;\n if (!readbackDue(lastReadbackAt.get(sourceId), frameTimeMs, cadence)) continue;\n if (pyramids.requestStats(sourceId, encoder)) lastReadbackAt.set(sourceId, frameTimeMs);\n }\n\n return { built, unbuilt };\n }\n\n function drawGroups(\n encoder: GPUCommandEncoder,\n resolution: SceneResolutionView | undefined,\n ): DrawFrameResult {\n const { store: pyramids, runner: passes } = ensureContext();\n const active = targets;\n if (active === undefined) {\n throw rendererError(\n \"pass-input\",\n \"No render targets are set. Call setTargets() (or pass views to drawFrame) before drawing.\",\n );\n }\n\n const dpr = Math.max(viewport.devicePixelRatio, 1e-3);\n const cssPerDevice = 1 / dpr;\n const viewportDevice: readonly [number, number] = [\n Math.max(1, Math.round(viewport.widthCss * dpr)),\n Math.max(1, Math.round(viewport.heightCss * dpr)),\n ];\n\n const skipped: { groupId: string; reason: string }[] = [];\n let drawn = 0;\n\n for (const entry of groups.values()) {\n const input = entry.input;\n if (input.surfaces.length === 0) continue;\n\n let surfaces: readonly ResolvedSurface[];\n try {\n surfaces = resolveSurfaces(input, governor.knobs.fieldFamily, material);\n } catch (error) {\n skipped.push({\n groupId: input.groupId,\n reason: error instanceof Error ? error.message : String(error),\n });\n continue;\n }\n\n const union = unionOf(input);\n /*\n * Clipped to the plane canvas, and clipped once, so that three things go on\n * describing the same rectangle.\n *\n * `groupFieldRect` grows the surface union by the rim and bulge margin, so a\n * surface within a few CSS px of the viewport's top or left edge produces a\n * rect with a negative origin. `opticsPass` and `highlightPass` scissor to\n * this rect on the plane canvas and `setScissorRect` takes unsigned values,\n * so an unclipped rect is a hard `RangeError` out of the WebGPU binding\n * rather than a clipped draw. A toolbar pinned to the left edge is enough to\n * hit it.\n *\n * The clip has to reach the instance frame too. The field texture is\n * allocated at this rect's size and `fs_optics` reads it by `uv` over the\n * *viewport*, so moving the viewport without moving the texture and the\n * instance origin with it would stretch the glass instead of clipping it.\n * That is why the origin handed to `packInstances` is derived from the\n * clipped device rect rather than from the CSS rect it came from. What is\n * lost is the part of the field that lies outside the canvas, which is the\n * part nothing can see.\n *\n * A group entirely on screen is unaffected: `snapRectToDevicePixels` has\n * already put both edges on device-pixel boundaries, so the arithmetic below\n * reproduces the previous origin and extent exactly.\n */\n const snapped = snapRectToDevicePixels(groupFieldRect(surfaces, union), dpr);\n const rectDevice: DeviceRect | undefined = clipFieldRectToCanvas(snapped, dpr, viewportDevice);\n if (rectDevice === undefined) continue;\n\n const packed = packInstances(surfaces, [\n rectDevice.x * cssPerDevice,\n rectDevice.y * cssPerDevice,\n ]);\n const fields = passes.fieldPass(encoder, {\n groupId: input.groupId,\n family: governor.knobs.fieldFamily,\n rectDevice,\n cssPerDevice,\n coverageRampCss: cssPerDevice,\n // Ladder rungs 2 and 3 turn this down; rung 0 and 1 leave it at 1, which\n // is the extent the group's rect already had.\n renderScale: governor.knobs.refractionResolutionScale,\n instances: packed.data,\n instanceCount: packed.count,\n union,\n });\n\n const state = stateOf(input, resolution);\n const policy = resolution?.accessibility.material ?? accessibility;\n const variant = variantOf(input);\n const optics = opticsUnderPolicy(material.optics[variant], policy, material);\n\n // Decision Log #19's dual cap, resolved once, on the CPU.\n const refraction = effectiveRefraction(\n accessibilityRefractionCap(policy),\n state.refraction,\n );\n const refractionScale = material.refractionScale[refraction];\n\n const sourceId = input.backdropSourceId;\n const pyramid = sourceId === undefined ? undefined : pyramids.resources(sourceId);\n const adapt =\n sourceId === undefined ? undefined : adaptationFor(sourceId).values;\n\n passes.opticsPass(encoder, {\n groupId: input.groupId,\n target: active.optics,\n targetFormat: active.format,\n rectDevice,\n fields,\n viewportDevice,\n cssPerDevice,\n coverageRampCss: cssPerDevice,\n fit:\n pyramid === undefined\n ? [1, 1, 0, 0]\n : coverFit(pyramid.plan.width, pyramid.plan.height),\n refractionScale,\n bodyLodPerPx: material.lensBodyLodPerPx,\n rimLodBias: material.lensRimLodBias,\n chainMaxLod: pyramid?.plan.maxLod ?? 0,\n tint: optics.tint,\n tintAlpha: optics.tintAlpha,\n adaptTint: adapt?.tint ?? optics.tint,\n adaptStrength:\n adapt?.observed === true\n ? adaptationStrength(policy, state.analysisExact, material)\n : 0,\n rimWidth: optics.rimWidth,\n rimAlpha: optics.rimAlpha,\n specularPower: optics.specularPower,\n specularGain: optics.specularGain,\n lightDirection: material.lightDirection,\n shadowDepth: optics.shadowDepth,\n shadowAlpha: optics.shadowAlpha,\n backdrop:\n pyramid === undefined || policy.glass === \"none\"\n ? undefined\n : {\n chain: pyramid.chain.createView(),\n body: pyramid.body.createView(),\n },\n });\n\n if (active.highlight !== undefined) {\n // One sweep phase and one press point per group: there is one pointer, and\n // a sweep travelling the container's unioned contour is what a\n // GlassEffectContainer is for. The per-pixel glow comes off the aux target.\n const lead = surfaces.reduce(\n (best, surface) => (surface.channels.glow > best.channels.glow ? surface : best),\n surfaces[0] as ResolvedSurface,\n );\n passes.highlightPass(encoder, {\n groupId: input.groupId,\n target: active.highlight,\n targetFormat: active.format,\n rectDevice,\n fields,\n viewportDevice,\n cssPerDevice,\n sweep: lead.channels.sweep,\n sweepBandRadians: material.sweepBandRadians,\n // Reduced Motion removes shimmer travel outright rather than freezing it.\n sweepGain: policy.glass === \"none\" ? 0 : material.sweepGain,\n rimWidth: optics.rimWidth,\n pressPointCss: lead.channels.pressPoint ?? lead.centre,\n glowRadiusCss: material.glowRadiusCss,\n glowGain: material.glowGain,\n colour: optics.highlight,\n });\n }\n\n drawn += 1;\n }\n\n return { groupsDrawn: drawn, rebuilds: pendingRebuilds, skipped, unbuilt: [...pendingUnbuilt] };\n }\n\n return {\n backend: \"webgpu\",\n\n get ready() {\n return host.status.device !== undefined && host.status.deviceHealth === \"ok\";\n },\n\n passes: RENDERER_PASS_IDS,\n shaderSource: allShaderSource(),\n\n get deviceStatus() {\n return host.status;\n },\n\n get capabilityInput() {\n return host.capabilityInput;\n },\n\n governor,\n\n get unbuiltSources() {\n return pendingUnbuilt;\n },\n\n get instrumentation() {\n const pool = context?.pool.stats;\n const cache = context?.cache.stats;\n return {\n pyramid:\n store?.instrumentation ?? {\n rebuilds: 0,\n refusedDuplicates: 0,\n skippedClean: 0,\n reallocations: 0,\n rebuildsInFrame: () => 0,\n peakRebuildsPerSourcePerFrame: 0,\n },\n texturePool: {\n live: pool?.live ?? 0,\n created: pool?.created ?? 0,\n destroyed: pool?.destroyed ?? 0,\n },\n pipelines: {\n renderPipelines: cache?.renderPipelines ?? 0,\n computePipelines: cache?.computePipelines ?? 0,\n },\n framesDrawn,\n deviceGenerations: generations,\n };\n },\n\n attachDevice(device, ownership) {\n host.attach(device, ownership ?? options.ownership ?? (options.device === device ? \"app\" : \"vitrea\"));\n },\n\n replaceDevice(device) {\n host.replaceDevice(device);\n },\n\n markWebGPUUnavailable(reason) {\n host.markUnavailable(reason);\n },\n\n registerBackdrop(provider) {\n if (providers.has(provider.id)) {\n throw rendererError(\n \"source-identity\",\n `Backdrop source \"${provider.id}\" is already registered. Unregister it first, or register the replacement under a new id.`,\n provider.id,\n );\n }\n providers.set(provider.id, provider);\n },\n\n unregisterBackdrop(sourceId) {\n const provider = providers.get(sourceId);\n if (provider === undefined) return;\n provider.destroy();\n providers.delete(sourceId);\n store?.forget(sourceId);\n adaptation.delete(sourceId);\n lastReadbackAt.delete(sourceId);\n },\n\n backdrop(sourceId) {\n return providers.get(sourceId);\n },\n\n setViewport(next) {\n const changed =\n next.widthCss !== viewport.widthCss ||\n next.heightCss !== viewport.heightCss ||\n next.devicePixelRatio !== viewport.devicePixelRatio;\n viewport = next;\n if (!changed) return;\n // A resize bumps the size epoch, which is what invalidates every dependent\n // allocation (§GPU device ownership) — group field textures included, since\n // their device extent is a function of the DPR.\n //\n // The bump alone, deliberately: `pool.acquire` destroys and reallocates a\n // stale-epoch entry on next use, so every allocation is replaced exactly\n // when it is next needed. Sweeping here instead destroyed the backdrop\n // chain and body textures *immediately*, and a static source rebuilds\n // nothing — so the very next frame bound two destroyed textures and lost\n // the whole plane's encoder to a validation error. Deferring costs one\n // frame's worth of superseded textures and nothing else.\n context?.pool.bumpSizeEpoch();\n },\n\n get viewport() {\n return viewport;\n },\n\n setGroup(input) {\n groups.set(input.groupId, { input });\n },\n\n removeGroup(groupId) {\n groups.delete(groupId);\n runner?.forget(groupId);\n },\n\n setAccessibility(policy) {\n accessibility = policy;\n },\n\n setMaterialProfile(patch) {\n material = withMaterialOverrides(DEFAULT_MATERIAL_PROFILE, patch);\n // The adaptation filters carry the old profile's tint ends, so they are\n // dropped rather than left to interpolate between two materials. Everything\n // else on the draw path reads the profile per frame, so the next frame\n // redraws with the new numbers on its own.\n adaptation.clear();\n },\n\n get materialProfile() {\n return material;\n },\n\n setTargets(next) {\n targets = {\n optics: next.optics,\n ...(next.highlight === undefined ? {} : { highlight: next.highlight }),\n format: next.format ?? OUTPUT_TEXTURE_FORMAT,\n };\n },\n\n drawFrame(args) {\n const { context: gpu, store: pyramids, runner: passes } = ensureContext();\n targets = {\n optics: args.optics,\n ...(args.highlight === undefined ? {} : { highlight: args.highlight }),\n format: args.format ?? OUTPUT_TEXTURE_FORMAT,\n };\n\n pyramids.beginFrame(args.frame.id);\n pyramids.setTimeline(args.timing);\n passes.setTimeline(args.timing);\n\n const encoder = gpu.device.createCommandEncoder({\n label: `vitrea:frame:${args.frame.id}`,\n });\n\n let result: DrawFrameResult;\n try {\n const rebuilt = runRebuilds(encoder, rebuildRequests(args.rebuild), args.frame.timeMs);\n pendingRebuilds = rebuilt.built;\n recordUnbuilt(args.frame.id, rebuilt.unbuilt);\n\n if (args.clear !== false) {\n passes.clearPass(encoder, args.optics);\n if (args.highlight !== undefined) passes.clearPass(encoder, args.highlight);\n }\n\n result = drawGroups(encoder, args.resolution);\n\n args.timing?.resolve(encoder);\n gpu.device.queue.submit([encoder.finish()]);\n // Success path only: starting a readback map for a copy that never\n // reached the queue is its own bug (see `requestStats`).\n pyramids.afterSubmit();\n } finally {\n // Owed whether or not the frame reached the queue. A throw anywhere above\n // leaves an acquired video held across the frame, and the next acquire\n // then fails the frame-protocol check — self-healing, but only after a\n // wasted frame and a decoder buffer nobody released.\n pyramids.releaseAcquired();\n }\n\n // Advance the adaptation filters by the real frame delta. The drivers are\n // frame-rate invariant by construction (§Motion), so a dropped frame and two\n // short ones produce the same value.\n const delta = lastFrameTimeMs === undefined ? 0 : args.frame.timeMs - lastFrameTimeMs;\n lastFrameTimeMs = args.frame.timeMs;\n if (delta > 0) {\n for (const state of adaptation.values()) state.advance(delta);\n }\n\n framesDrawn += 1;\n pyramids.setTimeline(undefined);\n passes.setTimeline(undefined);\n return result;\n },\n\n frameParticipant() {\n return {\n id: \"vitrea.renderer-webgpu\",\n\n write: (frameContext: FrameContextView) => {\n if (host.status.device === undefined || host.status.deviceHealth !== \"ok\") return;\n const { context: gpu, store: pyramids, runner: passes } = ensureContext();\n\n pyramids.beginFrame(frameContext.frame.id);\n pyramids.setTimeline(undefined);\n passes.setTimeline(undefined);\n\n pendingEncoder = gpu.device.createCommandEncoder({\n label: `vitrea:frame:${frameContext.frame.id}`,\n });\n // Core hands out the frame's rebuilds here and only here: one pass over\n // the dirty set per frame id, which is the §Core model invariant's other\n // half. This renderer's own ledger is what proves it kept its side.\n try {\n const rebuilt = runRebuilds(\n pendingEncoder,\n frameContext.consumeDirtyBackdropSources(),\n frameContext.frame.timeMs,\n );\n pendingRebuilds = rebuilt.built;\n recordUnbuilt(frameContext.frame.id, rebuilt.unbuilt);\n } catch (error) {\n // Nothing will submit this encoder, so the releases owed for what was\n // already acquired have to happen here rather than in `render`.\n pendingEncoder = undefined;\n pyramids.releaseAcquired();\n throw error;\n }\n },\n\n render: (frameContext: FrameContextView) => {\n const encoder = pendingEncoder;\n pendingEncoder = undefined;\n if (encoder === undefined || context === undefined) return;\n const passes = runner as PassRunner;\n const pyramids = store as PyramidStore;\n\n try {\n if (targets !== undefined) {\n passes.clearPass(encoder, targets.optics);\n if (targets.highlight !== undefined) passes.clearPass(encoder, targets.highlight);\n drawGroups(encoder, frameContext.resolution);\n }\n\n context.device.queue.submit([encoder.finish()]);\n pyramids.afterSubmit();\n } finally {\n pyramids.releaseAcquired();\n }\n\n const delta =\n lastFrameTimeMs === undefined ? 0 : frameContext.frame.timeMs - lastFrameTimeMs;\n lastFrameTimeMs = frameContext.frame.timeMs;\n if (delta > 0) {\n for (const state of adaptation.values()) state.advance(delta);\n }\n framesDrawn += 1;\n },\n };\n },\n\n async collectAdaptation() {\n if (store === undefined) return 0;\n const stats = await store.collectStats();\n for (const [sourceId, value] of stats) {\n const state = adaptationFor(sourceId);\n // The first observation jumps rather than filters: a 500 ms low-pass\n // starting from zero would fade the material in from black over half a\n // second on every page load.\n if (state.values.observed) state.observe(value);\n else state.reset(value);\n }\n return stats.size;\n },\n\n destroy() {\n for (const provider of providers.values()) provider.destroy();\n providers.clear();\n groups.clear();\n adaptation.clear();\n lastReadbackAt.clear();\n pendingUnbuilt = [];\n unbuiltFrameId = undefined;\n builtGeneration = undefined;\n dropContext();\n host.destroy();\n },\n };\n}\n"]}
|