avbridge 2.12.0 → 2.13.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +177 -0
  2. package/README.md +33 -0
  3. package/dist/{avi-EQE6AR75.cjs → avi-32UABODO.cjs} +12 -4
  4. package/dist/avi-32UABODO.cjs.map +1 -0
  5. package/dist/{avi-Y3N325WZ.cjs → avi-5BPR6QUX.cjs} +12 -4
  6. package/dist/avi-5BPR6QUX.cjs.map +1 -0
  7. package/dist/{avi-NNHH4AAA.js → avi-BLIH7KKV.js} +12 -4
  8. package/dist/avi-BLIH7KKV.js.map +1 -0
  9. package/dist/{avi-S7EY54YA.js → avi-GX2H34IQ.js} +12 -4
  10. package/dist/avi-GX2H34IQ.js.map +1 -0
  11. package/dist/{chunk-2LNXMGT6.js → chunk-5CX7BVVV.js} +5 -5
  12. package/dist/{chunk-2LNXMGT6.js.map → chunk-5CX7BVVV.js.map} +1 -1
  13. package/dist/{chunk-5Y5BTB5D.js → chunk-B76QWPFM.js} +3 -3
  14. package/dist/{chunk-5Y5BTB5D.js.map → chunk-B76QWPFM.js.map} +1 -1
  15. package/dist/{chunk-GJBNLPGI.cjs → chunk-E5MAM2P4.cjs} +9 -9
  16. package/dist/{chunk-GJBNLPGI.cjs.map → chunk-E5MAM2P4.cjs.map} +1 -1
  17. package/dist/{chunk-7EF4VTUS.cjs → chunk-OFJYEITB.cjs} +489 -113
  18. package/dist/chunk-OFJYEITB.cjs.map +1 -0
  19. package/dist/{chunk-HBHSUGNI.cjs → chunk-VLI3Y6IJ.cjs} +5 -5
  20. package/dist/{chunk-HBHSUGNI.cjs.map → chunk-VLI3Y6IJ.cjs.map} +1 -1
  21. package/dist/{chunk-Z26PXRUY.js → chunk-VOC24LYF.js} +486 -110
  22. package/dist/chunk-VOC24LYF.js.map +1 -0
  23. package/dist/element-browser.js +492 -130
  24. package/dist/element-browser.js.map +1 -1
  25. package/dist/element.cjs +3 -3
  26. package/dist/element.js +2 -2
  27. package/dist/index.cjs +18 -18
  28. package/dist/index.js +6 -6
  29. package/dist/player.cjs +658 -170
  30. package/dist/player.cjs.map +1 -1
  31. package/dist/player.d.cts +36 -4
  32. package/dist/player.d.ts +36 -4
  33. package/dist/player.js +658 -170
  34. package/dist/player.js.map +1 -1
  35. package/dist/{remux-VPKCLHHM.cjs → remux-NSBJFMLG.cjs} +9 -9
  36. package/dist/{remux-VPKCLHHM.cjs.map → remux-NSBJFMLG.cjs.map} +1 -1
  37. package/dist/{remux-7TA4FKTY.js → remux-PHUHO3VV.js} +4 -4
  38. package/dist/{remux-7TA4FKTY.js.map → remux-PHUHO3VV.js.map} +1 -1
  39. package/package.json +1 -1
  40. package/src/element/avbridge-player.ts +223 -43
  41. package/src/probe/avi.ts +34 -2
  42. package/src/strategies/fallback/audio-output.ts +164 -35
  43. package/src/strategies/fallback/decoder.ts +467 -60
  44. package/src/strategies/fallback/video-renderer.ts +209 -29
  45. package/src/strategies/hybrid/decoder.ts +56 -28
  46. package/src/strategies/remux/pipeline.ts +12 -3
  47. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.mjs +1 -1
  48. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.wasm +0 -0
  49. package/vendor/libav/avbridge/libav-avbridge.mjs +1 -1
  50. package/dist/avi-EQE6AR75.cjs.map +0 -1
  51. package/dist/avi-NNHH4AAA.js.map +0 -1
  52. package/dist/avi-S7EY54YA.js.map +0 -1
  53. package/dist/avi-Y3N325WZ.cjs.map +0 -1
  54. package/dist/chunk-7EF4VTUS.cjs.map +0 -1
  55. package/dist/chunk-Z26PXRUY.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/events.ts","../src/probe/mediabunny.ts","../src/probe/index.ts","../src/util/codec-strings.ts","../src/classify/rules.ts","../src/diagnostics.ts","../src/plugins/registry.ts","../src/strategies/native.ts","../src/strategies/remux/mse.ts","../src/strategies/remux/pipeline.ts","../src/strategies/remux/index.ts","../src/strategies/fallback/video-renderer.ts","../src/strategies/fallback/audio-output.ts","../src/strategies/fallback/variant-routing.ts","../src/util/libav-demux.ts","../src/strategies/hybrid/decoder.ts","../src/util/time-ranges.ts","../src/strategies/hybrid/index.ts","../src/strategies/fallback/decoder.ts","../src/strategies/fallback/index.ts","../src/plugins/builtin.ts","../src/player.ts","../src/element/avbridge-video.ts","../src/element/player-styles.ts","../src/element/player-icons.ts","../src/element/avbridge-player.ts","../src/player-element.ts"],"names":["wallNow","frame","drain","us","frames","samples","normalizeSource","loadBridge","READY_AUDIO_BUFFER_SECONDS","READY_TIMEOUT_SECONDS","attachSubtitleTracks"],"mappings":";;;;;;;AAaO,IAAM,eAAN,MAA6B;AAAA,EAC1B,YAAoE,EAAC;AAAA,EACrE,SAAkD,EAAC;AAAA,EAE3D,EAAA,CAA6B,OAAU,EAAA,EAAuC;AAC5E,IAAA,IAAI,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAC9B,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,GAAA,uBAAU,GAAA,EAAI;AACd,MAAA,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,GAAI,GAAA;AAAA,IAC1B;AACA,IAAA,GAAA,CAAI,IAAI,EAAE,CAAA;AAGV,IAAA,IAAI,OAAO,SAAA,CAAU,cAAA,CAAe,KAAK,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA,EAAG;AAC5D,MAAA,IAAI;AACF,QAAA,EAAA,CAAG,IAAA,CAAK,MAAA,CAAO,KAAK,CAAgB,CAAA;AAAA,MACtC,SAAS,GAAA,EAAK;AAEZ,QAAA,OAAA,CAAQ,KAAA,CAAM,qDAAqD,GAAG,CAAA;AAAA,MACxE;AAAA,IACF;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAAA,EACjC;AAAA,EAEA,GAAA,CAA8B,OAAU,EAAA,EAAiC;AACvE,IAAA,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,EAAG,MAAA,CAAO,EAAE,CAAA;AAAA,EAClC;AAAA,EAEA,IAAA,CAA+B,OAAU,OAAA,EAA4B;AACnE,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAChC,IAAA,IAAI,CAAC,GAAA,EAAK;AAEV,IAAA,KAAA,MAAW,EAAA,IAAM,CAAC,GAAG,GAAG,CAAA,EAAG;AACzB,MAAA,IAAI;AACF,QAAA,EAAA,CAAG,OAAO,CAAA;AAAA,MACZ,SAAS,GAAA,EAAK;AAGZ,QAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,GAAG,CAAA;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAA,CAAqC,OAAU,OAAA,EAA4B;AACzE,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA,GAAI,OAAA;AACrB,IAAA,IAAA,CAAK,IAAA,CAAK,OAAO,OAAO,CAAA;AAAA,EAC1B;AAAA,EAEA,SAAA,GAAkB;AAChB,IAAA,IAAA,CAAK,YAAY,EAAC;AAClB,IAAA,IAAA,CAAK,SAAS,EAAC;AAAA,EACjB;AACF,CAAA;;;AC9CA,eAAsB,mBAAA,CACpB,QACA,gBAAA,EACuB;AACvB,EAAA,MAAM,EAAA,GAAK,MAAM,OAAO,YAAY,CAAA;AACpC,EAAA,MAAM,KAAA,GAAQ,IAAI,EAAA,CAAG,KAAA,CAAM;AAAA,IACzB,MAAA,EAAQ,MAAM,qBAAA,CAAsB,EAAA,EAAI,MAAM,CAAA;AAAA,IAC9C,SAAS,EAAA,CAAG;AAAA,GACb,CAAA;AAED,EAAA,MAAM,SAAA,GAAY,MAAM,KAAA,CAAM,SAAA,EAAU;AACxC,EAAA,MAAM,WAAW,MAAM,UAAA,CAAW,MAAM,KAAA,CAAM,iBAAiB,CAAA;AAE/D,EAAA,MAAM,cAAgC,EAAC;AACvC,EAAA,MAAM,cAAgC,EAAC;AAEvC,EAAA,KAAA,MAAW,SAAS,SAAA,EAAW;AAC7B,IAAA,IAAI,KAAA,CAAM,cAAa,EAAG;AACxB,MAAA,MAAM,aAAa,MAAM,IAAA,CAAK,MAAM,KAAA,CAAM,yBAAyB,CAAA;AACnE,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACf,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,KAAA,EAAO,yBAAA,CAA0B,KAAA,CAAM,KAAK,CAAA;AAAA,QAC5C,KAAA,EAAO,KAAA,CAAM,YAAA,IAAgB,KAAA,CAAM,UAAA,IAAc,CAAA;AAAA,QACjD,MAAA,EAAQ,KAAA,CAAM,aAAA,IAAiB,KAAA,CAAM,WAAA,IAAe,CAAA;AAAA,QACpD,aAAa,UAAA,IAAc;AAAA,OAC5B,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,KAAA,CAAM,YAAA,EAAa,EAAG;AAC/B,MAAA,MAAM,aAAa,MAAM,IAAA,CAAK,MAAM,KAAA,CAAM,yBAAyB,CAAA;AACnE,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACf,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,KAAA,EAAO,yBAAA,CAA0B,KAAA,CAAM,KAAK,CAAA;AAAA,QAC5C,QAAA,EAAU,MAAM,gBAAA,IAAoB,CAAA;AAAA,QACpC,UAAA,EAAY,MAAM,UAAA,IAAc,CAAA;AAAA,QAChC,UAAU,KAAA,CAAM,YAAA;AAAA,QAChB,aAAa,UAAA,IAAc;AAAA,OAC5B,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,MAAM,SAAS,MAAM,IAAA,CAAK,MAAM,KAAA,CAAM,WAAW,CAAA;AACjD,EAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,MAAA,EAAQ,IAAA,EAAM,gBAAgB,CAAA;AAEjE,EAAA,OAAO;AAAA,IACL,QAAQ,MAAA,CAAO,QAAA;AAAA,IACf,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,SAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAA;AAAA,IACA,gBAAgB,EAAC;AAAA,IACjB,QAAA,EAAU,YAAA;AAAA,IACV;AAAA,GACF;AACF;AASA,eAAsB,qBAAA,CACpB,IACA,MAAA,EACiF;AACjF,EAAA,IAAI,MAAA,CAAO,SAAS,KAAA,EAAO;AACzB,IAAA,OAAO,IAAI,EAAA,CAAG,SAAA,CAAU,MAAA,CAAO,GAAG,CAAA;AAAA,EACpC;AACA,EAAA,OAAO,IAAI,EAAA,CAAG,UAAA,CAAW,MAAA,CAAO,IAAI,CAAA;AACtC;AAWA,eAAsB,8BAAA,CACpB,IACA,MAAA,EACiF;AACjF,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,SAAiB,IAAI,EAAA,CAAG,UAAU,MAAM,CAAA;AAC9D,EAAA,IAAI,MAAA,YAAkB,KAAK,OAAO,IAAI,GAAG,SAAA,CAAU,MAAA,CAAO,UAAU,CAAA;AACpE,EAAA,IAAI,kBAAkB,IAAA,EAAM,OAAO,IAAI,EAAA,CAAG,WAAW,MAAM,CAAA;AAC3D,EAAA,IAAI,MAAA,YAAkB,WAAA,EAAa,OAAO,IAAI,EAAA,CAAG,UAAA,CAAW,IAAI,IAAA,CAAK,CAAC,MAAM,CAAC,CAAC,CAAA;AAC9E,EAAA,IAAI,MAAA,YAAkB,UAAA,EAAY,OAAO,IAAI,EAAA,CAAG,UAAA,CAAW,IAAI,IAAA,CAAK,CAAC,MAAkB,CAAC,CAAC,CAAA;AACzF,EAAA,MAAM,IAAI,UAAU,wCAAwC,CAAA;AAC9D;AAEA,SAAS,gBAAA,CAAiB,YAAgC,OAAA,EAAuC;AAC/F,EAAA,MAAM,IAAA,GAAA,CAAQ,UAAA,IAAc,EAAA,EAAI,WAAA,EAAY;AAC5C,EAAA,IAAI,IAAA,CAAK,SAAS,UAAU,CAAA,IAAK,KAAK,QAAA,CAAS,KAAK,GAAG,OAAO,KAAA;AAC9D,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG,OAAO,MAAA;AAClC,EAAA,IAAI,IAAA,CAAK,SAAS,KAAK,CAAA,IAAK,KAAK,QAAA,CAAS,MAAM,GAAG,OAAO,KAAA;AAC1D,EAAA,IAAI,IAAA,CAAK,SAAS,KAAK,CAAA,IAAK,KAAK,QAAA,CAAS,WAAW,GAAG,OAAO,KAAA;AAC/D,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,KAAA;AACjC,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,KAAA;AACjC,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG,OAAO,MAAA;AAClC,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,KAAA;AACjC,EAAA,IAAI,IAAA,CAAK,SAAS,MAAM,CAAA,IAAK,KAAK,QAAA,CAAS,KAAK,GAAG,OAAO,MAAA;AAC1D,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,WAAW,CAAA,EAAG,OAAO,QAAA;AAC9F,EAAA,OAAO,OAAA;AACT;AAGO,SAAS,0BAA0B,CAAA,EAA0C;AAClF,EAAA,QAAQ,CAAA;AAAG,IACT,KAAK,KAAA;AAAQ,MAAA,OAAO,MAAA;AAAA,IACpB,KAAK,MAAA;AAAQ,MAAA,OAAO,MAAA;AAAA,IACpB,KAAK,KAAA;AAAQ,MAAA,OAAO,KAAA;AAAA,IACpB,KAAK,KAAA;AAAQ,MAAA,OAAO,KAAA;AAAA,IACpB,KAAK,KAAA;AAAQ,MAAA,OAAO,KAAA;AAAA,IACpB;AAME,MAAA,OAAO,IAAK,CAAA,GAAmB,SAAA;AAAA;AAErC;AAGO,SAAS,0BAA0B,CAAA,EAA8D;AACtG,EAAA,QAAQ,CAAA;AAAG,IACT,KAAK,MAAA;AAAQ,MAAA,OAAO,KAAA;AAAA,IACpB,KAAK,MAAA;AAAQ,MAAA,OAAO,MAAA;AAAA,IACpB,KAAK,KAAA;AAAQ,MAAA,OAAO,KAAA;AAAA,IACpB,KAAK,KAAA;AAAQ,MAAA,OAAO,KAAA;AAAA,IACpB,KAAK,KAAA;AAAQ,MAAA,OAAO,KAAA;AAAA,IACpB;AAAa,MAAA,OAAO,IAAA;AAAA;AAExB;AAEO,SAAS,0BAA0B,CAAA,EAA0C;AAClF,EAAA,QAAQ,CAAA;AAAG,IACT,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,QAAA;AAAU,MAAA,OAAO,QAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB;AAAe,MAAA,OAAO,IAAK,CAAA,GAAmB,SAAA;AAAA;AAElD;AAEO,SAAS,0BAA0B,CAAA,EAA8B;AACtE,EAAA,QAAQ,CAAA;AAAG,IACT,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,QAAA;AAAU,MAAA,OAAO,QAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB,KAAK,KAAA;AAAU,MAAA,OAAO,KAAA;AAAA,IACtB,KAAK,MAAA;AAAU,MAAA,OAAO,MAAA;AAAA,IACtB;AAAe,MAAA,OAAO,IAAA;AAAA;AAE1B;AAEA,eAAe,WAAW,EAAA,EAAiE;AACzF,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,MAAM,EAAA,EAAG;AACnB,IAAA,OAAO,OAAO,CAAA,KAAM,QAAA,IAAY,OAAO,QAAA,CAAS,CAAC,IAAI,CAAA,GAAI,KAAA,CAAA;AAAA,EAC3D,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,eAAe,KAAQ,EAAA,EAAkD;AACvE,EAAA,IAAI;AAAE,IAAA,OAAO,MAAM,EAAA,EAAG;AAAA,EAAG,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,MAAA;AAAA,EAAW;AACvD;;;ACjMA,IAAM,qBAAA,uBAA4B,GAAA,CAAmB;AAAA,EACnD,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAC,CAAA;AAkBD,eAAsB,KAAA,CACpB,QACA,SAAA,EACuB;AACvB,EAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,MAAA,EAAQ,SAAS,CAAA;AAC1D,EAAA,MAAM,OAAA,GAAU,MAAM,qBAAA,CAAsB,UAAU,CAAA;AAEtD,EAAA,IAAI,qBAAA,CAAsB,GAAA,CAAI,OAAO,CAAA,EAAG;AACtC,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,CAAoB,UAAA,EAAY,OAAO,CAAA;AAI5D,MAAA,MAAM,kBACJ,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,KAAA,KAAU,SAAS,CAAA,IACpD,OAAO,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,UAAU,SAAS,CAAA;AACtD,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,IAAI;AACF,UAAA,MAAM,EAAE,cAAA,EAAe,GAAI,MAAM,OAAO,mBAAU,CAAA;AAClD,UAAA,OAAO,MAAM,cAAA,CAAe,UAAA,EAAY,OAAO,CAAA;AAAA,QACjD,CAAA,CAAA,MAAQ;AAGN,UAAA,OAAO,MAAA;AAAA,QACT;AAAA,MACF;AACA,MAAA,OAAO,MAAA;AAAA,IACT,SAAS,aAAA,EAAe;AAOtB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,kCAAkC,OAAO,CAAA,6BAAA,CAAA;AAAA,QACxC,aAAA,CAAwB;AAAA,OAC3B;AACA,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,cAAA,EAAe,GAAI,MAAM,OAAO,mBAAU,CAAA;AAClD,QAAA,OAAO,MAAM,cAAA,CAAe,UAAA,EAAY,OAAO,CAAA;AAAA,MACjD,SAAS,QAAA,EAAU;AACjB,QAAA,MAAM,KAAA,GAAS,aAAA,CAAwB,OAAA,IAAW,MAAA,CAAO,aAAa,CAAA;AACtE,QAAA,MAAM,QAAQ,QAAA,YAAoB,KAAA,GAAQ,QAAA,CAAS,OAAA,GAAU,OAAO,QAAQ,CAAA;AAC5E,QAAA,MAAM,IAAI,aAAA;AAAA,UACR,gBAAA;AAAA,UACA,mBAAmB,OAAA,CAAQ,WAAA,EAAa,CAAA,mBAAA,EAAsB,KAAK,YAAY,KAAK,CAAA,CAAA,CAAA;AAAA,UACpF;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,cAAA,EAAe,GAAI,MAAM,OAAO,mBAAU,CAAA;AAClD,IAAA,OAAO,MAAM,cAAA,CAAe,UAAA,EAAY,OAAO,CAAA;AAAA,EACjD,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,QAAQ,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAE7D,IAAA,OAAA,CAAQ,KAAA,CAAM,mCAAA,EAAqC,OAAA,EAAS,OAAA,EAAS,GAAG,CAAA;AACxE,IAAA,IAAI,YAAY,SAAA,EAAW;AACzB,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,2BAAA;AAAA,QACA,CAAA,kFAAA,EAAqF,SAAS,cAAc,CAAA,CAAA;AAAA,QAC5G;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,IAAI,aAAA;AAAA,MACR,uBAAA;AAAA,MACA,GAAG,OAAA,CAAQ,WAAA,EAAa,CAAA,+CAAA,EAAkD,SAAS,cAAc,CAAA,CAAA;AAAA,MACjG;AAAA,KACF;AAAA,EACF;AACF;;;ACrGO,SAAS,iBAAiB,KAAA,EAAsC;AACrE,EAAA,IAAI,KAAA,CAAM,WAAA,EAAa,OAAO,KAAA,CAAM,WAAA;AACpC,EAAA,QAAQ,MAAM,KAAA;AAAO,IACnB,KAAK,MAAA,EAAQ;AAGX,MAAA,MAAM,UAAA,GAAa,YAAA,CAAa,KAAA,CAAM,OAAO,CAAA,IAAK,IAAA;AAClD,MAAA,MAAM,UAAA,GAAa,IAAA;AACnB,MAAA,MAAM,KAAA,GAAA,CAAA,CAAU,KAAA,CAAM,KAAA,IAAS,EAAA,IAAM,GAAA,EAAM,SAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AACvE,MAAA,OAAO,CAAA,KAAA,EAAQ,UAAU,CAAA,EAAG,UAAU,GAAG,KAAK,CAAA,CAAA;AAAA,IAChD;AAAA,IACA,KAAK,MAAA;AAEH,MAAA,OAAO,iBAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,eAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,eAAA;AAAA,IACT;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAEA,SAAS,aAAa,OAAA,EAAiC;AACrD,EAAA,IAAI,CAAC,SAAS,OAAO,IAAA;AACrB,EAAA,MAAM,CAAA,GAAI,QAAQ,WAAA,EAAY;AAC9B,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,UAAU,CAAA,EAAG,OAAO,IAAA;AACnC,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,MAAM,CAAA,EAAG,OAAO,IAAA;AAC/B,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,SAAS,CAAA,EAAG,OAAO,IAAA;AAClC,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,YAAY,CAAA,EAAG,OAAO,IAAA;AACrC,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,YAAY,CAAA,EAAG,OAAO,IAAA;AACrC,EAAA,IAAI,CAAA,CAAE,QAAA,CAAS,MAAM,CAAA,EAAG,OAAO,IAAA;AAC/B,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,iBAAiB,KAAA,EAAsC;AACrE,EAAA,IAAI,KAAA,CAAM,WAAA,EAAa,OAAO,KAAA,CAAM,WAAA;AACpC,EAAA,QAAQ,MAAM,KAAA;AAAO,IACnB,KAAK,KAAA;AACH,MAAA,OAAO,WAAA;AAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,YAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,QAAA;AACH,MAAA,OAAO,QAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAMO,SAAS,UAAA,CAAW,OAAuB,KAAA,EAAuC;AACvF,EAAA,MAAM,CAAA,GAAI,iBAAiB,KAAK,CAAA;AAChC,EAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,EAAA,MAAM,MAAA,GAAS,KAAA,GAAQ,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,gBAAA,CAAiB,KAAK,CAAA,IAAK,EAAE,CAAA,CAAA,CAAG,OAAA,CAAQ,IAAA,EAAM,EAAE,CAAA,GAAI,CAAA;AACnF,EAAA,OAAO,sBAAsB,MAAM,CAAA,CAAA,CAAA;AACrC;AAMO,SAAS,YAAY,IAAA,EAAuB;AACjD,EAAA,IAAI,OAAO,WAAA,KAAgB,WAAA,EAAa,OAAO,KAAA;AAC/C,EAAA,IAAI;AACF,IAAA,OAAO,WAAA,CAAY,gBAAgB,IAAI,CAAA;AAAA,EACzC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;;;ACpEO,IAAM,mBAAA,uBAA0B,GAAA,CAAgB,CAAC,QAAQ,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,KAAK,CAAC,CAAA;AACrF,IAAM,mBAAA,uBAA0B,GAAA,CAAgB;AAAA,EACrD,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAC,CAAA;AAKM,IAAM,qBAAA,uBAA4B,GAAA,CAAgB;AAAA,EACvD,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,OAAA;AAAA,EACf,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,MAAA;AAAA,EACxB,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,QAAA;AAAA,EAClB,IAAA;AAAA,EAAM,QAAA;AAAA,EACN,UAAA;AAAA,EAAY,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO;AAC9B,CAAC,CAAA;AACM,IAAM,qBAAA,uBAA4B,GAAA,CAAgB;AAAA,EACvD,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,KAAA;AAAA,EAAO,MAAA;AAAA,EAC1B,MAAA;AAAA,EAAQ,QAAA;AAAA,EAAU,QAAA;AAAA,EAAU,MAAA;AAAA,EAAQ,QAAA;AAAA,EACpC,KAAA;AAAA,EAAO;AACT,CAAC,CAAA;AAMD,IAAM,iBAAA,uBAAwB,GAAA,CAAmB;AAAA,EAC/C,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAC,CAAA;AAcD,IAAM,oBAAA,uBAA2B,GAAA,CAAmB;AAAA,EAClD,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAC,CAAA;AAKM,SAAS,gBAAgB,GAAA,EAAmC;AACjE,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,WAAA,CAAY,CAAC,CAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,WAAA,CAAY,CAAC,CAAA;AAG/B,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,IAAI,iBAAA,CAAkB,GAAA,CAAI,GAAA,CAAI,SAAS,CAAA,KAAM,CAAC,KAAA,IAAS,mBAAA,CAAoB,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,CAAA,EAAI;AAC5F,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,CAAA,WAAA,EAAc,GAAA,CAAI,SAAS,CAAA,kBAAA;AAAA,OACrC;AAAA,IACF;AACA,IAAA,IAAI,KAAA,IAAS,qBAAA,CAAsB,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,EAAG;AACnD,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,mBAAA;AAAA,QACP,QAAA,EAAU,UAAA;AAAA,QACV,MAAA,EAAQ,CAAA,aAAA,EAAgB,KAAA,CAAM,KAAK,CAAA,sBAAA;AAAA,OACrC;AAAA,IACF;AACA,IAAA,IAAI,oBAAA,CAAqB,GAAA,CAAI,GAAA,CAAI,SAAS,CAAA,EAAG;AAC3C,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,iBAAA;AAAA,QACP,QAAA,EAAU,OAAA;AAAA,QACV,MAAA,EAAQ,CAAA,yCAAA,EAA4C,GAAA,CAAI,SAAS,CAAA,CAAA;AAAA,OACnE;AAAA,IACF;AACA,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,mBAAA;AAAA,MACP,QAAA,EAAU,UAAA;AAAA,MACV,MAAA,EAAQ,CAAA,oBAAA,EAAuB,GAAA,CAAI,SAAS,CAAA,+BAAA;AAAA,KAC9C;AAAA,EACF;AAGA,EAAA,IAAI,qBAAA,CAAsB,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,EAAG;AAC1C,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,mBAAA;AAAA,MACP,QAAA,EAAU,UAAA;AAAA,MACV,MAAA,EAAQ,CAAA,aAAA,EAAgB,KAAA,CAAM,KAAK,CAAA,gDAAA;AAAA,KACrC;AAAA,EACF;AAIA,EAAA,MAAM,kBAAA,GAAqB,KAAA,KACzB,qBAAA,CAAsB,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,IACrC,CAAC,mBAAA,CAAoB,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,CAAA;AAEtC,EAAA,IAAI,kBAAA,EAAoB;AAMtB,IAAA,IAAI,oBAAoB,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,IAAK,oBAAmB,EAAG;AAChE,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,kBAAA;AAAA,QACP,QAAA,EAAU,QAAA;AAAA,QACV,QAAQ,CAAA,OAAA,EAAU,KAAA,CAAM,KAAK,CAAA,8CAAA,EAAiD,MAAM,KAAK,CAAA,8BAAA,CAAA;AAAA,QACzF,aAAA,EAAe,CAAC,UAAU;AAAA,OAC5B;AAAA,IACF;AACA,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,mBAAA;AAAA,MACP,QAAA,EAAU,UAAA;AAAA,MACV,MAAA,EAAQ,CAAA,aAAA,EAAgB,KAAA,CAAM,KAAK,CAAA,gDAAA;AAAA,KACrC;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,mBAAA,CAAoB,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,EAAG;AACzC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,mBAAA;AAAA,MACP,QAAA,EAAU,UAAA;AAAA,MACV,MAAA,EAAQ,CAAA,qBAAA,EAAwB,KAAA,CAAM,KAAK,CAAA,sBAAA;AAAA,KAC7C;AAAA,EACF;AAIA,EAAA,MAAM,iBAAA,GAAoB,iBAAA,CAAkB,GAAA,CAAI,GAAA,CAAI,SAAS,CAAA;AAE7D,EAAA,IAAI,iBAAA,IAAqB,iBAAA,CAAkB,KAAA,EAAO,KAAK,CAAA,EAAG;AAExD,IAAA,MAAM,IAAA,GAAO,UAAA,CAAW,KAAA,EAAO,KAAK,CAAA;AACpC,IAAA,IAAI,IAAA,IAAQ,WAAA,CAAY,IAAI,CAAA,EAAG;AAC7B,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,GAAA,EAAM,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,GAAA,GAAM,KAAA,CAAM,KAAA,GAAQ,EAAE,CAAA,eAAA;AAAA,OAC5E;AAAA,IACF;AACA,IAAA,IAAI,IAAA,IAAQ,IAAA,IAAQ,OAAO,WAAA,KAAgB,WAAA,EAAa;AAEtD,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,QAAA;AAAA,QACP,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,GAAA,EAAM,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,GAAA,GAAM,KAAA,CAAM,KAAA,GAAQ,EAAE,CAAA,mBAAA;AAAA,OAC5E;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,iBAAA,IAAqB,aAAA,CAAc,KAAK,CAAA,EAAG;AAC7C,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,cAAA;AAAA,MACP,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA,CAAA,EAAI,KAAA,CAAM,OAAA,IAAW,EAAE,CAAA,CAAA,EAAI,KAAA,CAAM,QAAA,IAAY,CAAC,CAAA,2DAAA,CAAA;AAAA,MACpE,aAAA,EAAe,CAAC,OAAA,EAAS,QAAA,EAAU,UAAU;AAAA,KAC/C;AAAA,EACF;AAKA,EAAA,IAAI,oBAAA,CAAqB,GAAA,CAAI,GAAA,CAAI,SAAS,CAAA,EAAG;AAQ3C,IAAA,MAAM,IAAA,GAAO,UAAA,CAAW,KAAA,EAAO,KAAK,CAAA;AACpC,IAAA,IAAI,QAAQ,OAAO,WAAA,KAAgB,eAAe,CAAC,WAAA,CAAY,IAAI,CAAA,EAAG;AACpE,MAAA,IAAI,oBAAmB,EAAG;AACxB,QAAA,OAAO;AAAA,UACL,KAAA,EAAO,kBAAA;AAAA,UACP,QAAA,EAAU,QAAA;AAAA,UACV,MAAA,EAAQ,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,gBAAA,EAAmB,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,GAAA,GAAM,KAAA,CAAM,KAAA,GAAQ,EAAE,CAAA,+EAAA,CAAA;AAAA,UACvF,aAAA,EAAe,CAAC,UAAU;AAAA,SAC5B;AAAA,MACF;AACA,MAAA,OAAO;AAAA,QACL,KAAA,EAAO,mBAAA;AAAA,QACP,QAAA,EAAU,UAAA;AAAA,QACV,MAAA,EAAQ,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,gBAAA,EAAmB,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,GAAA,GAAM,KAAA,CAAM,KAAA,GAAQ,EAAE,CAAA,mGAAA;AAAA,OACzF;AAAA,IACF;AAKA,IAAA,MAAM,aAAA,GAAgC,oBAAmB,GACrD,CAAC,UAAU,UAAU,CAAA,GACrB,CAAC,UAAU,CAAA;AACf,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,iBAAA;AAAA,MACP,QAAA,EAAU,OAAA;AAAA,MACV,MAAA,EAAQ,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,4FAAA,CAAA;AAAA,MACxB;AAAA,KACF;AAAA,EACF;AAKA,EAAA,IAAI,oBAAmB,EAAG;AACxB,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,kBAAA;AAAA,MACP,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,yCAAA,EAA4C,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,GAAA,GAAM,KAAA,CAAM,KAAA,GAAQ,EAAE,CAAA,sCAAA,CAAA;AAAA,MAChH,aAAA,EAAe,CAAC,UAAU;AAAA,KAC5B;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,mBAAA;AAAA,IACP,QAAA,EAAU,UAAA;AAAA,IACV,MAAA,EAAQ,CAAA,EAAG,GAAA,CAAI,SAAS,CAAA,yEAAA,EAA4E,KAAA,CAAM,KAAK,CAAA,EAAG,KAAA,GAAQ,GAAA,GAAM,KAAA,CAAM,KAAA,GAAQ,EAAE,CAAA,CAAA;AAAA,GAClJ;AACF;AAEA,SAAS,kBAAA,GAA8B;AACrC,EAAA,OAAO,OAAO,WAAW,YAAA,KAAiB,WAAA;AAC5C;AAEA,SAAS,iBAAA,CAAkB,OAAuB,KAAA,EAAiC;AACjF,EAAA,IAAI,KAAA,CAAM,UAAU,MAAA,EAAQ;AAE1B,IAAA,IAAI,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,QAAA,GAAW,GAAG,OAAO,KAAA;AACjD,IAAA,IAAI,KAAA,CAAM,eAAe,CAAC,UAAA,CAAW,KAAK,KAAA,CAAM,WAAW,GAAG,OAAO,KAAA;AAAA,EACvE;AACA,EAAA,IAAI,SAAS,CAAC,mBAAA,CAAoB,IAAI,KAAA,CAAM,KAAK,GAAG,OAAO,KAAA;AAC3D,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,cAAc,KAAA,EAAgC;AACrD,EAAA,IAAI,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,QAAA,GAAW,GAAG,OAAO,IAAA;AACjD,EAAA,IAAI,MAAM,WAAA,IAAe,gBAAA,CAAiB,KAAK,KAAA,CAAM,WAAW,GAAG,OAAO,IAAA;AAC1E,EAAA,IAAI,MAAM,KAAA,GAAQ,IAAA,IAAQ,KAAA,CAAM,MAAA,GAAS,MAAM,OAAO,IAAA;AACtD,EAAA,IAAI,KAAA,CAAM,GAAA,IAAO,KAAA,CAAM,GAAA,GAAM,IAAI,OAAO,IAAA;AACxC,EAAA,OAAO,KAAA;AACT;;;ACxQO,IAAM,cAAN,MAAkB;AAAA,EACf,SAAA,GAA8C,SAAA;AAAA,EAC9C,UAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,GAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA,GAA4C,SAAA;AAAA,EAC5C,aAAA,GAAsD,SAAA;AAAA,EACtD,MAAA,GAAS,EAAA;AAAA,EACT,QAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,UAAmC,EAAC;AAAA,EACpC,SAAA;AAAA,EACA,kBAAiF,EAAC;AAAA,EAE1F,YAAY,GAAA,EAAyB;AACnC,IAAA,IAAA,CAAK,YAAY,GAAA,CAAI,SAAA;AACrB,IAAA,IAAA,CAAK,WAAW,GAAA,CAAI,QAAA;AACpB,IAAA,IAAA,CAAK,WAAW,GAAA,CAAI,QAAA;AACpB,IAAA,MAAM,CAAA,GAAI,GAAA,CAAI,WAAA,CAAY,CAAC,CAAA;AAC3B,IAAA,IAAI,CAAA,EAAG;AACL,MAAA,IAAA,CAAK,aAAa,CAAA,CAAE,KAAA;AACpB,MAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,KAAA;AACf,MAAA,IAAA,CAAK,SAAS,CAAA,CAAE,MAAA;AAChB,MAAA,IAAA,CAAK,MAAM,CAAA,CAAE,GAAA;AAAA,IACf;AACA,IAAA,MAAM,CAAA,GAAI,GAAA,CAAI,WAAA,CAAY,CAAC,CAAA;AAC3B,IAAA,IAAI,CAAA,EAAG,IAAA,CAAK,UAAA,GAAa,CAAA,CAAE,KAAA;AAK3B,IAAA,MAAM,MAAM,GAAA,CAAI,MAAA;AAChB,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,YAAe,GAAA,EAAK;AACjD,MAAA,IAAA,CAAK,UAAA,GAAa,KAAA;AAClB,MAAA,IAAA,CAAK,SAAA,GAAY,YAAA;AAMjB,MAAA,IAAA,CAAK,cAAA,GAAiB,MAAA;AAAA,IACxB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,UAAA,GAAa,MAAA;AAClB,MAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,MAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eAAA,CACE,WACA,cAAA,EACM;AACN,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AACjB,IAAA,IAAA,CAAK,cAAA,GAAiB,cAAA;AAAA,EACxB;AAAA,EAEA,qBAAqB,CAAA,EAAyB;AAC5C,IAAA,IAAA,CAAK,WAAW,CAAA,CAAE,QAAA;AAClB,IAAA,IAAA,CAAK,gBAAgB,CAAA,CAAE,KAAA;AACvB,IAAA,IAAA,CAAK,SAAS,CAAA,CAAE,MAAA;AAAA,EAClB;AAAA,EAEA,cAAc,KAAA,EAAsC;AAMlD,IAAA,MAAM;AAAA,MACJ,UAAA;AAAA,MACA,eAAA;AAAA,MACA,GAAG;AAAA,KACL,GAAI,KAAA;AAIJ,IAAA,IAAI,UAAA,IAAc,IAAA,IAAQ,OAAO,eAAA,KAAoB,SAAA,EAAW;AAC9D,MAAA,IAAA,CAAK,eAAA,CAAgB,YAAY,eAAe,CAAA;AAAA,IAClD;AACA,IAAA,IAAA,CAAK,UAAU,EAAE,GAAG,IAAA,CAAK,OAAA,EAAS,GAAG,IAAA,EAAK;AAAA,EAC5C;AAAA,EAEA,oBAAA,CAAqB,UAAwB,MAAA,EAAsB;AACjE,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,eAAA,CAAgB,KAAK,EAAE,QAAA,EAAU,QAAQ,EAAA,EAAI,IAAA,CAAK,GAAA,EAAI,EAAG,CAAA;AAAA,EAChE;AAAA,EAEA,YAAY,GAAA,EAAkB;AAC5B,IAAA,IAAA,CAAK,SAAA,GAAY,GAAA;AAAA,EACnB;AAAA,EAEA,QAAA,GAAgC;AAC9B,IAAA,MAAM,IAAA,GAA4B;AAAA,MAChC,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,KAAK,IAAA,CAAK,GAAA;AAAA,MACV,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,eAAe,IAAA,CAAK,aAAA;AAAA,MACpB,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,gBAAgB,IAAA,CAAK,cAAA;AAAA,MACrB,OAAA,EAAS,EAAE,GAAG,IAAA,CAAK,SAAS,GAAI,IAAA,CAAK,SAAA,GAAY,EAAE,OAAO,IAAA,CAAK,SAAA,CAAU,OAAA,EAAQ,GAAI,EAAC,EAAG;AAAA,MACzF,eAAA,EAAiB,KAAK,eAAA,CAAgB,MAAA,GAAS,IAAI,CAAC,GAAG,IAAA,CAAK,eAAe,CAAA,GAAI;AAAA,KACjF;AACA,IAAA,OAAO,MAAA,CAAO,OAAO,IAAI,CAAA;AAAA,EAC3B;AACF,CAAA;;;AChIO,IAAM,iBAAN,MAAqB;AAAA,EAClB,UAAoB,EAAC;AAAA,EAE7B,QAAA,CAAS,MAAA,EAAgB,OAAA,GAAU,KAAA,EAAa;AAC9C,IAAA,IAAI,OAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA;AAAA,SACnC,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA;AAAA,EAC/B;AAAA,EAEA,GAAA,GAAyB;AACvB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAA,CAAQ,SAAuB,QAAA,EAAuC;AACpE,IAAA,KAAA,MAAW,CAAA,IAAK,KAAK,OAAA,EAAS;AAC5B,MAAA,IAAI,EAAE,IAAA,KAAS,QAAA,IAAY,EAAE,SAAA,CAAU,OAAO,GAAG,OAAO,CAAA;AAAA,IAC1D;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AACF,CAAA;;;ACrBA,eAAsB,mBAAA,CACpB,SACA,KAAA,EAC0B;AAC1B,EAAA,MAAM,EAAE,GAAA,EAAK,MAAA,EAAO,GAAI,gBAAA,CAAiB,QAAQ,MAAM,CAAA;AACvD,EAAA,KAAA,CAAM,GAAA,GAAM,GAAA;AAKZ,EAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC3C,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,OAAA,EAAQ;AACR,MAAA,OAAA,EAAQ;AAAA,IACV,CAAA;AACA,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,OAAA,EAAQ;AACR,MAAA,MAAA,CAAO,IAAI,MAAM,CAAA,wBAAA,EAA2B,KAAA,CAAM,OAAO,OAAA,IAAW,SAAS,EAAE,CAAC,CAAA;AAAA,IAClF,CAAA;AACA,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,KAAA,CAAM,mBAAA,CAAoB,kBAAkB,MAAM,CAAA;AAClD,MAAA,KAAA,CAAM,mBAAA,CAAoB,SAAS,OAAO,CAAA;AAAA,IAC5C,CAAA;AACA,IAAA,KAAA,CAAM,gBAAA,CAAiB,kBAAkB,MAAM,CAAA;AAC/C,IAAA,KAAA,CAAM,gBAAA,CAAiB,SAAS,OAAO,CAAA;AAAA,EACzC,CAAC,CAAA;AAED,EAAA,IAAI,KAAA,GAAQ,EAAE,aAAA,EAAe,CAAA,EAAG,eAAe,CAAA,EAAE;AAEjD,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,QAAA;AAAA,IACV,MAAM,IAAA,GAAO;AACX,MAAA,MAAM,MAAM,IAAA,EAAK;AAAA,IACnB,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,KAAA,CAAM,KAAA,EAAM;AAAA,IACd,CAAA;AAAA,IACA,MAAM,KAAK,IAAA,EAAM;AACf,MAAA,KAAA,CAAM,WAAA,GAAc,IAAA;AAAA,IACtB,CAAA;AAAA,IACA,MAAM,cAAc,EAAA,EAAI;AAMtB,MAAA,MAAM,SAAU,KAAA,CAAyG,WAAA;AACzH,MAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AACpC,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,MAAA,CAAO,CAAC,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAC,EAAE,EAAA,KAAO,MAAA,CAAO,EAAE,CAAA,IAAK,CAAA,KAAM,EAAA;AAAA,MAC3D;AAAA,IACF,CAAA;AAAA,IACA,MAAM,iBAAiB,EAAA,EAAI;AACzB,MAAA,MAAM,SAAS,KAAA,CAAM,UAAA;AACrB,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,MAAA,CAAO,CAAC,CAAA,CAAE,IAAA,GAAO,CAAA,KAAM,KAAK,SAAA,GAAY,UAAA;AAAA,MAC1C;AAAA,IACF,CAAA;AAAA,IACA,MAAM,OAAA,GAAU;AACd,MAAA,KAAA,CAAM,KAAA,EAAM;AACZ,MAAA,KAAA,CAAM,gBAAgB,KAAK,CAAA;AAC3B,MAAA,KAAA,CAAM,IAAA,EAAK;AACX,MAAA,MAAA,IAAS;AAAA,IACX,CAAA;AAAA,IACA,cAAA,GAAiB;AACf,MAAA,OAAO,MAAM,WAAA,IAAe,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA,eAAA,GAAkB;AAEhB,MAAA,MAAM,CAAA,GAAK,MAA8E,uBAAA,IAA0B;AACnH,MAAA,IAAI,CAAA,EAAG;AACL,QAAA,KAAA,GAAQ;AAAA,UACN,eAAe,CAAA,CAAE,gBAAA;AAAA,UACjB,eAAe,CAAA,CAAE;AAAA,SACnB;AAAA,MACF;AACA,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,WAAA,EAAa,QAAA,EAAS;AAAA,IAC3C;AAAA,GACF;AACF;AAEA,SAAS,iBAAiB,MAAA,EAAuD;AAC/E,EAAA,IAAI,kBAAkB,IAAA,EAAM;AAC1B,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,MAAM,CAAA;AACtC,IAAA,OAAO,EAAE,GAAA,EAAK,MAAA,EAAQ,MAAM,GAAA,CAAI,eAAA,CAAgB,GAAG,CAAA,EAAE;AAAA,EACvD;AACA,EAAA,IAAI,MAAA,YAAkB,WAAA,IAAe,MAAA,YAAkB,UAAA,EAAY;AACjE,IAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK,CAAC,MAAkB,CAAC,CAAA;AAC1C,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,IAAA,OAAO,EAAE,GAAA,EAAK,MAAA,EAAQ,MAAM,GAAA,CAAI,eAAA,CAAgB,GAAG,CAAA,EAAE;AAAA,EACvD;AACA,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,EAAU,OAAO,EAAE,KAAK,MAAA,EAAO;AACrD,EAAA,IAAI,kBAAkB,GAAA,EAAK,OAAO,EAAE,GAAA,EAAK,MAAA,CAAO,UAAS,EAAE;AAC3D,EAAA,MAAM,IAAI,UAAU,0CAA0C,CAAA;AAChE;;;AC1FO,IAAM,UAAN,MAAc;AAAA,EAWnB,YAA6B,OAAA,EAAyB;AAAzB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAC3B,IAAA,IAAI,OAAO,gBAAgB,WAAA,EAAa;AACtC,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,qBAAA;AAAA,QACA,qEAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,CAAC,WAAA,CAAY,eAAA,CAAgB,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC9C,MAAA,MAAM,IAAI,aAAA;AAAA,QACR,2BAAA;AAAA,QACA,CAAA,qCAAA,EAAwC,QAAQ,IAAI,CAAA,EAAA,CAAA;AAAA,QACpD;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,WAAA,EAAY;AACnC,IAAA,IAAA,CAAK,SAAA,GAAY,GAAA,CAAI,eAAA,CAAgB,IAAA,CAAK,WAAW,CAAA;AACrD,IAAA,OAAA,CAAQ,KAAA,CAAM,MAAM,IAAA,CAAK,SAAA;AAEzB,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,OAAA,CAAQ,CAAC,SAAS,MAAA,KAAW;AACnD,MAAA,IAAA,CAAK,YAAA,GAAe,OAAA;AACpB,MAAA,IAAA,CAAK,WAAA,GAAc,MAAA;AAAA,IACrB,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,WAAA,CAAY,gBAAA,CAAiB,YAAA,EAAc,MAAM;AACpD,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,YAAA,GAAe,IAAA,CAAK,WAAA,CAAY,eAAA,CAAgB,QAAQ,IAAI,CAAA;AACjE,QAAA,IAAA,CAAK,aAAa,IAAA,GAAO,UAAA;AACzB,QAAA,IAAA,CAAK,aAAa,gBAAA,CAAiB,WAAA,EAAa,MAAM,IAAA,CAAK,MAAM,CAAA;AACjE,QAAA,IAAA,CAAK,YAAA,EAAa;AAClB,QAAA,OAAA,CAAQ,OAAA,IAAU;AAAA,MACpB,SAAS,GAAA,EAAK;AACZ,QAAA,IAAA,CAAK,WAAA,CAAY,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA;AAAA,MACtE;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EApC6B,OAAA;AAAA,EAVrB,WAAA;AAAA,EACA,YAAA,GAAoC,IAAA;AAAA,EACpC,QAAuB,EAAC;AAAA,EACxB,iBAAA,GAAoB,KAAA;AAAA,EACpB,SAAA,GAAY,KAAA;AAAA,EACZ,YAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EAwCR,KAAA,GAAuB;AACrB,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA;AAAA,EAGA,OAAO,KAAA,EAAuC;AAC5C,IAAA,IAAI,KAAK,SAAA,EAAW;AACpB,IAAA,MAAM,EAAA,GAAK,KAAA,YAAiB,UAAA,GACvB,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,KAAA,CAAM,UAAA,EAAY,KAAA,CAAM,UAAA,GAAa,KAAA,CAAM,UAAU,CAAA,GACzE,KAAA;AACJ,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,EAAE,CAAA;AAClB,IAAA,IAAA,CAAK,IAAA,EAAK;AAAA,EACZ;AAAA,EAEQ,IAAA,GAAa;AACnB,IAAA,MAAM,KAAK,IAAA,CAAK,YAAA;AAChB,IAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,QAAA,EAAU;AAOxB,IAAA,IAAI,EAAA,CAAG,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC1B,MAAA,IAAI,IAAA,CAAK,oBAAoB,IAAA,EAAM;AACjC,QAAA,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,WAAA,GAAc,IAAA,CAAK,eAAA;AACtC,QAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,MACzB,CAAA,MAAA,IAAW,CAAC,IAAA,CAAK,yBAAA,EAA2B;AAK1C,QAAA,MAAM,CAAA,GAAI,KAAK,OAAA,CAAQ,KAAA;AACvB,QAAA,MAAM,UAAA,GAAa,EAAA,CAAG,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA;AACtC,QAAA,MAAM,QAAA,GAAW,EAAA,CAAG,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA;AAClC,QAAA,IAAI,CAAA,CAAE,WAAA,GAAc,UAAA,IAAc,CAAA,CAAE,cAAc,QAAA,EAAU;AAC1D,UAAA,CAAA,CAAE,WAAA,GAAc,UAAA;AAAA,QAClB;AACA,QAAA,IAAA,CAAK,yBAAA,GAA4B,IAAA;AAAA,MACnC;AACA,MAAA,IAAI,KAAK,UAAA,EAAY;AACnB,QAAA,IAAA,CAAK,UAAA,GAAa,KAAA;AAClB,QAAA,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,IAAA,EAAK,CAAE,MAAM,MAAM;AAAA,QAAyC,CAAC,CAAA;AAAA,MAClF;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM;AAC9B,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAI;AACF,MAAA,EAAA,CAAG,aAAa,IAAI,CAAA;AAAA,IACtB,SAAS,GAAA,EAAK;AAEZ,MAAA,IAAK,GAAA,CAAqB,SAAS,oBAAA,EAAsB;AACvD,QAAA,IAAA,CAAK,KAAA,EAAM;AACX,QAAA,IAAI;AACF,UAAA,EAAA,CAAG,aAAa,IAAI,CAAA;AACpB,UAAA;AAAA,QACF,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACF;AACA,MAAA,IAAA,CAAK,WAAA,CAAY,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA;AAAA,IACtE;AAAA,EACF;AAAA,EAEQ,KAAA,GAAc;AACpB,IAAA,MAAM,KAAK,IAAA,CAAK,YAAA;AAChB,IAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,QAAA,CAAS,WAAW,CAAA,EAAG;AACrC,IAAA,MAAM,KAAA,GAAQ,EAAA,CAAG,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA;AACjC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,WAAA;AAEnC,IAAA,IAAI,OAAA,GAAU,QAAQ,EAAA,EAAI;AACxB,MAAA,IAAI;AACF,QAAA,EAAA,CAAG,MAAA,CAAO,KAAA,EAAO,OAAA,GAAU,EAAE,CAAA;AAAA,MAC/B,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,iBAAA,IAAqB,IAAA,CAAK,SAAA,EAAW;AAC9C,IAAA,IAAA,CAAK,iBAAA,GAAoB,IAAA;AACzB,IAAA,MAAM,SAAS,MAAM;AACnB,MAAA,IAAI,KAAK,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,IAAA,CAAK,cAAc,QAAA,EAAU;AAExD,QAAA,IAAA,CAAK,cAAc,gBAAA,CAAiB,WAAA,EAAa,QAAQ,EAAE,IAAA,EAAM,MAAM,CAAA;AACvE,QAAA;AAAA,MACF;AACA,MAAA,IAAI;AACF,QAAA,IAAI,IAAA,CAAK,WAAA,CAAY,UAAA,KAAe,MAAA,EAAQ;AAC1C,UAAA,IAAA,CAAK,YAAY,WAAA,EAAY;AAAA,QAC/B;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AACA,IAAA,MAAA,EAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAA,GAAwB;AACtB,IAAA,MAAM,KAAK,IAAA,CAAK,YAAA;AAChB,IAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,QAAA,CAAS,MAAA,KAAW,GAAG,OAAO,CAAA;AAC5C,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,CAAQ,KAAA,CAAM,WAAA;AACnC,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AAC3C,MAAA,IAAI,EAAA,CAAG,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,IAAK,OAAA,IAAW,EAAA,CAAG,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,GAAI,OAAA,EAAS;AACnE,QAAA,OAAO,EAAA,CAAG,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,GAAI,OAAA;AAAA,MAC9B;AAAA,IACF;AACA,IAAA,OAAO,CAAA;AAAA,EACT;AAAA;AAAA,EAGA,aAAA,GAAwB;AACtB,IAAA,MAAM,KAAK,IAAA,CAAK,YAAA;AAChB,IAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,QAAA,CAAS,MAAA,KAAW,GAAG,OAAO,CAAA;AAC5C,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,EAAA,CAAG,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AAC3C,MAAA,KAAA,IAAS,EAAA,CAAG,SAAS,GAAA,CAAI,CAAC,IAAI,EAAA,CAAG,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,IACnD;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,WAAA,GAAsB;AACpB,IAAA,OAAO,KAAK,KAAA,CAAM,MAAA;AAAA,EACpB;AAAA;AAAA,EAGQ,eAAA,GAAiC,IAAA;AAAA;AAAA,EAEjC,UAAA,GAAa,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQb,yBAAA,GAA4B,KAAA;AAAA;AAAA,EAGpC,cAAc,IAAA,EAAqB;AACjC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,QAAA,EAAwB;AACjC,IAAA,MAAM,KAAK,IAAA,CAAK,YAAA;AAEhB,IAAA,IAAA,CAAK,QAAQ,EAAC;AACd,IAAA,IAAA,CAAK,eAAA,GAAkB,QAAA;AACvB,IAAA,IAAA,CAAK,yBAAA,GAA4B,IAAA;AACjC,IAAA,IAAI,CAAC,EAAA,IAAM,EAAA,CAAG,QAAA,CAAS,WAAW,CAAA,EAAG;AACrC,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,EAAA,CAAG,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA;AACjC,MAAA,MAAM,MAAM,EAAA,CAAG,QAAA,CAAS,IAAI,EAAA,CAAG,QAAA,CAAS,SAAS,CAAC,CAAA;AAClD,MAAA,EAAA,CAAG,MAAA,CAAO,OAAO,GAAG,CAAA;AAAA,IACtB,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,IAAA,CAAK,QAAQ,EAAC;AACd,IAAA,IAAI;AACF,MAAA,IAAI,KAAK,WAAA,CAAY,UAAA,KAAe,MAAA,EAAQ,IAAA,CAAK,YAAY,WAAA,EAAY;AAAA,IAC3E,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,GAAA,CAAI,eAAA,CAAgB,KAAK,SAAS,CAAA;AAAA,EACpC;AACF,CAAA;;;AC9MA,eAAsB,mBAAA,CACpB,KACA,KAAA,EACwB;AACxB,EAAA,MAAM,EAAA,GAAK,MAAM,OAAO,YAAY,CAAA;AAEpC,EAAA,MAAM,cAAA,GAAiB,GAAA,CAAI,WAAA,CAAY,CAAC,CAAA;AACxC,EAAA,IAAI,CAAC,cAAA,EAAgB,MAAM,IAAI,MAAM,kCAAkC,CAAA;AAGvE,EAAA,MAAM,YAAA,GAAe,yBAAA,CAA0B,cAAA,CAAe,KAAK,CAAA;AACnE,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,cAAA,CAAe,KAAK,CAAA,uCAAA,CAAyC,CAAA;AAAA,EACtG;AAIA,EAAA,MAAM,KAAA,GAAQ,IAAI,EAAA,CAAG,KAAA,CAAM;AAAA,IACzB,MAAA,EAAQ,MAAM,8BAAA,CAA+B,EAAA,EAAI,IAAI,MAAM,CAAA;AAAA,IAC3D,SAAS,EAAA,CAAG;AAAA,GACb,CAAA;AACD,EAAA,MAAM,SAAA,GAAY,MAAM,KAAA,CAAM,SAAA,EAAU;AACxC,EAAA,MAAM,UAAA,GAAa,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,cAAA,CAAe,EAAA,IAAM,CAAA,CAAE,YAAA,EAAc,CAAA;AACvF,EAAA,IAAI,CAAC,UAAA,IAAc,CAAC,UAAA,CAAW,cAAa,EAAG;AAC7C,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACzD;AAIA,EAAA,MAAM,WAAA,GAAc,MAAM,UAAA,CAAW,gBAAA,EAAiB;AAGtD,EAAA,MAAM,SAAA,GAAY,IAAI,EAAA,CAAG,iBAAA,CAAkB,UAAU,CAAA;AAQrD,EAAA,IAAI,oBAAA,GAAsC,GAAA,CAAI,WAAA,CAAY,CAAC,GAAG,EAAA,IAAM,IAAA;AACpE,EAAA,IAAI,UAAA,GAAqC,IAAA;AACzC,EAAA,IAAI,YAAA,GAAoE,IAAA;AACxE,EAAA,IAAI,SAAA,GAA8D,IAAA;AAClE,EAAA,IAAI,WAAA,GAAkC,IAAA;AAEtC,EAAA,eAAe,YAAA,GAA8B;AAC3C,IAAA,IAAI,wBAAwB,IAAA,EAAM;AAChC,MAAA,UAAA,GAAa,IAAA;AACb,MAAA,YAAA,GAAe,IAAA;AACf,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,WAAA,GAAc,IAAA;AACd,MAAA;AAAA,IACF;AACA,IAAA,MAAM,SAAA,GAAY,IAAI,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,oBAAoB,CAAA;AAC3E,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,oBAAoB,CAAA,CAAE,CAAA;AAAA,IACzE;AACA,IAAA,MAAM,QAAA,GAAW,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,SAAA,CAAU,EAAA,IAAM,CAAA,CAAE,YAAA,EAAc,CAAA;AAChF,IAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,CAAS,cAAa,EAAG;AACzC,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IACzD;AACA,IAAA,UAAA,GAAa,QAAA;AACb,IAAA,YAAA,GAAe,yBAAA,CAA0B,UAAU,KAAK,CAAA;AACxD,IAAA,SAAA,GAAY,IAAI,EAAA,CAAG,iBAAA,CAAkB,QAAQ,CAAA;AAC7C,IAAA,WAAA,GAAc,MAAM,SAAS,gBAAA,EAAiB;AAAA,EAChD;AAEA,EAAA,MAAM,YAAA,EAAa;AAGnB,EAAA,IAAI,IAAA,GAAuB,IAAA;AAC3B,EAAA,MAAM,KAAA,GAAQ,EAAE,YAAA,EAAc,CAAA,EAAG,cAAc,CAAA,EAAG,YAAA,EAAc,CAAA,EAAG,SAAA,EAAW,CAAA,EAAE;AAEhF,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,EAAA,IAAI,gBAAA,GAAmB,CAAA;AAIvB,EAAA,IAAI,aAAA,GAAuD,IAAA;AAM3D,EAAA,SAAS,YAAA,GAAe;AAEtB,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,IAAI;AAAE,QAAA,KAAK,cAAc,MAAA,EAAO;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IAC5D;AAEA,IAAA,IAAI,WAAA,GAAsC,IAAA;AAE1C,IAAA,MAAM,QAAA,GAAW,IAAI,cAAA,CAIlB;AAAA,MACD,KAAA,EAAO,OAAO,KAAA,KAAU;AACtB,QAAA,IAAI,SAAA,EAAW;AACf,QAAA,IAAI,CAAC,IAAA,EAAM;AACT,UAAA,MAAM,IAAA,GAAO,OAAO,WAAA,KAAgB,MAAA,CAAO,WAAA,EAAY,CAAA;AACvD,UAAA,IAAA,GAAO,IAAI,OAAA,CAAQ,EAAE,IAAA,EAAM,OAAO,CAAA;AAClC,UAAA,MAAM,KAAK,KAAA,EAAM;AAEjB,UAAA,IAAI,mBAAmB,CAAA,EAAG;AACxB,YAAA,IAAA,CAAK,WAAW,gBAAgB,CAAA;AAAA,UAClC;AACA,UAAA,IAAA,CAAK,cAAc,eAAe,CAAA;AAAA,QACpC;AAEA,QAAA,OAAO,IAAA,IAAQ,CAAC,SAAA,KAAc,IAAA,CAAK,aAAY,GAAI,EAAA,IAAM,IAAA,CAAK,aAAA,EAAc,GAAI,EAAA,IAAM,IAAA,CAAK,aAAA,KAAkB,GAAA,CAAA,EAAM;AACjH,UAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,QAC7C;AACA,QAAA,IAAI,SAAA,EAAW;AACf,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,IAAI,CAAA;AACtB,QAAA,KAAA,CAAM,YAAA,IAAgB,MAAM,IAAA,CAAK,UAAA;AACjC,QAAA,KAAA,CAAM,SAAA,EAAA;AAAA,MACR;AAAA,KACD,CAAA;AAED,IAAA,MAAM,MAAA,GAAS,IAAI,EAAA,CAAG,YAAA,CAAa,QAAQ,CAAA;AAC3C,IAAA,MAAM,MAAA,GAAS,IAAI,EAAA,CAAG,MAAA,CAAO;AAAA,MAC3B,QAAQ,IAAI,EAAA,CAAG,gBAAgB,EAAE,SAAA,EAAW,cAAc,CAAA;AAAA,MAC1D;AAAA,KACD,CAAA;AAGD,IAAA,MAAM,WAAA,GAAc,IAAI,EAAA,CAAG,wBAAA,CAAyB,YAAa,CAAA;AACjE,IAAA,MAAA,CAAO,cAAc,WAAW,CAAA;AAGhC,IAAA,IAAI,WAAA,GAAuE,IAAA;AAC3E,IAAA,IAAI,YAAA,IAAgB,UAAA,EAAY,YAAA,EAAa,EAAG;AAC9C,MAAA,WAAA,GAAc,IAAI,EAAA,CAAG,wBAAA,CAAyB,YAAkC,CAAA;AAChF,MAAA,MAAA,CAAO,cAAc,WAAW,CAAA;AAAA,IAClC;AAEA,IAAA,aAAA,GAAgB,MAAA;AAChB,IAAA,OAAO,EAAE,MAAA,EAAQ,WAAA,EAAa,WAAA,EAAY;AAAA,EAC5C;AAEA,EAAA,eAAe,QAAA,CAAS,OAAe,QAAA,EAAkB;AACvD,IAAA,MAAM,EAAE,MAAA,EAAQ,WAAA,EAAa,WAAA,KAAgB,YAAA,EAAa;AAE1D,IAAA,MAAM,OAAO,KAAA,EAAM;AAInB,IAAA,MAAM,gBAAA,GACJ,QAAA,GAAW,CAAA,GACN,MAAM,UAAU,YAAA,CAAa,QAAQ,CAAA,IAAO,MAAM,SAAA,CAAU,cAAA,EAAe,GAC5E,MAAM,UAAU,cAAA,EAAe;AACrC,IAAA,IAAI,CAAC,gBAAA,EAAkB;AAEvB,IAAA,MAAM,mBAAmB,SAAA,GACpB,SAAA,IAAa,QAAA,GAAW,CAAA,GACpB,MAAM,SAAA,CAAU,SAAA,CAAU,QAAQ,CAAA,IAAO,MAAM,SAAA,CAAU,cAAA,KAC1D,MAAM,SAAA,CAAU,gBAAe,GACnC,IAAA;AAEJ,IAAA,MAAM,SAAA,GAAY,SAAA,CAAU,OAAA,CAAQ,gBAAgB,CAAA;AACpD,IAAA,MAAM,YAAY,SAAA,IAAa,gBAAA,GAAmB,SAAA,CAAU,OAAA,CAAQ,gBAAgB,CAAA,GAAI,IAAA;AAExF,IAAA,IAAI,KAAA,GAAQ,MAAM,SAAA,CAAU,IAAA,EAAK;AACjC,IAAA,IAAI,KAAA,GAAQ,SAAA,GAAY,MAAM,SAAA,CAAU,IAAA,KAAS,EAAE,IAAA,EAAM,IAAA,EAAe,KAAA,EAAO,MAAA,EAAU;AACzF,IAAA,IAAI,UAAA,GAAa,IAAA;AACjB,IAAA,IAAI,UAAA,GAAa,IAAA;AAEjB,IAAA,OAAO,CAAC,aAAa,SAAA,KAAc,KAAA,KAAU,CAAC,KAAA,CAAM,IAAA,IAAQ,CAAC,KAAA,CAAM,IAAA,CAAA,EAAO;AAExE,MAAA,OACE,CAAC,SAAA,IACD,SAAA,KAAc,KAAA,IACd,IAAA,KACC,KAAK,aAAA,EAAc,GAAI,EAAA,IAAM,IAAA,CAAK,aAAY,GAAI,EAAA,IAAM,IAAA,CAAK,aAAA,KAAkB,EAAA,CAAA,EAChF;AACA,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,GAAG,CAAC,CAAA;AAAA,MAC7C;AACA,MAAA,IAAI,SAAA,IAAa,cAAc,KAAA,EAAO;AAEtC,MAAA,MAAM,MAAM,CAAC,KAAA,CAAM,OAAO,KAAA,CAAM,KAAA,CAAM,YAAY,MAAA,CAAO,iBAAA;AACzD,MAAA,MAAM,MAAM,CAAC,KAAA,CAAM,OAAO,KAAA,CAAM,KAAA,CAAM,YAAY,MAAA,CAAO,iBAAA;AASzD,MAAA,MAAM,eAAA,GAAkB,UAAA,IAAc,CAAC,KAAA,CAAM,IAAA;AAE7C,MAAA,IAAI,CAAC,KAAA,CAAM,IAAA,KAAS,eAAA,IAAmB,OAAO,GAAA,CAAA,EAAM;AAClD,QAAA,MAAM,WAAA,CAAY,GAAA;AAAA,UAChB,KAAA,CAAM,KAAA;AAAA,UACN,UAAA,IAAc,WAAA,GAAc,EAAE,aAAA,EAAe,aAAY,GAAI;AAAA,SAC/D;AACA,QAAA,UAAA,GAAa,KAAA;AACb,QAAA,KAAA,CAAM,YAAA,EAAA;AACN,QAAA,KAAA,GAAQ,MAAM,UAAU,IAAA,EAAK;AAAA,MAC/B,CAAA,MAAA,IAAW,SAAA,IAAa,WAAA,IAAe,CAAC,MAAM,IAAA,EAAM;AAClD,QAAA,MAAM,WAAA,CAAY,GAAA;AAAA,UAChB,KAAA,CAAM,KAAA;AAAA,UACN,UAAA,IAAc,WAAA,GAAc,EAAE,aAAA,EAAe,aAAY,GAAI;AAAA,SAC/D;AACA,QAAA,UAAA,GAAa,KAAA;AACb,QAAA,KAAA,CAAM,YAAA,EAAA;AACN,QAAA,KAAA,GAAQ,MAAM,UAAU,IAAA,EAAK;AAAA,MAC/B,CAAA,MAAO;AACL,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,SAAA,IAAa,SAAA,KAAc,KAAA,EAAO;AACrC,MAAA,MAAM,OAAO,QAAA,EAAS;AACtB,MAAA,IAAA,EAAM,WAAA,EAAY;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,KAAA,CAAM,QAAA,GAAW,CAAA,EAAG,WAAW,KAAA,EAAO;AAG1C,MAAA,eAAA,GAAkB,QAAA;AAClB,MAAA,gBAAA,GAAmB,QAAA;AACnB,MAAA,QAAA,CAAS,EAAE,SAAA,EAAW,QAAQ,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAE7C,QAAA,OAAA,CAAQ,KAAA,CAAM,qCAAqC,GAAG,CAAA;AACtD,QAAA,IAAI;AAAE,UAAA,IAAA,EAAM,OAAA,EAAQ;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAe;AAAA,MAChD,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,MAAM,IAAA,CAAK,IAAA,EAAM,QAAA,GAAW,KAAA,EAAO;AACjC,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,IAAA,CAAK,cAAc,QAAQ,CAAA;AAC3B,QAAA,IAAA,CAAK,WAAW,IAAI,CAAA;AAAA,MACtB,CAAA,MAAO;AACL,QAAA,eAAA,GAAkB,QAAA;AAClB,QAAA,gBAAA,GAAmB,IAAA;AAAA,MACrB;AACA,MAAA,QAAA,CAAS,EAAE,SAAA,EAAW,IAAI,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAEzC,QAAA,OAAA,CAAQ,KAAA,CAAM,4CAA4C,GAAG,CAAA;AAAA,MAC/D,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,YAAY,QAAA,EAAU;AACpB,MAAA,eAAA,GAAkB,QAAA;AAClB,MAAA,IAAI,IAAA,EAAM,IAAA,CAAK,aAAA,CAAc,QAAQ,CAAA;AAAA,IACvC,CAAA;AAAA,IACA,MAAM,aAAA,CAAc,OAAA,EAAS,IAAA,EAAM,QAAA,EAAU;AAC3C,MAAA,IAAI,yBAAyB,OAAA,EAAS;AACtC,MAAA,IAAI,CAAC,IAAI,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,OAAO,CAAA,EAAG;AAClD,QAAA,OAAA,CAAQ,IAAA,CAAK,2DAAsD,OAAO,CAAA;AAC1E,QAAA;AAAA,MACF;AAGA,MAAA,SAAA,EAAA;AACA,MAAA,oBAAA,GAAuB,OAAA;AACvB,MAAA,MAAM,YAAA,EAAa,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAClC,QAAA,OAAA,CAAQ,IAAA,CAAK,wCAAA,EAA2C,GAAA,CAAc,OAAO,CAAA;AAAA,MAC/E,CAAC,CAAA;AAKD,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,IAAI;AAAE,UAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAe;AAC7C,QAAA,IAAA,GAAO,IAAA;AAAA,MACT;AACA,MAAA,eAAA,GAAkB,QAAA;AAClB,MAAA,gBAAA,GAAmB,IAAA;AACnB,MAAA,QAAA,CAAS,EAAE,SAAA,EAAW,IAAI,CAAA,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAEzC,QAAA,OAAA,CAAQ,KAAA,CAAM,wDAAwD,GAAG,CAAA;AAAA,MAC3E,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,MAAM,OAAA,GAAU;AACd,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,SAAA,EAAA;AACA,MAAA,IAAI;AAAE,QAAA,IAAI,aAAA,EAAe,MAAM,aAAA,CAAc,MAAA,EAAO;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC9E,MAAA,IAAI;AAAE,QAAA,MAAM,MAAM,OAAA,EAAQ;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACpD,MAAA,IAAA,EAAM,OAAA,EAAQ;AAAA,IAChB,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,WAAA,EAAa,OAAA,EAAQ;AAAA,IAC1C;AAAA,GACF;AACF;;;AC/TA,eAAsB,kBAAA,CACpB,SACA,KAAA,EAC0B;AAC1B,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAW,MAAM,mBAAA,CAAoB,OAAA,EAAS,KAAK,CAAA;AAAA,EACrD,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,gCAAA,EAAoC,IAAc,OAAO,CAAA,0FAAA;AAAA,KAC3D;AAAA,EACF;AAKA,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,OAAA;AAAA,IACV,MAAM,IAAA,GAAO;AACX,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,IAAI,CAAC,OAAA,EAAS;AAGZ,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,MAAM,QAAA,CAAS,KAAA,CAAM,KAAA,CAAM,WAAA,IAAe,GAAG,IAAI,CAAA;AACjD,QAAA;AAAA,MACF;AAQA,MAAA,QAAA,CAAS,YAAY,IAAI,CAAA;AACzB,MAAA,IAAI;AACF,QAAA,MAAM,MAAM,IAAA,EAAK;AAAA,MACnB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,QAAA,GAAW,KAAA;AACX,MAAA,KAAA,CAAM,KAAA,EAAM;AAAA,IACd,CAAA;AAAA,IACA,MAAM,KAAK,IAAA,EAAM;AACf,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,OAAA,GAAU,IAAA;AAIV,QAAA,MAAM,QAAA,CAAS,IAAA,CAAK,IAAA,EAAM,QAAQ,CAAA;AAClC,QAAA;AAAA,MACF;AACA,MAAA,MAAM,UAAA,GAAa,CAAC,KAAA,CAAM,MAAA;AAC1B,MAAA,MAAM,QAAA,CAAS,IAAA,CAAK,IAAA,EAAM,UAAA,IAAc,QAAQ,CAAA;AAMhD,MAAA,cAAA,CAAe,MAAM;AACnB,QAAA,IAAI;AAAE,UAAA,KAAA,CAAM,aAAA,CAAc,IAAI,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAe;AAAA,MACzE,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,MAAM,cAAc,EAAA,EAAI;AACtB,MAAA,IAAI,CAAC,QAAQ,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,EAAG;AACjD,QAAA,OAAA,CAAQ,IAAA,CAAK,2DAAsD,EAAE,CAAA;AACrE,QAAA;AAAA,MACF;AACA,MAAA,MAAM,UAAA,GAAa,CAAC,KAAA,CAAM,MAAA;AAC1B,MAAA,MAAM,IAAA,GAAO,MAAM,WAAA,IAAe,CAAA;AAElC,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,MAAM,QAAA,CAAS,aAAA,CAAc,EAAA,EAAI,IAAA,EAAM,YAAY,UAAU,CAAA;AAC7D,QAAA;AAAA,MACF;AACA,MAAA,MAAM,QAAA,CAAS,aAAA,CAAc,EAAA,EAAI,IAAA,EAAM,cAAc,QAAQ,CAAA;AAAA,IAC/D,CAAA;AAAA,IACA,MAAM,iBAAiB,EAAA,EAAI;AACzB,MAAA,MAAM,SAAS,KAAA,CAAM,UAAA;AACrB,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,MAAA,CAAO,CAAC,CAAA,CAAE,IAAA,GAAO,CAAA,KAAM,KAAK,SAAA,GAAY,UAAA;AAAA,MAC1C;AAAA,IACF,CAAA;AAAA,IACA,cAAA,GAAiB;AACf,MAAA,OAAO,MAAM,WAAA,IAAe,CAAA;AAAA,IAC9B,CAAA;AAAA,IACA,MAAM,OAAA,GAAU;AACd,MAAA,KAAA,CAAM,KAAA,EAAM;AACZ,MAAA,MAAM,SAAS,OAAA,EAAQ;AACvB,MAAA,KAAA,CAAM,gBAAgB,KAAK,CAAA;AAC3B,MAAA,KAAA,CAAM,IAAA,EAAK;AAAA,IACb,CAAA;AAAA,IACA,eAAA,GAAkB;AAChB,MAAA,OAAO,SAAS,KAAA,EAAM;AAAA,IACxB;AAAA,GACF;AACF;;;ACrFA,SAAS,OAAA,GAAmB;AAC1B,EAAA,OAAO,OAAO,UAAA,KAAe,WAAA,IAAe,CAAC,CAAE,UAAA,CAAuC,cAAA;AACxF;AACA,IAAI,YAAA,GAAe,CAAA;AAEZ,IAAM,gBAAN,MAAoB;AAAA,EA6CzB,WAAA,CACmB,MAAA,EACA,KAAA,EACjB,GAAA,GAAM,EAAA,EACN;AAHiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAGjB,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,MAAO,GAAG,CAAA;AAC7C,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACpD,MAAA,IAAA,CAAK,iBAAA,GAAoB,OAAA;AAAA,IAC3B,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAO7C,IAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAChB,iHAAA;AAUF,IAAA,MAAM,MAAA,GACH,MAAA,CAAO,aAAA,IAAuC,MAAA,CAAO,UAAA;AACxD,IAAA,IAAI,MAAA,IAAU,kBAAkB,WAAA,EAAa;AAC3C,MAAA,IAAI,gBAAA,CAAiB,MAAM,CAAA,CAAE,QAAA,KAAa,QAAA,EAAU;AAClD,QAAA,MAAA,CAAO,MAAM,QAAA,GAAW,UAAA;AAAA,MAC1B;AAAA,IACF;AACA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAA,CAAO,YAAA,CAAa,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAA;AAAA,IACzC,CAAA,MAAO;AAML,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN;AAAA,OAEF;AACA,MAAA,QAAA,CAAS,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA;AAAA,IACvC;AACA,IAAA,MAAA,CAAO,MAAM,UAAA,GAAa,QAAA;AAK1B,IAAA,MAAM,aAAA,GAAgB,MAAA,YAAkB,WAAA,GAAc,MAAA,GAAS,QAAA,CAAS,IAAA;AACxE,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAI,eAAA,CAAgB,aAAa,CAAA;AAGxD,IAAA,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAE3B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA;AACvC,IAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,8CAA8C,CAAA;AACxE,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AAEX,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAC/B,IAAA,IAAA,CAAK,SAAA,GAAY,qBAAA,CAAsB,IAAA,CAAK,IAAI,CAAA;AAAA,EAClD;AAAA,EAjEmB,MAAA;AAAA,EACA,KAAA;AAAA,EA9CX,MAAA;AAAA,EACA,GAAA;AAAA,EACA,QAAsB,EAAC;AAAA,EACvB,SAAA,GAA2B,IAAA;AAAA,EAC3B,SAAA,GAAY,KAAA;AAAA,EAEZ,aAAA,GAAgB,CAAA;AAAA,EAChB,iBAAA,GAAoB,CAAA;AAAA,EACpB,qBAAA,GAAwB,CAAA;AAAA,EACxB,SAAA,GAAY,KAAA;AAAA;AAAA,EAEZ,aAAA,GAAgB,CAAA;AAAA;AAAA,EAEhB,eAAA;AAAA;AAAA,EAEA,YAAA,GAAe,CAAA;AAAA;AAAA,EAEf,YAAA,GAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASf,eAAA,GAA0C,IAAA;AAAA,EAC1C,aAAA,GAAkC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASlC,gBAAA,GAAmB,CAAA;AAAA,EACnB,aAAA,GAAgB,KAAA;AAAA,EAChB,mBAAA,GAAsB,CAAA;AAAA;AAAA,EAGrB,eAAA;AAAA,EACD,iBAAA;AAAA;AAAA,EAuER,SAAA,GAAqB;AACnB,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,KAAK,aAAA,GAAgB,CAAA;AAAA,EACvD;AAAA;AAAA,EAGA,UAAA,GAAqB;AACnB,IAAA,OAAO,KAAK,KAAA,CAAM,MAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASS,cAAA,GAAiB,EAAA;AAAA,EAE1B,QAAQ,KAAA,EAAyB;AAC/B,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,KAAA,CAAM,KAAA,EAAM;AACZ,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,KAAK,CAAA;AACrB,IAAA,IAAI,KAAK,KAAA,CAAM,MAAA,KAAW,CAAA,IAAK,IAAA,CAAK,kBAAkB,CAAA,EAAG;AACvD,MAAA,IAAA,CAAK,iBAAA,EAAkB;AAAA,IACzB;AAIA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,EAAA,EAAI;AAC7B,MAAA,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM,EAAG,KAAA,EAAM;AAC1B,MAAA,IAAA,CAAK,qBAAA,EAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAgB,MAAA,EAAgC;AACtD,IAAA,MAAM,OAAO,MAAM;AACjB,MAAA,IAAI,KAAK,aAAA,EAAe;AACxB,MAAA,MAAM,SAAS,MAAA,CAAO,UAAA;AACtB,MAAA,IAAI,SAAQ,EAAG;AAEb,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,8CAAA,EAA4C,MAAA,CAAO,MAAM,CAAA,OAAA,CAAS,CAAA;AAAA,MAChF;AACA,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,MAAM,CAAA,GAAI,OAAO,CAAC,CAAA;AAClB,QAAA,IAAI,SAAQ,EAAG;AAEb,UAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,sBAAA,EAAyB,CAAC,CAAA,OAAA,EAAU,EAAE,IAAI,CAAA,MAAA,EAAS,CAAA,CAAE,IAAI,CAAA,MAAA,EAAS,CAAA,CAAE,IAAA,EAAM,MAAA,IAAU,CAAC,CAAA,CAAE,CAAA;AAAA,QACrG;AACA,QAAA,IAAI,CAAA,CAAE,IAAA,KAAS,WAAA,IAAe,CAAA,CAAE,SAAS,UAAA,EAAY;AACnD,UAAA,IAAA,CAAK,aAAA,GAAgB,CAAA;AACrB,UAAA,CAAA,CAAE,IAAA,GAAO,QAAA;AACT,UAAA,IAAI,SAAQ,EAAG;AAEb,YAAA,OAAA,CAAQ,IAAI,CAAA,yCAAA,CAA2C,CAAA;AAAA,UACzD;AAEA,UAAA,MAAM,UAAU,MAAA,CAAO,aAAA,CAAc,CAAA,eAAA,EAAkB,CAAA,CAAE,QAAQ,CAAA,EAAA,CAAI,CAAA;AACrE,UAAA,IAAI,OAAA,EAAS;AACX,YAAA,OAAA,CAAQ,gBAAA,CAAiB,QAAQ,MAAM;AACrC,cAAA,IAAI,SAAQ,EAAG;AAEb,gBAAA,OAAA,CAAQ,IAAI,CAAA,2CAAA,EAA8C,CAAA,CAAE,IAAA,EAAM,MAAA,IAAU,CAAC,CAAA,CAAE,CAAA;AAAA,cACjF;AAAA,YACF,CAAC,CAAA;AACD,YAAA,OAAA,CAAQ,gBAAA,CAAiB,OAAA,EAAS,CAAC,EAAA,KAAO;AAExC,cAAA,OAAA,CAAQ,IAAA,CAAK,wCAAwC,EAAE,CAAA;AAAA,YACzD,CAAC,CAAA;AAAA,UACH;AACA,UAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAA;AACA,IAAA,IAAA,EAAK;AACL,IAAA,IAAI,OAAO,MAAA,CAAO,UAAA,CAAW,gBAAA,KAAqB,UAAA,EAAY;AAC5D,MAAA,MAAA,CAAO,UAAA,CAAW,gBAAA,CAAiB,UAAA,EAAY,CAAC,CAAA,KAAM;AACpD,QAAA,IAAI,SAAQ,EAAG;AAEb,UAAA,OAAA,CAAQ,IAAI,sCAAsC,CAAA;AAAA,QACpD;AAEA,QAAA,IAAA,EAAK;AAAA,MACP,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEQ,WAAA,GAAc,KAAA;AAAA;AAAA,EAGd,eAAA,GAAwB;AAC9B,IAAA,IAAI,CAAC,IAAA,CAAK,eAAA,IAAmB,CAAC,KAAK,aAAA,EAAe;AAClD,IAAA,MAAM,IAAA,GAAO,KAAK,aAAA,CAAc,IAAA;AAChC,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG;AAChC,IAAA,IAAI,OAAA,EAAQ,IAAK,CAAC,IAAA,CAAK,WAAA,EAAa;AAClC,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAEnB,MAAA,OAAA,CAAQ,IAAI,CAAA,gCAAA,EAAmC,IAAA,CAAK,MAAM,CAAA,cAAA,EAAiB,KAAK,CAAC,CAAA,CAAE,SAAS,CAAA,WAAA,EAAc,KAAK,IAAA,CAAK,MAAA,GAAO,CAAC,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA;AAAA,IACzI;AACA,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,GAAA,EAAI;AACzB,IAAA,IAAI,UAAA,GAAa,EAAA;AACjB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACpC,MAAA,MAAM,CAAA,GAAI,KAAK,CAAC,CAAA;AAChB,MAAA,IAAI,CAAA,IAAK,CAAA,CAAE,SAAA,IAAa,CAAA,IAAK,EAAE,OAAA,EAAS;AACtC,QAAA,MAAM,MAAA,GAAS,CAAA;AACf,QAAA,UAAA,GAAa,OAAO,IAAA,IAAQ,EAAA;AAC5B,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,gBAAgB,OAAA,CAAQ,UAAA,CAAW,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAC,CAAA;AAAA,EACjE;AAAA,EAEQ,IAAA,GAAa;AACnB,IAAA,IAAI,KAAK,SAAA,EAAW;AACpB,IAAA,IAAA,CAAK,SAAA,GAAY,qBAAA,CAAsB,IAAA,CAAK,IAAI,CAAA;AAEhD,IAAA,IAAA,CAAK,eAAA,EAAgB;AAErB,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAE7B,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,SAAA,EAAU;AAGrC,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM;AAC9B,QAAA,IAAA,CAAK,MAAM,IAAI,CAAA;AACf,QAAA,IAAA,CAAK,KAAA,EAAM;AACX,QAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,QAAA,IAAA,CAAK,aAAA,GAAgB,YAAY,GAAA,EAAI;AAAA,MACvC;AACA,MAAA;AAAA,IACF;AASA,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,GAAA,EAAI,GAAI,GAAA;AACzC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,CAAC,EAAE,SAAA,IAAa,CAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,MAAA,GAAS,CAAA,IAAK,IAAA,CAAK,MAAM,MAAA,GAAS,CAAA;AAEjD,IAAA,IAAI,MAAA,EAAQ;AAMV,MAAA,MAAMA,QAAAA,GAAU,YAAY,GAAA,EAAI;AAChC,MAAA,IAAI,CAAC,IAAA,CAAK,aAAA,IAAiBA,QAAAA,GAAU,IAAA,CAAK,sBAAsB,GAAA,EAAQ;AACtE,QAAA,IAAA,CAAK,mBAAmB,MAAA,GAAS,aAAA;AACjC,QAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,QAAA,IAAA,CAAK,mBAAA,GAAsBA,QAAAA;AAAA,MAC7B;AAEA,MAAA,MAAM,UAAA,GAAa,gBAAgB,IAAA,CAAK,gBAAA;AACxC,MAAA,MAAM,eAAA,GAAkB,KAAK,eAAA,GAAkB,GAAA;AAC/C,MAAA,MAAM,aAAa,UAAA,GAAa,eAAA;AAEhC,MAAA,IAAI,OAAA,GAAU,EAAA;AACd,MAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AAC1C,QAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,CAAC,EAAE,SAAA,IAAa,CAAA;AACtC,QAAA,IAAI,MAAM,UAAA,EAAY;AACpB,UAAA,OAAA,GAAU,CAAA;AAAA,QACZ,CAAA,MAAO;AACL,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,IAAA,CAAK,YAAA,EAAA;AACL,QAAA,IAAI,SAAQ,EAAG;AACb,UAAA,MAAM,GAAA,GAAM,YAAY,GAAA,EAAI;AAC5B,UAAA,IAAI,GAAA,GAAM,eAAe,GAAA,EAAM;AAC7B,YAAA,MAAM,SAAA,GAAA,CAAa,MAAA,GAAS,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAA;AAC3C,YAAA,MAAM,OAAA,GAAA,CAAW,UAAA,GAAa,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAA;AAC7C,YAAA,MAAM,UAAA,GAAA,CAAA,CAAe,MAAA,GAAS,aAAA,IAAiB,GAAA,EAAM,QAAQ,CAAC,CAAA;AAC9D,YAAA,MAAM,OAAA,GAAA,CAAW,IAAA,CAAK,gBAAA,GAAmB,GAAA,EAAM,QAAQ,CAAC,CAAA;AAExD,YAAA,OAAA,CAAQ,GAAA;AAAA,cACN,8BAA8B,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA,SAAA,EAAY,SAAS,CAAA,cAAA,EAAiB,OAAO,CAAA,YAAA,EAChF,UAAU,YAAY,OAAO,CAAA,WAAA,EAAc,KAAK,aAAa,CAAA,SAAA,EAAY,KAAK,iBAAiB,CAAA;AAAA,aAC7G;AACA,YAAA,YAAA,GAAe,GAAA;AAAA,UACjB;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,eAAA,GAAkB,aAAa,eAAA,GAAkB,CAAA;AACvD,MAAA,IAAI,OAAA,GAAU,CAAA;AACd,MAAA,OAAO,UAAU,CAAA,EAAG;AAClB,QAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,CAAC,EAAE,SAAA,IAAa,CAAA;AACtC,QAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,UAAA,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM,EAAG,KAAA,EAAM;AAC1B,UAAA,IAAA,CAAK,iBAAA,EAAA;AACL,UAAA,OAAA,EAAA;AACA,UAAA,OAAA,EAAA;AAAA,QACF,CAAA,MAAO;AACL,UAAA;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAA,CAAK,YAAA,EAAA;AAEL,MAAA,IAAI,SAAQ,EAAG;AACb,QAAA,MAAM,GAAA,GAAM,YAAY,GAAA,EAAI;AAC5B,QAAA,IAAI,GAAA,GAAM,eAAe,GAAA,EAAM;AAC7B,UAAA,MAAM,SAAA,GAAa,IAAA,CAAK,KAAA,CAAM,CAAC,GAAG,SAAA,IAAa,CAAA;AAC/C,UAAA,MAAM,OAAA,GAAA,CAAW,UAAA,GAAa,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAA;AAC7C,UAAA,MAAM,KAAA,GAAA,CAAS,SAAA,GAAY,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAA;AAC1C,UAAA,MAAM,UAAA,GAAA,CAAA,CAAe,SAAA,GAAY,aAAA,IAAiB,GAAA,EAAM,QAAQ,CAAC,CAAA;AACjE,UAAA,MAAM,OAAA,GAAA,CAAW,IAAA,CAAK,gBAAA,GAAmB,GAAA,EAAM,QAAQ,CAAC,CAAA;AAExD,UAAA,OAAA,CAAQ,GAAA;AAAA,YACN,+BAA+B,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA,YAAA,EAAe,OAAO,cAAc,KAAK,CAAA,YAAA,EAC7E,UAAU,CAAA,SAAA,EAAY,OAAO,cAAc,OAAO,CAAA,aAAA,EAAgB,KAAK,iBAAiB,CAAA,SAAA,EAAY,KAAK,aAAa,CAAA;AAAA,WACpI;AACA,UAAA,YAAA,GAAe,GAAA;AAAA,QACjB;AAAA,MACF;AAEA,MAAA,MAAMC,MAAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM;AAC/B,MAAA,IAAA,CAAK,MAAMA,MAAK,CAAA;AAChB,MAAAA,OAAM,KAAA,EAAM;AACZ,MAAA,IAAA,CAAK,aAAA,GAAgB,YAAY,GAAA,EAAI;AACrC,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,OAAA,GAAU,YAAY,GAAA,EAAI;AAChC,IAAA,IAAI,OAAA,GAAU,IAAA,CAAK,aAAA,GAAgB,IAAA,CAAK,kBAAkB,CAAA,EAAG;AAE7D,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,EAAM;AAC/B,IAAA,IAAA,CAAK,MAAM,KAAK,CAAA;AAChB,IAAA,KAAA,CAAM,KAAA,EAAM;AACZ,IAAA,IAAA,CAAK,aAAA,GAAgB,OAAA;AAAA,EACvB;AAAA,EAEQ,MAAM,KAAA,EAAyB;AACrC,IAAA,IACE,IAAA,CAAK,OAAO,KAAA,KAAU,KAAA,CAAM,gBAC5B,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,KAAA,CAAM,aAAA,EAC7B;AACA,MAAA,IAAA,CAAK,MAAA,CAAO,QAAQ,KAAA,CAAM,YAAA;AAC1B,MAAA,IAAA,CAAK,MAAA,CAAO,SAAS,KAAA,CAAM,aAAA;AAAA,IAC7B;AACA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,GAAA,CAAI,SAAA,CAAU,KAAA,EAAO,CAAA,EAAG,CAAA,EAAG,KAAK,MAAA,CAAO,KAAA,EAAO,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AACrE,MAAA,IAAA,CAAK,aAAA,EAAA;AAAA,IACP,SAAS,GAAA,EAAK;AAGZ,MAAA,IAAI,IAAA,CAAK,aAAA,KAAkB,CAAA,IAAK,IAAA,CAAK,sBAAsB,CAAA,EAAG;AAE5D,QAAA,OAAA,CAAQ,IAAA,CAAK,uCAAuC,GAAG,CAAA;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,KAAA,GAAc;AACZ,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,CAAM,MAAA;AACzB,IAAA,OAAO,IAAA,CAAK,MAAM,MAAA,GAAS,CAAA,OAAQ,KAAA,CAAM,KAAA,IAAS,KAAA,EAAM;AACxD,IAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AACjB,IAAA,IAAA,CAAK,aAAA,GAAgB,KAAA;AACrB,IAAA,IAAI,OAAA,EAAQ,IAAK,KAAA,GAAQ,CAAA,EAAG;AAE1B,MAAA,OAAA,CAAQ,GAAA,CAAI,uCAAuC,KAAK,CAAA,SAAA,EAAY,KAAK,aAAa,CAAA,OAAA,EAAU,IAAA,CAAK,iBAAiB,CAAA,CAAE,CAAA;AAAA,IAC1H;AAAA,EACF;AAAA,EAEA,KAAA,GAAiC;AAC/B,IAAA,OAAO;AAAA,MACL,eAAe,IAAA,CAAK,aAAA;AAAA,MACpB,mBAAmB,IAAA,CAAK,iBAAA;AAAA,MACxB,uBAAuB,IAAA,CAAK,qBAAA;AAAA,MAC5B,UAAA,EAAY,KAAK,KAAA,CAAM;AAAA,KACzB;AAAA,EACF;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,EAAM,oBAAA,CAAqB,KAAK,SAAS,CAAA;AAC/D,IAAA,IAAA,CAAK,KAAA,EAAM;AACX,IAAA,IAAI,KAAK,eAAA,EAAiB;AAAE,MAAA,IAAA,CAAK,gBAAgB,OAAA,EAAQ;AAAG,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,IAAM;AACzF,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,IAAA,IAAA,CAAK,OAAO,MAAA,EAAO;AACnB,IAAA,IAAA,CAAK,MAAA,CAAO,MAAM,UAAA,GAAa,EAAA;AAAA,EACjC;AACF,CAAA;;;AC/YO,IAAM,cAAN,MAAyC;AAAA,EACtC,GAAA;AAAA,EACA,IAAA;AAAA,EAEA,KAAA,GAAuC,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYvC,OAAA,GAAU,KAAA;AAAA;AAAA,EAEV,YAAA,GAAe,CAAA;AAAA;AAAA,EAGf,eAAA,GAAkB,CAAA;AAAA;AAAA,EAGlB,iBAAA,GAAoB,CAAA;AAAA,EACpB,eAAA,GAAkB,CAAA;AAAA,EAElB,eAA+B,EAAC;AAAA,EAEhC,eAAA,GAAkB,CAAA;AAAA,EAClB,SAAA,GAAY,KAAA;AAAA;AAAA,EAGZ,OAAA,GAAU,CAAA;AAAA;AAAA,EAEV,MAAA,GAAS,KAAA;AAAA;AAAA;AAAA;AAAA,EAIT,KAAA,GAAQ,CAAA;AAAA,EAEhB,WAAA,GAAc;AACZ,IAAA,IAAA,CAAK,GAAA,GAAM,IAAI,YAAA,EAAa;AAC5B,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,UAAA,EAAW;AAChC,IAAA,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,UAAU,CAAA,EAAiB;AACzB,IAAA,IAAA,CAAK,OAAA,GAAU,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,CAAC,CAAC,CAAA;AACzC,IAAA,IAAA,CAAK,SAAA,EAAU;AAAA,EACjB;AAAA,EAEA,SAAA,GAAoB;AAClB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA,EAGA,SAAS,CAAA,EAAkB;AACzB,IAAA,IAAA,CAAK,MAAA,GAAS,CAAA;AACd,IAAA,IAAA,CAAK,SAAA,EAAU;AAAA,EACjB;AAAA,EAEA,QAAA,GAAoB;AAClB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,IAAA,EAAoB;AAClC,IAAA,IAAI,IAAA,KAAS,KAAK,KAAA,EAAO;AAGzB,IAAA,MAAM,CAAA,GAAI,KAAK,GAAA,EAAI;AACnB,IAAA,IAAA,CAAK,iBAAA,GAAoB,CAAA;AACzB,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,CAAI,WAAA;AAChC,IAAA,IAAA,CAAK,YAAA,GAAe,YAAY,GAAA,EAAI;AACpC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,EACf;AAAA,EAEA,eAAA,GAA0B;AACxB,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA,EAEQ,SAAA,GAAkB;AACxB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,OAAA;AACtC,IAAA,IAAI;AAAE,MAAA,IAAA,CAAK,IAAA,CAAK,KAAK,KAAA,GAAQ,MAAA;AAAA,IAAQ,CAAA,CAAA,MAAQ;AAAA,IAAe;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,EACjB;AAAA;AAAA,EAIA,GAAA,GAAc;AACZ,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAI,IAAA,CAAK,UAAU,SAAA,EAAW;AAC5B,QAAA,OAAO,IAAA,CAAK,qBAAqB,WAAA,CAAY,GAAA,KAAQ,IAAA,CAAK,YAAA,IAAgB,MAAO,IAAA,CAAK,KAAA;AAAA,MACxF;AACA,MAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,IACd;AACA,IAAA,IAAI,IAAA,CAAK,UAAU,SAAA,EAAW;AAC5B,MAAA,OAAO,KAAK,iBAAA,GAAA,CAAqB,IAAA,CAAK,IAAI,WAAA,GAAc,IAAA,CAAK,mBAAmB,IAAA,CAAK,KAAA;AAAA,IACvF;AACA,IAAA,OAAO,IAAA,CAAK,iBAAA;AAAA,EACd;AAAA,EAEA,SAAA,GAAqB;AACnB,IAAA,OAAO,KAAK,KAAA,KAAU,SAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAA,GAAsB;AAIpB,IAAA,IAAI,IAAA,CAAK,SAAS,OAAO,CAAA;AACzB,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzB,MAAA,IAAI,GAAA,GAAM,CAAA;AACV,MAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,YAAA,EAAc,GAAA,IAAO,CAAA,CAAE,WAAA;AAC5C,MAAA,OAAO,GAAA;AAAA,IACT;AACA,IAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,eAAA,GAAkB,IAAA,CAAK,KAAK,CAAA;AAAA,EACtD;AAAA;AAAA,EAGA,SAAA,GAAqB;AACnB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAA,CAAS,OAAA,EAAuB,QAAA,EAAkB,UAAA,EAA0B;AAC1E,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,OAAA,EAAS;AACpC,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,GAAS,QAAA;AACpC,IAAA,MAAM,cAAc,UAAA,GAAa,UAAA;AAEjC,IAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,IAAU,IAAA,CAAK,UAAU,QAAA,EAAU;AACpD,MAAA,IAAA,CAAK,YAAA,CAAa,KAAK,EAAE,OAAA,EAAS,UAAU,UAAA,EAAY,UAAA,EAAY,aAAa,CAAA;AACjF,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,WAAA,CAAY,OAAA,EAAS,QAAA,EAAU,UAAA,EAAY,UAAU,CAAA;AAAA,EAC5D;AAAA,EAEQ,WAAA,CACN,OAAA,EACA,QAAA,EACA,UAAA,EACA,UAAA,EACM;AACN,IAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,YAAA,CAAa,QAAA,EAAU,YAAY,UAAU,CAAA;AACrE,IAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,QAAA,EAAU,EAAA,EAAA,EAAM;AACpC,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,cAAA,CAAe,EAAE,CAAA;AAC5C,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,EAAY,CAAA,EAAA,EAAK;AACnC,QAAA,WAAA,CAAY,CAAC,CAAA,GAAI,OAAA,CAAQ,CAAA,GAAI,WAAW,EAAE,CAAA;AAAA,MAC5C;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAmB;AACzC,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,IAAI,CAAA;AAEtB,IAAA,IAAI,KAAK,KAAA,KAAU,CAAA,EAAG,IAAA,CAAK,YAAA,CAAa,QAAQ,IAAA,CAAK,KAAA;AAIrD,IAAA,IAAI,WAAW,IAAA,CAAK,eAAA,GAAA,CAAmB,KAAK,eAAA,GAAkB,IAAA,CAAK,qBAAqB,IAAA,CAAK,KAAA;AAkB7F,IAAA,IAAI,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa;AACnC,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,CAAI,WAAA;AAChC,MAAA,IAAA,CAAK,oBAAoB,IAAA,CAAK,eAAA;AAC9B,MAAA,QAAA,GAAW,KAAK,GAAA,CAAI,WAAA;AAAA,IACtB;AAEA,IAAA,IAAA,CAAK,MAAM,QAAQ,CAAA;AAEnB,IAAA,IAAA,CAAK,mBAAmB,UAAA,GAAa,UAAA;AACrC,IAAA,IAAA,CAAK,eAAA,EAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,KAAA,KAAU,SAAA,EAAW;AAKhD,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,YAAA,GAAe,YAAY,GAAA,EAAI;AACpC,MAAA,IAAA,CAAK,KAAA,GAAQ,SAAA;AACb,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAA,KAAU,WAAA,EAAa;AAClC,MAAA,MAAM,IAAA,CAAK,IAAI,MAAA,EAAO;AAAA,IACxB;AAIA,IAAA,IAAI;AAAE,MAAA,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAAe;AAEtE,IAAA,IAAI,IAAA,CAAK,UAAU,QAAA,EAAU;AAI3B,MAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,CAAI,WAAA;AAChC,MAAA,IAAA,CAAK,KAAA,GAAQ,SAAA;AAEb,MAAA,MAAMC,SAAQ,IAAA,CAAK,YAAA;AACnB,MAAA,IAAA,CAAK,eAAe,EAAC;AACrB,MAAA,KAAA,MAAW,KAAKA,MAAAA,EAAO;AACrB,QAAA,IAAA,CAAK,WAAA,CAAY,EAAE,OAAA,EAAS,CAAA,CAAE,UAAU,CAAA,CAAE,UAAA,EAAY,EAAE,UAAU,CAAA;AAAA,MACpE;AACA,MAAA;AAAA,IACF;AAKA,IAAA,MAAM,aAAA,GAAgB,IAAA;AACtB,IAAA,IAAA,CAAK,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,WAAA,GAAc,aAAA;AAC9C,IAAA,IAAA,CAAK,kBAAkB,IAAA,CAAK,iBAAA;AAC5B,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAA;AAEb,IAAA,MAAM,QAAQ,IAAA,CAAK,YAAA;AACnB,IAAA,IAAA,CAAK,eAAe,EAAC;AACrB,IAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,MAAA,IAAA,CAAK,WAAA,CAAY,EAAE,OAAA,EAAS,CAAA,CAAE,UAAU,CAAA,CAAE,UAAA,EAAY,EAAE,UAAU,CAAA;AAAA,IACpE;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,IAAA,CAAK,UAAU,SAAA,EAAW;AAC9B,IAAA,IAAA,CAAK,iBAAA,GAAoB,KAAK,GAAA,EAAI;AAClC,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAA;AACb,IAAA,IAAI,KAAK,OAAA,EAAS;AAMlB,IAAA,IAAI;AAAE,MAAA,IAAA,CAAK,KAAK,UAAA,EAAW;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAAe;AACrD,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAA,KAAU,SAAA,EAAW;AAChC,MAAA,MAAM,IAAA,CAAK,IAAI,OAAA,EAAQ;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,MAAM,YAAA,EAAqC;AAC/C,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,eAAe,EAAC;AACrB,MAAA,IAAA,CAAK,iBAAA,GAAoB,YAAA;AACzB,MAAA,IAAA,CAAK,YAAA,GAAe,YAAY,GAAA,EAAI;AACpC,MAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AAAE,MAAA,IAAA,CAAK,KAAK,UAAA,EAAW;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAAe;AACrD,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,UAAA,EAAW;AAChC,IAAA,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA;AACtC,IAAA,IAAA,CAAK,SAAA,EAAU;AAEf,IAAA,IAAA,CAAK,eAAe,EAAC;AACrB,IAAA,IAAA,CAAK,iBAAA,GAAoB,YAAA;AACzB,IAAA,IAAA,CAAK,eAAA,GAAkB,YAAA;AACvB,IAAA,IAAA,CAAK,eAAA,GAAkB,KAAK,GAAA,CAAI,WAAA;AAChC,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AAEb,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAA,KAAU,SAAA,EAAW;AAChC,MAAA,MAAM,IAAA,CAAK,IAAI,OAAA,EAAQ;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,KAAA,GAAiC;AAC/B,IAAA,OAAO;AAAA,MACL,iBAAiB,IAAA,CAAK,eAAA;AAAA,MACtB,WAAA,EAAa,KAAK,WAAA,EAAY;AAAA,MAC9B,YAAY,IAAA,CAAK,KAAA;AAAA,MACjB,SAAA,EAAW,IAAA,CAAK,OAAA,GAAU,MAAA,GAAS;AAAA,KACrC;AAAA,EACF;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,IAAI;AAAE,MAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAAe;AAAA,EACjD;AACF,CAAA;;;ACzWA,IAAM,oCAAoB,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,EAAO,KAAK,CAAC,CAAA;AAIvD,IAAM,eAAA,uBAAsB,GAAA,CAAgB,CAAC,OAAO,KAAA,EAAO,MAAA,EAAQ,QAAA,EAAU,MAAM,CAAC,CAAA;AACpF,IAAM,eAAA,uBAAsB,GAAA,CAAgB,CAAC,QAAQ,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,KAAK,CAAC,CAAA;AAE1E,SAAS,iBAAiB,GAAA,EAAiC;AAChE,EAAA,IAAI,iBAAA,CAAkB,GAAA,CAAI,GAAA,CAAI,SAAS,GAAG,OAAO,UAAA;AACjD,EAAA,KAAA,MAAW,CAAA,IAAK,IAAI,WAAA,EAAa;AAE/B,IAAA,IAAI,CAAC,eAAA,CAAgB,GAAA,CAAI,CAAA,CAAE,KAAK,GAAG,OAAO,UAAA;AAAA,EAC5C;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,IAAI,WAAA,EAAa;AAC/B,IAAA,IAAI,CAAC,eAAA,CAAgB,GAAA,CAAI,CAAA,CAAE,KAAK,GAAG,OAAO,UAAA;AAAA,EAC5C;AACA,EAAA,OAAO,WAAA;AACT;;;ACqLO,SAAS,uBAAA,CACd,GAAA,EACA,MAAA,EACA,gBAAA,EACM;AACN,EAAA,MAAM,EAAA,GAAK,IAAI,GAAA,IAAO,CAAA;AACtB,EAAA,MAAM,EAAA,GAAK,IAAI,KAAA,IAAS,CAAA;AACxB,EAAA,MAAM,SAAA,GAAa,OAAO,WAAA,IAAe,EAAA,KAAO,KAAM,CAAC,MAAA,CAAO,SAAS,EAAE,CAAA;AACzE,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,MAAMC,MAAK,MAAA,EAAO;AAClB,IAAA,GAAA,CAAI,GAAA,GAAMA,GAAAA;AACV,IAAA,GAAA,CAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,GAAA,CAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,GAAA,CAAI,aAAA,GAAgB,GAAA;AACpB,IAAA;AAAA,EACF;AACA,EAAA,MAAM,EAAA,GAAK,gBAAA,IAAoB,CAAC,CAAA,EAAG,GAAS,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,KAAK,UAAA,GAAc,EAAA;AACjC,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAO,KAAA,GAAQ,GAAA,GAAY,GAAG,CAAC,CAAA,GAAK,EAAA,CAAG,CAAC,CAAC,CAAA;AACzD,EAAA,IAAI,MAAA,CAAO,SAAS,EAAE,CAAA,IAAK,KAAK,GAAA,CAAI,EAAE,CAAA,IAAK,MAAA,CAAO,gBAAA,EAAkB;AAClE,IAAA,GAAA,CAAI,GAAA,GAAM,EAAA;AACV,IAAA,GAAA,CAAI,KAAA,GAAQ,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,CAAA;AAC1B,IAAA,GAAA,CAAI,aAAA,GAAgB,CAAA;AACpB,IAAA,GAAA,CAAI,aAAA,GAAgB,GAAA;AACpB,IAAA;AAAA,EACF;AACA,EAAA,MAAM,WAAW,MAAA,EAAO;AACxB,EAAA,GAAA,CAAI,GAAA,GAAM,QAAA;AACV,EAAA,GAAA,CAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,GAAA,CAAI,aAAA,GAAgB,CAAA;AACpB,EAAA,GAAA,CAAI,aAAA,GAAgB,GAAA;AACtB;AAaO,SAAS,YAAA,CACd,KACA,QAAA,EACe;AACf,EAAA,MAAM,EAAA,GAAK,IAAI,GAAA,IAAO,CAAA;AACtB,EAAA,MAAM,EAAA,GAAK,IAAI,KAAA,IAAS,CAAA;AACxB,EAAA,MAAM,SAAA,GAAa,OAAO,WAAA,IAAe,EAAA,KAAO,KAAM,CAAC,MAAA,CAAO,SAAS,EAAE,CAAA;AACzE,EAAA,IAAI,WAAW,OAAO,IAAA;AACtB,EAAA,MAAM,EAAA,GAAK,QAAA,IAAY,CAAC,CAAA,EAAG,GAAS,CAAA;AACpC,EAAA,IAAI,CAAC,GAAG,CAAC,CAAA,IAAK,CAAC,EAAA,CAAG,CAAC,GAAG,OAAO,IAAA;AAC7B,EAAA,MAAM,KAAA,GAAQ,KAAK,UAAA,GAAc,EAAA;AACjC,EAAA,MAAM,MAAO,KAAA,GAAQ,EAAA,CAAG,CAAC,CAAA,GAAK,GAAG,CAAC,CAAA;AAClC,EAAA,OAAO,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,GAAI,GAAA,GAAM,IAAA;AACtC;AAYA,IAAM,gBAAA,GAAmB,CAAA;AACzB,IAAM,iBAAA,GAAoB,CAAA;AAC1B,IAAM,iBAAA,GAAoB,CAAA;AAC1B,IAAM,iBAAA,GAAoB,CAAA;AAC1B,IAAM,iBAAA,GAAoB,CAAA;AAC1B,IAAM,kBAAA,GAAqB,CAAA;AAC3B,IAAM,kBAAA,GAAqB,CAAA;AAC3B,IAAM,kBAAA,GAAqB,CAAA;AAQpB,SAAS,+BAA+B,KAAA,EAA8C;AAC3F,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,QAAA,IAAY,KAAA,CAAM,qBAAA,IAAyB,CAAA;AAClE,EAAA,MAAM,UAAA,GAAa,MAAM,WAAA,IAAe,KAAA;AACxC,EAAA,MAAM,SAAA,GAAY,MAAM,UAAA,IAAc,CAAA;AACtC,EAAA,IAAI,SAAA,KAAc,GAAG,OAAO,IAAA;AAE5B,EAAA,MAAM,GAAA,GAAM,IAAI,YAAA,CAAa,SAAA,GAAY,QAAQ,CAAA;AAEjD,EAAA,QAAQ,MAAM,MAAA;AAAQ,IACpB,KAAK,kBAAA,EAAoB;AACvB,MAAA,MAAM,MAAA,GAAS,YAAA,CAAa,KAAA,CAAM,IAAA,EAAM,QAAQ,CAAA;AAChD,MAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,QAAA,EAAU,EAAA,EAAA,EAAM;AACpC,QAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,MAAA,CAAO,EAAE,CAAC,CAAA;AAClC,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK,GAAA,CAAI,CAAA,GAAI,QAAA,GAAW,EAAE,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA;AAAA,MACtE;AACA,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA,KAAK,iBAAA,EAAmB;AACtB,MAAA,MAAM,IAAA,GAAO,SAAA,CAAU,KAAA,CAAM,IAAI,CAAA;AACjC,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,GAAY,QAAA,EAAU,KAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA;AAC9D,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA,KAAK,kBAAA,EAAoB;AACvB,MAAA,MAAM,MAAA,GAAS,YAAA,CAAa,KAAA,CAAM,IAAA,EAAM,QAAQ,CAAA;AAChD,MAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,QAAA,EAAU,EAAA,EAAA,EAAM;AACpC,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAC,CAAA;AAChC,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK,GAAA,CAAI,CAAA,GAAI,QAAA,GAAW,EAAE,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA,GAAI,KAAA;AAAA,MAC1E;AACA,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA,KAAK,iBAAA,EAAmB;AACtB,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAC/B,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,GAAY,QAAA,EAAU,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAI,KAAA;AAClE,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA,KAAK,kBAAA,EAAoB;AACvB,MAAA,MAAM,MAAA,GAAS,YAAA,CAAa,KAAA,CAAM,IAAA,EAAM,QAAQ,CAAA;AAChD,MAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,QAAA,EAAU,EAAA,EAAA,EAAM;AACpC,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAC,CAAA;AAChC,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK,GAAA,CAAI,CAAA,GAAI,QAAA,GAAW,EAAE,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA,GAAI,UAAA;AAAA,MAC1E;AACA,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA,KAAK,iBAAA,EAAmB;AACtB,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAC/B,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,GAAY,QAAA,EAAU,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAI,UAAA;AAClE,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA,KAAK,iBAAA,EAAmB;AACtB,MAAA,MAAM,MAAA,GAAS,YAAA,CAAa,KAAA,CAAM,IAAA,EAAM,QAAQ,CAAA;AAChD,MAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,QAAA,EAAU,EAAA,EAAA,EAAM;AACpC,QAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,EAAE,CAAC,CAAA;AAChC,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,EAAW,CAAA,EAAA,EAAK,GAAA,CAAI,CAAA,GAAI,QAAA,GAAW,EAAE,CAAA,GAAA,CAAK,KAAA,CAAM,CAAC,IAAI,GAAA,IAAO,GAAA;AAAA,MAClF;AACA,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA,KAAK,gBAAA,EAAkB;AACrB,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAC/B,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,SAAA,GAAY,QAAA,EAAU,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,GAAA,IAAO,GAAA;AAC1E,MAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAW;AAAA,IAC3C;AAAA,IACA;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAEA,SAAS,YAAA,CAAa,MAAe,QAAA,EAA6B;AAChE,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,EAAG,OAAO,IAAA;AAChC,EAAA,MAAM,GAAA,GAAM,IAAA;AACZ,EAAA,MAAM,MAAM,GAAA,CAAI,MAAA;AAChB,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,QAAQ,CAAA;AAC5C,EAAA,MAAM,SAAoB,EAAC;AAC3B,EAAA,KAAA,IAAS,EAAA,GAAK,CAAA,EAAG,EAAA,GAAK,QAAA,EAAU,EAAA,EAAA,EAAM;AACpC,IAAA,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,QAAA,GAAW,GAAA,CAAI,QAAA,CAAS,EAAA,GAAK,UAAA,EAAA,CAAa,EAAA,GAAK,CAAA,IAAK,UAAU,CAAA,GAAI,GAAG,CAAA;AAAA,EACvF;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,UAAU,CAAA,EAA0B;AAC3C,EAAA,IAAI,CAAA,YAAa,cAAc,OAAO,CAAA;AACtC,EAAA,MAAM,EAAA,GAAK,CAAA;AACX,EAAA,OAAO,IAAI,aAAa,EAAA,CAAG,MAAA,EAAQ,GAAG,UAAA,EAAY,EAAA,CAAG,aAAa,CAAC,CAAA;AACrE;AACA,SAAS,QAAQ,CAAA,EAAwB;AACvC,EAAA,IAAI,CAAA,YAAa,YAAY,OAAO,CAAA;AACpC,EAAA,MAAM,EAAA,GAAK,CAAA;AACX,EAAA,OAAO,IAAI,WAAW,EAAA,CAAG,MAAA,EAAQ,GAAG,UAAA,EAAY,EAAA,CAAG,aAAa,CAAC,CAAA;AACnE;AACA,SAAS,QAAQ,CAAA,EAAwB;AACvC,EAAA,IAAI,CAAA,YAAa,YAAY,OAAO,CAAA;AACpC,EAAA,MAAM,EAAA,GAAK,CAAA;AACX,EAAA,OAAO,IAAI,WAAW,EAAA,CAAG,MAAA,EAAQ,GAAG,UAAA,EAAY,EAAA,CAAG,aAAa,CAAC,CAAA;AACnE;AACA,SAAS,QAAQ,CAAA,EAAwB;AACvC,EAAA,IAAI,CAAA,YAAa,YAAY,OAAO,CAAA;AACpC,EAAA,MAAM,EAAA,GAAK,CAAA;AACX,EAAA,OAAO,IAAI,UAAA,CAAW,EAAA,CAAG,QAAQ,EAAA,CAAG,UAAA,EAAY,GAAG,UAAU,CAAA;AAC/D;AAOO,SAAS,sBAAA,CACd,KAAA,EACA,MAAA,EACA,gBAAA,EACM;AACN,EAAA,MAAM,EAAA,GAAK,MAAM,GAAA,IAAO,CAAA;AACxB,EAAA,MAAM,EAAA,GAAK,MAAM,KAAA,IAAS,CAAA;AAC1B,EAAA,MAAM,SAAA,GAAa,OAAO,WAAA,IAAe,EAAA,KAAO,KAAM,CAAC,MAAA,CAAO,SAAS,EAAE,CAAA;AACzE,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,MAAMA,MAAK,MAAA,EAAO;AAClB,IAAA,KAAA,CAAM,GAAA,GAAMA,GAAAA;AACZ,IAAA,KAAA,CAAM,KAAA,GAAQ,CAAA;AACd,IAAA;AAAA,EACF;AACA,EAAA,MAAM,EAAA,GAAK,gBAAA,IAAoB,CAAC,CAAA,EAAG,GAAS,CAAA;AAC5C,EAAA,MAAM,KAAA,GAAQ,KAAK,UAAA,GAAc,EAAA;AACjC,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAO,KAAA,GAAQ,GAAA,GAAY,GAAG,CAAC,CAAA,GAAK,EAAA,CAAG,CAAC,CAAC,CAAA;AACzD,EAAA,IAAI,MAAA,CAAO,SAAS,EAAE,CAAA,IAAK,KAAK,GAAA,CAAI,EAAE,CAAA,IAAK,MAAA,CAAO,gBAAA,EAAkB;AAClE,IAAA,KAAA,CAAM,GAAA,GAAM,EAAA;AACZ,IAAA,KAAA,CAAM,KAAA,GAAQ,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,CAAA;AAC5B,IAAA;AAAA,EACF;AACA,EAAA,MAAM,WAAW,MAAA,EAAO;AACxB,EAAA,KAAA,CAAM,GAAA,GAAM,QAAA;AACZ,EAAA,KAAA,CAAM,KAAA,GAAQ,CAAA;AAChB;;;ACnXA,eAAsB,mBAAmB,IAAA,EAAgE;AACvG,EAAA,MAAM,OAAA,GAAwB,gBAAA,CAAiB,IAAA,CAAK,OAAO,CAAA;AAC3D,EAAA,MAAM,KAAA,GAAS,MAAM,SAAA,CAAU,OAAO,CAAA;AACtC,EAAA,MAAM,MAAA,GAAS,MAAM,UAAA,EAAW;AAKhC,EAAA,MAAM,EAAE,iBAAA,EAAkB,GAAI,MAAM,OAAO,iCAAiC,CAAA;AAC5E,EAAA,MAAM,WAAA,GAAc,MAAM,iBAAA,CAAkB,KAAA,EAA6D,KAAK,QAAA,EAAU,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAA;AAEnJ,EAAA,MAAM,OAAA,GAAU,MAAM,KAAA,CAAM,eAAA,EAAgB;AAC5C,EAAA,MAAM,CAAC,SAAS,OAAO,CAAA,GAAI,MAAM,KAAA,CAAM,oBAAA,CAAqB,KAAK,QAAQ,CAAA;AACzE,EAAA,MAAM,WAAA,GAAc,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,UAAA,KAAe,KAAA,CAAM,kBAAkB,CAAA,IAAK,IAAA;AAGtF,EAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAY,CAAC,CAAA,EAAG,EAAA;AACvD,EAAA,IAAI,WAAA,GAAA,CACD,iBAAA,IAAqB,IAAA,GAClB,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,UAAA,KAAe,KAAA,CAAM,kBAAA,IAAsB,CAAA,CAAE,UAAU,iBAAiB,CAAA,GAC9F,MAAA,KACJ,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,UAAA,KAAe,KAAA,CAAM,kBAAkB,CAAA,IAAK,IAAA;AAEpE,EAAA,IAAI,CAAC,WAAA,IAAe,CAAC,WAAA,EAAa;AAChC,IAAA,MAAM,IAAI,MAAM,+CAA+C,CAAA;AAAA,EACjE;AAGA,EAAA,IAAI,YAAA,GAAkD,IAAA;AACtD,EAAA,IAAI,UAAA,GAAa,KAAA;AAEjB,EAAA,SAAS,UAAU,MAAA,EAAsB;AACvC,IAAA,IAAI,UAAA,EAAY;AAChB,IAAA,UAAA,GAAa,IAAA;AACb,IAAA,YAAA,GAAe,MAAM,CAAA;AAAA,EACvB;AAGA,EAAA,IAAI,YAAA,GAAoC,IAAA;AACxC,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,mBAAA,CAAoB,OAAO,WAAW,CAAA;AAClE,MAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,MAAM,6BAA6B,CAAA;AAE1D,MAAA,MAAM,SAAA,GAAY,MAAM,YAAA,CAAa,iBAAA,CAAkB,MAAM,CAAA;AAC7D,MAAA,IAAI,CAAC,SAAA,CAAU,SAAA,EAAW,MAAM,IAAI,KAAA,CAAM,CAAA,sCAAA,EAAyC,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA,CAAE,CAAA;AAE3G,MAAA,YAAA,GAAe,IAAI,YAAA,CAAa;AAAA,QAC9B,MAAA,EAAQ,CAAC,KAAA,KAAsB;AAC7B,UAAA,IAAA,CAAK,QAAA,CAAS,QAAQ,KAAK,CAAA;AAC3B,UAAA,kBAAA,EAAA;AAAA,QACF,CAAA;AAAA,QACA,KAAA,EAAO,CAAC,GAAA,KAAsB;AAC5B,UAAA,OAAA,CAAQ,KAAA,CAAM,4CAA4C,GAAG,CAAA;AAC7D,UAAA,SAAA,CAAU,CAAA,8BAAA,EAAiC,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,QAC1D;AAAA,OACD,CAAA;AACD,MAAA,YAAA,CAAa,UAAU,MAAM,CAAA;AAE7B,MAAA,IAAI,WAAA,CAAY,aAAA,IAAiB,WAAA,CAAY,aAAA,EAAe;AAC1D,QAAA,aAAA,GAAgB,CAAC,WAAA,CAAY,aAAA,EAAe,WAAA,CAAY,aAAa,CAAA;AAAA,MACvE;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,6DAA6D,GAAG,CAAA;AAC9E,MAAA,SAAA,CAAU,CAAA,oCAAA,EAAwC,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAEzE,MAAA,MAAM,WAAA,CAAY,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AACzC,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AAGA,EAAA,IAAI,QAAA,GAA+B,IAAA;AACnC,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,IAAI;AACF,MAAA,MAAM,GAAG,CAAA,EAAG,GAAA,EAAK,KAAK,IAAI,MAAM,KAAA,CAAM,eAAA,CAAgB,WAAA,CAAY,QAAA,EAAU;AAAA,QAC1E,UAAU,WAAA,CAAY;AAAA,OACvB,CAAA;AACD,MAAA,QAAA,GAAW,EAAE,CAAA,EAAG,GAAA,EAAK,KAAA,EAAM;AAC3B,MAAA,IAAI,WAAA,CAAY,aAAA,IAAiB,WAAA,CAAY,aAAA,EAAe;AAC1D,QAAA,aAAA,GAAgB,CAAC,WAAA,CAAY,aAAA,EAAe,WAAA,CAAY,aAAa,CAAA;AAAA,MACvE;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,0GAAA;AAAA,QACC,GAAA,CAAc;AAAA,OACjB;AAAA,IACF;AAAA,EACF;AAIA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,IAAA,CAAK,MAAM,UAAA,EAAW;AAAA,EACxB;AAEA,EAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,QAAA,EAAU;AAC9B,IAAA,MAAM,WAAA,CAAY,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AACzC,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,EACrE;AAGA,EAAA,IAAI,MAAA,GAAwB,IAAA;AAC5B,EAAA,IAAI,MAAA,GAAwB,IAAA;AAC5B,EAAA,IAAI,eAAe,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAC,CAAA,EAAG,UAAU,OAAA,EAAS;AACjE,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,MAAM,KAAA,CAAM,wBAAA,CAAyB,sBAAsB,CAAA;AACpE,MAAA,IAAI,MAAA,IAAU,IAAA,IAAQ,MAAA,IAAU,CAAA,EAAG;AACjC,QAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,mBAAA,CAAoB,MAAM,CAAA;AACpD,QAAA,MAAM,KAAA,CAAM,uBAAA,CAAwB,KAAA,EAAO,WAAA,CAAY,QAAQ,CAAA;AAC/D,QAAA,MAAM,KAAA,CAAM,YAAY,MAAM,CAAA;AAC9B,QAAA,MAAA,GAAS,MAAM,MAAM,eAAA,EAAgB;AACrC,QAAA,GAAA,CAAI,IAAA,CAAK,OAAO,0CAA0C,CAAA;AAAA,MAC5D,CAAA,MAAO;AAEL,QAAA,OAAA,CAAQ,KAAK,qEAAqE,CAAA;AAClF,QAAA,MAAA,GAAS,IAAA;AAAA,MACX;AAAA,IACF,SAAS,GAAA,EAAK;AAEZ,MAAA,OAAA,CAAQ,IAAA,CAAK,wCAAA,EAA2C,GAAA,CAAc,OAAO,CAAA;AAC7E,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,MAAA,GAAS,IAAA;AAAA,IACX;AAAA,EACF;AAEA,EAAA,eAAe,SAAS,OAAA,EAAgD;AACtE,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,MAAA,EAAQ,OAAO,OAAA;AAC/B,IAAA,MAAM,MAAqB,EAAC;AAC5B,IAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,MAAA,MAAM,KAAA,CAAM,gBAAA,CAAiB,MAAA,EAAQ,GAAG,CAAA;AACxC,MAAA,MAAM,OAAA,GAAU,MAAM,KAAA,CAAM,kBAAA,CAAmB,QAAQ,MAAM,CAAA;AAC7D,MAAA,IAAI,UAAU,CAAA,EAAG;AAAE,QAAA,GAAA,CAAI,KAAK,GAAG,CAAA;AAAG,QAAA;AAAA,MAAU;AAC5C,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,OAAA,GAAU,MAAM,KAAA,CAAM,qBAAA,CAAsB,QAAQ,MAAM,CAAA;AAChE,QAAA,IAAI,UAAU,CAAA,EAAG;AACjB,QAAA,GAAA,CAAI,IAAA,CAAK,MAAM,KAAA,CAAM,iBAAA,CAAkB,MAAM,CAAC,CAAA;AAAA,MAChD;AAAA,IACF;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAEA,EAAA,eAAe,QAAA,GAA0B;AACvC,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,MAAA,EAAQ;AACxB,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,CAAM,kBAAA,CAAmB,MAAA,EAAQ,CAAC,CAAA;AACxC,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,qBAAA,CAAsB,QAAQ,MAAM,CAAA;AAC5D,QAAA,IAAI,MAAM,CAAA,EAAG;AAAA,MACf;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAAe;AAAA,EACzB;AAGA,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,WAAA,GAAoC,IAAA;AAExC,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,kBAAA,GAAqB,CAAA;AACzB,EAAA,IAAI,kBAAA,GAAqB,CAAA;AACzB,EAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,EAAA,IAAI,gBAAA,GAAmB,CAAA;AAEvB,EAAA,IAAI,gBAAA,GAAmB,CAAA;AACvB,EAAA,IAAI,gBAAA,GAAmB,CAAA;AAEvB,EAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,WAAA,EAAa,KAAK,CAAA;AACvF,EAAA,MAAM,WAAW,cAAA,EAAgB,GAAA,IAAO,eAAe,GAAA,GAAM,CAAA,GAAI,eAAe,GAAA,GAAM,EAAA;AACtF,EAAA,MAAM,gBAAA,GAAmB,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,GAAA,GAAY,QAAQ,CAAC,CAAA;AAIrE,EAAA,eAAe,SAAS,OAAA,EAAgC;AACtD,IAAA,OAAO,CAAC,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AAC1C,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AACF,QAAA,CAAC,SAAS,OAAO,CAAA,GAAI,MAAM,KAAA,CAAM,mBAAA,CAAoB,SAAS,OAAA,EAAS;AAAA,UACrE,OAAO,EAAA,GAAK;AAAA,SACb,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,iDAAiD,GAAG,CAAA;AAClE,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AAExC,MAAA,MAAM,YAAA,GAAe,WAAA,GAAc,OAAA,CAAQ,WAAA,CAAY,KAAK,CAAA,GAAI,MAAA;AAChE,MAAA,MAAM,YAAA,GAAe,WAAA,GAAc,OAAA,CAAQ,WAAA,CAAY,KAAK,CAAA,GAAI,MAAA;AAOhE,MAAA,IAAI,gBAAgB,aAAA,EAAe;AACjC,QAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC9B,UAAA,MAAM,GAAA,GAAM,YAAA,CAAa,GAAA,EAAK,aAAa,CAAA;AAC3C,UAAA,IAAI,GAAA,IAAO,IAAA,IAAQ,GAAA,GAAM,gBAAA,EAAkB,gBAAA,GAAmB,GAAA;AAAA,QAChE;AAAA,MACF;AACA,MAAA,IAAI,gBAAgB,aAAA,EAAe;AACjC,QAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC9B,UAAA,MAAM,GAAA,GAAM,YAAA,CAAa,GAAA,EAAK,aAAa,CAAA;AAC3C,UAAA,IAAI,GAAA,IAAO,IAAA,IAAQ,GAAA,GAAM,gBAAA,EAAkB,gBAAA,GAAmB,GAAA;AAAA,QAChE;AAAA,MACF;AAQA,MAAA,IAAI,QAAA,IAAY,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AACvD,QAAA,MAAM,gBAAA,CAAiB,cAAc,OAAO,CAAA;AAAA,MAC9C;AACA,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AAKxC,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,CAAC,CAAC,CAAA;AACzC,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AAGxC,MAAA,IAAI,YAAA,IAAgB,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AAC3D,QAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,YAAY,CAAA;AAC7C,QAAA,KAAA,MAAW,OAAO,SAAA,EAAW;AAC3B,UAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AACxC,UAAA,uBAAA,CAAwB,KAAK,MAAM;AACjC,YAAA,MAAM,EAAA,GAAK,gBAAA;AACX,YAAA,gBAAA,IAAoB,gBAAA;AACpB,YAAA,OAAO,EAAA;AAAA,UACT,GAAG,aAAa,CAAA;AAChB,UAAA,IAAI;AACF,YAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,yBAAA,CAA0B,GAAA,EAAK,WAAW,CAAA;AAC/D,YAAA,YAAA,CAAa,OAAO,KAAK,CAAA;AACzB,YAAA,cAAA,EAAA;AAAA,UACF,SAAS,GAAA,EAAK;AACZ,YAAA,IAAI,mBAAmB,CAAA,EAAG;AACxB,cAAA,OAAA,CAAQ,IAAA,CAAK,wDAAwD,GAAG,CAAA;AACxE,cAAA,SAAA,CAAU,CAAA,iCAAA,EAAqC,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AACtE,cAAA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,MAAA,WAAA,IAAA,CAAgB,YAAA,EAAc,MAAA,IAAU,CAAA,KAAM,YAAA,EAAc,MAAA,IAAU,CAAA,CAAA;AAGtE,MAAA,OACE,CAAC,SAAA,IACD,OAAA,KAAY,cACV,YAAA,IAAgB,YAAA,CAAa,kBAAkB,EAAA,IAC/C,IAAA,CAAK,MAAM,WAAA,EAAY,GAAI,KAC3B,IAAA,CAAK,QAAA,CAAS,YAAW,IAAK,IAAA,CAAK,SAAS,cAAA,CAAA,EAC9C;AACA,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,MAC5C;AAEA,MAAA,IAAI,OAAA,KAAY,MAAM,WAAA,EAAa;AAEjC,QAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,KAAA,KAAU,YAAA,EAAc;AACvD,UAAA,IAAI;AAAE,YAAA,MAAM,aAAa,KAAA,EAAM;AAAA,UAAG,CAAA,CAAA,MAAQ;AAAA,UAAe;AAAA,QAC3D;AAEA,QAAA,IAAI,UAAU,MAAM,gBAAA,CAAiB,EAAC,EAAG,SAAS,IAAI,CAAA;AACtD,QAAA;AAAA,MACF;AACA,MAAA,IAAI,WAAW,OAAA,KAAY,CAAA,IAAK,OAAA,KAAY,CAAC,MAAM,MAAA,EAAQ;AACzD,QAAA,OAAA,CAAQ,IAAA,CAAK,kDAAkD,OAAO,CAAA;AACtE,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,eAAe,gBAAA,CAAiB,IAAA,EAAqB,OAAA,EAAiB,KAAA,GAAQ,KAAA,EAAO;AACnF,IAAA,IAAI,CAAC,QAAA,IAAY,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AAKrD,IAAA,MAAM,eAAA,GAAkB,CAAA;AACxB,IAAA,IAAI,YAA0B,EAAC;AAE/B,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,eAAA,EAAiB;AACrD,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AACxC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAI,eAAe,CAAA;AAC/C,MAAA,MAAM,MAAA,GAAS,CAAA,GAAI,eAAA,IAAmB,IAAA,CAAK,MAAA;AAC3C,MAAA,IAAI;AACF,QAAA,MAAMC,OAAAA,GAAS,MAAM,KAAA,CAAM,eAAA;AAAA,UACzB,QAAA,CAAS,CAAA;AAAA,UACT,QAAA,CAAS,GAAA;AAAA,UACT,QAAA,CAAS,KAAA;AAAA,UACT,KAAA;AAAA,UACA,MAAA,IAAU,KAAA,GAAQ,EAAE,GAAA,EAAK,IAAA,EAAM,cAAc,IAAA,EAAK,GAAI,EAAE,YAAA,EAAc,IAAA;AAAK,SAC7E;AACA,QAAA,SAAA,GAAY,SAAA,CAAU,OAAOA,OAAM,CAAA;AAAA,MACrC,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,GAAG,CAAA;AAC3D,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,UAAA,CAAW,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,IACxD;AAGA,IAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,IAAK,KAAA,EAAO;AAC9B,MAAA,IAAI;AACF,QAAA,SAAA,GAAY,MAAM,KAAA,CAAM,eAAA;AAAA,UACtB,QAAA,CAAS,CAAA;AAAA,UAAG,QAAA,CAAS,GAAA;AAAA,UAAK,QAAA,CAAS,KAAA;AAAA,UAAO,EAAC;AAAA,UAC3C,EAAE,GAAA,EAAK,IAAA,EAAM,YAAA,EAAc,IAAA;AAAK,SAClC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,yCAAyC,GAAG,CAAA;AAC1D,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AACxC,IAAA,MAAM,MAAA,GAAS,SAAA;AAEf,IAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AACxC,MAAA,sBAAA;AAAA,QACE,CAAA;AAAA,QACA,MAAM;AACJ,UAAA,MAAM,EAAA,GAAK,gBAAA;AACX,UAAA,MAAMC,QAAAA,GAAU,EAAE,UAAA,IAAc,IAAA;AAChC,UAAA,MAAM,UAAA,GAAa,EAAE,WAAA,IAAe,KAAA;AACpC,UAAA,gBAAA,IAAoB,IAAA,CAAK,KAAA,CAAOA,QAAAA,GAAU,GAAA,GAAa,UAAU,CAAA;AACjE,UAAA,OAAO,EAAA;AAAA,QACT,CAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,MAAM,OAAA,GAAU,+BAA+B,CAAC,CAAA;AAChD,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,IAAA,CAAK,MAAM,QAAA,CAAS,OAAA,CAAQ,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAQ,UAAU,CAAA;AACtE,QAAA,kBAAA,EAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,SAAA,GAAY,CAAA;AACZ,EAAA,WAAA,GAAc,QAAA,CAAS,SAAS,CAAA,CAAE,KAAA;AAAA,IAAM,CAAC,GAAA,KACvC,OAAA,CAAQ,KAAA,CAAM,kCAAkC,GAAG;AAAA,GACrD;AAEA,EAAA,OAAO;AAAA,IACL,aAAa,OAAA,EAAyC;AACpD,MAAA,YAAA,GAAe,OAAA;AAEf,MAAA,IAAI,UAAA,UAAoB,kEAAkE,CAAA;AAAA,IAC5F,CAAA;AAAA,IAEA,MAAM,OAAA,GAAU;AACd,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,SAAA,EAAA;AACA,MAAA,IAAI;AAAE,QAAA,MAAM,WAAA;AAAA,MAAa,CAAA,CAAA,MAAQ;AAAA,MAAe;AAChD,MAAA,IAAI;AAAE,QAAA,IAAI,MAAA,EAAQ,MAAM,KAAA,CAAM,WAAA,CAAY,MAAM,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC1E,MAAA,IAAI;AAAE,QAAA,IAAI,MAAA,EAAQ,MAAM,KAAA,CAAM,cAAA,GAAiB,MAAM,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC/E,MAAA,IAAI;AAAE,QAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,KAAA,KAAU,QAAA,eAAuB,KAAA,EAAM;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACxG,MAAA,IAAI;AAAE,QAAA,IAAI,QAAA,QAAgB,KAAA,CAAM,eAAA,GAAkB,SAAS,CAAA,EAAG,QAAA,CAAS,GAAA,EAAK,QAAA,CAAS,KAAK,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACpH,MAAA,IAAI;AAAE,QAAA,MAAM,KAAA,CAAM,iBAAiB,OAAO,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACpE,MAAA,IAAI;AAAE,QAAA,MAAM,KAAA,CAAM,wBAAwB,OAAO,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC3E,MAAA,IAAI;AAAE,QAAA,MAAM,YAAY,MAAA,EAAO;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IAC3D,CAAA;AAAA,IAEA,MAAM,aAAA,CAAc,OAAA,EAAS,OAAA,EAAS;AACpC,MAAA,IAAI,WAAA,IAAe,WAAA,CAAY,KAAA,KAAU,OAAA,EAAS;AAClD,MAAA,MAAM,YAAY,OAAA,CAAQ,IAAA;AAAA,QACxB,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,KAAA,CAAM,kBAAA,IAAsB,EAAE,KAAA,KAAU;AAAA,OAClE;AACA,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,OAAA,CAAQ,IAAA,CAAK,6DAAwD,OAAO,CAAA;AAC5E,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,WAAW,EAAE,SAAA;AACnB,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,IAAI;AAAE,UAAA,MAAM,WAAA;AAAA,QAAa,CAAA,CAAA,MAAQ;AAAA,QAAe;AAAA,MAClD;AACA,MAAA,IAAI,SAAA,EAAW;AAGf,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,IAAI;AAAE,UAAA,MAAM,MAAM,eAAA,GAAkB,QAAA,CAAS,GAAG,QAAA,CAAS,GAAA,EAAK,SAAS,KAAK,CAAA;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAe;AACtG,QAAA,QAAA,GAAW,IAAA;AAAA,MACb;AACA,MAAA,IAAI;AACF,QAAA,MAAM,GAAG,CAAA,EAAG,GAAA,EAAK,KAAK,IAAI,MAAM,KAAA,CAAM,eAAA,CAAgB,SAAA,CAAU,QAAA,EAAU;AAAA,UACxE,UAAU,SAAA,CAAU;AAAA,SACrB,CAAA;AACD,QAAA,QAAA,GAAW,EAAE,CAAA,EAAG,GAAA,EAAK,KAAA,EAAM;AAC3B,QAAA,aAAA,GAAgB,SAAA,CAAU,iBAAiB,SAAA,CAAU,aAAA,GACjD,CAAC,SAAA,CAAU,aAAA,EAAe,SAAA,CAAU,aAAa,CAAA,GACjD,KAAA,CAAA;AAAA,MACN,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,4EAAA;AAAA,UACC,GAAA,CAAc;AAAA,SACjB;AACA,QAAA,QAAA,GAAW,IAAA;AACX,QAAA,IAAA,CAAK,MAAM,UAAA,EAAW;AAAA,MACxB;AAEA,MAAA,WAAA,GAAc,SAAA;AAGd,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAC3C,QAAA,MAAM,CAAC,IAAA,EAAM,IAAI,CAAA,GAAI,KAAA,CAAM,WACvB,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,GACnB,CAAC,IAAA,GAAO,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,GAAO,UAAW,CAAC,CAAA;AAC7C,QAAA,MAAM,KAAA,CAAM,aAAA;AAAA,UACV,OAAA;AAAA,UACA,CAAA,CAAA;AAAA,UACA,IAAA;AAAA,UACA,IAAA;AAAA,UACA,MAAM,oBAAA,IAAwB;AAAA,SAChC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,iDAAiD,GAAG,CAAA;AAAA,MACnE;AAGA,MAAA,IAAI;AACF,QAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,KAAA,KAAU,YAAA,EAAc;AACvD,UAAA,MAAM,aAAa,KAAA,EAAM;AAAA,QAC3B;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAAe;AACvB,MAAA,MAAM,QAAA,EAAS;AAEf,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AACjD,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAEjD,MAAA,WAAA,GAAc,QAAA,CAAS,QAAQ,CAAA,CAAE,KAAA;AAAA,QAAM,CAAC,GAAA,KACtC,OAAA,CAAQ,KAAA,CAAM,uDAAuD,GAAG;AAAA,OAC1E;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,KAAK,OAAA,EAAS;AAClB,MAAA,MAAM,WAAW,EAAE,SAAA;AACnB,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,IAAI;AAAE,UAAA,MAAM,WAAA;AAAA,QAAa,CAAA,CAAA,MAAQ;AAAA,QAAe;AAAA,MAClD;AACA,MAAA,IAAI,SAAA,EAAW;AAEf,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAC3C,QAAA,MAAM,CAAC,IAAA,EAAM,IAAI,CAAA,GAAI,KAAA,CAAM,WACvB,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,GACnB,CAAC,IAAA,GAAO,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,GAAO,UAAW,CAAC,CAAA;AAC7C,QAAA,MAAM,KAAA,CAAM,aAAA;AAAA,UACV,OAAA;AAAA,UACA,CAAA,CAAA;AAAA,UACA,IAAA;AAAA,UACA,IAAA;AAAA,UACA,MAAM,oBAAA,IAAwB;AAAA,SAChC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,2CAA2C,GAAG,CAAA;AAAA,MAC7D;AAGA,MAAA,IAAI;AACF,QAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,KAAA,KAAU,YAAA,EAAc;AACvD,UAAA,MAAM,aAAa,KAAA,EAAM;AAAA,QAC3B;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAAe;AAGvB,MAAA,IAAI;AACF,QAAA,IAAI,QAAA,EAAU,MAAM,KAAA,CAAM,qBAAA,GAAwB,SAAS,CAAC,CAAA;AAAA,MAC9D,CAAA,CAAA,MAAQ;AAAA,MAAe;AACvB,MAAA,MAAM,QAAA,EAAS;AAEf,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AACjD,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAEjD,MAAA,WAAA,GAAc,QAAA,CAAS,QAAQ,CAAA,CAAE,KAAA;AAAA,QAAM,CAAC,GAAA,KACtC,OAAA,CAAQ,KAAA,CAAM,8CAA8C,GAAG;AAAA,OACjE;AAAA,IACF,CAAA;AAAA,IAEA,gBAAA,GAAmB;AACjB,MAAA,OAAO,gBAAA;AAAA,IACT,CAAA;AAAA,IAEA,KAAA,GAAQ;AACN,MAAA,OAAO;AAAA,QACL,WAAA,EAAa,kBAAA;AAAA,QACb,WAAA;AAAA,QACA,kBAAA;AAAA,QACA,cAAA;AAAA,QACA,kBAAA;AAAA,QACA,UAAA,EAAY,MAAA,GAAS,CAAC,sBAAsB,IAAI,EAAC;AAAA,QACjD,oBAAA,EAAsB,cAAc,eAAA,IAAmB,CAAA;AAAA;AAAA,QAEvD,UAAA,EAAY,WAAA,CAAY,SAAA,KAAc,YAAA,GAAe,YAAA,GAAe,QAAA;AAAA,QACpE,eAAA,EAAiB,YAAY,SAAA,KAAc,YAAA;AAAA,QAC3C,GAAG,IAAA,CAAK,QAAA,CAAS,KAAA,EAAM;AAAA,QACvB,GAAG,IAAA,CAAK,KAAA,CAAM,KAAA;AAAM,OACtB;AAAA,IACF;AAAA,GACF;AACF;AAcA,eAAe,UAAA,GAAoC;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAM,OAAO,4BAA6B,CAAA;AAC1D,IAAA,OAAO,OAAA,CAAQ,WAAA;AAAA,EACjB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,yCAAA,EAA6C,IAAc,OAAO,CAAA;AAAA,KACpE;AAAA,EACF;AACF;;;ACvkBO,SAAS,eAAe,MAAA,EAA6C;AAC1E,EAAA,MAAM,MAAA,GAAS,OAAO,KAAA,EAAM;AAC5B,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,IAAI,MAAA,GAAiB;AACnB,MAAA,OAAO,MAAA,CAAO,MAAA;AAAA,IAChB,CAAA;AAAA,IACA,MAAM,KAAA,EAAuB;AAC3B,MAAA,IAAI,KAAA,GAAQ,CAAA,IAAK,KAAA,IAAS,MAAA,CAAO,MAAA,EAAQ;AACvC,QAAA,MAAM,IAAI,YAAA;AAAA,UACR,CAAA,wBAAA,EAA2B,KAAK,CAAA,sBAAA,EAAyB,MAAA,CAAO,MAAM,CAAA,CAAA,CAAA;AAAA,UACtE;AAAA,SACF;AAAA,MACF;AACA,MAAA,OAAO,MAAA,CAAO,KAAK,CAAA,CAAE,CAAC,CAAA;AAAA,IACxB,CAAA;AAAA,IACA,IAAI,KAAA,EAAuB;AACzB,MAAA,IAAI,KAAA,GAAQ,CAAA,IAAK,KAAA,IAAS,MAAA,CAAO,MAAA,EAAQ;AACvC,QAAA,MAAM,IAAI,YAAA;AAAA,UACR,CAAA,sBAAA,EAAyB,KAAK,CAAA,sBAAA,EAAyB,MAAA,CAAO,MAAM,CAAA,CAAA,CAAA;AAAA,UACpE;AAAA,SACF;AAAA,MACF;AACA,MAAA,OAAO,MAAA,CAAO,KAAK,CAAA,CAAE,CAAC,CAAA;AAAA,IACxB;AAAA,GACF;AACA,EAAA,OAAO,IAAA;AACT;;;ACtBA,IAAM,0BAAA,GAA6B,GAAA;AACnC,IAAM,qBAAA,GAAwB,EAAA;AAE9B,eAAsB,mBAAA,CACpB,GAAA,EACA,MAAA,EACA,SAAA,EAC0B;AAG1B,EAAA,MAAM,EAAE,eAAA,EAAAC,gBAAAA,EAAgB,GAAI,MAAM,OAAO,sBAAsB,CAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,MAAMA,gBAAAA,CAAgB,GAAA,CAAI,MAAM,CAAA;AAE/C,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,WAAA,CAAY,CAAC,GAAG,GAAA,IAAO,EAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY;AAC9B,EAAA,MAAM,QAAA,GAAW,IAAI,aAAA,CAAc,MAAA,EAAQ,OAAO,GAAG,CAAA;AAErD,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAAM,kBAAA,CAAmB;AAAA,MACjC,MAAA;AAAA,MACA,QAAA,EAAU,IAAI,IAAA,IAAQ,WAAA;AAAA,MACtB,OAAA,EAAS,GAAA;AAAA,MACT,QAAA;AAAA,MACA,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,KAAA,CAAM,OAAA,EAAQ;AACd,IAAA,QAAA,CAAS,OAAA,EAAQ;AACjB,IAAA,MAAM,GAAA;AAAA,EACR;AAOA,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,aAAA,EAAe;AAAA,IAC3C,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,GAAA,EAAI;AAAA,IACrB,GAAA,EAAK,CAAC,CAAA,KAAc;AAAE,MAAA,KAAK,OAAO,CAAC,CAAA;AAAA,IAAG;AAAA,GACvC,CAAA;AACD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,QAAA,EAAU;AAAA,IACtC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,CAAC,KAAA,CAAM,SAAA;AAAU,GAC7B,CAAA;AACD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,QAAA,EAAU;AAAA,IACtC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,SAAA,EAAU;AAAA,IAC3B,GAAA,EAAK,CAAC,CAAA,KAAc;AAClB,MAAA,KAAA,CAAM,UAAU,CAAC,CAAA;AACjB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,cAAc,CAAC,CAAA;AAAA,IAChD;AAAA,GACD,CAAA;AACD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,OAAA,EAAS;AAAA,IACrC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,QAAA,EAAS;AAAA,IAC1B,GAAA,EAAK,CAAC,CAAA,KAAe;AACnB,MAAA,KAAA,CAAM,SAAS,CAAC,CAAA;AAChB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,cAAc,CAAC,CAAA;AAAA,IAChD;AAAA,GACD,CAAA;AACD,EAAA,IAAI,IAAI,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA,EAAG;AACjD,IAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAA,EAAY;AAAA,MACxC,YAAA,EAAc,IAAA;AAAA,MACd,GAAA,EAAK,MAAM,GAAA,CAAI,QAAA,IAAY;AAAA,KAC5B,CAAA;AAAA,EACH;AACA,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,cAAA,EAAgB;AAAA,IAC5C,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,eAAA,EAAgB;AAAA,IACjC,GAAA,EAAK,CAAC,CAAA,KAAc;AAClB,MAAA,KAAA,CAAM,gBAAgB,CAAC,CAAA;AACvB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,YAAY,CAAC,CAAA;AAAA,IAC9C;AAAA,GACD,CAAA;AAED,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,YAAA,EAAc;AAAA,IAC1C,YAAA,EAAc,IAAA;AAAA,IACd,KAAK,MAAc;AACjB,MAAA,IAAI,CAAC,QAAA,CAAS,SAAA,EAAU,EAAG,OAAO,CAAA;AAClC,MAAA,IAAI,CAAC,KAAA,CAAM,SAAA,EAAU,IAAK,KAAA,CAAM,WAAA,EAAY,IAAK,CAAA,IAAK,CAAC,KAAA,CAAM,SAAA,EAAU,EAAG,OAAO,CAAA;AACjF,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,GACD,CAAA;AACD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAA,EAAY;AAAA,IACxC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,cAAA,CAAe,GAAA,CAAI,YAAY,MAAA,CAAO,QAAA,CAAS,IAAI,QAAQ,CAAA,IAAK,IAAI,QAAA,GAAW,CAAA,GACtF,CAAC,CAAC,CAAA,EAAG,IAAI,QAAQ,CAAC,CAAA,GAClB,EAAE;AAAA,GACP,CAAA;AACD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAA,EAAY;AAAA,IACxC,YAAA,EAAc,IAAA;AAAA,IACd,KAAK,MAAM;AACT,MAAA,MAAM,GAAA,GAAM,QAAQ,gBAAA,EAAiB;AACrC,MAAA,OAAO,cAAA,CAAe,GAAA,GAAM,CAAA,GAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA,GAAI,EAAE,CAAA;AAAA,IACjD;AAAA,GACD,CAAA;AAED,EAAA,eAAe,aAAA,GAA+B;AAC5C,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,aAAa,KAAA,CAAM,SAAA,EAAU,IAAK,KAAA,CAAM,aAAY,IAAK,0BAAA;AAC/D,MAAA,IAAI,UAAA,IAAc,QAAA,CAAS,SAAA,EAAU,EAAG;AACtC,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,WAAA,CAAY,GAAA,EAAI,GAAI,KAAA,IAAS,MAAO,qBAAA,EAAuB;AAChE,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,IAC5C;AAAA,EACF;AAEA,EAAA,eAAe,OAAO,OAAA,EAAgC;AACpD,IAAA,MAAM,UAAA,GAAa,MAAM,SAAA,EAAU;AAEnC,IAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AACzC,IAAA,MAAM,KAAA,CAAM,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAClC,IAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,CAAE,KAAA;AAAA,MAAM,CAAC,GAAA,KACjC,OAAA,CAAQ,IAAA,CAAK,0CAA0C,GAAG;AAAA,KAC5D;AACA,IAAA,MAAM,KAAA,CAAM,MAAM,OAAO,CAAA;AACzB,IAAA,QAAA,CAAS,KAAA,EAAM;AACf,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,aAAA,EAAc;AACpB,MAAA,MAAM,MAAM,KAAA,EAAM;AAAA,IACpB;AACA,IAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,EAC1C;AAKA,EAAA,cAAA,CAAe,MAAM;AACnB,IAAA,IAAI;AAAE,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,gBAAgB,CAAC,CAAA;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAA0B;AAAA,EAC7F,CAAC,CAAA;AAGD,EAAA,IAAI,iBAAA,GAAuD,IAAA;AAC3D,EAAA,OAAA,CAAQ,YAAA,CAAa,CAAC,MAAA,KAAW,iBAAA,GAAoB,MAAM,CAAC,CAAA;AAE5D,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,QAAA;AAAA,IAEV,MAAM,IAAA,GAAO;AACX,MAAA,IAAI,CAAC,KAAA,CAAM,SAAA,EAAU,EAAG;AACtB,QAAA,MAAM,aAAA,EAAc;AACpB,QAAA,MAAM,MAAM,KAAA,EAAM;AAGlB,QAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,MAAM,CAAC,CAAA;AACtC,QAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AAAA,MAC3C;AAAA,IACF,CAAA;AAAA,IAEA,KAAA,GAAQ;AACN,MAAA,KAAK,MAAM,KAAA,EAAM;AACjB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,OAAO,CAAC,CAAA;AAAA,IACzC,CAAA;AAAA,IAEA,MAAM,KAAK,IAAA,EAAM;AACf,MAAA,MAAM,OAAO,IAAI,CAAA;AAAA,IACnB,CAAA;AAAA,IAEA,MAAM,cAAc,EAAA,EAAI;AACtB,MAAA,IAAI,CAAC,IAAI,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,EAAG;AAC7C,QAAA,OAAA,CAAQ,IAAA,CAAK,4DAAuD,EAAE,CAAA;AACtE,QAAA;AAAA,MACF;AACA,MAAA,MAAM,UAAA,GAAa,MAAM,SAAA,EAAU;AACnC,MAAA,MAAM,WAAA,GAAc,MAAM,GAAA,EAAI;AAC9B,MAAA,MAAM,KAAA,CAAM,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAClC,MAAA,MAAM,OAAA,CAAQ,aAAA,CAAc,EAAA,EAAI,WAAW,CAAA,CAAE,KAAA;AAAA,QAAM,CAAC,GAAA,KAClD,OAAA,CAAQ,IAAA,CAAK,oDAAoD,GAAG;AAAA,OACtE;AACA,MAAA,MAAM,KAAA,CAAM,MAAM,WAAW,CAAA;AAC7B,MAAA,QAAA,CAAS,KAAA,EAAM;AACf,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,MAAM,aAAA,EAAc;AACpB,QAAA,MAAM,MAAM,KAAA,EAAM;AAAA,MACpB;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,iBAAiB,GAAA,EAAK;AAAA,IAE5B,CAAA;AAAA,IAEA,cAAA,GAAiB;AACf,MAAA,OAAO,MAAM,GAAA,EAAI;AAAA,IACnB,CAAA;AAAA,IAEA,aAAa,OAAA,EAAmC;AAC9C,MAAA,iBAAA,GAAoB,OAAA;AAAA,IACtB,CAAA;AAAA,IAEA,MAAM,OAAA,GAAU;AACd,MAAA,MAAM,QAAQ,OAAA,EAAQ;AACtB,MAAA,QAAA,CAAS,OAAA,EAAQ;AACjB,MAAA,KAAA,CAAM,OAAA,EAAQ;AACd,MAAA,IAAI;AACF,QAAA,OAAQ,MAAA,CAA8C,WAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,QAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,MAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,MAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,KAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,UAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,QAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,YAAA;AAAA,MACxD,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IACzB,CAAA;AAAA,IAEA,eAAA,GAAkB;AAChB,MAAA,OAAO,QAAQ,KAAA,EAAM;AAAA,IACvB;AAAA,GACF;AACF;;;ACnKA,eAAsB,aAAa,IAAA,EAAoD;AASrF,EAAA,MAAM,OAAA,GAAwB,UAAA;AAE9B,EAAA,MAAM,KAAA,GAAS,MAAM,SAAA,CAAU,OAAO,CAAA;AACtC,EAAA,MAAM,MAAA,GAAS,MAAMC,WAAAA,EAAW;AAKhC,EAAA,MAAM,EAAE,iBAAA,EAAkB,GAAI,MAAM,OAAO,iCAAiC,CAAA;AAC5E,EAAA,MAAM,WAAA,GAAc,MAAM,iBAAA,CAAkB,KAAA,EAA6D,KAAK,QAAA,EAAU,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAA;AAGnJ,EAAA,MAAM,OAAA,GAAU,MAAM,KAAA,CAAM,eAAA,EAAgB;AAE5C,EAAA,MAAM,CAAC,SAAS,OAAO,CAAA,GAAI,MAAM,KAAA,CAAM,oBAAA,CAAqB,KAAK,QAAQ,CAAA;AACzE,EAAA,MAAM,WAAA,GAAc,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,UAAA,KAAe,KAAA,CAAM,kBAAkB,CAAA,IAAK,IAAA;AAItF,EAAA,MAAM,iBAAA,GAAoB,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAY,CAAC,CAAA,EAAG,EAAA;AACvD,EAAA,IAAI,WAAA,GAAA,CACD,iBAAA,IAAqB,IAAA,GAClB,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,UAAA,KAAe,KAAA,CAAM,kBAAA,IAAsB,CAAA,CAAE,UAAU,iBAAiB,CAAA,GAC9F,MAAA,KACJ,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,UAAA,KAAe,KAAA,CAAM,kBAAkB,CAAA,IAAK,IAAA;AAEpE,EAAA,IAAI,CAAC,WAAA,IAAe,CAAC,WAAA,EAAa;AAChC,IAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,EACnE;AAGA,EAAA,IAAI,QAAA,GAA+B,IAAA;AACnC,EAAA,IAAI,QAAA,GAA+B,IAAA;AACnC,EAAA,IAAI,aAAA;AACJ,EAAA,IAAI,aAAA;AAEJ,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,IAAI;AACF,MAAA,MAAM,GAAG,CAAA,EAAG,GAAA,EAAK,KAAK,IAAI,MAAM,KAAA,CAAM,eAAA,CAAgB,WAAA,CAAY,QAAA,EAAU;AAAA,QAC1E,UAAU,WAAA,CAAY;AAAA,OACvB,CAAA;AACD,MAAA,QAAA,GAAW,EAAE,CAAA,EAAG,GAAA,EAAK,KAAA,EAAM;AAC3B,MAAA,IAAI,WAAA,CAAY,aAAA,IAAiB,WAAA,CAAY,aAAA,EAAe;AAC1D,QAAA,aAAA,GAAgB,CAAC,WAAA,CAAY,aAAA,EAAe,WAAA,CAAY,aAAa,CAAA;AAAA,MACvE;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,4CAA4C,GAAG,CAAA;AAAA,IAC/D;AAAA,EACF;AAEA,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,IAAI;AACF,MAAA,MAAM,GAAG,CAAA,EAAG,GAAA,EAAK,KAAK,IAAI,MAAM,KAAA,CAAM,eAAA,CAAgB,WAAA,CAAY,QAAA,EAAU;AAAA,QAC1E,UAAU,WAAA,CAAY;AAAA,OACvB,CAAA;AACD,MAAA,QAAA,GAAW,EAAE,CAAA,EAAG,GAAA,EAAK,KAAA,EAAM;AAC3B,MAAA,IAAI,WAAA,CAAY,aAAA,IAAiB,WAAA,CAAY,aAAA,EAAe;AAC1D,QAAA,aAAA,GAAgB,CAAC,WAAA,CAAY,aAAA,EAAe,WAAA,CAAY,aAAa,CAAA;AAAA,MACvE;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN,6FAAA;AAAA,QACC,GAAA,CAAc;AAAA,OACjB;AAAA,IACF;AAAA,EACF;AAIA,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,IAAA,CAAK,MAAM,UAAA,EAAW;AAAA,EACxB;AAEA,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,EAAU;AAC1B,IAAA,MAAM,WAAA,CAAY,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AACzC,IAAA,MAAM,MAAA,GAAS;AAAA,MACb,WAAA,GAAc,UAAU,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAC,CAAA,EAAG,KAAA,IAAS,SAAS,CAAA,CAAA,GAAK,IAAA;AAAA,MAC5E,WAAA,GAAc,UAAU,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAC,CAAA,EAAG,KAAA,IAAS,SAAS,CAAA,CAAA,GAAK;AAAA,KAC9E,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,IAAI,CAAA;AAC3B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,2DAAA,EAA8D,MAAM,CAAA,QAAA,EAC5D,OAAO,CAAA,6LAAA;AAAA,KAGjB;AAAA,EACF;AAOA,EAAA,IAAI,MAAA,GAAwB,IAAA;AAC5B,EAAA,IAAI,MAAA,GAAwB,IAAA;AAC5B,EAAA,IAAI,eAAe,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAC,CAAA,EAAG,UAAU,OAAA,EAAS;AACjE,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,MAAM,KAAA,CAAM,wBAAA,CAAyB,sBAAsB,CAAA;AACpE,MAAA,IAAI,MAAA,IAAU,IAAA,IAAQ,MAAA,IAAU,CAAA,EAAG;AACjC,QAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,mBAAA,CAAoB,MAAM,CAAA;AACpD,QAAA,MAAM,KAAA,CAAM,uBAAA,CAAwB,KAAA,EAAO,WAAA,CAAY,QAAQ,CAAA;AAC/D,QAAA,MAAM,KAAA,CAAM,YAAY,MAAM,CAAA;AAC9B,QAAA,MAAA,GAAS,MAAM,MAAM,eAAA,EAAgB;AACrC,QAAA,GAAA,CAAI,IAAA,CAAK,OAAO,iCAAiC,CAAA;AAAA,MACnD,CAAA,MAAO;AAEL,QAAA,OAAA,CAAQ,KAAK,8EAAyE,CAAA;AACtF,QAAA,MAAA,GAAS,IAAA;AAAA,MACX;AAAA,IACF,SAAS,GAAA,EAAK;AAEZ,MAAA,OAAA,CAAQ,IAAA,CAAK,qDAAA,EAAwD,GAAA,CAAc,OAAO,CAAA;AAC1F,MAAA,MAAA,GAAS,IAAA;AACT,MAAA,MAAA,GAAS,IAAA;AAAA,IACX;AAAA,EACF;AAGA,EAAA,eAAe,SAAS,OAAA,EAAgD;AACtE,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,MAAA,EAAQ,OAAO,OAAA;AAC/B,IAAA,MAAM,MAAqB,EAAC;AAC5B,IAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AACzB,MAAA,MAAM,KAAA,CAAM,gBAAA,CAAiB,MAAA,EAAQ,GAAG,CAAA;AACxC,MAAA,MAAM,OAAA,GAAU,MAAM,KAAA,CAAM,kBAAA,CAAmB,QAAQ,MAAM,CAAA;AAC7D,MAAA,IAAI,UAAU,CAAA,EAAG;AACf,QAAA,GAAA,CAAI,KAAK,GAAG,CAAA;AACZ,QAAA;AAAA,MACF;AACA,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,OAAA,GAAU,MAAM,KAAA,CAAM,qBAAA,CAAsB,QAAQ,MAAM,CAAA;AAChE,QAAA,IAAI,UAAU,CAAA,EAAG;AACjB,QAAA,GAAA,CAAI,IAAA,CAAK,MAAM,KAAA,CAAM,iBAAA,CAAkB,MAAM,CAAC,CAAA;AAAA,MAChD;AAAA,IACF;AACA,IAAA,OAAO,GAAA;AAAA,EACT;AAGA,EAAA,eAAe,QAAA,GAA0B;AACvC,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,MAAA,EAAQ;AACxB,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,CAAM,kBAAA,CAAmB,MAAA,EAAQ,CAAC,CAAA;AACxC,MAAA,OAAO,IAAA,EAAM;AACX,QAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,qBAAA,CAAsB,QAAQ,MAAM,CAAA;AAC5D,QAAA,IAAI,MAAM,CAAA,EAAG;AAAA,MACf;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAA4B;AAAA,EACtC;AAGA,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,WAAA,GAAoC,IAAA;AAExC,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,kBAAA,GAAqB,CAAA;AACzB,EAAA,IAAI,gBAAA,GAAmB,CAAA;AACvB,EAAA,IAAI,kBAAA,GAAqB,CAAA;AAWzB,EAAA,IAAI,oBAAA,GAAuB,CAAA;AAC3B,EAAA,IAAI,mBAAA,GAAsB,CAAA;AAC1B,EAAA,IAAI,kBAAA,GAAqB,KAAA;AACzB,EAAA,IAAI,sBAAA,GAAyB,KAAA;AAG7B,EAAA,IAAI,gBAAA,GAAmB,CAAA;AACvB,EAAA,IAAI,gBAAA,GAAmB,CAAA;AAEvB,EAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,OAAA,CAAQ,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,WAAA,EAAa,KAAK,CAAA;AACvF,EAAA,MAAM,WAAW,cAAA,EAAgB,GAAA,IAAO,eAAe,GAAA,GAAM,CAAA,GAAI,eAAe,GAAA,GAAM,EAAA;AACtF,EAAA,MAAM,gBAAA,GAAmB,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,GAAA,GAAY,QAAQ,CAAC,CAAA;AAIrE,EAAA,eAAe,SAAS,OAAA,EAAgC;AACtD,IAAA,OAAO,CAAC,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AAC1C,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI,OAAA;AACJ,MAAA,IAAI;AAaF,QAAA,CAAC,SAAS,OAAO,CAAA,GAAI,MAAM,KAAA,CAAM,mBAAA,CAAoB,SAAS,OAAA,EAAS;AAAA,UACrE,OAAO,EAAA,GAAK;AAAA,SACb,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,GAAG,CAAA;AAC3D,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AAExC,MAAA,MAAM,YAAA,GAAe,WAAA,GAAc,OAAA,CAAQ,WAAA,CAAY,KAAK,CAAA,GAAI,MAAA;AAChE,MAAA,MAAM,YAAA,GAAe,WAAA,GAAc,OAAA,CAAQ,WAAA,CAAY,KAAK,CAAA,GAAI,MAAA;AAMhE,MAAA,IAAI,gBAAgB,aAAA,EAAe;AACjC,QAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC9B,UAAA,MAAM,GAAA,GAAM,YAAA,CAAa,GAAA,EAAK,aAAa,CAAA;AAC3C,UAAA,IAAI,GAAA,IAAO,IAAA,IAAQ,GAAA,GAAM,gBAAA,EAAkB,gBAAA,GAAmB,GAAA;AAAA,QAChE;AAAA,MACF;AACA,MAAA,IAAI,gBAAgB,aAAA,EAAe;AACjC,QAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC9B,UAAA,MAAM,GAAA,GAAM,YAAA,CAAa,GAAA,EAAK,aAAa,CAAA;AAC3C,UAAA,IAAI,GAAA,IAAO,IAAA,IAAQ,GAAA,GAAM,gBAAA,EAAkB,gBAAA,GAAmB,GAAA;AAAA,QAChE;AAAA,MACF;AAUA,MAAA,IAAI,QAAA,IAAY,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AACvD,QAAA,MAAM,gBAAA,CAAiB,cAAc,OAAO,CAAA;AAAA,MAC9C;AACA,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AACxC,MAAA,IAAI,QAAA,IAAY,YAAA,IAAgB,YAAA,CAAa,MAAA,GAAS,CAAA,EAAG;AACvD,QAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,YAAY,CAAA;AAC7C,QAAA,MAAM,gBAAA,CAAiB,WAAW,OAAO,CAAA;AAAA,MAC3C;AAEA,MAAA,WAAA,IAAA,CAAgB,YAAA,EAAc,MAAA,IAAU,CAAA,KAAM,YAAA,EAAc,MAAA,IAAU,CAAA,CAAA;AAGtE,MAAA,IAAI,qBAAqB,CAAA,EAAG;AAC1B,QAAA,IAAI,yBAAyB,CAAA,EAAG;AAC9B,UAAA,oBAAA,GAAuB,YAAY,GAAA,EAAI;AAAA,QACzC;AACA,QAAA,MAAM,iBAAA,GAAA,CAAqB,WAAA,CAAY,GAAA,EAAI,GAAI,oBAAA,IAAwB,GAAA;AAGvE,QAAA,IAAI,iBAAA,GAAoB,CAAA,IAAK,CAAC,kBAAA,EAAoB;AAChD,UAAA,MAAM,iBAAiB,iBAAA,GAAoB,QAAA;AAC3C,UAAA,MAAM,QAAQ,kBAAA,GAAqB,cAAA;AACnC,UAAA,IAAI,QAAQ,GAAA,EAAK;AACf,YAAA,IAAI,mBAAA,KAAwB,CAAA,EAAG,mBAAA,GAAsB,WAAA,CAAY,GAAA,EAAI;AACrE,YAAA,IAAA,CAAK,WAAA,CAAY,GAAA,EAAI,GAAI,mBAAA,IAAuB,MAAO,CAAA,EAAG;AACxD,cAAA,kBAAA,GAAqB,IAAA;AACrB,cAAA,OAAA,CAAQ,IAAA;AAAA,gBACN,wBAAA;AAAA,gBACA,CAAA,yCAAA,EACG,kBAAkB,CAAA,WAAA,EAAc,iBAAA,CAAkB,QAAQ,CAAC,CAAC,OAC1D,kBAAA,GAAqB,iBAAA,EAAmB,QAAQ,CAAC,CAAC,WAAW,QAAQ,CAAA,mBAAA,EAAA,CACtE,QAAQ,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,4MAAA;AAAA,eAG7B;AAAA,YACF;AAAA,UACF,CAAA,MAAO;AACL,YAAA,mBAAA,GAAsB,CAAA;AAAA,UACxB;AAAA,QACF;AASA,QAAA,IACE,CAAC,sBAAA,IACD,kBAAA,GAAqB,GAAA,EACrB;AACA,UAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,QAAA,CAAS,KAAA,EAAM;AAC1C,UAAA,MAAM,QAAA,GAAW,cAAc,qBAAA,IAAyB,CAAA;AACxD,UAAA,IAAI,QAAA,GAAW,qBAAqB,GAAA,EAAK;AACvC,YAAA,sBAAA,GAAyB,IAAA;AACzB,YAAA,OAAA,CAAQ,IAAA;AAAA,cACN,0BAAA;AAAA,cACA,CAAA,qBAAA,EAAwB,QAAQ,CAAA,CAAA,EAAI,kBAAkB,CAAA,SAAA,EAAA,CAChD,WAAW,kBAAA,GAAsB,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,4QAAA;AAAA,aAKxD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AASA,MAAA,OACE,CAAC,SAAA,IACD,OAAA,KAAY,SAAA,KACX,KAAK,KAAA,CAAM,WAAA,EAAY,GAAI,CAAA,IAC1B,KAAK,QAAA,CAAS,UAAA,EAAW,IAAK,IAAA,CAAK,SAAS,cAAA,CAAA,EAC9C;AACA,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,MAC5C;AAEA,MAAA,IAAI,OAAA,KAAY,MAAM,WAAA,EAAa;AACjC,QAAA,IAAI,UAAU,MAAM,gBAAA;AAAA,UAAiB,EAAC;AAAA,UAAG,OAAA;AAAA;AAAA,UAAmB;AAAA,SAAI;AAChE,QAAA,IAAI,UAAU,MAAM,gBAAA;AAAA,UAAiB,EAAC;AAAA,UAAG,OAAA;AAAA;AAAA,UAAmB;AAAA,SAAI;AAChE,QAAA;AAAA,MACF;AACA,MAAA,IAAI,WAAW,OAAA,KAAY,CAAA,IAAK,OAAA,KAAY,CAAC,MAAM,MAAA,EAAQ;AACzD,QAAA,OAAA,CAAQ,IAAA,CAAK,2CAA2C,OAAO,CAAA;AAC/D,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,eAAe,gBAAA,CAAiB,IAAA,EAAqB,OAAA,EAAiB,KAAA,GAAQ,KAAA,EAAO;AACnF,IAAA,IAAI,CAAC,QAAA,IAAY,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AACrD,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,MAAM,KAAA,CAAM,eAAA;AAAA,QACnB,QAAA,CAAS,CAAA;AAAA,QACT,QAAA,CAAS,GAAA;AAAA,QACT,QAAA,CAAS,KAAA;AAAA,QACT,IAAA;AAAA,QACA,KAAA,GAAQ,EAAE,GAAA,EAAK,IAAA,EAAM,cAAc,IAAA,EAAK,GAAI,EAAE,YAAA,EAAc,IAAA;AAAK,OACnE;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,yCAAyC,GAAG,CAAA;AAC1D,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AAExC,IAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AACxC,MAAA,sBAAA;AAAA,QACE,CAAA;AAAA,QACA,MAAM;AACJ,UAAA,MAAM,EAAA,GAAK,gBAAA;AACX,UAAA,gBAAA,IAAoB,gBAAA;AACpB,UAAA,OAAO,EAAA;AAAA,QACT,CAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,IAAI;AACF,QAAA,MAAM,EAAA,GAAK,MAAA,CAAO,mBAAA,CAAoB,CAAA,EAAG,EAAE,UAAU,CAAC,CAAA,EAAG,GAAS,CAAA,EAAG,CAAA;AACrE,QAAA,IAAA,CAAK,QAAA,CAAS,QAAQ,EAAE,CAAA;AACxB,QAAA,kBAAA,EAAA;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,uBAAuB,CAAA,EAAG;AAC5B,UAAA,OAAA,CAAQ,IAAA,CAAK,0CAA0C,GAAG,CAAA;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,eAAe,gBAAA,CAAiB,IAAA,EAAqB,OAAA,EAAiB,KAAA,GAAQ,KAAA,EAAO;AACnF,IAAA,IAAI,CAAC,QAAA,IAAY,SAAA,IAAa,OAAA,KAAY,SAAA,EAAW;AACrD,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,MAAM,KAAA,CAAM,eAAA;AAAA,QACnB,QAAA,CAAS,CAAA;AAAA,QACT,QAAA,CAAS,GAAA;AAAA,QACT,QAAA,CAAS,KAAA;AAAA,QACT,IAAA;AAAA,QACA,KAAA,GAAQ,EAAE,GAAA,EAAK,IAAA,EAAM,cAAc,IAAA,EAAK,GAAI,EAAE,YAAA,EAAc,IAAA;AAAK,OACnE;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,yCAAyC,GAAG,CAAA;AAC1D,MAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AAExC,IAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACtB,MAAA,IAAI,OAAA,KAAY,aAAa,SAAA,EAAW;AACxC,MAAA,sBAAA;AAAA,QACE,CAAA;AAAA,QACA,MAAM;AACJ,UAAA,MAAM,EAAA,GAAK,gBAAA;AACX,UAAA,MAAMF,QAAAA,GAAU,EAAE,UAAA,IAAc,IAAA;AAChC,UAAA,MAAM,UAAA,GAAa,EAAE,WAAA,IAAe,KAAA;AACpC,UAAA,gBAAA,IAAoB,IAAA,CAAK,KAAA,CAAOA,QAAAA,GAAU,GAAA,GAAa,UAAU,CAAA;AACjE,UAAA,OAAO,EAAA;AAAA,QACT,CAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,MAAM,OAAA,GAAU,+BAA+B,CAAC,CAAA;AAChD,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,IAAA,CAAK,MAAM,QAAA,CAAS,OAAA,CAAQ,MAAM,OAAA,CAAQ,QAAA,EAAU,QAAQ,UAAU,CAAA;AACtE,QAAA,kBAAA,EAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,SAAA,GAAY,CAAA;AACZ,EAAA,WAAA,GAAc,QAAA,CAAS,SAAS,CAAA,CAAE,KAAA;AAAA,IAAM,CAAC,GAAA,KACvC,OAAA,CAAQ,KAAA,CAAM,mCAAmC,GAAG;AAAA,GACtD;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,OAAA,GAAU;AACd,MAAA,SAAA,GAAY,IAAA;AACZ,MAAA,SAAA,EAAA;AACA,MAAA,IAAI;AAAE,QAAA,MAAM,WAAA;AAAA,MAAa,CAAA,CAAA,MAAQ;AAAA,MAAe;AAChD,MAAA,IAAI;AAAE,QAAA,IAAI,MAAA,EAAQ,MAAM,KAAA,CAAM,WAAA,CAAY,MAAM,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC1E,MAAA,IAAI;AAAE,QAAA,IAAI,MAAA,EAAQ,MAAM,KAAA,CAAM,cAAA,GAAiB,MAAM,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC/E,MAAA,IAAI;AAAE,QAAA,IAAI,QAAA,QAAgB,KAAA,CAAM,eAAA,GAAkB,SAAS,CAAA,EAAG,QAAA,CAAS,GAAA,EAAK,QAAA,CAAS,KAAK,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACpH,MAAA,IAAI;AAAE,QAAA,IAAI,QAAA,QAAgB,KAAA,CAAM,eAAA,GAAkB,SAAS,CAAA,EAAG,QAAA,CAAS,GAAA,EAAK,QAAA,CAAS,KAAK,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACpH,MAAA,IAAI;AAAE,QAAA,MAAM,KAAA,CAAM,iBAAiB,OAAO,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACpE,MAAA,IAAI;AAAE,QAAA,MAAM,KAAA,CAAM,wBAAwB,OAAO,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC3E,MAAA,IAAI;AAAE,QAAA,MAAM,YAAY,MAAA,EAAO;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IAC3D,CAAA;AAAA,IAEA,MAAM,aAAA,CAAc,OAAA,EAAS,OAAA,EAAS;AACpC,MAAA,IAAI,WAAA,IAAe,WAAA,CAAY,KAAA,KAAU,OAAA,EAAS;AAClD,MAAA,MAAM,YAAY,OAAA,CAAQ,IAAA;AAAA,QACxB,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,KAAA,CAAM,kBAAA,IAAsB,EAAE,KAAA,KAAU;AAAA,OAClE;AACA,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,OAAA,CAAQ,IAAA,CAAK,+DAA0D,OAAO,CAAA;AAC9E,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,WAAW,EAAE,SAAA;AACnB,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,IAAI;AAAE,UAAA,MAAM,WAAA;AAAA,QAAa,CAAA,CAAA,MAAQ;AAAA,QAAe;AAAA,MAClD;AACA,MAAA,IAAI,SAAA,EAAW;AAGf,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,IAAI;AAAE,UAAA,MAAM,MAAM,eAAA,GAAkB,QAAA,CAAS,GAAG,QAAA,CAAS,GAAA,EAAK,SAAS,KAAK,CAAA;AAAA,QAAG,CAAA,CAAA,MAAQ;AAAA,QAAe;AACtG,QAAA,QAAA,GAAW,IAAA;AAAA,MACb;AACA,MAAA,IAAI;AACF,QAAA,MAAM,GAAG,CAAA,EAAG,GAAA,EAAK,KAAK,IAAI,MAAM,KAAA,CAAM,eAAA,CAAgB,SAAA,CAAU,QAAA,EAAU;AAAA,UACxE,UAAU,SAAA,CAAU;AAAA,SACrB,CAAA;AACD,QAAA,QAAA,GAAW,EAAE,CAAA,EAAG,GAAA,EAAK,KAAA,EAAM;AAC3B,QAAA,aAAA,GAAgB,SAAA,CAAU,iBAAiB,SAAA,CAAU,aAAA,GACjD,CAAC,SAAA,CAAU,aAAA,EAAe,SAAA,CAAU,aAAa,CAAA,GACjD,KAAA,CAAA;AAAA,MACN,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,sFAAA;AAAA,UACC,GAAA,CAAc;AAAA,SACjB;AACA,QAAA,QAAA,GAAW,IAAA;AACX,QAAA,IAAA,CAAK,MAAM,UAAA,EAAW;AAAA,MACxB;AAEA,MAAA,WAAA,GAAc,SAAA;AAId,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAC3C,QAAA,MAAM,CAAC,IAAA,EAAM,IAAI,CAAA,GAAI,KAAA,CAAM,WACvB,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,GACnB,CAAC,IAAA,GAAO,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,GAAO,UAAW,CAAC,CAAA;AAC7C,QAAA,MAAM,KAAA,CAAM,aAAA;AAAA,UACV,OAAA;AAAA,UACA,CAAA,CAAA;AAAA,UACA,IAAA;AAAA,UACA,IAAA;AAAA,UACA,MAAM,oBAAA,IAAwB;AAAA,SAChC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,mDAAmD,GAAG,CAAA;AAAA,MACrE;AAIA,MAAA,IAAI;AAAE,QAAA,IAAI,QAAA,EAAU,MAAM,KAAA,CAAM,qBAAA,GAAwB,SAAS,CAAC,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC5F,MAAA,MAAM,QAAA,EAAS;AAEf,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AACjD,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAEjD,MAAA,WAAA,GAAc,QAAA,CAAS,QAAQ,CAAA,CAAE,KAAA;AAAA,QAAM,CAAC,GAAA,KACtC,OAAA,CAAQ,KAAA,CAAM,yDAAyD,GAAG;AAAA,OAC5E;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,KAAK,OAAA,EAAS;AAKlB,MAAA,MAAM,WAAW,EAAE,SAAA;AACnB,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,IAAI;AAAE,UAAA,MAAM,WAAA;AAAA,QAAa,CAAA,CAAA,MAAQ;AAAA,QAAe;AAAA,MAClD;AACA,MAAA,IAAI,SAAA,EAAW;AAEf,MAAA,IAAI;AAOF,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAC3C,QAAA,MAAM,CAAC,IAAA,EAAM,IAAI,CAAA,GAAI,KAAA,CAAM,WACvB,KAAA,CAAM,QAAA,CAAS,IAAI,CAAA,GACnB,CAAC,IAAA,GAAO,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,GAAO,UAAW,CAAC,CAAA;AAC7C,QAAA,MAAM,KAAA,CAAM,aAAA;AAAA,UACV,OAAA;AAAA,UACA,CAAA,CAAA;AAAA,UACA,IAAA;AAAA,UACA,IAAA;AAAA,UACA,MAAM,oBAAA,IAAwB;AAAA,SAChC;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,oCAAoC,GAAG,CAAA;AAAA,MACtD;AASA,MAAA,IAAI;AACF,QAAA,IAAI,QAAA,EAAU,MAAM,KAAA,CAAM,qBAAA,GAAwB,SAAS,CAAC,CAAA;AAAA,MAC9D,CAAA,CAAA,MAAQ;AAAA,MAAe;AACvB,MAAA,IAAI;AACF,QAAA,IAAI,QAAA,EAAU,MAAM,KAAA,CAAM,qBAAA,GAAwB,SAAS,CAAC,CAAA;AAAA,MAC9D,CAAA,CAAA,MAAQ;AAAA,MAAe;AACvB,MAAA,MAAM,QAAA,EAAS;AAIf,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AACjD,MAAA,gBAAA,GAAmB,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,GAAS,CAAA;AAMjD,MAAA,WAAA,GAAc,QAAA,CAAS,QAAQ,CAAA,CAAE,KAAA;AAAA,QAAM,CAAC,GAAA,KACtC,OAAA,CAAQ,KAAA,CAAM,+CAA+C,GAAG;AAAA,OAClE;AAAA,IACF,CAAA;AAAA,IAEA,gBAAA,GAAmB;AACjB,MAAA,OAAO,gBAAA;AAAA,IACT,CAAA;AAAA,IAEA,KAAA,GAAQ;AACN,MAAA,OAAO;AAAA,QACL,WAAA,EAAa,YAAA;AAAA,QACb,WAAA;AAAA,QACA,kBAAA;AAAA,QACA,kBAAA;AAAA,QACA,UAAA,EAAY,MAAA,GAAS,CAAC,sBAAsB,IAAI,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKjD,UAAA,EAAY,WAAA,CAAY,SAAA,KAAc,YAAA,GAAe,YAAA,GAAe,QAAA;AAAA,QACpE,eAAA,EAAiB,YAAY,SAAA,KAAc,YAAA;AAAA,QAC3C,GAAG,IAAA,CAAK,QAAA,CAAS,KAAA,EAAM;AAAA,QACvB,GAAG,IAAA,CAAK,KAAA,CAAM,KAAA;AAAM,OACtB;AAAA,IACF;AAAA,GACF;AACF;AAMA,eAAeE,WAAAA,GAAoC;AACjD,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAM,OAAO,4BAAmB,CAAA;AAChD,IAAA,OAAO,OAAA,CAAQ,WAAA;AAAA,EACjB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,iJAAA,EAEO,IAAc,OAAO,CAAA,CAAA;AAAA,KAC9B;AAAA,EACF;AACF;;;ACvnBA,IAAMC,2BAAAA,GAA6B,IAAA;AACnC,IAAMC,sBAAAA,GAAwB,CAAA;AAE9B,eAAsB,qBAAA,CACpB,GAAA,EACA,MAAA,EACA,SAAA,EAC0B;AAG1B,EAAA,MAAM,EAAE,eAAA,EAAAH,gBAAAA,EAAgB,GAAI,MAAM,OAAO,sBAAsB,CAAA;AAC/D,EAAA,MAAM,MAAA,GAAS,MAAMA,gBAAAA,CAAgB,GAAA,CAAI,MAAM,CAAA;AAE/C,EAAA,MAAM,GAAA,GAAM,GAAA,CAAI,WAAA,CAAY,CAAC,GAAG,GAAA,IAAO,EAAA;AACvC,EAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY;AAC9B,EAAA,MAAM,QAAA,GAAW,IAAI,aAAA,CAAc,MAAA,EAAQ,OAAO,GAAG,CAAA;AAErD,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAAM,YAAA,CAAa;AAAA,MAC3B,MAAA;AAAA,MACA,QAAA,EAAU,IAAI,IAAA,IAAQ,WAAA;AAAA,MACtB,OAAA,EAAS,GAAA;AAAA,MACT,QAAA;AAAA,MACA,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,KAAA,CAAM,OAAA,EAAQ;AACd,IAAA,QAAA,CAAS,OAAA,EAAQ;AACjB,IAAA,MAAM,GAAA;AAAA,EACR;AAKA,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,aAAA,EAAe;AAAA,IAC3C,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,GAAA,EAAI;AAAA,IACrB,GAAA,EAAK,CAAC,CAAA,KAAc;AAGlB,MAAA,KAAK,OAAO,CAAC,CAAA;AAAA,IACf;AAAA,GACD,CAAA;AAMD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,QAAA,EAAU;AAAA,IACtC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,CAAC,KAAA,CAAM,SAAA;AAAU,GAC7B,CAAA;AACD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,QAAA,EAAU;AAAA,IACtC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,SAAA,EAAU;AAAA,IAC3B,GAAA,EAAK,CAAC,CAAA,KAAc;AAClB,MAAA,KAAA,CAAM,UAAU,CAAC,CAAA;AACjB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,cAAc,CAAC,CAAA;AAAA,IAChD;AAAA,GACD,CAAA;AACD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,OAAA,EAAS;AAAA,IACrC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,QAAA,EAAS;AAAA,IAC1B,GAAA,EAAK,CAAC,CAAA,KAAe;AACnB,MAAA,KAAA,CAAM,SAAS,CAAC,CAAA;AAChB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,cAAc,CAAC,CAAA;AAAA,IAChD;AAAA,GACD,CAAA;AAED,EAAA,IAAI,IAAI,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA,EAAG;AACjD,IAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAA,EAAY;AAAA,MACxC,YAAA,EAAc,IAAA;AAAA,MACd,GAAA,EAAK,MAAM,GAAA,CAAI,QAAA,IAAY;AAAA,KAC5B,CAAA;AAAA,EACH;AAIA,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,cAAA,EAAgB;AAAA,IAC5C,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,KAAA,CAAM,eAAA,EAAgB;AAAA,IACjC,GAAA,EAAK,CAAC,CAAA,KAAc;AAClB,MAAA,KAAA,CAAM,gBAAgB,CAAC,CAAA;AACvB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,YAAY,CAAC,CAAA;AAAA,IAC9C;AAAA,GACD,CAAA;AAUD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,YAAA,EAAc;AAAA,IAC1C,YAAA,EAAc,IAAA;AAAA,IACd,KAAK,MAAc;AACjB,MAAA,IAAI,CAAC,QAAA,CAAS,SAAA,EAAU,EAAG,OAAO,CAAA;AAClC,MAAA,IAAI,CAAC,KAAA,CAAM,SAAA,EAAU,IAAK,KAAA,CAAM,WAAA,EAAY,IAAK,CAAA,IAAK,CAAC,KAAA,CAAM,SAAA,EAAU,EAAG,OAAO,CAAA;AACjF,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,GACD,CAAA;AAED,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAA,EAAY;AAAA,IACxC,YAAA,EAAc,IAAA;AAAA,IACd,GAAA,EAAK,MAAM,cAAA,CAAe,GAAA,CAAI,YAAY,MAAA,CAAO,QAAA,CAAS,IAAI,QAAQ,CAAA,IAAK,IAAI,QAAA,GAAW,CAAA,GACtF,CAAC,CAAC,CAAA,EAAG,IAAI,QAAQ,CAAC,CAAA,GAClB,EAAE;AAAA,GACP,CAAA;AAMD,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,UAAA,EAAY;AAAA,IACxC,YAAA,EAAc,IAAA;AAAA,IACd,KAAK,MAAM;AACT,MAAA,MAAM,GAAA,GAAM,QAAQ,gBAAA,EAAiB;AACrC,MAAA,OAAO,cAAA,CAAe,GAAA,GAAM,CAAA,GAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA,GAAI,EAAE,CAAA;AAAA,IACjD;AAAA,GACD,CAAA;AA+BD,EAAA,eAAe,aAAA,GAA+B;AAC5C,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,IAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,IAAA,GAAA,CAAI,IAAA;AAAA,MAAK,YAAA;AAAA,MACP,CAAA,8BAAA,EAA4BE,8BAA6B,GAAI,CAAA,YAAA;AAAA,KAC/D;AACA,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,MAAM,aAAa,KAAA,CAAM,SAAA,EAAU,GAAI,QAAA,GAAW,MAAM,WAAA,EAAY;AACpE,MAAA,MAAM,UAAA,GAAa,KAAA,CAAM,SAAA,EAAU,IAAK,UAAA,IAAcA,2BAAAA;AACtD,MAAA,MAAM,SAAA,GAAY,SAAS,SAAA,EAAU;AACrC,MAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAE9B,MAAA,IAAI,SAAA,IAAa,cAAA,KAAmB,CAAA,EAAG,cAAA,GAAiB,KAAA;AAGxD,MAAA,IAAI,cAAc,SAAA,EAAW;AAC3B,QAAA,GAAA,CAAI,IAAA;AAAA,UAAK,YAAA;AAAA,UACP,CAAA,kBAAA,EAAA,CAAsB,KAAA,GAAQ,KAAA,EAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,UAAA,EAAA,CACpC,UAAA,GAAa,GAAA,EAAM,QAAQ,CAAC,CAAC,CAAA,WAAA,EAAc,QAAA,CAAS,YAAY,CAAA,CAAA;AAAA,SAC7E;AACA,QAAA;AAAA,MACF;AAIA,MAAA,IACE,SAAA,IACA,cAAA,GAAiB,CAAA,IACjB,KAAA,GAAQ,kBAAkB,GAAA,EAC1B;AACA,QAAA,GAAA,CAAI,IAAA;AAAA,UAAK,YAAA;AAAA,UACP,CAAA,qCAAA,EAAA,CAAyC,KAAA,GAAQ,KAAA,EAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,WAAA,EACvD,QAAA,CAAS,UAAA,EAAY,CAAA,QAAA,EAAA,CAAY,UAAA,GAAa,GAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,wIAAA;AAAA,SAG3E;AACA,QAAA;AAAA,MACF;AAGA,MAAA,IAAA,CAAK,KAAA,GAAQ,KAAA,IAAS,GAAA,GAAOC,sBAAAA,EAAuB;AAClD,QAAA,GAAA,CAAI,IAAA;AAAA,UAAK,YAAA;AAAA,UACP,sBAAsBA,sBAAqB,CAAA,eAAA,EAAA,CACjC,UAAA,GAAa,GAAA,EAAM,QAAQ,CAAC,CAAC,CAAA,WAAA,EAC5BD,2BAAAA,GAA6B,GAAI,CAAA,YAAA,EAClC,QAAA,CAAS,UAAA,EAAY,kDACAC,sBAAqB,CAAA,qJAAA;AAAA,SAGtD;AACA,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,EAAE,CAAC,CAAA;AAAA,IAC5C;AAAA,EACF;AAEA,EAAA,eAAe,OAAO,OAAA,EAAgC;AACpD,IAAA,MAAM,UAAA,GAAa,MAAM,SAAA,EAAU;AAKnC,IAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AAEzC,IAAA,MAAM,KAAA,CAAM,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAElC,IAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,OAAO,CAAA,CAAE,KAAA;AAAA,MAAM,CAAC,GAAA,KACjC,OAAA,CAAQ,IAAA,CAAK,mCAAmC,GAAG;AAAA,KACrD;AAGA,IAAA,MAAM,KAAA,CAAM,MAAM,OAAO,CAAA;AACzB,IAAA,QAAA,CAAS,KAAA,EAAM;AAGf,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,MAAM,aAAA,EAAc;AACpB,MAAA,MAAM,MAAM,KAAA,EAAM;AAAA,IACpB;AAGA,IAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,QAAQ,CAAC,CAAA;AAAA,EAC1C;AAQA,EAAA,cAAA,CAAe,MAAM;AACnB,IAAA,IAAI;AAAE,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,gBAAgB,CAAC,CAAA;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAA0B;AAAA,EAC7F,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,UAAA;AAAA,IAEV,MAAM,IAAA,GAAO;AAGX,MAAA,IAAI,CAAC,KAAA,CAAM,SAAA,EAAU,EAAG;AACtB,QAAA,MAAM,aAAA,EAAc;AACpB,QAAA,MAAM,MAAM,KAAA,EAAM;AAClB,QAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,MAAM,CAAC,CAAA;AACtC,QAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,SAAS,CAAC,CAAA;AAAA,MAC3C;AAAA,IACF,CAAA;AAAA,IAEA,KAAA,GAAQ;AACN,MAAA,KAAK,MAAM,KAAA,EAAM;AACjB,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,KAAA,CAAM,OAAO,CAAC,CAAA;AAAA,IACzC,CAAA;AAAA,IAEA,MAAM,KAAK,IAAA,EAAM;AACf,MAAA,MAAM,OAAO,IAAI,CAAA;AAAA,IACnB,CAAA;AAAA,IAEA,MAAM,cAAc,EAAA,EAAI;AAEtB,MAAA,IAAI,CAAC,IAAI,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,EAAE,CAAA,EAAG;AAC7C,QAAA,OAAA,CAAQ,IAAA,CAAK,8DAAyD,EAAE,CAAA;AACxE,QAAA;AAAA,MACF;AACA,MAAA,MAAM,UAAA,GAAa,MAAM,SAAA,EAAU;AACnC,MAAA,MAAM,WAAA,GAAc,MAAM,GAAA,EAAI;AAE9B,MAAA,MAAM,KAAA,CAAM,KAAA,EAAM,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAClC,MAAA,MAAM,OAAA,CAAQ,aAAA,CAAc,EAAA,EAAI,WAAW,CAAA,CAAE,KAAA;AAAA,QAAM,CAAC,GAAA,KAClD,OAAA,CAAQ,IAAA,CAAK,sDAAsD,GAAG;AAAA,OACxE;AACA,MAAA,MAAM,KAAA,CAAM,MAAM,WAAW,CAAA;AAC7B,MAAA,QAAA,CAAS,KAAA,EAAM;AACf,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,MAAM,aAAA,EAAc;AACpB,QAAA,MAAM,MAAM,KAAA,EAAM;AAAA,MACpB;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,iBAAiB,GAAA,EAAK;AAAA,IAE5B,CAAA;AAAA,IAEA,cAAA,GAAiB;AACf,MAAA,OAAO,MAAM,GAAA,EAAI;AAAA,IACnB,CAAA;AAAA,IACA,MAAM,OAAA,GAAU;AACd,MAAA,MAAM,QAAQ,OAAA,EAAQ;AACtB,MAAA,QAAA,CAAS,OAAA,EAAQ;AACjB,MAAA,KAAA,CAAM,OAAA,EAAQ;AACd,MAAA,IAAI;AACF,QAAA,OAAQ,MAAA,CAA8C,WAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,QAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,MAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,MAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,KAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,UAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,QAAA;AACtD,QAAA,OAAQ,MAAA,CAA8C,YAAA;AAAA,MACxD,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IACzB,CAAA;AAAA,IAEA,eAAA,GAAkB;AAChB,MAAA,OAAO,QAAQ,KAAA,EAAM;AAAA,IACvB;AAAA,GACF;AACF;;;AC7WA,IAAM,YAAA,GAAuB;AAAA,EAC3B,IAAA,EAAM,QAAA;AAAA,EACN,WAAW,MAAM,IAAA;AAAA,EACjB,SAAS,CAAC,GAAA,EAAK,KAAA,KAAU,mBAAA,CAAoB,KAAK,KAAK;AACzD,CAAA;AAEA,IAAM,WAAA,GAAsB;AAAA,EAC1B,IAAA,EAAM,OAAA;AAAA,EACN,WAAW,MAAM,IAAA;AAAA,EACjB,SAAS,CAAC,GAAA,EAAK,KAAA,KAAU,kBAAA,CAAmB,KAAK,KAAK;AACxD,CAAA;AAEA,IAAM,YAAA,GAAuB;AAAA,EAC3B,IAAA,EAAM,QAAA;AAAA,EACN,SAAA,EAAW,MAAM,OAAO,YAAA,KAAiB,WAAA;AAAA,EACzC,OAAA,EAAS,CAAC,GAAA,EAAK,KAAA,EAAO,cAAc,mBAAA,CAAoB,GAAA,EAAK,OAAO,SAAS;AAC/E,CAAA;AAEA,IAAM,cAAA,GAAyB;AAAA,EAC7B,IAAA,EAAM,UAAA;AAAA,EACN,WAAW,MAAM,IAAA;AAAA,EACjB,OAAA,EAAS,CAAC,GAAA,EAAK,KAAA,EAAO,cAAc,qBAAA,CAAsB,GAAA,EAAK,OAAO,SAAS;AACjF,CAAA;AAEO,SAAS,iBAAiB,QAAA,EAAgC;AAC/D,EAAA,QAAA,CAAS,SAAS,YAAY,CAAA;AAC9B,EAAA,QAAA,CAAS,SAAS,WAAW,CAAA;AAC7B,EAAA,QAAA,CAAS,SAAS,YAAY,CAAA;AAC9B,EAAA,QAAA,CAAS,SAAS,cAAc,CAAA;AAClC;;;ACNO,SAAS,sBAAsB,MAAA,EAAkC;AACtE,EAAA,IAAI,OAAO,gBAAA,KAAqB,WAAA,IAAe,EAAE,MAAA,YAAkB,mBAAmB,OAAO,CAAA;AAC7F,EAAA,MAAM,KAAM,MAAA,CAA+F,uBAAA;AAC3G,EAAA,IAAI,OAAO,OAAO,UAAA,EAAY;AAC5B,IAAA,IAAI;AAAE,MAAA,OAAO,EAAA,CAAG,IAAA,CAAK,MAAM,CAAA,CAAE,gBAAA;AAAA,IAAkB,CAAA,CAAA,MAAQ;AAAA,IAAqB;AAAA,EAC9E;AACA,EAAA,MAAM,SAAU,MAAA,CAAmE,uBAAA;AACnF,EAAA,OAAO,OAAO,MAAA,KAAW,QAAA,GAAW,MAAA,GAAS,CAAA;AAC/C;AAcO,SAAS,qBAAqB,KAAA,EAS6C;AAChF,EAAA,MAAM,aAAA,GAAgB,MAAM,oBAAA,IAAwB,GAAA;AACpD,EAAA,MAAM,cAAA,GAAiB,MAAM,qBAAA,IAAyB,GAAA;AACtD,EAAA,IAAI,CAAC,KAAA,CAAM,YAAA,IAAgB,MAAM,GAAA,GAAM,KAAA,CAAM,mBAAmB,aAAA,EAAe;AAC7E,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAM,YAAA,EAAa;AAAA,EAC9C;AACA,EAAA,IACE,KAAA,CAAM,aAAA,IACN,KAAA,CAAM,YAAA,IACN,CAAC,KAAA,CAAM,cAAA,IACP,KAAA,CAAM,GAAA,GAAM,KAAA,CAAM,qBAAA,GAAwB,cAAA,EAC1C;AACA,IAAA,OAAO,EAAE,QAAA,EAAU,IAAA,EAAM,IAAA,EAAM,cAAA,EAAe;AAAA,EAChD;AACA,EAAA,OAAO,EAAE,UAAU,KAAA,EAAM;AAC3B;AAEO,IAAM,aAAA,GAAN,MAAM,cAAA,CAAc;AAAA;AAAA;AAAA;AAAA,EAoDjB,WAAA,CACW,SACA,QAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAEjB,IAAA,MAAM,EAAE,WAAA,EAAa,OAAA,EAAS,UAAA,EAAW,GAAI,OAAA;AAC7C,IAAA,IAAI,WAAA,IAAe,OAAA,IAAW,UAAA,KAAe,MAAA,EAAW;AACtD,MAAA,IAAA,CAAK,SAAA,GAAY,EAAE,WAAA,EAAa,OAAA,EAAS,UAAA,EAAW;AAAA,IACtD;AAAA,EACF;AAAA,EAPmB,OAAA;AAAA,EACA,QAAA;AAAA,EArDX,OAAA,GAAU,IAAI,YAAA,EAA6B;AAAA,EAC3C,OAAA,GAAkC,IAAA;AAAA,EAClC,IAAA,GAAO,IAAI,WAAA,EAAY;AAAA,EACvB,kBAAA,GAA4D,IAAA;AAAA;AAAA,EAG5D,YAAA,GAAoC,IAAA;AAAA,EACpC,cAAA,GAAwC,IAAA;AAAA;AAAA,EAGxC,UAAA,GAAoD,IAAA;AAAA,EACpD,gBAAA,GAAmB,CAAA;AAAA,EACnB,oBAAA,GAAuB,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,mBAAA,GAAsB,CAAA;AAAA,EACtB,0BAAA,GAA6B,CAAA;AAAA,EAC7B,aAAA,GAAqC,IAAA;AAAA;AAAA;AAAA;AAAA,EAKrC,aAAA,GAAqC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,UAAA,GAA+B,OAAA;AAAA,EAC/B,uBAAA,GAA0B,KAAA;AAAA,EAC1B,kBAAA,GAA0C,IAAA;AAAA;AAAA,EAG1C,gBAAA,GAAkC,QAAQ,OAAA,EAAQ;AAAA;AAAA;AAAA,EAIlD,iBAAA,GAAoB,IAAI,mBAAA,EAAoB;AAAA;AAAA;AAAA;AAAA,EAKnC,SAAA;AAAA,EAejB,aAAa,OAAO,OAAA,EAAsD;AACxE,IAAA,MAAM,QAAA,GAAW,IAAI,cAAA,EAAe;AACpC,IAAA,gBAAA,CAAiB,QAAQ,CAAA;AACzB,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA,KAAA,MAAW,CAAA,IAAK,OAAA,CAAQ,OAAA,EAAS,QAAA,CAAS,QAAA;AAAA,QAAS,CAAA;AAAA;AAAA,QAAiB;AAAA,OAAI;AAAA,IAC1E;AACA,IAAA,MAAM,MAAA,GAAS,IAAI,cAAA,CAAc,OAAA,EAAS,QAAQ,CAAA;AAClD,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,SAAA,EAAU;AAAA,IACzB,SAAS,GAAA,EAAK;AACZ,MAAC,IAA2C,MAAA,GAAS,MAAA;AACrD,MAAA,MAAM,GAAA;AAAA,IACR;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAc,SAAA,GAA2B;AACvC,IAAA,MAAM,cAAA,GAAiB,YAAY,GAAA,EAAI;AACvC,IAAA,IAAI;AACF,MAAA,GAAA,CAAI,IAAA,CAAK,aAAa,OAAO,CAAA;AAC7B,MAAA,MAAM,GAAA,GAAM,MAAM,GAAA,CAAI,KAAA,CAAM,SAAS,OAAA,EAAS,GAAA,EAAM,MAAM,KAAA,CAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAC,CAAA;AACpG,MAAA,GAAA,CAAI,IAAA;AAAA,QAAK,OAAA;AAAA,QACP,aAAa,GAAA,CAAI,SAAS,UAAU,GAAA,CAAI,WAAA,CAAY,CAAC,CAAA,EAAG,KAAA,IAAS,GAAG,CAAA,OAAA,EAC3D,GAAA,CAAI,YAAY,CAAC,CAAA,EAAG,SAAS,GAAG,CAAA,UAAA,EAAa,IAAI,QAAQ,CAAA;AAAA,OACpE;AACA,MAAA,IAAA,CAAK,IAAA,CAAK,YAAY,GAAG,CAAA;AACzB,MAAA,IAAA,CAAK,YAAA,GAAe,GAAA;AAGpB,MAAA,IAAI,IAAA,CAAK,QAAQ,SAAA,EAAW;AAC1B,QAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW;AACtC,UAAA,GAAA,CAAI,eAAe,IAAA,CAAK;AAAA,YACtB,EAAA,EAAI,IAAI,cAAA,CAAe,MAAA;AAAA,YACvB,MAAA,EAAQ,EAAE,MAAA,KAAW,CAAA,CAAE,IAAI,QAAA,CAAS,MAAM,IAAI,KAAA,GAAQ,KAAA,CAAA;AAAA,YACtD,UAAU,CAAA,CAAE,QAAA;AAAA,YACZ,YAAY,CAAA,CAAE;AAAA,WACf,CAAA;AAAA,QACH;AAAA,MACF;AACA,MAAA,IAAI,KAAK,OAAA,CAAQ,SAAA,IAAa,IAAA,CAAK,OAAA,CAAQ,kBAAkB,IAAA,EAAM;AACjE,QAAA,MAAM,KAAA,GAAQ,MAAM,gBAAA,CAAiB,IAAA,CAAK,QAAQ,MAAA,EAAQ,IAAA,CAAK,QAAQ,SAAS,CAAA;AAChF,QAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AAGrB,UAAA,IAAA,CAAK,iBAAA,CAAkB,KAAA,CAAM,CAAA,CAAE,GAAG,CAAA;AAClC,UAAA,GAAA,CAAI,eAAe,IAAA,CAAK;AAAA,YACtB,EAAA,EAAI,IAAI,cAAA,CAAe,MAAA;AAAA,YACvB,QAAQ,CAAA,CAAE,MAAA;AAAA,YACV,UAAU,CAAA,CAAE,QAAA;AAAA,YACZ,YAAY,CAAA,CAAE;AAAA,WACf,CAAA;AAAA,QACH;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,eAAA,GAC1B,oBAAA,CAAqB,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB,GAAG,CAAA,GACtD,eAAA,CAAS,GAAG,CAAA;AAChB,MAAA,GAAA,CAAI,IAAA;AAAA,QAAK,UAAA;AAAA,QACP,YAAY,QAAA,CAAS,QAAQ,UAAU,QAAA,CAAS,KAAK,YAAY,QAAA,CAAS,MAAM,CAAA,CAAA,CAAA,IAC/E,QAAA,CAAS,gBAAgB,CAAA,UAAA,EAAa,QAAA,CAAS,cAAc,IAAA,CAAK,QAAG,CAAC,CAAA,CAAA,GAAK,EAAA;AAAA,OAC9E;AACA,MAAA,IAAA,CAAK,cAAA,GAAiB,QAAA;AACtB,MAAA,IAAA,CAAK,IAAA,CAAK,qBAAqB,QAAQ,CAAA;AAEvC,MAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,UAAA,EAAY;AAAA,QAClC,UAAU,QAAA,CAAS,QAAA;AAAA,QACnB,QAAQ,QAAA,CAAS;AAAA,OAClB,CAAA;AAGD,MAAA,MAAM,IAAA,CAAK,YAAA,CAAa,QAAA,CAAS,QAAA,EAAU,SAAS,MAAM,CAAA;AAO1D,MAAA,MAAM,oBAAA;AAAA,QACJ,KAAK,OAAA,CAAQ,MAAA;AAAA,QACb,GAAA,CAAI,cAAA;AAAA,QACJ,IAAA,CAAK,iBAAA;AAAA,QACL,CAAC,KAAK,KAAA,KAAU;AAEd,UAAA,OAAA,CAAQ,KAAK,CAAA,oBAAA,EAAuB,KAAA,CAAM,EAAE,CAAA,SAAA,EAAY,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,QACvE,CAAA;AAAA,QACA,IAAA,CAAK;AAAA,OACP;AAEA,MAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,QAAA,EAAU;AAAA,QAChC,OAAO,GAAA,CAAI,WAAA;AAAA,QACX,OAAO,GAAA,CAAI,WAAA;AAAA,QACX,UAAU,GAAA,CAAI;AAAA,OACf,CAAA;AAED,MAAA,IAAA,CAAK,mBAAA,EAAoB;AACzB,MAAA,IAAA,CAAK,gBAAgB,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,SAAS,KAAA,CAAS,CAAA;AAC/D,MAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,gBAAA,CAAiB,OAAA,EAAS,KAAK,aAAa,CAAA;AAKhE,MAAA,IAAI,KAAK,OAAA,CAAQ,kBAAA,KAAuB,UAAA,IAAc,OAAO,aAAa,WAAA,EAAa;AACrF,QAAA,IAAA,CAAK,kBAAA,GAAqB,MAAM,IAAA,CAAK,kBAAA,EAAmB;AACxD,QAAA,QAAA,CAAS,gBAAA,CAAiB,kBAAA,EAAoB,IAAA,CAAK,kBAAkB,CAAA;AAAA,MACvE;AAEA,MAAA,IAAA,CAAK,OAAA,CAAQ,UAAA,CAAW,OAAA,EAAS,KAAA,CAAS,CAAA;AAC1C,MAAA,MAAM,gBAAA,GAAmB,WAAA,CAAY,GAAA,EAAI,GAAI,cAAA;AAC7C,MAAA,GAAA,CAAI,KAAK,WAAA,EAAa,CAAA,SAAA,EAAY,iBAAiB,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,CAAI,CAAA;AACjE,MAAA,IAAI,mBAAmB,GAAA,EAAM;AAE3B,QAAA,OAAA,CAAQ,IAAA;AAAA,UACN,sBAAA;AAAA,UACA,CAAA,qBAAA,EAAwB,gBAAA,CAAiB,OAAA,CAAQ,CAAC,CAAC,CAAA,qFAAA;AAAA,SAErD;AAAA,MACF;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,MAAM,CAAA,GAAI,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAC5D,MAAA,IAAA,CAAK,IAAA,CAAK,YAAY,CAAC,CAAA;AACvB,MAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,CAAC,CAAA;AAC5B,MAAA,MAAM,CAAA;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAA,CAAa,QAAA,EAAwB,MAAA,EAA+B;AAChF,IAAA,MAAM,SAAS,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,cAAe,QAAQ,CAAA;AACjE,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,IAClE;AAEA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,OAAA,GAAU,MAAM,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,cAAe,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAA;AAAA,IAC7F,SAAS,GAAA,EAAK;AAEZ,MAAA,MAAM,KAAA,GAAQ,KAAK,cAAA,EAAgB,aAAA;AACnC,MAAA,IAAI,KAAA,IAAS,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AAC7B,QAAA,MAAM,IAAA,GAAO,MAAM,KAAA,EAAM;AACzB,QAAA,OAAA,CAAQ,IAAA,CAAK,cAAc,QAAQ,CAAA,SAAA,EAAa,IAAc,OAAO,CAAA,iBAAA,EAAoB,IAAI,CAAA,CAAE,CAAA;AAC/F,QAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,gBAAA,EAAkB;AAAA,UAClC,IAAA,EAAM,QAAA;AAAA,UACN,EAAA,EAAI,IAAA;AAAA,UACJ,MAAA,EAAQ,CAAA,EAAG,QAAQ,CAAA,SAAA,EAAa,IAAc,OAAO,CAAA,CAAA;AAAA,UACrD,WAAA,EAAa;AAAA,SACd,CAAA;AACD,QAAA,IAAA,CAAK,IAAA,CAAK,qBAAqB,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,SAAA,EAAa,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AACpF,QAAA,OAAO,IAAA,CAAK,YAAA,CAAa,IAAA,EAAM,CAAA,eAAA,EAAkB,QAAQ,CAAA,CAAE,CAAA;AAAA,MAC7D;AACA,MAAA,MAAM,GAAA;AAAA,IACR;AAGA,IAAA,IAAA,CAAK,OAAA,CAAQ,YAAA,GAAe,CAAC,WAAA,KAAgB;AAC3C,MAAA,KAAK,IAAA,CAAK,SAAS,WAAW,CAAA;AAAA,IAChC,CAAC,CAAA;AAGD,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAGtB,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,QAAA,KAAa,QAAA,EAAU;AACtC,MAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,UAAA,EAAY;AAAA,QAClC,QAAA,EAAU,KAAK,OAAA,CAAQ,QAAA;AAAA,QACvB;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA,EAIA,MAAc,SAAS,MAAA,EAA+B;AAEpD,IAAA,IAAA,CAAK,gBAAA,GAAmB,KAAK,gBAAA,CAAiB,IAAA;AAAA,MAAK,MACjD,IAAA,CAAK,UAAA,CAAW,MAAM;AAAA,KACxB,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AACf,MAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA;AAAA,IAChF,CAAC,CAAA;AACD,IAAA,MAAM,IAAA,CAAK,gBAAA;AAAA,EACb;AAAA,EAEA,MAAc,WAAW,MAAA,EAA+B;AACtD,IAAA,MAAM,KAAA,GAAQ,KAAK,cAAA,EAAgB,aAAA;AACnC,IAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAChC,MAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,IAAI,KAAA;AAAA,QAC7B,CAAA,UAAA,EAAa,IAAA,CAAK,OAAA,EAAS,QAAQ,aAAa,MAAM,CAAA,wBAAA;AAAA,OACvD,CAAA;AACD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,OAAA,EAAS,cAAA,EAAe,IAAK,CAAA;AACtD,IAAA,MAAM,aAAa,IAAA,CAAK,OAAA,GAAU,CAAC,IAAA,CAAK,OAAA,CAAQ,OAAO,MAAA,GAAS,KAAA;AAChE,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,OAAA,EAAS,QAAA,IAAY,QAAA;AAK/C,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAI;AAAE,QAAA,MAAM,IAAA,CAAK,QAAQ,OAAA,EAAQ;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC3D,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,IACjB;AAMA,IAAA,MAAM,SAAmB,EAAC;AAC1B,IAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,MAAA,MAAM,YAAA,GAAe,MAAM,KAAA,EAAM;AACjC,MAAA,OAAA,CAAQ,KAAK,CAAA,2BAAA,EAA8B,YAAY,OAAO,YAAY,CAAA,EAAA,EAAK,MAAM,CAAA,CAAE,CAAA;AAEvF,MAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,gBAAA,EAAkB;AAAA,QAClC,IAAA,EAAM,YAAA;AAAA,QACN,EAAA,EAAI,YAAA;AAAA,QACJ,MAAA;AAAA,QACA;AAAA,OACD,CAAA;AACD,MAAA,IAAA,CAAK,IAAA,CAAK,oBAAA,CAAqB,YAAA,EAAc,MAAM,CAAA;AAEnD,MAAA,MAAM,SAAS,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,cAAe,YAAY,CAAA;AACrE,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,YAAY,CAAA,qBAAA,CAAuB,CAAA;AAClD,QAAA;AAAA,MACF;AAEA,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,OAAA,GAAU,MAAM,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,cAAe,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAA;AAAA,MAC7F,SAAS,GAAA,EAAK;AACZ,QAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,YAAY,CAAA,EAAA,EAAK,GAAG,CAAA,CAAE,CAAA;AACrC,QAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,WAAA,EAAc,YAAY,CAAA,wCAAA,EAA2C,GAAG,CAAA,CAAE,CAAA;AACvF,QAAA;AAAA,MACF;AAGA,MAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,UAAA,EAAY;AAAA,QAClC,QAAA,EAAU,YAAA;AAAA,QACV,MAAA,EAAQ,cAAc,MAAM,CAAA;AAAA,OAC7B,CAAA;AACD,MAAA,IAAA,CAAK,OAAA,CAAQ,YAAA,GAAe,CAAC,WAAA,KAAgB;AAC3C,QAAA,KAAK,IAAA,CAAK,SAAS,WAAW,CAAA;AAAA,MAChC,CAAC,CAAA;AACD,MAAA,IAAA,CAAK,gBAAA,EAAiB;AACtB,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA;AACnC,QAAA,IAAI,UAAA,EAAY,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAK;AAAA,MAC1C,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,IAAA,CAAK,2DAA2D,GAAG,CAAA;AAAA,MAC7E;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,IAAI,aAAA;AAAA,MAC7B,4BAAA;AAAA,MACA,CAAA,gCAAA,EAAmC,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,MACpD;AAAA,KACD,CAAA;AAAA,EACH;AAAA;AAAA,EAIQ,gBAAA,GAAyB;AAC/B,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,YAAA,KAAiB,KAAA,EAAO;AACzC,IAAA,IAAI,CAAC,IAAA,CAAK,cAAA,EAAgB,aAAA,EAAe,MAAA,EAAQ;AAEjD,IAAA,MAAM,QAAA,GAAW,KAAK,OAAA,EAAS,QAAA;AAC/B,IAAA,IAAI,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,OAAA,EAAS;AAEjD,MAAA,IAAA,CAAK,oBAAA,GAAuB,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,WAAA;AAChD,MAAA,IAAA,CAAK,gBAAA,GAAmB,YAAY,GAAA,EAAI;AACxC,MAAA,IAAA,CAAK,mBAAA,GAAsB,qBAAA,CAAsB,IAAA,CAAK,OAAA,CAAQ,MAAM,CAAA;AACpE,MAAA,IAAA,CAAK,0BAAA,GAA6B,YAAY,GAAA,EAAI;AAElD,MAAA,MAAM,aAAA,GAAA,CAAiB,IAAA,CAAK,YAAA,EAAc,WAAA,CAAY,UAAU,CAAA,IAAK,CAAA;AAErE,MAAA,IAAA,CAAK,UAAA,GAAa,YAAY,MAAM;AAClC,QAAA,MAAM,CAAA,GAAI,KAAK,OAAA,CAAQ,MAAA;AACvB,QAAA,MAAM,GAAA,GAAM,YAAY,GAAA,EAAI;AAC5B,QAAA,IAAI,EAAE,MAAA,IAAU,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,aAAa,CAAA,EAAG;AAC3C,UAAA,IAAA,CAAK,uBAAuB,CAAA,CAAE,WAAA;AAC9B,UAAA,IAAA,CAAK,gBAAA,GAAmB,GAAA;AACxB,UAAA,IAAA,CAAK,mBAAA,GAAsB,sBAAsB,CAAC,CAAA;AAClD,UAAA,IAAA,CAAK,0BAAA,GAA6B,GAAA;AAClC,UAAA;AAAA,QACF;AACA,QAAA,MAAM,YAAA,GAAe,CAAA,CAAE,WAAA,KAAgB,IAAA,CAAK,oBAAA;AAC5C,QAAA,MAAM,MAAA,GAAS,sBAAsB,CAAC,CAAA;AACtC,QAAA,MAAM,cAAA,GAAiB,SAAS,IAAA,CAAK,mBAAA;AAErC,QAAA,MAAM,SAAS,oBAAA,CAAqB;AAAA,UAClC,aAAA;AAAA,UACA,YAAA;AAAA,UACA,cAAA;AAAA,UACA,GAAA;AAAA,UACA,kBAAkB,IAAA,CAAK,gBAAA;AAAA,UACvB,uBAAuB,IAAA,CAAK;AAAA,SAC7B,CAAA;AAED,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,IAAA,CAAK,uBAAuB,CAAA,CAAE,WAAA;AAC9B,UAAA,IAAA,CAAK,gBAAA,GAAmB,GAAA;AAAA,QAC1B;AACA,QAAA,IAAI,cAAA,EAAgB;AAClB,UAAA,IAAA,CAAK,mBAAA,GAAsB,MAAA;AAC3B,UAAA,IAAA,CAAK,0BAAA,GAA6B,GAAA;AAAA,QACpC;AAEA,QAAA,IAAI,OAAO,QAAA,EAAU;AACnB,UAAA,MAAM,MAAA,GAAS,MAAA,CAAO,IAAA,KAAS,YAAA,GAC3B,GAAG,QAAQ,CAAA,4BAAA,EAA+B,CAAA,CAAE,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,CAAA,GAClE,GAAG,QAAQ,CAAA,0HAAA,CAAA;AACf,UAAA,KAAK,IAAA,CAAK,SAAS,MAAM,CAAA;AAAA,QAC3B;AAAA,MACF,GAAG,GAAI,CAAA;AAGP,MAAA,MAAM,UAAU,MAAM;AACpB,QAAA,KAAK,IAAA,CAAK,QAAA;AAAA,UACR,CAAA,EAAG,QAAQ,CAAA,iBAAA,EAAoB,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA,EAAO,WAAW,SAAS,CAAA;AAAA,SAChF;AAAA,MACF,CAAA;AACA,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,gBAAA,CAAiB,OAAA,EAAS,SAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AACrE,MAAA,IAAA,CAAK,aAAA,GAAgB,OAAA;AAAA,IACvB;AAAA,EAEF;AAAA,EAEQ,eAAA,GAAwB;AAC9B,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,aAAA,CAAc,KAAK,UAAU,CAAA;AAC7B,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,IACpB;AACA,IAAA,IAAI,KAAK,aAAA,EAAe;AACtB,MAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,mBAAA,CAAoB,OAAA,EAAS,KAAK,aAAa,CAAA;AACnE,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,MAAM,WAAA,CAAY,QAAA,EAAwB,MAAA,EAAgC;AACxE,IAAA,IAAI,CAAC,KAAK,YAAA,EAAc,MAAM,IAAI,aAAA,CAAc,oBAAA,EAAsB,uFAAkF,oFAAoF,CAAA;AAC5O,IAAA,IAAI,IAAA,CAAK,OAAA,EAAS,QAAA,KAAa,QAAA,EAAU;AAEzC,IAAA,IAAA,CAAK,gBAAA,GAAmB,KAAK,gBAAA,CAAiB,IAAA;AAAA,MAAK,MACjD,IAAA,CAAK,aAAA,CAAc,QAAA,EAAU,MAAM;AAAA,KACrC;AACA,IAAA,MAAM,IAAA,CAAK,gBAAA;AAAA,EACb;AAAA,EAEA,MAAc,aAAA,CAAc,QAAA,EAAwB,MAAA,EAAgC;AAClF,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,OAAA,EAAS,cAAA,EAAe,IAAK,CAAA;AACtD,IAAA,MAAM,aAAa,IAAA,CAAK,OAAA,GAAU,CAAC,IAAA,CAAK,OAAA,CAAQ,OAAO,MAAA,GAAS,KAAA;AAChE,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,OAAA,EAAS,QAAA,IAAY,QAAA;AAC/C,IAAA,MAAM,YAAA,GAAe,MAAA,IAAU,CAAA,iBAAA,EAAoB,QAAQ,CAAA,CAAA;AAE3D,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,gBAAA,EAAkB;AAAA,MAClC,IAAA,EAAM,YAAA;AAAA,MACN,EAAA,EAAI,QAAA;AAAA,MACJ,MAAA,EAAQ,YAAA;AAAA,MACR;AAAA,KACD,CAAA;AACD,IAAA,IAAA,CAAK,IAAA,CAAK,oBAAA,CAAqB,QAAA,EAAU,YAAY,CAAA;AAErD,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAI;AAAE,QAAA,MAAM,IAAA,CAAK,QAAQ,OAAA,EAAQ;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAC3D,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,IACjB;AAEA,IAAA,MAAM,SAAS,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,IAAA,CAAK,cAAe,QAAQ,CAAA;AACjE,IAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,KAAA,CAAM,CAAA,kCAAA,EAAqC,QAAQ,CAAA,CAAA,CAAG,CAAA;AAE7E,IAAA,IAAA,CAAK,OAAA,GAAU,MAAM,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,cAAe,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAA;AAE3F,IAAA,IAAA,CAAK,OAAA,CAAQ,WAAW,UAAA,EAAY;AAAA,MAClC,QAAA;AAAA,MACA,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,IAAA,CAAK,OAAA,CAAQ,YAAA,GAAe,CAAC,WAAA,KAAgB;AAC3C,MAAA,KAAK,IAAA,CAAK,SAAS,WAAW,CAAA;AAAA,IAChC,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAEtB,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA;AACnC,MAAA,IAAI,UAAA,EAAY,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAK;AAAA,IAC1C,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,IAAA,CAAK,gEAAgE,GAAG,CAAA;AAAA,IAClF;AAAA,EACF;AAAA;AAAA,EAIQ,mBAAA,GAA4B;AAClC,IAAA,IAAA,CAAK,kBAAA,GAAqB,YAAY,MAAM;AAC1C,MAAA,MAAM,IAAI,IAAA,CAAK,OAAA,EAAS,gBAAe,IAAK,IAAA,CAAK,QAAQ,MAAA,CAAO,WAAA;AAChE,MAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,YAAA,EAAc,EAAE,WAAA,EAAa,GAAG,CAAA;AAAA,IACpD,GAAG,GAAG,CAAA;AAAA,EACR;AAAA;AAAA;AAAA,EAKA,EAAA,CAA8B,OAAU,EAAA,EAA6C;AACnF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,KAAA,EAAO,EAAE,CAAA;AAAA,EAClC;AAAA;AAAA,EAGA,GAAA,CAA+B,OAAU,EAAA,EAAuC;AAC9E,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,EAAE,CAAA;AAAA,EAC5B;AAAA;AAAA,EAGA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS,MAAM,IAAI,aAAA,CAAc,oBAAA,EAAsB,uFAAkF,oFAAoF,CAAA;AACvO,IAAA,IAAA,CAAK,UAAA,GAAa,MAAA;AAClB,IAAA,IAAA,CAAK,uBAAA,GAA0B,KAAA;AAC/B,IAAA,MAAM,IAAA,CAAK,QAAQ,IAAA,EAAK;AAAA,EAC1B;AAAA;AAAA,EAGA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,OAAA;AAClB,IAAA,IAAA,CAAK,uBAAA,GAA0B,KAAA;AAC/B,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBAAA,GAA2B;AACjC,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACnB,IAAA,MAAM,SAAS,sBAAA,CAAuB;AAAA,MACpC,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,gBAAA,EAAkB,CAAC,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,MAAA;AAAA,MACvC,yBAAyB,IAAA,CAAK;AAAA,KAC/B,CAAA;AACD,IAAA,IAAI,WAAW,OAAA,EAAS;AACtB,MAAA,IAAA,CAAK,uBAAA,GAA0B,IAAA;AAC/B,MAAA,GAAA,CAAI,IAAA,CAAK,cAAc,+BAA0B,CAAA;AACjD,MAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,IACrB,CAAA,MAAA,IAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,IAAA,CAAK,uBAAA,GAA0B,KAAA;AAC/B,MAAA,GAAA,CAAI,IAAA,CAAK,cAAc,kCAA6B,CAAA;AACpD,MAAA,KAAK,KAAK,OAAA,CAAQ,IAAA,EAAK,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AAEtC,QAAA,OAAA,CAAQ,IAAA,CAAK,mDAAmD,GAAG,CAAA;AAAA,MACrE,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAK,IAAA,EAA6B;AACtC,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS,MAAM,IAAI,aAAA,CAAc,oBAAA,EAAsB,uFAAkF,oFAAoF,CAAA;AACvO,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA;AAAA,EAC9B;AAAA;AAAA,EAGA,MAAM,cAAc,EAAA,EAA2B;AAC7C,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS,MAAM,IAAI,aAAA,CAAc,oBAAA,EAAsB,uFAAkF,oFAAoF,CAAA;AACvO,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,EAAE,CAAA;AAAA,EACrC;AAAA;AAAA,EAGA,MAAM,iBAAiB,EAAA,EAAkC;AACvD,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS,MAAM,IAAI,aAAA,CAAc,oBAAA,EAAsB,uFAAkF,oFAAoF,CAAA;AACvO,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,gBAAA,CAAiB,EAAE,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,cAAA,GAAsC;AACpC,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,OAAA,CAAQ,iBAAiB,CAAA;AAAA,IACxD;AACA,IAAA,OAAO,IAAA,CAAK,KAAK,QAAA,EAAS;AAAA,EAC5B;AAAA;AAAA,EAGA,WAAA,GAAsB;AACpB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,QAAA,EAAS,CAAE,QAAA;AACtC,IAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,OAAO,QAAA,CAAS,QAAQ,GAAG,OAAO,QAAA;AACtE,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,QAAA;AACtC,IAAA,OAAO,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,GAAI,SAAA,GAAY,GAAA;AAAA,EAClD;AAAA;AAAA,EAGA,cAAA,GAAyB;AACvB,IAAA,OAAO,KAAK,OAAA,EAAS,cAAA,MAAoB,IAAA,CAAK,OAAA,CAAQ,OAAO,WAAA,IAAe,CAAA;AAAA,EAC9E;AAAA;AAAA,EAGA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,KAAK,kBAAA,EAAoB;AAC3B,MAAA,aAAA,CAAc,KAAK,kBAAkB,CAAA;AACrC,MAAA,IAAA,CAAK,kBAAA,GAAqB,IAAA;AAAA,IAC5B;AACA,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,IAAI,KAAK,aAAA,EAAe;AACtB,MAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,mBAAA,CAAoB,OAAA,EAAS,KAAK,aAAa,CAAA;AACnE,MAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AAAA,IACvB;AACA,IAAA,IAAI,KAAK,kBAAA,EAAoB;AAC3B,MAAA,QAAA,CAAS,mBAAA,CAAoB,kBAAA,EAAoB,IAAA,CAAK,kBAAkB,CAAA;AACxE,MAAA,IAAA,CAAK,kBAAA,GAAqB,IAAA;AAAA,IAC5B;AACA,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,IAAA,CAAK,QAAQ,OAAA,EAAQ;AAC3B,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,IACjB;AAGA,IAAA,IAAA,CAAK,kBAAkB,SAAA,EAAU;AACjC,IAAA,IAAA,CAAK,QAAQ,SAAA,EAAU;AAAA,EACzB;AACF,CAAA;AAEA,eAAsB,aAAa,OAAA,EAAsD;AACvF,EAAA,OAAO,aAAA,CAAc,OAAO,OAAO,CAAA;AACrC;AASO,SAAS,uBAAuB,KAAA,EAKP;AAC9B,EAAA,IAAI,MAAM,MAAA,EAAQ;AAEhB,IAAA,IAAI,KAAA,CAAM,UAAA,KAAe,MAAA,IAAU,KAAA,CAAM,kBAAkB,OAAO,OAAA;AAClE,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAA,CAAM,yBAAyB,OAAO,QAAA;AAC1C,EAAA,OAAO,MAAA;AACT;AAYO,SAAS,oBAAA,CACd,SACA,GAAA,EACgB;AAChB,EAAA,MAAM,OAAA,GAAU,gBAAS,GAAG,CAAA;AAC5B,EAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,OAAA,EAAS,OAAO,CAAA;AAC5C,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,aAAA,IAAiB,oBAAA,CAAqB,OAAO,CAAA;AACvE,EAAA,MAAM,gBAAgB,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,MAAM,OAAO,CAAA;AAC3D,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,GAAA;AAAA,IACP,QAAA,EAAU,OAAA;AAAA,IACV,MAAA,EAAQ,qBAAqB,OAAO,CAAA,uCAAA,CAAA;AAAA,IACpC;AAAA,GACF;AACF;AAEA,SAAS,eAAA,CACP,UACA,OAAA,EACyB;AAEzB,EAAA,IAAI,OAAA,CAAQ,QAAA,KAAa,QAAA,EAAU,OAAO,OAAA,CAAQ,KAAA;AAClD,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,QAAA;AAAY,MAAA,OAAO,QAAA;AAAA,IACxB,KAAK,OAAA;AAAY,MAAA,OAAO,iBAAA;AAAA,IACxB,KAAK,QAAA;AAAY,MAAA,OAAO,kBAAA;AAAA,IACxB,KAAK,UAAA;AAAY,MAAA,OAAO,mBAAA;AAAA;AAE5B;AAEA,SAAS,qBAAqB,QAAA,EAAwC;AACpE,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,QAAA;AAAY,MAAA,OAAO,CAAC,OAAA,EAAS,QAAA,EAAU,UAAU,CAAA;AAAA,IACtD,KAAK,OAAA;AAAY,MAAA,OAAO,CAAC,UAAU,UAAU,CAAA;AAAA,IAC7C,KAAK,QAAA;AAAY,MAAA,OAAO,CAAC,UAAU,CAAA;AAAA,IACnC,KAAK,UAAA;AAAY,MAAA,OAAO,EAAC;AAAA;AAE7B;;;ACtsBA,IAAM,yBAAA,uBAAgC,GAAA,CAAuB;AAAA,EAC3D,MAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAC,CAAA;AAID,IAAM,6BAAa,IAAI,GAAA,CAAa,CAAC,SAAA,EAAW,OAAA,EAAS,MAAM,CAAC,CAAA;AAChE,IAAM,WAAA,GAAuB,SAAA;AAe7B,IAAM,sBAAA,GAAyB;AAAA,EAC7B,WAAA;AAAA,EACA,gBAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,gBAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,gBAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA;AAeA,IAAM,eAAA,GACJ,OAAO,WAAA,KAAgB,WAAA,GACnB,cACC,MAAM;AAAC,CAAA;AASP,IAAM,oBAAA,GAAN,cAAmC,eAAA,CAAgB;AAAA,EACxD,OAAgB,kBAAA,GAAqB;AAAA,IACnC,KAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,aAAA;AAAA,IACA,aAAA;AAAA,IACA,uBAAA;AAAA,IACA,aAAA;AAAA,IACA,gBAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AAAA;AAAA;AAAA,EAKQ,QAAA;AAAA;AAAA,EAGA,OAAA,GAAgC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhC,YAAA,GAAe,CAAA;AAAA;AAAA,EAGf,UAAA,GAAa,KAAA;AAAA;AAAA,EAGb,IAAA,GAAsB,IAAA;AAAA,EACtB,OAAA,GAA6B,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,wBAAA,GAA2B,KAAA;AAAA;AAAA,EAG3B,SAAA,GAAiC,IAAA;AAAA,EACjC,cAAA,GAAuC,IAAA;AAAA,EACvC,eAAiC,EAAC;AAAA;AAAA;AAAA,EAGlC,kBAAuC,EAAC;AAAA;AAAA;AAAA;AAAA,EAIxC,iBAAsC,EAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQvC,UAAA,GAAuF,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUvF,kBAAA,GAAwC,MAAA;AAAA;AAAA;AAAA;AAAA,EAKxC,IAAA,GAAgB,WAAA;AAAA;AAAA;AAAA,EAGhB,QAAA;AAAA;AAAA,EAGA,YAAA,GAA8B,IAAA;AAAA;AAAA,EAE9B,YAAA,GAAe,KAAA;AAAA;AAAA,EAGf,cAAA,GAA0C,IAAA;AAAA;AAAA;AAAA;AAAA,EAK1C,wBAAA,GAAgD,IAAA;AAAA;AAAA;AAAA,EAGhD,kBAAA,GAAqB,KAAA;AAAA;AAAA,EAI7B,WAAA,GAAc;AACZ,IAAA,KAAA,EAAM;AACN,IAAA,MAAM,OAAO,IAAA,CAAK,YAAA,CAAa,EAAE,IAAA,EAAM,QAAQ,CAAA;AAO/C,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC1C,IAAA,KAAA,CAAM,YAAA,CAAa,QAAQ,OAAO,CAAA;AAClC,IAAA,KAAA,CAAM,KAAA,CAAM,OAAA,GAAU,CAAA,sEAAA,EAAyE,WAAW,CAAA,CAAA,CAAA;AAC1G,IAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AACtB,IAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AAEhB,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAC9C,IAAA,IAAA,CAAK,QAAA,CAAS,YAAA,CAAa,MAAA,EAAQ,OAAO,CAAA;AAC1C,IAAA,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,OAAA,GAAU,CAAA,oFAAA,EAAuF,WAAW,CAAA,EAAA,CAAA;AAChI,IAAA,IAAA,CAAK,SAAS,WAAA,GAAc,IAAA;AAC5B,IAAA,KAAA,CAAM,WAAA,CAAY,KAAK,QAAQ,CAAA;AAO/B,IAAA,IAAA,CAAK,QAAA,CAAS,gBAAA,CAAiB,UAAA,EAAY,MAAM;AAC/C,MAAA,IAAI,KAAK,UAAA,EAAY;AACrB,MAAA,IAAA,CAAK,UAAU,UAAA,EAAY,EAAE,UAAU,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA;AAAA,IACjE,CAAC,CAAA;AAMD,IAAA,KAAA,MAAW,aAAa,sBAAA,EAAwB;AAC9C,MAAA,IAAA,CAAK,QAAA,CAAS,gBAAA,CAAiB,SAAA,EAAW,MAAM;AAC9C,QAAA,IAAI,KAAK,UAAA,EAAY;AACrB,QAAA,IAAA,CAAK,aAAA,CAAc,IAAI,KAAA,CAAM,SAAA,EAAW,EAAE,OAAA,EAAS,KAAA,EAAO,CAAC,CAAA;AAAA,MAC7D,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,iBAAA,GAA0B;AACxB,IAAA,IAAI,KAAK,UAAA,EAAY;AAGrB,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,IAAI,CAAC,KAAK,cAAA,EAAgB;AACxB,MAAA,IAAA,CAAK,iBAAiB,IAAI,gBAAA,CAAiB,MAAM,IAAA,CAAK,iBAAiB,CAAA;AACvE,MAAA,IAAA,CAAK,cAAA,CAAe,QAAQ,IAAA,EAAM,EAAE,WAAW,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA;AAAA,IACvE;AACA,IAAA,IAAI,CAAC,KAAK,wBAAA,EAA0B;AAClC,MAAA,IAAA,CAAK,wBAAA,GAA2B,MAAM,IAAA,CAAK,mBAAA,EAAoB;AAC/D,MAAA,QAAA,CAAS,gBAAA,CAAiB,kBAAA,EAAoB,IAAA,CAAK,wBAAwB,CAAA;AAAA,IAC7E;AAGA,IAAA,MAAM,MAAA,GAAS,KAAK,aAAA,EAAc;AAClC,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,KAAK,IAAA,CAAK,WAAW,MAAM,CAAA;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,oBAAA,GAA6B;AAC3B,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,IAAI,KAAK,cAAA,EAAgB;AACvB,MAAA,IAAA,CAAK,eAAe,UAAA,EAAW;AAC/B,MAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,IACxB;AACA,IAAA,IAAI,KAAK,wBAAA,EAA0B;AACjC,MAAA,QAAA,CAAS,mBAAA,CAAoB,kBAAA,EAAoB,IAAA,CAAK,wBAAwB,CAAA;AAC9E,MAAA,IAAA,CAAK,wBAAA,GAA2B,IAAA;AAAA,IAClC;AAGA,IAAA,IAAA,CAAK,uBAAA,EAAwB;AAK7B,IAAA,IAAA,CAAK,YAAA,EAAA;AACL,IAAA,KAAK,KAAK,SAAA,EAAU;AAAA,EACtB;AAAA,EAEA,wBAAA,CAAyB,IAAA,EAAc,SAAA,EAA0B,QAAA,EAA+B;AAC9F,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,QAAQ,IAAA;AAAM,MACZ,KAAK,KAAA;AACH,QAAA,IAAI,KAAK,wBAAA,EAA0B;AACnC,QAAA,IAAA,CAAK,gBAAgB,QAAQ,CAAA;AAC7B,QAAA;AAAA,MACF,KAAK,UAAA;AAAA,MACL,KAAK,OAAA;AAAA,MACL,KAAK,MAAA;AAAA,MACL,KAAK,aAAA;AAAA,MACL,KAAK,uBAAA;AAEH,QAAA,IAAI,QAAA,IAAY,IAAA,EAAM,IAAA,CAAK,QAAA,CAAS,gBAAgB,IAAI,CAAA;AAAA,aACnD,IAAA,CAAK,QAAA,CAAS,YAAA,CAAa,IAAA,EAAM,QAAQ,CAAA;AAC9C,QAAA;AAAA,MACF,KAAK,SAAA;AAAA,MACL,KAAK,QAAA;AAAA,MACL,KAAK,aAAA;AACH,QAAA,IAAI,QAAA,IAAY,IAAA,EAAM,IAAA,CAAK,QAAA,CAAS,gBAAgB,IAAI,CAAA;AAAA,aACnD,IAAA,CAAK,QAAA,CAAS,YAAA,CAAa,IAAA,EAAM,QAAQ,CAAA;AAC9C,QAAA;AAAA,MACF,KAAK,aAAA;AAEH,QAAA;AAAA,MACF,KAAK,gBAAA;AACH,QAAA,IAAI,QAAA,IAAY,yBAAA,CAA0B,GAAA,CAAI,QAA6B,CAAA,EAAG;AAC5E,UAAA,IAAA,CAAK,kBAAA,GAAqB,QAAA;AAAA,QAC5B,CAAA,MAAO;AACL,UAAA,IAAA,CAAK,kBAAA,GAAqB,MAAA;AAAA,QAC5B;AACA,QAAA;AAAA,MACF,KAAK,KAAA,EAAO;AACV,QAAA,MAAM,OAAgB,QAAA,IAAY,UAAA,CAAW,GAAA,CAAI,QAAmB,IAC/D,QAAA,GACD,WAAA;AACJ,QAAA,IAAI,IAAA,KAAS,KAAK,IAAA,EAAM;AACxB,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,QAAA,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,WAAA,CAAY,gBAAA,EAAkB,IAAI,CAAA;AACtD,QAAA,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa,EAAE,GAAA,EAAK,MAAM,CAAA;AACzC,QAAA;AAAA,MACF;AAAA;AACF,EACF;AAAA;AAAA;AAAA,EAKQ,aAAA,GAAmC;AACzC,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,IAAA,EAAM,OAAO,IAAA,CAAK,OAAA;AACtC,IAAA,IAAI,IAAA,CAAK,IAAA,IAAQ,IAAA,EAAM,OAAO,IAAA,CAAK,IAAA;AACnC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYQ,eAAA,GAAwB;AAE9B,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,gBAAA,CAAiB,OAAO,CAAA;AACvD,IAAA,KAAA,MAAW,KAAK,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA,IAAK,MAAA,EAAO;AAM/C,IAAA,IAAA,CAAK,iBAAiB,EAAC;AACvB,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,KAAA,MAAW,KAAA,IAAS,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC7C,MAAA,IAAI,KAAA,CAAM,YAAY,OAAA,EAAS;AAC7B,QAAA,MAAM,KAAA,GAAQ,KAAA;AACd,QAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,SAAA,CAAU,IAAI,CAAA;AAClC,QAAA,IAAA,CAAK,QAAA,CAAS,YAAY,KAAK,CAAA;AAC/B,QAAA,MAAM,GAAA,GAAM,KAAA,CAAM,YAAA,CAAa,KAAK,CAAA,IAAK,MAAA;AACzC,QAAA,MAAM,SAAS,GAAA,EAAK,WAAA,GAAc,QAAA,CAAS,MAAM,IAAI,KAAA,GAAQ,KAAA;AAC7D,QAAA,IAAA,CAAK,eAAe,IAAA,CAAK;AAAA,UACvB,IAAI,GAAA,GAAQ,OAAA;AAAA,UACZ,MAAA;AAAA,UACA,UAAU,KAAA,CAAM,OAAA,IAAW,KAAA,CAAM,YAAA,CAAa,OAAO,CAAA,IAAK,MAAA;AAAA,UAC1D,UAAA,EAAY;AAAA,SACb,CAAA;AACD,QAAA,OAAA,EAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAA,CAAK,UAAU,cAAA,EAAgB;AAAA,MAC7B,aAAa,IAAA,CAAK,YAAA;AAAA,MAClB,gBAAgB,IAAA,CAAK;AAAA,KACtB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA,EAIQ,gBAAgB,KAAA,EAA4B;AAElD,IAAA,IAAI,KAAA,KAAU,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,WAAW,IAAA,EAAM;AACjD,IAAA,IAAA,CAAK,IAAA,GAAO,KAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,EACxB;AAAA;AAAA,EAGQ,gBAAA,GAAyB;AAC/B,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,MAAM,MAAA,GAAS,KAAK,aAAA,EAAc;AAClC,IAAA,IAAI,UAAU,IAAA,EAAM;AAElB,MAAA,IAAA,CAAK,YAAA,EAAA;AACL,MAAA,KAAK,KAAK,SAAA,EAAU;AACpB,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,KAAK,IAAA,CAAK,WAAW,MAAM,CAAA;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA,EAIA,MAAc,WAAW,MAAA,EAAmC;AAC1D,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,MAAM,EAAA,GAAK,EAAE,IAAA,CAAK,YAAA;AAKlB,IAAA,MAAM,IAAA,CAAK,UAAU,EAAE,CAAA;AACvB,IAAA,IAAI,EAAA,KAAO,IAAA,CAAK,YAAA,IAAgB,IAAA,CAAK,UAAA,EAAY;AAEjD,IAAA,IAAA,CAAK,SAAA,CAAU,WAAA,EAAa,EAAE,CAAA;AAE9B,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,MAAM,YAAA,CAAa;AAAA,QAC1B,MAAA;AAAA,QACA,QAAQ,IAAA,CAAK,QAAA;AAAA;AAAA;AAAA;AAAA,QAIb,GAAI,KAAK,kBAAA,KAAuB,MAAA,GAC5B,EAAE,eAAA,EAAiB,IAAA,CAAK,kBAAA,EAAmB,GAC3C,EAAC;AAAA,QACL,GAAI,KAAK,UAAA,GAAa,EAAE,WAAW,IAAA,CAAK,UAAA,KAAe;AAAC,OACzD,CAAA;AAAA,IACH,SAAS,GAAA,EAAK;AAEZ,MAAA,IAAI,EAAA,KAAO,IAAA,CAAK,YAAA,IAAgB,IAAA,CAAK,UAAA,EAAY;AACjD,MAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AACvB,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,OAAO,IAAA,CAAK,YAAA,IAAgB,KAAK,UAAA,IAAc,CAAC,KAAK,WAAA,EAAa;AACpE,MAAA,IAAI;AAAE,QAAA,MAAM,OAAO,OAAA,EAAQ;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AACrD,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AAKf,IAAA,IAAA,CAAK,eAAA,EAAgB;AAIrB,IAAA,MAAA,CAAO,GAAG,UAAA,EAAY,CAAC,EAAE,QAAA,EAAU,QAAO,KAAM;AAE9C,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,cAAA,EAAe,CAAE,aAAA;AACpC,MAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,MAAA,IAAA,CAAK,cAAA,GAAiB,GAAA,KAAQ,SAAA,GAAY,IAAA,GAAO,GAAA;AACjD,MAAA,IAAA,CAAK,UAAU,gBAAA,EAAkB;AAAA,QAC/B,QAAA;AAAA,QACA,eAAe,IAAA,CAAK,cAAA;AAAA,QACpB,MAAA;AAAA,QACA,WAAA,EAAa,OAAO,cAAA;AAAe,OACpC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,kBAAkB,CAAC,EAAE,MAAM,EAAA,EAAI,MAAA,EAAQ,aAAY,KAAM;AACjE,MAAA,IAAA,CAAK,UAAU,gBAAA,EAAkB;AAAA,QAC/B,IAAA;AAAA,QACA,QAAA,EAAU,EAAA;AAAA,QACV,aAAA,EAAe,OAAO,cAAA,EAAe,CAAE,kBAAkB,SAAA,GAAY,IAAA,GAAO,MAAA,CAAO,cAAA,EAAe,CAAE,aAAA;AAAA,QACpG,MAAA;AAAA,QACA,WAAA;AAAA,QACA,WAAA,EAAa,OAAO,cAAA;AAAe,OACpC,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,UAAU,CAAC,EAAE,OAAO,EAAA,EAAI,KAAA,EAAO,UAAS,KAAM;AACtD,MAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AACpB,MAAA,IAAA,CAAK,eAAA,GAAkB,QAAA;AACvB,MAAA,IAAA,CAAK,UAAU,cAAA,EAAgB;AAAA,QAC7B,WAAA,EAAa,KAAA;AAAA,QACb,cAAA,EAAgB;AAAA,OACjB,CAAA;AAAA,IACH,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AACjC,MAAA,IAAA,CAAK,eAAe,GAAG,CAAA;AAAA,IACzB,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,YAAA,EAAc,CAAC,EAAE,aAAY,KAAM;AAC3C,MAAA,IAAA,CAAK,SAAA,CAAU,YAAA,EAAc,EAAE,WAAA,EAAa,CAAA;AAAA,IAC9C,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,SAAS,MAAM;AACvB,MAAA,IAAA,CAAK,SAAA,CAAU,OAAA,EAAS,EAAE,CAAA;AAAA,IAC5B,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,SAAS,MAAM;AACvB,MAAA,IAAA,CAAK,UAAU,OAAA,EAAS,EAAE,aAAa,MAAA,CAAO,cAAA,IAAkB,CAAA;AAEhE,MAAA,IAAI,IAAA,CAAK,gBAAgB,IAAA,EAAM;AAC7B,QAAA,MAAM,IAAI,IAAA,CAAK,YAAA;AACf,QAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AACpB,QAAA,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,CAAE,MAAM,MAAM;AAAA,QAAe,CAAC,CAAA;AAAA,MAClD;AAEA,MAAA,IAAI,KAAK,YAAA,EAAc;AACrB,QAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AACpB,QAAA,KAAK,MAAA,CAAO,IAAA,EAAK,CAAE,KAAA,CAAM,MAAM;AAAA,QAAyC,CAAC,CAAA;AAAA,MAC3E,CAAA,MAAA,IAAW,KAAK,QAAA,EAAU;AACxB,QAAA,KAAK,MAAA,CAAO,IAAA,EAAK,CAAE,KAAA,CAAM,MAAM;AAAA,QAAe,CAAC,CAAA;AAAA,MACjD;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,UAAU,kBAAA,EAA4C;AAClE,IAAA,IAAI,sBAAsB,IAAA,EAAM;AAI9B,MAAA,IAAA,CAAK,YAAA,EAAA;AAAA,IACP;AACA,IAAA,MAAM,SAAS,IAAA,CAAK,OAAA;AACpB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AACtB,IAAA,IAAA,CAAK,eAAe,EAAC;AACrB,IAAA,IAAA,CAAK,kBAAkB,EAAC;AACxB,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAI;AAAE,QAAA,MAAM,OAAO,OAAA,EAAQ;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IACvD;AAAA,EACF;AAAA;AAAA,EAIA,IAAI,GAAA,GAAqB;AACvB,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,EACd;AAAA,EAEA,IAAI,IAAI,KAAA,EAAsB;AAC5B,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,IAAA,CAAK,gBAAgB,KAAK,CAAA;AAAA,IAC5B,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,YAAA,CAAa,OAAO,KAAK,CAAA;AAAA,IAChC;AAAA,EAEF;AAAA,EAEA,IAAI,MAAA,GAA4B;AAC9B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAI,OAAO,KAAA,EAA0B;AAEnC,IAAA,IAAI,KAAA,KAAU,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,QAAQ,IAAA,EAAM;AACjD,IAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AACf,IAAA,IAAI,SAAS,IAAA,EAAM;AAGjB,MAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,MAAA,IAAI,IAAA,CAAK,YAAA,CAAa,KAAK,CAAA,EAAG;AAC5B,QAAA,IAAA,CAAK,wBAAA,GAA2B,IAAA;AAChC,QAAA,IAAI;AACF,UAAA,IAAA,CAAK,gBAAgB,KAAK,CAAA;AAAA,QAC5B,CAAA,SAAE;AACA,UAAA,IAAA,CAAK,wBAAA,GAA2B,KAAA;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,EACxB;AAAA,EAEA,IAAI,QAAA,GAAoB;AACtB,IAAA,OAAO,IAAA,CAAK,aAAa,UAAU,CAAA;AAAA,EACrC;AAAA,EAEA,IAAI,SAAS,KAAA,EAAgB;AAC3B,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,UAAA,EAAY,EAAE,CAAA;AAAA,SACtC,IAAA,CAAK,gBAAgB,UAAU,CAAA;AAAA,EACtC;AAAA,EAEA,IAAI,KAAA,GAAiB;AAInB,IAAA,OAAO,KAAK,QAAA,CAAS,KAAA;AAAA,EACvB;AAAA,EAEA,IAAI,MAAM,KAAA,EAAgB;AAMxB,IAAA,IAAA,CAAK,SAAS,KAAA,GAAQ,KAAA;AAGtB,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,OAAA,EAAS,EAAE,CAAA;AAAA,SACnC,IAAA,CAAK,gBAAgB,OAAO,CAAA;AAAA,EACnC;AAAA,EAEA,IAAI,IAAA,GAAgB;AAClB,IAAA,OAAO,IAAA,CAAK,aAAa,MAAM,CAAA;AAAA,EACjC;AAAA,EAEA,IAAI,KAAK,KAAA,EAAgB;AACvB,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ,EAAE,CAAA;AAAA,SAClC,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAAA,EAClC;AAAA,EAEA,IAAI,OAAA,GAAwC;AAC1C,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,YAAA,CAAa,SAAS,CAAA;AACrC,IAAA,OAAO,MAAM,MAAA,IAAU,CAAA,KAAM,UAAA,IAAc,CAAA,KAAM,SAAS,CAAA,GAAI,MAAA;AAAA,EAChE;AAAA,EAEA,IAAI,QAAQ,KAAA,EAAqC;AAC/C,IAAA,IAAA,CAAK,YAAA,CAAa,WAAW,KAAK,CAAA;AAAA,EACpC;AAAA,EAEA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,IAAA,CAAK,aAAa,aAAa,CAAA;AAAA,EACxC;AAAA,EAEA,IAAI,YAAY,KAAA,EAAgB;AAC9B,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,aAAA,EAAe,EAAE,CAAA;AAAA,SACzC,IAAA,CAAK,gBAAgB,aAAa,CAAA;AAAA,EACzC;AAAA,EAEA,IAAI,GAAA,GAAe;AACjB,IAAA,OAAO,IAAA,CAAK,IAAA;AAAA,EACd;AAAA,EAEA,IAAI,IAAI,KAAA,EAAgB;AACtB,IAAA,IAAI,CAAC,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA,EAAG;AAC5B,IAAA,IAAA,CAAK,YAAA,CAAa,OAAO,KAAK,CAAA;AAAA,EAChC;AAAA,EAEA,IAAI,iBAAA,GAAuC;AACzC,IAAA,OAAO,IAAA,CAAK,kBAAA;AAAA,EACd;AAAA,EAEA,IAAI,kBAAkB,KAAA,EAA0B;AAC9C,IAAA,IAAI,yBAAA,CAA0B,GAAA,CAAI,KAAK,CAAA,EAAG;AACxC,MAAA,IAAA,CAAK,YAAA,CAAa,kBAAkB,KAAK,CAAA;AAAA,IAC3C;AAAA,EACF;AAAA,EAEA,IAAI,WAAA,GAAsB;AACxB,IAAA,OAAO,IAAA,CAAK,OAAA,EAAS,cAAA,EAAe,IAAK,CAAA;AAAA,EAC3C;AAAA,EAEA,IAAI,YAAY,KAAA,EAAe;AAC7B,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,KAAK,KAAK,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,CAAE,MAAM,MAAM;AAAA,MAAe,CAAC,CAAA;AAAA,IAC5D,CAAA,MAAO;AAEL,MAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,IAAI,QAAA,GAAmB;AACrB,IAAA,OAAO,IAAA,CAAK,OAAA,EAAS,WAAA,EAAY,IAAK,GAAA;AAAA,EACxC;AAAA,EAEA,IAAI,MAAA,GAAkB;AACpB,IAAA,OAAO,KAAK,QAAA,CAAS,MAAA;AAAA,EACvB;AAAA,EAEA,IAAI,KAAA,GAAiB;AACnB,IAAA,OAAO,KAAK,QAAA,CAAS,KAAA;AAAA,EACvB;AAAA,EAEA,IAAI,UAAA,GAAqB;AACvB,IAAA,OAAO,KAAK,QAAA,CAAS,UAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,IAAI,QAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,QAAA,CAAS,QAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,MAAA,GAAiB;AACnB,IAAA,OAAO,KAAK,QAAA,CAAS,MAAA;AAAA,EACvB;AAAA,EACA,IAAI,OAAO,KAAA,EAAe;AACxB,IAAA,IAAI,SAAS,IAAA,IAAQ,KAAA,KAAU,EAAA,EAAI,IAAA,CAAK,gBAAgB,QAAQ,CAAA;AAAA,SAC3D,IAAA,CAAK,YAAA,CAAa,QAAA,EAAU,KAAK,CAAA;AAAA,EACxC;AAAA,EAEA,IAAI,MAAA,GAAiB;AACnB,IAAA,OAAO,KAAK,QAAA,CAAS,MAAA;AAAA,EACvB;AAAA,EACA,IAAI,OAAO,KAAA,EAAe;AACxB,IAAA,IAAA,CAAK,SAAS,MAAA,GAAS,KAAA;AAAA,EACzB;AAAA,EAEA,IAAI,YAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,QAAA,CAAS,YAAA;AAAA,EACvB;AAAA,EACA,IAAI,aAAa,KAAA,EAAe;AAC9B,IAAA,IAAA,CAAK,SAAS,YAAA,GAAe,KAAA;AAAA,EAC/B;AAAA,EAEA,IAAI,UAAA,GAAqB;AACvB,IAAA,OAAO,KAAK,QAAA,CAAS,UAAA;AAAA,EACvB;AAAA,EAEA,IAAI,WAAA,GAAsB;AACxB,IAAA,OAAO,KAAK,QAAA,CAAS,WAAA;AAAA,EACvB;AAAA,EAEA,IAAI,MAAA,GAAqB;AACvB,IAAA,OAAO,KAAK,QAAA,CAAS,MAAA;AAAA,EACvB;AAAA,EAEA,IAAI,QAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,QAAA,CAAS,QAAA;AAAA,EACvB;AAAA,EAEA,IAAI,WAAA,GAA6B;AAC/B,IAAA,OAAO,KAAK,QAAA,CAAS,WAAA;AAAA,EACvB;AAAA,EACA,IAAI,YAAY,KAAA,EAAsB;AACpC,IAAA,IAAI,KAAA,IAAS,IAAA,EAAM,IAAA,CAAK,eAAA,CAAgB,aAAa,CAAA;AAAA,SAChD,IAAA,CAAK,YAAA,CAAa,aAAA,EAAe,KAAK,CAAA;AAAA,EAC7C;AAAA,EAEA,IAAI,qBAAA,GAAiC;AACnC,IAAA,OAAO,KAAK,QAAA,CAAS,qBAAA;AAAA,EACvB;AAAA,EACA,IAAI,sBAAsB,KAAA,EAAgB;AACxC,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,uBAAA,EAAyB,EAAE,CAAA;AAAA,SACnD,IAAA,CAAK,gBAAgB,uBAAuB,CAAA;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,QAAA,EAAqC;AAC/C,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,WAAA,CAAY,QAAQ,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,IAAI,YAAA,GAAiC;AACnC,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEA,IAAI,QAAA,GAAgC;AAClC,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,IAAI,aAAA,GAAsC;AACxC,IAAA,OAAO,IAAA,CAAK,cAAA;AAAA,EACd;AAAA,EAEA,IAAI,MAAA,GAA+B;AACjC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAI,WAAA,GAAgC;AAClC,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA,EAEA,IAAI,cAAA,GAAsC;AAKxC,IAAA,OAAO,IAAA,CAAK,cAAA,CAAe,MAAA,KAAW,CAAA,GAClC,IAAA,CAAK,eAAA,GACL,CAAC,GAAG,IAAA,CAAK,eAAA,EAAiB,GAAG,IAAA,CAAK,cAAc,CAAA;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,IAAI,SAAA,GAAsF;AACxF,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA,EAEA,IAAI,UAAU,KAAA,EAAiF;AAC7F,IAAA,IAAA,CAAK,UAAA,GAAa,KAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,QAAA,EAAqF;AACrG,IAAA,MAAM,EAAE,oBAAA,EAAAC,qBAAAA,EAAqB,GAAI,MAAM,OAAO,yBAAuB,CAAA;AACrE,IAAA,MAAM,MAAA,GAAS,SAAS,MAAA,KAAW,QAAA,CAAS,IAAI,QAAA,CAAS,MAAM,IAAI,KAAA,GAAQ,KAAA,CAAA;AAC3E,IAAA,MAAM,KAAA,GAAQ;AAAA,MACZ,EAAA,EAAI,KAAK,eAAA,CAAgB,MAAA;AAAA,MACzB,MAAA;AAAA,MACA,UAAU,QAAA,CAAS,QAAA;AAAA,MACnB,YAAY,QAAA,CAAS;AAAA,KACvB;AACA,IAAA,IAAA,CAAK,eAAA,CAAgB,KAAK,KAAK,CAAA;AAE/B,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,+BAAA,EAAkC,KAAA,CAAM,EAAE,CAAA,QAAA,EAAW,MAAM,CAAA,MAAA,EAAS,QAAA,CAAS,QAAA,IAAY,GAAG,CAAA,CAAE,CAAA;AAC1G,IAAA,MAAMA,qBAAAA;AAAA,MACJ,IAAA,CAAK,QAAA;AAAA,MACL,IAAA,CAAK,eAAA;AAAA,MACL,MAAA;AAAA,MACA,CAAC,KAAK,CAAA,KAAM;AAEV,QAAA,OAAA,CAAQ,KAAK,CAAA,yBAAA,EAA4B,CAAA,CAAE,EAAE,CAAA,SAAA,EAAY,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,MACxE;AAAA,KACF;AAKA,IAAA,MAAM,UAAA,GAAa,KAAK,QAAA,CAAS,UAAA;AACjC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,MAAA,IAAI,UAAA,CAAW,CAAC,CAAA,CAAE,KAAA,MAAW,SAAS,QAAA,IAAY,CAAA,SAAA,EAAY,KAAA,CAAM,EAAE,CAAA,CAAA,CAAA,EAAK;AACzE,QAAA,UAAA,CAAW,CAAC,EAAE,IAAA,GAAO,SAAA;AAErB,QAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,kCAAA,EAAqC,CAAC,CAAA,cAAA,CAAgB,CAAA;AAClE,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,UAAU,cAAA,EAAgB;AAAA,MAC7B,aAAa,IAAA,CAAK,YAAA;AAAA,MAClB,gBAAgB,IAAA,CAAK;AAAA,KACtB,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,iBAAA,GAA6B;AAC/B,IAAA,OAAO,IAAA,CAAK,aAAa,qBAAqB,CAAA;AAAA,EAChD;AAAA,EAEA,IAAI,kBAAkB,KAAA,EAAgB;AACpC,IAAA,IAAI,KAAA,EAAO,IAAA,CAAK,YAAA,CAAa,qBAAA,EAAuB,EAAE,CAAA;AAAA,SACjD,IAAA,CAAK,gBAAgB,qBAAqB,CAAA;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAA,GAA4B;AAClC,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,MAAM,OAAO,QAAA,CAAS,iBAAA;AACtB,IAAA,MAAM,aAAA,GAAgB,IAAA,IAAQ,IAAA,IAAQ,IAAA,CAAK,kBAAkB,IAAI,CAAA;AACjE,IAAA,IAAI,aAAA,IAAiB,CAAC,IAAA,CAAK,kBAAA,EAAoB;AAC7C,MAAA,IAAI,KAAK,iBAAA,EAAmB;AAC5B,MAAA,MAAM,MAAA,GAAS,KAAK,mBAAA,EAAoB;AACxC,MAAA,IAAI,CAAC,MAAA,EAAQ;AACb,MAAA,KAAK,IAAA,CAAK,iBAAiB,MAAM,CAAA;AAAA,IACnC,CAAA,MAAA,IAAW,CAAC,aAAA,IAAiB,IAAA,CAAK,kBAAA,EAAoB;AACpD,MAAA,IAAA,CAAK,uBAAA,EAAwB;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,kBAAkB,MAAA,EAA0B;AAClD,IAAA,IAAI,IAAA,GAAoB,IAAA;AACxB,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA;AAC5B,MAAA,MAAM,SAAsB,IAAA,CAAK,UAAA;AACjC,MAAA,IAAI,MAAA,YAAkB,UAAA,EAAY,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,WAC3C,IAAA,GAAO,MAAA;AAAA,IACd;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,mBAAA,GAAuD;AAC7D,IAAA,MAAM,CAAA,GAAI,KAAK,QAAA,CAAS,UAAA;AACxB,IAAA,MAAM,CAAA,GAAI,KAAK,QAAA,CAAS,WAAA;AACxB,IAAA,IAAI,CAAC,CAAA,IAAK,CAAC,CAAA,EAAG,OAAO,IAAA;AACrB,IAAA,IAAI,CAAA,KAAM,GAAG,OAAO,IAAA;AACpB,IAAA,OAAO,CAAA,GAAI,IAAI,WAAA,GAAc,UAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAiB,MAAA,EAAiD;AAC9E,IAAA,MAAM,KAAM,MAAA,CAET,WAAA;AACH,IAAA,IAAI,CAAC,EAAA,IAAM,OAAO,EAAA,CAAG,SAAS,UAAA,EAAY;AAC1C,IAAA,IAAI;AACF,MAAA,MAAM,EAAA,CAAG,KAAK,MAAM,CAAA;AACpB,MAAA,IAAA,CAAK,kBAAA,GAAqB,IAAA;AAAA,IAC5B,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,uBAAA,GAAgC;AACtC,IAAA,IAAI,CAAC,KAAK,kBAAA,EAAoB;AAC9B,IAAA,IAAA,CAAK,kBAAA,GAAqB,KAAA;AAC1B,IAAA,MAAM,KAAK,MAAA,CAAO,WAAA;AAClB,IAAA,IAAI,EAAA,IAAM,OAAO,EAAA,CAAG,MAAA,KAAW,UAAA,EAAY;AACzC,MAAA,IAAI;AAAE,QAAA,EAAA,CAAG,MAAA,EAAO;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAe;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,MAAM,MAAA,GAAS,KAAK,aAAA,EAAc;AAClC,IAAA,IAAI,UAAU,IAAA,EAAM;AACpB,IAAA,MAAM,IAAA,CAAK,WAAW,MAAM,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAM,IAAA,CAAK,QAAQ,IAAA,EAAK;AAAA,IAC1B,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AACpB,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAA,GAAyB;AAC7B,IAAA,IAAI,KAAK,UAAA,EAAY;AACrB,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,IAAA,MAAM,KAAK,SAAA,EAAU;AACrB,IAAA,IAAA,CAAK,SAAA,CAAU,SAAA,EAAW,EAAE,CAAA;AAAA,EAC9B;AAAA,EAEA,MAAM,cAAc,EAAA,EAA2B;AAC7C,IAAA,IAAI,IAAA,CAAK,UAAA,IAAc,CAAC,IAAA,CAAK,OAAA,EAAS;AACtC,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,aAAA,CAAc,EAAE,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,iBAAiB,EAAA,EAAkC;AACvD,IAAA,IAAI,IAAA,CAAK,UAAA,IAAc,CAAC,IAAA,CAAK,OAAA,EAAS;AACtC,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,gBAAA,CAAiB,EAAE,CAAA;AAAA,EACxC;AAAA,EAEA,cAAA,GAA6C;AAC3C,IAAA,OAAO,IAAA,CAAK,OAAA,EAAS,cAAA,EAAe,IAAK,IAAA;AAAA,EAC3C;AAAA,EAqBS,gBAAA,CACP,IAAA,EACA,QAAA,EACA,OAAA,EACM;AACN,IAAA,KAAA,CAAM,gBAAA,CAAiB,IAAA,EAAM,QAAA,EAAU,OAAO,CAAA;AAAA,EAChD;AAAA,EAiBS,mBAAA,CACP,IAAA,EACA,QAAA,EACA,OAAA,EACM;AACN,IAAA,KAAA,CAAM,mBAAA,CAAoB,IAAA,EAAM,QAAA,EAAU,OAAO,CAAA;AAAA,EACnD;AAAA;AAAA,EAIQ,SAAA,CAAa,MAAc,MAAA,EAAiB;AAClD,IAAA,IAAA,CAAK,aAAA,CAAc,IAAI,WAAA,CAAY,IAAA,EAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,KAAA,EAAO,CAAC,CAAA;AAAA,EACtE;AAAA,EAEQ,eAAe,GAAA,EAAoB;AACzC,IAAA,MAAM,KAAA,GAAQ,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAChE,IAAA,IAAA,CAAK,SAAA,CAAU,OAAA,EAAS,EAAE,KAAA,EAAO,WAAA,EAAa,KAAK,OAAA,EAAS,cAAA,EAAe,IAAK,IAAA,EAAM,CAAA;AAAA,EACxF;AACF,CAAA;;;AC/jCO,IAAM,aAAA;AAAA;AAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAA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","file":"player.js","sourcesContent":["/**\n * Tiny strongly-typed event emitter. We avoid pulling in eventemitter3 / mitt\n * because we only need a handful of methods and want zero deps.\n *\n * Supports \"sticky\" events via {@link TypedEmitter.emitSticky}: the last value\n * for that event is remembered, and any future `on()` subscriber receives it\n * immediately. This is the right pattern for one-shot state-snapshot events\n * like \"strategy chosen\" or \"player ready\" — callers that subscribe after the\n * event has already fired still need to react to it.\n */\n\nexport type Listener<T> = (payload: T) => void;\n\nexport class TypedEmitter<EventMap> {\n private listeners: { [K in keyof EventMap]?: Set<Listener<EventMap[K]>> } = {};\n private sticky: { [K in keyof EventMap]?: EventMap[K] } = {};\n\n on<K extends keyof EventMap>(event: K, fn: Listener<EventMap[K]>): () => void {\n let set = this.listeners[event];\n if (!set) {\n set = new Set();\n this.listeners[event] = set;\n }\n set.add(fn);\n\n // Replay any sticky value that's already been emitted for this event.\n if (Object.prototype.hasOwnProperty.call(this.sticky, event)) {\n try {\n fn(this.sticky[event] as EventMap[K]);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] listener threw replaying sticky value:\", err);\n }\n }\n\n return () => this.off(event, fn);\n }\n\n off<K extends keyof EventMap>(event: K, fn: Listener<EventMap[K]>): void {\n this.listeners[event]?.delete(fn);\n }\n\n emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {\n const set = this.listeners[event];\n if (!set) return;\n // Snapshot so listeners can unsubscribe themselves.\n for (const fn of [...set]) {\n try {\n fn(payload);\n } catch (err) {\n // Don't let one bad listener break the others.\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] listener threw:\", err);\n }\n }\n }\n\n /**\n * Like {@link emit} but also remembers the value so future subscribers\n * receive it on `on()`. Use for one-shot state-snapshot events.\n */\n emitSticky<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {\n this.sticky[event] = payload;\n this.emit(event, payload);\n }\n\n removeAll(): void {\n this.listeners = {};\n this.sticky = {};\n }\n}\n","import type {\n AudioCodec,\n AudioTrackInfo,\n ContainerKind,\n MediaContext,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport type { NormalizedSource } from \"../util/source.js\";\n\n/**\n * Probe via mediabunny. Built against the real (typed) API exported by\n * `mediabunny.d.ts`:\n *\n * - `Input.getTracks()` returns `InputTrack[]`; each track has `isVideoTrack()`\n * / `isAudioTrack()` type guards plus a `codec` getter that returns one of\n * the enum strings (`\"avc\"|\"hevc\"|\"vp9\"|\"vp8\"|\"av1\"` for video,\n * `\"aac\"|\"opus\"|...` for audio).\n * - For decoder metadata + codec parameter strings we call\n * `getDecoderConfig()` and `getCodecParameterString()` on the typed track.\n *\n * The bridging back to avbridge's own codec naming (`h264` instead of mediabunny's\n * `avc`) happens here so the rest of the codebase keeps a single vocabulary.\n */\nexport async function probeWithMediabunny(\n source: NormalizedSource,\n sniffedContainer: ContainerKind,\n): Promise<MediaContext> {\n const mb = await import(\"mediabunny\");\n const input = new mb.Input({\n source: await buildMediabunnySource(mb, source),\n formats: mb.ALL_FORMATS,\n });\n\n const allTracks = await input.getTracks();\n const duration = await safeNumber(() => input.computeDuration());\n\n const videoTracks: VideoTrackInfo[] = [];\n const audioTracks: AudioTrackInfo[] = [];\n\n for (const track of allTracks) {\n if (track.isVideoTrack()) {\n const codecParam = await safe(() => track.getCodecParameterString());\n videoTracks.push({\n id: track.id,\n codec: mediabunnyVideoToAvbridge(track.codec),\n width: track.displayWidth ?? track.codedWidth ?? 0,\n height: track.displayHeight ?? track.codedHeight ?? 0,\n codecString: codecParam ?? undefined,\n });\n } else if (track.isAudioTrack()) {\n const codecParam = await safe(() => track.getCodecParameterString());\n audioTracks.push({\n id: track.id,\n codec: mediabunnyAudioToAvbridge(track.codec),\n channels: track.numberOfChannels ?? 0,\n sampleRate: track.sampleRate ?? 0,\n language: track.languageCode,\n codecString: codecParam ?? undefined,\n });\n }\n }\n\n const format = await safe(() => input.getFormat());\n const container = resolveContainer(format?.name, sniffedContainer);\n\n return {\n source: source.original,\n name: source.name,\n byteLength: source.byteLength,\n container,\n videoTracks,\n audioTracks,\n subtitleTracks: [],\n probedBy: \"mediabunny\",\n duration,\n };\n}\n\n/**\n * Build the right mediabunny `Source` for a normalized input. URL sources\n * use `UrlSource` (Range requests, prefetch, parallelism) so we don't\n * buffer the whole file into memory. Blob/File sources use `BlobSource`.\n *\n * Exported so the remux strategy can use the same routing logic.\n */\nexport async function buildMediabunnySource(\n mb: typeof import(\"mediabunny\"),\n source: NormalizedSource,\n): Promise<InstanceType<typeof mb.BlobSource> | InstanceType<typeof mb.UrlSource>> {\n if (source.kind === \"url\") {\n return new mb.UrlSource(source.url);\n }\n return new mb.BlobSource(source.blob);\n}\n\n/**\n * Build a mediabunny `Source` directly from a raw `MediaInput`, bypassing\n * `normalizeSource`. Used by strategies that already have the original\n * input on hand (via `MediaContext.source`) and don't need a sniff window.\n *\n * This is the routing point that decides \"stream from URL via Range\n * requests\" vs \"wrap in-memory bytes as BlobSource\". Always prefer\n * `UrlSource` for URL inputs so we don't accidentally buffer the file.\n */\nexport async function buildMediabunnySourceFromInput(\n mb: typeof import(\"mediabunny\"),\n source: import(\"../types.js\").MediaInput,\n): Promise<InstanceType<typeof mb.BlobSource> | InstanceType<typeof mb.UrlSource>> {\n if (typeof source === \"string\") return new mb.UrlSource(source);\n if (source instanceof URL) return new mb.UrlSource(source.toString());\n if (source instanceof Blob) return new mb.BlobSource(source);\n if (source instanceof ArrayBuffer) return new mb.BlobSource(new Blob([source]));\n if (source instanceof Uint8Array) return new mb.BlobSource(new Blob([source as BlobPart]));\n throw new TypeError(\"unsupported source type for mediabunny\");\n}\n\nfunction resolveContainer(formatName: string | undefined, sniffed: ContainerKind): ContainerKind {\n const name = (formatName ?? \"\").toLowerCase();\n if (name.includes(\"matroska\") || name.includes(\"mkv\")) return \"mkv\";\n if (name.includes(\"webm\")) return \"webm\";\n if (name.includes(\"mp4\") || name.includes(\"isom\")) return \"mp4\";\n if (name.includes(\"mov\") || name.includes(\"quicktime\")) return \"mov\";\n if (name.includes(\"ogg\")) return \"ogg\";\n if (name.includes(\"wav\")) return \"wav\";\n if (name.includes(\"flac\")) return \"flac\";\n if (name.includes(\"mp3\")) return \"mp3\";\n if (name.includes(\"adts\") || name.includes(\"aac\")) return \"adts\";\n if (name.includes(\"mpegts\") || name.includes(\"mpeg-ts\") || name.includes(\"transport\")) return \"mpegts\";\n return sniffed;\n}\n\n/** Mediabunny video codec → avbridge video codec. */\nexport function mediabunnyVideoToAvbridge(c: string | null | undefined): VideoCodec {\n switch (c) {\n case \"avc\": return \"h264\";\n case \"hevc\": return \"h265\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n default:\n // Preserve the original codec string when mediabunny gave us something\n // we don't recognize. The classifier checks `NATIVE_VIDEO_CODECS.has()`\n // and routes anything outside that set through the fallback chain — so\n // returning the unknown name (instead of silently relabeling it as\n // \"h264\") gets correct routing AND honest diagnostics.\n return c ? (c as VideoCodec) : \"unknown\";\n }\n}\n\n/** avbridge video codec → mediabunny video codec (for output sources). */\nexport function avbridgeVideoToMediabunny(c: VideoCodec): \"avc\" | \"hevc\" | \"vp9\" | \"vp8\" | \"av1\" | null {\n switch (c) {\n case \"h264\": return \"avc\";\n case \"h265\": return \"hevc\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n default: return null;\n }\n}\n\nexport function mediabunnyAudioToAvbridge(c: string | null | undefined): AudioCodec {\n switch (c) {\n case \"aac\": return \"aac\";\n case \"mp3\": return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n default: return c ? (c as AudioCodec) : \"unknown\";\n }\n}\n\nexport function avbridgeAudioToMediabunny(c: AudioCodec): string | null {\n switch (c) {\n case \"aac\": return \"aac\";\n case \"mp3\": return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n default: return null;\n }\n}\n\nasync function safeNumber(fn: () => Promise<number> | number): Promise<number | undefined> {\n try {\n const v = await fn();\n return typeof v === \"number\" && Number.isFinite(v) ? v : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function safe<T>(fn: () => Promise<T> | T): Promise<T | undefined> {\n try { return await fn(); } catch { return undefined; }\n}\n","import type { ContainerKind, MediaContext, MediaInput, TransportConfig } from \"../types.js\";\nimport { normalizeSource, sniffNormalizedSource } from \"../util/source.js\";\nimport { probeWithMediabunny } from \"./mediabunny.js\";\nimport { AvbridgeError, ERR_PROBE_FAILED, ERR_PROBE_UNKNOWN_CONTAINER, ERR_LIBAV_NOT_REACHABLE } from \"../errors.js\";\n\n/** Containers mediabunny can demux. Sniff results outside this set go straight to libav. */\nconst MEDIABUNNY_CONTAINERS = new Set<ContainerKind>([\n \"mp4\",\n \"mov\",\n \"mkv\",\n \"webm\",\n \"ogg\",\n \"wav\",\n \"mp3\",\n \"flac\",\n \"adts\",\n \"mpegts\",\n]);\n\n/**\n * Probe a source and produce a {@link MediaContext}.\n *\n * Routing:\n * 1. Sniff the magic header. Cheap, deterministic, ignores file extensions.\n * 2. If the container is one mediabunny supports → try mediabunny first\n * (fast path — it's a single pass of WASM-free JS parsing). If mediabunny\n * throws (e.g. an assertion on an unsupported sample entry like `mp4v`\n * for MPEG-4 Part 2 in ISOBMFF, or an exotic MKV codec), fall through to\n * libav.js which handles the long tail of codecs mediabunny doesn't.\n * The combined-error case surfaces *both* failures so the user sees\n * which path each step took.\n * 3. If sniffing identifies AVI/ASF/FLV (or `unknown`) → libav.js directly.\n * mediabunny can't read those containers at all, so there's no fast path\n * to try.\n */\nexport async function probe(\n source: MediaInput,\n transport?: TransportConfig,\n): Promise<MediaContext> {\n const normalized = await normalizeSource(source, transport);\n const sniffed = await sniffNormalizedSource(normalized);\n\n if (MEDIABUNNY_CONTAINERS.has(sniffed)) {\n try {\n const result = await probeWithMediabunny(normalized, sniffed);\n // If mediabunny returned unknown codecs, try libav which recognizes\n // a wider range (DTS, TrueHD, etc.). Only escalate if there ARE\n // tracks with unknown codecs — otherwise mediabunny's result is fine.\n const hasUnknownCodec =\n result.videoTracks.some((t) => t.codec === \"unknown\") ||\n result.audioTracks.some((t) => t.codec === \"unknown\");\n if (hasUnknownCodec) {\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch {\n // libav also failed — return mediabunny's result (unknown codecs\n // are better than no result at all)\n return result;\n }\n }\n return result;\n } catch (mediabunnyErr) {\n // mediabunny rejected the file. Before giving up, try libav — it can\n // demux a much wider range of codec combinations in ISOBMFF/MKV/etc.\n // than mediabunny's pure-JS parser (e.g. mp4v, wmv3-in-asf, flac in\n // an MP4 container). This is \"escalation\", not \"masking\": if libav\n // also fails we surface both errors below.\n // eslint-disable-next-line no-console\n console.warn(\n `[avbridge] mediabunny rejected ${sniffed} file, falling back to libav:`,\n (mediabunnyErr as Error).message,\n );\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch (libavErr) {\n const mbMsg = (mediabunnyErr as Error).message || String(mediabunnyErr);\n const lvMsg = libavErr instanceof Error ? libavErr.message : String(libavErr);\n throw new AvbridgeError(\n ERR_PROBE_FAILED,\n `Failed to probe ${sniffed.toUpperCase()} file. mediabunny: ${mbMsg}. libav: ${lvMsg}.`,\n \"The file may be corrupt, truncated, or in an unsupported format. Enable AVBRIDGE_DEBUG for detailed logs.\",\n );\n }\n }\n }\n\n // sniffed === avi | asf | flv | unknown — try libav.\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch (err) {\n const inner = err instanceof Error ? err.message : String(err);\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] libav probe failed for\", sniffed, \"file:\", err);\n if (sniffed === \"unknown\") {\n throw new AvbridgeError(\n ERR_PROBE_UNKNOWN_CONTAINER,\n `Unable to probe source: container format could not be identified. libav fallback: ${inner || \"(no details)\"}`,\n \"The file may be corrupt or in a format avbridge doesn't recognize. Check the file plays in VLC or ffprobe.\",\n );\n }\n throw new AvbridgeError(\n ERR_LIBAV_NOT_REACHABLE,\n `${sniffed.toUpperCase()} files require libav.js, which failed to load: ${inner || \"(no details)\"}`,\n \"Install @libav.js/variant-webcodecs, or check that AVBRIDGE_LIBAV_BASE points to the correct path.\",\n );\n }\n}\n","import type { AudioTrackInfo, VideoTrackInfo } from \"../types.js\";\n\n/**\n * Build an RFC 6381 codec string for use with `MediaSource.isTypeSupported`\n * and `<source type=...>`. Returns null when we don't have enough info to\n * compose one — callers should treat that as \"ask the browser at runtime via\n * a different channel\" rather than guessing.\n */\nexport function videoCodecString(track: VideoTrackInfo): string | null {\n if (track.codecString) return track.codecString;\n switch (track.codec) {\n case \"h264\": {\n // avc1.PPCCLL — profile (1B), constraint (1B), level (1B). Default to\n // High Profile @ 4.0 if we don't know — common on real-world content.\n const profileHex = profileToHex(track.profile) ?? \"64\"; // 0x64 = High\n const constraint = \"00\";\n const level = ((track.level ?? 40) & 0xff).toString(16).padStart(2, \"0\");\n return `avc1.${profileHex}${constraint}${level}`;\n }\n case \"h265\":\n // Default Main Profile @ Level 4.1 (0x5d = 93) — `hvc1.1.6.L93.B0`.\n return \"hvc1.1.6.L93.B0\";\n case \"vp8\":\n return \"vp8\";\n case \"vp9\":\n return \"vp09.00.10.08\";\n case \"av1\":\n return \"av01.0.04M.08\";\n default:\n return null;\n }\n}\n\nfunction profileToHex(profile?: string): string | null {\n if (!profile) return null;\n const p = profile.toLowerCase();\n if (p.includes(\"baseline\")) return \"42\";\n if (p.includes(\"main\")) return \"4d\";\n if (p.includes(\"high 10\")) return \"6e\";\n if (p.includes(\"high 4:2:2\")) return \"7a\";\n if (p.includes(\"high 4:4:4\")) return \"f4\";\n if (p.includes(\"high\")) return \"64\";\n return null;\n}\n\nexport function audioCodecString(track: AudioTrackInfo): string | null {\n if (track.codecString) return track.codecString;\n switch (track.codec) {\n case \"aac\":\n return \"mp4a.40.2\"; // AAC-LC\n case \"mp3\":\n return \"mp4a.40.34\";\n case \"opus\":\n return \"opus\";\n case \"vorbis\":\n return \"vorbis\";\n case \"flac\":\n return \"flac\";\n default:\n return null;\n }\n}\n\n/**\n * Compose a `video/mp4; codecs=\"...\"` MIME for MSE. Returns null if either\n * codec string can't be produced — caller should fall back to remux refusal.\n */\nexport function mp4MimeFor(video: VideoTrackInfo, audio?: AudioTrackInfo): string | null {\n const v = videoCodecString(video);\n if (!v) return null;\n const codecs = audio ? `${v},${audioCodecString(audio) ?? \"\"}`.replace(/,$/, \"\") : v;\n return `video/mp4; codecs=\"${codecs}\"`;\n}\n\n/**\n * Wrap `MediaSource.isTypeSupported` so it returns false (instead of throwing)\n * in environments without MSE — e.g. jsdom under vitest.\n */\nexport function mseSupports(mime: string): boolean {\n if (typeof MediaSource === \"undefined\") return false;\n try {\n return MediaSource.isTypeSupported(mime);\n } catch {\n return false;\n }\n}\n","import type {\n AudioCodec,\n AudioTrackInfo,\n Classification,\n ContainerKind,\n MediaContext,\n StrategyName,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport { mp4MimeFor, mseSupports } from \"../util/codec-strings.js\";\n\n/**\n * Codecs we know `<video>` and MSE support across modern desktop + Android.\n * The decision to remux instead of decode hinges on this list.\n */\n/** Codecs the browser can decode natively (also the set WebCodecs can transcode). */\nexport const NATIVE_VIDEO_CODECS = new Set<VideoCodec>([\"h264\", \"h265\", \"vp8\", \"vp9\", \"av1\"]);\nexport const NATIVE_AUDIO_CODECS = new Set<AudioCodec>([\n \"aac\",\n \"mp3\",\n \"opus\",\n \"vorbis\",\n \"flac\",\n]);\n\n/**\n * Codecs no major browser plays, period. These force the WASM fallback.\n */\nexport const FALLBACK_VIDEO_CODECS = new Set<VideoCodec>([\n \"wmv3\", \"vc1\", \"mpeg4\",\n \"rv10\", \"rv20\", \"rv30\", \"rv40\",\n \"mpeg2\", \"mpeg1\", \"theora\",\n \"dv\", \"hq_hqa\",\n \"rawvideo\", \"qtrle\", \"png\", \"vp6f\",\n]);\nexport const FALLBACK_AUDIO_CODECS = new Set<AudioCodec>([\n \"wmav2\", \"wmapro\", \"ac3\", \"eac3\",\n \"cook\", \"ra_144\", \"ra_288\", \"sipr\", \"atrac3\",\n \"dts\", \"truehd\",\n]);\n\n/**\n * Containers `<video>` plays directly. Anything else with otherwise-supported\n * codecs is a remux candidate — IF mediabunny can read the container.\n */\nconst NATIVE_CONTAINERS = new Set<ContainerKind>([\n \"mp4\",\n \"mov\",\n \"webm\",\n \"ogg\",\n \"wav\",\n \"mp3\",\n \"flac\",\n \"adts\",\n]);\n\n/**\n * Containers mediabunny can demux. The remux strategy feeds the source through\n * mediabunny → fMP4 → MSE, so the source container must be one mediabunny\n * understands. AVI, ASF, FLV are NOT in this set — mediabunny rejects them\n * with \"unsupported or unrecognizable format\". Files in those containers with\n * otherwise-native codecs (e.g. AVI + H.264 + MP3) must go to the fallback\n * strategy even though the *codecs* are browser-supported.\n *\n * MPEG-TS is in this set: mediabunny demuxes it natively, but browsers\n * cannot play `<video src=\"*.ts\">` directly (MPEG-TS is HLS-only), so even\n * a TS file with H.264 + AAC has to go through the remux path.\n */\nconst REMUXABLE_CONTAINERS = new Set<ContainerKind>([\n \"mp4\",\n \"mov\",\n \"mkv\",\n \"webm\",\n \"ogg\",\n \"wav\",\n \"mp3\",\n \"flac\",\n \"adts\",\n \"mpegts\",\n]);\n\n/**\n * Pure classification — no I/O, no async. Test-friendly.\n */\nexport function classifyContext(ctx: MediaContext): Classification {\n const video = ctx.videoTracks[0];\n const audio = ctx.audioTracks[0];\n\n // Audio-only files: mediabunny handles all the common ones natively.\n if (!video) {\n if (NATIVE_CONTAINERS.has(ctx.container) && (!audio || NATIVE_AUDIO_CODECS.has(audio.codec))) {\n return {\n class: \"NATIVE\",\n strategy: \"native\",\n reason: `audio-only ${ctx.container} with native codec`,\n };\n }\n if (audio && FALLBACK_AUDIO_CODECS.has(audio.codec)) {\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `audio codec \"${audio.codec}\" requires WASM decode`,\n };\n }\n if (REMUXABLE_CONTAINERS.has(ctx.container)) {\n return {\n class: \"REMUX_CANDIDATE\",\n strategy: \"remux\",\n reason: `audio-only file in non-native container \"${ctx.container}\"`,\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `audio-only file in \"${ctx.container}\" (not remuxable by mediabunny)`,\n };\n }\n\n // Video paths.\n if (FALLBACK_VIDEO_CODECS.has(video.codec)) {\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `video codec \"${video.codec}\" has no browser decoder; WASM fallback required`,\n };\n }\n // Audio codec needs WASM decode — either it's in the known fallback set\n // or it's unrecognized (\"unknown\" / not in native set). Unknown codecs\n // definitely can't play natively, so they get the same treatment.\n const audioNeedsFallback = audio && (\n FALLBACK_AUDIO_CODECS.has(audio.codec) ||\n !NATIVE_AUDIO_CODECS.has(audio.codec)\n );\n if (audioNeedsFallback) {\n // If the VIDEO codec is native, prefer hybrid (WebCodecs hardware video\n // decode + libav software audio decode) over full WASM fallback. This is\n // critical for Blu-ray MKVs: H.264 1080p in WASM is unwatchably slow,\n // but WebCodecs decodes it at full speed while libav handles the DTS/AC3\n // audio in software.\n if (NATIVE_VIDEO_CODECS.has(video.codec) && webCodecsAvailable()) {\n return {\n class: \"HYBRID_CANDIDATE\",\n strategy: \"hybrid\",\n reason: `video \"${video.codec}\" is hardware-decodable via WebCodecs; audio \"${audio.codec}\" decoded in software by libav`,\n fallbackChain: [\"fallback\"],\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `audio codec \"${audio.codec}\" has no browser decoder; WASM fallback required`,\n };\n }\n\n if (!NATIVE_VIDEO_CODECS.has(video.codec)) {\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `unknown video codec \"${video.codec}\", routing to fallback`,\n };\n }\n\n // Codecs are native. Now decide between NATIVE and REMUX based on the\n // container and codec quirks.\n const isNativeContainer = NATIVE_CONTAINERS.has(ctx.container);\n\n if (isNativeContainer && isSafeNativeCombo(video, audio)) {\n // Confirm with the browser when we have access to MediaSource.\n const mime = mp4MimeFor(video, audio);\n if (mime && mseSupports(mime)) {\n return {\n class: \"NATIVE\",\n strategy: \"native\",\n reason: `${ctx.container} + ${video.codec}${audio ? \"/\" + audio.codec : \"\"} plays natively`,\n };\n }\n if (mime == null || typeof MediaSource === \"undefined\") {\n // No MSE in this environment (e.g. tests) — trust the heuristic.\n return {\n class: \"NATIVE\",\n strategy: \"native\",\n reason: `${ctx.container} + ${video.codec}${audio ? \"/\" + audio.codec : \"\"} (heuristic native)`,\n };\n }\n }\n\n if (isNativeContainer && isRiskyNative(video)) {\n return {\n class: \"RISKY_NATIVE\",\n strategy: \"native\",\n reason: `${video.codec} ${video.profile ?? \"\"} ${video.bitDepth ?? 8}-bit may stutter on mobile; will escalate to remux on stall`,\n fallbackChain: [\"remux\", \"hybrid\", \"fallback\"],\n };\n }\n\n // Codecs are native but the container isn't. Can we remux?\n // Remuxing goes through mediabunny, which only supports certain containers.\n // AVI/ASF/FLV are NOT in that set — mediabunny rejects them at Input().\n if (REMUXABLE_CONTAINERS.has(ctx.container)) {\n // Feature-detect: the remux target is fragmented MP4 via MSE. If the\n // browser's MSE can't decode this codec combo (e.g. HEVC on\n // open-source Chromium — no proprietary codecs by design — or\n // future codec/container combos we haven't thought of), remux will\n // stall. Degrade gracefully: try hybrid (WebCodecs hardware decode)\n // or fallback (WASM software decode) without waiting for runtime\n // escalation.\n const mime = mp4MimeFor(video, audio);\n if (mime && typeof MediaSource !== \"undefined\" && !mseSupports(mime)) {\n if (webCodecsAvailable()) {\n return {\n class: \"HYBRID_CANDIDATE\",\n strategy: \"hybrid\",\n reason: `${ctx.container} container with ${video.codec}${audio ? \"/\" + audio.codec : \"\"}; MSE rejects the remux target mime — routing to WebCodecs hardware decode`,\n fallbackChain: [\"fallback\"],\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `${ctx.container} container with ${video.codec}${audio ? \"/\" + audio.codec : \"\"}; MSE rejects the remux target mime and WebCodecs is unavailable — falling back to WASM decode`,\n };\n }\n // Give REMUX_CANDIDATE a fallback chain so the runtime stall / decode\n // supervisors have somewhere to escalate to when MSE lies about codec\n // support (the Firefox HEVC case — audio plays, video never paints).\n // The initial pick is still remux; these only engage on stall.\n const fallbackChain: StrategyName[] = webCodecsAvailable()\n ? [\"hybrid\", \"fallback\"]\n : [\"fallback\"];\n return {\n class: \"REMUX_CANDIDATE\",\n strategy: \"remux\",\n reason: `${ctx.container} container with native-supported codecs — remux to fragmented MP4 for reliable playback`,\n fallbackChain,\n };\n }\n\n // Container is unreadable by mediabunny (AVI, ASF, FLV, etc.) but codecs\n // are browser-supported. Use the hybrid strategy (libav demux + WebCodecs\n // hardware decode) when WebCodecs is available; otherwise full WASM decode.\n if (webCodecsAvailable()) {\n return {\n class: \"HYBRID_CANDIDATE\",\n strategy: \"hybrid\",\n reason: `${ctx.container} container requires libav demux; codecs (${video.codec}${audio ? \"/\" + audio.codec : \"\"}) are hardware-decodable via WebCodecs`,\n fallbackChain: [\"fallback\"],\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `${ctx.container} container cannot be remuxed by mediabunny; falling back to WASM decode (${video.codec}${audio ? \"/\" + audio.codec : \"\"})`,\n };\n}\n\nfunction webCodecsAvailable(): boolean {\n return typeof globalThis.VideoDecoder !== \"undefined\";\n}\n\nfunction isSafeNativeCombo(video: VideoTrackInfo, audio?: AudioTrackInfo): boolean {\n if (video.codec === \"h264\") {\n // 8-bit yuv420p H.264 is the safe combo. Hi10P / 4:2:2 / 4:4:4 are not.\n if (video.bitDepth && video.bitDepth > 8) return false;\n if (video.pixelFormat && !/yuv420p$/.test(video.pixelFormat)) return false;\n }\n if (audio && !NATIVE_AUDIO_CODECS.has(audio.codec)) return false;\n return true;\n}\n\nfunction isRiskyNative(video: VideoTrackInfo): boolean {\n if (video.bitDepth && video.bitDepth > 8) return true;\n if (video.pixelFormat && /yuv4(2[24]|44)/.test(video.pixelFormat)) return true;\n if (video.width > 3840 || video.height > 2160) return true;\n if (video.fps && video.fps > 60) return true;\n return false;\n}\n","import type {\n Classification,\n DiagnosticsSnapshot,\n MediaContext,\n StrategyName,\n} from \"./types.js\";\n\n/**\n * Accumulates diagnostic info as the player walks probe → classify → play.\n * `snapshot()` produces an immutable view shaped exactly like the example in\n * design doc §12.\n */\nexport class Diagnostics {\n private container: DiagnosticsSnapshot[\"container\"] = \"unknown\";\n private videoCodec?: DiagnosticsSnapshot[\"videoCodec\"];\n private audioCodec?: DiagnosticsSnapshot[\"audioCodec\"];\n private width?: number;\n private height?: number;\n private fps?: number;\n private duration?: number;\n private strategy: DiagnosticsSnapshot[\"strategy\"] = \"pending\";\n private strategyClass: DiagnosticsSnapshot[\"strategyClass\"] = \"pending\";\n private reason = \"\";\n private probedBy?: DiagnosticsSnapshot[\"probedBy\"];\n private sourceType?: DiagnosticsSnapshot[\"sourceType\"];\n private transport?: DiagnosticsSnapshot[\"transport\"];\n private rangeSupported?: DiagnosticsSnapshot[\"rangeSupported\"];\n private runtime: Record<string, unknown> = {};\n private lastError?: Error;\n private strategyHistory: Array<{ strategy: StrategyName; reason: string; at: number }> = [];\n\n recordProbe(ctx: MediaContext): void {\n this.container = ctx.container;\n this.probedBy = ctx.probedBy;\n this.duration = ctx.duration;\n const v = ctx.videoTracks[0];\n if (v) {\n this.videoCodec = v.codec;\n this.width = v.width;\n this.height = v.height;\n this.fps = v.fps;\n }\n const a = ctx.audioTracks[0];\n if (a) this.audioCodec = a.codec;\n // Source-type detection. For blob inputs we know the transport with\n // certainty. For URL inputs we know the *intended* transport but not\n // whether the server actually honors Range — that's confirmed later by\n // the strategy that fetches the bytes (via {@link recordTransport}).\n const src = ctx.source;\n if (typeof src === \"string\" || src instanceof URL) {\n this.sourceType = \"url\";\n this.transport = \"http-range\";\n // Intentionally NOT setting rangeSupported here. Inferring \"true\" from\n // input type was misleading: native/remux URL paths rely on the\n // browser's or mediabunny's own Range handling and don't fail-fast on\n // a non-supporting server. Strategies that prove Range support call\n // recordTransport() once they have a confirmed answer.\n this.rangeSupported = undefined;\n } else {\n this.sourceType = \"blob\";\n this.transport = \"memory\";\n this.rangeSupported = false;\n }\n }\n\n /**\n * Called by a strategy once it has a confirmed answer about how the\n * source bytes are actually flowing (e.g. after the libav HTTP block\n * reader's initial Range probe succeeded). Lets diagnostics report the\n * truth instead of an input-type heuristic.\n */\n recordTransport(\n transport: NonNullable<DiagnosticsSnapshot[\"transport\"]>,\n rangeSupported: boolean,\n ): void {\n this.transport = transport;\n this.rangeSupported = rangeSupported;\n }\n\n recordClassification(c: Classification): void {\n this.strategy = c.strategy;\n this.strategyClass = c.class;\n this.reason = c.reason;\n }\n\n recordRuntime(stats: Record<string, unknown>): void {\n // Strategies can surface confirmed transport info in their runtime\n // stats under the well-known `_transport` / `_rangeSupported` keys.\n // When present, they're hoisted to the typed fields via\n // recordTransport() and stripped from the generic runtime bag so they\n // don't duplicate.\n const {\n _transport,\n _rangeSupported,\n ...rest\n } = stats as Record<string, unknown> & {\n _transport?: NonNullable<DiagnosticsSnapshot[\"transport\"]>;\n _rangeSupported?: boolean;\n };\n if (_transport != null && typeof _rangeSupported === \"boolean\") {\n this.recordTransport(_transport, _rangeSupported);\n }\n this.runtime = { ...this.runtime, ...rest };\n }\n\n recordStrategySwitch(strategy: StrategyName, reason: string): void {\n this.strategy = strategy;\n this.reason = reason;\n this.strategyHistory.push({ strategy, reason, at: Date.now() });\n }\n\n recordError(err: Error): void {\n this.lastError = err;\n }\n\n snapshot(): DiagnosticsSnapshot {\n const snap: DiagnosticsSnapshot = {\n container: this.container,\n videoCodec: this.videoCodec,\n audioCodec: this.audioCodec,\n width: this.width,\n height: this.height,\n fps: this.fps,\n duration: this.duration,\n strategy: this.strategy,\n strategyClass: this.strategyClass,\n reason: this.reason,\n probedBy: this.probedBy,\n sourceType: this.sourceType,\n transport: this.transport,\n rangeSupported: this.rangeSupported,\n runtime: { ...this.runtime, ...(this.lastError ? { error: this.lastError.message } : {}) },\n strategyHistory: this.strategyHistory.length > 0 ? [...this.strategyHistory] : undefined,\n };\n return Object.freeze(snap);\n }\n}\n","import type { MediaContext, Plugin, StrategyName } from \"../types.js\";\n\n/**\n * Plugin registry. Built-in strategies are registered as plugins so that\n * user-supplied plugins can preempt them. The registry is consulted twice:\n * once by the player layer to find a plugin matching the picked strategy, and\n * (optionally) by classification to ask plugins what they support.\n */\nexport class PluginRegistry {\n private plugins: Plugin[] = [];\n\n register(plugin: Plugin, prepend = false): void {\n if (prepend) this.plugins.unshift(plugin);\n else this.plugins.push(plugin);\n }\n\n all(): readonly Plugin[] {\n return this.plugins;\n }\n\n /**\n * Find the first plugin that claims this context AND its name matches the\n * strategy. Built-in strategy plugins are named exactly `\"native\"`,\n * `\"remux\"`, `\"fallback\"`.\n */\n findFor(context: MediaContext, strategy: StrategyName): Plugin | null {\n for (const p of this.plugins) {\n if (p.name === strategy && p.canHandle(context)) return p;\n }\n return null;\n }\n}\n","import type { MediaContext, PlaybackSession } from \"../types.js\";\n\n/**\n * Simplest strategy: hand the source to the browser. Works for any\n * MP4/WebM/MP3/etc. that the user agent already plays.\n *\n * The only complexity is that the source might be a `File`/`Blob` (use\n * `URL.createObjectURL`), an `ArrayBuffer`/`Uint8Array` (wrap in a Blob first),\n * or a string URL (assign directly).\n */\nexport async function createNativeSession(\n context: MediaContext,\n video: HTMLVideoElement,\n): Promise<PlaybackSession> {\n const { url, revoke } = sourceToVideoUrl(context.source);\n video.src = url;\n\n // Wait for metadata so the player resolves only once playback is actually\n // ready. We expose errors via the player's \"error\" event, not by throwing\n // here, because failure here often means we should escalate to remux.\n await new Promise<void>((resolve, reject) => {\n const onMeta = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(new Error(`<video> failed to load: ${video.error?.message ?? \"unknown\"}`));\n };\n const cleanup = () => {\n video.removeEventListener(\"loadedmetadata\", onMeta);\n video.removeEventListener(\"error\", onError);\n };\n video.addEventListener(\"loadedmetadata\", onMeta);\n video.addEventListener(\"error\", onError);\n });\n\n let stats = { framesDecoded: 0, framesDropped: 0 };\n\n return {\n strategy: \"native\",\n async play() {\n await video.play();\n },\n pause() {\n video.pause();\n },\n async seek(time) {\n video.currentTime = time;\n },\n async setAudioTrack(id) {\n // HTMLMediaElement.audioTracks isn't exposed on all browsers (Chrome\n // needs the MediaCapabilities flag for many containers). Best-effort:\n // try by string id match first, then by index. If the list doesn't\n // exist, silently no-op — the user will still hear whatever track the\n // browser picked by default.\n const tracks = (video as unknown as { audioTracks?: { length: number; [i: number]: { id: string; enabled: boolean } } }).audioTracks;\n if (!tracks || tracks.length === 0) return;\n for (let i = 0; i < tracks.length; i++) {\n tracks[i].enabled = tracks[i].id === String(id) || i === id;\n }\n },\n async setSubtitleTrack(id) {\n const tracks = video.textTracks;\n for (let i = 0; i < tracks.length; i++) {\n tracks[i].mode = i === id ? \"showing\" : \"disabled\";\n }\n },\n async destroy() {\n video.pause();\n video.removeAttribute(\"src\");\n video.load();\n revoke?.();\n },\n getCurrentTime() {\n return video.currentTime || 0;\n },\n getRuntimeStats() {\n // getVideoPlaybackQuality is the standard hook; not all UAs implement it.\n const q = (video as unknown as { getVideoPlaybackQuality?: () => VideoPlaybackQuality }).getVideoPlaybackQuality?.();\n if (q) {\n stats = {\n framesDecoded: q.totalVideoFrames,\n framesDropped: q.droppedVideoFrames,\n };\n }\n return { ...stats, decoderType: \"native\" };\n },\n };\n}\n\nfunction sourceToVideoUrl(source: unknown): { url: string; revoke?: () => void } {\n if (source instanceof Blob) {\n const url = URL.createObjectURL(source);\n return { url, revoke: () => URL.revokeObjectURL(url) };\n }\n if (source instanceof ArrayBuffer || source instanceof Uint8Array) {\n const blob = new Blob([source as BlobPart]);\n const url = URL.createObjectURL(blob);\n return { url, revoke: () => URL.revokeObjectURL(url) };\n }\n if (typeof source === \"string\") return { url: source };\n if (source instanceof URL) return { url: source.toString() };\n throw new TypeError(\"native strategy: unsupported source type\");\n}\n\ninterface VideoPlaybackQuality {\n totalVideoFrames: number;\n droppedVideoFrames: number;\n}\n","/**\n * MediaSource Extensions plumbing. Wraps a `MediaSource` + single\n * `SourceBuffer` with an append queue that respects `updateend` backpressure.\n */\n\nimport { AvbridgeError, ERR_MSE_NOT_SUPPORTED, ERR_MSE_CODEC_NOT_SUPPORTED } from \"../../errors.js\";\n\nexport interface MseSinkOptions {\n mime: string;\n video: HTMLVideoElement;\n /** Called once the MediaSource is open and ready for appends. */\n onReady?: () => void;\n}\n\nexport class MseSink {\n private mediaSource: MediaSource;\n private sourceBuffer: SourceBuffer | null = null;\n private queue: ArrayBuffer[] = [];\n private endOfStreamCalled = false;\n private destroyed = false;\n private readyPromise: Promise<void>;\n private resolveReady!: () => void;\n private rejectReady!: (err: Error) => void;\n private objectUrl: string;\n\n constructor(private readonly options: MseSinkOptions) {\n if (typeof MediaSource === \"undefined\") {\n throw new AvbridgeError(\n ERR_MSE_NOT_SUPPORTED,\n \"MediaSource Extensions (MSE) are not supported in this environment.\",\n \"MSE is required for the remux strategy. Use a browser that supports MSE, or try the fallback strategy.\",\n );\n }\n if (!MediaSource.isTypeSupported(options.mime)) {\n throw new AvbridgeError(\n ERR_MSE_CODEC_NOT_SUPPORTED,\n `This browser's MSE does not support \"${options.mime}\".`,\n \"The codec combination can't be played via remux in this browser. The player will try the next strategy automatically.\",\n );\n }\n\n this.mediaSource = new MediaSource();\n this.objectUrl = URL.createObjectURL(this.mediaSource);\n options.video.src = this.objectUrl;\n\n this.readyPromise = new Promise((resolve, reject) => {\n this.resolveReady = resolve;\n this.rejectReady = reject;\n });\n\n this.mediaSource.addEventListener(\"sourceopen\", () => {\n try {\n this.sourceBuffer = this.mediaSource.addSourceBuffer(options.mime);\n this.sourceBuffer.mode = \"segments\";\n this.sourceBuffer.addEventListener(\"updateend\", () => this.pump());\n this.resolveReady();\n options.onReady?.();\n } catch (err) {\n this.rejectReady(err instanceof Error ? err : new Error(String(err)));\n }\n });\n }\n\n ready(): Promise<void> {\n return this.readyPromise;\n }\n\n /** Queue a chunk of fMP4 bytes (init segment or media segment). */\n append(chunk: ArrayBuffer | Uint8Array): void {\n if (this.destroyed) return;\n const ab = chunk instanceof Uint8Array\n ? (chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength) as ArrayBuffer)\n : chunk;\n this.queue.push(ab);\n this.pump();\n }\n\n private pump(): void {\n const sb = this.sourceBuffer;\n if (!sb || sb.updating) return;\n\n // Apply deferred actions once the SourceBuffer has any data. Deferred\n // seek and deferred autoplay are independent — both can fire here, or\n // either alone. Setting `currentTime` before data exists causes the\n // browser to snap back to the nearest buffered range; calling `play()`\n // before data exists puts the video into a stuck waiting state.\n if (sb.buffered.length > 0) {\n if (this.pendingSeekTime !== null) {\n this.options.video.currentTime = this.pendingSeekTime;\n this.pendingSeekTime = null;\n } else if (!this.hasSnappedToFirstBuffered) {\n // First data arrival with no pending seek. If currentTime is\n // outside the first buffered range (typical for MPEG-TS sources\n // whose PTS doesn't start at 0), snap into the buffered range\n // so the video element doesn't wait forever for nonexistent data.\n const v = this.options.video;\n const firstStart = sb.buffered.start(0);\n const firstEnd = sb.buffered.end(0);\n if (v.currentTime < firstStart || v.currentTime > firstEnd) {\n v.currentTime = firstStart;\n }\n this.hasSnappedToFirstBuffered = true;\n }\n if (this.playOnSeek) {\n this.playOnSeek = false;\n this.options.video.play().catch(() => { /* ignore — autoplay may be blocked */ });\n }\n }\n\n const next = this.queue.shift();\n if (!next) return;\n try {\n sb.appendBuffer(next);\n } catch (err) {\n // QuotaExceededError → evict the oldest few seconds and retry once.\n if ((err as DOMException).name === \"QuotaExceededError\") {\n this.evict();\n try {\n sb.appendBuffer(next);\n return;\n } catch {\n /* fall through to error */\n }\n }\n this.rejectReady(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n private evict(): void {\n const sb = this.sourceBuffer;\n if (!sb || sb.buffered.length === 0) return;\n const start = sb.buffered.start(0);\n const current = this.options.video.currentTime;\n // Drop everything that's at least 10s behind the current position.\n if (current - start > 10) {\n try {\n sb.remove(start, current - 10);\n } catch {\n /* ignore */\n }\n }\n }\n\n /** Indicate the source is finished. Future seeks past the end will fail. */\n endOfStream(): void {\n if (this.endOfStreamCalled || this.destroyed) return;\n this.endOfStreamCalled = true;\n const tryEnd = () => {\n if (this.queue.length > 0 || this.sourceBuffer?.updating) {\n // Wait for the queue to drain.\n this.sourceBuffer?.addEventListener(\"updateend\", tryEnd, { once: true });\n return;\n }\n try {\n if (this.mediaSource.readyState === \"open\") {\n this.mediaSource.endOfStream();\n }\n } catch {\n /* ignore */\n }\n };\n tryEnd();\n }\n\n /** Seconds of media buffered ahead of the current playback position. */\n bufferedAhead(): number {\n const sb = this.sourceBuffer;\n if (!sb || sb.buffered.length === 0) return 0;\n const current = this.options.video.currentTime;\n for (let i = 0; i < sb.buffered.length; i++) {\n if (sb.buffered.start(i) <= current && sb.buffered.end(i) > current) {\n return sb.buffered.end(i) - current;\n }\n }\n return 0;\n }\n\n /** Total seconds of media buffered across all ranges. */\n totalBuffered(): number {\n const sb = this.sourceBuffer;\n if (!sb || sb.buffered.length === 0) return 0;\n let total = 0;\n for (let i = 0; i < sb.buffered.length; i++) {\n total += sb.buffered.end(i) - sb.buffered.start(i);\n }\n return total;\n }\n\n /** Number of chunks waiting in the append queue. */\n queueLength(): number {\n return this.queue.length;\n }\n\n /** Time to seek to once the SourceBuffer has data at this position. */\n private pendingSeekTime: number | null = null;\n /** Whether to resume playback after the deferred seek completes. */\n private playOnSeek = false;\n /**\n * On the very first data arrival, if `currentTime` falls outside the first\n * buffered range, snap it to the start of that range. MPEG-TS sources\n * commonly start their PTS at a non-zero value (e.g. ~1.5s); without this\n * snap, the video element sits at `currentTime=0` waiting forever for\n * data that doesn't exist.\n */\n private hasSnappedToFirstBuffered = false;\n\n /** Request that playback resumes automatically once the deferred seek fires. */\n setPlayOnSeek(play: boolean): void {\n this.playOnSeek = play;\n }\n\n /**\n * Discard all buffered media and schedule a deferred seek. The actual\n * `video.currentTime` assignment happens in `pump()` once the SourceBuffer\n * has data at the target position — setting it earlier causes the browser\n * to snap back to the nearest buffered range.\n */\n invalidate(seekTime: number): void {\n const sb = this.sourceBuffer;\n // Clear the pending queue — stale fragments from the old pump position.\n this.queue = [];\n this.pendingSeekTime = seekTime;\n this.hasSnappedToFirstBuffered = true; // explicit seek overrides the auto-snap\n if (!sb || sb.buffered.length === 0) return;\n try {\n const start = sb.buffered.start(0);\n const end = sb.buffered.end(sb.buffered.length - 1);\n sb.remove(start, end);\n } catch {\n /* ignore — sourcebuffer may be in updating state */\n }\n }\n\n destroy(): void {\n this.destroyed = true;\n this.queue = [];\n try {\n if (this.mediaSource.readyState === \"open\") this.mediaSource.endOfStream();\n } catch {\n /* ignore */\n }\n URL.revokeObjectURL(this.objectUrl);\n }\n}\n","import type { MediaContext } from \"../../types.js\";\nimport { MseSink } from \"./mse.js\";\nimport {\n avbridgeVideoToMediabunny,\n avbridgeAudioToMediabunny,\n buildMediabunnySourceFromInput,\n} from \"../../probe/mediabunny.js\";\n\n/**\n * Remux pipeline built against mediabunny's real API.\n *\n * Key design notes:\n *\n * - mediabunny's fMP4 muxer is a streaming muxer that requires monotonically\n * increasing timestamps. It cannot accept out-of-order packets after a seek.\n * Therefore, on each seek we create a **fresh** Output + sources + StreamTarget.\n * The MseSink handles the SourceBuffer reset via `invalidate()`.\n *\n * - Backpressure is enforced at two levels: in the WritableStream write handler\n * (limits append queue depth and total buffered time) and in the pump loop\n * (limits buffered-ahead and total buffered time). Without this, long files\n * dump gigabytes into the SourceBuffer and exhaust memory.\n */\nexport interface RemuxPipeline {\n start(fromTime?: number, autoPlay?: boolean): Promise<void>;\n seek(time: number, autoPlay?: boolean): Promise<void>;\n /** Update the autoplay intent mid-flight — used when play() arrives after seek() but before the MseSink has been constructed. */\n setAutoPlay(autoPlay: boolean): void;\n /**\n * Switch the active audio track. Tears down the current Output, rebuilds\n * with the new audio source, and resumes pumping at the given time.\n */\n setAudioTrack(trackId: number, timeSec: number, autoPlay: boolean): Promise<void>;\n destroy(): Promise<void>;\n stats(): Record<string, unknown>;\n}\n\nexport async function createRemuxPipeline(\n ctx: MediaContext,\n video: HTMLVideoElement,\n): Promise<RemuxPipeline> {\n const mb = await import(\"mediabunny\");\n\n const videoTrackInfo = ctx.videoTracks[0];\n if (!videoTrackInfo) throw new Error(\"remux: source has no video track\");\n\n // Map avbridge codec names back to mediabunny's enum strings.\n const mbVideoCodec = avbridgeVideoToMediabunny(videoTrackInfo.codec);\n if (!mbVideoCodec) {\n throw new Error(`remux: video codec \"${videoTrackInfo.codec}\" is not supported by mediabunny output`);\n }\n\n // Open the input. URL sources go through mediabunny's UrlSource so the\n // muxer streams via Range requests instead of buffering the whole file.\n const input = new mb.Input({\n source: await buildMediabunnySourceFromInput(mb, ctx.source),\n formats: mb.ALL_FORMATS,\n });\n const allTracks = await input.getTracks();\n const inputVideo = allTracks.find((t) => t.id === videoTrackInfo.id && t.isVideoTrack());\n if (!inputVideo || !inputVideo.isVideoTrack()) {\n throw new Error(\"remux: video track not found in input\");\n }\n\n // Pull the video WebCodecs decoder config once — used as `meta` on the\n // first packet after every Output rebuild.\n const videoConfig = await inputVideo.getDecoderConfig();\n\n // Packet sink for video — reused across seeks.\n const videoSink = new mb.EncodedPacketSink(inputVideo);\n\n // Audio selection is mutable: setAudioTrack() can swap it. The selected\n // audio derived state (input track, codec, sink, config) is rebuilt via\n // rebuildAudio() whenever the id changes.\n type InputAudioTrack = InstanceType<typeof mb.InputAudioTrack>;\n type AudioDecCfg = Awaited<ReturnType<InputAudioTrack[\"getDecoderConfig\"]>>;\n\n let selectedAudioTrackId: number | null = ctx.audioTracks[0]?.id ?? null;\n let inputAudio: InputAudioTrack | null = null;\n let mbAudioCodec: ReturnType<typeof avbridgeAudioToMediabunny> | null = null;\n let audioSink: InstanceType<typeof mb.EncodedPacketSink> | null = null;\n let audioConfig: AudioDecCfg | null = null;\n\n async function rebuildAudio(): Promise<void> {\n if (selectedAudioTrackId == null) {\n inputAudio = null;\n mbAudioCodec = null;\n audioSink = null;\n audioConfig = null;\n return;\n }\n const trackInfo = ctx.audioTracks.find((t) => t.id === selectedAudioTrackId);\n if (!trackInfo) {\n throw new Error(`remux: no audio track with id ${selectedAudioTrackId}`);\n }\n const newInput = allTracks.find((t) => t.id === trackInfo.id && t.isAudioTrack());\n if (!newInput || !newInput.isAudioTrack()) {\n throw new Error(\"remux: audio track not found in input\");\n }\n inputAudio = newInput;\n mbAudioCodec = avbridgeAudioToMediabunny(trackInfo.codec);\n audioSink = new mb.EncodedPacketSink(newInput);\n audioConfig = await newInput.getDecoderConfig();\n }\n\n await rebuildAudio();\n\n // MSE sink — created lazily on first output write, reused across seeks.\n let sink: MseSink | null = null;\n const stats = { videoPackets: 0, audioPackets: 0, bytesWritten: 0, fragments: 0 };\n\n let destroyed = false;\n let pumpToken = 0;\n let pendingAutoPlay = false;\n let pendingStartTime = 0;\n\n // The current Output instance. Recreated on each seek because mediabunny's\n // fMP4 muxer requires monotonically increasing timestamps.\n let currentOutput: InstanceType<typeof mb.Output> | null = null;\n\n /**\n * Create a fresh mediabunny Output wired to the MSE sink. Called once at\n * start and again on each seek.\n */\n function createOutput() {\n // Cancel the previous output if it exists.\n if (currentOutput) {\n try { void currentOutput.cancel(); } catch { /* ignore */ }\n }\n\n let mimePromise: Promise<string> | null = null;\n\n const writable = new WritableStream<{\n type: \"write\";\n data: Uint8Array<ArrayBuffer>;\n position: number;\n }>({\n write: async (chunk) => {\n if (destroyed) return;\n if (!sink) {\n const mime = await (mimePromise ??= output.getMimeType());\n sink = new MseSink({ mime, video });\n await sink.ready();\n // Apply deferred seek + autoPlay for the initial start.\n if (pendingStartTime > 0) {\n sink.invalidate(pendingStartTime);\n }\n sink.setPlayOnSeek(pendingAutoPlay);\n }\n // Backpressure: wait for the SourceBuffer append queue to drain.\n while (sink && !destroyed && (sink.queueLength() > 10 || sink.bufferedAhead() > 60 || sink.totalBuffered() > 120)) {\n await new Promise((r) => setTimeout(r, 500));\n }\n if (destroyed) return;\n sink.append(chunk.data);\n stats.bytesWritten += chunk.data.byteLength;\n stats.fragments++;\n },\n });\n\n const target = new mb.StreamTarget(writable);\n const output = new mb.Output({\n format: new mb.Mp4OutputFormat({ fastStart: \"fragmented\" }),\n target,\n });\n\n // Build the output sources.\n const videoSource = new mb.EncodedVideoPacketSource(mbVideoCodec!);\n output.addVideoTrack(videoSource);\n\n type AudioSourceCtorArg = ConstructorParameters<typeof mb.EncodedAudioPacketSource>[0];\n let audioSource: InstanceType<typeof mb.EncodedAudioPacketSource> | null = null;\n if (mbAudioCodec && inputAudio?.isAudioTrack()) {\n audioSource = new mb.EncodedAudioPacketSource(mbAudioCodec as AudioSourceCtorArg);\n output.addAudioTrack(audioSource);\n }\n\n currentOutput = output;\n return { output, videoSource, audioSource };\n }\n\n async function pumpLoop(token: number, fromTime: number) {\n const { output, videoSource, audioSource } = createOutput();\n\n await output.start();\n\n\n // Find the starting key packet so we never push partial GOPs.\n const startVideoPacket =\n fromTime > 0\n ? (await videoSink.getKeyPacket(fromTime)) ?? (await videoSink.getFirstPacket())\n : await videoSink.getFirstPacket();\n if (!startVideoPacket) return;\n\n const startAudioPacket = audioSink\n ? (audioSink && fromTime > 0\n ? (await audioSink.getPacket(fromTime)) ?? (await audioSink.getFirstPacket())\n : await audioSink.getFirstPacket())\n : null;\n\n const videoIter = videoSink.packets(startVideoPacket);\n const audioIter = audioSink && startAudioPacket ? audioSink.packets(startAudioPacket) : null;\n\n let vNext = await videoIter.next();\n let aNext = audioIter ? await audioIter.next() : { done: true as const, value: undefined };\n let firstVideo = true;\n let firstAudio = true;\n\n while (!destroyed && pumpToken === token && (!vNext.done || !aNext.done)) {\n // Backpressure: pause pumping when we've buffered enough.\n while (\n !destroyed &&\n pumpToken === token &&\n sink &&\n (sink.bufferedAhead() > 30 || sink.queueLength() > 20 || sink.totalBuffered() > 90)\n ) {\n await new Promise((r) => setTimeout(r, 500));\n }\n if (destroyed || pumpToken !== token) break;\n\n const vTs = !vNext.done ? vNext.value.timestamp : Number.POSITIVE_INFINITY;\n const aTs = !aNext.done ? aNext.value.timestamp : Number.POSITIVE_INFINITY;\n\n // Mediabunny's muxer requires the first packet on a fresh Output to\n // be a key packet. We fetched `startVideoPacket` via\n // `videoSink.getKeyPacket(fromTime)` so the first video packet is\n // guaranteed to be a keyframe — but a demuxer can hand us an audio\n // packet with a lower timestamp, which mediabunny rejects with\n // \"First packet must be a key packet.\" Force the first video\n // packet out before we let any audio through.\n const forceVideoFirst = firstVideo && !vNext.done;\n\n if (!vNext.done && (forceVideoFirst || vTs <= aTs)) {\n await videoSource.add(\n vNext.value,\n firstVideo && videoConfig ? { decoderConfig: videoConfig } : undefined,\n );\n firstVideo = false;\n stats.videoPackets++;\n vNext = await videoIter.next();\n } else if (audioIter && audioSource && !aNext.done) {\n await audioSource.add(\n aNext.value,\n firstAudio && audioConfig ? { decoderConfig: audioConfig } : undefined,\n );\n firstAudio = false;\n stats.audioPackets++;\n aNext = await audioIter.next();\n } else {\n break;\n }\n }\n\n if (!destroyed && pumpToken === token) {\n await output.finalize();\n sink?.endOfStream();\n }\n }\n\n return {\n async start(fromTime = 0, autoPlay = false) {\n // Store autoPlay/seekTime so the MseSink (created lazily on first\n // write) can apply the deferred seek and auto-play.\n pendingAutoPlay = autoPlay;\n pendingStartTime = fromTime;\n pumpLoop(++pumpToken, fromTime).catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] remux pipeline failed:\", err);\n try { sink?.destroy(); } catch { /* ignore */ }\n });\n },\n async seek(time, autoPlay = false) {\n if (sink) {\n sink.setPlayOnSeek(autoPlay);\n sink.invalidate(time);\n } else {\n pendingAutoPlay = autoPlay;\n pendingStartTime = time;\n }\n pumpLoop(++pumpToken, time).catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] remux pipeline reseek failed:\", err);\n });\n },\n setAutoPlay(autoPlay) {\n pendingAutoPlay = autoPlay;\n if (sink) sink.setPlayOnSeek(autoPlay);\n },\n async setAudioTrack(trackId, time, autoPlay) {\n if (selectedAudioTrackId === trackId) return;\n if (!ctx.audioTracks.some((t) => t.id === trackId)) {\n console.warn(\"[avbridge] remux: setAudioTrack — unknown track id\", trackId);\n return;\n }\n // Stop the current pump. The next pumpLoop() will build a fresh\n // Output that uses the newly-selected audio source.\n pumpToken++;\n selectedAudioTrackId = trackId;\n await rebuildAudio().catch((err) => {\n console.warn(\"[avbridge] remux: rebuildAudio failed:\", (err as Error).message);\n });\n // Tear down the existing MseSink — the audio codec may have changed,\n // and the SourceBuffer's mime is fixed at construction time. The next\n // createOutput will recompute `getMimeType()` and the write handler\n // will lazily build a new sink.\n if (sink) {\n try { sink.destroy(); } catch { /* ignore */ }\n sink = null;\n }\n pendingAutoPlay = autoPlay;\n pendingStartTime = time;\n pumpLoop(++pumpToken, time).catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] remux pipeline setAudioTrack pump failed:\", err);\n });\n },\n async destroy() {\n destroyed = true;\n pumpToken++;\n try { if (currentOutput) await currentOutput.cancel(); } catch { /* ignore */ }\n try { await input.dispose(); } catch { /* ignore */ }\n sink?.destroy();\n },\n stats() {\n return { ...stats, decoderType: \"remux\" };\n },\n };\n}\n\n","import type { MediaContext, PlaybackSession } from \"../../types.js\";\nimport { createRemuxPipeline, type RemuxPipeline } from \"./pipeline.js\";\n\n/**\n * Strategy entry: build the remux pipeline, then expose a {@link PlaybackSession}\n * that delegates to the underlying `<video>` element for playback control and\n * to the pipeline for source-side seek invalidation.\n */\nexport async function createRemuxSession(\n context: MediaContext,\n video: HTMLVideoElement,\n): Promise<PlaybackSession> {\n let pipeline: RemuxPipeline;\n try {\n pipeline = await createRemuxPipeline(context, video);\n } catch (err) {\n throw new Error(\n `remux strategy failed to start: ${(err as Error).message}. The container or codec combination is not supported by mediabunny + MSE on this browser.`,\n );\n }\n\n // Don't pump yet — wait for the first play() or seek() to start from the\n // right position. The player's strategy-switch flow calls seek(currentTime)\n // immediately after creation, so pumping from 0 here would be wasted work.\n let started = false;\n let wantPlay = false;\n\n return {\n strategy: \"remux\",\n async play() {\n wantPlay = true;\n if (!started) {\n // First play — start the pump. The deferred seek in MseSink will\n // call video.play() once data is available (via autoPlay flag).\n started = true;\n await pipeline.start(video.currentTime || 0, true);\n return;\n }\n // seek() may have already started the pump with autoPlay=false\n // (strategy-switch flow calls seek before play). Flip the pipeline's\n // pending autoPlay so the MseSink fires video.play() once buffered\n // data lands, and also attempt an immediate video.play() in case the\n // sink is already wired up. The immediate call can reject when\n // video.src hasn't been set yet — that's fine, the deferred path will\n // catch it.\n pipeline.setAutoPlay(true);\n try {\n await video.play();\n } catch {\n /* sink not ready yet; setAutoPlay will handle playback on first buffered write */\n }\n },\n pause() {\n wantPlay = false;\n video.pause();\n },\n async seek(time) {\n if (!started) {\n started = true;\n // autoPlay=true so playback starts as soon as data arrives at\n // the seek target (handles the strategy-switch case where play()\n // is called right after seek()).\n await pipeline.seek(time, wantPlay);\n return;\n }\n const wasPlaying = !video.paused;\n await pipeline.seek(time, wasPlaying || wantPlay);\n // HTMLMediaElement contract: Firefox + WebKit's MSE doesn't\n // reliably fire `seeked` after a SourceBuffer remove+refill\n // cycle (Chromium does). Dispatch manually so consumers get a\n // consistent signal across browsers. Duplicating a native\n // `seeked` is harmless per spec.\n queueMicrotask(() => {\n try { video.dispatchEvent(new Event(\"seeked\")); } catch { /* ignore */ }\n });\n },\n async setAudioTrack(id) {\n if (!context.audioTracks.some((t) => t.id === id)) {\n console.warn(\"[avbridge] remux: setAudioTrack — unknown track id\", id);\n return;\n }\n const wasPlaying = !video.paused;\n const time = video.currentTime || 0;\n // Not yet started? Just note the selection and let play()/seek() drive.\n if (!started) {\n started = true;\n await pipeline.setAudioTrack(id, time, wantPlay || wasPlaying);\n return;\n }\n await pipeline.setAudioTrack(id, time, wasPlaying || wantPlay);\n },\n async setSubtitleTrack(id) {\n const tracks = video.textTracks;\n for (let i = 0; i < tracks.length; i++) {\n tracks[i].mode = i === id ? \"showing\" : \"disabled\";\n }\n },\n getCurrentTime() {\n return video.currentTime || 0;\n },\n async destroy() {\n video.pause();\n await pipeline.destroy();\n video.removeAttribute(\"src\");\n video.load();\n },\n getRuntimeStats() {\n return pipeline.stats();\n },\n };\n}\n","import type { ClockSource } from \"./audio-output.js\";\nimport { SubtitleOverlay } from \"../../subtitles/render.js\";\n\n/**\n * Renders decoded `VideoFrame`s into a 2D canvas overlaid on the user's\n * `<video>` element. The fallback strategy never assigns a src to the video,\n * so we hide it and put the canvas in its place visually.\n *\n * The renderer has two modes:\n *\n * 1. **Pre-roll** — `clock.isPlaying()` is false. The very first decoded\n * frame is painted as a \"poster\" so the user sees something while audio\n * buffers; subsequent frames stay queued without being dropped.\n *\n * 2. **Synced** — `clock.isPlaying()` is true. On each rAF tick, find the\n * latest frame whose timestamp ≤ `clock.now() + lookahead` and paint it.\n * Drop any older frames as \"late.\"\n *\n * The pre-roll behavior is what fixes the cold-start \"first minute is all\n * dropped\" problem: without it, the wall clock raced ahead while the\n * decoder was still warming up, and every frame was already in the past by\n * the time it landed in the queue.\n */\n// Periodic debug log — throttled to once per second so it doesn't\n// flood the console at 60Hz rAF rate.\nfunction isDebug(): boolean {\n return typeof globalThis !== \"undefined\" && !!(globalThis as Record<string, unknown>).AVBRIDGE_DEBUG;\n}\nlet lastDebugLog = 0;\n\nexport class VideoRenderer {\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D;\n private queue: VideoFrame[] = [];\n private rafHandle: number | null = null;\n private destroyed = false;\n\n private framesPainted = 0;\n private framesDroppedLate = 0;\n private framesDroppedOverflow = 0;\n private prerolled = false;\n /** Wall-clock time of the last paint, in ms (performance.now()). */\n private lastPaintWall = 0;\n /** Minimum ms between paints — paces video at roughly source fps. */\n private paintIntervalMs: number;\n /** Cumulative count of frames skipped because all PTS are in the future. */\n private ticksWaiting = 0;\n /** Cumulative count of ticks where PTS mode painted a frame. */\n private ticksPainted = 0;\n\n /**\n * Subtitle overlay div attached to the stage wrapper alongside the\n * canvas. Created lazily when subtitle tracks are attached via the\n * target's `<track>` children. Canvas strategies (hybrid, fallback)\n * hide the <video>, so we can't rely on the browser's native cue\n * rendering; we read TextTrack.cues and render into this overlay.\n */\n private subtitleOverlay: SubtitleOverlay | null = null;\n private subtitleTrack: TextTrack | null = null;\n\n /**\n * Calibration offset (microseconds) between video PTS and audio clock.\n * Video PTS and AudioContext.currentTime can drift ~0.1% relative to\n * each other (different clock domains). Over 45 minutes that's 2.6s.\n * We measure the offset on the first painted frame and update it\n * periodically so the PTS comparison stays calibrated.\n */\n private ptsCalibrationUs = 0;\n private ptsCalibrated = false;\n private lastCalibrationWall = 0;\n\n /** Resolves once the first decoded frame has been enqueued. */\n readonly firstFrameReady: Promise<void>;\n private resolveFirstFrame!: () => void;\n\n constructor(\n private readonly target: HTMLVideoElement,\n private readonly clock: ClockSource,\n fps = 30,\n ) {\n this.paintIntervalMs = Math.max(1, 1000 / fps);\n this.firstFrameReady = new Promise<void>((resolve) => {\n this.resolveFirstFrame = resolve;\n });\n\n this.canvas = document.createElement(\"canvas\");\n // `object-fit` is driven by the `--avbridge-fit` custom property so the\n // `<avbridge-video>` element's `fit` attribute can retarget the canvas\n // without reaching into the fallback strategy. Default is `contain` —\n // letterboxes the canvas bitmap (sized to frame.displayWidth ×\n // displayHeight in paint()) inside the stage so portrait / non-stage-aspect\n // content isn't stretched. Canvas is a replaced element, so object-fit applies.\n this.canvas.style.cssText =\n \"position:absolute;left:0;top:0;width:100%;height:100%;background:black;object-fit:var(--avbridge-fit, contain);\";\n\n // Attach the canvas next to the video. When the video lives inside an\n // `<avbridge-video>` shadow root, `target.parentElement` is the\n // positioned `<div part=\"stage\">` wrapper the element created\n // precisely for this purpose. When the video is used standalone\n // (legacy `createPlayer({ target: videoEl })` path), we fall back to\n // `parentNode` — which handles plain Elements, and also ShadowRoots\n // if someone inserts a bare <video> inside their own shadow DOM\n // without a wrapper.\n const parent: ParentNode | null =\n (target.parentElement as ParentNode | null) ?? target.parentNode;\n if (parent && parent instanceof HTMLElement) {\n if (getComputedStyle(parent).position === \"static\") {\n parent.style.position = \"relative\";\n }\n }\n if (parent) {\n parent.insertBefore(this.canvas, target);\n } else {\n // No parent at all — the target is detached. Fall back to appending\n // the canvas to document.body so at least the frames are visible\n // somewhere while the consumer fixes their DOM layout. This is a\n // loud fallback: log a warning so the misuse is obvious.\n // eslint-disable-next-line no-console\n console.warn(\n \"[avbridge] fallback renderer: target <video> has no parent; \" +\n \"appending canvas to document.body as a fallback.\",\n );\n document.body.appendChild(this.canvas);\n }\n target.style.visibility = \"hidden\";\n\n // Create a subtitle overlay on the same parent as the canvas so cues\n // appear over the rendered video. Shows nothing until a TextTrack\n // gets attached via attachSubtitleTracks.\n const overlayParent = parent instanceof HTMLElement ? parent : document.body;\n this.subtitleOverlay = new SubtitleOverlay(overlayParent);\n // Watch for <track> children on the target <video>. When one is\n // added, grab its TextTrack and poll cues from it each tick.\n this.watchTextTracks(target);\n\n const ctx = this.canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"video renderer: failed to acquire 2D context\");\n this.ctx = ctx;\n\n this.tick = this.tick.bind(this);\n this.rafHandle = requestAnimationFrame(this.tick);\n }\n\n /** True once at least one frame has been enqueued. */\n hasFrames(): boolean {\n return this.queue.length > 0 || this.framesPainted > 0;\n }\n\n /** Current depth of the frame queue. Used by the decoder for backpressure. */\n queueDepth(): number {\n return this.queue.length;\n }\n\n /**\n * Soft cap for decoder backpressure. The decoder pump throttles when\n * `queueDepth() >= queueHighWater`. Set high enough that normal decode\n * bursts don't trigger the renderer's overflow-drop loop (which runs at\n * every paint), but low enough that the decoder doesn't run unboundedly\n * ahead. The hard cap in `enqueue()` is 64.\n */\n readonly queueHighWater = 30;\n\n enqueue(frame: VideoFrame): void {\n if (this.destroyed) {\n frame.close();\n return;\n }\n this.queue.push(frame);\n if (this.queue.length === 1 && this.framesPainted === 0) {\n this.resolveFirstFrame();\n }\n // Hard cap. Should rarely trigger because the decoder backs off at\n // queueHighWater (30) and the drift correction trims gently. This is\n // the last-resort defense against runaway producers.\n while (this.queue.length > 60) {\n this.queue.shift()?.close();\n this.framesDroppedOverflow++;\n }\n }\n\n /**\n * Watch the target <video>'s textTracks list. When a track is added,\n * grab it and start polling cues on each render tick. Existing tracks\n * (if any) are picked up immediately.\n */\n private watchTextTracks(target: HTMLVideoElement): void {\n const pick = () => {\n if (this.subtitleTrack) return;\n const tracks = target.textTracks;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] watchTextTracks pick() — ${tracks.length} tracks`);\n }\n for (let i = 0; i < tracks.length; i++) {\n const t = tracks[i];\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] track ${i}: kind=${t.kind} mode=${t.mode} cues=${t.cues?.length ?? 0}`);\n }\n if (t.kind === \"subtitles\" || t.kind === \"captions\") {\n this.subtitleTrack = t;\n t.mode = \"hidden\"; // hidden means \"cues available via API, don't render\"\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] picked track, mode=hidden`);\n }\n // Listen for cue load completion\n const trackEl = target.querySelector(`track[srclang=\"${t.language}\"]`) as HTMLTrackElement | null;\n if (trackEl) {\n trackEl.addEventListener(\"load\", () => {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] track element loaded, cues=${t.cues?.length ?? 0}`);\n }\n });\n trackEl.addEventListener(\"error\", (ev) => {\n // eslint-disable-next-line no-console\n console.warn(`[avbridge:subs] track element error:`, ev);\n });\n }\n break;\n }\n }\n };\n pick();\n if (typeof target.textTracks.addEventListener === \"function\") {\n target.textTracks.addEventListener(\"addtrack\", (e) => {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(\"[avbridge:subs] addtrack event fired\");\n }\n void e;\n pick();\n });\n }\n }\n\n private _loggedCues = false;\n\n /** Find the active cue (if any) for the given media time. */\n private updateSubtitles(): void {\n if (!this.subtitleOverlay || !this.subtitleTrack) return;\n const cues = this.subtitleTrack.cues;\n if (!cues || cues.length === 0) return;\n if (isDebug() && !this._loggedCues) {\n this._loggedCues = true;\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] cues available: ${cues.length}, first start=${cues[0].startTime}, last end=${cues[cues.length-1].endTime}`);\n }\n const t = this.clock.now();\n let activeText = \"\";\n for (let i = 0; i < cues.length; i++) {\n const c = cues[i];\n if (t >= c.startTime && t <= c.endTime) {\n const vttCue = c as VTTCue & { text?: string };\n activeText = vttCue.text ?? \"\";\n break;\n }\n }\n // Strip VTT tags for plain rendering (e.g. <c.en> voice tags)\n this.subtitleOverlay.setText(activeText.replace(/<[^>]+>/g, \"\"));\n }\n\n private tick(): void {\n if (this.destroyed) return;\n this.rafHandle = requestAnimationFrame(this.tick);\n\n this.updateSubtitles();\n\n if (this.queue.length === 0) return;\n\n const playing = this.clock.isPlaying();\n\n // Pre-roll: paint the very first frame as a poster while audio buffers.\n if (!playing) {\n if (!this.prerolled) {\n const head = this.queue.shift()!;\n this.paint(head);\n head.close();\n this.prerolled = true;\n this.lastPaintWall = performance.now();\n }\n return;\n }\n\n // PTS-based painting: find the latest frame whose presentation time\n // has arrived (timestamp ≤ audio clock), paint it, and discard any\n // older frames. This produces correct cadence at any display refresh\n // rate and any source fps — no 3:2 pulldown artifacts.\n //\n // Fallback: if frame timestamps are unreliable (all zero, synthetic),\n // fall back to wall-clock pacing as before.\n const rawAudioNowUs = this.clock.now() * 1_000_000;\n const headTs = this.queue[0].timestamp ?? 0;\n const hasPts = headTs > 0 || this.queue.length > 1;\n\n if (hasPts) {\n // Calibration: video PTS and audio clock (AudioContext.currentTime)\n // live in different clock domains with a fixed offset (different epoch)\n // plus a small rate drift (~7ms/s). We snap the offset on first paint\n // and re-snap every 10 seconds. Between snaps, max drift is ~70ms\n // (under 2 frames at 24fps, below lip-sync perception threshold).\n const wallNow = performance.now();\n if (!this.ptsCalibrated || wallNow - this.lastCalibrationWall > 10_000) {\n this.ptsCalibrationUs = headTs - rawAudioNowUs;\n this.ptsCalibrated = true;\n this.lastCalibrationWall = wallNow;\n }\n\n const audioNowUs = rawAudioNowUs + this.ptsCalibrationUs;\n const frameDurationUs = this.paintIntervalMs * 1000;\n const deadlineUs = audioNowUs + frameDurationUs;\n\n let bestIdx = -1;\n for (let i = 0; i < this.queue.length; i++) {\n const ts = this.queue[i].timestamp ?? 0;\n if (ts <= deadlineUs) {\n bestIdx = i;\n } else {\n break;\n }\n }\n\n if (bestIdx < 0) {\n this.ticksWaiting++;\n if (isDebug()) {\n const now = performance.now();\n if (now - lastDebugLog > 1000) {\n const headPtsMs = (headTs / 1000).toFixed(1);\n const audioMs = (audioNowUs / 1000).toFixed(1);\n const rawDriftMs = ((headTs - rawAudioNowUs) / 1000).toFixed(1);\n const calibMs = (this.ptsCalibrationUs / 1000).toFixed(1);\n // eslint-disable-next-line no-console\n console.log(\n `[avbridge:renderer] WAIT q=${this.queue.length} headPTS=${headPtsMs}ms calibAudio=${audioMs}ms ` +\n `rawDrift=${rawDriftMs}ms calib=${calibMs}ms painted=${this.framesPainted} dropped=${this.framesDroppedLate}`,\n );\n lastDebugLog = now;\n }\n }\n return;\n }\n\n // Only drop frames that are more than 2 frame-durations behind.\n const dropThresholdUs = audioNowUs - frameDurationUs * 2;\n let dropped = 0;\n while (bestIdx > 0) {\n const ts = this.queue[0].timestamp ?? 0;\n if (ts < dropThresholdUs) {\n this.queue.shift()?.close();\n this.framesDroppedLate++;\n bestIdx--;\n dropped++;\n } else {\n break;\n }\n }\n\n this.ticksPainted++;\n\n if (isDebug()) {\n const now = performance.now();\n if (now - lastDebugLog > 1000) {\n const paintedTs = (this.queue[0]?.timestamp ?? 0);\n const audioMs = (audioNowUs / 1000).toFixed(1);\n const ptsMs = (paintedTs / 1000).toFixed(1);\n const rawDriftMs = ((paintedTs - rawAudioNowUs) / 1000).toFixed(1);\n const calibMs = (this.ptsCalibrationUs / 1000).toFixed(1);\n // eslint-disable-next-line no-console\n console.log(\n `[avbridge:renderer] PAINT q=${this.queue.length} calibAudio=${audioMs}ms nextPTS=${ptsMs}ms ` +\n `rawDrift=${rawDriftMs}ms calib=${calibMs}ms dropped=${dropped} total_drops=${this.framesDroppedLate} painted=${this.framesPainted}`,\n );\n lastDebugLog = now;\n }\n }\n\n const frame = this.queue.shift()!;\n this.paint(frame);\n frame.close();\n this.lastPaintWall = performance.now();\n return;\n }\n\n // Wall-clock fallback: used when timestamps are unreliable (all zero).\n const wallNow = performance.now();\n if (wallNow - this.lastPaintWall < this.paintIntervalMs - 2) return;\n\n const frame = this.queue.shift()!;\n this.paint(frame);\n frame.close();\n this.lastPaintWall = wallNow;\n }\n\n private paint(frame: VideoFrame): void {\n if (\n this.canvas.width !== frame.displayWidth ||\n this.canvas.height !== frame.displayHeight\n ) {\n this.canvas.width = frame.displayWidth;\n this.canvas.height = frame.displayHeight;\n }\n try {\n this.ctx.drawImage(frame, 0, 0, this.canvas.width, this.canvas.height);\n this.framesPainted++;\n } catch (err) {\n // Log only once so a structurally broken frame format doesn't spam\n // the console at 60 Hz, but we still find out about it.\n if (this.framesPainted === 0 && this.framesDroppedLate === 0) {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] canvas drawImage failed:\", err);\n }\n }\n }\n\n /** Discard all queued frames. Used by seek to drop stale buffers. */\n flush(): void {\n const count = this.queue.length;\n while (this.queue.length > 0) this.queue.shift()?.close();\n this.prerolled = false;\n this.ptsCalibrated = false; // recalibrate at new seek position\n if (isDebug() && count > 0) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:renderer] FLUSH discarded=${count} painted=${this.framesPainted} drops=${this.framesDroppedLate}`);\n }\n }\n\n stats(): Record<string, unknown> {\n return {\n framesPainted: this.framesPainted,\n framesDroppedLate: this.framesDroppedLate,\n framesDroppedOverflow: this.framesDroppedOverflow,\n queueDepth: this.queue.length,\n };\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafHandle != null) cancelAnimationFrame(this.rafHandle);\n this.flush();\n if (this.subtitleOverlay) { this.subtitleOverlay.destroy(); this.subtitleOverlay = null; }\n this.subtitleTrack = null;\n this.canvas.remove();\n this.target.style.visibility = \"\";\n }\n}\n","/**\n * Web Audio output for the fallback strategy.\n *\n * Owns the **media-time clock** for fallback playback. Audio is the master:\n * decoded video frames are presented based on what `now()` returns here.\n *\n * State machine:\n *\n * ┌──────┐ schedule() ┌──────┐ ┌────────┐\n * │ idle │ ───────────▶ │ idle │ ── start() ──▶│ playing│\n * └──────┘ (queues) └──────┘ └────┬───┘\n * ▲ │\n * │ │ pause()\n * │ ▼\n * │ ┌────────┐\n * └────────────── reset(t) ─────────────── ── │ paused │\n * └────────┘\n *\n * - **idle**: AudioContext is suspended (no playback). `schedule()` queues\n * samples in `pendingQueue`; `now()` returns `mediaTimeOfAnchor`.\n * - **playing**: AudioContext is running. `schedule()` writes directly to\n * the audio graph at the right time. `now()` advances with `ctx.currentTime`.\n * - **paused**: AudioContext is suspended. `now()` returns the media time\n * captured at pause. `start()` resumes.\n *\n * Key invariant: between any two `start()` calls, `mediaTimeOfNext` (the\n * media time of the next sample to be scheduled) must equal the media time\n * the playback is at. This is what makes the cold-start race go away — we\n * never schedule audio with a stale wall-clock anchor.\n */\n\ninterface PendingChunk {\n samples: Float32Array;\n channels: number;\n sampleRate: number;\n frameCount: number;\n durationSec: number;\n}\n\nexport interface ClockSource {\n /** Current media time in seconds. */\n now(): number;\n /** True if media is currently playing (audio scheduler is running). */\n isPlaying(): boolean;\n}\n\nexport class AudioOutput implements ClockSource {\n private ctx: AudioContext;\n private gain: GainNode;\n\n private state: \"idle\" | \"playing\" | \"paused\" = \"idle\";\n\n /**\n * Wall-clock fallback mode. When true, this output behaves as if audio\n * is unavailable — `now()` advances from `performance.now()` instead of\n * the audio context, `schedule()` is a no-op, and `bufferAhead()` returns\n * Infinity so the session's `waitForBuffer()` doesn't block on audio.\n *\n * Set by the decoder via {@link setNoAudio} when audio decode init fails.\n * This is what lets video play even when the audio codec isn't supported\n * by the loaded libav variant.\n */\n private noAudio = false;\n /** Wall-clock anchor (ms from `performance.now()`) for noAudio mode. */\n private wallAnchorMs = 0;\n\n /** Media time at which the next sample will be scheduled. */\n private mediaTimeOfNext = 0;\n\n /** Anchor: media time `mediaTimeOfAnchor` corresponds to ctx time `ctxTimeAtAnchor`. */\n private mediaTimeOfAnchor = 0;\n private ctxTimeAtAnchor = 0;\n\n private pendingQueue: PendingChunk[] = [];\n\n private framesScheduled = 0;\n private destroyed = false;\n\n /** User-set volume (0..1). Applied to the gain node. */\n private _volume = 1;\n /** User-set muted flag. When true, gain is forced to 0. */\n private _muted = false;\n /** Playback rate. Scales the media clock and each AudioBufferSourceNode's\n * playbackRate so audio pitches up/down accordingly (same as native\n * <video>.playbackRate). Default 1. */\n private _rate = 1;\n\n constructor() {\n this.ctx = new AudioContext();\n this.gain = this.ctx.createGain();\n this.gain.connect(this.ctx.destination);\n }\n\n /** Set volume (0..1). Applied immediately to the gain node. */\n setVolume(v: number): void {\n this._volume = Math.max(0, Math.min(1, v));\n this.applyGain();\n }\n\n getVolume(): number {\n return this._volume;\n }\n\n /** Set muted. When true, output is silenced regardless of volume. */\n setMuted(m: boolean): void {\n this._muted = m;\n this.applyGain();\n }\n\n getMuted(): boolean {\n return this._muted;\n }\n\n /** Set playback rate. Scales the media clock and pitches audio output\n * (same as native <video>.playbackRate — speed without pitch correction).\n * Rebases the anchor so the clock transition is seamless. */\n setPlaybackRate(rate: number): void {\n if (rate === this._rate) return;\n // Rebase anchor at the current media time before changing rate,\n // so the clock doesn't jump.\n const t = this.now();\n this.mediaTimeOfAnchor = t;\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.wallAnchorMs = performance.now();\n this._rate = rate;\n }\n\n getPlaybackRate(): number {\n return this._rate;\n }\n\n private applyGain(): void {\n const target = this._muted ? 0 : this._volume;\n try { this.gain.gain.value = target; } catch { /* ignore */ }\n }\n\n /**\n * Switch into wall-clock fallback mode. Called by the decoder when no\n * audio decoder could be initialized for the source. Once set, this\n * output drives playback time from `performance.now()` and ignores\n * any incoming audio samples.\n */\n setNoAudio(): void {\n this.noAudio = true;\n }\n\n // ── ClockSource ────────────────────────────────────────────────────────\n\n now(): number {\n if (this.noAudio) {\n if (this.state === \"playing\") {\n return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1000 * this._rate;\n }\n return this.mediaTimeOfAnchor;\n }\n if (this.state === \"playing\") {\n return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor) * this._rate;\n }\n return this.mediaTimeOfAnchor;\n }\n\n isPlaying(): boolean {\n return this.state === \"playing\";\n }\n\n // ── Buffering ─────────────────────────────────────────────────────────\n\n /**\n * How many seconds of audio are buffered ahead of the current playback\n * position. While idle, this counts the pending queue. While playing,\n * it counts how far `mediaTimeOfNext` is ahead of `now()`.\n */\n bufferAhead(): number {\n // In wall-clock mode, no samples are ever scheduled — the buffer is\n // genuinely empty. Callers that want to gate cold-start should check\n // {@link isNoAudio} and skip the audio gate entirely instead.\n if (this.noAudio) return 0;\n if (this.state === \"idle\") {\n let sec = 0;\n for (const c of this.pendingQueue) sec += c.durationSec;\n return sec;\n }\n return Math.max(0, this.mediaTimeOfNext - this.now());\n }\n\n /** True if this output is in wall-clock fallback mode (no audio decode). */\n isNoAudio(): boolean {\n return this.noAudio;\n }\n\n /**\n * Schedule a chunk of decoded samples. Queues internally while idle (cold\n * start or post-seek), schedules directly to the audio graph while playing.\n * In wall-clock mode, samples are silently discarded.\n */\n schedule(samples: Float32Array, channels: number, sampleRate: number): void {\n if (this.destroyed || this.noAudio) return;\n const frameCount = samples.length / channels;\n const durationSec = frameCount / sampleRate;\n\n if (this.state === \"idle\" || this.state === \"paused\") {\n this.pendingQueue.push({ samples, channels, sampleRate, frameCount, durationSec });\n return;\n }\n\n this.scheduleNow(samples, channels, sampleRate, frameCount);\n }\n\n private scheduleNow(\n samples: Float32Array,\n channels: number,\n sampleRate: number,\n frameCount: number,\n ): void {\n const buffer = this.ctx.createBuffer(channels, frameCount, sampleRate);\n for (let ch = 0; ch < channels; ch++) {\n const channelData = buffer.getChannelData(ch);\n for (let i = 0; i < frameCount; i++) {\n channelData[i] = samples[i * channels + ch];\n }\n }\n const node = this.ctx.createBufferSource();\n node.buffer = buffer;\n node.connect(this.gain);\n // Pitch the audio to match the playback rate (same as native <video>).\n if (this._rate !== 1) node.playbackRate.value = this._rate;\n\n // Convert media time → ctx time using the anchor + rate. At rate=2,\n // each second of media time occupies 0.5s of ctx time.\n let ctxStart = this.ctxTimeAtAnchor + (this.mediaTimeOfNext - this.mediaTimeOfAnchor) / this._rate;\n\n // When the decoder is slower than realtime, `ctxStart` falls into\n // the past (ctx.currentTime has already passed it). Clamping each\n // sample to `ctx.currentTime` individually (the old behavior)\n // caused every stale sample in a burst to start at *the same\n // instant*, stacking them on top of each other — the audible\n // symptom was a series of clicks / a chord of stuttering cook\n // packets.\n //\n // Correct behavior: when the first sample of a burst is behind,\n // *rebase the anchor forward* so ctxStart = ctx.currentTime now.\n // Subsequent samples in the same burst then schedule at\n // ctxStart + offset as usual, laying out sequentially on the\n // timeline instead of piling up. The downside is a visible jump\n // in the audio clock — but the alternative was silent corruption.\n // `now()` readers (the video renderer) just see the clock step\n // forward and drop any frames older than the new time.\n if (ctxStart < this.ctx.currentTime) {\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.mediaTimeOfAnchor = this.mediaTimeOfNext;\n ctxStart = this.ctx.currentTime;\n }\n\n node.start(ctxStart);\n\n this.mediaTimeOfNext += frameCount / sampleRate;\n this.framesScheduled++;\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n /**\n * Start (or resume) playback. On a cold start (or after a reset), drains\n * the pending queue scheduling all queued samples to play starting at\n * `ctx.currentTime + STARTUP_DELAY`. On resume from pause, just re-anchors\n * the media↔ctx time mapping and unsuspends the context.\n */\n async start(): Promise<void> {\n if (this.destroyed || this.state === \"playing\") return;\n\n // Wall-clock mode: no audio context involved. Anchor to performance.now()\n // and let `now()` advance from there. The renderer's tick loop will see\n // `isPlaying() === true` and start painting frames.\n if (this.noAudio) {\n this.wallAnchorMs = performance.now();\n this.state = \"playing\";\n return;\n }\n\n if (this.ctx.state === \"suspended\") {\n await this.ctx.resume();\n }\n\n // Reconnect the gain node — pause() disconnects it to cut off\n // in-flight audio instantly. Safe to call even if already connected.\n try { this.gain.connect(this.ctx.destination); } catch { /* ignore */ }\n\n if (this.state === \"paused\") {\n // Resume: media time should continue from where we paused. ctx.currentTime\n // is preserved across suspend/resume, so re-anchoring it to \"now\" with\n // the same mediaTimeOfAnchor gives a continuous clock.\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.state = \"playing\";\n // Drain anything that was scheduled while paused.\n const drain = this.pendingQueue;\n this.pendingQueue = [];\n for (const c of drain) {\n this.scheduleNow(c.samples, c.channels, c.sampleRate, c.frameCount);\n }\n return;\n }\n\n // Cold start (or post-seek). Anchor: the first sample we scheduled lands\n // at ctxTimeAtAnchor (a tiny bit in the future), and that ctx time\n // corresponds to media time mediaTimeOfAnchor.\n const STARTUP_DELAY = 0.05;\n this.ctxTimeAtAnchor = this.ctx.currentTime + STARTUP_DELAY;\n this.mediaTimeOfNext = this.mediaTimeOfAnchor;\n this.state = \"playing\";\n\n const drain = this.pendingQueue;\n this.pendingQueue = [];\n for (const c of drain) {\n this.scheduleNow(c.samples, c.channels, c.sampleRate, c.frameCount);\n }\n }\n\n /** Pause playback. Suspends the audio context. */\n async pause(): Promise<void> {\n if (this.state !== \"playing\") return;\n this.mediaTimeOfAnchor = this.now();\n this.state = \"paused\";\n if (this.noAudio) return;\n // Disconnect the gain node immediately so any in-flight scheduled\n // buffers are silenced instantly. ctx.suspend() is async and\n // already-started AudioBufferSourceNodes keep playing until the\n // context actually suspends — without the disconnect, audio bleeds\n // through for ~200ms after pause().\n try { this.gain.disconnect(); } catch { /* ignore */ }\n if (this.ctx.state === \"running\") {\n await this.ctx.suspend();\n }\n }\n\n /**\n * Reset to a new media time. Discards all queued and scheduled audio,\n * disconnects the gain node so any in-flight scheduled buffers are cut\n * off, and returns to the idle state. Used by `seek()`.\n *\n * After reset, callers should re-buffer audio (the decoder will start\n * supplying new samples) and then call `start()` to resume playback.\n */\n async reset(newMediaTime: number): Promise<void> {\n if (this.noAudio) {\n this.pendingQueue = [];\n this.mediaTimeOfAnchor = newMediaTime;\n this.wallAnchorMs = performance.now();\n this.state = \"idle\";\n return;\n }\n\n try { this.gain.disconnect(); } catch { /* ignore */ }\n this.gain = this.ctx.createGain();\n this.gain.connect(this.ctx.destination);\n this.applyGain();\n\n this.pendingQueue = [];\n this.mediaTimeOfAnchor = newMediaTime;\n this.mediaTimeOfNext = newMediaTime;\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.state = \"idle\";\n\n if (this.ctx.state === \"running\") {\n await this.ctx.suspend();\n }\n }\n\n stats(): Record<string, unknown> {\n return {\n framesScheduled: this.framesScheduled,\n bufferAhead: this.bufferAhead(),\n audioState: this.state,\n clockMode: this.noAudio ? \"wall\" : \"audio\",\n };\n }\n\n destroy(): void {\n this.destroyed = true;\n try { this.ctx.close(); } catch { /* ignore */ }\n }\n}\n","import type { MediaContext, AudioCodec, VideoCodec } from \"../../types.js\";\nimport type { LibavVariant } from \"./libav-loader.js\";\n\n/**\n * Decide which libav.js variant to load for a given media context.\n *\n * - **webcodecs** (~5 MB, npm) — modern formats only, designed for the\n * WebCodecs bridge. Used when the codec is browser-supported and we just\n * need libav.js for demuxing or as a parser source.\n *\n * - **avbridge** (custom build, vendor/libav/) — has the AVI/ASF/FLV demuxers\n * and the legacy decoders (WMV3, MPEG-4 Part 2, VC-1, MS-MPEG4 v1/2/3,\n * AC-3, WMA*). Required for any of those formats; the npm variants ship\n * none of them.\n *\n * Rule: pick \"avbridge\" if either the container or any codec is one only the\n * custom build can handle. Otherwise pick \"webcodecs\".\n */\n\nconst LEGACY_CONTAINERS = new Set([\"avi\", \"asf\", \"flv\"]);\n\n/** Codecs the webcodecs variant can handle (native browser codecs only).\n * Anything not in these sets needs the custom avbridge variant. */\nconst WEBCODECS_AUDIO = new Set<AudioCodec>([\"aac\", \"mp3\", \"opus\", \"vorbis\", \"flac\"]);\nconst WEBCODECS_VIDEO = new Set<VideoCodec>([\"h264\", \"h265\", \"vp8\", \"vp9\", \"av1\"]);\n\nexport function pickLibavVariant(ctx: MediaContext): LibavVariant {\n if (LEGACY_CONTAINERS.has(ctx.container)) return \"avbridge\";\n for (const v of ctx.videoTracks) {\n // Any codec the webcodecs variant can't handle → need avbridge\n if (!WEBCODECS_VIDEO.has(v.codec)) return \"avbridge\";\n }\n for (const a of ctx.audioTracks) {\n if (!WEBCODECS_AUDIO.has(a.codec)) return \"avbridge\";\n }\n return \"webcodecs\";\n}\n","/**\n * Shared libav demux session. Opens a libav demuxer over a NormalizedSource\n * and provides a linear, cancellable packet pump.\n *\n * Phase 1 API: deliberately minimal. The first consumer is the AVI/ASF/FLV\n * transcode path (src/convert/transcode-libav.ts), which is strictly linear.\n * No seek, no track swapping — those were added to hybrid/fallback's\n * private pumps for playback reasons. When those paths migrate here, the\n * API will grow to cover their needs.\n *\n * The shared timestamp sanitizers (sanitizePacketTimestamp,\n * sanitizeFrameTimestamp) also live here. They were previously duplicated\n * in convert/remux.ts and strategies/hybrid/decoder.ts. The duplicates\n * stay put in Phase 1 with TODO pointers; migration is a follow-up.\n */\n\nimport { loadLibav, type LibavVariant } from \"../strategies/fallback/libav-loader.js\";\nimport { pickLibavVariant } from \"../strategies/fallback/variant-routing.js\";\nimport { prepareLibavInput } from \"./libav-http-reader.js\";\nimport type { MediaContext, TransportConfig } from \"../types.js\";\nimport type { NormalizedSource } from \"./source.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Structural types (mirror libav.js' shape without dragging in its types)\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\nexport interface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\nexport interface LibavFrame {\n data: unknown;\n format: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n nb_samples?: number;\n pts?: number;\n ptshi?: number;\n width?: number;\n height?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n f64toi64?(val: number): [number, number];\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Session\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface LibavDemuxSession {\n readonly libav: LibavRuntime;\n readonly fmtCtx: number;\n readonly streams: LibavStream[];\n readonly videoStream: LibavStream | null;\n readonly audioStream: LibavStream | null;\n /** True when the input is being streamed via HTTP Range requests. */\n readonly transport: \"http-range\" | \"blob\";\n /**\n * Linear read-to-EOF pump. Invokes the callbacks for each\n * ff_read_frame_multi batch (audio is handed over before video per\n * batch, matching the audio-first ordering that the hybrid/fallback\n * playback pumps use — see POSTMORTEMS.md entry 1).\n *\n * Honors the AbortSignal between batches. Invokes `onEof` once when\n * the demuxer returns EOF. Does NOT handle seek.\n */\n pump(cb: {\n onVideoPackets?: (pkts: LibavPacket[]) => Promise<void>;\n onAudioPackets?: (pkts: LibavPacket[]) => Promise<void>;\n onEof?: () => Promise<void>;\n signal?: AbortSignal;\n }): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface OpenLibavDemuxOptions {\n source: NormalizedSource;\n filename: string;\n context: MediaContext;\n transport?: TransportConfig;\n /** Override automatic variant picking. Defaults to pickLibavVariant(context). */\n variant?: LibavVariant;\n}\n\nexport async function openLibavDemux(opts: OpenLibavDemuxOptions): Promise<LibavDemuxSession> {\n const variant: LibavVariant = opts.variant ?? pickLibavVariant(opts.context);\n const libav = (await loadLibav(variant)) as unknown as LibavRuntime;\n\n const inputHandle = await prepareLibavInput(\n libav as unknown as Parameters<typeof prepareLibavInput>[0],\n opts.filename,\n opts.source,\n opts.transport,\n );\n\n const readPkt = await libav.av_packet_alloc();\n const [fmtCtx, streams] = await libav.ff_init_demuxer_file(opts.filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n const audioStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n let destroyed = false;\n\n async function pump(cb: Parameters<LibavDemuxSession[\"pump\"]>[0]): Promise<void> {\n while (!destroyed) {\n if (cb.signal?.aborted) return;\n\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n [readErr, packets] = await libav.ff_read_frame_multi(fmtCtx, readPkt, {\n // 16 KB batch — chosen so each read produces a handful of\n // packets, keeping downstream queues bounded. Same rationale\n // as the hybrid/fallback pumps (see CLAUDE.md note).\n limit: 16 * 1024,\n });\n } catch (err) {\n throw new Error(`libav-demux: ff_read_frame_multi failed: ${(err as Error).message}`);\n }\n\n if (destroyed || cb.signal?.aborted) return;\n\n const videoPackets = videoStream ? packets[videoStream.index] : undefined;\n const audioPackets = audioStream ? packets[audioStream.index] : undefined;\n\n // Audio-first ordering. Audio decode is cheap; video decode can\n // be expensive. Feeding audio first ensures the audio consumer\n // has samples to work with before any long video-decode block.\n if (cb.onAudioPackets && audioPackets && audioPackets.length > 0) {\n await cb.onAudioPackets(audioPackets);\n }\n if (destroyed || cb.signal?.aborted) return;\n if (cb.onVideoPackets && videoPackets && videoPackets.length > 0) {\n await cb.onVideoPackets(videoPackets);\n }\n\n if (readErr === libav.AVERROR_EOF) {\n if (cb.onEof) await cb.onEof();\n return;\n }\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n throw new Error(`libav-demux: ff_read_frame_multi returned ${readErr}`);\n }\n }\n }\n\n async function destroy(): Promise<void> {\n destroyed = true;\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmtCtx); } catch { /* ignore */ }\n try { await inputHandle.detach(); } catch { /* ignore */ }\n }\n\n return {\n libav,\n fmtCtx,\n streams,\n videoStream,\n audioStream,\n transport: inputHandle.transport,\n pump,\n destroy,\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Timestamp sanitizers (extracted from convert/remux.ts + hybrid/decoder.ts)\n//\n// libav can hand us packets/frames with pts = AV_NOPTS_VALUE (encoded as\n// ptshi = -2147483648, pts = 0) for inputs whose demuxer can't determine\n// presentation times. AVI is the canonical example. Downstream consumers\n// that treat pts as int64 overflow and throw.\n//\n// The sanitizer replaces invalid pts with a synthetic microsecond counter,\n// and normalizes valid pts to a 1/1e6 time_base so consumers don't need\n// to track the source time_base per packet.\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Sanitize a libav packet's timestamp. Mutates `pkt` in place.\n * If the packet has AV_NOPTS_VALUE, replaces pts with `nextUs()`.\n * Otherwise normalizes to µs with time_base = 1/1_000_000.\n */\nexport function sanitizePacketTimestamp(\n pkt: LibavPacket,\n nextUs: () => number,\n fallbackTimeBase?: [number, number],\n): void {\n const lo = pkt.pts ?? 0;\n const hi = pkt.ptshi ?? 0;\n const isInvalid = (hi === -2147483648 && lo === 0) || !Number.isFinite(lo);\n if (isInvalid) {\n const us = nextUs();\n pkt.pts = us;\n pkt.ptshi = 0;\n pkt.time_base_num = 1;\n pkt.time_base_den = 1_000_000;\n return;\n }\n const tb = fallbackTimeBase ?? [1, 1_000_000];\n const pts64 = hi * 0x100000000 + lo;\n const us = Math.round((pts64 * 1_000_000 * tb[0]) / tb[1]);\n if (Number.isFinite(us) && Math.abs(us) <= Number.MAX_SAFE_INTEGER) {\n pkt.pts = us;\n pkt.ptshi = us < 0 ? -1 : 0;\n pkt.time_base_num = 1;\n pkt.time_base_den = 1_000_000;\n return;\n }\n const fallback = nextUs();\n pkt.pts = fallback;\n pkt.ptshi = 0;\n pkt.time_base_num = 1;\n pkt.time_base_den = 1_000_000;\n}\n\n/**\n * Convert a raw libav packet's pts to seconds using the given stream\n * time_base, or return `null` if the packet lacks a valid pts. Used by\n * the hybrid + fallback strategies to track the demuxer's read-ahead\n * progress (the signal behind `<video>.buffered` on canvas strategies).\n *\n * Separate from `sanitizePacketTimestamp` — sanitization mutates the\n * packet and happens right before decoder feed; this peeks at the\n * timestamp earlier in the pump so we can track buffered extent without\n * perturbing the decode path.\n */\nexport function packetPtsSec(\n pkt: Pick<LibavPacket, \"pts\" | \"ptshi\">,\n timeBase: [number, number] | undefined,\n): number | null {\n const lo = pkt.pts ?? 0;\n const hi = pkt.ptshi ?? 0;\n const isInvalid = (hi === -2147483648 && lo === 0) || !Number.isFinite(lo);\n if (isInvalid) return null;\n const tb = timeBase ?? [1, 1_000_000];\n if (!tb[0] || !tb[1]) return null;\n const pts64 = hi * 0x100000000 + lo;\n const sec = (pts64 * tb[0]) / tb[1];\n return Number.isFinite(sec) ? sec : null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Audio frame → interleaved Float32 (extracted from\n// strategies/hybrid/decoder.ts + strategies/fallback/decoder.ts).\n//\n// libav hands us decoded audio frames in whichever sample format the codec\n// uses (FLTP, S16P, etc.). Most downstream consumers (Web Audio, WebCodecs\n// AudioEncoder) want interleaved Float32. This does the conversion without\n// any dependencies.\n// ─────────────────────────────────────────────────────────────────────────\n\nconst AV_SAMPLE_FMT_U8 = 0;\nconst AV_SAMPLE_FMT_S16 = 1;\nconst AV_SAMPLE_FMT_S32 = 2;\nconst AV_SAMPLE_FMT_FLT = 3;\nconst AV_SAMPLE_FMT_U8P = 5;\nconst AV_SAMPLE_FMT_S16P = 6;\nconst AV_SAMPLE_FMT_S32P = 7;\nconst AV_SAMPLE_FMT_FLTP = 8;\n\nexport interface InterleavedSamples {\n data: Float32Array;\n channels: number;\n sampleRate: number;\n}\n\nexport function libavFrameToInterleavedFloat32(frame: LibavFrame): InterleavedSamples | null {\n const channels = frame.channels ?? frame.ch_layout_nb_channels ?? 1;\n const sampleRate = frame.sample_rate ?? 44100;\n const nbSamples = frame.nb_samples ?? 0;\n if (nbSamples === 0) return null;\n\n const out = new Float32Array(nbSamples * channels);\n\n switch (frame.format) {\n case AV_SAMPLE_FMT_FLTP: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asFloat32(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = plane[i];\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_FLT: {\n const flat = asFloat32(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = flat[i];\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S16P: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asInt16(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = plane[i] / 32768;\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S16: {\n const flat = asInt16(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = flat[i] / 32768;\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S32P: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asInt32(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = plane[i] / 2147483648;\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S32: {\n const flat = asInt32(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = flat[i] / 2147483648;\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_U8P: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asUint8(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = (plane[i] - 128) / 128;\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_U8: {\n const flat = asUint8(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = (flat[i] - 128) / 128;\n return { data: out, channels, sampleRate };\n }\n default:\n return null;\n }\n}\n\nfunction ensurePlanes(data: unknown, channels: number): unknown[] {\n if (Array.isArray(data)) return data;\n const arr = data as { length: number; subarray?: (a: number, b: number) => unknown };\n const len = arr.length;\n const perChannel = Math.floor(len / channels);\n const planes: unknown[] = [];\n for (let ch = 0; ch < channels; ch++) {\n planes.push(arr.subarray ? arr.subarray(ch * perChannel, (ch + 1) * perChannel) : arr);\n }\n return planes;\n}\n\nfunction asFloat32(x: unknown): Float32Array {\n if (x instanceof Float32Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Float32Array(ta.buffer, ta.byteOffset, ta.byteLength / 4);\n}\nfunction asInt16(x: unknown): Int16Array {\n if (x instanceof Int16Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Int16Array(ta.buffer, ta.byteOffset, ta.byteLength / 2);\n}\nfunction asInt32(x: unknown): Int32Array {\n if (x instanceof Int32Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Int32Array(ta.buffer, ta.byteOffset, ta.byteLength / 4);\n}\nfunction asUint8(x: unknown): Uint8Array {\n if (x instanceof Uint8Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Uint8Array(ta.buffer, ta.byteOffset, ta.byteLength);\n}\n\n/**\n * Sanitize a decoded frame's timestamp. Mutates `frame` in place.\n * Returns nothing; callers that want derived metadata (e.g. a\n * VideoFrame timestamp in µs) should read `frame.pts` after calling.\n */\nexport function sanitizeFrameTimestamp(\n frame: LibavFrame,\n nextUs: () => number,\n fallbackTimeBase?: [number, number],\n): void {\n const lo = frame.pts ?? 0;\n const hi = frame.ptshi ?? 0;\n const isInvalid = (hi === -2147483648 && lo === 0) || !Number.isFinite(lo);\n if (isInvalid) {\n const us = nextUs();\n frame.pts = us;\n frame.ptshi = 0;\n return;\n }\n const tb = fallbackTimeBase ?? [1, 1_000_000];\n const pts64 = hi * 0x100000000 + lo;\n const us = Math.round((pts64 * 1_000_000 * tb[0]) / tb[1]);\n if (Number.isFinite(us) && Math.abs(us) <= Number.MAX_SAFE_INTEGER) {\n frame.pts = us;\n frame.ptshi = us < 0 ? -1 : 0;\n return;\n }\n const fallback = nextUs();\n frame.pts = fallback;\n frame.ptshi = 0;\n}\n","/**\n * Hybrid decoder: libav.js demux + WebCodecs VideoDecoder + libav audio decode.\n *\n * This is the hardware-accelerated path for files in containers mediabunny\n * can't read (AVI, ASF, FLV) but whose codecs ARE browser-supported.\n * libav.js handles demuxing, then:\n *\n * - **Video**: bridge.packetToEncodedVideoChunk → VideoDecoder (hardware)\n * - **Audio**: libav ff_decode_multi (software). Chrome's AudioDecoder\n * rejects raw MP3 packets from AVI, and audio decode is cheap enough\n * that software decode is fine.\n *\n * The demux pump loop, seek handling, and synthetic timestamp logic mirror\n * fallback/decoder.ts. The key difference is the video decode path.\n */\n\nimport { loadLibav, type LibavVariant } from \"../fallback/libav-loader.js\";\nimport { VideoRenderer } from \"../fallback/video-renderer.js\";\nimport { AudioOutput } from \"../fallback/audio-output.js\";\nimport type { MediaContext } from \"../../types.js\";\nimport { dbg } from \"../../util/debug.js\";\nimport { pickLibavVariant } from \"../fallback/variant-routing.js\";\nimport {\n sanitizePacketTimestamp,\n sanitizeFrameTimestamp,\n libavFrameToInterleavedFloat32,\n packetPtsSec,\n} from \"../../util/libav-demux.js\";\n\nexport interface HybridDecoderHandles {\n destroy(): Promise<void>;\n seek(timeSec: number): Promise<void>;\n /** Swap the active audio track — rebuilds the libav audio decoder + reseeks. */\n setAudioTrack(trackId: number, timeSec: number): Promise<void>;\n stats(): Record<string, unknown>;\n onFatalError(handler: (reason: string) => void): void;\n /**\n * The demuxer's read-ahead frontier in seconds — the highest pts\n * observed on any packet handed back from `ff_read_frame_multi`.\n * Monotonically non-decreasing: seeks don't reset it, since the\n * frontier represents \"how far we've ever demuxed through this\n * source,\" which matches what a seek-bar buffered indicator should\n * show. Backs `<video>.buffered` on canvas strategies. Returns 0\n * before any valid pts have been seen (some AVI/FLV sources may\n * never reach this — their `buffered` stays empty).\n */\n bufferedUntilSec(): number;\n}\n\nexport interface StartHybridDecoderOptions {\n /** Normalized source — either a Blob in memory or a URL we'll stream via Range requests. */\n source: import(\"../../util/source.js\").NormalizedSource;\n filename: string;\n context: MediaContext;\n renderer: VideoRenderer;\n audio: AudioOutput;\n transport?: import(\"../../types.js\").TransportConfig;\n}\n\nexport async function startHybridDecoder(opts: StartHybridDecoderOptions): Promise<HybridDecoderHandles> {\n const variant: LibavVariant = pickLibavVariant(opts.context);\n const libav = (await loadLibav(variant)) as unknown as LibavRuntime;\n const bridge = await loadBridge();\n\n // For URL sources, prepareLibavInput attaches an HTTP block reader so\n // libav demuxes via Range requests. For Blob sources, it falls back to\n // mkreadaheadfile (in-memory). The returned handle owns cleanup.\n const { prepareLibavInput } = await import(\"../../util/libav-http-reader.js\");\n const inputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], opts.filename, opts.source, opts.transport);\n\n const readPkt = await libav.av_packet_alloc();\n const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(opts.filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n // Audio stream is mutable (setAudioTrack swaps it). Prefer the id the\n // probe layer listed first so both entry points agree.\n const firstAudioTrackId = opts.context.audioTracks[0]?.id;\n let audioStream: LibavStream | null =\n (firstAudioTrackId != null\n ? streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === firstAudioTrackId)\n : undefined) ??\n streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n if (!videoStream && !audioStream) {\n throw new Error(\"hybrid decoder: file has no decodable streams\");\n }\n\n // ── Fatal error callback ──────────────────────────────────────────────\n let fatalHandler: ((reason: string) => void) | null = null;\n let fatalFired = false;\n\n function fireFatal(reason: string): void {\n if (fatalFired) return;\n fatalFired = true;\n fatalHandler?.(reason);\n }\n\n // ── WebCodecs VideoDecoder ────────────────────────────────────────────\n let videoDecoder: VideoDecoder | null = null;\n let videoTimeBase: [number, number] | undefined;\n\n if (videoStream) {\n try {\n const config = await bridge.videoStreamToConfig(libav, videoStream);\n if (!config) throw new Error(\"bridge returned null config\");\n\n const supported = await VideoDecoder.isConfigSupported(config);\n if (!supported.supported) throw new Error(`VideoDecoder does not support config: ${JSON.stringify(config)}`);\n\n videoDecoder = new VideoDecoder({\n output: (frame: VideoFrame) => {\n opts.renderer.enqueue(frame);\n videoFramesDecoded++;\n },\n error: (err: DOMException) => {\n console.error(\"[avbridge] WebCodecs VideoDecoder error:\", err);\n fireFatal(`WebCodecs VideoDecoder error: ${err.message}`);\n },\n });\n videoDecoder.configure(config);\n\n if (videoStream.time_base_num && videoStream.time_base_den) {\n videoTimeBase = [videoStream.time_base_num, videoStream.time_base_den];\n }\n } catch (err) {\n console.error(\"[avbridge] hybrid: failed to init WebCodecs VideoDecoder:\", err);\n fireFatal(`WebCodecs VideoDecoder init failed: ${(err as Error).message}`);\n // Clean up and throw — the player will escalate to fallback\n await inputHandle.detach().catch(() => {});\n throw err;\n }\n }\n\n // ── libav software AudioDecoder ───────────────────────────────────────\n let audioDec: SoftDecoder | null = null;\n let audioTimeBase: [number, number] | undefined;\n\n if (audioStream) {\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(audioStream.codec_id, {\n codecpar: audioStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n if (audioStream.time_base_num && audioStream.time_base_den) {\n audioTimeBase = [audioStream.time_base_num, audioStream.time_base_den];\n }\n } catch (err) {\n console.warn(\n \"[avbridge] hybrid: audio decoder unavailable for this codec — playing video with wall-clock timing:\",\n (err as Error).message,\n );\n }\n }\n\n // No audio decoder? Switch the audio output into wall-clock mode so the\n // video renderer doesn't stall waiting for an audio clock that never starts.\n if (!audioDec) {\n opts.audio.setNoAudio();\n }\n\n if (!videoDecoder && !audioDec) {\n await inputHandle.detach().catch(() => {});\n throw new Error(\"hybrid decoder: could not initialize any decoders\");\n }\n\n // ── Bitstream filter for MPEG-4 Part 2 packed B-frames ───────────────\n let bsfCtx: number | null = null;\n let bsfPkt: number | null = null;\n if (videoStream && opts.context.videoTracks[0]?.codec === \"mpeg4\") {\n try {\n bsfCtx = await libav.av_bsf_list_parse_str_js(\"mpeg4_unpack_bframes\");\n if (bsfCtx != null && bsfCtx >= 0) {\n const parIn = await libav.AVBSFContext_par_in(bsfCtx);\n await libav.avcodec_parameters_copy(parIn, videoStream.codecpar);\n await libav.av_bsf_init(bsfCtx);\n bsfPkt = await libav.av_packet_alloc();\n dbg.info(\"bsf\", \"mpeg4_unpack_bframes BSF active (hybrid)\");\n } else {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] mpeg4_unpack_bframes BSF not available in hybrid decoder\");\n bsfCtx = null;\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] hybrid: failed to init BSF:\", (err as Error).message);\n bsfCtx = null;\n bsfPkt = null;\n }\n }\n\n async function applyBSF(packets: LibavPacket[]): Promise<LibavPacket[]> {\n if (!bsfCtx || !bsfPkt) return packets;\n const out: LibavPacket[] = [];\n for (const pkt of packets) {\n await libav.ff_copyin_packet(bsfPkt, pkt);\n const sendErr = await libav.av_bsf_send_packet(bsfCtx, bsfPkt);\n if (sendErr < 0) { out.push(pkt); continue; }\n while (true) {\n const recvErr = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (recvErr < 0) break;\n out.push(await libav.ff_copyout_packet(bsfPkt));\n }\n }\n return out;\n }\n\n async function flushBSF(): Promise<void> {\n if (!bsfCtx || !bsfPkt) return;\n try {\n await libav.av_bsf_send_packet(bsfCtx, 0);\n while (true) {\n const err = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (err < 0) break;\n }\n } catch { /* ignore */ }\n }\n\n // ── Mutable state ─────────────────────────────────────────────────────\n let destroyed = false;\n let pumpToken = 0;\n let pumpRunning: Promise<void> | null = null;\n\n let packetsRead = 0;\n let videoFramesDecoded = 0;\n let audioFramesDecoded = 0;\n let videoChunksFed = 0;\n let bufferedUntilSec = 0;\n\n let syntheticVideoUs = 0;\n let syntheticAudioUs = 0;\n\n const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);\n const videoFps = videoTrackInfo?.fps && videoTrackInfo.fps > 0 ? videoTrackInfo.fps : 30;\n const videoFrameStepUs = Math.max(1, Math.round(1_000_000 / videoFps));\n\n // ── Pump loop ─────────────────────────────────────────────────────────\n\n async function pumpLoop(myToken: number): Promise<void> {\n while (!destroyed && myToken === pumpToken) {\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n [readErr, packets] = await libav.ff_read_frame_multi(fmt_ctx, readPkt, {\n limit: 16 * 1024,\n });\n } catch (err) {\n console.error(\"[avbridge] hybrid ff_read_frame_multi failed:\", err);\n return;\n }\n\n if (myToken !== pumpToken || destroyed) return;\n\n const videoPackets = videoStream ? packets[videoStream.index] : undefined;\n const audioPackets = audioStream ? packets[audioStream.index] : undefined;\n\n // Track how far the demuxer has read through the source — the\n // signal behind `<video>.buffered` on this strategy. Peek at raw\n // packet pts using each stream's native time_base (before the\n // sanitizePacketTimestamp call later in the loop, which\n // overwrites to µs). Monotonic: we never walk it backward.\n if (videoPackets && videoTimeBase) {\n for (const pkt of videoPackets) {\n const sec = packetPtsSec(pkt, videoTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n }\n }\n if (audioPackets && audioTimeBase) {\n for (const pkt of audioPackets) {\n const sec = packetPtsSec(pkt, audioTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n }\n }\n\n // Decode audio BEFORE video. Same rationale as fallback decoder\n // (POSTMORTEMS.md entry 1, fix #2): audio decode via libav's\n // ff_decode_multi is a blocking WASM call that prevents rAF from\n // firing. For heavy codecs like DTS, a single batch can take\n // 10-50 ms. Processing audio first ensures the audio scheduler is\n // fed before video decode starts, reducing perceived stutter.\n if (audioDec && audioPackets && audioPackets.length > 0) {\n await decodeAudioBatch(audioPackets, myToken);\n }\n if (myToken !== pumpToken || destroyed) return;\n\n // Yield to the event loop so the video renderer's rAF callback\n // can fire between the audio decode (blocking) and the video feed\n // (async). Without this, the renderer starves during DTS decode.\n await new Promise((r) => setTimeout(r, 0));\n if (myToken !== pumpToken || destroyed) return;\n\n // Feed video packets to WebCodecs VideoDecoder (after BSF if applicable)\n if (videoDecoder && videoPackets && videoPackets.length > 0) {\n const processed = await applyBSF(videoPackets);\n for (const pkt of processed) {\n if (myToken !== pumpToken || destroyed) return;\n sanitizePacketTimestamp(pkt, () => {\n const ts = syntheticVideoUs;\n syntheticVideoUs += videoFrameStepUs;\n return ts;\n }, videoTimeBase);\n try {\n const chunk = bridge.packetToEncodedVideoChunk(pkt, videoStream);\n videoDecoder.decode(chunk);\n videoChunksFed++;\n } catch (err) {\n if (videoChunksFed === 0) {\n console.warn(\"[avbridge] hybrid: packetToEncodedVideoChunk failed:\", err);\n fireFatal(`WebCodecs chunk creation failed: ${(err as Error).message}`);\n return;\n }\n }\n }\n }\n\n packetsRead += (videoPackets?.length ?? 0) + (audioPackets?.length ?? 0);\n\n // Backpressure: WebCodecs decodeQueueSize + audio buffer + renderer queue\n while (\n !destroyed &&\n myToken === pumpToken &&\n ((videoDecoder && videoDecoder.decodeQueueSize > 10) ||\n opts.audio.bufferAhead() > 2.0 ||\n opts.renderer.queueDepth() >= opts.renderer.queueHighWater)\n ) {\n await new Promise((r) => setTimeout(r, 50));\n }\n\n if (readErr === libav.AVERROR_EOF) {\n // Flush WebCodecs decoder\n if (videoDecoder && videoDecoder.state === \"configured\") {\n try { await videoDecoder.flush(); } catch { /* ignore */ }\n }\n // Flush libav audio decoder\n if (audioDec) await decodeAudioBatch([], myToken, true);\n return;\n }\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n console.warn(\"[avbridge] hybrid ff_read_frame_multi returned\", readErr);\n return;\n }\n }\n }\n\n async function decodeAudioBatch(pkts: LibavPacket[], myToken: number, flush = false) {\n if (!audioDec || destroyed || myToken !== pumpToken) return;\n\n // For heavy codecs (DTS, AC3), decode in small sub-batches and yield\n // between them so the event loop can run rAF for video painting.\n // Each ff_decode_multi call is a blocking WASM invocation.\n const AUDIO_SUB_BATCH = 4; // packets per sub-batch\n let allFrames: LibavFrame[] = [];\n\n for (let i = 0; i < pkts.length; i += AUDIO_SUB_BATCH) {\n if (myToken !== pumpToken || destroyed) return;\n const slice = pkts.slice(i, i + AUDIO_SUB_BATCH);\n const isLast = i + AUDIO_SUB_BATCH >= pkts.length;\n try {\n const frames = await libav.ff_decode_multi(\n audioDec.c,\n audioDec.pkt,\n audioDec.frame,\n slice,\n isLast && flush ? { fin: true, ignoreErrors: true } : { ignoreErrors: true },\n );\n allFrames = allFrames.concat(frames);\n } catch (err) {\n console.error(\"[avbridge] hybrid audio decode failed:\", err);\n return;\n }\n // Yield between sub-batches so rAF can fire\n if (!isLast) await new Promise((r) => setTimeout(r, 0));\n }\n\n // Handle flush-only call (empty pkts array)\n if (pkts.length === 0 && flush) {\n try {\n allFrames = await libav.ff_decode_multi(\n audioDec.c, audioDec.pkt, audioDec.frame, [],\n { fin: true, ignoreErrors: true },\n );\n } catch (err) {\n console.error(\"[avbridge] hybrid audio flush failed:\", err);\n return;\n }\n }\n\n if (myToken !== pumpToken || destroyed) return;\n const frames = allFrames;\n\n for (const f of frames) {\n if (myToken !== pumpToken || destroyed) return;\n sanitizeFrameTimestamp(\n f,\n () => {\n const ts = syntheticAudioUs;\n const samples = f.nb_samples ?? 1024;\n const sampleRate = f.sample_rate ?? 44100;\n syntheticAudioUs += Math.round((samples * 1_000_000) / sampleRate);\n return ts;\n },\n audioTimeBase,\n );\n const samples = libavFrameToInterleavedFloat32(f);\n if (samples) {\n opts.audio.schedule(samples.data, samples.channels, samples.sampleRate);\n audioFramesDecoded++;\n }\n }\n }\n\n // Kick off initial pump\n pumpToken = 1;\n pumpRunning = pumpLoop(pumpToken).catch((err) =>\n console.error(\"[avbridge] hybrid pump failed:\", err),\n );\n\n return {\n onFatalError(handler: (reason: string) => void): void {\n fatalHandler = handler;\n // If fatal already fired before handler was attached, fire immediately\n if (fatalFired) handler(\"WebCodecs decode failed (error occurred before handler attached)\");\n },\n\n async destroy() {\n destroyed = true;\n pumpToken++;\n try { await pumpRunning; } catch { /* ignore */ }\n try { if (bsfCtx) await libav.av_bsf_free(bsfCtx); } catch { /* ignore */ }\n try { if (bsfPkt) await libav.av_packet_free?.(bsfPkt); } catch { /* ignore */ }\n try { if (videoDecoder && videoDecoder.state !== \"closed\") videoDecoder.close(); } catch { /* ignore */ }\n try { if (audioDec) await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmt_ctx); } catch { /* ignore */ }\n try { await inputHandle.detach(); } catch { /* ignore */ }\n },\n\n async setAudioTrack(trackId, timeSec) {\n if (audioStream && audioStream.index === trackId) return;\n const newStream = streams.find(\n (s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === trackId,\n );\n if (!newStream) {\n console.warn(\"[avbridge] hybrid: setAudioTrack — no stream with id\", trackId);\n return;\n }\n\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n // Tear down old audio decoder, build new one.\n if (audioDec) {\n try { await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n audioDec = null;\n }\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(newStream.codec_id, {\n codecpar: newStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n audioTimeBase = newStream.time_base_num && newStream.time_base_den\n ? [newStream.time_base_num, newStream.time_base_den]\n : undefined;\n } catch (err) {\n console.warn(\n \"[avbridge] hybrid: setAudioTrack init failed — switching to no-audio:\",\n (err as Error).message,\n );\n audioDec = null;\n opts.audio.setNoAudio();\n }\n\n audioStream = newStream;\n\n // Re-seek demuxer to current time for the new track.\n try {\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] hybrid: setAudioTrack seek failed:\", err);\n }\n\n // Flush video decoder too — demuxer moved back to a keyframe.\n try {\n if (videoDecoder && videoDecoder.state === \"configured\") {\n await videoDecoder.flush();\n }\n } catch { /* ignore */ }\n await flushBSF();\n\n syntheticVideoUs = Math.round(timeSec * 1_000_000);\n syntheticAudioUs = Math.round(timeSec * 1_000_000);\n\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] hybrid pump failed (post-setAudioTrack):\", err),\n );\n },\n\n async seek(timeSec) {\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n try {\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] hybrid av_seek_frame failed:\", err);\n }\n\n // Flush WebCodecs VideoDecoder\n try {\n if (videoDecoder && videoDecoder.state === \"configured\") {\n await videoDecoder.flush();\n }\n } catch { /* ignore */ }\n\n // Flush libav audio decoder\n try {\n if (audioDec) await libav.avcodec_flush_buffers?.(audioDec.c);\n } catch { /* ignore */ }\n await flushBSF();\n\n syntheticVideoUs = Math.round(timeSec * 1_000_000);\n syntheticAudioUs = Math.round(timeSec * 1_000_000);\n\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] hybrid pump failed (post-seek):\", err),\n );\n },\n\n bufferedUntilSec() {\n return bufferedUntilSec;\n },\n\n stats() {\n return {\n decoderType: \"webcodecs-hybrid\",\n packetsRead,\n videoFramesDecoded,\n videoChunksFed,\n audioFramesDecoded,\n bsfApplied: bsfCtx ? [\"mpeg4_unpack_bframes\"] : [],\n videoDecodeQueueSize: videoDecoder?.decodeQueueSize ?? 0,\n // Confirmed transport info — see fallback decoder for the pattern.\n _transport: inputHandle.transport === \"http-range\" ? \"http-range\" : \"memory\",\n _rangeSupported: inputHandle.transport === \"http-range\",\n ...opts.renderer.stats(),\n ...opts.audio.stats(),\n };\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Packet timestamp sanitizer for WebCodecs chunks.\n//\n// AVI packets often have AV_NOPTS_VALUE. The bridge's packetToEncodedVideoChunk\n// uses the packet's pts + time_base. We normalize to microseconds with a 1/1e6\n// time_base to avoid overflow.\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Bridge loader\n// ─────────────────────────────────────────────────────────────────────────────\n\nasync function loadBridge(): Promise<BridgeModule> {\n try {\n const wrapper = await import(\"../fallback/libav-import.js\");\n return wrapper.libavBridge as unknown as BridgeModule;\n } catch (err) {\n throw new Error(\n `failed to load libavjs-webcodecs-bridge: ${(err as Error).message}`,\n );\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Structural types\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface SoftDecoder {\n c: number;\n pkt: number;\n frame: number;\n}\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavFrame {\n data: unknown;\n format: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n nb_samples?: number;\n pts?: number;\n ptshi?: number;\n width?: number;\n height?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n AVSEEK_FLAG_BACKWARD?: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n ff_init_decoder(\n codec: number | string,\n config?: { codecpar?: number; time_base?: [number, number] },\n ): Promise<[number, number, number, number]>;\n ff_decode_multi(\n c: number,\n pkt: number,\n frame: number,\n packets: LibavPacket[],\n opts?: { fin?: boolean; ignoreErrors?: boolean },\n ): Promise<LibavFrame[]>;\n ff_free_decoder?(c: number, pkt: number, frame: number): Promise<void>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n av_seek_frame(\n fmt_ctx: number,\n stream: number,\n tsLo: number,\n tsHi: number,\n flags: number,\n ): Promise<number>;\n avcodec_flush_buffers?(c: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n f64toi64?(val: number): [number, number];\n\n // BSF methods\n av_bsf_list_parse_str_js(str: string): Promise<number>;\n AVBSFContext_par_in(ctx: number): Promise<number>;\n avcodec_parameters_copy(dst: number, src: number): Promise<number>;\n av_bsf_init(ctx: number): Promise<number>;\n av_bsf_send_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_receive_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_free(ctx: number): Promise<void>;\n ff_copyin_packet(pktPtr: number, packet: LibavPacket): Promise<void>;\n ff_copyout_packet(pkt: number): Promise<LibavPacket>;\n}\n\ninterface BridgeModule {\n videoStreamToConfig(libav: unknown, stream: unknown): Promise<VideoDecoderConfig | null>;\n packetToEncodedVideoChunk(pkt: unknown, stream: unknown): EncodedVideoChunk;\n}\n","/**\n * Synthesize a `TimeRanges`-shaped object for the HTMLMediaElement contract\n * on canvas strategies (hybrid/fallback). The real `TimeRanges` interface\n * is browser-only and not constructable; this object duck-types it.\n *\n * `ranges` is an array of `[start, end]` pairs in seconds, in ascending\n * order. The returned object exposes `length`, `start(i)`, `end(i)` —\n * the full surface consumers actually use.\n *\n * NOTE: Plain objects and real TimeRanges aren't `instanceof`-comparable,\n * but consumer code virtually never checks that. The methods + length\n * property are what matters.\n */\nexport function makeTimeRanges(ranges: Array<[number, number]>): TimeRanges {\n const frozen = ranges.slice();\n const impl = {\n get length(): number {\n return frozen.length;\n },\n start(index: number): number {\n if (index < 0 || index >= frozen.length) {\n throw new DOMException(\n `TimeRanges.start: index ${index} out of range (length=${frozen.length})`,\n \"IndexSizeError\",\n );\n }\n return frozen[index][0];\n },\n end(index: number): number {\n if (index < 0 || index >= frozen.length) {\n throw new DOMException(\n `TimeRanges.end: index ${index} out of range (length=${frozen.length})`,\n \"IndexSizeError\",\n );\n }\n return frozen[index][1];\n },\n };\n return impl as TimeRanges;\n}\n","import type { MediaContext, PlaybackSession, TransportConfig } from \"../../types.js\";\nimport { VideoRenderer } from \"../fallback/video-renderer.js\";\nimport { AudioOutput } from \"../fallback/audio-output.js\";\nimport { startHybridDecoder, type HybridDecoderHandles } from \"./decoder.js\";\nimport { makeTimeRanges } from \"../../util/time-ranges.js\";\n\n/**\n * Hybrid strategy session.\n *\n * Uses libav.js for demuxing + WebCodecs VideoDecoder for hardware-accelerated\n * video decode + libav.js software decode for audio. Same canvas + Web Audio\n * output as the fallback strategy.\n *\n * Falls back to the pure-WASM fallback strategy if WebCodecs fails (via the\n * onFatalError callback that the player wires to its escalation mechanism).\n */\n\nconst READY_AUDIO_BUFFER_SECONDS = 0.3;\nconst READY_TIMEOUT_SECONDS = 10;\n\nexport async function createHybridSession(\n ctx: MediaContext,\n target: HTMLVideoElement,\n transport?: TransportConfig,\n): Promise<PlaybackSession> {\n // Normalize the source so URL inputs go through the libav HTTP block\n // reader instead of being buffered into memory.\n const { normalizeSource } = await import(\"../../util/source.js\");\n const source = await normalizeSource(ctx.source);\n\n const fps = ctx.videoTracks[0]?.fps ?? 30;\n const audio = new AudioOutput();\n const renderer = new VideoRenderer(target, audio, fps);\n\n let handles: HybridDecoderHandles;\n try {\n handles = await startHybridDecoder({\n source,\n filename: ctx.name ?? \"input.bin\",\n context: ctx,\n renderer,\n audio,\n transport,\n });\n } catch (err) {\n audio.destroy();\n renderer.destroy();\n throw err;\n }\n\n // Patch <video> element for the unified player layer. The underlying\n // <video> never has its own src; all playback state lives in the audio\n // clock + canvas renderer. We expose that state via property getters\n // so standard HTMLMediaElement consumers (like <avbridge-player>'s\n // controls UI) see the real values.\n Object.defineProperty(target, \"currentTime\", {\n configurable: true,\n get: () => audio.now(),\n set: (v: number) => { void doSeek(v); },\n });\n Object.defineProperty(target, \"paused\", {\n configurable: true,\n get: () => !audio.isPlaying(),\n });\n Object.defineProperty(target, \"volume\", {\n configurable: true,\n get: () => audio.getVolume(),\n set: (v: number) => {\n audio.setVolume(v);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n Object.defineProperty(target, \"muted\", {\n configurable: true,\n get: () => audio.getMuted(),\n set: (m: boolean) => {\n audio.setMuted(m);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n if (ctx.duration && Number.isFinite(ctx.duration)) {\n Object.defineProperty(target, \"duration\", {\n configurable: true,\n get: () => ctx.duration ?? NaN,\n });\n }\n Object.defineProperty(target, \"playbackRate\", {\n configurable: true,\n get: () => audio.getPlaybackRate(),\n set: (v: number) => {\n audio.setPlaybackRate(v);\n target.dispatchEvent(new Event(\"ratechange\"));\n },\n });\n // HTMLMediaElement parity surfaces — see fallback/index.ts for rationale.\n Object.defineProperty(target, \"readyState\", {\n configurable: true,\n get: (): number => {\n if (!renderer.hasFrames()) return 0;\n if (!audio.isPlaying() && audio.bufferAhead() <= 0 && !audio.isNoAudio()) return 1;\n return 2;\n },\n });\n Object.defineProperty(target, \"seekable\", {\n configurable: true,\n get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0\n ? [[0, ctx.duration]]\n : []),\n });\n Object.defineProperty(target, \"buffered\", {\n configurable: true,\n get: () => {\n const end = handles.bufferedUntilSec();\n return makeTimeRanges(end > 0 ? [[0, end]] : []);\n },\n });\n\n async function waitForBuffer(): Promise<void> {\n const start = performance.now();\n while (true) {\n const audioReady = audio.isNoAudio() || audio.bufferAhead() >= READY_AUDIO_BUFFER_SECONDS;\n if (audioReady && renderer.hasFrames()) {\n return;\n }\n if ((performance.now() - start) / 1000 > READY_TIMEOUT_SECONDS) return;\n await new Promise((r) => setTimeout(r, 50));\n }\n }\n\n async function doSeek(timeSec: number): Promise<void> {\n const wasPlaying = audio.isPlaying();\n // HTMLMediaElement contract — see fallback/index.ts for the why.\n target.dispatchEvent(new Event(\"seeking\"));\n await audio.pause().catch(() => {});\n await handles.seek(timeSec).catch((err) =>\n console.warn(\"[avbridge] hybrid decoder seek failed:\", err),\n );\n await audio.reset(timeSec);\n renderer.flush();\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n target.dispatchEvent(new Event(\"seeked\"));\n }\n\n // HTMLMediaElement contract: `loadedmetadata` once the session is\n // ready. The inner <video> never fires this itself on the hybrid\n // path — it has no src.\n queueMicrotask(() => {\n try { target.dispatchEvent(new Event(\"loadedmetadata\")); } catch { /* element torn down */ }\n });\n\n // Store the fatal error handler so the player can wire escalation\n let fatalErrorHandler: ((reason: string) => void) | null = null;\n handles.onFatalError((reason) => fatalErrorHandler?.(reason));\n\n return {\n strategy: \"hybrid\",\n\n async play() {\n if (!audio.isPlaying()) {\n await waitForBuffer();\n await audio.start();\n // Dispatch play/playing events so HTMLMediaElement consumers\n // (e.g. <avbridge-player>'s controls UI) update their state.\n target.dispatchEvent(new Event(\"play\"));\n target.dispatchEvent(new Event(\"playing\"));\n }\n },\n\n pause() {\n void audio.pause();\n target.dispatchEvent(new Event(\"pause\"));\n },\n\n async seek(time) {\n await doSeek(time);\n },\n\n async setAudioTrack(id) {\n if (!ctx.audioTracks.some((t) => t.id === id)) {\n console.warn(\"[avbridge] hybrid: setAudioTrack — unknown track id\", id);\n return;\n }\n const wasPlaying = audio.isPlaying();\n const currentTime = audio.now();\n await audio.pause().catch(() => {});\n await handles.setAudioTrack(id, currentTime).catch((err) =>\n console.warn(\"[avbridge] hybrid: handles.setAudioTrack failed:\", err),\n );\n await audio.reset(currentTime);\n renderer.flush();\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n },\n\n async setSubtitleTrack(_id) {\n // Post-MVP for hybrid strategy\n },\n\n getCurrentTime() {\n return audio.now();\n },\n\n onFatalError(handler: (reason: string) => void) {\n fatalErrorHandler = handler;\n },\n\n async destroy() {\n await handles.destroy();\n renderer.destroy();\n audio.destroy();\n try {\n delete (target as unknown as Record<string, unknown>).currentTime;\n delete (target as unknown as Record<string, unknown>).duration;\n delete (target as unknown as Record<string, unknown>).paused;\n delete (target as unknown as Record<string, unknown>).volume;\n delete (target as unknown as Record<string, unknown>).muted;\n delete (target as unknown as Record<string, unknown>).readyState;\n delete (target as unknown as Record<string, unknown>).seekable;\n delete (target as unknown as Record<string, unknown>).playbackRate;\n } catch { /* ignore */ }\n },\n\n getRuntimeStats() {\n return handles.stats();\n },\n };\n}\n","/**\n * libav.js demux + decode loop for the fallback strategy.\n *\n * Design:\n *\n * - **Always software decode.** The fallback strategy is only entered when\n * classification has decided no browser decoder will handle the codec set,\n * so the WebCodecs hardware path is dead weight here. Going through libav\n * uniformly also avoids brittleness around `EncodedAudioChunk` framing for\n * codecs like MP3-in-AVI where the browser's AudioDecoder rejects libav's\n * raw demuxed packets.\n *\n * - **Cancellable pump loop.** Each pump iteration is gated on a token that\n * `seek()` increments. When the token changes mid-batch, the loop exits\n * and a fresh one starts at the new position. This is how seek interrupts\n * the decoder cleanly without having to await an arbitrarily long\n * `ff_decode_multi` call.\n *\n * - **Synthetic timestamps.** AVI demuxers report `AV_NOPTS_VALUE` for most\n * packets — they're frame-indexed, not time-indexed. We replace any\n * invalid pts with a per-stream synthetic counter (frame index × 1e6/fps\n * for video; sample-accurate for audio) so the bridge's chunk constructor\n * doesn't overflow int64.\n */\n\nimport { loadLibav, type LibavVariant } from \"./libav-loader.js\";\nimport { VideoRenderer } from \"./video-renderer.js\";\nimport { AudioOutput } from \"./audio-output.js\";\nimport type { MediaContext } from \"../../types.js\";\nimport { pickLibavVariant } from \"./variant-routing.js\";\nimport { dbg } from \"../../util/debug.js\";\nimport {\n sanitizeFrameTimestamp,\n libavFrameToInterleavedFloat32,\n packetPtsSec,\n} from \"../../util/libav-demux.js\";\n\nexport interface DecoderHandles {\n destroy(): Promise<void>;\n /** Seek to the given time in seconds. Returns once the new pump has been kicked off. */\n seek(timeSec: number): Promise<void>;\n /**\n * Switch the active audio track. The decoder tears down the current audio\n * decoder, initializes one for the stream whose container id matches\n * `trackId` (== libav `stream.index`), seeks the demuxer to `timeSec`, and\n * restarts the pump. No-op if the track is already active.\n */\n setAudioTrack(trackId: number, timeSec: number): Promise<void>;\n stats(): Record<string, unknown>;\n /**\n * The demuxer's read-ahead frontier in seconds. See\n * `HybridDecoderHandles.bufferedUntilSec` for the full contract —\n * same semantics, same consumer (`<video>.buffered` on canvas\n * strategies).\n */\n bufferedUntilSec(): number;\n}\n\nexport interface StartDecoderOptions {\n /** Normalized source — either a Blob in memory or a URL we'll stream via Range requests. */\n source: import(\"../../util/source.js\").NormalizedSource;\n filename: string;\n context: MediaContext;\n renderer: VideoRenderer;\n audio: AudioOutput;\n transport?: import(\"../../types.js\").TransportConfig;\n}\n\nexport async function startDecoder(opts: StartDecoderOptions): Promise<DecoderHandles> {\n // Fallback always does full software decode. The \"webcodecs\" libav\n // variant is trimmed to demuxing + WebCodecs-companion use; it lacks\n // software decoders for codecs whose browsers usually handle them\n // (e.g. h265). When we've reached fallback for those codecs, it's\n // precisely because the browser *can't* decode them — so we need\n // the full \"avbridge\" variant with software decoders. pickLibavVariant\n // is still right for the hybrid strategy (which software-decodes only\n // audio and relies on WebCodecs for video), but not here.\n const variant: LibavVariant = \"avbridge\";\n void pickLibavVariant; // kept in scope for future opt-in use\n const libav = (await loadLibav(variant)) as unknown as LibavRuntime;\n const bridge = await loadBridge();\n\n // For URL sources, prepareLibavInput attaches an HTTP block reader so\n // libav demuxes via Range requests. For Blob sources, it falls back to\n // mkreadaheadfile (in-memory). The returned handle owns cleanup.\n const { prepareLibavInput } = await import(\"../../util/libav-http-reader.js\");\n const inputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], opts.filename, opts.source, opts.transport);\n\n // Pre-allocate one AVPacket for ff_read_frame_multi to reuse.\n const readPkt = await libav.av_packet_alloc();\n\n const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(opts.filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n // Audio stream is mutable so setAudioTrack() can swap it. Default to the\n // track the context picked first (matches probe ordering). We resolve by\n // container id so the selection survives stream reordering.\n const firstAudioTrackId = opts.context.audioTracks[0]?.id;\n let audioStream: LibavStream | null =\n (firstAudioTrackId != null\n ? streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === firstAudioTrackId)\n : undefined) ??\n streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n if (!videoStream && !audioStream) {\n throw new Error(\"fallback decoder: file has no decodable streams\");\n }\n\n // ── Set up software decoders ─────────────────────────────────────────\n let videoDec: SoftDecoder | null = null;\n let audioDec: SoftDecoder | null = null;\n let videoTimeBase: [number, number] | undefined;\n let audioTimeBase: [number, number] | undefined;\n\n if (videoStream) {\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(videoStream.codec_id, {\n codecpar: videoStream.codecpar,\n });\n videoDec = { c, pkt, frame };\n if (videoStream.time_base_num && videoStream.time_base_den) {\n videoTimeBase = [videoStream.time_base_num, videoStream.time_base_den];\n }\n } catch (err) {\n console.error(\"[avbridge] failed to init video decoder:\", err);\n }\n }\n\n if (audioStream) {\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(audioStream.codec_id, {\n codecpar: audioStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n if (audioStream.time_base_num && audioStream.time_base_den) {\n audioTimeBase = [audioStream.time_base_num, audioStream.time_base_den];\n }\n } catch (err) {\n console.warn(\n \"[avbridge] fallback: audio decoder unavailable — playing video with wall-clock timing:\",\n (err as Error).message,\n );\n }\n }\n\n // No audio decoder? Switch audio output into wall-clock mode so video can\n // play even when the audio codec isn't supported by the loaded libav variant.\n if (!audioDec) {\n opts.audio.setNoAudio();\n }\n\n if (!videoDec && !audioDec) {\n await inputHandle.detach().catch(() => {});\n const codecs = [\n videoStream ? `video: ${opts.context.videoTracks[0]?.codec ?? \"unknown\"}` : null,\n audioStream ? `audio: ${opts.context.audioTracks[0]?.codec ?? \"unknown\"}` : null,\n ].filter(Boolean).join(\", \");\n throw new Error(\n `fallback decoder: could not initialize any libav decoders (${codecs}). ` +\n `The \"${variant}\" libav variant lacks software decoders for these codecs — ` +\n `rebuild with scripts/build-libav.sh including the missing decoder, ` +\n `or use a lighter strategy (native, remux, hybrid) instead.`,\n );\n }\n\n // ── Bitstream filter for MPEG-4 Part 2 packed B-frames ───────────────\n // Applied unconditionally for mpeg4 video — the BSF is a no-op when\n // the stream doesn't actually have packed B-frames, so false positives\n // are harmless. Without it, DivX files with packed B-frames produce\n // garbled frame ordering.\n let bsfCtx: number | null = null;\n let bsfPkt: number | null = null;\n if (videoStream && opts.context.videoTracks[0]?.codec === \"mpeg4\") {\n try {\n bsfCtx = await libav.av_bsf_list_parse_str_js(\"mpeg4_unpack_bframes\");\n if (bsfCtx != null && bsfCtx >= 0) {\n const parIn = await libav.AVBSFContext_par_in(bsfCtx);\n await libav.avcodec_parameters_copy(parIn, videoStream.codecpar);\n await libav.av_bsf_init(bsfCtx);\n bsfPkt = await libav.av_packet_alloc();\n dbg.info(\"bsf\", \"mpeg4_unpack_bframes BSF active\");\n } else {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] mpeg4_unpack_bframes BSF not available — decoding without it\");\n bsfCtx = null;\n }\n } catch (err) {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] failed to init mpeg4_unpack_bframes BSF:\", (err as Error).message);\n bsfCtx = null;\n bsfPkt = null;\n }\n }\n\n /** Run video packets through the BSF. Returns original packets if no BSF active. */\n async function applyBSF(packets: LibavPacket[]): Promise<LibavPacket[]> {\n if (!bsfCtx || !bsfPkt) return packets;\n const out: LibavPacket[] = [];\n for (const pkt of packets) {\n await libav.ff_copyin_packet(bsfPkt, pkt);\n const sendErr = await libav.av_bsf_send_packet(bsfCtx, bsfPkt);\n if (sendErr < 0) {\n out.push(pkt); // BSF rejected — pass through original\n continue;\n }\n while (true) {\n const recvErr = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (recvErr < 0) break; // EAGAIN or EOF\n out.push(await libav.ff_copyout_packet(bsfPkt));\n }\n }\n return out;\n }\n\n /** Flush the BSF (on seek or EOF) to drain any internally buffered packets. */\n async function flushBSF(): Promise<void> {\n if (!bsfCtx || !bsfPkt) return;\n try {\n await libav.av_bsf_send_packet(bsfCtx, 0);\n while (true) {\n const err = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (err < 0) break;\n }\n } catch { /* ignore flush errors */ }\n }\n\n // ── Mutable state shared across pump loops ───────────────────────────\n let destroyed = false;\n let pumpToken = 0; // bumped on seek; pump loops bail when token changes\n let pumpRunning: Promise<void> | null = null;\n\n let packetsRead = 0;\n let videoFramesDecoded = 0;\n let bufferedUntilSec = 0;\n let audioFramesDecoded = 0;\n\n // Decode-rate watchdog. Samples framesDecoded every second and\n // compares against realtime expected frames for the source fps. If\n // the decoder sustains less than 60% of realtime for more than\n // 5 seconds (counting only time since the first frame emerged),\n // emits a one-shot diagnostic so users know why playback is\n // stuttering instead of guessing. A second one-shot fires if the\n // renderer's overflow-drop rate exceeds 10% of decoded frames —\n // that symptom means the decoder is BURSTING faster than the\n // renderer can drain, which is a different bug from \"decoder slow\".\n let watchdogFirstFrameMs = 0;\n let watchdogSlowSinceMs = 0;\n let watchdogSlowWarned = false;\n let watchdogOverflowWarned = false;\n\n // Synthetic timestamp counters. Reset on seek.\n let syntheticVideoUs = 0;\n let syntheticAudioUs = 0;\n\n const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);\n const videoFps = videoTrackInfo?.fps && videoTrackInfo.fps > 0 ? videoTrackInfo.fps : 30;\n const videoFrameStepUs = Math.max(1, Math.round(1_000_000 / videoFps));\n\n // ── Pump loop ─────────────────────────────────────────────────────────\n\n async function pumpLoop(myToken: number): Promise<void> {\n while (!destroyed && myToken === pumpToken) {\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n // Batch size tunes the tradeoff between JS↔WASM call overhead\n // (small = more crossings per second) and queue burstiness\n // (large = decoder hands the renderer big bursts at once that\n // can blow past the renderer's 64-frame hard cap before the\n // per-batch `queueHighWater` throttle runs).\n //\n // We tried 64 KB and saw ~30% overflow drops on RMVB:rv40 at\n // 1024x768 because one decode batch regularly produced >30\n // frames. 16 KB keeps each batch ≈ 4-6 video packets at\n // typical bitrates, so the worst-case queue spike stays under\n // `queueHighWater` and the throttle has a chance to apply\n // backpressure *between* batches rather than within one.\n [readErr, packets] = await libav.ff_read_frame_multi(fmt_ctx, readPkt, {\n limit: 16 * 1024,\n });\n } catch (err) {\n console.error(\"[avbridge] ff_read_frame_multi failed:\", err);\n return;\n }\n\n if (myToken !== pumpToken || destroyed) return;\n\n const videoPackets = videoStream ? packets[videoStream.index] : undefined;\n const audioPackets = audioStream ? packets[audioStream.index] : undefined;\n\n // Track demuxer read-ahead for <video>.buffered on this strategy.\n // Peek raw pts before sanitizePacketTimestamp (which would\n // clobber to µs and lose the source-native scale). Monotonic;\n // seeks don't reset.\n if (videoPackets && videoTimeBase) {\n for (const pkt of videoPackets) {\n const sec = packetPtsSec(pkt, videoTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n }\n }\n if (audioPackets && audioTimeBase) {\n for (const pkt of audioPackets) {\n const sec = packetPtsSec(pkt, audioTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n }\n }\n\n // Decode audio BEFORE video. On software-decode-bound content\n // (rv40/mpeg4/wmv3 @ 720p+) a single video batch can take\n // 200-400 ms of wall time; if the scheduler hasn't been fed\n // during that window, audio output runs dry and the user hears\n // clicks/gaps. Audio is time-critical; video can drop a frame\n // and nobody notices. Audio decode is also typically <1 ms per\n // packet for cook/mp3/aac, so doing it first barely delays\n // video decoding at all.\n if (audioDec && audioPackets && audioPackets.length > 0) {\n await decodeAudioBatch(audioPackets, myToken);\n }\n if (myToken !== pumpToken || destroyed) return;\n if (videoDec && videoPackets && videoPackets.length > 0) {\n const processed = await applyBSF(videoPackets);\n await decodeVideoBatch(processed, myToken);\n }\n\n packetsRead += (videoPackets?.length ?? 0) + (audioPackets?.length ?? 0);\n\n // ── Decode-rate watchdog ──────────────────────────────────────\n if (videoFramesDecoded > 0) {\n if (watchdogFirstFrameMs === 0) {\n watchdogFirstFrameMs = performance.now();\n }\n const elapsedSinceFirst = (performance.now() - watchdogFirstFrameMs) / 1000;\n\n // 1. Slow-decode detection (sustained <60% of realtime fps).\n if (elapsedSinceFirst > 1 && !watchdogSlowWarned) {\n const expectedFrames = elapsedSinceFirst * videoFps;\n const ratio = videoFramesDecoded / expectedFrames;\n if (ratio < 0.6) {\n if (watchdogSlowSinceMs === 0) watchdogSlowSinceMs = performance.now();\n if ((performance.now() - watchdogSlowSinceMs) / 1000 > 5) {\n watchdogSlowWarned = true;\n console.warn(\n \"[avbridge:decode-rate]\",\n `decoder is running slower than realtime: ` +\n `${videoFramesDecoded} frames in ${elapsedSinceFirst.toFixed(1)}s ` +\n `(${(videoFramesDecoded / elapsedSinceFirst).toFixed(1)} fps vs ${videoFps} fps source — ` +\n `${(ratio * 100).toFixed(0)}% of realtime). ` +\n `Playback will stutter. Typical causes: software decode of a codec with no WebCodecs support ` +\n `(rv40, mpeg4 @ 720p+, wmv3), or a resolution too large for single-threaded WASM to keep up with.`,\n );\n }\n } else {\n watchdogSlowSinceMs = 0;\n }\n }\n\n // 2. Overflow-drop detection (>10% of decoded frames dropped\n // by the renderer's hard cap). This means the decoder\n // produces BURSTS — it's fast enough on average but one\n // batch delivers >30 frames at a time, overflowing before\n // the queueHighWater throttle can apply backpressure.\n // Symptom is different from \"decoder slow\": here the fps\n // ratio looks fine but the user sees choppy playback.\n if (\n !watchdogOverflowWarned &&\n videoFramesDecoded > 100 // wait for a meaningful sample\n ) {\n const rendererStats = opts.renderer.stats() as { framesDroppedOverflow?: number };\n const overflow = rendererStats.framesDroppedOverflow ?? 0;\n if (overflow / videoFramesDecoded > 0.1) {\n watchdogOverflowWarned = true;\n console.warn(\n \"[avbridge:overflow-drop]\",\n `renderer is dropping ${overflow}/${videoFramesDecoded} frames ` +\n `(${((overflow / videoFramesDecoded) * 100).toFixed(0)}%) because the decoder ` +\n `is producing bursts faster than the canvas can drain. Symptom: choppy ` +\n `playback despite decoder keeping up on average. Fix would be smaller ` +\n `read batches in the pump loop or a lower queueHighWater cap — see ` +\n `src/strategies/fallback/decoder.ts.`,\n );\n }\n }\n }\n\n // Throttle: don't run too far ahead of playback. Two backpressure\n // signals:\n // - Audio buffer (mediaTimeOfNext - now()) > 2 sec — we have\n // plenty of audio scheduled.\n // - Renderer queue depth >= queueHighWater — the canvas can't\n // drain fast enough. Without this, fast software decode of\n // small frames piles up in the renderer and overflows.\n while (\n !destroyed &&\n myToken === pumpToken &&\n (opts.audio.bufferAhead() > 2.0 ||\n opts.renderer.queueDepth() >= opts.renderer.queueHighWater)\n ) {\n await new Promise((r) => setTimeout(r, 50));\n }\n\n if (readErr === libav.AVERROR_EOF) {\n if (videoDec) await decodeVideoBatch([], myToken, /*flush*/ true);\n if (audioDec) await decodeAudioBatch([], myToken, /*flush*/ true);\n return;\n }\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n console.warn(\"[avbridge] ff_read_frame_multi returned\", readErr);\n return;\n }\n }\n }\n\n async function decodeVideoBatch(pkts: LibavPacket[], myToken: number, flush = false) {\n if (!videoDec || destroyed || myToken !== pumpToken) return;\n let frames: LibavFrame[];\n try {\n frames = await libav.ff_decode_multi(\n videoDec.c,\n videoDec.pkt,\n videoDec.frame,\n pkts,\n flush ? { fin: true, ignoreErrors: true } : { ignoreErrors: true },\n );\n } catch (err) {\n console.error(\"[avbridge] video decode batch failed:\", err);\n return;\n }\n if (myToken !== pumpToken || destroyed) return;\n\n for (const f of frames) {\n if (myToken !== pumpToken || destroyed) return;\n sanitizeFrameTimestamp(\n f,\n () => {\n const ts = syntheticVideoUs;\n syntheticVideoUs += videoFrameStepUs;\n return ts;\n },\n videoTimeBase,\n );\n // sanitizeFrameTimestamp normalizes pts to µs, so the bridge can\n // always use the 1/1e6 timebase.\n try {\n const vf = bridge.laFrameToVideoFrame(f, { timeBase: [1, 1_000_000] });\n opts.renderer.enqueue(vf);\n videoFramesDecoded++;\n } catch (err) {\n if (videoFramesDecoded === 0) {\n console.warn(\"[avbridge] laFrameToVideoFrame failed:\", err);\n }\n }\n }\n }\n\n async function decodeAudioBatch(pkts: LibavPacket[], myToken: number, flush = false) {\n if (!audioDec || destroyed || myToken !== pumpToken) return;\n let frames: LibavFrame[];\n try {\n frames = await libav.ff_decode_multi(\n audioDec.c,\n audioDec.pkt,\n audioDec.frame,\n pkts,\n flush ? { fin: true, ignoreErrors: true } : { ignoreErrors: true },\n );\n } catch (err) {\n console.error(\"[avbridge] audio decode batch failed:\", err);\n return;\n }\n if (myToken !== pumpToken || destroyed) return;\n\n for (const f of frames) {\n if (myToken !== pumpToken || destroyed) return;\n sanitizeFrameTimestamp(\n f,\n () => {\n const ts = syntheticAudioUs;\n const samples = f.nb_samples ?? 1024;\n const sampleRate = f.sample_rate ?? 44100;\n syntheticAudioUs += Math.round((samples * 1_000_000) / sampleRate);\n return ts;\n },\n audioTimeBase,\n );\n const samples = libavFrameToInterleavedFloat32(f);\n if (samples) {\n opts.audio.schedule(samples.data, samples.channels, samples.sampleRate);\n audioFramesDecoded++;\n }\n }\n }\n\n // Kick off the initial pump.\n pumpToken = 1;\n pumpRunning = pumpLoop(pumpToken).catch((err) =>\n console.error(\"[avbridge] decoder pump failed:\", err),\n );\n\n return {\n async destroy() {\n destroyed = true;\n pumpToken++;\n try { await pumpRunning; } catch { /* ignore */ }\n try { if (bsfCtx) await libav.av_bsf_free(bsfCtx); } catch { /* ignore */ }\n try { if (bsfPkt) await libav.av_packet_free?.(bsfPkt); } catch { /* ignore */ }\n try { if (videoDec) await libav.ff_free_decoder?.(videoDec.c, videoDec.pkt, videoDec.frame); } catch { /* ignore */ }\n try { if (audioDec) await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmt_ctx); } catch { /* ignore */ }\n try { await inputHandle.detach(); } catch { /* ignore */ }\n },\n\n async setAudioTrack(trackId, timeSec) {\n if (audioStream && audioStream.index === trackId) return;\n const newStream = streams.find(\n (s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === trackId,\n );\n if (!newStream) {\n console.warn(\"[avbridge] fallback: setAudioTrack — no stream with id\", trackId);\n return;\n }\n\n // Stop the pump before touching libav state. Same discipline as seek().\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n // Tear down the old audio decoder and init a fresh one for the new stream.\n if (audioDec) {\n try { await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n audioDec = null;\n }\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(newStream.codec_id, {\n codecpar: newStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n audioTimeBase = newStream.time_base_num && newStream.time_base_den\n ? [newStream.time_base_num, newStream.time_base_den]\n : undefined;\n } catch (err) {\n console.warn(\n \"[avbridge] fallback: setAudioTrack init failed — falling back to no-audio mode:\",\n (err as Error).message,\n );\n audioDec = null;\n opts.audio.setNoAudio();\n }\n\n audioStream = newStream;\n\n // Re-seek so packets resume from the user's current position for the\n // new track (and the same video position).\n try {\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] fallback: setAudioTrack seek failed:\", err);\n }\n\n // Flush the video decoder too — we just moved the demuxer back to a\n // keyframe boundary.\n try { if (videoDec) await libav.avcodec_flush_buffers?.(videoDec.c); } catch { /* ignore */ }\n await flushBSF();\n\n syntheticVideoUs = Math.round(timeSec * 1_000_000);\n syntheticAudioUs = Math.round(timeSec * 1_000_000);\n\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] fallback pump failed (post-setAudioTrack):\", err),\n );\n },\n\n async seek(timeSec) {\n // Cancel the current pump and wait for it to actually exit before\n // we start moving file pointers around — concurrent ff_decode_multi\n // and av_seek_frame on the same context would be a recipe for memory\n // corruption inside libav.\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n try {\n // libav.js's `av_seek_frame` takes the timestamp as a *split*\n // (lo, hi) int64 pair, NOT a single number. The function signature\n // is: av_seek_frame(s, stream_index, tsLo, tsHi, flags). Passing a\n // single number put AVSEEK_FLAG_BACKWARD (1) into tsHi, which\n // produced a bogus int64 = 4.29e9 + tsLo ≈ 73 min for any small\n // seek target — seeking past EOF and stalling the pump.\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] av_seek_frame failed:\", err);\n }\n\n // Reset the decoder state. After the previous pump exited via the\n // EOF path it called ff_decode_multi with `fin: true`, which sends a\n // NULL packet to the decoder and puts it in drain mode — meaning all\n // subsequent decode calls return EOF. `avcodec_flush_buffers` clears\n // that state so a fresh stream of post-seek packets is accepted.\n // Also clears any internal frame reordering buffer, which is what we\n // want anyway since we just changed positions.\n try {\n if (videoDec) await libav.avcodec_flush_buffers?.(videoDec.c);\n } catch { /* ignore */ }\n try {\n if (audioDec) await libav.avcodec_flush_buffers?.(audioDec.c);\n } catch { /* ignore */ }\n await flushBSF();\n\n // Reset synthetic timestamp counters to the seek target so newly\n // decoded frames start at the right media time.\n syntheticVideoUs = Math.round(timeSec * 1_000_000);\n syntheticAudioUs = Math.round(timeSec * 1_000_000);\n\n // The renderer & audio output are reset by the fallback session\n // wrapper that called us — see strategies/fallback/index.ts.\n\n // Start a fresh pump for the new token.\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] decoder pump failed (post-seek):\", err),\n );\n },\n\n bufferedUntilSec() {\n return bufferedUntilSec;\n },\n\n stats() {\n return {\n decoderType: \"libav-wasm\",\n packetsRead,\n videoFramesDecoded,\n audioFramesDecoded,\n bsfApplied: bsfCtx ? [\"mpeg4_unpack_bframes\"] : [],\n // Confirmed transport info: once prepareLibavInput returns\n // successfully, we *know* whether the source is http-range (probe\n // succeeded and returned 206) or in-memory blob. Diagnostics hoists\n // these `_`-prefixed keys to the typed fields.\n _transport: inputHandle.transport === \"http-range\" ? \"http-range\" : \"memory\",\n _rangeSupported: inputHandle.transport === \"http-range\",\n ...opts.renderer.stats(),\n ...opts.audio.stats(),\n };\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Bridge loader (lazy via the static-import wrapper).\n// ─────────────────────────────────────────────────────────────────────────────\n\nasync function loadBridge(): Promise<BridgeModule> {\n try {\n const wrapper = await import(\"./libav-import.js\");\n return wrapper.libavBridge as unknown as BridgeModule;\n } catch (err) {\n throw new Error(\n `failed to load libavjs-webcodecs-bridge — install the optional peer deps with: ` +\n `npm i libavjs-webcodecs-bridge @libav.js/variant-webcodecs. ` +\n `(${(err as Error).message})`,\n );\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Structural types.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface SoftDecoder {\n c: number;\n pkt: number;\n frame: number;\n}\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavFrame {\n data: unknown;\n format: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n nb_samples?: number;\n pts?: number;\n ptshi?: number;\n width?: number;\n height?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n AVSEEK_FLAG_BACKWARD?: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n ff_init_decoder(\n codec: number | string,\n config?: { codecpar?: number; time_base?: [number, number] },\n ): Promise<[number, number, number, number]>;\n ff_decode_multi(\n c: number,\n pkt: number,\n frame: number,\n packets: LibavPacket[],\n opts?: { fin?: boolean; ignoreErrors?: boolean },\n ): Promise<LibavFrame[]>;\n ff_free_decoder?(c: number, pkt: number, frame: number): Promise<void>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n av_seek_frame(\n fmt_ctx: number,\n stream: number,\n tsLo: number,\n tsHi: number,\n flags: number,\n ): Promise<number>;\n avcodec_flush_buffers?(c: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n /** Sync helper exposed by libav.js: split a JS number into (lo, hi) int64. */\n f64toi64?(val: number): [number, number];\n\n // BSF (bitstream filter) methods — used for mpeg4_unpack_bframes\n av_bsf_list_parse_str_js(str: string): Promise<number>;\n AVBSFContext_par_in(ctx: number): Promise<number>;\n avcodec_parameters_copy(dst: number, src: number): Promise<number>;\n av_bsf_init(ctx: number): Promise<number>;\n av_bsf_send_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_receive_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_free(ctx: number): Promise<void>;\n\n // Packet copy helpers — bridge JS packet objects to/from C-level pointers\n ff_copyin_packet(pktPtr: number, packet: LibavPacket): Promise<void>;\n ff_copyout_packet(pkt: number): Promise<LibavPacket>;\n}\n\ninterface BridgeModule {\n laFrameToVideoFrame(\n frame: LibavFrame,\n opts?: { VideoFrame?: unknown; timeBase?: [number, number]; transfer?: boolean },\n ): VideoFrame;\n laFrameToAudioData(\n frame: LibavFrame,\n opts?: { AudioData?: unknown; timeBase?: [number, number] },\n ): AudioData;\n}\n","import type { MediaContext, PlaybackSession, TransportConfig } from \"../../types.js\";\nimport { VideoRenderer } from \"./video-renderer.js\";\nimport { AudioOutput } from \"./audio-output.js\";\nimport { startDecoder, type DecoderHandles } from \"./decoder.js\";\nimport { dbg } from \"../../util/debug.js\";\nimport { makeTimeRanges } from \"../../util/time-ranges.js\";\n\n/**\n * Fallback strategy session.\n *\n * Owns the orchestration between the libav decoder, the audio scheduler,\n * and the canvas renderer. Three things make this non-trivial:\n *\n * 1. **Cold-start ready gate.** When `play()` is called, we wait until the\n * audio scheduler has buffered enough audio (≥ 300 ms) AND the renderer\n * has at least one decoded video frame, before actually telling the\n * audio context to start. Without this gate, audio and the wall clock\n * race ahead of the still-warming-up software decoder, and every video\n * frame lands \"in the past\" and gets dropped.\n *\n * 2. **Pause / resume.** The audio context is suspended on pause and\n * resumed on play. The media-time anchor is preserved across the\n * suspend so the clock is continuous.\n *\n * 3. **Seek.** Pauses the audio scheduler, asks the decoder to cancel its\n * current pump and `av_seek_frame` to the target, resets the audio\n * output's media-time anchor to the seek target, flushes the renderer\n * queue, then re-enters the ready gate. If we were playing before the\n * seek, we automatically resume once the buffer fills.\n *\n * The unified player API on top of this just sees `play() / pause() /\n * seek(t)` — none of the buffering choreography leaks out.\n */\n\n// Gate for cold-start playback. We want to start playing as soon as\n// there's any decoded output — the decoder will keep pumping during\n// playback, so more-is-better buffering only helps for fast decoders.\n//\n// For software-decode-bound content (rv40 / wmv3 / mpeg4 @ 720p+ on\n// single-threaded WASM), the decoder may run *slower* than realtime.\n// Waiting for a large audio-buffer threshold is actively wrong in that\n// case: it will never be reached, so the old gate would sit out its\n// full 10-second timeout before playing anything. An aggressive gate\n// ships the first frame to the screen fast, at the cost of the audio\n// clock racing a little ahead of video in the first few seconds —\n// which is the same situation we'd have been in after the timeout\n// anyway.\n//\n// READY_AUDIO_BUFFER_SECONDS: minimum audio queued before start. Set\n// low enough that a slow decoder still reaches it before the user\n// loses patience; 40 ms ≈ 2 cook packets or ~2 AAC packets.\n// READY_TIMEOUT_SECONDS: hard safety. If even 40 ms of audio can't be\n// produced in 3 s, give up and play whatever we have.\nconst READY_AUDIO_BUFFER_SECONDS = 0.04;\nconst READY_TIMEOUT_SECONDS = 3;\n\nexport async function createFallbackSession(\n ctx: MediaContext,\n target: HTMLVideoElement,\n transport?: TransportConfig,\n): Promise<PlaybackSession> {\n // Normalize the source so URL inputs go through the libav HTTP block\n // reader instead of being buffered into memory.\n const { normalizeSource } = await import(\"../../util/source.js\");\n const source = await normalizeSource(ctx.source);\n\n const fps = ctx.videoTracks[0]?.fps ?? 30;\n const audio = new AudioOutput();\n const renderer = new VideoRenderer(target, audio, fps);\n\n let handles: DecoderHandles;\n try {\n handles = await startDecoder({\n source,\n filename: ctx.name ?? \"input.bin\",\n context: ctx,\n renderer,\n audio,\n transport,\n });\n } catch (err) {\n audio.destroy();\n renderer.destroy();\n throw err;\n }\n\n // Patch the <video> element so the unified player layer (which polls\n // `target.currentTime` for `timeupdate` events and lets users assign to\n // it for seeks) gets the right values from the fallback strategy.\n Object.defineProperty(target, \"currentTime\", {\n configurable: true,\n get: () => audio.now(),\n set: (v: number) => {\n // Fire-and-forget — the user is expected to await player.seek() if\n // they want to know when the seek completes.\n void doSeek(v);\n },\n });\n // Mirror `paused` / `volume` / `muted` from the audio output — the\n // underlying <video> never has its own src, so its native state is\n // meaningless. This lets HTMLMediaElement consumers (<avbridge-player>\n // controls) see the real values and control volume through the audio\n // output's GainNode.\n Object.defineProperty(target, \"paused\", {\n configurable: true,\n get: () => !audio.isPlaying(),\n });\n Object.defineProperty(target, \"volume\", {\n configurable: true,\n get: () => audio.getVolume(),\n set: (v: number) => {\n audio.setVolume(v);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n Object.defineProperty(target, \"muted\", {\n configurable: true,\n get: () => audio.getMuted(),\n set: (m: boolean) => {\n audio.setMuted(m);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n // Mirror duration so the demo's controls can use target.duration too.\n if (ctx.duration && Number.isFinite(ctx.duration)) {\n Object.defineProperty(target, \"duration\", {\n configurable: true,\n get: () => ctx.duration ?? NaN,\n });\n }\n // Playback rate — canvas strategies don't use the real <video>, so the\n // native playbackRate property does nothing. Patch it to drive the\n // AudioOutput clock speed + pitch.\n Object.defineProperty(target, \"playbackRate\", {\n configurable: true,\n get: () => audio.getPlaybackRate(),\n set: (v: number) => {\n audio.setPlaybackRate(v);\n target.dispatchEvent(new Event(\"ratechange\"));\n },\n });\n // Synthesize HTMLMediaElement parity surfaces that the canvas strategies\n // can't otherwise answer truthfully (the inner <video> has no src, so\n // its own readyState/seekable are zero/empty).\n //\n // readyState: HAVE_NOTHING (0) until the first frame lands; then\n // HAVE_CURRENT_DATA (2) once the cold-start gate is released (both\n // audio+video ready). Simplified from the full five-level spec — we\n // don't distinguish HAVE_FUTURE_DATA vs HAVE_ENOUGH_DATA since our\n // pump semantics make those essentially the same state.\n Object.defineProperty(target, \"readyState\", {\n configurable: true,\n get: (): number => {\n if (!renderer.hasFrames()) return 0; // HAVE_NOTHING\n if (!audio.isPlaying() && audio.bufferAhead() <= 0 && !audio.isNoAudio()) return 1; // HAVE_METADATA\n return 2; // HAVE_CURRENT_DATA (or better — but 2 is the honest lower bound)\n },\n });\n // seekable: a progressive source is fully seekable once we have duration.\n Object.defineProperty(target, \"seekable\", {\n configurable: true,\n get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0\n ? [[0, ctx.duration]]\n : []),\n });\n // buffered: demuxer's read-ahead frontier (highest pts pumped from\n // libav). Single [0, end] range — approximation of \"how far we've\n // read through the source,\" the signal the seek-bar buffered\n // indicator wants. Real MSE-style per-range tracking isn't\n // meaningful here since decoded frames are consumed in flight.\n Object.defineProperty(target, \"buffered\", {\n configurable: true,\n get: () => {\n const end = handles.bufferedUntilSec();\n return makeTimeRanges(end > 0 ? [[0, end]] : []);\n },\n });\n\n /**\n * Wait until the decoder has produced enough buffered output to start\n * playback smoothly. Returns early on timeout so we don't hang forever\n * if the decoder is producing nothing (e.g. immediately past EOF after\n * a seek to the end).\n *\n * The gate has three exit paths in order of preference:\n *\n * 1. **Fully ready** — audio buffer ≥ target AND ≥1 video frame.\n * The happy path for fast decoders (native + remux never reach\n * this function; this is fallback only).\n *\n * 2. **Video-ready, audio grace period elapsed** — we have video\n * frames but the audio scheduler is still empty. RM/AVI\n * containers commonly deliver a video GOP before their first\n * audio packet, so \"no audio yet\" ≠ \"no audio coming\". We give\n * the demuxer a 500 ms grace window from first-frame, then\n * start regardless. Audio will be scheduled at its correct\n * media time once its packets arrive.\n *\n * 3. **Hard timeout** — after {@link READY_TIMEOUT_SECONDS} seconds\n * with neither condition met, start anyway and emit an\n * unconditional diagnostic so the specific underflow is visible.\n *\n * Path #2 is what fixed the \"RMVB sits on the play button for 10 s\n * with audio=0ms, frames=N\" case — the gate was waiting on audio\n * packets that were several seconds behind in the file stream, and\n * the timeout was the only way out.\n */\n async function waitForBuffer(): Promise<void> {\n const start = performance.now();\n let firstFrameAtMs = 0;\n dbg.info(\"cold-start\",\n `gate entry: want audio ≥ ${READY_AUDIO_BUFFER_SECONDS * 1000}ms + 1 frame`,\n );\n while (true) {\n const audioAhead = audio.isNoAudio() ? Infinity : audio.bufferAhead();\n const audioReady = audio.isNoAudio() || audioAhead >= READY_AUDIO_BUFFER_SECONDS;\n const hasFrames = renderer.hasFrames();\n const nowMs = performance.now();\n\n if (hasFrames && firstFrameAtMs === 0) firstFrameAtMs = nowMs;\n\n // Happy path: both ready.\n if (audioReady && hasFrames) {\n dbg.info(\"cold-start\",\n `gate satisfied in ${(nowMs - start).toFixed(0)}ms ` +\n `(audio=${(audioAhead * 1000).toFixed(0)}ms, frames=${renderer.queueDepth()})`,\n );\n return;\n }\n\n // Grace path: have video, still waiting for audio that's\n // on its way (first 500 ms after first-frame).\n if (\n hasFrames &&\n firstFrameAtMs > 0 &&\n nowMs - firstFrameAtMs >= 500\n ) {\n dbg.info(\"cold-start\",\n `gate released on video-only grace at ${(nowMs - start).toFixed(0)}ms ` +\n `(frames=${renderer.queueDepth()}, audio=${(audioAhead * 1000).toFixed(0)}ms — ` +\n `demuxer hasn't delivered audio packets yet, starting anyway and letting ` +\n `the audio scheduler catch up at its media-time anchor)`,\n );\n return;\n }\n\n // Hard timeout.\n if ((nowMs - start) / 1000 > READY_TIMEOUT_SECONDS) {\n dbg.diag(\"cold-start\",\n `gate TIMEOUT after ${READY_TIMEOUT_SECONDS}s — ` +\n `audio=${(audioAhead * 1000).toFixed(0)}ms ` +\n `(needed ${READY_AUDIO_BUFFER_SECONDS * 1000}ms), ` +\n `frames=${renderer.queueDepth()} (needed ≥1). ` +\n `Decoder produced nothing in ${READY_TIMEOUT_SECONDS}s — either a corrupt source, ` +\n `a missing codec, or WASM is catastrophically slow on this file. ` +\n `Check getDiagnostics().runtime for decode counters.`,\n );\n return;\n }\n await new Promise((r) => setTimeout(r, 50));\n }\n }\n\n async function doSeek(timeSec: number): Promise<void> {\n const wasPlaying = audio.isPlaying();\n // HTMLMediaElement contract: dispatch `seeking` once the seek\n // operation begins. The inner <video> never fires this itself on\n // canvas strategies (no src), so we dispatch manually to preserve\n // the contract for consumers listening via `<avbridge-video>`.\n target.dispatchEvent(new Event(\"seeking\"));\n // 1. Stop audio (suspend ctx + capture media time).\n await audio.pause().catch(() => {});\n // 2. Tell the decoder to cancel its pump and seek the demuxer.\n await handles.seek(timeSec).catch((err) =>\n console.warn(\"[avbridge] decoder seek failed:\", err),\n );\n // 3. Reset audio + renderer to the new media time. New samples from\n // the decoder will queue against this anchor.\n await audio.reset(timeSec);\n renderer.flush();\n // 4. If we were playing, wait for the buffer to fill again and then\n // resume. If we were paused, leave it paused at the new position.\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n // HTMLMediaElement contract: dispatch `seeked` after the seek has\n // completed (demuxer + renderer reset + optional buffer refill).\n target.dispatchEvent(new Event(\"seeked\"));\n }\n\n // HTMLMediaElement contract: dispatch `loadedmetadata` once the\n // session is ready (duration, dimensions, tracks known via the\n // MediaContext). Dispatched on a microtask so it lands after the\n // session promise resolves and consumers have a chance to attach\n // listeners. The inner <video> never fires this itself here — it\n // has no src.\n queueMicrotask(() => {\n try { target.dispatchEvent(new Event(\"loadedmetadata\")); } catch { /* element torn down */ }\n });\n\n return {\n strategy: \"fallback\",\n\n async play() {\n // Either a cold start (very first play() call) or a resume from\n // pause. AudioOutput.start() handles both.\n if (!audio.isPlaying()) {\n await waitForBuffer();\n await audio.start();\n target.dispatchEvent(new Event(\"play\"));\n target.dispatchEvent(new Event(\"playing\"));\n }\n },\n\n pause() {\n void audio.pause();\n target.dispatchEvent(new Event(\"pause\"));\n },\n\n async seek(time) {\n await doSeek(time);\n },\n\n async setAudioTrack(id) {\n // Verify the id refers to a real track.\n if (!ctx.audioTracks.some((t) => t.id === id)) {\n console.warn(\"[avbridge] fallback: setAudioTrack — unknown track id\", id);\n return;\n }\n const wasPlaying = audio.isPlaying();\n const currentTime = audio.now();\n // Suspend audio, rebuild the decoder + seek, reset audio output, re-gate.\n await audio.pause().catch(() => {});\n await handles.setAudioTrack(id, currentTime).catch((err) =>\n console.warn(\"[avbridge] fallback: handles.setAudioTrack failed:\", err),\n );\n await audio.reset(currentTime);\n renderer.flush();\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n },\n\n async setSubtitleTrack(_id) {\n // Subtitle overlay support is post-MVP for the fallback strategy.\n },\n\n getCurrentTime() {\n return audio.now();\n },\n async destroy() {\n await handles.destroy();\n renderer.destroy();\n audio.destroy();\n try {\n delete (target as unknown as Record<string, unknown>).currentTime;\n delete (target as unknown as Record<string, unknown>).duration;\n delete (target as unknown as Record<string, unknown>).paused;\n delete (target as unknown as Record<string, unknown>).volume;\n delete (target as unknown as Record<string, unknown>).muted;\n delete (target as unknown as Record<string, unknown>).readyState;\n delete (target as unknown as Record<string, unknown>).seekable;\n delete (target as unknown as Record<string, unknown>).playbackRate;\n } catch { /* ignore */ }\n },\n\n getRuntimeStats() {\n return handles.stats();\n },\n };\n}\n","import type { Plugin } from \"../types.js\";\nimport { createNativeSession } from \"../strategies/native.js\";\nimport { createRemuxSession } from \"../strategies/remux/index.js\";\nimport { createHybridSession } from \"../strategies/hybrid/index.js\";\nimport { createFallbackSession } from \"../strategies/fallback/index.js\";\nimport type { PluginRegistry } from \"./registry.js\";\n\nconst nativePlugin: Plugin = {\n name: \"native\",\n canHandle: () => true,\n execute: (ctx, video) => createNativeSession(ctx, video),\n};\n\nconst remuxPlugin: Plugin = {\n name: \"remux\",\n canHandle: () => true,\n execute: (ctx, video) => createRemuxSession(ctx, video),\n};\n\nconst hybridPlugin: Plugin = {\n name: \"hybrid\",\n canHandle: () => typeof VideoDecoder !== \"undefined\",\n execute: (ctx, video, transport) => createHybridSession(ctx, video, transport),\n};\n\nconst fallbackPlugin: Plugin = {\n name: \"fallback\",\n canHandle: () => true,\n execute: (ctx, video, transport) => createFallbackSession(ctx, video, transport),\n};\n\nexport function registerBuiltins(registry: PluginRegistry): void {\n registry.register(nativePlugin);\n registry.register(remuxPlugin);\n registry.register(hybridPlugin);\n registry.register(fallbackPlugin);\n}\n","import { TypedEmitter } from \"./events.js\";\nimport { probe } from \"./probe/index.js\";\nimport { classify } from \"./classify/index.js\";\nimport { Diagnostics } from \"./diagnostics.js\";\nimport { PluginRegistry } from \"./plugins/registry.js\";\nimport { registerBuiltins } from \"./plugins/builtin.js\";\nimport { discoverSidecars, attachSubtitleTracks, SubtitleResourceBag } from \"./subtitles/index.js\";\nimport { dbg } from \"./util/debug.js\";\nimport type {\n Classification,\n CreatePlayerOptions,\n DiagnosticsSnapshot,\n MediaContext,\n PlaybackSession,\n PlayerEventMap,\n PlayerEventName,\n StrategyName,\n TransportConfig,\n Listener,\n} from \"./types.js\";\nimport { AvbridgeError, ERR_PLAYER_NOT_READY, ERR_ALL_STRATEGIES_EXHAUSTED } from \"./errors.js\";\n\n/**\n * Decoded-video-frame counter reader. Prefers the standard\n * `getVideoPlaybackQuality().totalVideoFrames` (all evergreen browsers);\n * falls back to the WebKit-prefixed `webkitDecodedFrameCount` for older\n * Safari. Returns 0 for non-video elements or when nothing exposes the\n * count — the caller treats 0 as \"no signal\" (constant across samples,\n * which is fine).\n */\nexport function readDecodedFrameCount(target: HTMLMediaElement): number {\n if (typeof HTMLVideoElement === \"undefined\" || !(target instanceof HTMLVideoElement)) return 0;\n const vq = (target as HTMLVideoElement & { getVideoPlaybackQuality?: () => { totalVideoFrames: number } }).getVideoPlaybackQuality;\n if (typeof vq === \"function\") {\n try { return vq.call(target).totalVideoFrames; } catch { /* fall through */ }\n }\n const legacy = (target as HTMLVideoElement & { webkitDecodedFrameCount?: number }).webkitDecodedFrameCount;\n return typeof legacy === \"number\" ? legacy : 0;\n}\n\n/**\n * Pure decision function for the stall supervisor. Takes a snapshot of\n * the observable state and returns whether to escalate. Extracted so it\n * can be unit-tested without spinning up a real player / media element.\n *\n * - `time-stall`: `currentTime` hasn't moved for `timeStallThresholdMs`\n * despite the element being in a state where it should be playing.\n * - `silent-video`: the media has a video track, `currentTime` is\n * advancing (audio is playing), but the decoder has produced no new\n * frames for `frameStallThresholdMs`. Catches Firefox-style \"MSE\n * reports codec supported but the decoder can't actually decode it\".\n */\nexport function evaluateDecodeHealth(input: {\n hasVideoTrack: boolean;\n timeAdvanced: boolean;\n framesAdvanced: boolean;\n now: number;\n lastProgressTime: number;\n lastFrameProgressTime: number;\n timeStallThresholdMs?: number;\n frameStallThresholdMs?: number;\n}): { escalate: false } | { escalate: true; kind: \"time-stall\" | \"silent-video\" } {\n const timeThreshold = input.timeStallThresholdMs ?? 5000;\n const frameThreshold = input.frameStallThresholdMs ?? 3000;\n if (!input.timeAdvanced && input.now - input.lastProgressTime > timeThreshold) {\n return { escalate: true, kind: \"time-stall\" };\n }\n if (\n input.hasVideoTrack &&\n input.timeAdvanced &&\n !input.framesAdvanced &&\n input.now - input.lastFrameProgressTime > frameThreshold\n ) {\n return { escalate: true, kind: \"silent-video\" };\n }\n return { escalate: false };\n}\n\nexport class UnifiedPlayer {\n private emitter = new TypedEmitter<PlayerEventMap>();\n private session: PlaybackSession | null = null;\n private diag = new Diagnostics();\n private timeupdateInterval: ReturnType<typeof setInterval> | null = null;\n\n // Saved from bootstrap for strategy switching\n private mediaContext: MediaContext | null = null;\n private classification: Classification | null = null;\n\n // Stall detection\n private stallTimer: ReturnType<typeof setInterval> | null = null;\n private lastProgressTime = 0;\n private lastProgressPosition = -1;\n /** Last observed `HTMLVideoElement.getVideoPlaybackQuality().totalVideoFrames`\n * (or `webkitDecodedFrameCount` fallback). Used by the silent-video\n * watchdog — catches cases where `currentTime` advances (audio plays)\n * but the decoder produces no frames, e.g. Firefox claiming `hev1.*`\n * via MSE when the decoder actually can't decode HEVC. */\n private lastVideoFrameCount = 0;\n private lastVideoFrameProgressTime = 0;\n private errorListener: (() => void) | null = null;\n\n // Bound so we can removeEventListener in destroy(); without this the\n // listener outlives the player and accumulates on elements that swap\n // source (e.g. <avbridge-video>).\n private endedListener: (() => void) | null = null;\n\n // Background tab handling. userIntent is what the user last asked for\n // (play vs pause) — used to decide whether to auto-resume on visibility\n // return. autoPausedForVisibility tracks whether we paused because the\n // tab was hidden, so we don't resume playback the user deliberately\n // paused (e.g. via media keys while hidden).\n private userIntent: \"play\" | \"pause\" = \"pause\";\n private autoPausedForVisibility = false;\n private visibilityListener: (() => void) | null = null;\n\n // Serializes escalation / setStrategy calls\n private switchingPromise: Promise<void> = Promise.resolve();\n\n // Owns blob URLs created during sidecar discovery + SRT->VTT conversion.\n // Revoked at destroy() so repeated source swaps don't leak.\n private subtitleResources = new SubtitleResourceBag();\n\n // Transport config extracted from CreatePlayerOptions. Threaded to probe,\n // subtitle fetches, and strategy session creators. Not stored on MediaContext\n // because it's runtime config, not media analysis.\n private readonly transport: TransportConfig | undefined;\n\n /**\n * @internal Use {@link createPlayer} or {@link UnifiedPlayer.create} instead.\n */\n private constructor(\n private readonly options: CreatePlayerOptions,\n private readonly registry: PluginRegistry,\n ) {\n const { requestInit, fetchFn, cacheBytes } = options;\n if (requestInit || fetchFn || cacheBytes !== undefined) {\n this.transport = { requestInit, fetchFn, cacheBytes };\n }\n }\n\n static async create(options: CreatePlayerOptions): Promise<UnifiedPlayer> {\n const registry = new PluginRegistry();\n registerBuiltins(registry);\n if (options.plugins) {\n for (const p of options.plugins) registry.register(p, /* prepend */ true);\n }\n const player = new UnifiedPlayer(options, registry);\n try {\n await player.bootstrap();\n } catch (err) {\n (err as Error & { player?: UnifiedPlayer }).player = player;\n throw err;\n }\n return player;\n }\n\n private async bootstrap(): Promise<void> {\n const bootstrapStart = performance.now();\n try {\n dbg.info(\"bootstrap\", \"start\");\n const ctx = await dbg.timed(\"probe\", \"probe\", 3000, () => probe(this.options.source, this.transport));\n dbg.info(\"probe\",\n `container=${ctx.container} video=${ctx.videoTracks[0]?.codec ?? \"-\"} ` +\n `audio=${ctx.audioTracks[0]?.codec ?? \"-\"} probedBy=${ctx.probedBy}`,\n );\n this.diag.recordProbe(ctx);\n this.mediaContext = ctx;\n\n // Merge sidecar / explicit subtitles\n if (this.options.subtitles) {\n for (const s of this.options.subtitles) {\n ctx.subtitleTracks.push({\n id: ctx.subtitleTracks.length,\n format: s.format ?? (s.url.endsWith(\".srt\") ? \"srt\" : \"vtt\"),\n language: s.language,\n sidecarUrl: s.url,\n });\n }\n }\n if (this.options.directory && this.options.source instanceof File) {\n const found = await discoverSidecars(this.options.source, this.options.directory);\n for (const s of found) {\n // Track every blob URL we adopted from discovery so it gets\n // revoked at destroy() — otherwise repeated source changes leak.\n this.subtitleResources.track(s.url);\n ctx.subtitleTracks.push({\n id: ctx.subtitleTracks.length,\n format: s.format,\n language: s.language,\n sidecarUrl: s.url,\n });\n }\n }\n\n const decision = this.options.initialStrategy\n ? buildInitialDecision(this.options.initialStrategy, ctx)\n : classify(ctx);\n dbg.info(\"classify\",\n `strategy=${decision.strategy} class=${decision.class} reason=\"${decision.reason}\"` +\n (decision.fallbackChain ? ` fallback=${decision.fallbackChain.join(\"→\")}` : \"\"),\n );\n this.classification = decision;\n this.diag.recordClassification(decision);\n\n this.emitter.emitSticky(\"strategy\", {\n strategy: decision.strategy,\n reason: decision.reason,\n });\n\n // Try the primary strategy, falling through the chain on failure\n await this.startSession(decision.strategy, decision.reason);\n\n // Apply subtitles for all strategies. Native/remux render them via\n // the inner <video>'s native text-track engine. Hybrid/fallback\n // hide the <video> and render cues into the canvas overlay — see\n // each session's SubtitleOverlay wiring. The <track> elements are\n // attached in both cases so cues are parsed by the browser.\n await attachSubtitleTracks(\n this.options.target,\n ctx.subtitleTracks,\n this.subtitleResources,\n (err, track) => {\n // eslint-disable-next-line no-console\n console.warn(`[avbridge] subtitle ${track.id} failed: ${err.message}`);\n },\n this.transport,\n );\n\n this.emitter.emitSticky(\"tracks\", {\n video: ctx.videoTracks,\n audio: ctx.audioTracks,\n subtitle: ctx.subtitleTracks,\n });\n\n this.startTimeupdateLoop();\n this.endedListener = () => this.emitter.emit(\"ended\", undefined);\n this.options.target.addEventListener(\"ended\", this.endedListener);\n\n // Auto-pause on background tab (unless explicitly opted out).\n // Chrome throttles rAF and setTimeout in hidden tabs, so playback\n // degrades anyway — better to pause cleanly and resume on return.\n if (this.options.backgroundBehavior !== \"continue\" && typeof document !== \"undefined\") {\n this.visibilityListener = () => this.onVisibilityChange();\n document.addEventListener(\"visibilitychange\", this.visibilityListener);\n }\n\n this.emitter.emitSticky(\"ready\", undefined);\n const bootstrapElapsed = performance.now() - bootstrapStart;\n dbg.info(\"bootstrap\", `ready in ${bootstrapElapsed.toFixed(0)}ms`);\n if (bootstrapElapsed > 5000) {\n // eslint-disable-next-line no-console\n console.warn(\n \"[avbridge:bootstrap]\",\n `total bootstrap time ${bootstrapElapsed.toFixed(0)}ms — unusually slow. ` +\n `Enable globalThis.AVBRIDGE_DEBUG for a per-phase breakdown.`,\n );\n }\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n this.diag.recordError(e);\n this.emitter.emit(\"error\", e);\n throw e;\n }\n }\n\n /**\n * Try to start a session with the given strategy. On failure, walk the\n * fallback chain. Throws only if all strategies are exhausted.\n */\n private async startSession(strategy: StrategyName, reason: string): Promise<void> {\n const plugin = this.registry.findFor(this.mediaContext!, strategy);\n if (!plugin) {\n throw new Error(`no plugin available for strategy \"${strategy}\"`);\n }\n\n try {\n this.session = await plugin.execute(this.mediaContext!, this.options.target, this.transport);\n } catch (err) {\n // Try the fallback chain\n const chain = this.classification?.fallbackChain;\n if (chain && chain.length > 0) {\n const next = chain.shift()!;\n console.warn(`[avbridge] ${strategy} failed (${(err as Error).message}), escalating to ${next}`);\n this.emitter.emit(\"strategychange\", {\n from: strategy,\n to: next,\n reason: `${strategy} failed: ${(err as Error).message}`,\n currentTime: 0,\n });\n this.diag.recordStrategySwitch(next, `${strategy} failed: ${(err as Error).message}`);\n return this.startSession(next, `escalated from ${strategy}`);\n }\n throw err;\n }\n\n // Wire up fatal error handler for hybrid/fallback escalation\n this.session.onFatalError?.((fatalReason) => {\n void this.escalate(fatalReason);\n });\n\n // Attach stall supervisor\n this.attachSupervisor();\n\n // Update sticky strategy event if we ended up on a different strategy\n if (this.session.strategy !== strategy) {\n this.emitter.emitSticky(\"strategy\", {\n strategy: this.session.strategy,\n reason,\n });\n }\n }\n\n // ── Escalation ──────────────────────────────────────────────────────────\n\n private async escalate(reason: string): Promise<void> {\n // Serialize with other switch operations\n this.switchingPromise = this.switchingPromise.then(() =>\n this.doEscalate(reason),\n ).catch((err) => {\n this.emitter.emit(\"error\", err instanceof Error ? err : new Error(String(err)));\n });\n await this.switchingPromise;\n }\n\n private async doEscalate(reason: string): Promise<void> {\n const chain = this.classification?.fallbackChain;\n if (!chain || chain.length === 0) {\n this.emitter.emit(\"error\", new Error(\n `strategy \"${this.session?.strategy}\" failed: ${reason} (no fallback available)`,\n ));\n return;\n }\n\n const currentTime = this.session?.getCurrentTime() ?? 0;\n const wasPlaying = this.session ? !this.options.target.paused : false;\n const fromStrategy = this.session?.strategy ?? \"native\";\n\n // Tear down the current session before walking the chain — once we\n // commit to escalating, the existing session is going away regardless\n // of which fallback step succeeds.\n this.clearSupervisor();\n if (this.session) {\n try { await this.session.destroy(); } catch { /* ignore */ }\n this.session = null;\n }\n\n // Walk every remaining entry in the chain. Previously this method\n // popped exactly one entry and gave up if its plugin failed to start —\n // a recoverable failure in one fallback step blocked later viable\n // strategies (inconsistent with startSession() which already loops).\n const errors: string[] = [];\n while (chain.length > 0) {\n const nextStrategy = chain.shift()!;\n console.warn(`[avbridge] escalating from ${fromStrategy} to ${nextStrategy}: ${reason}`);\n\n this.emitter.emit(\"strategychange\", {\n from: fromStrategy,\n to: nextStrategy,\n reason,\n currentTime,\n });\n this.diag.recordStrategySwitch(nextStrategy, reason);\n\n const plugin = this.registry.findFor(this.mediaContext!, nextStrategy);\n if (!plugin) {\n errors.push(`${nextStrategy}: no plugin available`);\n continue;\n }\n\n try {\n this.session = await plugin.execute(this.mediaContext!, this.options.target, this.transport);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n errors.push(`${nextStrategy}: ${msg}`);\n console.warn(`[avbridge] ${nextStrategy} failed during escalation, trying next: ${msg}`);\n continue;\n }\n\n // Success — finish wiring and restore playback.\n this.emitter.emitSticky(\"strategy\", {\n strategy: nextStrategy,\n reason: `escalated: ${reason}`,\n });\n this.session.onFatalError?.((fatalReason) => {\n void this.escalate(fatalReason);\n });\n this.attachSupervisor();\n try {\n await this.session.seek(currentTime);\n if (wasPlaying) await this.session.play();\n } catch (err) {\n console.warn(\"[avbridge] failed to restore position after escalation:\", err);\n }\n return;\n }\n\n // Chain exhausted with no working strategy.\n this.emitter.emit(\"error\", new AvbridgeError(\n ERR_ALL_STRATEGIES_EXHAUSTED,\n `All playback strategies failed: ${errors.join(\"; \")}`,\n \"This file may require a codec or container that isn't available in this browser. Try the fallback strategy or check browser codec support.\",\n ));\n }\n\n // ── Stall supervision ─────────────────────────────────────────────────\n\n private attachSupervisor(): void {\n this.clearSupervisor();\n if (this.options.autoEscalate === false) return;\n if (!this.classification?.fallbackChain?.length) return;\n\n const strategy = this.session?.strategy;\n if (strategy === \"native\" || strategy === \"remux\") {\n // Monitor currentTime progress\n this.lastProgressPosition = this.options.target.currentTime;\n this.lastProgressTime = performance.now();\n this.lastVideoFrameCount = readDecodedFrameCount(this.options.target);\n this.lastVideoFrameProgressTime = performance.now();\n\n const hasVideoTrack = (this.mediaContext?.videoTracks.length ?? 0) > 0;\n\n this.stallTimer = setInterval(() => {\n const t = this.options.target;\n const now = performance.now();\n if (t.paused || t.ended || t.readyState < 2) {\n this.lastProgressPosition = t.currentTime;\n this.lastProgressTime = now;\n this.lastVideoFrameCount = readDecodedFrameCount(t);\n this.lastVideoFrameProgressTime = now;\n return;\n }\n const timeAdvanced = t.currentTime !== this.lastProgressPosition;\n const frames = readDecodedFrameCount(t);\n const framesAdvanced = frames > this.lastVideoFrameCount;\n\n const health = evaluateDecodeHealth({\n hasVideoTrack,\n timeAdvanced,\n framesAdvanced,\n now,\n lastProgressTime: this.lastProgressTime,\n lastFrameProgressTime: this.lastVideoFrameProgressTime,\n });\n\n if (timeAdvanced) {\n this.lastProgressPosition = t.currentTime;\n this.lastProgressTime = now;\n }\n if (framesAdvanced) {\n this.lastVideoFrameCount = frames;\n this.lastVideoFrameProgressTime = now;\n }\n\n if (health.escalate) {\n const reason = health.kind === \"time-stall\"\n ? `${strategy} strategy stalled for 5s at ${t.currentTime.toFixed(1)}s`\n : `${strategy} strategy: audio is advancing but the video decoder has produced no new frames for 3s — likely a silent codec failure`;\n void this.escalate(reason);\n }\n }, 1000);\n\n // Listen for media element errors\n const onError = () => {\n void this.escalate(\n `${strategy} strategy error: ${this.options.target.error?.message ?? \"unknown\"}`,\n );\n };\n this.options.target.addEventListener(\"error\", onError, { once: true });\n this.errorListener = onError;\n }\n // Hybrid/fallback escalation is handled via onFatalError callback\n }\n\n private clearSupervisor(): void {\n if (this.stallTimer) {\n clearInterval(this.stallTimer);\n this.stallTimer = null;\n }\n if (this.errorListener) {\n this.options.target.removeEventListener(\"error\", this.errorListener);\n this.errorListener = null;\n }\n }\n\n // ── Public: manual strategy switch ────────────────────────────────────\n\n /** Manually switch to a different playback strategy. Preserves current position and play/pause state. Concurrent calls are serialized. */\n async setStrategy(strategy: StrategyName, reason?: string): Promise<void> {\n if (!this.mediaContext) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n if (this.session?.strategy === strategy) return;\n\n this.switchingPromise = this.switchingPromise.then(() =>\n this.doSetStrategy(strategy, reason),\n );\n await this.switchingPromise;\n }\n\n private async doSetStrategy(strategy: StrategyName, reason?: string): Promise<void> {\n const currentTime = this.session?.getCurrentTime() ?? 0;\n const wasPlaying = this.session ? !this.options.target.paused : false;\n const fromStrategy = this.session?.strategy ?? \"native\";\n const switchReason = reason ?? `manual switch to ${strategy}`;\n\n this.emitter.emit(\"strategychange\", {\n from: fromStrategy,\n to: strategy,\n reason: switchReason,\n currentTime,\n });\n this.diag.recordStrategySwitch(strategy, switchReason);\n\n this.clearSupervisor();\n if (this.session) {\n try { await this.session.destroy(); } catch { /* ignore */ }\n this.session = null;\n }\n\n const plugin = this.registry.findFor(this.mediaContext!, strategy);\n if (!plugin) throw new Error(`no plugin available for strategy \"${strategy}\"`);\n\n this.session = await plugin.execute(this.mediaContext!, this.options.target, this.transport);\n\n this.emitter.emitSticky(\"strategy\", {\n strategy,\n reason: switchReason,\n });\n\n this.session.onFatalError?.((fatalReason) => {\n void this.escalate(fatalReason);\n });\n this.attachSupervisor();\n\n try {\n await this.session.seek(currentTime);\n if (wasPlaying) await this.session.play();\n } catch (err) {\n console.warn(\"[avbridge] failed to restore position after strategy switch:\", err);\n }\n }\n\n // ── Timeupdate loop ───────────────────────────────────────────────────\n\n private startTimeupdateLoop(): void {\n this.timeupdateInterval = setInterval(() => {\n const t = this.session?.getCurrentTime() ?? this.options.target.currentTime;\n this.emitter.emit(\"timeupdate\", { currentTime: t });\n }, 250);\n }\n\n // ── Public API ────────────────────────────────────────────────────────\n\n /** Subscribe to a player event. Returns an unsubscribe function. Sticky events (strategy, ready, tracks) replay for late subscribers. */\n on<K extends PlayerEventName>(event: K, fn: Listener<PlayerEventMap[K]>): () => void {\n return this.emitter.on(event, fn);\n }\n\n /** Remove a previously registered event listener. */\n off<K extends PlayerEventName>(event: K, fn: Listener<PlayerEventMap[K]>): void {\n this.emitter.off(event, fn);\n }\n\n /** Begin or resume playback. Throws if the player is not ready. */\n async play(): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n this.userIntent = \"play\";\n this.autoPausedForVisibility = false;\n await this.session.play();\n }\n\n /** Pause playback. No-op if the player is not ready or already paused. */\n pause(): void {\n this.userIntent = \"pause\";\n this.autoPausedForVisibility = false;\n this.session?.pause();\n }\n\n /**\n * Handle browser tab visibility changes. On hide: pause if the user\n * had been playing. On show: resume if we were the one who paused.\n * Skips when `backgroundBehavior: \"continue\"` is set (listener isn't\n * installed in that case).\n */\n private onVisibilityChange(): void {\n if (!this.session) return;\n const action = decideVisibilityAction({\n hidden: document.hidden,\n userIntent: this.userIntent,\n sessionIsPlaying: !this.options.target.paused,\n autoPausedForVisibility: this.autoPausedForVisibility,\n });\n if (action === \"pause\") {\n this.autoPausedForVisibility = true;\n dbg.info(\"visibility\", \"tab hidden — auto-paused\");\n this.session.pause();\n } else if (action === \"resume\") {\n this.autoPausedForVisibility = false;\n dbg.info(\"visibility\", \"tab visible — auto-resuming\");\n void this.session.play().catch((err) => {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] auto-resume after tab return failed:\", err);\n });\n }\n }\n\n /** Seek to the given time in seconds. Throws if the player is not ready. */\n async seek(time: number): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n await this.session.seek(time);\n }\n\n /** Switch the active audio track by track ID. Throws if the player is not ready. */\n async setAudioTrack(id: number): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n await this.session.setAudioTrack(id);\n }\n\n /** Switch the active subtitle track by track ID, or pass `null` to disable subtitles. */\n async setSubtitleTrack(id: number | null): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n await this.session.setSubtitleTrack(id);\n }\n\n /** Return a snapshot of current diagnostics: container, codecs, strategy, runtime stats, and strategy history. */\n getDiagnostics(): DiagnosticsSnapshot {\n if (this.session) {\n this.diag.recordRuntime(this.session.getRuntimeStats());\n }\n return this.diag.snapshot();\n }\n\n /** Return the total duration in seconds, or `NaN` if unknown. */\n getDuration(): number {\n const fromDiag = this.diag.snapshot().duration;\n if (typeof fromDiag === \"number\" && Number.isFinite(fromDiag)) return fromDiag;\n const fromVideo = this.options.target.duration;\n return Number.isFinite(fromVideo) ? fromVideo : NaN;\n }\n\n /** Return the current playback position in seconds. */\n getCurrentTime(): number {\n return this.session?.getCurrentTime() ?? this.options.target.currentTime ?? 0;\n }\n\n /** Tear down the player: stop timers, destroy the active session, remove all event listeners. The player is unusable after this call. */\n async destroy(): Promise<void> {\n if (this.timeupdateInterval) {\n clearInterval(this.timeupdateInterval);\n this.timeupdateInterval = null;\n }\n this.clearSupervisor();\n if (this.endedListener) {\n this.options.target.removeEventListener(\"ended\", this.endedListener);\n this.endedListener = null;\n }\n if (this.visibilityListener) {\n document.removeEventListener(\"visibilitychange\", this.visibilityListener);\n this.visibilityListener = null;\n }\n if (this.session) {\n await this.session.destroy();\n this.session = null;\n }\n // Revoke every blob URL we created for sidecar discovery / SRT->VTT\n // conversion. This is the cleanup leg of the leak fix.\n this.subtitleResources.revokeAll();\n this.emitter.removeAll();\n }\n}\n\nexport async function createPlayer(options: CreatePlayerOptions): Promise<UnifiedPlayer> {\n return UnifiedPlayer.create(options);\n}\n\n/**\n * Pure decision function for visibility-change handling. Separated from\n * the class method so it can be unit-tested without a full player\n * instance.\n *\n * @internal — exported for unit tests; not part of the public API.\n */\nexport function decideVisibilityAction(state: {\n hidden: boolean;\n userIntent: \"play\" | \"pause\";\n sessionIsPlaying: boolean;\n autoPausedForVisibility: boolean;\n}): \"pause\" | \"resume\" | \"noop\" {\n if (state.hidden) {\n // Tab hidden: pause if user had been playing and session is active\n if (state.userIntent === \"play\" && state.sessionIsPlaying) return \"pause\";\n return \"noop\";\n }\n // Tab visible: resume only if we're the one who paused\n if (state.autoPausedForVisibility) return \"resume\";\n return \"noop\";\n}\n\n/**\n * Build a synthetic classification for an explicit `initialStrategy` override.\n * The `class` is derived from the chosen strategy so diagnostics and any\n * downstream consumer of `strategyClass` see the real strategy. The fallback\n * chain is inherited from the natural classification but must never contain\n * `initial` itself — otherwise `startSession` would retry the strategy that\n * just failed before escalating.\n *\n * @internal — exported for unit tests; not part of the public API.\n */\nexport function buildInitialDecision(\n initial: StrategyName,\n ctx: MediaContext,\n): Classification {\n const natural = classify(ctx);\n const cls = strategyToClass(initial, natural);\n const inherited = natural.fallbackChain ?? defaultFallbackChain(initial);\n const fallbackChain = inherited.filter((s) => s !== initial);\n return {\n class: cls,\n strategy: initial,\n reason: `initial strategy \"${initial}\" requested via options.initialStrategy`,\n fallbackChain,\n };\n}\n\nfunction strategyToClass(\n strategy: StrategyName,\n natural: Classification,\n): Classification[\"class\"] {\n // If the natural classification picked the same strategy, use its class.\n if (natural.strategy === strategy) return natural.class;\n switch (strategy) {\n case \"native\": return \"NATIVE\";\n case \"remux\": return \"REMUX_CANDIDATE\";\n case \"hybrid\": return \"HYBRID_CANDIDATE\";\n case \"fallback\": return \"FALLBACK_REQUIRED\";\n }\n}\n\nfunction defaultFallbackChain(strategy: StrategyName): StrategyName[] {\n switch (strategy) {\n case \"native\": return [\"remux\", \"hybrid\", \"fallback\"];\n case \"remux\": return [\"hybrid\", \"fallback\"];\n case \"hybrid\": return [\"fallback\"];\n case \"fallback\": return [];\n }\n}\n","/**\n * `<avbridge-video>` — `HTMLMediaElement`-compatible primitive backed by the\n * avbridge engine. Drop-in replacement for a `<video>` element with no\n * built-in UI.\n *\n * Purpose:\n *\n * 1. Validate the public API by being a real consumer of `createPlayer()`.\n * 2. Drive lifecycle correctness in the core via adversarial integration tests.\n * 3. Give consumers a `<video>`-compatible primitive they can wrap with\n * their own UI.\n *\n * **It is not a player UI framework.** For YouTube-style chrome (seek\n * bar, play/pause, settings menu, fullscreen, auto-hiding controls) use\n * `<avbridge-player>` — it wraps this element with a full UI. See\n * `docs/dev/WEB_COMPONENT_SPEC.md` for the full spec, lifecycle invariants,\n * and edge case list.\n */\n\nimport { createPlayer, type UnifiedPlayer } from \"../player.js\";\nimport type {\n MediaInput,\n StrategyName,\n StrategyClass,\n AudioTrackInfo,\n SubtitleTrackInfo,\n DiagnosticsSnapshot,\n AvbridgeVideoElementEventMap,\n} from \"../types.js\";\n\n/** Strategy preference passed via the `preferstrategy` attribute. */\ntype PreferredStrategy = \"auto\" | StrategyName;\n\nconst PREFERRED_STRATEGY_VALUES = new Set<PreferredStrategy>([\n \"auto\",\n \"native\",\n \"remux\",\n \"hybrid\",\n \"fallback\",\n]);\n\n/** Fit mode — how the video fills the element's box. Mirrors CSS object-fit. */\ntype FitMode = \"contain\" | \"cover\" | \"fill\";\nconst FIT_VALUES = new Set<FitMode>([\"contain\", \"cover\", \"fill\"]);\nconst DEFAULT_FIT: FitMode = \"contain\";\n\n/**\n * Standard `HTMLMediaElement` events we forward from the inner `<video>`\n * to the wrapper element so consumers can `el.addEventListener(\"loadedmetadata\", ...)`\n * exactly like they would with a real `<video>`. The element also dispatches\n * its own custom events (`strategychange`, `ready`, `error`, etc.) — those\n * are NOT in this list because they're avbridge-specific.\n *\n * Note: `progress` and `timeupdate` are deliberately NOT forwarded here.\n * `progress` is dispatched by the constructor with our own `{ buffered }`\n * detail. `timeupdate` is dispatched by the player layer (so it works for\n * canvas-rendered fallback playback too, where the inner <video> never\n * fires its own timeupdate).\n */\nconst FORWARDED_VIDEO_EVENTS = [\n \"loadstart\",\n \"loadedmetadata\",\n \"loadeddata\",\n \"canplay\",\n \"canplaythrough\",\n \"play\",\n \"playing\",\n \"pause\",\n \"seeking\",\n \"seeked\",\n \"volumechange\",\n \"ratechange\",\n \"durationchange\",\n \"waiting\",\n \"stalled\",\n \"emptied\",\n \"resize\",\n \"error\",\n] as const;\n\n/**\n * `HTMLElement` is a browser-only global. SSR frameworks (Next.js, Astro,\n * Remix, etc.) commonly import library modules on the server to extract\n * types or do tree-shaking, even if the user only ends up using them in\n * the browser. If we extended `HTMLElement` directly, the `class extends`\n * expression would be evaluated at module load time and crash in Node.\n *\n * The fix: in non-browser environments, fall back to an empty stub class.\n * The element is never *constructed* server-side (the registration in\n * `element.ts` is guarded by `typeof customElements !== \"undefined\"`), so\n * the stub is never instantiated — it just lets the class declaration\n * evaluate cleanly so the module can be imported anywhere.\n */\nconst HTMLElementCtor: typeof HTMLElement =\n typeof HTMLElement !== \"undefined\"\n ? HTMLElement\n : (class {} as unknown as typeof HTMLElement);\n\n/**\n * Custom element. Lifecycle correctness is enforced via a monotonically\n * increasing `_bootstrapId`: every async bootstrap captures the ID at start\n * and discards itself if the ID has changed by the time it resolves. This\n * single pattern handles disconnect-during-bootstrap, rapid src reassignment,\n * bootstrap races, and destroy-during-bootstrap.\n */\nexport class AvbridgeVideoElement extends HTMLElementCtor {\n static readonly observedAttributes = [\n \"src\",\n \"autoplay\",\n \"muted\",\n \"loop\",\n \"preload\",\n \"poster\",\n \"playsinline\",\n \"crossorigin\",\n \"disableremoteplayback\",\n \"diagnostics\",\n \"preferstrategy\",\n \"fit\",\n \"no-orientation-lock\",\n ];\n\n // ── Internal state ─────────────────────────────────────────────────────\n\n /** The shadow DOM `<video>` element that strategies render into. */\n private _videoEl!: HTMLVideoElement;\n\n /** Active player session, if any. Cleared on teardown. */\n private _player: UnifiedPlayer | null = null;\n\n /**\n * Monotonic counter incremented on every (re)bootstrap. Async bootstrap\n * work captures the current ID; if it doesn't match by the time the work\n * resolves, the work is discarded.\n */\n private _bootstrapId = 0;\n\n /** True after destroy() — element is permanently unusable. */\n private _destroyed = false;\n\n /** Internal source state. Either string-form (src) OR rich (source). */\n private _src: string | null = null;\n private _source: MediaInput | null = null;\n\n /**\n * Set when the `source` property setter is in the middle of clearing the\n * `src` attribute as part of mutual exclusion. The attributeChangedCallback\n * checks this flag and skips its normal \"clear source\" side effect, which\n * would otherwise wipe the value we just set.\n */\n private _suppressSrcAttrCallback = false;\n\n /** Last-known runtime state surfaced via getters. */\n private _strategy: StrategyName | null = null;\n private _strategyClass: StrategyClass | null = null;\n private _audioTracks: AudioTrackInfo[] = [];\n /** Subtitle tracks reported by the active UnifiedPlayer (options.subtitles\n * + embedded container tracks + programmatic addSubtitle calls). */\n private _subtitleTracks: SubtitleTrackInfo[] = [];\n /** Subtitle tracks derived from light-DOM `<track>` children. Maintained\n * by _syncTextTracks on every mutation. Merged into the public\n * `subtitleTracks` getter so the player's settings menu sees them. */\n private _htmlTrackInfo: SubtitleTrackInfo[] = [];\n\n /**\n * External subtitle list forwarded to `createPlayer()` on the next\n * bootstrap. Setting this after bootstrap queues it for the next\n * source change; consumers that need to swap subtitles mid-playback\n * should set `source` to reload.\n */\n private _subtitles: Array<{ url: string; language?: string; format?: \"vtt\" | \"srt\" }> | null = null;\n\n /**\n * Initial strategy preference. `\"auto\"` means \"let the classifier decide\";\n * any other value is passed to `createPlayer({ initialStrategy })` and\n * skips classification on the next bootstrap. Note that this only affects\n * the *initial* pick — runtime fallback escalation still applies, so a\n * preference of `\"native\"` may still escalate to remux/hybrid/fallback if\n * native fails.\n */\n private _preferredStrategy: PreferredStrategy = \"auto\";\n\n /** Current fit mode. Applied to the inner `<video>` via object-fit, and\n * to the fallback canvas via the `--avbridge-fit` CSS custom property on\n * the stage wrapper (see `src/strategies/fallback/video-renderer.ts`). */\n private _fit: FitMode = DEFAULT_FIT;\n /** The stage wrapper — the element the canvas attaches into, and where\n * the `--avbridge-fit` CSS custom property lives. */\n private _stageEl!: HTMLDivElement;\n\n /** Set if currentTime was assigned before the player was ready. */\n private _pendingSeek: number | null = null;\n /** Set if play() was called before the player was ready. */\n private _pendingPlay = false;\n\n /** MutationObserver tracking light-DOM `<track>` children. */\n private _trackObserver: MutationObserver | null = null;\n\n /** Document-level fullscreenchange handler — installed while connected so\n * the element can lock/unlock screen orientation to match the video's\n * intrinsic aspect. */\n private _fullscreenChangeHandler: (() => void) | null = null;\n /** True if we successfully called screen.orientation.lock() on the last\n * fullscreen entry. Used to know whether to unlock on exit. */\n private _orientationLocked = false;\n\n // ── Construction & lifecycle ───────────────────────────────────────────\n\n constructor() {\n super();\n const root = this.attachShadow({ mode: \"open\" });\n\n // A positioned wrapper inside the shadow root. The fallback strategy\n // overlays a canvas on top of the <video> via `target.parentNode` —\n // that only works if the parent is a real Element with layout. Without\n // this wrapper, `target.parentElement` would be null (ShadowRoot is\n // not an Element) and the canvas would never attach to the DOM.\n const stage = document.createElement(\"div\");\n stage.setAttribute(\"part\", \"stage\");\n stage.style.cssText = `position:relative;width:100%;height:100%;display:block;--avbridge-fit:${DEFAULT_FIT};`;\n root.appendChild(stage);\n this._stageEl = stage;\n\n this._videoEl = document.createElement(\"video\");\n this._videoEl.setAttribute(\"part\", \"video\");\n this._videoEl.style.cssText = `width:100%;height:100%;display:block;background:#000;object-fit:var(--avbridge-fit, ${DEFAULT_FIT});`;\n this._videoEl.playsInline = true;\n stage.appendChild(this._videoEl);\n\n // Forward the underlying <video>'s `progress` event so consumers can\n // observe buffered-range updates without reaching into the shadow DOM.\n // This works for native + remux (real video element with buffered\n // ranges) and is a no-op for hybrid/fallback (canvas-rendered, no\n // buffered ranges yet).\n this._videoEl.addEventListener(\"progress\", () => {\n if (this._destroyed) return;\n this._dispatch(\"progress\", { buffered: this._videoEl.buffered });\n });\n\n // Forward all standard HTMLMediaElement events from the inner <video>\n // so consumers can use the element as a drop-in <video> replacement.\n // Each event is re-dispatched on the wrapper element with no detail —\n // listeners that need state should read it from the element directly.\n for (const eventName of FORWARDED_VIDEO_EVENTS) {\n this._videoEl.addEventListener(eventName, () => {\n if (this._destroyed) return;\n this.dispatchEvent(new Event(eventName, { bubbles: false }));\n });\n }\n }\n\n connectedCallback(): void {\n if (this._destroyed) return;\n // Pick up any <track> children that were declared in HTML before the\n // element upgraded, and watch for future additions/removals.\n this._syncTextTracks();\n if (!this._trackObserver) {\n this._trackObserver = new MutationObserver(() => this._syncTextTracks());\n this._trackObserver.observe(this, { childList: true, subtree: false });\n }\n if (!this._fullscreenChangeHandler) {\n this._fullscreenChangeHandler = () => this._onFullscreenChange();\n document.addEventListener(\"fullscreenchange\", this._fullscreenChangeHandler);\n }\n // Connection is the trigger for bootstrap. If we have a pending source\n // (set before connect), kick off bootstrap now.\n const source = this._activeSource();\n if (source != null) {\n void this._bootstrap(source);\n }\n }\n\n disconnectedCallback(): void {\n if (this._destroyed) return;\n if (this._trackObserver) {\n this._trackObserver.disconnect();\n this._trackObserver = null;\n }\n if (this._fullscreenChangeHandler) {\n document.removeEventListener(\"fullscreenchange\", this._fullscreenChangeHandler);\n this._fullscreenChangeHandler = null;\n }\n // If we were fullscreen via some ancestor and got disconnected, release\n // any orientation lock we had taken.\n this._releaseOrientationLock();\n // Bump the bootstrap token so any in-flight async work is invalidated\n // before we tear down. _teardown() also bumps but we want the bump to\n // happen synchronously here so any awaited promise that resolves\n // between `disconnect` and `_teardown` sees the new ID.\n this._bootstrapId++;\n void this._teardown();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (this._destroyed) return;\n switch (name) {\n case \"src\":\n if (this._suppressSrcAttrCallback) break;\n this._setSrcInternal(newValue);\n break;\n case \"autoplay\":\n case \"muted\":\n case \"loop\":\n case \"playsinline\":\n case \"disableremoteplayback\":\n // Reflect onto the underlying <video> element.\n if (newValue == null) this._videoEl.removeAttribute(name);\n else this._videoEl.setAttribute(name, newValue);\n break;\n case \"preload\":\n case \"poster\":\n case \"crossorigin\":\n if (newValue == null) this._videoEl.removeAttribute(name);\n else this._videoEl.setAttribute(name, newValue);\n break;\n case \"diagnostics\":\n // Phase A: no UI. Property is observable for users via getDiagnostics().\n break;\n case \"preferstrategy\":\n if (newValue && PREFERRED_STRATEGY_VALUES.has(newValue as PreferredStrategy)) {\n this._preferredStrategy = newValue as PreferredStrategy;\n } else {\n this._preferredStrategy = \"auto\";\n }\n break;\n case \"fit\": {\n const next: FitMode = newValue && FIT_VALUES.has(newValue as FitMode)\n ? (newValue as FitMode)\n : DEFAULT_FIT;\n if (next === this._fit) break;\n this._fit = next;\n this._stageEl.style.setProperty(\"--avbridge-fit\", next);\n this._dispatch(\"fitchange\", { fit: next });\n break;\n }\n }\n }\n\n // ── Source handling ────────────────────────────────────────────────────\n\n /** Returns the currently-active source (src or source), whichever is set. */\n private _activeSource(): MediaInput | null {\n if (this._source != null) return this._source;\n if (this._src != null) return this._src;\n return null;\n }\n\n /**\n * Mirror light-DOM `<track>` children into the shadow `<video>` so that\n * the browser's native text-track machinery picks them up. Called on\n * connect, on every mutation of light-DOM children, and once after each\n * source change so newly-set tracks survive a fresh `<video>`.\n *\n * Strategy: clone the children. We don't move them because the user's\n * code may still hold references to the originals (e.g. to set `default`).\n * The shadow copies are throwaway — we wipe them on every sync.\n */\n private _syncTextTracks(): void {\n // Remove existing shadow tracks.\n const existing = this._videoEl.querySelectorAll(\"track\");\n for (const t of Array.from(existing)) t.remove();\n // Clone every <track> light-DOM child into the shadow video, and\n // rebuild the HTML-derived subtitle info list so the `<avbridge-player>`\n // settings menu can render them alongside options-sourced tracks.\n // HTML tracks are assigned high, stable IDs (10000+index) to avoid\n // colliding with container-embedded ids (typically < 32).\n this._htmlTrackInfo = [];\n let htmlIdx = 0;\n for (const child of Array.from(this.children)) {\n if (child.tagName === \"TRACK\") {\n const track = child as HTMLTrackElement;\n const clone = track.cloneNode(true) as HTMLTrackElement;\n this._videoEl.appendChild(clone);\n const src = track.getAttribute(\"src\") ?? undefined;\n const format = src?.toLowerCase().endsWith(\".srt\") ? \"srt\" : \"vtt\";\n this._htmlTrackInfo.push({\n id: 10000 + htmlIdx,\n format,\n language: track.srclang || track.getAttribute(\"label\") || undefined,\n sidecarUrl: src,\n });\n htmlIdx++;\n }\n }\n this._dispatch(\"trackschange\", {\n audioTracks: this._audioTracks,\n subtitleTracks: this.subtitleTracks,\n });\n }\n\n /** Internal src setter — separate from the property setter so the\n * attributeChangedCallback can use it without re-entering reflection. */\n private _setSrcInternal(value: string | null): void {\n // Same-value reassignment: no-op (#11 in the lifecycle list).\n if (value === this._src && this._source == null) return;\n this._src = value;\n this._source = null;\n this._onSourceChanged();\n }\n\n /** Called whenever the active source changes (src or source). */\n private _onSourceChanged(): void {\n if (this._destroyed) return;\n const source = this._activeSource();\n if (source == null) {\n // Null transition: tear down and stay idle.\n this._bootstrapId++;\n void this._teardown();\n return;\n }\n // Only bootstrap if we're connected to the DOM.\n if (this.isConnected) {\n void this._bootstrap(source);\n }\n }\n\n // ── Bootstrap (the only place a UnifiedPlayer is created) ──────────────\n\n private async _bootstrap(source: MediaInput): Promise<void> {\n if (this._destroyed) return;\n const id = ++this._bootstrapId;\n\n // Tear down any existing player before starting a new one. Pass the\n // bootstrap id we just claimed so teardown doesn't bump it again\n // (which would invalidate ourselves).\n await this._teardown(id);\n if (id !== this._bootstrapId || this._destroyed) return;\n\n this._dispatch(\"loadstart\", {});\n\n let player: UnifiedPlayer;\n try {\n player = await createPlayer({\n source,\n target: this._videoEl,\n // Honor the consumer's preferred initial strategy. \"auto\" means\n // \"let the classifier decide\" — the createPlayer call simply doesn't\n // pass initialStrategy in that case.\n ...(this._preferredStrategy !== \"auto\"\n ? { initialStrategy: this._preferredStrategy }\n : {}),\n ...(this._subtitles ? { subtitles: this._subtitles } : {}),\n });\n } catch (err) {\n // Stale or destroyed — silently abandon.\n if (id !== this._bootstrapId || this._destroyed) return;\n this._dispatchError(err);\n return;\n }\n\n // Race check: if anything happened during the await above, bail.\n if (id !== this._bootstrapId || this._destroyed || !this.isConnected) {\n try { await player.destroy(); } catch { /* ignore */ }\n return;\n }\n\n this._player = player;\n\n // Resync any light-DOM <track> children into the (possibly fresh) shadow\n // <video>. Strategies that swap or reset the inner video state would\n // otherwise lose the tracks the user declared in HTML.\n this._syncTextTracks();\n\n // Wire events. The unsubscribe handles are not stored individually\n // because destroy() will tear down the whole session anyway.\n player.on(\"strategy\", ({ strategy, reason }) => {\n // strategy event fires on initial classification AND any escalation.\n const cls = player.getDiagnostics().strategyClass;\n this._strategy = strategy;\n this._strategyClass = cls === \"pending\" ? null : cls;\n this._dispatch(\"strategychange\", {\n strategy,\n strategyClass: this._strategyClass,\n reason,\n diagnostics: player.getDiagnostics(),\n });\n });\n\n player.on(\"strategychange\", ({ from, to, reason, currentTime }) => {\n this._dispatch(\"strategychange\", {\n from,\n strategy: to,\n strategyClass: player.getDiagnostics().strategyClass === \"pending\" ? null : player.getDiagnostics().strategyClass,\n reason,\n currentTime,\n diagnostics: player.getDiagnostics(),\n });\n });\n\n player.on(\"tracks\", ({ video: _v, audio, subtitle }) => {\n this._audioTracks = audio;\n this._subtitleTracks = subtitle;\n this._dispatch(\"trackschange\", {\n audioTracks: audio,\n subtitleTracks: subtitle,\n });\n });\n\n player.on(\"error\", (err: Error) => {\n this._dispatchError(err);\n });\n\n player.on(\"timeupdate\", ({ currentTime }) => {\n this._dispatch(\"timeupdate\", { currentTime });\n });\n\n player.on(\"ended\", () => {\n this._dispatch(\"ended\", {});\n });\n\n player.on(\"ready\", () => {\n this._dispatch(\"ready\", { diagnostics: player.getDiagnostics() });\n // Apply any pending seek that was set before the player existed.\n if (this._pendingSeek != null) {\n const t = this._pendingSeek;\n this._pendingSeek = null;\n void player.seek(t).catch(() => { /* ignore */ });\n }\n // Honor any pending play() that was queued before bootstrap finished.\n if (this._pendingPlay) {\n this._pendingPlay = false;\n void player.play().catch(() => { /* ignore — autoplay may be blocked */ });\n } else if (this.autoplay) {\n void player.play().catch(() => { /* ignore */ });\n }\n });\n }\n\n /**\n * Tear down the active player and reset runtime state. Idempotent.\n * If `currentBootstrapId` is provided, the bootstrap counter is NOT\n * incremented (used by `_bootstrap()` to avoid invalidating itself).\n */\n private async _teardown(currentBootstrapId?: number): Promise<void> {\n if (currentBootstrapId == null) {\n // External callers (disconnect, destroy, source change) should bump\n // the counter so any in-flight bootstrap is invalidated. The internal\n // _bootstrap() call passes its own ID and we skip the bump.\n this._bootstrapId++;\n }\n const player = this._player;\n this._player = null;\n this._strategy = null;\n this._strategyClass = null;\n this._audioTracks = [];\n this._subtitleTracks = [];\n if (player) {\n try { await player.destroy(); } catch { /* ignore */ }\n }\n }\n\n // ── Public properties ──────────────────────────────────────────────────\n\n get src(): string | null {\n return this._src;\n }\n\n set src(value: string | null) {\n if (value == null) {\n this.removeAttribute(\"src\");\n } else {\n this.setAttribute(\"src\", value);\n }\n // attributeChangedCallback handles the rest.\n }\n\n get source(): MediaInput | null {\n return this._source;\n }\n\n set source(value: MediaInput | null) {\n // Same-value reassignment for rich values is identity-based.\n if (value === this._source && this._src == null) return;\n this._source = value;\n if (value != null) {\n // Setting source clears src. Suppress the attribute callback so\n // removing the src attribute doesn't wipe the source we just set.\n this._src = null;\n if (this.hasAttribute(\"src\")) {\n this._suppressSrcAttrCallback = true;\n try {\n this.removeAttribute(\"src\");\n } finally {\n this._suppressSrcAttrCallback = false;\n }\n }\n }\n this._onSourceChanged();\n }\n\n get autoplay(): boolean {\n return this.hasAttribute(\"autoplay\");\n }\n\n set autoplay(value: boolean) {\n if (value) this.setAttribute(\"autoplay\", \"\");\n else this.removeAttribute(\"autoplay\");\n }\n\n get muted(): boolean {\n // Read through to the inner <video>'s IDL property — on canvas\n // strategies the property is patched via Object.defineProperty to\n // mirror AudioOutput state, and consumers need the truthful value.\n return this._videoEl.muted;\n }\n\n set muted(value: boolean) {\n // Drive the IDL property (fires volumechange per HTML spec) rather\n // than toggling the attribute (which on most browsers is parse-time\n // only and does NOT fire volumechange when toggled runtime). On\n // canvas strategies, the property is patched via Object.defineProperty\n // which also dispatches volumechange; one code path, both worlds.\n this._videoEl.muted = value;\n // Keep the attribute in sync so CSS selectors like [muted] and\n // re-queries via getAttribute reflect current state.\n if (value) this.setAttribute(\"muted\", \"\");\n else this.removeAttribute(\"muted\");\n }\n\n get loop(): boolean {\n return this.hasAttribute(\"loop\");\n }\n\n set loop(value: boolean) {\n if (value) this.setAttribute(\"loop\", \"\");\n else this.removeAttribute(\"loop\");\n }\n\n get preload(): \"none\" | \"metadata\" | \"auto\" {\n const v = this.getAttribute(\"preload\");\n return v === \"none\" || v === \"metadata\" || v === \"auto\" ? v : \"auto\";\n }\n\n set preload(value: \"none\" | \"metadata\" | \"auto\") {\n this.setAttribute(\"preload\", value);\n }\n\n get diagnostics(): boolean {\n return this.hasAttribute(\"diagnostics\");\n }\n\n set diagnostics(value: boolean) {\n if (value) this.setAttribute(\"diagnostics\", \"\");\n else this.removeAttribute(\"diagnostics\");\n }\n\n get fit(): FitMode {\n return this._fit;\n }\n\n set fit(value: FitMode) {\n if (!FIT_VALUES.has(value)) return;\n this.setAttribute(\"fit\", value);\n }\n\n get preferredStrategy(): PreferredStrategy {\n return this._preferredStrategy;\n }\n\n set preferredStrategy(value: PreferredStrategy) {\n if (PREFERRED_STRATEGY_VALUES.has(value)) {\n this.setAttribute(\"preferstrategy\", value);\n }\n }\n\n get currentTime(): number {\n return this._player?.getCurrentTime() ?? 0;\n }\n\n set currentTime(value: number) {\n if (this._player) {\n void this._player.seek(value).catch(() => { /* ignore */ });\n } else {\n // Defer to the next bootstrap. The `ready` handler applies it.\n this._pendingSeek = value;\n }\n }\n\n get duration(): number {\n return this._player?.getDuration() ?? NaN;\n }\n\n get paused(): boolean {\n return this._videoEl.paused;\n }\n\n get ended(): boolean {\n return this._videoEl.ended;\n }\n\n get readyState(): number {\n return this._videoEl.readyState;\n }\n\n /**\n * Buffered time ranges for the active source. Mirrors the standard\n * `<video>.buffered` `TimeRanges` API.\n *\n * - **Native / remux:** pass-through to the real `<video>.buffered`\n * (reflects the browser's SourceBuffer / progressive-download state).\n * - **Hybrid / fallback:** a single `[0, frontier]` range synthesized\n * from the demuxer's read progress — \"how far libav has ever pumped\n * packets through.\" Monotonic; does not shrink on seek. This is an\n * approximation, not MSE-fidelity: decoded frames on canvas strategies\n * are consumed in flight, so we can't report per-range availability\n * the way MSE does. Enough for a seek-bar buffered indicator.\n */\n get buffered(): TimeRanges {\n return this._videoEl.buffered;\n }\n\n // ── HTMLMediaElement parity ───────────────────────────────────────────\n // Mirror the standard <video> surface so consumers can drop the element\n // in as a <video> replacement. Each property is a thin passthrough to the\n // shadow `<video>`.\n\n get poster(): string {\n return this._videoEl.poster;\n }\n set poster(value: string) {\n if (value == null || value === \"\") this.removeAttribute(\"poster\");\n else this.setAttribute(\"poster\", value);\n }\n\n get volume(): number {\n return this._videoEl.volume;\n }\n set volume(value: number) {\n this._videoEl.volume = value;\n }\n\n get playbackRate(): number {\n return this._videoEl.playbackRate;\n }\n set playbackRate(value: number) {\n this._videoEl.playbackRate = value;\n }\n\n get videoWidth(): number {\n return this._videoEl.videoWidth;\n }\n\n get videoHeight(): number {\n return this._videoEl.videoHeight;\n }\n\n get played(): TimeRanges {\n return this._videoEl.played;\n }\n\n get seekable(): TimeRanges {\n return this._videoEl.seekable;\n }\n\n get crossOrigin(): string | null {\n return this._videoEl.crossOrigin;\n }\n set crossOrigin(value: string | null) {\n if (value == null) this.removeAttribute(\"crossorigin\");\n else this.setAttribute(\"crossorigin\", value);\n }\n\n get disableRemotePlayback(): boolean {\n return this._videoEl.disableRemotePlayback;\n }\n set disableRemotePlayback(value: boolean) {\n if (value) this.setAttribute(\"disableremoteplayback\", \"\");\n else this.removeAttribute(\"disableremoteplayback\");\n }\n\n /**\n * Native `HTMLMediaElement.canPlayType()` passthrough. Note that this\n * answers about the *browser's* native support, not avbridge's full\n * capabilities — avbridge can play many formats this method returns \"\"\n * for, by routing them to the remux/hybrid/fallback strategies.\n */\n canPlayType(mimeType: string): CanPlayTypeResult {\n return this._videoEl.canPlayType(mimeType);\n }\n\n /**\n * **Escape hatch.** The underlying shadow-DOM `<video>` element.\n *\n * Use for native browser APIs the wrapper doesn't expose:\n * - `el.videoElement.requestPictureInPicture()`\n * - `el.videoElement.audioTracks` (browser native, not avbridge's track list)\n * - direct integration with libraries that need a real HTMLVideoElement\n *\n * **Caveat:** When the active strategy is `\"fallback\"` or `\"hybrid\"`,\n * frames are rendered to a canvas overlay, not into this `<video>`.\n * APIs that depend on the actual pixels (Picture-in-Picture, captureStream)\n * will not show the playing content in those modes. Check `el.strategy`\n * before using such APIs.\n */\n get videoElement(): HTMLVideoElement {\n return this._videoEl;\n }\n\n get strategy(): StrategyName | null {\n return this._strategy;\n }\n\n get strategyClass(): StrategyClass | null {\n return this._strategyClass;\n }\n\n get player(): UnifiedPlayer | null {\n return this._player;\n }\n\n get audioTracks(): AudioTrackInfo[] {\n return this._audioTracks;\n }\n\n get subtitleTracks(): SubtitleTrackInfo[] {\n // Merge player-sourced tracks with light-DOM `<track>` children.\n // Both sources coexist: options.subtitles + embedded-in-container\n // tracks contribute to _subtitleTracks; HTML `<track>` children\n // contribute _htmlTrackInfo with ids in the 10000+ range.\n return this._htmlTrackInfo.length === 0\n ? this._subtitleTracks\n : [...this._subtitleTracks, ...this._htmlTrackInfo];\n }\n\n /**\n * External subtitle files to attach when the source loads. Takes effect\n * on the next bootstrap — set before assigning `source`, or reload via\n * `load()` after changing. For dynamic post-bootstrap addition, use\n * `addSubtitle()` instead.\n *\n * @example\n * el.subtitles = [{ url: \"/en.srt\", format: \"srt\", language: \"en\" }];\n * el.src = \"/movie.mp4\";\n */\n get subtitles(): Array<{ url: string; language?: string; format?: \"vtt\" | \"srt\" }> | null {\n return this._subtitles;\n }\n\n set subtitles(value: Array<{ url: string; language?: string; format?: \"vtt\" | \"srt\" }> | null) {\n this._subtitles = value;\n }\n\n /**\n * Attach a subtitle track to the current playback without rebuilding\n * the player. Works while the element is playing — converts SRT to\n * VTT if needed, adds a `<track>` to the inner `<video>`. Canvas\n * strategies pick up the new track via their textTracks watcher.\n */\n async addSubtitle(subtitle: { url: string; language?: string; format?: \"vtt\" | \"srt\" }): Promise<void> {\n const { attachSubtitleTracks } = await import(\"../subtitles/index.js\");\n const format = subtitle.format ?? (subtitle.url.endsWith(\".srt\") ? \"srt\" : \"vtt\");\n const track = {\n id: this._subtitleTracks.length,\n format,\n language: subtitle.language,\n sidecarUrl: subtitle.url,\n };\n this._subtitleTracks.push(track);\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] addSubtitle id=${track.id} format=${format} lang=${subtitle.language ?? \"?\"}`);\n await attachSubtitleTracks(\n this._videoEl,\n this._subtitleTracks,\n undefined,\n (err, t) => {\n // eslint-disable-next-line no-console\n console.warn(`[avbridge:subs] subtitle ${t.id} failed: ${err.message}`);\n },\n );\n // Enable the newly-added track so it renders immediately. On native\n // strategy the <video>'s textTrack must be mode=\"showing\"; on canvas\n // strategies the renderer's watchTextTracks picks it up from the\n // hidden-mode textTracks.\n const textTracks = this._videoEl.textTracks;\n for (let i = 0; i < textTracks.length; i++) {\n if (textTracks[i].label === (subtitle.language ?? `Subtitle ${track.id}`)) {\n textTracks[i].mode = \"showing\";\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] enabled textTrack[${i}] mode=showing`);\n break;\n }\n }\n // Notify the settings sheet so it rebuilds with the new track.\n this._dispatch(\"trackschange\", {\n audioTracks: this._audioTracks,\n subtitleTracks: this.subtitleTracks,\n });\n }\n\n /**\n * Disable the automatic `screen.orientation.lock()` that runs on\n * fullscreen entry. Set when you want to honor the device's native\n * auto-rotate instead of matching the video's intrinsic orientation.\n */\n get noOrientationLock(): boolean {\n return this.hasAttribute(\"no-orientation-lock\");\n }\n\n set noOrientationLock(value: boolean) {\n if (value) this.setAttribute(\"no-orientation-lock\", \"\");\n else this.removeAttribute(\"no-orientation-lock\");\n }\n\n // ── Fullscreen orientation lock ────────────────────────────────────────\n\n /** Called whenever `document.fullscreenchange` fires. If this element (or\n * any of its ancestors) is now fullscreen, derive the target orientation\n * from the video's intrinsic size and call `screen.orientation.lock()`.\n * On exit, release the lock we took. iOS Safari rejects `lock()` — we\n * swallow the rejection so nothing breaks on that path. */\n private _onFullscreenChange(): void {\n if (this._destroyed) return;\n const fsEl = document.fullscreenElement;\n const nowFullscreen = fsEl != null && this._isInsideOrEquals(fsEl);\n if (nowFullscreen && !this._orientationLocked) {\n if (this.noOrientationLock) return;\n const target = this._desiredOrientation();\n if (!target) return; // square or unknown — don't lock\n void this._lockOrientation(target);\n } else if (!nowFullscreen && this._orientationLocked) {\n this._releaseOrientationLock();\n }\n }\n\n /** Walk composed-tree ancestors to see if `target` is this element or\n * any ancestor across shadow boundaries. `Node.contains()` can't cross\n * shadow roots, so when `<avbridge-player>` (the fullscreen element)\n * hosts this `<avbridge-video>` inside its shadow DOM, `contains()`\n * returns false. */\n private _isInsideOrEquals(target: Element): boolean {\n let node: Node | null = this;\n while (node) {\n if (node === target) return true;\n const parent: Node | null = node.parentNode;\n if (parent instanceof ShadowRoot) node = parent.host;\n else node = parent;\n }\n return false;\n }\n\n /** Derive \"landscape\" / \"portrait\" from the intrinsic video dimensions.\n * Returns null when dimensions aren't known yet or the video is square.\n * Uses `videoWidth` / `videoHeight` from the inner `<video>`, which the\n * browser sets to the display-aspect-corrected size (so anamorphic\n * content is judged by its display aspect, not pixel aspect). */\n private _desiredOrientation(): \"landscape\" | \"portrait\" | null {\n const w = this._videoEl.videoWidth;\n const h = this._videoEl.videoHeight;\n if (!w || !h) return null;\n if (w === h) return null;\n return w > h ? \"landscape\" : \"portrait\";\n }\n\n /** Attempt to lock screen orientation. Swallows rejections — iOS Safari\n * doesn't implement `lock()`, and desktop / non-fullscreen contexts will\n * reject too. Records success so we know whether to unlock on exit. */\n private async _lockOrientation(target: \"landscape\" | \"portrait\"): Promise<void> {\n const so = (screen as Screen & {\n orientation?: ScreenOrientation & { lock?: (o: string) => Promise<void> };\n }).orientation;\n if (!so || typeof so.lock !== \"function\") return;\n try {\n await so.lock(target);\n this._orientationLocked = true;\n } catch {\n // iOS Safari, desktop, or user denied — ignore.\n }\n }\n\n private _releaseOrientationLock(): void {\n if (!this._orientationLocked) return;\n this._orientationLocked = false;\n const so = screen.orientation as ScreenOrientation | undefined;\n if (so && typeof so.unlock === \"function\") {\n try { so.unlock(); } catch { /* ignore */ }\n }\n }\n\n // ── Public methods ─────────────────────────────────────────────────────\n\n /** Force a (re-)bootstrap if a source is currently set. */\n async load(): Promise<void> {\n if (this._destroyed) return;\n const source = this._activeSource();\n if (source == null) return;\n await this._bootstrap(source);\n }\n\n /**\n * Begin or resume playback. If the player isn't ready yet, the call is\n * queued and applied once `ready` fires.\n */\n async play(): Promise<void> {\n if (this._destroyed) return;\n if (this._player) {\n await this._player.play();\n } else {\n this._pendingPlay = true;\n }\n }\n\n pause(): void {\n if (this._destroyed) return;\n this._pendingPlay = false;\n this._player?.pause();\n }\n\n /**\n * Tear down the element permanently. After destroy(), the element ignores\n * all method calls and attribute changes.\n */\n async destroy(): Promise<void> {\n if (this._destroyed) return;\n this._destroyed = true;\n await this._teardown();\n this._dispatch(\"destroy\", {});\n }\n\n async setAudioTrack(id: number): Promise<void> {\n if (this._destroyed || !this._player) return;\n await this._player.setAudioTrack(id);\n }\n\n async setSubtitleTrack(id: number | null): Promise<void> {\n if (this._destroyed || !this._player) return;\n await this._player.setSubtitleTrack(id);\n }\n\n getDiagnostics(): DiagnosticsSnapshot | null {\n return this._player?.getDiagnostics() ?? null;\n }\n\n // ── Typed addEventListener / removeEventListener overloads ────────────\n // Consumers using avbridge-specific events get a typed CustomEvent\n // payload; standard HTMLMediaElement events retain their native types.\n\n override addEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void {\n super.addEventListener(type, listener, options);\n }\n\n override removeEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void {\n super.removeEventListener(type, listener, options);\n }\n\n // ── Event helpers ──────────────────────────────────────────────────────\n\n private _dispatch<T>(name: string, detail: T): void {\n this.dispatchEvent(new CustomEvent(name, { detail, bubbles: false }));\n }\n\n private _dispatchError(err: unknown): void {\n const error = err instanceof Error ? err : new Error(String(err));\n this._dispatch(\"error\", { error, diagnostics: this._player?.getDiagnostics() ?? null });\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"avbridge-video\": AvbridgeVideoElement;\n }\n}\n","/**\n * Shadow DOM CSS for <avbridge-player>.\n * YouTube-inspired dark theme. All controls use ::part() for external styling.\n */\n\nexport const PLAYER_STYLES = /* css */ `\n:host {\n display: block;\n position: relative;\n width: 100%;\n background: #000;\n overflow: hidden;\n user-select: none;\n -webkit-user-select: none;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n color: #fff;\n line-height: 1;\n}\n\n:host(:fullscreen),\n:host(:fullscreen) .avp {\n width: 100vw;\n height: 100vh;\n}\n\n/* ── Container ────────────────────────────────────────────────────────── */\n\n:host {\n -webkit-tap-highlight-color: transparent;\n outline: none;\n}\n\n.avp {\n position: relative;\n width: 100%;\n height: 100%;\n -webkit-tap-highlight-color: transparent;\n user-select: none;\n}\n\n.avp avbridge-video {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n/* Drag-and-drop file target highlight. */\n.avp.avp-dragover::after {\n content: \"\";\n position: absolute;\n inset: 8px;\n border: 2px dashed rgba(255, 255, 255, 0.75);\n border-radius: 4px;\n background: rgba(0, 0, 0, 0.25);\n pointer-events: none;\n z-index: 10;\n}\n\n/* ── Center overlay ───────────────────────────────────────────────────── */\n\n.avp-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 2;\n}\n\n.avp-overlay-btn {\n width: 68px;\n height: 68px;\n border-radius: 50%;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n color: #fff;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: opacity 0.2s, transform 0.15s;\n opacity: 0;\n transform: scale(0.9);\n}\n\n.avp-overlay-btn svg {\n width: 36px;\n height: 36px;\n}\n\n.avp-overlay-btn:hover {\n background: rgba(0, 0, 0, 0.75);\n transform: scale(1);\n}\n\n:host([data-state=\"idle\"]) .avp-overlay-btn,\n:host([data-state=\"paused\"]) .avp-overlay-btn {\n opacity: 1;\n transform: scale(1);\n}\n\n/* ── Loading spinner ──────────────────────────────────────────────────── */\n\n.avp-spinner {\n width: 48px;\n height: 48px;\n border: 4px solid rgba(255, 255, 255, 0.3);\n border-top-color: #fff;\n border-radius: 50%;\n display: none;\n pointer-events: none;\n}\n\n:host([data-state=\"loading\"]) .avp-spinner,\n:host([data-state=\"buffering\"]) .avp-spinner {\n display: block;\n animation: avp-spin 0.8s linear infinite;\n}\n\n:host([data-state=\"loading\"]) .avp-overlay-btn,\n:host([data-state=\"buffering\"]) .avp-overlay-btn {\n display: none;\n}\n\n@keyframes avp-spin {\n to { transform: rotate(360deg); }\n}\n\n/* ── Double-tap ripple ────────────────────────────────────────────────── */\n\n.avp-ripple {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n width: 100px;\n height: 100px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n opacity: 0;\n z-index: 3;\n}\n\n.avp-ripple svg { width: 28px; height: 28px; }\n.avp-ripple-left { left: 15%; }\n.avp-ripple-right { right: 15%; }\n\n.avp-ripple.active {\n animation: avp-ripple 0.5s ease-out;\n}\n\n@keyframes avp-ripple {\n 0% { opacity: 1; transform: translateY(-50%) scale(0.5); }\n 100% { opacity: 0; transform: translateY(-50%) scale(1.5); }\n}\n\n/* ── Speed indicator (tap-and-hold) ───────────────────────────────────── */\n\n.avp-speed-indicator {\n position: absolute;\n top: 12px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.7);\n padding: 6px 16px;\n border-radius: 20px;\n font-size: 14px;\n font-weight: 600;\n pointer-events: none;\n opacity: 0;\n z-index: 4;\n transition: opacity 0.15s;\n}\n\n.avp-speed-indicator.active { opacity: 1; }\n\n/* ── Controls bar ─────────────────────────────────────────────────────── */\n\n.avp-controls {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 5;\n padding: 0 12px 8px;\n background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));\n display: flex;\n flex-direction: column;\n gap: 4px;\n opacity: 1;\n transition: opacity 0.25s;\n}\n\n:host([data-controls-hidden]) .avp-controls {\n opacity: 0;\n pointer-events: none;\n}\n\n:host([data-controls-hidden]) { cursor: none; }\n\n/* ── Top toolbar (slotted consumer chrome) ─────────────────────────────\n Two named slots (top-left, top-right) let consumers place back / title /\n translate buttons inside the auto-hide chrome. Wrapper has\n pointer-events:none so empty slots don't block container clicks; each\n side re-enables pointer-events so real buttons remain interactive. */\n\n.avp-toolbar-top {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 5;\n padding: 8px 12px 24px;\n background: linear-gradient(rgba(0, 0, 0, 0.6), transparent);\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n opacity: 1;\n pointer-events: none;\n transition: opacity 0.25s;\n}\n\n.avp-toolbar-top-left,\n.avp-toolbar-top-right {\n display: flex;\n align-items: center;\n gap: 8px;\n pointer-events: auto;\n}\n\n/* Left slot fills remaining space so slotted text/content can grow.\n min-width: 0 prevents flex children from overflowing the toolbar. */\n.avp-toolbar-top-left {\n flex: 1;\n min-width: 0;\n}\n\n.avp-toolbar-top-right { margin-left: auto; flex-shrink: 0; }\n\n/* Hide the gradient band when no consumer has slotted anything — we\n toggle data-toolbar-empty from JS via slotchange. */\n:host([data-toolbar-empty]) .avp-toolbar-top {\n background: none;\n}\n\n:host([data-controls-hidden]) .avp-toolbar-top {\n opacity: 0;\n pointer-events: none;\n}\n\n/* ── Content overlay ─────────────────────────────────────────────────── */\n/* Consumer-provided rich content (tweet cards, media info, annotations).\n Sits above the video, below the play-button overlay and controls in\n z-order. Auto-hides with the chrome. The wrapper is pointer-events:none\n so taps fall through to the video; consumers opt in on their content\n with pointer-events:auto. */\n\n.avp-content-overlay {\n position: absolute;\n inset: 0;\n z-index: 1;\n pointer-events: none;\n opacity: 1;\n transition: opacity 0.25s;\n}\n\n.avp-content-overlay ::slotted(*) {\n pointer-events: auto;\n}\n\n:host([data-controls-hidden]) .avp-content-overlay {\n opacity: 0;\n}\n\n/* ── Seek bar ─────────────────────────────────────────────────────────── */\n\n.avp-seek {\n position: relative;\n height: 20px;\n display: flex;\n align-items: center;\n cursor: pointer;\n /* Claim all touch gestures on the seek bar. Without this, Android\n * browsers (Chrome, Samsung Internet) treat horizontal drags as\n * scroll candidates and cancel pointermove once the gesture\n * resolves, breaking scrub. touch-action must be set in CSS —\n * preventDefault() on pointerdown is too late. */\n touch-action: none;\n}\n\n.avp-seek-track {\n position: absolute;\n left: 0;\n right: 0;\n height: 3px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n overflow: hidden;\n transition: height 0.1s;\n}\n\n.avp-seek:hover .avp-seek-track { height: 5px; }\n\n.avp-seek-buffered {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n.avp-seek-buffered-range {\n position: absolute;\n top: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.35);\n border-radius: inherit;\n}\n\n.avp-seek-progress {\n position: absolute;\n left: 0;\n height: 100%;\n background: #f00;\n border-radius: inherit;\n}\n\n.avp-seek-input {\n position: absolute;\n width: 100%;\n height: 100%;\n margin: 0;\n opacity: 0;\n /* Disable pointer events — we handle clicks/drags manually on .avp-seek\n * so the click position maps linearly across the full track width.\n * The input is still used for keyboard accessibility. */\n pointer-events: none;\n z-index: 1;\n}\n\n.avp-seek-thumb {\n position: absolute;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #f00;\n top: 50%;\n /* Thumb center follows the cursor exactly: left = pct% of track width,\n * then translate(-50%) centers the thumb on that point. Matches the\n * manual pointer-to-time mapping in _timeFromSeekPointer which is\n * also linear from 0% to 100% of the track width. */\n left: calc(var(--pct, 0) * 1%);\n transform: translate(-50%, -50%) scale(0);\n transition: transform 0.1s;\n pointer-events: none;\n}\n\n.avp-seek:hover .avp-seek-thumb { transform: translate(-50%, -50%) scale(1); }\n\n.avp-seek-tooltip {\n position: absolute;\n bottom: 24px;\n background: rgba(0, 0, 0, 0.8);\n padding: 4px 8px;\n border-radius: 3px;\n font-size: 12px;\n white-space: nowrap;\n transform: translateX(-50%);\n pointer-events: none;\n display: none;\n}\n\n.avp-seek:hover .avp-seek-tooltip { display: block; }\n\n/* Show tooltip during active drag (touch or mouse). The JS side sets\n data-seeking on .avp-seek while the user is scrubbing. */\n.avp-seek[data-seeking] .avp-seek-tooltip { display: block; }\n\n/* Enlarge thumb while scrubbing. */\n.avp-seek[data-seeking] .avp-seek-thumb {\n transform: translate(-50%, -50%) scale(1.4);\n}\n\n/* ── Bottom row ───────────────────────────────────────────────────────── */\n\n.avp-bottom {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 36px;\n}\n\n.avp-btn {\n background: none;\n border: none;\n color: #fff;\n padding: 4px;\n cursor: pointer;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.9;\n transition: opacity 0.1s;\n}\n\n.avp-btn:hover { opacity: 1; }\n.avp-btn svg { width: 24px; height: 24px; }\n\n/* ── Volume ───────────────────────────────────────────────────────────── */\n\n.avp-volume {\n display: flex;\n align-items: center;\n gap: 0;\n}\n\n.avp-volume-slider {\n width: 0;\n overflow: hidden;\n transition: width 0.15s;\n display: flex;\n align-items: center;\n /* Extra padding so the thumb isn't clipped at track edges */\n padding: 6px 0;\n margin: -6px 0;\n}\n\n.avp-volume:hover .avp-volume-slider { width: 68px; }\n\n.avp-volume-input {\n width: 60px;\n height: 4px;\n -webkit-appearance: none;\n appearance: none;\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n outline: none;\n cursor: pointer;\n /* Prevent thumb clipping — the thumb is taller than the track */\n overflow: visible;\n margin: 0;\n}\n\n.avp-volume-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #fff;\n cursor: pointer;\n}\n\n.avp-volume-input::-moz-range-thumb {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #fff;\n border: none;\n cursor: pointer;\n}\n\n/* ── Time display ─────────────────────────────────────────────────────── */\n\n.avp-time {\n font-size: 13px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n opacity: 0.9;\n}\n\n/* ── Strategy badge ───────────────────────────────────────────────────── */\n\n.avp-badge {\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 3px;\n background: rgba(255, 255, 255, 0.15);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n opacity: 0.8;\n}\n\n.avp-badge[data-strategy=\"native\"] { background: rgba(45, 106, 79, 0.7); }\n.avp-badge[data-strategy=\"remux\"] { background: rgba(30, 96, 145, 0.7); }\n.avp-badge[data-strategy=\"hybrid\"] { background: rgba(199, 125, 255, 0.4); }\n.avp-badge[data-strategy=\"fallback\"] { background: rgba(157, 78, 221, 0.5); }\n\n/* ── Spacer ───────────────────────────────────────────────────────────── */\n\n.avp-spacer { flex: 1; }\n\n/* ── Settings bottom sheet ────────────────────────────────────────────── */\n\n/* Scrim — semi-transparent overlay behind the sheet, above the video.\n Tapping it dismisses the sheet. */\n.avp-settings-scrim {\n position: absolute;\n inset: 0;\n z-index: 9;\n background: rgba(0, 0, 0, 0.4);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n}\n\n.avp-settings-scrim.open {\n opacity: 1;\n pointer-events: auto;\n}\n\n/* Sheet container — slides up from the bottom. Height is content-driven\n up to a JS-measured max (set on open via style.maxHeight). */\n.avp-settings {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 10;\n background: rgba(28, 28, 28, 0.97);\n border-radius: 12px 12px 0 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n transform: translateY(100%);\n transition: transform 0.2s ease-out;\n max-height: 70%;\n padding-bottom: 52px;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5);\n}\n\n.avp-settings.open {\n transform: translateY(0);\n}\n\n/* Drag handle indicator at top of sheet. */\n.avp-settings-handle {\n width: 36px;\n height: 4px;\n border-radius: 2px;\n background: rgba(255, 255, 255, 0.3);\n margin: 8px auto 4px;\n}\n\n/* ── Accordion sections ──────────────────────────────────────────────── */\n\n.avp-settings-section {\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n}\n\n.avp-settings-section:last-child { border-bottom: none; }\n\n/* Section header — clickable row showing label + current value. */\n.avp-settings-header {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n transition: background 0.1s;\n}\n\n.avp-settings-header:hover { background: rgba(255, 255, 255, 0.06); }\n\n.avp-settings-header-label {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 500;\n}\n\n.avp-settings-header-value {\n margin-left: auto;\n opacity: 0.6;\n font-size: 13px;\n text-align: right;\n}\n\n/* Invisible native <select> layered over the value portion of the row.\n Covers from the value text to the right edge so tapping the value\n opens the OS picker. The label side remains inert. */\n.avp-settings-select {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 50%;\n opacity: 0;\n cursor: pointer;\n font-size: 16px;\n direction: rtl;\n}\n\n/* Toggle-style rows (Stats for Nerds) — no select, just clickable. */\n.avp-settings-toggle {\n cursor: pointer;\n}\n.avp-settings-toggle:hover { background: rgba(255, 255, 255, 0.06); }\n\n/* ── Stats for nerds ──────────────────────────────────────────────────── */\n\n.avp-stats {\n position: absolute;\n top: 12px;\n left: 12px;\n background: rgba(0, 0, 0, 0.8);\n padding: 12px 16px;\n border-radius: 6px;\n font-size: 12px;\n font-family: \"SF Mono\", \"Menlo\", \"Consolas\", monospace;\n line-height: 1.6;\n white-space: pre;\n pointer-events: auto;\n z-index: 6;\n max-width: 400px;\n overflow: auto;\n display: none;\n}\n\n.avp-stats.open { display: block; }\n\n/* ── Mobile adjustments ───────────────────────────────────────────────── */\n\n@media (pointer: coarse) {\n .avp-btn svg { width: 28px; height: 28px; }\n .avp-btn { padding: 8px; }\n\n /* Taller touch target on mobile (44px, matching YouTube Mobile)\n while keeping the visual track thin. Negative margin collapses\n the extra space so the controls layout doesn't shift. */\n .avp-seek { height: 44px; margin-top: -12px; margin-bottom: -12px; }\n .avp-seek-track { height: 4px; }\n .avp-seek:hover .avp-seek-track { height: 4px; }\n .avp-seek-thumb {\n transform: translate(-50%, -50%) scale(1);\n width: 16px;\n height: 16px;\n }\n .avp-seek[data-seeking] .avp-seek-thumb {\n transform: translate(-50%, -50%) scale(1.5);\n }\n /* Move tooltip above the taller touch zone. */\n .avp-seek-tooltip { bottom: 32px; }\n\n .avp-volume:hover .avp-volume-slider { width: 0; }\n .avp-overlay-btn { width: 56px; height: 56px; }\n .avp-overlay-btn svg { width: 30px; height: 30px; }\n}\n`;\n","/**\n * Inline SVG icons for <avbridge-player> controls.\n * All icons are 24x24 viewBox, stroke-based where possible for\n * easy theming via CSS `color` (currentColor fill/stroke).\n */\n\nexport const ICON_PLAY = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7z\"/></svg>`;\n\nexport const ICON_PAUSE = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 19h4V5H6zm8-14v14h4V5z\"/></svg>`;\n\nexport const ICON_VOLUME_UP = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/></svg>`;\n\nexport const ICON_VOLUME_OFF = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z\"/></svg>`;\n\nexport const ICON_SETTINGS = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.49.49 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 00-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.49.49 0 00-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z\"/></svg>`;\n\nexport const ICON_FULLSCREEN = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/></svg>`;\n\nexport const ICON_FULLSCREEN_EXIT = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/></svg>`;\n\nexport const ICON_REPLAY_10 = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M11.99 5V1l-5 5 5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6h-2c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z\"/><text x=\"10\" y=\"16\" font-size=\"8\" text-anchor=\"middle\" fill=\"currentColor\" font-family=\"sans-serif\">10</text></svg>`;\n\nexport const ICON_FORWARD_10 = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M18 13c0 3.31-2.69 6-6 6s-6-2.69-6-6 2.69-6 6-6v4l5-5-5-5v4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8h-2z\"/><text x=\"14\" y=\"16\" font-size=\"8\" text-anchor=\"middle\" fill=\"currentColor\" font-family=\"sans-serif\">10</text></svg>`;\n\nexport const ICON_SPEED = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M10 8v8l6-4-6-4zm10.77-1.67L22 7.67l-.77-1.34c-.3-.53-.8-.93-1.41-1.05l-1.7-.3c-.16-.43-.36-.84-.6-1.22l.8-1.54-.77-1.34-.77 1.34.8 1.54c-.24.38-.44.79-.6 1.22l-1.7.3c-.61.12-1.11.52-1.41 1.05L13 7.67l1.23-1.34c-.3.53-.3 1.15 0 1.67L15.46 10l-1.23 2.34c-.3.53-.3 1.15 0 1.67L15.46 16l-1.23 2.34.77 1.34.77-1.34-1.23-2.34c.3-.53.3-1.15 0-1.67L13.31 12l1.23-2.34c.3-.53.3-1.15 0-1.67z\"/></svg>`;\n","/**\n * `<avbridge-player>` — YouTube-style controls element.\n *\n * Wraps `<avbridge-video>` with a full player UI: play/pause, seek bar,\n * volume, settings menu (speed, subtitles, audio tracks), fullscreen,\n * keyboard shortcuts, touch gestures, and auto-hiding controls.\n *\n * All properties, methods, and events from `<avbridge-video>` are proxied\n * through. Consumers interact with `<avbridge-player>` exclusively.\n */\n\n// Import the class concretely and register — side-effect-only imports\n// are tree-shaken by Rollup in production builds.\nimport { AvbridgeVideoElement } from \"./avbridge-video.js\";\nif (typeof customElements !== \"undefined\" && !customElements.get(\"avbridge-video\")) {\n customElements.define(\"avbridge-video\", AvbridgeVideoElement);\n}\nimport { PLAYER_STYLES } from \"./player-styles.js\";\nimport {\n ICON_PLAY, ICON_PAUSE,\n ICON_VOLUME_UP, ICON_VOLUME_OFF,\n ICON_SETTINGS,\n ICON_FULLSCREEN, ICON_FULLSCREEN_EXIT,\n ICON_REPLAY_10, ICON_FORWARD_10,\n} from \"./player-icons.js\";\nimport type { AvbridgeVideoElementEventMap, SettingsSectionConfig } from \"../types.js\";\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction formatTime(sec: number): string {\n if (!Number.isFinite(sec) || sec < 0) sec = 0;\n const total = Math.floor(sec);\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n const mm = String(m).padStart(h > 0 ? 2 : 1, \"0\");\n const ss = String(s).padStart(2, \"0\");\n return h > 0 ? `${h}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n\nconst PLAYBACK_SPEEDS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] as const;\nconst DEFAULT_CONTROLS_HIDE_MS = 3000;\n\ntype PlayerState = \"idle\" | \"loading\" | \"playing\" | \"paused\" | \"buffering\" | \"ended\" | \"error\";\n\n// ── Forwarded events ─────────────────────────────────────────────────────\n\nconst FORWARDED_EVENTS = [\n \"ready\", \"error\", \"strategychange\", \"trackschange\", \"loadstart\", \"destroy\",\n \"play\", \"playing\", \"pause\", \"seeking\", \"seeked\", \"volumechange\",\n \"ratechange\", \"durationchange\", \"canplay\", \"canplaythrough\",\n \"waiting\", \"stalled\", \"emptied\", \"resize\",\n \"loadedmetadata\", \"loadeddata\", \"timeupdate\", \"ended\", \"progress\",\n] as const;\n\n// ── Observed attributes ──────────────────────────────────────────────────\n\nconst PROXY_ATTRIBUTES = [\n \"src\", \"autoplay\", \"muted\", \"loop\", \"preload\", \"poster\",\n \"playsinline\", \"crossorigin\", \"disableremoteplayback\", \"preferstrategy\",\n \"fit\",\n] as const;\n\n/** Player-only attributes that don't forward to <avbridge-video>. */\nconst PLAYER_ATTRIBUTES = [\"show-fit\"] as const;\n\nconst FIT_MODES = [\"contain\", \"cover\", \"fill\"] as const;\ntype FitMode = (typeof FIT_MODES)[number];\n\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport class AvbridgePlayerElement extends HTMLElement {\n static readonly observedAttributes = [...PROXY_ATTRIBUTES, ...PLAYER_ATTRIBUTES];\n\n // ── Internal DOM refs ──────────────────────────────────────────────────\n\n private _video!: AvbridgeVideoElement;\n private _playBtn!: HTMLButtonElement;\n private _overlayBtn!: HTMLButtonElement;\n private _seekInput!: HTMLInputElement;\n private _seekProgress!: HTMLDivElement;\n private _seekBuffered!: HTMLDivElement;\n private _seekThumb!: HTMLDivElement;\n private _seekTooltip!: HTMLDivElement;\n private _timeDisplay!: HTMLSpanElement;\n private _volumeBtn!: HTMLButtonElement;\n private _volumeInput!: HTMLInputElement;\n private _settingsBtn!: HTMLButtonElement;\n private _settingsMenu!: HTMLDivElement;\n private _settingsScrim!: HTMLDivElement;\n private _customSections: import(\"../types.js\").SettingsSectionConfig[] = [];\n private _fullscreenBtn!: HTMLButtonElement;\n // Strategy badge removed — visible in Stats for Nerds instead.\n // Spinner is rendered but driven entirely by CSS :host([data-state]) selectors.\n private _speedIndicator!: HTMLDivElement;\n private _rippleLeft!: HTMLDivElement;\n private _rippleRight!: HTMLDivElement;\n\n // ── State ──────────────────────────────────────────────────────────────\n\n private _state: PlayerState = \"idle\";\n private _controlsTimer: ReturnType<typeof setTimeout> | null = null;\n private _settingsOpen = false;\n private _activeAudioTrackId: number | null = null;\n private _activeSubtitleTrackId: number | null = null;\n private _userSeeking = false;\n private _holdTimer: ReturnType<typeof setTimeout> | null = null;\n private _holdSpeedActive = false;\n private _savedPlaybackRate = 1;\n private _lastTapTime = 0;\n private _tapTimer: ReturnType<typeof setTimeout> | null = null;\n private _statsOpen = false;\n private _statsEl!: HTMLDivElement;\n private _statsInterval: ReturnType<typeof setInterval> | null = null;\n private _eventCleanup: (() => void)[] = [];\n private _updateToolbarEmpty: () => void = () => { /* wired in constructor */ };\n private _toolbarTop!: HTMLDivElement;\n\n // ── Constructor ────────────────────────────────────────────────────────\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = `<style>${PLAYER_STYLES}</style>${this._template()}`;\n\n // Grab refs\n this._video = shadow.querySelector(\"avbridge-video\") as AvbridgeVideoElement;\n this._playBtn = shadow.querySelector(\".avp-play\") as HTMLButtonElement;\n this._overlayBtn = shadow.querySelector(\".avp-overlay-btn\") as HTMLButtonElement;\n this._seekInput = shadow.querySelector(\".avp-seek-input\") as HTMLInputElement;\n this._seekProgress = shadow.querySelector(\".avp-seek-progress\") as HTMLDivElement;\n this._seekBuffered = shadow.querySelector(\".avp-seek-buffered\") as HTMLDivElement;\n this._seekThumb = shadow.querySelector(\".avp-seek-thumb\") as HTMLDivElement;\n this._seekTooltip = shadow.querySelector(\".avp-seek-tooltip\") as HTMLDivElement;\n this._timeDisplay = shadow.querySelector(\".avp-time\") as HTMLSpanElement;\n this._volumeBtn = shadow.querySelector(\".avp-volume-btn\") as HTMLButtonElement;\n this._volumeInput = shadow.querySelector(\".avp-volume-input\") as HTMLInputElement;\n this._settingsBtn = shadow.querySelector(\".avp-settings-btn\") as HTMLButtonElement;\n this._settingsMenu = shadow.querySelector(\".avp-settings\") as HTMLDivElement;\n this._settingsScrim = shadow.querySelector(\".avp-settings-scrim\") as HTMLDivElement;\n this._fullscreenBtn = shadow.querySelector(\".avp-fullscreen\") as HTMLButtonElement;\n // Badge removed from controls bar — strategy visible in Stats for Nerds.\n // Spinner is rendered in shadow DOM, driven by CSS :host([data-state]).\n this._speedIndicator = shadow.querySelector(\".avp-speed-indicator\") as HTMLDivElement;\n this._statsEl = shadow.querySelector(\".avp-stats\") as HTMLDivElement;\n this._rippleLeft = shadow.querySelector(\".avp-ripple-left\") as HTMLDivElement;\n this._rippleRight = shadow.querySelector(\".avp-ripple-right\") as HTMLDivElement;\n this._toolbarTop = shadow.querySelector('[part=\"toolbar-top\"]') as HTMLDivElement;\n // Start visible — controls are shown until the auto-hide timer fires.\n this._toolbarTop.setAttribute(\"data-visible\", \"true\");\n\n // Track whether the top toolbar has any slotted content. Used to hide\n // its gradient when empty (see data-toolbar-empty in player-styles.ts).\n // MUST defer the initial attribute write to connectedCallback — the\n // Custom Elements spec forbids constructors from adding attributes.\n const slots = shadow.querySelectorAll<HTMLSlotElement>('slot[name=\"top-left\"], slot[name=\"top-right\"]');\n this._updateToolbarEmpty = () => {\n const hasContent = Array.from(slots).some((s) => s.assignedNodes({ flatten: true }).length > 0);\n if (hasContent) this.removeAttribute(\"data-toolbar-empty\");\n else this.setAttribute(\"data-toolbar-empty\", \"\");\n };\n for (const s of slots) s.addEventListener(\"slotchange\", this._updateToolbarEmpty);\n\n this._bindEvents();\n }\n\n private _template(): string {\n return `\n<div part=\"container\" class=\"avp\">\n <avbridge-video part=\"video\"></avbridge-video>\n <div part=\"toolbar-top\" class=\"avp-toolbar-top\">\n <div part=\"toolbar-top-left\" class=\"avp-toolbar-top-left\"><slot name=\"top-left\"></slot></div>\n <div part=\"toolbar-top-right\" class=\"avp-toolbar-top-right\"><slot name=\"top-right\"></slot></div>\n </div>\n <div part=\"content-overlay\" class=\"avp-content-overlay\"><slot name=\"content-overlay\"></slot></div>\n <div part=\"overlay\" class=\"avp-overlay\">\n <button class=\"avp-overlay-btn\" aria-label=\"Play\">${ICON_PLAY}</button>\n <div class=\"avp-spinner\"></div>\n </div>\n <div class=\"avp-speed-indicator\">2x</div>\n <div class=\"avp-stats\" part=\"stats-panel\"></div>\n <div class=\"avp-ripple avp-ripple-left\">${ICON_REPLAY_10}</div>\n <div class=\"avp-ripple avp-ripple-right\">${ICON_FORWARD_10}</div>\n <div part=\"controls\" class=\"avp-controls\">\n <div class=\"avp-seek\" part=\"seek-bar\">\n <div class=\"avp-seek-track\">\n <div class=\"avp-seek-buffered\"></div>\n <div class=\"avp-seek-progress\"></div>\n </div>\n <div class=\"avp-seek-thumb\"></div>\n <div class=\"avp-seek-tooltip\">0:00</div>\n <input class=\"avp-seek-input\" type=\"range\" min=\"0\" max=\"0\" step=\"any\" value=\"0\" aria-label=\"Seek\">\n </div>\n <div class=\"avp-bottom\">\n <button class=\"avp-btn avp-play\" part=\"play-button\" aria-label=\"Play\">${ICON_PLAY}</button>\n <div class=\"avp-volume\">\n <button class=\"avp-btn avp-volume-btn\" part=\"volume-button\" aria-label=\"Mute\">${ICON_VOLUME_UP}</button>\n <div class=\"avp-volume-slider\">\n <input class=\"avp-volume-input\" part=\"volume-slider\" type=\"range\" min=\"0\" max=\"1\" step=\"0.05\" value=\"1\" aria-label=\"Volume\">\n </div>\n </div>\n <span class=\"avp-time\" part=\"time-display\">0:00 / 0:00</span>\n <span class=\"avp-spacer\"></span>\n <button class=\"avp-btn avp-settings-btn\" part=\"settings-button\" aria-label=\"Settings\">${ICON_SETTINGS}</button>\n <button class=\"avp-btn avp-fullscreen\" part=\"fullscreen-button\" aria-label=\"Fullscreen\">${ICON_FULLSCREEN}</button>\n </div>\n <div class=\"avp-settings-scrim\"></div>\n <div class=\"avp-settings\" part=\"settings-menu\"><div class=\"avp-settings-handle\"></div></div>\n </div>\n</div>`;\n }\n\n // ── Event wiring ───────────────────────────────────────────────────────\n\n private _bindEvents(): void {\n const on = <K extends keyof HTMLElementEventMap>(\n el: EventTarget, event: K | string, fn: (e: Event) => void, opts?: AddEventListenerOptions,\n ) => {\n el.addEventListener(event, fn, opts);\n this._eventCleanup.push(() => el.removeEventListener(event, fn, opts));\n };\n\n // Forward events from inner video\n for (const name of FORWARDED_EVENTS) {\n on(this._video, name, (e) => {\n const detail = (e as CustomEvent).detail;\n this.dispatchEvent(\n detail !== undefined\n ? new CustomEvent(name, { detail, bubbles: e.bubbles, composed: true })\n : new Event(name, { bubbles: e.bubbles }),\n );\n });\n }\n\n // State tracking\n on(this._video, \"loadstart\", () => this._setState(\"loading\"));\n on(this._video, \"ready\", () => {\n this._setState(this._video.paused ? \"paused\" : \"playing\");\n this._seekInput.max = String(this._video.duration || 0);\n this._updateTime();\n this._buildSettingsMenu();\n });\n on(this._video, \"play\", () => this._setState(\"playing\"));\n on(this._video, \"playing\", () => this._setState(\"playing\"));\n on(this._video, \"pause\", () => this._setState(\"paused\"));\n on(this._video, \"waiting\", () => this._setState(\"buffering\"));\n on(this._video, \"ended\", () => this._setState(\"ended\"));\n on(this._video, \"error\", () => this._setState(\"error\"));\n on(this._video, \"timeupdate\", () => this._updateTime());\n // `progress` fires as the inner element's buffered ranges grow — keep the\n // seek bar's buffered indicator fresh even when paused or filling ahead\n // without timeupdate advancing. `<avbridge-video>` dispatches this on\n // all strategies (including the synthesized ranges for canvas strategies).\n on(this._video, \"progress\", () => this._updateBuffered());\n on(this._video, \"volumechange\", () => this._updateVolume());\n // Strategy changes are visible in Stats for Nerds.\n on(this._video, \"trackschange\", () => this._buildSettingsMenu());\n on(this._video, \"durationchange\", () => {\n this._seekInput.max = String(this._video.duration || 0);\n });\n\n // Play / pause\n on(this._playBtn, \"click\", (e) => { e.stopPropagation(); this._togglePlay(); });\n on(this._overlayBtn, \"click\", (e) => { e.stopPropagation(); this._togglePlay(); });\n\n // Seek bar — manual pointer handling so the click position maps\n // linearly across the FULL track width (native <input type=\"range\">\n // clamps the thumb center inside [thumbWidth/2, trackWidth -\n // thumbWidth/2], which causes a visible click-to-thumb offset at\n // the edges). The input is still used for keyboard accessibility\n // (arrow keys, home/end) via its 'input' event.\n on(this._seekInput, \"input\", () => {\n // Only accept keyboard-driven input events (not synthesized\n // from pointer, which we handle manually below).\n if (this._userSeeking) return;\n this._onSeekInput();\n });\n on(this._seekInput, \"change\", () => {\n if (this._userSeeking) return;\n this._onSeekCommit();\n });\n const seekBar = this.shadowRoot!.querySelector(\".avp-seek\") as HTMLElement;\n on(seekBar, \"pointerdown\", (e) => this._onSeekPointerDown(e as PointerEvent));\n on(seekBar, \"pointermove\", (e) => this._onSeekHover(e as PointerEvent));\n\n // Volume\n on(this._volumeBtn, \"click\", (e) => { e.stopPropagation(); this._toggleMute(); });\n on(this._volumeInput, \"input\", () => {\n const vol = Number(this._volumeInput.value);\n this._video.volume = vol;\n this._video.videoElement.volume = vol;\n this._video.muted = false;\n this._video.videoElement.muted = false;\n this._updateVolume();\n });\n\n // Settings\n on(this._settingsBtn, \"click\", (e) => { e.stopPropagation(); this._toggleSettings(); });\n on(this._settingsScrim, \"click\", () => this._closeSettings());\n\n // Fullscreen\n on(this._fullscreenBtn, \"click\", (e) => { e.stopPropagation(); this._toggleFullscreen(); });\n on(document, \"fullscreenchange\", () => this._updateFullscreenIcon());\n\n // Click / tap on video area — uses a delayed-tap pattern (like YouTube)\n // to distinguish single-tap (play/pause) from double-tap (seek ±10s).\n // On mouse: single click → play/pause, dblclick → fullscreen.\n // On touch: single tap (after 250ms) → play/pause, double tap → seek.\n const container = this.shadowRoot!.querySelector(\".avp\")!;\n on(container, \"click\", (e) => this._onContainerClick(e as MouseEvent));\n on(container, \"dblclick\", (e) => this._onContainerDblClick(e as MouseEvent));\n\n // Dismiss settings sheet when clicking outside it. The scrim handles\n // most of this (its own click handler calls _closeSettings), but we\n // also catch clicks outside the player element entirely.\n on(document, \"click\", (e) => {\n if (this._settingsOpen && !this.contains(e.target as Node)) {\n this._closeSettings();\n }\n });\n\n // Auto-hide controls\n on(container, \"pointermove\", () => this._showControls());\n on(container, \"pointerleave\", () => this._scheduleHide());\n\n // Touch gestures: hold for 2x speed\n on(container, \"pointerdown\", (e) => this._onPointerDown(e as PointerEvent));\n on(container, \"pointerup\", (e) => this._onPointerUp(e as PointerEvent));\n on(container, \"pointercancel\", () => this._cancelHold());\n\n // Drag-and-drop file input. Drop a video file onto the player area\n // and it loads + plays. Files of non-video types are rejected silently\n // (no MIME sniffing — we let probe() decide). The dragover listener\n // calls preventDefault so the drop event actually fires.\n on(container, \"dragenter\", (e) => {\n e.preventDefault();\n const dt = (e as DragEvent).dataTransfer;\n if (!dt || !Array.from(dt.types).includes(\"Files\")) return;\n (container as HTMLElement).classList.add(\"avp-dragover\");\n });\n on(container, \"dragover\", (e) => {\n e.preventDefault();\n const dt = (e as DragEvent).dataTransfer;\n if (dt) dt.dropEffect = \"copy\";\n });\n on(container, \"dragleave\", (e) => {\n // dragleave fires on every child — only clear when we leave the container.\n if ((e as DragEvent).target === container) {\n (container as HTMLElement).classList.remove(\"avp-dragover\");\n }\n });\n on(container, \"drop\", (e) => {\n e.preventDefault();\n (container as HTMLElement).classList.remove(\"avp-dragover\");\n const file = (e as DragEvent).dataTransfer?.files?.[0];\n if (!file) return;\n // Reuse the existing source-assignment path. play() errors are\n // reported via the normal error event; don't swallow here.\n (this._video as unknown as { source: unknown }).source = file;\n void this._video.play().catch(() => { /* error event already fired */ });\n });\n\n // Keyboard\n on(this, \"keydown\", (e) => this._onKeydown(e as KeyboardEvent));\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────────\n\n connectedCallback(): void {\n this._setState(\"idle\");\n // Attribute writes the Custom Elements spec forbids in constructors\n // — document.createElement rejects with \"The result must not have\n // attributes\" — deferred here. Surfaced by the Playwright\n // cross-browser tests.\n if (!this.hasAttribute(\"tabindex\")) {\n this.setAttribute(\"tabindex\", \"0\");\n }\n this._updateToolbarEmpty();\n }\n\n disconnectedCallback(): void {\n this._clearTimers();\n }\n\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n if (!this._video) return;\n // Player-only attributes — not forwarded to the inner <avbridge-video>.\n if ((PLAYER_ATTRIBUTES as readonly string[]).includes(name)) {\n if (name === \"show-fit\" && this._settingsOpen) {\n this._buildSettingsMenu();\n }\n return;\n }\n // Proxy everything else down.\n if (value == null) this._video.removeAttribute(name);\n else this._video.setAttribute(name, value);\n }\n\n // ── State management ───────────────────────────────────────────────────\n\n private _setState(state: PlayerState): void {\n this._state = state;\n this.dataset.state = state;\n\n // Update play/pause icons\n const playing = state === \"playing\" || state === \"buffering\";\n this._playBtn.innerHTML = playing ? ICON_PAUSE : ICON_PLAY;\n this._playBtn.ariaLabel = playing ? \"Pause\" : \"Play\";\n this._overlayBtn.innerHTML = ICON_PLAY;\n\n // Auto-hide logic\n if (playing) this._scheduleHide();\n else this._showControls();\n }\n\n // ── Controls: play/pause ───────────────────────────────────────────────\n\n private _togglePlay(): void {\n if (this._state === \"idle\" || this._state === \"error\") return;\n if (this._video.paused) void this._video.play();\n else this._video.pause();\n }\n\n // ── Controls: seek ─────────────────────────────────────────────────────\n\n private _onSeekInput(): void {\n const t = Number(this._seekInput.value);\n this._updateSeekVisuals(t);\n this._timeDisplay.textContent = `${formatTime(t)} / ${formatTime(this._video.duration)}`;\n }\n\n private _onSeekCommit(): void {\n this._video.currentTime = Number(this._seekInput.value);\n this._userSeeking = false;\n }\n\n /** Linear click-to-time mapping across the full track width (no edge clamping). */\n private _timeFromSeekPointer(clientX: number): number {\n const seekBar = this.shadowRoot!.querySelector(\".avp-seek\") as HTMLElement;\n const rect = seekBar.getBoundingClientRect();\n const frac = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n return frac * (this._video.duration || 0);\n }\n\n /** Seekbar width below which drag-to-scrub seeks in real-time (vs\n * preview-only). On narrow bars precise positioning is hard, so\n * immediate video feedback is more useful than a time tooltip. */\n private static readonly SCRUB_WIDTH_THRESHOLD = 400;\n\n private _onSeekPointerDown(e: PointerEvent): void {\n // Ignore synthetic clicks originating from the input's own handling\n if (e.button !== 0 && e.pointerType === \"mouse\") return;\n e.preventDefault();\n this._userSeeking = true;\n const seekBar = this.shadowRoot!.querySelector(\".avp-seek\") as HTMLElement;\n seekBar.setPointerCapture(e.pointerId);\n seekBar.setAttribute(\"data-seeking\", \"\");\n\n // Decide scrub mode based on physical width.\n const scrubMode = seekBar.getBoundingClientRect().width < AvbridgePlayerElement.SCRUB_WIDTH_THRESHOLD;\n let lastScrubCommit = 0;\n\n const initial = this._timeFromSeekPointer(e.clientX);\n this._seekInput.value = String(initial);\n this._onSeekInput();\n this._updateSeekTooltip(e.clientX);\n if (scrubMode) this._onSeekCommit();\n\n const onMove = (ev: PointerEvent) => {\n const t = this._timeFromSeekPointer(ev.clientX);\n this._seekInput.value = String(t);\n this._onSeekInput();\n this._updateSeekTooltip(ev.clientX);\n // In scrub mode, commit seeks throttled to ~4 Hz so we don't\n // overwhelm the seek pipeline (especially on canvas strategies\n // where each seek restarts the decoder pump).\n if (scrubMode) {\n const now = performance.now();\n if (now - lastScrubCommit > 250) {\n lastScrubCommit = now;\n this._onSeekCommit();\n this._userSeeking = true; // keep seeking flag live\n }\n }\n };\n const onUp = (ev: PointerEvent) => {\n const t = this._timeFromSeekPointer(ev.clientX);\n this._seekInput.value = String(t);\n this._onSeekCommit();\n this._seekInput.focus();\n seekBar.removeAttribute(\"data-seeking\");\n seekBar.removeEventListener(\"pointermove\", onMove);\n seekBar.removeEventListener(\"pointerup\", onUp);\n seekBar.removeEventListener(\"pointercancel\", onUp);\n try { seekBar.releasePointerCapture(e.pointerId); } catch { /* ignore */ }\n };\n seekBar.addEventListener(\"pointermove\", onMove);\n seekBar.addEventListener(\"pointerup\", onUp);\n seekBar.addEventListener(\"pointercancel\", onUp);\n }\n\n private _onSeekHover(e: PointerEvent): void {\n this._updateSeekTooltip(e.clientX);\n }\n\n private _updateSeekTooltip(clientX: number): void {\n const rect = this._seekInput.getBoundingClientRect();\n const frac = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n const t = frac * (this._video.duration || 0);\n this._seekTooltip.textContent = formatTime(t);\n this._seekTooltip.style.left = `${frac * 100}%`;\n }\n\n private _updateSeekVisuals(t: number): void {\n const dur = this._video.duration || 0;\n const pct = dur > 0 ? (t / dur) * 100 : 0;\n this._seekProgress.style.width = `${pct}%`;\n // Thumb position uses a CSS calc that matches the native range input's\n // click-to-value math (thumb stays within track bounds). See player-styles.ts.\n this._seekThumb.style.setProperty(\"--pct\", String(pct));\n }\n\n // ── Controls: time ─────────────────────────────────────────────────────\n\n private _updateTime(): void {\n if (this._userSeeking) return;\n const t = this._video.currentTime;\n const d = this._video.duration;\n this._seekInput.value = String(t);\n this._updateSeekVisuals(t);\n this._timeDisplay.textContent = `${formatTime(t)} / ${formatTime(d)}`;\n this._updateBuffered();\n }\n\n /**\n * Render every buffered range as its own segment so gaps (common on MSE\n * after seeks) are visible. Not gated by `_userSeeking` — ranges should\n * keep updating while the user scrubs, and runs cheaply on `progress`.\n */\n private _updateBuffered(): void {\n const d = this._video.duration;\n if (!(d > 0)) return;\n let buf: TimeRanges;\n try { buf = this._video.buffered; } catch { return; }\n const count = buf ? buf.length : 0;\n const host = this._seekBuffered;\n // Reconcile child count. Segment divs are styled via .avp-seek-buffered-range.\n while (host.childElementCount > count) host.lastElementChild!.remove();\n while (host.childElementCount < count) {\n const seg = document.createElement(\"div\");\n seg.className = \"avp-seek-buffered-range\";\n host.appendChild(seg);\n }\n for (let i = 0; i < count; i++) {\n let start: number; let end: number;\n try { start = buf.start(i); end = buf.end(i); } catch { continue; }\n const s = Math.max(0, start);\n const e = Math.min(d, end);\n if (e <= s) continue;\n const seg = host.children[i] as HTMLElement;\n seg.style.left = `${(s / d) * 100}%`;\n seg.style.width = `${((e - s) / d) * 100}%`;\n }\n }\n\n // ── Controls: volume ───────────────────────────────────────────────────\n\n private _toggleMute(): void {\n // Set both the element attribute AND the inner <video> property directly,\n // because avbridge-video's attribute-based muted toggling can diverge\n // from the <video> property on a running element.\n const newMuted = !this._video.muted;\n this._video.muted = newMuted;\n this._video.videoElement.muted = newMuted;\n this._updateVolume();\n }\n\n private _updateVolume(): void {\n const muted = this._video.muted || this._video.videoElement.muted || this._video.volume === 0;\n this._volumeBtn.innerHTML = muted ? ICON_VOLUME_OFF : ICON_VOLUME_UP;\n this._volumeInput.value = muted ? \"0\" : String(this._video.volume);\n }\n\n // ── Controls: settings ─────────────────────────────────────────────────\n\n private _toggleSettings(): void {\n this._settingsOpen = !this._settingsOpen;\n this._settingsMenu.classList.toggle(\"open\", this._settingsOpen);\n this._settingsScrim.classList.toggle(\"open\", this._settingsOpen);\n if (this._settingsOpen) {\n this._fitSettingsToPlayer();\n this._showControls();\n }\n }\n\n private _fitSettingsToPlayer(): void {\n const container = this.shadowRoot?.querySelector(\".avp\") as HTMLElement | null;\n if (!container) return;\n const rect = container.getBoundingClientRect();\n // Bottom sheet can use up to 70% of the player height, leaving room\n // to see the video behind the scrim. Floor at 120px so it's always\n // usable.\n const maxH = Math.max(120, Math.floor(rect.height * 0.7));\n this._settingsMenu.style.maxHeight = `${maxH}px`;\n }\n\n private _closeSettings(): void {\n this._settingsOpen = false;\n this._settingsMenu.classList.remove(\"open\");\n this._settingsScrim.classList.remove(\"open\");\n }\n\n private _buildSettingsMenu(): void {\n const sections: string[] = [];\n\n // Helper: a row with an invisible native <select> layered on top of\n // a styled label+value. Tapping opens the OS picker (escapes the\n // shadow DOM — intentional for small players). The visible label\n // updates on change.\n const selectRow = (label: string, currentValue: string, options: string, selectAttrs: string): string =>\n `<div class=\"avp-settings-section\">` +\n `<div class=\"avp-settings-header\">` +\n `<span class=\"avp-settings-header-label\">${label}</span>` +\n `<span class=\"avp-settings-header-value\">${currentValue}</span>` +\n `<select class=\"avp-settings-select\" ${selectAttrs}>${options}</select>` +\n `</div>` +\n `</div>`;\n\n // Speed\n const currentRate = this._video.playbackRate ?? 1;\n const speedValue = Math.abs(currentRate - 1) < 0.01 ? \"Normal\" : `${currentRate}x`;\n let speedOpts = \"\";\n for (const spd of PLAYBACK_SPEEDS) {\n const sel = Math.abs(spd - currentRate) < 0.01 ? \" selected\" : \"\";\n const label = spd === 1 ? \"Normal\" : `${spd}x`;\n speedOpts += `<option value=\"${spd}\"${sel}>${label}</option>`;\n }\n sections.push(selectRow(\"Speed\", speedValue, speedOpts, `data-action=\"speed\"`));\n\n // Audio tracks\n const audios = this._video.audioTracks ?? [];\n if (audios.length > 1) {\n const activeAudioId = this._activeAudioTrackId ?? audios[0]?.id;\n const activeAudio = audios.find((t: { id: number }) => t.id === activeAudioId) ?? audios[0];\n const audioValue = activeAudio?.language ?? `Track ${activeAudio?.id ?? 1}`;\n let audioOpts = \"\";\n for (const t of audios) {\n const sel = t.id === activeAudioId ? \" selected\" : \"\";\n audioOpts += `<option value=\"${t.id}\"${sel}>${t.language ?? `Track ${t.id}`}</option>`;\n }\n sections.push(selectRow(\"Audio\", audioValue, audioOpts, `data-action=\"audio\"`));\n }\n\n // Subtitle tracks\n const subs = this._video.subtitleTracks ?? [];\n if (subs.length > 0) {\n const activeSubId = this._activeSubtitleTrackId;\n const activeSub = activeSubId != null ? subs.find((t: { id: number }) => t.id === activeSubId) : null;\n const subValue = activeSub ? (activeSub.language ?? `Track ${activeSub.id}`) : \"Off\";\n let subOpts = `<option value=\"-1\"${activeSubId == null ? \" selected\" : \"\"}>Off</option>`;\n for (const t of subs) {\n const sel = t.id === activeSubId ? \" selected\" : \"\";\n subOpts += `<option value=\"${t.id}\"${sel}>${t.language ?? `Track ${t.id}`}</option>`;\n }\n sections.push(selectRow(\"Subtitles\", subValue, subOpts, `data-action=\"subtitle\"`));\n }\n\n // Fit mode — opt-in via the `show-fit` attribute\n if (this.hasAttribute(\"show-fit\")) {\n const currentFit = (this._video.fit ?? \"contain\") as FitMode;\n const fitValue = currentFit[0].toUpperCase() + currentFit.slice(1);\n let fitOpts = \"\";\n for (const mode of FIT_MODES) {\n const sel = mode === currentFit ? \" selected\" : \"\";\n const label = mode[0].toUpperCase() + mode.slice(1);\n fitOpts += `<option value=\"${mode}\"${sel}>${label}</option>`;\n }\n sections.push(selectRow(\"Fit\", fitValue, fitOpts, `data-action=\"fit\"`));\n }\n\n // Consumer-added sections\n for (const cfg of this._customSections) {\n const activeItem = cfg.items.find((i) => i.active);\n let customOpts = \"\";\n for (const item of cfg.items) {\n const sel = item.active ? \" selected\" : \"\";\n customOpts += `<option value=\"${item.id}\"${sel}>${item.label}</option>`;\n }\n sections.push(selectRow(cfg.label, activeItem?.label ?? \"\", customOpts, `data-action=\"custom\" data-custom-id=\"${cfg.id}\"`));\n }\n\n // Stats for nerds — toggle row (no select)\n sections.push(\n `<div class=\"avp-settings-section\">` +\n `<div class=\"avp-settings-header avp-settings-toggle\" data-stats>` +\n `<span class=\"avp-settings-header-label\">Stats for Nerds</span>` +\n `</div>` +\n `</div>`,\n );\n\n // Rebuild sheet content (preserve the handle).\n const handle = this._settingsMenu.querySelector(\".avp-settings-handle\");\n this._settingsMenu.innerHTML = \"\";\n if (handle) this._settingsMenu.appendChild(handle);\n else this._settingsMenu.insertAdjacentHTML(\"afterbegin\", `<div class=\"avp-settings-handle\"></div>`);\n this._settingsMenu.insertAdjacentHTML(\"beforeend\", sections.join(\"\"));\n\n // ── <select> change handlers ──\n for (const sel of this._settingsMenu.querySelectorAll<HTMLSelectElement>(\".avp-settings-select\")) {\n sel.addEventListener(\"change\", (e) => {\n e.stopPropagation();\n const action = sel.dataset.action;\n const val = sel.value;\n switch (action) {\n case \"speed\":\n this._video.playbackRate = Number(val);\n break;\n case \"audio\":\n this._activeAudioTrackId = Number(val);\n void this._video.setAudioTrack(Number(val));\n break;\n case \"subtitle\": {\n const subId = Number(val);\n this._activeSubtitleTrackId = subId >= 0 ? subId : null;\n void this._video.setSubtitleTrack(subId >= 0 ? subId : null);\n break;\n }\n case \"fit\":\n this.setAttribute(\"fit\", val);\n break;\n case \"custom\": {\n const cfgId = sel.dataset.customId!;\n const cfg = this._customSections.find((s) => s.id === cfgId);\n cfg?.onSelect(val);\n break;\n }\n }\n this._buildSettingsMenu();\n });\n }\n\n // Stats toggle (no select — just a clickable row)\n const statsRow = this._settingsMenu.querySelector(\"[data-stats]\");\n if (statsRow) {\n statsRow.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this._toggleStats();\n this._closeSettings();\n });\n }\n }\n\n // ── Stats for nerds ────────────────────────────────────────────────────\n\n private _toggleStats(): void {\n this._statsOpen = !this._statsOpen;\n this._statsEl.classList.toggle(\"open\", this._statsOpen);\n if (this._statsOpen) {\n this._updateStats();\n this._statsInterval = setInterval(() => this._updateStats(), 1000);\n } else {\n if (this._statsInterval) { clearInterval(this._statsInterval); this._statsInterval = null; }\n }\n }\n\n private _updateStats(): void {\n const d = this._video.getDiagnostics() as Record<string, unknown> | null;\n if (!d) { this._statsEl.textContent = \"No diagnostics\"; return; }\n const rt = (d.runtime ?? {}) as Record<string, unknown>;\n const lines: string[] = [\n `Container: ${d.container ?? \"?\"}`,\n `Video: ${d.videoCodec ?? \"?\"} ${d.width ?? \"?\"}×${d.height ?? \"?\"}`,\n `Audio: ${d.audioCodec ?? \"none\"}`,\n `Strategy: ${d.strategy ?? \"?\"} Class: ${d.strategyClass ?? \"?\"}`,\n `Transport: ${d.transport ?? \"?\"} Range: ${d.rangeSupported ?? \"?\"}`,\n `Duration: ${typeof d.duration === \"number\" ? d.duration.toFixed(1) + \"s\" : \"?\"}`,\n ];\n if (rt.framesDecoded != null) lines.push(`Frames: ${rt.framesDecoded} decoded, ${rt.framesDropped ?? 0} dropped`);\n if (rt.framesPainted != null) lines.push(`Painted: ${rt.framesPainted} Late: ${rt.framesDroppedLate ?? 0} Overflow: ${rt.framesDroppedOverflow ?? 0}`);\n if (rt.videoFramesDecoded != null) lines.push(`Video decoded: ${rt.videoFramesDecoded} Chunks fed: ${rt.videoChunksFed ?? \"?\"}`);\n if (rt.audioFramesDecoded != null) lines.push(`Audio decoded: ${rt.audioFramesDecoded}`);\n if (rt.packetsRead != null) lines.push(`Packets read: ${rt.packetsRead}`);\n if (rt.bsfApplied && (rt.bsfApplied as string[]).length > 0) lines.push(`BSF: ${(rt.bsfApplied as string[]).join(\", \")}`);\n if (rt.audioState != null) lines.push(`Audio state: ${rt.audioState} Clock: ${rt.clockMode ?? \"?\"}`);\n if (d.probedBy) lines.push(`Probed by: ${d.probedBy}`);\n this._statsEl.textContent = lines.join(\"\\n\");\n }\n\n // ── Controls: fullscreen ───────────────────────────────────────────────\n\n private _toggleFullscreen(): void {\n if (document.fullscreenElement === this) {\n void document.exitFullscreen();\n } else {\n void this.requestFullscreen();\n }\n }\n\n private _updateFullscreenIcon(): void {\n const fs = document.fullscreenElement === this;\n this._fullscreenBtn.innerHTML = fs ? ICON_FULLSCREEN_EXIT : ICON_FULLSCREEN;\n }\n\n // ── Controls: auto-hide ────────────────────────────────────────────────\n\n /**\n * Reveal the auto-hiding chrome (top toolbar + bottom controls) and\n * re-start the auto-hide timer. Call this from app-level code to\n * briefly surface the player UI — e.g. to confirm \"you just swiped to\n * this video\" in a carousel, or to flash the title on focus change.\n *\n * @param durationMs How long the chrome stays visible before fading.\n * Defaults to the player's normal 3 s auto-hide.\n * Pointer movement or any other interaction resets\n * the timer, so a user hovering during the flash\n * sees no flicker.\n */\n showControls(durationMs?: number): void {\n this.removeAttribute(\"data-controls-hidden\");\n this._toolbarTop.setAttribute(\"data-visible\", \"true\");\n this._scheduleHide(durationMs);\n }\n\n private _showControls(): void {\n this.showControls();\n }\n\n private _scheduleHide(durationMs?: number): void {\n const ms = durationMs ?? this._getControlsTimeout();\n if (this._controlsTimer) clearTimeout(this._controlsTimer);\n if (this._state !== \"playing\" && this._state !== \"buffering\") return;\n if (this._settingsOpen) return;\n // A timeout of 0 or negative means \"never hide\" (controls always visible).\n if (ms <= 0) return;\n this._controlsTimer = setTimeout(() => {\n if (this._state === \"playing\") {\n this.setAttribute(\"data-controls-hidden\", \"\");\n this._toolbarTop.setAttribute(\"data-visible\", \"false\");\n }\n }, ms);\n }\n\n /** Read the controls-timeout attribute. 0 or negative = never hide.\n * Unset = default 3000ms. */\n private _getControlsTimeout(): number {\n const attr = this.getAttribute(\"controls-timeout\");\n if (attr == null) return DEFAULT_CONTROLS_HIDE_MS;\n const n = Number(attr);\n return Number.isFinite(n) ? n : DEFAULT_CONTROLS_HIDE_MS;\n }\n\n // Strategy is visible in Stats for Nerds, no badge in controls bar.\n\n // ── Click / tap handling (YouTube delayed-tap pattern) ──────────────────\n //\n // Problem: single click toggles play, double click toggles fullscreen (or\n // seek on touch). Firing play on the first click causes a play→pause\n // glitch on every double-click. YouTube solves this by delaying the\n // single-click action by ~250ms; if a second click arrives in that window\n // it's treated as a double-click and the single-click action is cancelled.\n\n /** Track whether the last interaction was touch so click handler can skip. */\n private _lastPointerTypeWasTouch = false;\n /** True for ~50ms after a touch double-tap was handled, so the\n * synthetic dblclick from the browser doesn't also fire fullscreen. */\n private _touchDoubleTapConsumed = false;\n\n /** True if the event's composed path passes through consumer-slotted\n * content (toolbar or content-overlay). Slotted content lives in the\n * light DOM so `.closest(\".avp-toolbar-top\")` on the event target won't\n * find the shadow-DOM wrapper — `composedPath()` does. */\n private _isSlottedContentEvent(e: Event): boolean {\n for (const node of e.composedPath()) {\n if (node instanceof HTMLElement &&\n (node.classList.contains(\"avp-toolbar-top\") ||\n node.classList.contains(\"avp-content-overlay\"))) return true;\n }\n return false;\n }\n\n private _onContainerClick(e: MouseEvent): void {\n // Ignore clicks on controls and slotted content\n if ((e.target as HTMLElement).closest?.(\".avp-controls, .avp-settings, .avp-overlay-btn\")) return;\n if (this._isSlottedContentEvent(e)) return;\n\n // If the bottom sheet is open, any click outside it dismisses\n // instead of toggling play/pause.\n if (this._settingsOpen) {\n this._closeSettings();\n return;\n }\n\n // Touch taps are handled by _onPointerUp (show/hide controls + double-tap).\n // The browser fires a synthetic click after touchend — skip it.\n if (this._lastPointerTypeWasTouch) {\n this._lastPointerTypeWasTouch = false;\n return;\n }\n\n // Mouse: delay single-click to let dblclick cancel it\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n this._tapTimer = setTimeout(() => {\n this._tapTimer = null;\n this._togglePlay();\n }, 250);\n }\n\n private _onContainerDblClick(e: MouseEvent): void {\n if ((e.target as HTMLElement).closest?.(\".avp-controls, .avp-settings\")) return;\n if (this._isSlottedContentEvent(e)) return;\n // On touch devices, the browser synthesizes a dblclick after two\n // rapid taps. But we already handled the double-tap in _onPointerUp\n // (which does ff/rw on sides, fullscreen in center). Skip the\n // synthetic dblclick so both don't fire.\n if (this._touchDoubleTapConsumed) return;\n // Cancel the pending single-click play/pause\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n this._toggleFullscreen();\n }\n\n // ── Touch gestures ─────────────────────────────────────────────────────\n\n private _onPointerDown(e: PointerEvent): void {\n if (e.pointerType !== \"touch\") return;\n // Tap-and-hold for 2x speed\n this._holdTimer = setTimeout(() => {\n this._holdSpeedActive = true;\n this._savedPlaybackRate = this._video.playbackRate;\n this._video.playbackRate = 2;\n this._speedIndicator.classList.add(\"active\");\n }, 500);\n }\n\n private _onPointerUp(e: PointerEvent): void {\n this._cancelHold();\n if (e.pointerType !== \"touch\") return;\n this._lastPointerTypeWasTouch = true;\n\n // Ignore touches on controls — buttons have their own handlers\n if ((e.target as HTMLElement).closest?.(\".avp-controls, .avp-settings, .avp-overlay-btn\")) return;\n if (this._isSlottedContentEvent(e)) return;\n\n // If the bottom sheet is open, dismiss it on any touch outside.\n if (this._settingsOpen) {\n this._closeSettings();\n return;\n }\n\n // Double-tap detection\n const now = Date.now();\n if (now - this._lastTapTime < 300) {\n // Double tap — cancel pending single tap and seek\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n const rect = this.getBoundingClientRect();\n const x = e.clientX - rect.left;\n if (x < rect.width / 3) {\n this._doDoubleTap(\"left\");\n } else if (x > (rect.width * 2) / 3) {\n this._doDoubleTap(\"right\");\n } else {\n this._toggleFullscreen();\n }\n // Prevent the synthetic dblclick (fired ~50ms later by the\n // browser) from also toggling fullscreen.\n this._touchDoubleTapConsumed = true;\n setTimeout(() => { this._touchDoubleTapConsumed = false; }, 100);\n this._lastTapTime = 0;\n return;\n }\n // Single tap on touch — toggle controls visibility (NOT play/pause).\n // YouTube mobile: tap shows/hides controls. Play button toggles playback.\n this._lastTapTime = now;\n this._tapTimer = setTimeout(() => {\n this._tapTimer = null;\n if (this.hasAttribute(\"data-controls-hidden\")) {\n this._showControls();\n } else {\n this.setAttribute(\"data-controls-hidden\", \"\");\n }\n }, 250);\n }\n\n private _cancelHold(): void {\n if (this._holdTimer) {\n clearTimeout(this._holdTimer);\n this._holdTimer = null;\n }\n if (this._holdSpeedActive) {\n this._holdSpeedActive = false;\n this._video.playbackRate = this._savedPlaybackRate;\n this._speedIndicator.classList.remove(\"active\");\n }\n }\n\n private _doDoubleTap(side: \"left\" | \"right\"): void {\n const ripple = side === \"left\" ? this._rippleLeft : this._rippleRight;\n ripple.classList.remove(\"active\");\n // Force reflow to restart animation\n void ripple.offsetWidth;\n ripple.classList.add(\"active\");\n\n const delta = side === \"left\" ? -10 : 10;\n this._video.currentTime = Math.max(0, this._video.currentTime + delta);\n }\n\n // ── Keyboard shortcuts ─────────────────────────────────────────────────\n\n /** Duration of one frame in seconds, derived from diagnostics fps or\n * a 30fps default. Used for frame-step shortcuts (`,` / `.`). */\n private _frameDuration(): number {\n const diag = this._video.getDiagnostics() as { fps?: number } | null;\n const fps = diag?.fps && diag.fps > 0 ? diag.fps : 30;\n return 1 / fps;\n }\n\n private _onKeydown(e: KeyboardEvent): void {\n // Don't intercept if the user is typing in an input\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;\n\n switch (e.key) {\n case \" \":\n case \"k\":\n e.preventDefault();\n this._togglePlay();\n break;\n case \"f\":\n e.preventDefault();\n this._toggleFullscreen();\n break;\n case \"m\":\n e.preventDefault();\n this._toggleMute();\n break;\n case \"ArrowLeft\":\n case \"j\":\n e.preventDefault();\n this._video.currentTime = Math.max(0, this._video.currentTime - 5);\n break;\n case \"ArrowRight\":\n case \"l\":\n e.preventDefault();\n this._video.currentTime = Math.min(this._video.duration || 0, this._video.currentTime + 5);\n break;\n case \"ArrowUp\":\n e.preventDefault();\n this._video.volume = Math.min(1, this._video.volume + 0.1);\n break;\n case \"ArrowDown\":\n e.preventDefault();\n this._video.volume = Math.max(0, this._video.volume - 0.1);\n break;\n case \">\":\n e.preventDefault();\n this._video.playbackRate = Math.min(2, this._video.playbackRate + 0.25);\n this._buildSettingsMenu();\n break;\n case \"<\":\n e.preventDefault();\n this._video.playbackRate = Math.max(0.25, this._video.playbackRate - 0.25);\n this._buildSettingsMenu();\n break;\n case \",\":\n // Frame-back (YouTube-style: , while paused steps back one frame)\n e.preventDefault();\n if (!this._video.paused) this._video.pause();\n this._video.currentTime = Math.max(0, this._video.currentTime - this._frameDuration());\n break;\n case \".\":\n // Frame-forward (YouTube-style: . while paused steps forward one frame)\n e.preventDefault();\n if (!this._video.paused) this._video.pause();\n this._video.currentTime = Math.min(\n this._video.duration || 0,\n this._video.currentTime + this._frameDuration(),\n );\n break;\n case \"Escape\":\n if (this._settingsOpen) {\n e.preventDefault();\n this._closeSettings();\n }\n break;\n }\n this._showControls();\n }\n\n // ── Cleanup ────────────────────────────────────────────────────────────\n\n private _clearTimers(): void {\n if (this._controlsTimer) { clearTimeout(this._controlsTimer); this._controlsTimer = null; }\n if (this._holdTimer) { clearTimeout(this._holdTimer); this._holdTimer = null; }\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n if (this._statsInterval) { clearInterval(this._statsInterval); this._statsInterval = null; }\n }\n\n // ── Property proxies ───────────────────────────────────────────────────\n\n get src(): string { return this._video.src ?? \"\"; }\n set src(v: string) { this._video.src = v; }\n\n get source(): unknown { return this._video.source; }\n set source(v: unknown) { (this._video as unknown as { source: unknown }).source = v; }\n\n get currentTime(): number { return this._video.currentTime; }\n set currentTime(v: number) { this._video.currentTime = v; }\n\n get duration(): number { return this._video.duration; }\n get paused(): boolean { return this._video.paused; }\n get ended(): boolean { return this._video.ended; }\n get readyState(): number { return this._video.readyState; }\n\n get volume(): number { return this._video.volume; }\n set volume(v: number) { this._video.volume = v; this._updateVolume(); }\n\n get muted(): boolean { return this._video.muted; }\n set muted(v: boolean) { this._video.muted = v; this._updateVolume(); }\n\n get playbackRate(): number { return this._video.playbackRate; }\n set playbackRate(v: number) { this._video.playbackRate = v; }\n\n get autoplay(): boolean { return this._video.autoplay; }\n set autoplay(v: boolean) { this._video.autoplay = v; }\n\n get loop(): boolean { return this._video.loop; }\n set loop(v: boolean) { this._video.loop = v; }\n\n get videoWidth(): number { return this._video.videoWidth; }\n get videoHeight(): number { return this._video.videoHeight; }\n get buffered(): TimeRanges { return this._video.buffered; }\n get played(): TimeRanges { return this._video.played; }\n get seekable(): TimeRanges { return this._video.seekable; }\n\n get strategy(): string | undefined { return this._video.strategy ?? undefined; }\n get strategyClass(): string | undefined { return this._video.strategyClass ?? undefined; }\n get audioTracks(): unknown[] { return this._video.audioTracks ?? []; }\n get subtitleTracks(): unknown[] { return this._video.subtitleTracks ?? []; }\n\n /**\n * External subtitle files to attach when the source loads. Forwarded\n * to the inner <avbridge-video>. Takes effect on next bootstrap.\n */\n get subtitles(): unknown {\n return (this._video as unknown as { subtitles: unknown }).subtitles;\n }\n set subtitles(value: unknown) {\n (this._video as unknown as { subtitles: unknown }).subtitles = value;\n }\n\n /** Attach a subtitle track to the current playback without a reload. */\n async addSubtitle(subtitle: { url: string; language?: string; format?: \"vtt\" | \"srt\" }): Promise<void> {\n return (this._video as unknown as { addSubtitle: (s: unknown) => Promise<void> }).addSubtitle(subtitle);\n }\n get player(): unknown { return this._video.player; }\n get videoElement(): HTMLVideoElement { return this._video.videoElement; }\n\n // ── Method proxies ─────────────────────────────────────────────────────\n\n async play(): Promise<void> { return this._video.play(); }\n pause(): void { this._video.pause(); }\n async load(): Promise<void> { return this._video.load(); }\n async destroy(): Promise<void> {\n this._clearTimers();\n for (const fn of this._eventCleanup) fn();\n this._eventCleanup = [];\n return this._video.destroy();\n }\n async setAudioTrack(id: number): Promise<void> { return this._video.setAudioTrack(id); }\n\n addSettingsSection(config: SettingsSectionConfig): void {\n this._customSections = this._customSections.filter((s) => s.id !== config.id);\n this._customSections.push(config);\n this._buildSettingsMenu();\n }\n\n removeSettingsSection(id: string): void {\n this._customSections = this._customSections.filter((s) => s.id !== id);\n this._buildSettingsMenu();\n }\n async setSubtitleTrack(id: number | null): Promise<void> { return this._video.setSubtitleTrack(id); }\n getDiagnostics(): unknown { return this._video.getDiagnostics(); }\n canPlayType(mime: string): string { return this._video.canPlayType(mime); }\n\n // ── Typed addEventListener / removeEventListener overloads ────────────\n // Forwarded events from the inner <avbridge-video> preserve their\n // typed CustomEvent detail. Standard HTMLMediaElement events retain\n // their native typing via HTMLElementEventMap.\n\n override addEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void {\n super.addEventListener(type, listener, options);\n }\n\n override removeEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void {\n super.removeEventListener(type, listener, options);\n }\n}\n","/**\n * Registration entry point for `<avbridge-player>`.\n *\n * Import `\"avbridge/player\"` to register the element. This also registers\n * `<avbridge-video>` (which `<avbridge-player>` wraps internally).\n *\n * Separate from `\"avbridge/element\"` so consumers who only need the bare\n * `<avbridge-video>` primitive don't pay for the controls CSS/JS.\n */\n\nimport { AvbridgePlayerElement } from \"./element/avbridge-player.js\";\n\nexport { AvbridgePlayerElement } from \"./element/avbridge-player.js\";\nexport type { AvbridgeVideoElement } from \"./element/avbridge-video.js\";\n\nif (!customElements.get(\"avbridge-player\")) {\n customElements.define(\"avbridge-player\", AvbridgePlayerElement);\n}\n"]}
1
+ {"version":3,"sources":["../src/events.ts","../src/probe/mediabunny.ts","../src/probe/index.ts","../src/util/codec-strings.ts","../src/classify/rules.ts","../src/diagnostics.ts","../src/plugins/registry.ts","../src/strategies/native.ts","../src/strategies/remux/mse.ts","../src/strategies/remux/pipeline.ts","../src/strategies/remux/index.ts","../src/strategies/fallback/video-renderer.ts","../src/strategies/fallback/audio-output.ts","../src/strategies/fallback/variant-routing.ts","../src/util/libav-demux.ts","../src/strategies/hybrid/decoder.ts","../src/util/time-ranges.ts","../src/strategies/hybrid/index.ts","../src/strategies/fallback/decoder.ts","../src/strategies/fallback/index.ts","../src/plugins/builtin.ts","../src/player.ts","../src/element/avbridge-video.ts","../src/element/player-styles.ts","../src/element/player-icons.ts","../src/element/avbridge-player.ts","../src/player-element.ts"],"names":["wallNow","frame","isDebug","drain","us","frames","normalizeSource","loadBridge","READY_AUDIO_BUFFER_SECONDS","READY_TIMEOUT_SECONDS","attachSubtitleTracks"],"mappings":"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A;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AA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","file":"player.js","sourcesContent":["/**\n * Tiny strongly-typed event emitter. We avoid pulling in eventemitter3 / mitt\n * because we only need a handful of methods and want zero deps.\n *\n * Supports \"sticky\" events via {@link TypedEmitter.emitSticky}: the last value\n * for that event is remembered, and any future `on()` subscriber receives it\n * immediately. This is the right pattern for one-shot state-snapshot events\n * like \"strategy chosen\" or \"player ready\" — callers that subscribe after the\n * event has already fired still need to react to it.\n */\n\nexport type Listener<T> = (payload: T) => void;\n\nexport class TypedEmitter<EventMap> {\n private listeners: { [K in keyof EventMap]?: Set<Listener<EventMap[K]>> } = {};\n private sticky: { [K in keyof EventMap]?: EventMap[K] } = {};\n\n on<K extends keyof EventMap>(event: K, fn: Listener<EventMap[K]>): () => void {\n let set = this.listeners[event];\n if (!set) {\n set = new Set();\n this.listeners[event] = set;\n }\n set.add(fn);\n\n // Replay any sticky value that's already been emitted for this event.\n if (Object.prototype.hasOwnProperty.call(this.sticky, event)) {\n try {\n fn(this.sticky[event] as EventMap[K]);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] listener threw replaying sticky value:\", err);\n }\n }\n\n return () => this.off(event, fn);\n }\n\n off<K extends keyof EventMap>(event: K, fn: Listener<EventMap[K]>): void {\n this.listeners[event]?.delete(fn);\n }\n\n emit<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {\n const set = this.listeners[event];\n if (!set) return;\n // Snapshot so listeners can unsubscribe themselves.\n for (const fn of [...set]) {\n try {\n fn(payload);\n } catch (err) {\n // Don't let one bad listener break the others.\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] listener threw:\", err);\n }\n }\n }\n\n /**\n * Like {@link emit} but also remembers the value so future subscribers\n * receive it on `on()`. Use for one-shot state-snapshot events.\n */\n emitSticky<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {\n this.sticky[event] = payload;\n this.emit(event, payload);\n }\n\n removeAll(): void {\n this.listeners = {};\n this.sticky = {};\n }\n}\n","import type {\n AudioCodec,\n AudioTrackInfo,\n ContainerKind,\n MediaContext,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport type { NormalizedSource } from \"../util/source.js\";\n\n/**\n * Probe via mediabunny. Built against the real (typed) API exported by\n * `mediabunny.d.ts`:\n *\n * - `Input.getTracks()` returns `InputTrack[]`; each track has `isVideoTrack()`\n * / `isAudioTrack()` type guards plus a `codec` getter that returns one of\n * the enum strings (`\"avc\"|\"hevc\"|\"vp9\"|\"vp8\"|\"av1\"` for video,\n * `\"aac\"|\"opus\"|...` for audio).\n * - For decoder metadata + codec parameter strings we call\n * `getDecoderConfig()` and `getCodecParameterString()` on the typed track.\n *\n * The bridging back to avbridge's own codec naming (`h264` instead of mediabunny's\n * `avc`) happens here so the rest of the codebase keeps a single vocabulary.\n */\nexport async function probeWithMediabunny(\n source: NormalizedSource,\n sniffedContainer: ContainerKind,\n): Promise<MediaContext> {\n const mb = await import(\"mediabunny\");\n const input = new mb.Input({\n source: await buildMediabunnySource(mb, source),\n formats: mb.ALL_FORMATS,\n });\n\n const allTracks = await input.getTracks();\n const duration = await safeNumber(() => input.computeDuration());\n\n const videoTracks: VideoTrackInfo[] = [];\n const audioTracks: AudioTrackInfo[] = [];\n\n for (const track of allTracks) {\n if (track.isVideoTrack()) {\n const codecParam = await safe(() => track.getCodecParameterString());\n videoTracks.push({\n id: track.id,\n codec: mediabunnyVideoToAvbridge(track.codec),\n width: track.displayWidth ?? track.codedWidth ?? 0,\n height: track.displayHeight ?? track.codedHeight ?? 0,\n codecString: codecParam ?? undefined,\n });\n } else if (track.isAudioTrack()) {\n const codecParam = await safe(() => track.getCodecParameterString());\n audioTracks.push({\n id: track.id,\n codec: mediabunnyAudioToAvbridge(track.codec),\n channels: track.numberOfChannels ?? 0,\n sampleRate: track.sampleRate ?? 0,\n language: track.languageCode,\n codecString: codecParam ?? undefined,\n });\n }\n }\n\n const format = await safe(() => input.getFormat());\n const container = resolveContainer(format?.name, sniffedContainer);\n\n return {\n source: source.original,\n name: source.name,\n byteLength: source.byteLength,\n container,\n videoTracks,\n audioTracks,\n subtitleTracks: [],\n probedBy: \"mediabunny\",\n duration,\n };\n}\n\n/**\n * Build the right mediabunny `Source` for a normalized input. URL sources\n * use `UrlSource` (Range requests, prefetch, parallelism) so we don't\n * buffer the whole file into memory. Blob/File sources use `BlobSource`.\n *\n * Exported so the remux strategy can use the same routing logic.\n */\nexport async function buildMediabunnySource(\n mb: typeof import(\"mediabunny\"),\n source: NormalizedSource,\n): Promise<InstanceType<typeof mb.BlobSource> | InstanceType<typeof mb.UrlSource>> {\n if (source.kind === \"url\") {\n return new mb.UrlSource(source.url);\n }\n return new mb.BlobSource(source.blob);\n}\n\n/**\n * Build a mediabunny `Source` directly from a raw `MediaInput`, bypassing\n * `normalizeSource`. Used by strategies that already have the original\n * input on hand (via `MediaContext.source`) and don't need a sniff window.\n *\n * This is the routing point that decides \"stream from URL via Range\n * requests\" vs \"wrap in-memory bytes as BlobSource\". Always prefer\n * `UrlSource` for URL inputs so we don't accidentally buffer the file.\n */\nexport async function buildMediabunnySourceFromInput(\n mb: typeof import(\"mediabunny\"),\n source: import(\"../types.js\").MediaInput,\n): Promise<InstanceType<typeof mb.BlobSource> | InstanceType<typeof mb.UrlSource>> {\n if (typeof source === \"string\") return new mb.UrlSource(source);\n if (source instanceof URL) return new mb.UrlSource(source.toString());\n if (source instanceof Blob) return new mb.BlobSource(source);\n if (source instanceof ArrayBuffer) return new mb.BlobSource(new Blob([source]));\n if (source instanceof Uint8Array) return new mb.BlobSource(new Blob([source as BlobPart]));\n throw new TypeError(\"unsupported source type for mediabunny\");\n}\n\nfunction resolveContainer(formatName: string | undefined, sniffed: ContainerKind): ContainerKind {\n const name = (formatName ?? \"\").toLowerCase();\n if (name.includes(\"matroska\") || name.includes(\"mkv\")) return \"mkv\";\n if (name.includes(\"webm\")) return \"webm\";\n if (name.includes(\"mp4\") || name.includes(\"isom\")) return \"mp4\";\n if (name.includes(\"mov\") || name.includes(\"quicktime\")) return \"mov\";\n if (name.includes(\"ogg\")) return \"ogg\";\n if (name.includes(\"wav\")) return \"wav\";\n if (name.includes(\"flac\")) return \"flac\";\n if (name.includes(\"mp3\")) return \"mp3\";\n if (name.includes(\"adts\") || name.includes(\"aac\")) return \"adts\";\n if (name.includes(\"mpegts\") || name.includes(\"mpeg-ts\") || name.includes(\"transport\")) return \"mpegts\";\n return sniffed;\n}\n\n/** Mediabunny video codec → avbridge video codec. */\nexport function mediabunnyVideoToAvbridge(c: string | null | undefined): VideoCodec {\n switch (c) {\n case \"avc\": return \"h264\";\n case \"hevc\": return \"h265\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n default:\n // Preserve the original codec string when mediabunny gave us something\n // we don't recognize. The classifier checks `NATIVE_VIDEO_CODECS.has()`\n // and routes anything outside that set through the fallback chain — so\n // returning the unknown name (instead of silently relabeling it as\n // \"h264\") gets correct routing AND honest diagnostics.\n return c ? (c as VideoCodec) : \"unknown\";\n }\n}\n\n/** avbridge video codec → mediabunny video codec (for output sources). */\nexport function avbridgeVideoToMediabunny(c: VideoCodec): \"avc\" | \"hevc\" | \"vp9\" | \"vp8\" | \"av1\" | null {\n switch (c) {\n case \"h264\": return \"avc\";\n case \"h265\": return \"hevc\";\n case \"vp8\": return \"vp8\";\n case \"vp9\": return \"vp9\";\n case \"av1\": return \"av1\";\n default: return null;\n }\n}\n\nexport function mediabunnyAudioToAvbridge(c: string | null | undefined): AudioCodec {\n switch (c) {\n case \"aac\": return \"aac\";\n case \"mp3\": return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n default: return c ? (c as AudioCodec) : \"unknown\";\n }\n}\n\nexport function avbridgeAudioToMediabunny(c: AudioCodec): string | null {\n switch (c) {\n case \"aac\": return \"aac\";\n case \"mp3\": return \"mp3\";\n case \"opus\": return \"opus\";\n case \"vorbis\": return \"vorbis\";\n case \"flac\": return \"flac\";\n case \"ac3\": return \"ac3\";\n case \"eac3\": return \"eac3\";\n default: return null;\n }\n}\n\nasync function safeNumber(fn: () => Promise<number> | number): Promise<number | undefined> {\n try {\n const v = await fn();\n return typeof v === \"number\" && Number.isFinite(v) ? v : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function safe<T>(fn: () => Promise<T> | T): Promise<T | undefined> {\n try { return await fn(); } catch { return undefined; }\n}\n","import type { ContainerKind, MediaContext, MediaInput, TransportConfig } from \"../types.js\";\nimport { normalizeSource, sniffNormalizedSource } from \"../util/source.js\";\nimport { probeWithMediabunny } from \"./mediabunny.js\";\nimport { AvbridgeError, ERR_PROBE_FAILED, ERR_PROBE_UNKNOWN_CONTAINER, ERR_LIBAV_NOT_REACHABLE } from \"../errors.js\";\n\n/** Containers mediabunny can demux. Sniff results outside this set go straight to libav. */\nconst MEDIABUNNY_CONTAINERS = new Set<ContainerKind>([\n \"mp4\",\n \"mov\",\n \"mkv\",\n \"webm\",\n \"ogg\",\n \"wav\",\n \"mp3\",\n \"flac\",\n \"adts\",\n \"mpegts\",\n]);\n\n/**\n * Probe a source and produce a {@link MediaContext}.\n *\n * Routing:\n * 1. Sniff the magic header. Cheap, deterministic, ignores file extensions.\n * 2. If the container is one mediabunny supports → try mediabunny first\n * (fast path — it's a single pass of WASM-free JS parsing). If mediabunny\n * throws (e.g. an assertion on an unsupported sample entry like `mp4v`\n * for MPEG-4 Part 2 in ISOBMFF, or an exotic MKV codec), fall through to\n * libav.js which handles the long tail of codecs mediabunny doesn't.\n * The combined-error case surfaces *both* failures so the user sees\n * which path each step took.\n * 3. If sniffing identifies AVI/ASF/FLV (or `unknown`) → libav.js directly.\n * mediabunny can't read those containers at all, so there's no fast path\n * to try.\n */\nexport async function probe(\n source: MediaInput,\n transport?: TransportConfig,\n): Promise<MediaContext> {\n const normalized = await normalizeSource(source, transport);\n const sniffed = await sniffNormalizedSource(normalized);\n\n if (MEDIABUNNY_CONTAINERS.has(sniffed)) {\n try {\n const result = await probeWithMediabunny(normalized, sniffed);\n // If mediabunny returned unknown codecs, try libav which recognizes\n // a wider range (DTS, TrueHD, etc.). Only escalate if there ARE\n // tracks with unknown codecs — otherwise mediabunny's result is fine.\n const hasUnknownCodec =\n result.videoTracks.some((t) => t.codec === \"unknown\") ||\n result.audioTracks.some((t) => t.codec === \"unknown\");\n if (hasUnknownCodec) {\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch {\n // libav also failed — return mediabunny's result (unknown codecs\n // are better than no result at all)\n return result;\n }\n }\n return result;\n } catch (mediabunnyErr) {\n // mediabunny rejected the file. Before giving up, try libav — it can\n // demux a much wider range of codec combinations in ISOBMFF/MKV/etc.\n // than mediabunny's pure-JS parser (e.g. mp4v, wmv3-in-asf, flac in\n // an MP4 container). This is \"escalation\", not \"masking\": if libav\n // also fails we surface both errors below.\n // eslint-disable-next-line no-console\n console.warn(\n `[avbridge] mediabunny rejected ${sniffed} file, falling back to libav:`,\n (mediabunnyErr as Error).message,\n );\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch (libavErr) {\n const mbMsg = (mediabunnyErr as Error).message || String(mediabunnyErr);\n const lvMsg = libavErr instanceof Error ? libavErr.message : String(libavErr);\n throw new AvbridgeError(\n ERR_PROBE_FAILED,\n `Failed to probe ${sniffed.toUpperCase()} file. mediabunny: ${mbMsg}. libav: ${lvMsg}.`,\n \"The file may be corrupt, truncated, or in an unsupported format. Enable AVBRIDGE_DEBUG for detailed logs.\",\n );\n }\n }\n }\n\n // sniffed === avi | asf | flv | unknown — try libav.\n try {\n const { probeWithLibav } = await import(\"./avi.js\");\n return await probeWithLibav(normalized, sniffed);\n } catch (err) {\n const inner = err instanceof Error ? err.message : String(err);\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] libav probe failed for\", sniffed, \"file:\", err);\n if (sniffed === \"unknown\") {\n throw new AvbridgeError(\n ERR_PROBE_UNKNOWN_CONTAINER,\n `Unable to probe source: container format could not be identified. libav fallback: ${inner || \"(no details)\"}`,\n \"The file may be corrupt or in a format avbridge doesn't recognize. Check the file plays in VLC or ffprobe.\",\n );\n }\n throw new AvbridgeError(\n ERR_LIBAV_NOT_REACHABLE,\n `${sniffed.toUpperCase()} files require libav.js, which failed to load: ${inner || \"(no details)\"}`,\n \"Install @libav.js/variant-webcodecs, or check that AVBRIDGE_LIBAV_BASE points to the correct path.\",\n );\n }\n}\n","import type { AudioTrackInfo, VideoTrackInfo } from \"../types.js\";\n\n/**\n * Build an RFC 6381 codec string for use with `MediaSource.isTypeSupported`\n * and `<source type=...>`. Returns null when we don't have enough info to\n * compose one — callers should treat that as \"ask the browser at runtime via\n * a different channel\" rather than guessing.\n */\nexport function videoCodecString(track: VideoTrackInfo): string | null {\n if (track.codecString) return track.codecString;\n switch (track.codec) {\n case \"h264\": {\n // avc1.PPCCLL — profile (1B), constraint (1B), level (1B). Default to\n // High Profile @ 4.0 if we don't know — common on real-world content.\n const profileHex = profileToHex(track.profile) ?? \"64\"; // 0x64 = High\n const constraint = \"00\";\n const level = ((track.level ?? 40) & 0xff).toString(16).padStart(2, \"0\");\n return `avc1.${profileHex}${constraint}${level}`;\n }\n case \"h265\":\n // Default Main Profile @ Level 4.1 (0x5d = 93) — `hvc1.1.6.L93.B0`.\n return \"hvc1.1.6.L93.B0\";\n case \"vp8\":\n return \"vp8\";\n case \"vp9\":\n return \"vp09.00.10.08\";\n case \"av1\":\n return \"av01.0.04M.08\";\n default:\n return null;\n }\n}\n\nfunction profileToHex(profile?: string): string | null {\n if (!profile) return null;\n const p = profile.toLowerCase();\n if (p.includes(\"baseline\")) return \"42\";\n if (p.includes(\"main\")) return \"4d\";\n if (p.includes(\"high 10\")) return \"6e\";\n if (p.includes(\"high 4:2:2\")) return \"7a\";\n if (p.includes(\"high 4:4:4\")) return \"f4\";\n if (p.includes(\"high\")) return \"64\";\n return null;\n}\n\nexport function audioCodecString(track: AudioTrackInfo): string | null {\n if (track.codecString) return track.codecString;\n switch (track.codec) {\n case \"aac\":\n return \"mp4a.40.2\"; // AAC-LC\n case \"mp3\":\n return \"mp4a.40.34\";\n case \"opus\":\n return \"opus\";\n case \"vorbis\":\n return \"vorbis\";\n case \"flac\":\n return \"flac\";\n default:\n return null;\n }\n}\n\n/**\n * Compose a `video/mp4; codecs=\"...\"` MIME for MSE. Returns null if either\n * codec string can't be produced — caller should fall back to remux refusal.\n */\nexport function mp4MimeFor(video: VideoTrackInfo, audio?: AudioTrackInfo): string | null {\n const v = videoCodecString(video);\n if (!v) return null;\n const codecs = audio ? `${v},${audioCodecString(audio) ?? \"\"}`.replace(/,$/, \"\") : v;\n return `video/mp4; codecs=\"${codecs}\"`;\n}\n\n/**\n * Wrap `MediaSource.isTypeSupported` so it returns false (instead of throwing)\n * in environments without MSE — e.g. jsdom under vitest.\n */\nexport function mseSupports(mime: string): boolean {\n if (typeof MediaSource === \"undefined\") return false;\n try {\n return MediaSource.isTypeSupported(mime);\n } catch {\n return false;\n }\n}\n","import type {\n AudioCodec,\n AudioTrackInfo,\n Classification,\n ContainerKind,\n MediaContext,\n StrategyName,\n VideoCodec,\n VideoTrackInfo,\n} from \"../types.js\";\nimport { mp4MimeFor, mseSupports } from \"../util/codec-strings.js\";\n\n/**\n * Codecs we know `<video>` and MSE support across modern desktop + Android.\n * The decision to remux instead of decode hinges on this list.\n */\n/** Codecs the browser can decode natively (also the set WebCodecs can transcode). */\nexport const NATIVE_VIDEO_CODECS = new Set<VideoCodec>([\"h264\", \"h265\", \"vp8\", \"vp9\", \"av1\"]);\nexport const NATIVE_AUDIO_CODECS = new Set<AudioCodec>([\n \"aac\",\n \"mp3\",\n \"opus\",\n \"vorbis\",\n \"flac\",\n]);\n\n/**\n * Codecs no major browser plays, period. These force the WASM fallback.\n */\nexport const FALLBACK_VIDEO_CODECS = new Set<VideoCodec>([\n \"wmv3\", \"vc1\", \"mpeg4\",\n \"rv10\", \"rv20\", \"rv30\", \"rv40\",\n \"mpeg2\", \"mpeg1\", \"theora\",\n \"dv\", \"hq_hqa\",\n \"rawvideo\", \"qtrle\", \"png\", \"vp6f\",\n]);\nexport const FALLBACK_AUDIO_CODECS = new Set<AudioCodec>([\n \"wmav2\", \"wmapro\", \"ac3\", \"eac3\",\n \"cook\", \"ra_144\", \"ra_288\", \"sipr\", \"atrac3\",\n \"dts\", \"truehd\",\n]);\n\n/**\n * Containers `<video>` plays directly. Anything else with otherwise-supported\n * codecs is a remux candidate — IF mediabunny can read the container.\n */\nconst NATIVE_CONTAINERS = new Set<ContainerKind>([\n \"mp4\",\n \"mov\",\n \"webm\",\n \"ogg\",\n \"wav\",\n \"mp3\",\n \"flac\",\n \"adts\",\n]);\n\n/**\n * Containers mediabunny can demux. The remux strategy feeds the source through\n * mediabunny → fMP4 → MSE, so the source container must be one mediabunny\n * understands. AVI, ASF, FLV are NOT in this set — mediabunny rejects them\n * with \"unsupported or unrecognizable format\". Files in those containers with\n * otherwise-native codecs (e.g. AVI + H.264 + MP3) must go to the fallback\n * strategy even though the *codecs* are browser-supported.\n *\n * MPEG-TS is in this set: mediabunny demuxes it natively, but browsers\n * cannot play `<video src=\"*.ts\">` directly (MPEG-TS is HLS-only), so even\n * a TS file with H.264 + AAC has to go through the remux path.\n */\nconst REMUXABLE_CONTAINERS = new Set<ContainerKind>([\n \"mp4\",\n \"mov\",\n \"mkv\",\n \"webm\",\n \"ogg\",\n \"wav\",\n \"mp3\",\n \"flac\",\n \"adts\",\n \"mpegts\",\n]);\n\n/**\n * Pure classification — no I/O, no async. Test-friendly.\n */\nexport function classifyContext(ctx: MediaContext): Classification {\n const video = ctx.videoTracks[0];\n const audio = ctx.audioTracks[0];\n\n // Audio-only files: mediabunny handles all the common ones natively.\n if (!video) {\n if (NATIVE_CONTAINERS.has(ctx.container) && (!audio || NATIVE_AUDIO_CODECS.has(audio.codec))) {\n return {\n class: \"NATIVE\",\n strategy: \"native\",\n reason: `audio-only ${ctx.container} with native codec`,\n };\n }\n if (audio && FALLBACK_AUDIO_CODECS.has(audio.codec)) {\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `audio codec \"${audio.codec}\" requires WASM decode`,\n };\n }\n if (REMUXABLE_CONTAINERS.has(ctx.container)) {\n return {\n class: \"REMUX_CANDIDATE\",\n strategy: \"remux\",\n reason: `audio-only file in non-native container \"${ctx.container}\"`,\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `audio-only file in \"${ctx.container}\" (not remuxable by mediabunny)`,\n };\n }\n\n // Video paths.\n if (FALLBACK_VIDEO_CODECS.has(video.codec)) {\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `video codec \"${video.codec}\" has no browser decoder; WASM fallback required`,\n };\n }\n // Audio codec needs WASM decode — either it's in the known fallback set\n // or it's unrecognized (\"unknown\" / not in native set). Unknown codecs\n // definitely can't play natively, so they get the same treatment.\n const audioNeedsFallback = audio && (\n FALLBACK_AUDIO_CODECS.has(audio.codec) ||\n !NATIVE_AUDIO_CODECS.has(audio.codec)\n );\n if (audioNeedsFallback) {\n // If the VIDEO codec is native, prefer hybrid (WebCodecs hardware video\n // decode + libav software audio decode) over full WASM fallback. This is\n // critical for Blu-ray MKVs: H.264 1080p in WASM is unwatchably slow,\n // but WebCodecs decodes it at full speed while libav handles the DTS/AC3\n // audio in software.\n if (NATIVE_VIDEO_CODECS.has(video.codec) && webCodecsAvailable()) {\n return {\n class: \"HYBRID_CANDIDATE\",\n strategy: \"hybrid\",\n reason: `video \"${video.codec}\" is hardware-decodable via WebCodecs; audio \"${audio.codec}\" decoded in software by libav`,\n fallbackChain: [\"fallback\"],\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `audio codec \"${audio.codec}\" has no browser decoder; WASM fallback required`,\n };\n }\n\n if (!NATIVE_VIDEO_CODECS.has(video.codec)) {\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `unknown video codec \"${video.codec}\", routing to fallback`,\n };\n }\n\n // Codecs are native. Now decide between NATIVE and REMUX based on the\n // container and codec quirks.\n const isNativeContainer = NATIVE_CONTAINERS.has(ctx.container);\n\n if (isNativeContainer && isSafeNativeCombo(video, audio)) {\n // Confirm with the browser when we have access to MediaSource.\n const mime = mp4MimeFor(video, audio);\n if (mime && mseSupports(mime)) {\n return {\n class: \"NATIVE\",\n strategy: \"native\",\n reason: `${ctx.container} + ${video.codec}${audio ? \"/\" + audio.codec : \"\"} plays natively`,\n };\n }\n if (mime == null || typeof MediaSource === \"undefined\") {\n // No MSE in this environment (e.g. tests) — trust the heuristic.\n return {\n class: \"NATIVE\",\n strategy: \"native\",\n reason: `${ctx.container} + ${video.codec}${audio ? \"/\" + audio.codec : \"\"} (heuristic native)`,\n };\n }\n }\n\n if (isNativeContainer && isRiskyNative(video)) {\n return {\n class: \"RISKY_NATIVE\",\n strategy: \"native\",\n reason: `${video.codec} ${video.profile ?? \"\"} ${video.bitDepth ?? 8}-bit may stutter on mobile; will escalate to remux on stall`,\n fallbackChain: [\"remux\", \"hybrid\", \"fallback\"],\n };\n }\n\n // Codecs are native but the container isn't. Can we remux?\n // Remuxing goes through mediabunny, which only supports certain containers.\n // AVI/ASF/FLV are NOT in that set — mediabunny rejects them at Input().\n if (REMUXABLE_CONTAINERS.has(ctx.container)) {\n // Feature-detect: the remux target is fragmented MP4 via MSE. If the\n // browser's MSE can't decode this codec combo (e.g. HEVC on\n // open-source Chromium — no proprietary codecs by design — or\n // future codec/container combos we haven't thought of), remux will\n // stall. Degrade gracefully: try hybrid (WebCodecs hardware decode)\n // or fallback (WASM software decode) without waiting for runtime\n // escalation.\n const mime = mp4MimeFor(video, audio);\n if (mime && typeof MediaSource !== \"undefined\" && !mseSupports(mime)) {\n if (webCodecsAvailable()) {\n return {\n class: \"HYBRID_CANDIDATE\",\n strategy: \"hybrid\",\n reason: `${ctx.container} container with ${video.codec}${audio ? \"/\" + audio.codec : \"\"}; MSE rejects the remux target mime — routing to WebCodecs hardware decode`,\n fallbackChain: [\"fallback\"],\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `${ctx.container} container with ${video.codec}${audio ? \"/\" + audio.codec : \"\"}; MSE rejects the remux target mime and WebCodecs is unavailable — falling back to WASM decode`,\n };\n }\n // Give REMUX_CANDIDATE a fallback chain so the runtime stall / decode\n // supervisors have somewhere to escalate to when MSE lies about codec\n // support (the Firefox HEVC case — audio plays, video never paints).\n // The initial pick is still remux; these only engage on stall.\n const fallbackChain: StrategyName[] = webCodecsAvailable()\n ? [\"hybrid\", \"fallback\"]\n : [\"fallback\"];\n return {\n class: \"REMUX_CANDIDATE\",\n strategy: \"remux\",\n reason: `${ctx.container} container with native-supported codecs — remux to fragmented MP4 for reliable playback`,\n fallbackChain,\n };\n }\n\n // Container is unreadable by mediabunny (AVI, ASF, FLV, etc.) but codecs\n // are browser-supported. Use the hybrid strategy (libav demux + WebCodecs\n // hardware decode) when WebCodecs is available; otherwise full WASM decode.\n if (webCodecsAvailable()) {\n return {\n class: \"HYBRID_CANDIDATE\",\n strategy: \"hybrid\",\n reason: `${ctx.container} container requires libav demux; codecs (${video.codec}${audio ? \"/\" + audio.codec : \"\"}) are hardware-decodable via WebCodecs`,\n fallbackChain: [\"fallback\"],\n };\n }\n return {\n class: \"FALLBACK_REQUIRED\",\n strategy: \"fallback\",\n reason: `${ctx.container} container cannot be remuxed by mediabunny; falling back to WASM decode (${video.codec}${audio ? \"/\" + audio.codec : \"\"})`,\n };\n}\n\nfunction webCodecsAvailable(): boolean {\n return typeof globalThis.VideoDecoder !== \"undefined\";\n}\n\nfunction isSafeNativeCombo(video: VideoTrackInfo, audio?: AudioTrackInfo): boolean {\n if (video.codec === \"h264\") {\n // 8-bit yuv420p H.264 is the safe combo. Hi10P / 4:2:2 / 4:4:4 are not.\n if (video.bitDepth && video.bitDepth > 8) return false;\n if (video.pixelFormat && !/yuv420p$/.test(video.pixelFormat)) return false;\n }\n if (audio && !NATIVE_AUDIO_CODECS.has(audio.codec)) return false;\n return true;\n}\n\nfunction isRiskyNative(video: VideoTrackInfo): boolean {\n if (video.bitDepth && video.bitDepth > 8) return true;\n if (video.pixelFormat && /yuv4(2[24]|44)/.test(video.pixelFormat)) return true;\n if (video.width > 3840 || video.height > 2160) return true;\n if (video.fps && video.fps > 60) return true;\n return false;\n}\n","import type {\n Classification,\n DiagnosticsSnapshot,\n MediaContext,\n StrategyName,\n} from \"./types.js\";\n\n/**\n * Accumulates diagnostic info as the player walks probe → classify → play.\n * `snapshot()` produces an immutable view shaped exactly like the example in\n * design doc §12.\n */\nexport class Diagnostics {\n private container: DiagnosticsSnapshot[\"container\"] = \"unknown\";\n private videoCodec?: DiagnosticsSnapshot[\"videoCodec\"];\n private audioCodec?: DiagnosticsSnapshot[\"audioCodec\"];\n private width?: number;\n private height?: number;\n private fps?: number;\n private duration?: number;\n private strategy: DiagnosticsSnapshot[\"strategy\"] = \"pending\";\n private strategyClass: DiagnosticsSnapshot[\"strategyClass\"] = \"pending\";\n private reason = \"\";\n private probedBy?: DiagnosticsSnapshot[\"probedBy\"];\n private sourceType?: DiagnosticsSnapshot[\"sourceType\"];\n private transport?: DiagnosticsSnapshot[\"transport\"];\n private rangeSupported?: DiagnosticsSnapshot[\"rangeSupported\"];\n private runtime: Record<string, unknown> = {};\n private lastError?: Error;\n private strategyHistory: Array<{ strategy: StrategyName; reason: string; at: number }> = [];\n\n recordProbe(ctx: MediaContext): void {\n this.container = ctx.container;\n this.probedBy = ctx.probedBy;\n this.duration = ctx.duration;\n const v = ctx.videoTracks[0];\n if (v) {\n this.videoCodec = v.codec;\n this.width = v.width;\n this.height = v.height;\n this.fps = v.fps;\n }\n const a = ctx.audioTracks[0];\n if (a) this.audioCodec = a.codec;\n // Source-type detection. For blob inputs we know the transport with\n // certainty. For URL inputs we know the *intended* transport but not\n // whether the server actually honors Range — that's confirmed later by\n // the strategy that fetches the bytes (via {@link recordTransport}).\n const src = ctx.source;\n if (typeof src === \"string\" || src instanceof URL) {\n this.sourceType = \"url\";\n this.transport = \"http-range\";\n // Intentionally NOT setting rangeSupported here. Inferring \"true\" from\n // input type was misleading: native/remux URL paths rely on the\n // browser's or mediabunny's own Range handling and don't fail-fast on\n // a non-supporting server. Strategies that prove Range support call\n // recordTransport() once they have a confirmed answer.\n this.rangeSupported = undefined;\n } else {\n this.sourceType = \"blob\";\n this.transport = \"memory\";\n this.rangeSupported = false;\n }\n }\n\n /**\n * Called by a strategy once it has a confirmed answer about how the\n * source bytes are actually flowing (e.g. after the libav HTTP block\n * reader's initial Range probe succeeded). Lets diagnostics report the\n * truth instead of an input-type heuristic.\n */\n recordTransport(\n transport: NonNullable<DiagnosticsSnapshot[\"transport\"]>,\n rangeSupported: boolean,\n ): void {\n this.transport = transport;\n this.rangeSupported = rangeSupported;\n }\n\n recordClassification(c: Classification): void {\n this.strategy = c.strategy;\n this.strategyClass = c.class;\n this.reason = c.reason;\n }\n\n recordRuntime(stats: Record<string, unknown>): void {\n // Strategies can surface confirmed transport info in their runtime\n // stats under the well-known `_transport` / `_rangeSupported` keys.\n // When present, they're hoisted to the typed fields via\n // recordTransport() and stripped from the generic runtime bag so they\n // don't duplicate.\n const {\n _transport,\n _rangeSupported,\n ...rest\n } = stats as Record<string, unknown> & {\n _transport?: NonNullable<DiagnosticsSnapshot[\"transport\"]>;\n _rangeSupported?: boolean;\n };\n if (_transport != null && typeof _rangeSupported === \"boolean\") {\n this.recordTransport(_transport, _rangeSupported);\n }\n this.runtime = { ...this.runtime, ...rest };\n }\n\n recordStrategySwitch(strategy: StrategyName, reason: string): void {\n this.strategy = strategy;\n this.reason = reason;\n this.strategyHistory.push({ strategy, reason, at: Date.now() });\n }\n\n recordError(err: Error): void {\n this.lastError = err;\n }\n\n snapshot(): DiagnosticsSnapshot {\n const snap: DiagnosticsSnapshot = {\n container: this.container,\n videoCodec: this.videoCodec,\n audioCodec: this.audioCodec,\n width: this.width,\n height: this.height,\n fps: this.fps,\n duration: this.duration,\n strategy: this.strategy,\n strategyClass: this.strategyClass,\n reason: this.reason,\n probedBy: this.probedBy,\n sourceType: this.sourceType,\n transport: this.transport,\n rangeSupported: this.rangeSupported,\n runtime: { ...this.runtime, ...(this.lastError ? { error: this.lastError.message } : {}) },\n strategyHistory: this.strategyHistory.length > 0 ? [...this.strategyHistory] : undefined,\n };\n return Object.freeze(snap);\n }\n}\n","import type { MediaContext, Plugin, StrategyName } from \"../types.js\";\n\n/**\n * Plugin registry. Built-in strategies are registered as plugins so that\n * user-supplied plugins can preempt them. The registry is consulted twice:\n * once by the player layer to find a plugin matching the picked strategy, and\n * (optionally) by classification to ask plugins what they support.\n */\nexport class PluginRegistry {\n private plugins: Plugin[] = [];\n\n register(plugin: Plugin, prepend = false): void {\n if (prepend) this.plugins.unshift(plugin);\n else this.plugins.push(plugin);\n }\n\n all(): readonly Plugin[] {\n return this.plugins;\n }\n\n /**\n * Find the first plugin that claims this context AND its name matches the\n * strategy. Built-in strategy plugins are named exactly `\"native\"`,\n * `\"remux\"`, `\"fallback\"`.\n */\n findFor(context: MediaContext, strategy: StrategyName): Plugin | null {\n for (const p of this.plugins) {\n if (p.name === strategy && p.canHandle(context)) return p;\n }\n return null;\n }\n}\n","import type { MediaContext, PlaybackSession } from \"../types.js\";\n\n/**\n * Simplest strategy: hand the source to the browser. Works for any\n * MP4/WebM/MP3/etc. that the user agent already plays.\n *\n * The only complexity is that the source might be a `File`/`Blob` (use\n * `URL.createObjectURL`), an `ArrayBuffer`/`Uint8Array` (wrap in a Blob first),\n * or a string URL (assign directly).\n */\nexport async function createNativeSession(\n context: MediaContext,\n video: HTMLVideoElement,\n): Promise<PlaybackSession> {\n const { url, revoke } = sourceToVideoUrl(context.source);\n video.src = url;\n\n // Wait for metadata so the player resolves only once playback is actually\n // ready. We expose errors via the player's \"error\" event, not by throwing\n // here, because failure here often means we should escalate to remux.\n await new Promise<void>((resolve, reject) => {\n const onMeta = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(new Error(`<video> failed to load: ${video.error?.message ?? \"unknown\"}`));\n };\n const cleanup = () => {\n video.removeEventListener(\"loadedmetadata\", onMeta);\n video.removeEventListener(\"error\", onError);\n };\n video.addEventListener(\"loadedmetadata\", onMeta);\n video.addEventListener(\"error\", onError);\n });\n\n let stats = { framesDecoded: 0, framesDropped: 0 };\n\n return {\n strategy: \"native\",\n async play() {\n await video.play();\n },\n pause() {\n video.pause();\n },\n async seek(time) {\n video.currentTime = time;\n },\n async setAudioTrack(id) {\n // HTMLMediaElement.audioTracks isn't exposed on all browsers (Chrome\n // needs the MediaCapabilities flag for many containers). Best-effort:\n // try by string id match first, then by index. If the list doesn't\n // exist, silently no-op — the user will still hear whatever track the\n // browser picked by default.\n const tracks = (video as unknown as { audioTracks?: { length: number; [i: number]: { id: string; enabled: boolean } } }).audioTracks;\n if (!tracks || tracks.length === 0) return;\n for (let i = 0; i < tracks.length; i++) {\n tracks[i].enabled = tracks[i].id === String(id) || i === id;\n }\n },\n async setSubtitleTrack(id) {\n const tracks = video.textTracks;\n for (let i = 0; i < tracks.length; i++) {\n tracks[i].mode = i === id ? \"showing\" : \"disabled\";\n }\n },\n async destroy() {\n video.pause();\n video.removeAttribute(\"src\");\n video.load();\n revoke?.();\n },\n getCurrentTime() {\n return video.currentTime || 0;\n },\n getRuntimeStats() {\n // getVideoPlaybackQuality is the standard hook; not all UAs implement it.\n const q = (video as unknown as { getVideoPlaybackQuality?: () => VideoPlaybackQuality }).getVideoPlaybackQuality?.();\n if (q) {\n stats = {\n framesDecoded: q.totalVideoFrames,\n framesDropped: q.droppedVideoFrames,\n };\n }\n return { ...stats, decoderType: \"native\" };\n },\n };\n}\n\nfunction sourceToVideoUrl(source: unknown): { url: string; revoke?: () => void } {\n if (source instanceof Blob) {\n const url = URL.createObjectURL(source);\n return { url, revoke: () => URL.revokeObjectURL(url) };\n }\n if (source instanceof ArrayBuffer || source instanceof Uint8Array) {\n const blob = new Blob([source as BlobPart]);\n const url = URL.createObjectURL(blob);\n return { url, revoke: () => URL.revokeObjectURL(url) };\n }\n if (typeof source === \"string\") return { url: source };\n if (source instanceof URL) return { url: source.toString() };\n throw new TypeError(\"native strategy: unsupported source type\");\n}\n\ninterface VideoPlaybackQuality {\n totalVideoFrames: number;\n droppedVideoFrames: number;\n}\n","/**\n * MediaSource Extensions plumbing. Wraps a `MediaSource` + single\n * `SourceBuffer` with an append queue that respects `updateend` backpressure.\n */\n\nimport { AvbridgeError, ERR_MSE_NOT_SUPPORTED, ERR_MSE_CODEC_NOT_SUPPORTED } from \"../../errors.js\";\n\nexport interface MseSinkOptions {\n mime: string;\n video: HTMLVideoElement;\n /** Called once the MediaSource is open and ready for appends. */\n onReady?: () => void;\n}\n\nexport class MseSink {\n private mediaSource: MediaSource;\n private sourceBuffer: SourceBuffer | null = null;\n private queue: ArrayBuffer[] = [];\n private endOfStreamCalled = false;\n private destroyed = false;\n private readyPromise: Promise<void>;\n private resolveReady!: () => void;\n private rejectReady!: (err: Error) => void;\n private objectUrl: string;\n\n constructor(private readonly options: MseSinkOptions) {\n if (typeof MediaSource === \"undefined\") {\n throw new AvbridgeError(\n ERR_MSE_NOT_SUPPORTED,\n \"MediaSource Extensions (MSE) are not supported in this environment.\",\n \"MSE is required for the remux strategy. Use a browser that supports MSE, or try the fallback strategy.\",\n );\n }\n if (!MediaSource.isTypeSupported(options.mime)) {\n throw new AvbridgeError(\n ERR_MSE_CODEC_NOT_SUPPORTED,\n `This browser's MSE does not support \"${options.mime}\".`,\n \"The codec combination can't be played via remux in this browser. The player will try the next strategy automatically.\",\n );\n }\n\n this.mediaSource = new MediaSource();\n this.objectUrl = URL.createObjectURL(this.mediaSource);\n options.video.src = this.objectUrl;\n\n this.readyPromise = new Promise((resolve, reject) => {\n this.resolveReady = resolve;\n this.rejectReady = reject;\n });\n\n this.mediaSource.addEventListener(\"sourceopen\", () => {\n try {\n this.sourceBuffer = this.mediaSource.addSourceBuffer(options.mime);\n this.sourceBuffer.mode = \"segments\";\n this.sourceBuffer.addEventListener(\"updateend\", () => this.pump());\n this.resolveReady();\n options.onReady?.();\n } catch (err) {\n this.rejectReady(err instanceof Error ? err : new Error(String(err)));\n }\n });\n }\n\n ready(): Promise<void> {\n return this.readyPromise;\n }\n\n /** Queue a chunk of fMP4 bytes (init segment or media segment). */\n append(chunk: ArrayBuffer | Uint8Array): void {\n if (this.destroyed) return;\n const ab = chunk instanceof Uint8Array\n ? (chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength) as ArrayBuffer)\n : chunk;\n this.queue.push(ab);\n this.pump();\n }\n\n private pump(): void {\n const sb = this.sourceBuffer;\n if (!sb || sb.updating) return;\n\n // Apply deferred actions once the SourceBuffer has any data. Deferred\n // seek and deferred autoplay are independent — both can fire here, or\n // either alone. Setting `currentTime` before data exists causes the\n // browser to snap back to the nearest buffered range; calling `play()`\n // before data exists puts the video into a stuck waiting state.\n if (sb.buffered.length > 0) {\n if (this.pendingSeekTime !== null) {\n this.options.video.currentTime = this.pendingSeekTime;\n this.pendingSeekTime = null;\n } else if (!this.hasSnappedToFirstBuffered) {\n // First data arrival with no pending seek. If currentTime is\n // outside the first buffered range (typical for MPEG-TS sources\n // whose PTS doesn't start at 0), snap into the buffered range\n // so the video element doesn't wait forever for nonexistent data.\n const v = this.options.video;\n const firstStart = sb.buffered.start(0);\n const firstEnd = sb.buffered.end(0);\n if (v.currentTime < firstStart || v.currentTime > firstEnd) {\n v.currentTime = firstStart;\n }\n this.hasSnappedToFirstBuffered = true;\n }\n if (this.playOnSeek) {\n this.playOnSeek = false;\n this.options.video.play().catch(() => { /* ignore — autoplay may be blocked */ });\n }\n }\n\n const next = this.queue.shift();\n if (!next) return;\n try {\n sb.appendBuffer(next);\n } catch (err) {\n // QuotaExceededError → evict the oldest few seconds and retry once.\n if ((err as DOMException).name === \"QuotaExceededError\") {\n this.evict();\n try {\n sb.appendBuffer(next);\n return;\n } catch {\n /* fall through to error */\n }\n }\n this.rejectReady(err instanceof Error ? err : new Error(String(err)));\n }\n }\n\n private evict(): void {\n const sb = this.sourceBuffer;\n if (!sb || sb.buffered.length === 0) return;\n const start = sb.buffered.start(0);\n const current = this.options.video.currentTime;\n // Drop everything that's at least 10s behind the current position.\n if (current - start > 10) {\n try {\n sb.remove(start, current - 10);\n } catch {\n /* ignore */\n }\n }\n }\n\n /** Indicate the source is finished. Future seeks past the end will fail. */\n endOfStream(): void {\n if (this.endOfStreamCalled || this.destroyed) return;\n this.endOfStreamCalled = true;\n const tryEnd = () => {\n if (this.queue.length > 0 || this.sourceBuffer?.updating) {\n // Wait for the queue to drain.\n this.sourceBuffer?.addEventListener(\"updateend\", tryEnd, { once: true });\n return;\n }\n try {\n if (this.mediaSource.readyState === \"open\") {\n this.mediaSource.endOfStream();\n }\n } catch {\n /* ignore */\n }\n };\n tryEnd();\n }\n\n /** Seconds of media buffered ahead of the current playback position. */\n bufferedAhead(): number {\n const sb = this.sourceBuffer;\n if (!sb || sb.buffered.length === 0) return 0;\n const current = this.options.video.currentTime;\n for (let i = 0; i < sb.buffered.length; i++) {\n if (sb.buffered.start(i) <= current && sb.buffered.end(i) > current) {\n return sb.buffered.end(i) - current;\n }\n }\n return 0;\n }\n\n /** Total seconds of media buffered across all ranges. */\n totalBuffered(): number {\n const sb = this.sourceBuffer;\n if (!sb || sb.buffered.length === 0) return 0;\n let total = 0;\n for (let i = 0; i < sb.buffered.length; i++) {\n total += sb.buffered.end(i) - sb.buffered.start(i);\n }\n return total;\n }\n\n /** Number of chunks waiting in the append queue. */\n queueLength(): number {\n return this.queue.length;\n }\n\n /** Time to seek to once the SourceBuffer has data at this position. */\n private pendingSeekTime: number | null = null;\n /** Whether to resume playback after the deferred seek completes. */\n private playOnSeek = false;\n /**\n * On the very first data arrival, if `currentTime` falls outside the first\n * buffered range, snap it to the start of that range. MPEG-TS sources\n * commonly start their PTS at a non-zero value (e.g. ~1.5s); without this\n * snap, the video element sits at `currentTime=0` waiting forever for\n * data that doesn't exist.\n */\n private hasSnappedToFirstBuffered = false;\n\n /** Request that playback resumes automatically once the deferred seek fires. */\n setPlayOnSeek(play: boolean): void {\n this.playOnSeek = play;\n }\n\n /**\n * Discard all buffered media and schedule a deferred seek. The actual\n * `video.currentTime` assignment happens in `pump()` once the SourceBuffer\n * has data at the target position — setting it earlier causes the browser\n * to snap back to the nearest buffered range.\n */\n invalidate(seekTime: number): void {\n const sb = this.sourceBuffer;\n // Clear the pending queue — stale fragments from the old pump position.\n this.queue = [];\n this.pendingSeekTime = seekTime;\n this.hasSnappedToFirstBuffered = true; // explicit seek overrides the auto-snap\n if (!sb || sb.buffered.length === 0) return;\n try {\n const start = sb.buffered.start(0);\n const end = sb.buffered.end(sb.buffered.length - 1);\n sb.remove(start, end);\n } catch {\n /* ignore — sourcebuffer may be in updating state */\n }\n }\n\n destroy(): void {\n this.destroyed = true;\n this.queue = [];\n try {\n if (this.mediaSource.readyState === \"open\") this.mediaSource.endOfStream();\n } catch {\n /* ignore */\n }\n URL.revokeObjectURL(this.objectUrl);\n }\n}\n","import type { MediaContext } from \"../../types.js\";\nimport { MseSink } from \"./mse.js\";\nimport {\n avbridgeVideoToMediabunny,\n avbridgeAudioToMediabunny,\n buildMediabunnySourceFromInput,\n} from \"../../probe/mediabunny.js\";\n\n/**\n * Remux pipeline built against mediabunny's real API.\n *\n * Key design notes:\n *\n * - mediabunny's fMP4 muxer is a streaming muxer that requires monotonically\n * increasing timestamps. It cannot accept out-of-order packets after a seek.\n * Therefore, on each seek we create a **fresh** Output + sources + StreamTarget.\n * The MseSink handles the SourceBuffer reset via `invalidate()`.\n *\n * - Backpressure is enforced at two levels: in the WritableStream write handler\n * (limits append queue depth and total buffered time) and in the pump loop\n * (limits buffered-ahead and total buffered time). Without this, long files\n * dump gigabytes into the SourceBuffer and exhaust memory.\n */\nexport interface RemuxPipeline {\n start(fromTime?: number, autoPlay?: boolean): Promise<void>;\n seek(time: number, autoPlay?: boolean): Promise<void>;\n /** Update the autoplay intent mid-flight — used when play() arrives after seek() but before the MseSink has been constructed. */\n setAutoPlay(autoPlay: boolean): void;\n /**\n * Switch the active audio track. Tears down the current Output, rebuilds\n * with the new audio source, and resumes pumping at the given time.\n */\n setAudioTrack(trackId: number, timeSec: number, autoPlay: boolean): Promise<void>;\n destroy(): Promise<void>;\n stats(): Record<string, unknown>;\n}\n\nexport async function createRemuxPipeline(\n ctx: MediaContext,\n video: HTMLVideoElement,\n): Promise<RemuxPipeline> {\n const mb = await import(\"mediabunny\");\n\n const videoTrackInfo = ctx.videoTracks[0];\n if (!videoTrackInfo) throw new Error(\"remux: source has no video track\");\n\n // Map avbridge codec names back to mediabunny's enum strings.\n const mbVideoCodec = avbridgeVideoToMediabunny(videoTrackInfo.codec);\n if (!mbVideoCodec) {\n throw new Error(`remux: video codec \"${videoTrackInfo.codec}\" is not supported by mediabunny output`);\n }\n\n // Open the input. URL sources go through mediabunny's UrlSource so the\n // muxer streams via Range requests instead of buffering the whole file.\n const input = new mb.Input({\n source: await buildMediabunnySourceFromInput(mb, ctx.source),\n formats: mb.ALL_FORMATS,\n });\n const allTracks = await input.getTracks();\n const inputVideo = allTracks.find((t) => t.id === videoTrackInfo.id && t.isVideoTrack());\n if (!inputVideo || !inputVideo.isVideoTrack()) {\n throw new Error(\"remux: video track not found in input\");\n }\n\n // Pull the video WebCodecs decoder config once — used as `meta` on the\n // first packet after every Output rebuild.\n const videoConfig = await inputVideo.getDecoderConfig();\n\n // Packet sink for video — reused across seeks.\n const videoSink = new mb.EncodedPacketSink(inputVideo);\n\n // Audio selection is mutable: setAudioTrack() can swap it. The selected\n // audio derived state (input track, codec, sink, config) is rebuilt via\n // rebuildAudio() whenever the id changes.\n type InputAudioTrack = InstanceType<typeof mb.InputAudioTrack>;\n type AudioDecCfg = Awaited<ReturnType<InputAudioTrack[\"getDecoderConfig\"]>>;\n\n let selectedAudioTrackId: number | null = ctx.audioTracks[0]?.id ?? null;\n let inputAudio: InputAudioTrack | null = null;\n let mbAudioCodec: ReturnType<typeof avbridgeAudioToMediabunny> | null = null;\n let audioSink: InstanceType<typeof mb.EncodedPacketSink> | null = null;\n let audioConfig: AudioDecCfg | null = null;\n\n async function rebuildAudio(): Promise<void> {\n if (selectedAudioTrackId == null) {\n inputAudio = null;\n mbAudioCodec = null;\n audioSink = null;\n audioConfig = null;\n return;\n }\n const trackInfo = ctx.audioTracks.find((t) => t.id === selectedAudioTrackId);\n if (!trackInfo) {\n throw new Error(`remux: no audio track with id ${selectedAudioTrackId}`);\n }\n const newInput = allTracks.find((t) => t.id === trackInfo.id && t.isAudioTrack());\n if (!newInput || !newInput.isAudioTrack()) {\n throw new Error(\"remux: audio track not found in input\");\n }\n inputAudio = newInput;\n mbAudioCodec = avbridgeAudioToMediabunny(trackInfo.codec);\n audioSink = new mb.EncodedPacketSink(newInput);\n audioConfig = await newInput.getDecoderConfig();\n }\n\n await rebuildAudio();\n\n // MSE sink — created lazily on first output write, reused across seeks.\n let sink: MseSink | null = null;\n const stats = { videoPackets: 0, audioPackets: 0, bytesWritten: 0, fragments: 0 };\n\n let destroyed = false;\n let pumpToken = 0;\n let pendingAutoPlay = false;\n let pendingStartTime = 0;\n\n // The current Output instance. Recreated on each seek because mediabunny's\n // fMP4 muxer requires monotonically increasing timestamps.\n let currentOutput: InstanceType<typeof mb.Output> | null = null;\n\n /**\n * Create a fresh mediabunny Output wired to the MSE sink. Called once at\n * start and again on each seek.\n */\n function createOutput() {\n // Cancel the previous output if it exists.\n if (currentOutput) {\n try { void currentOutput.cancel(); } catch { /* ignore */ }\n }\n\n let mimePromise: Promise<string> | null = null;\n // Capture the active pump token at the moment this output was created.\n // A subsequent seek bumps `pumpToken`, and any in-flight write from this\n // (now-stale) output must drop its chunk instead of appending to the\n // SourceBuffer — otherwise stale fragments land at their original\n // timestamps, the deferred seek applies against the wrong buffered\n // range, and the video snaps to the end of the stale range.\n const myToken = pumpToken;\n\n const writable = new WritableStream<{\n type: \"write\";\n data: Uint8Array<ArrayBuffer>;\n position: number;\n }>({\n write: async (chunk) => {\n if (destroyed || pumpToken !== myToken) return;\n if (!sink) {\n const mime = await (mimePromise ??= output.getMimeType());\n if (destroyed || pumpToken !== myToken) return;\n sink = new MseSink({ mime, video });\n await sink.ready();\n if (destroyed || pumpToken !== myToken) return;\n // Apply deferred seek + autoPlay for the initial start.\n if (pendingStartTime > 0) {\n sink.invalidate(pendingStartTime);\n }\n sink.setPlayOnSeek(pendingAutoPlay);\n }\n // Backpressure: wait for the SourceBuffer append queue to drain.\n while (sink && !destroyed && pumpToken === myToken && (sink.queueLength() > 10 || sink.bufferedAhead() > 60 || sink.totalBuffered() > 120)) {\n await new Promise((r) => setTimeout(r, 500));\n }\n if (destroyed || pumpToken !== myToken) return;\n sink.append(chunk.data);\n stats.bytesWritten += chunk.data.byteLength;\n stats.fragments++;\n },\n });\n\n const target = new mb.StreamTarget(writable);\n const output = new mb.Output({\n format: new mb.Mp4OutputFormat({ fastStart: \"fragmented\" }),\n target,\n });\n\n // Build the output sources.\n const videoSource = new mb.EncodedVideoPacketSource(mbVideoCodec!);\n output.addVideoTrack(videoSource);\n\n type AudioSourceCtorArg = ConstructorParameters<typeof mb.EncodedAudioPacketSource>[0];\n let audioSource: InstanceType<typeof mb.EncodedAudioPacketSource> | null = null;\n if (mbAudioCodec && inputAudio?.isAudioTrack()) {\n audioSource = new mb.EncodedAudioPacketSource(mbAudioCodec as AudioSourceCtorArg);\n output.addAudioTrack(audioSource);\n }\n\n currentOutput = output;\n return { output, videoSource, audioSource };\n }\n\n async function pumpLoop(token: number, fromTime: number) {\n const { output, videoSource, audioSource } = createOutput();\n\n await output.start();\n\n\n // Find the starting key packet so we never push partial GOPs.\n const startVideoPacket =\n fromTime > 0\n ? (await videoSink.getKeyPacket(fromTime)) ?? (await videoSink.getFirstPacket())\n : await videoSink.getFirstPacket();\n if (!startVideoPacket) return;\n\n const startAudioPacket = audioSink\n ? (audioSink && fromTime > 0\n ? (await audioSink.getPacket(fromTime)) ?? (await audioSink.getFirstPacket())\n : await audioSink.getFirstPacket())\n : null;\n\n const videoIter = videoSink.packets(startVideoPacket);\n const audioIter = audioSink && startAudioPacket ? audioSink.packets(startAudioPacket) : null;\n\n let vNext = await videoIter.next();\n let aNext = audioIter ? await audioIter.next() : { done: true as const, value: undefined };\n let firstVideo = true;\n let firstAudio = true;\n\n while (!destroyed && pumpToken === token && (!vNext.done || !aNext.done)) {\n // Backpressure: pause pumping when we've buffered enough.\n while (\n !destroyed &&\n pumpToken === token &&\n sink &&\n (sink.bufferedAhead() > 30 || sink.queueLength() > 20 || sink.totalBuffered() > 90)\n ) {\n await new Promise((r) => setTimeout(r, 500));\n }\n if (destroyed || pumpToken !== token) break;\n\n const vTs = !vNext.done ? vNext.value.timestamp : Number.POSITIVE_INFINITY;\n const aTs = !aNext.done ? aNext.value.timestamp : Number.POSITIVE_INFINITY;\n\n // Mediabunny's muxer requires the first packet on a fresh Output to\n // be a key packet. We fetched `startVideoPacket` via\n // `videoSink.getKeyPacket(fromTime)` so the first video packet is\n // guaranteed to be a keyframe — but a demuxer can hand us an audio\n // packet with a lower timestamp, which mediabunny rejects with\n // \"First packet must be a key packet.\" Force the first video\n // packet out before we let any audio through.\n const forceVideoFirst = firstVideo && !vNext.done;\n\n if (!vNext.done && (forceVideoFirst || vTs <= aTs)) {\n await videoSource.add(\n vNext.value,\n firstVideo && videoConfig ? { decoderConfig: videoConfig } : undefined,\n );\n firstVideo = false;\n stats.videoPackets++;\n vNext = await videoIter.next();\n } else if (audioIter && audioSource && !aNext.done) {\n await audioSource.add(\n aNext.value,\n firstAudio && audioConfig ? { decoderConfig: audioConfig } : undefined,\n );\n firstAudio = false;\n stats.audioPackets++;\n aNext = await audioIter.next();\n } else {\n break;\n }\n }\n\n if (!destroyed && pumpToken === token) {\n await output.finalize();\n sink?.endOfStream();\n }\n }\n\n return {\n async start(fromTime = 0, autoPlay = false) {\n // Store autoPlay/seekTime so the MseSink (created lazily on first\n // write) can apply the deferred seek and auto-play.\n pendingAutoPlay = autoPlay;\n pendingStartTime = fromTime;\n pumpLoop(++pumpToken, fromTime).catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] remux pipeline failed:\", err);\n try { sink?.destroy(); } catch { /* ignore */ }\n });\n },\n async seek(time, autoPlay = false) {\n if (sink) {\n sink.setPlayOnSeek(autoPlay);\n sink.invalidate(time);\n } else {\n pendingAutoPlay = autoPlay;\n pendingStartTime = time;\n }\n pumpLoop(++pumpToken, time).catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] remux pipeline reseek failed:\", err);\n });\n },\n setAutoPlay(autoPlay) {\n pendingAutoPlay = autoPlay;\n if (sink) sink.setPlayOnSeek(autoPlay);\n },\n async setAudioTrack(trackId, time, autoPlay) {\n if (selectedAudioTrackId === trackId) return;\n if (!ctx.audioTracks.some((t) => t.id === trackId)) {\n console.warn(\"[avbridge] remux: setAudioTrack — unknown track id\", trackId);\n return;\n }\n // Stop the current pump. The next pumpLoop() will build a fresh\n // Output that uses the newly-selected audio source.\n pumpToken++;\n selectedAudioTrackId = trackId;\n await rebuildAudio().catch((err) => {\n console.warn(\"[avbridge] remux: rebuildAudio failed:\", (err as Error).message);\n });\n // Tear down the existing MseSink — the audio codec may have changed,\n // and the SourceBuffer's mime is fixed at construction time. The next\n // createOutput will recompute `getMimeType()` and the write handler\n // will lazily build a new sink.\n if (sink) {\n try { sink.destroy(); } catch { /* ignore */ }\n sink = null;\n }\n pendingAutoPlay = autoPlay;\n pendingStartTime = time;\n pumpLoop(++pumpToken, time).catch((err) => {\n // eslint-disable-next-line no-console\n console.error(\"[avbridge] remux pipeline setAudioTrack pump failed:\", err);\n });\n },\n async destroy() {\n destroyed = true;\n pumpToken++;\n try { if (currentOutput) await currentOutput.cancel(); } catch { /* ignore */ }\n try { await input.dispose(); } catch { /* ignore */ }\n sink?.destroy();\n },\n stats() {\n return { ...stats, decoderType: \"remux\" };\n },\n };\n}\n\n","import type { MediaContext, PlaybackSession } from \"../../types.js\";\nimport { createRemuxPipeline, type RemuxPipeline } from \"./pipeline.js\";\n\n/**\n * Strategy entry: build the remux pipeline, then expose a {@link PlaybackSession}\n * that delegates to the underlying `<video>` element for playback control and\n * to the pipeline for source-side seek invalidation.\n */\nexport async function createRemuxSession(\n context: MediaContext,\n video: HTMLVideoElement,\n): Promise<PlaybackSession> {\n let pipeline: RemuxPipeline;\n try {\n pipeline = await createRemuxPipeline(context, video);\n } catch (err) {\n throw new Error(\n `remux strategy failed to start: ${(err as Error).message}. The container or codec combination is not supported by mediabunny + MSE on this browser.`,\n );\n }\n\n // Don't pump yet — wait for the first play() or seek() to start from the\n // right position. The player's strategy-switch flow calls seek(currentTime)\n // immediately after creation, so pumping from 0 here would be wasted work.\n let started = false;\n let wantPlay = false;\n\n return {\n strategy: \"remux\",\n async play() {\n wantPlay = true;\n if (!started) {\n // First play — start the pump. The deferred seek in MseSink will\n // call video.play() once data is available (via autoPlay flag).\n started = true;\n await pipeline.start(video.currentTime || 0, true);\n return;\n }\n // seek() may have already started the pump with autoPlay=false\n // (strategy-switch flow calls seek before play). Flip the pipeline's\n // pending autoPlay so the MseSink fires video.play() once buffered\n // data lands, and also attempt an immediate video.play() in case the\n // sink is already wired up. The immediate call can reject when\n // video.src hasn't been set yet — that's fine, the deferred path will\n // catch it.\n pipeline.setAutoPlay(true);\n try {\n await video.play();\n } catch {\n /* sink not ready yet; setAutoPlay will handle playback on first buffered write */\n }\n },\n pause() {\n wantPlay = false;\n video.pause();\n },\n async seek(time) {\n if (!started) {\n started = true;\n // autoPlay=true so playback starts as soon as data arrives at\n // the seek target (handles the strategy-switch case where play()\n // is called right after seek()).\n await pipeline.seek(time, wantPlay);\n return;\n }\n const wasPlaying = !video.paused;\n await pipeline.seek(time, wasPlaying || wantPlay);\n // HTMLMediaElement contract: Firefox + WebKit's MSE doesn't\n // reliably fire `seeked` after a SourceBuffer remove+refill\n // cycle (Chromium does). Dispatch manually so consumers get a\n // consistent signal across browsers. Duplicating a native\n // `seeked` is harmless per spec.\n queueMicrotask(() => {\n try { video.dispatchEvent(new Event(\"seeked\")); } catch { /* ignore */ }\n });\n },\n async setAudioTrack(id) {\n if (!context.audioTracks.some((t) => t.id === id)) {\n console.warn(\"[avbridge] remux: setAudioTrack — unknown track id\", id);\n return;\n }\n const wasPlaying = !video.paused;\n const time = video.currentTime || 0;\n // Not yet started? Just note the selection and let play()/seek() drive.\n if (!started) {\n started = true;\n await pipeline.setAudioTrack(id, time, wantPlay || wasPlaying);\n return;\n }\n await pipeline.setAudioTrack(id, time, wasPlaying || wantPlay);\n },\n async setSubtitleTrack(id) {\n const tracks = video.textTracks;\n for (let i = 0; i < tracks.length; i++) {\n tracks[i].mode = i === id ? \"showing\" : \"disabled\";\n }\n },\n getCurrentTime() {\n return video.currentTime || 0;\n },\n async destroy() {\n video.pause();\n await pipeline.destroy();\n video.removeAttribute(\"src\");\n video.load();\n },\n getRuntimeStats() {\n return pipeline.stats();\n },\n };\n}\n","import type { ClockSource } from \"./audio-output.js\";\nimport { SubtitleOverlay } from \"../../subtitles/render.js\";\n\n/**\n * Renders decoded `VideoFrame`s into a 2D canvas overlaid on the user's\n * `<video>` element. The fallback strategy never assigns a src to the video,\n * so we hide it and put the canvas in its place visually.\n *\n * The renderer has two modes:\n *\n * 1. **Pre-roll** — `clock.isPlaying()` is false. The very first decoded\n * frame is painted as a \"poster\" so the user sees something while audio\n * buffers; subsequent frames stay queued without being dropped.\n *\n * 2. **Synced** — `clock.isPlaying()` is true. On each rAF tick, find the\n * latest frame whose timestamp ≤ `clock.now() + lookahead` and paint it.\n * Drop any older frames as \"late.\"\n *\n * The pre-roll behavior is what fixes the cold-start \"first minute is all\n * dropped\" problem: without it, the wall clock raced ahead while the\n * decoder was still warming up, and every frame was already in the past by\n * the time it landed in the queue.\n */\n// Periodic debug log — throttled to once per second so it doesn't\n// flood the console at 60Hz rAF rate.\nfunction isDebug(): boolean {\n return typeof globalThis !== \"undefined\" && !!(globalThis as Record<string, unknown>).AVBRIDGE_DEBUG;\n}\nlet lastDebugLog = 0;\n\nexport class VideoRenderer {\n private canvas: HTMLCanvasElement;\n private ctx: CanvasRenderingContext2D;\n private queue: VideoFrame[] = [];\n private rafHandle: number | null = null;\n private destroyed = false;\n\n private framesPainted = 0;\n private framesDroppedLate = 0;\n private framesDroppedOverflow = 0;\n /** True once the head frame has been painted as a pre-roll poster\n * since the last flush. Used to ensure pre-roll paints exactly one\n * frame (held static) during the post-seek discard window. */\n private prerolled = false;\n /** PTS (µs) of the most recently painted frame. Used as the calibration\n * reference on the first post-flush snap: the pre-roll path paints one\n * frame *before* PTS-based playback starts, so the queue head's PTS at\n * first PTS-based paint is the *next* frame, off by one frameDur from\n * the actually-displayed frame. Calibrating against the painted frame\n * instead of the queue head removes that one-frame offset and yields\n * calib ≈ 0 instead of +frameDur. */\n private lastPaintedPtsUs = 0;\n private hasLastPaintedPts = false;\n /** Audio-clock reading (ms) at the previous paint, for overlay Δaud. */\n private lastPaintAudMs = 0;\n /** Wall-clock time of the last paint, in ms (performance.now()). */\n private lastPaintWall = 0;\n /** Minimum ms between paints — paces video at roughly source fps. */\n private paintIntervalMs: number;\n /** Cumulative count of frames skipped because all PTS are in the future. */\n private ticksWaiting = 0;\n /** Cumulative count of ticks where PTS mode painted a frame. */\n private ticksPainted = 0;\n\n /**\n * Subtitle overlay div attached to the stage wrapper alongside the\n * canvas. Created lazily when subtitle tracks are attached via the\n * target's `<track>` children. Canvas strategies (hybrid, fallback)\n * hide the <video>, so we can't rely on the browser's native cue\n * rendering; we read TextTrack.cues and render into this overlay.\n */\n private subtitleOverlay: SubtitleOverlay | null = null;\n private subtitleTrack: TextTrack | null = null;\n\n /**\n * Calibration offset (microseconds) between video PTS and audio clock.\n * Video PTS and AudioContext.currentTime can drift ~0.1% relative to\n * each other (different clock domains). Over 45 minutes that's 2.6s.\n * We measure the offset on the first painted frame and update it\n * periodically so the PTS comparison stays calibrated.\n */\n private ptsCalibrationUs = 0;\n private ptsCalibrated = false;\n private lastCalibrationWall = 0;\n\n /** Resolves once the first decoded frame has been enqueued. */\n readonly firstFrameReady: Promise<void>;\n private resolveFirstFrame!: () => void;\n\n constructor(\n private readonly target: HTMLVideoElement,\n private readonly clock: ClockSource,\n fps = 30,\n ) {\n this.paintIntervalMs = Math.max(1, 1000 / fps);\n this.firstFrameReady = new Promise<void>((resolve) => {\n this.resolveFirstFrame = resolve;\n });\n\n this.canvas = document.createElement(\"canvas\");\n // `object-fit` is driven by the `--avbridge-fit` custom property so the\n // `<avbridge-video>` element's `fit` attribute can retarget the canvas\n // without reaching into the fallback strategy. Default is `contain` —\n // letterboxes the canvas bitmap (sized to frame.displayWidth ×\n // displayHeight in paint()) inside the stage so portrait / non-stage-aspect\n // content isn't stretched. Canvas is a replaced element, so object-fit applies.\n this.canvas.style.cssText =\n \"position:absolute;left:0;top:0;width:100%;height:100%;background:black;object-fit:var(--avbridge-fit, contain);\";\n\n // Attach the canvas next to the video. When the video lives inside an\n // `<avbridge-video>` shadow root, `target.parentElement` is the\n // positioned `<div part=\"stage\">` wrapper the element created\n // precisely for this purpose. When the video is used standalone\n // (legacy `createPlayer({ target: videoEl })` path), we fall back to\n // `parentNode` — which handles plain Elements, and also ShadowRoots\n // if someone inserts a bare <video> inside their own shadow DOM\n // without a wrapper.\n const parent: ParentNode | null =\n (target.parentElement as ParentNode | null) ?? target.parentNode;\n if (parent && parent instanceof HTMLElement) {\n if (getComputedStyle(parent).position === \"static\") {\n parent.style.position = \"relative\";\n }\n }\n if (parent) {\n parent.insertBefore(this.canvas, target);\n } else {\n // No parent at all — the target is detached. Fall back to appending\n // the canvas to document.body so at least the frames are visible\n // somewhere while the consumer fixes their DOM layout. This is a\n // loud fallback: log a warning so the misuse is obvious.\n // eslint-disable-next-line no-console\n console.warn(\n \"[avbridge] fallback renderer: target <video> has no parent; \" +\n \"appending canvas to document.body as a fallback.\",\n );\n document.body.appendChild(this.canvas);\n }\n target.style.visibility = \"hidden\";\n\n // Create a subtitle overlay on the same parent as the canvas so cues\n // appear over the rendered video. Shows nothing until a TextTrack\n // gets attached via attachSubtitleTracks.\n const overlayParent = parent instanceof HTMLElement ? parent : document.body;\n this.subtitleOverlay = new SubtitleOverlay(overlayParent);\n // Watch for <track> children on the target <video>. When one is\n // added, grab its TextTrack and poll cues from it each tick.\n this.watchTextTracks(target);\n\n const ctx = this.canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"video renderer: failed to acquire 2D context\");\n this.ctx = ctx;\n\n this.tick = this.tick.bind(this);\n this.rafHandle = requestAnimationFrame(this.tick);\n }\n\n /**\n * True once at least one frame has been enqueued *since the last flush*.\n * Used by `readyState` — initial cold-start reports HAVE_NOTHING until\n * any frame has arrived, and after a seek we want the same semantics\n * (HAVE_NOTHING until post-seek frames arrive), so the cumulative\n * `framesPainted > 0` that used to live here was wrong: it kept the\n * state \"true forever\" after the first frame ever, so post-seek\n * `waitForBuffer()` would exit immediately with an empty queue and\n * leave video frozen while audio kept going.\n */\n hasFrames(): boolean {\n return this.queue.length > 0 || this.hasEverEnqueuedSinceFlush;\n }\n\n private hasEverEnqueuedSinceFlush = false;\n\n /** Current depth of the frame queue. Used by the decoder for backpressure. */\n queueDepth(): number {\n return this.queue.length;\n }\n\n /**\n * Cap the decoder may fill the queue up to. Used by the decoder's\n * enqueue-side discard logic (it closes new frames instead of pushing\n * them when this is reached). Sized so a long post-seek catch-up\n * fits — the decoder produces frames at PTS T_kf onwards rapidly\n * while the demuxer is chewing through pre-target audio; if the\n * queue can hold the whole post-seek burst, the renderer plays\n * smoothly from pre-roll without a frozen-video gap when audio.start\n * fires. At ~340 KB per SD frame the cap is ~85 MB peak; at HD it's\n * larger but still bounded.\n */\n readonly queueHighWater = 256;\n\n enqueue(frame: VideoFrame): void {\n if (this.destroyed) {\n frame.close();\n return;\n }\n this.queue.push(frame);\n this.hasEverEnqueuedSinceFlush = true;\n if (this.queue.length === 1 && this.framesPainted === 0) {\n this.resolveFirstFrame();\n }\n // Hard cap. The decoder's enqueue-side discard at `queueHighWater`\n // is the primary defense; this `+8` margin is just safety for a\n // racy producer. Drops the OLDEST frames, which during catch-up\n // would mean losing the frames closest to the seek target — so the\n // decoder should be tuned to never reach this.\n while (this.queue.length > this.queueHighWater + 8) {\n this.queue.shift()?.close();\n this.framesDroppedOverflow++;\n }\n }\n\n /**\n * Watch the target <video>'s textTracks list. When a track is added,\n * grab it and start polling cues on each render tick. Existing tracks\n * (if any) are picked up immediately.\n */\n private watchTextTracks(target: HTMLVideoElement): void {\n const pick = () => {\n if (this.subtitleTrack) return;\n const tracks = target.textTracks;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] watchTextTracks pick() — ${tracks.length} tracks`);\n }\n for (let i = 0; i < tracks.length; i++) {\n const t = tracks[i];\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] track ${i}: kind=${t.kind} mode=${t.mode} cues=${t.cues?.length ?? 0}`);\n }\n if (t.kind === \"subtitles\" || t.kind === \"captions\") {\n this.subtitleTrack = t;\n t.mode = \"hidden\"; // hidden means \"cues available via API, don't render\"\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] picked track, mode=hidden`);\n }\n // Listen for cue load completion\n const trackEl = target.querySelector(`track[srclang=\"${t.language}\"]`) as HTMLTrackElement | null;\n if (trackEl) {\n trackEl.addEventListener(\"load\", () => {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] track element loaded, cues=${t.cues?.length ?? 0}`);\n }\n });\n trackEl.addEventListener(\"error\", (ev) => {\n // eslint-disable-next-line no-console\n console.warn(`[avbridge:subs] track element error:`, ev);\n });\n }\n break;\n }\n }\n };\n pick();\n if (typeof target.textTracks.addEventListener === \"function\") {\n target.textTracks.addEventListener(\"addtrack\", (e) => {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(\"[avbridge:subs] addtrack event fired\");\n }\n void e;\n pick();\n });\n }\n }\n\n private _loggedCues = false;\n\n /** Find the active cue (if any) for the given media time. */\n private updateSubtitles(): void {\n if (!this.subtitleOverlay || !this.subtitleTrack) return;\n const cues = this.subtitleTrack.cues;\n if (!cues || cues.length === 0) return;\n if (isDebug() && !this._loggedCues) {\n this._loggedCues = true;\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] cues available: ${cues.length}, first start=${cues[0].startTime}, last end=${cues[cues.length-1].endTime}`);\n }\n const t = this.clock.now();\n let activeText = \"\";\n for (let i = 0; i < cues.length; i++) {\n const c = cues[i];\n if (t >= c.startTime && t <= c.endTime) {\n const vttCue = c as VTTCue & { text?: string };\n activeText = vttCue.text ?? \"\";\n break;\n }\n }\n // Strip VTT tags for plain rendering (e.g. <c.en> voice tags)\n this.subtitleOverlay.setText(activeText.replace(/<[^>]+>/g, \"\"));\n }\n\n private tick(): void {\n if (this.destroyed) return;\n this.rafHandle = requestAnimationFrame(this.tick);\n\n this.updateSubtitles();\n\n if (this.queue.length === 0) return;\n\n const playing = this.clock.isPlaying();\n\n // Pre-roll: paint the head frame ONCE as a poster while audio buffers.\n //\n // Safety invariant (load-bearing): with the decoder.ts content-clock\n // fix (POSTMORTEMS 2026-06-01), pre-target frames are discarded at\n // the decoder/enqueue boundary, so queue[0] here is guaranteed to be\n // a near-target frame — never the keyframe-to-target preroll sequence\n // that previously caused the post-seek fast-forward when painted.\n //\n // Paint at most ONE frame and hold it (gate via `prerolled`). Do NOT\n // shift the queue: when audio unfreezes and `playing` becomes true,\n // the regular PTS loop below will paint this same frame again and\n // shift it out. That second paint is a no-op visually (same pixels)\n // so there's no flicker.\n //\n // If the queue is empty (decoder still grinding through the post-seek\n // discard window), just return — last pre-flush frame stays on canvas\n // as the freeze poster, which is the safe fallback.\n if (!playing) {\n if (!this.prerolled && this.queue.length > 0) {\n this.prerolled = true;\n this.paint(this.queue[0]);\n }\n return;\n }\n\n // PTS-based painting: find the latest frame whose presentation time\n // has arrived (timestamp ≤ audio clock), paint it, and discard any\n // older frames. This produces correct cadence at any display refresh\n // rate and any source fps — no 3:2 pulldown artifacts.\n //\n // Fallback: if frame timestamps are unreliable (all zero, synthetic),\n // fall back to wall-clock pacing as before.\n const rawAudioNowUs = this.clock.now() * 1_000_000;\n const headTs = this.queue[0].timestamp ?? 0;\n const hasPts = headTs > 0 || this.queue.length > 1;\n\n if (hasPts) {\n // Calibration: video PTS and audio clock (AudioContext.currentTime)\n // live in different clock domains with a fixed offset (different epoch)\n // plus a small rate drift (~7ms/s). We snap the offset on first paint\n // and re-snap every 10 seconds. Between snaps, max drift is ~70ms\n // (under 2 frames at 24fps, below lip-sync perception threshold).\n //\n // Two cases for the *first* snap after flush:\n // - Anchor `rawAudioNowUs` against `clock.now()` (default for the\n // periodic 10s re-snap) drifts with the audio clock — including\n // decode-stall lag accumulated between `audio.start()` and the\n // first frame's arrival. On a slow seek where the first frame\n // lands 1–2s after audio resumed, this captures the lag as a\n // permanent offset and the video stays that far behind audio.\n // - For the *first* snap post-flush we instead use the audio's\n // **anchor time** (`mediaTimeOfAnchor`, == the seek target / 0\n // on cold start). That gives `headTs − seekTarget` ≈ keyframe\n // offset (usually < 100ms), independent of decode delay.\n const wallNow = performance.now();\n // First snap after flush/cold-start anchors against the audio's\n // *master-clock reference* (= `mediaTimeOfAnchor`, == the rebased\n // audio first-chunk PTS), NOT `clock.now()`. `clock.now()` includes\n // wall-clock-drifted elapsed time between `audio.start()` and the\n // first paint — on a slow seek where the first frame lands 1-2 s\n // after audio resumed, that decode delay gets baked into the\n // calibration as a permanent video-lag offset. See POSTMORTEMS.md\n // (2026-04-13). The periodic re-snap continues to use `rawAudioNow`\n // as the original design intended — a stateless independent snap\n // every 10 s bounds drift to ~70 ms at the documented ~7 ms/s rate,\n // below the lip-sync perception threshold. Do *not* introduce a\n // smoothed / EMA / bounded-delta variant here: the measured offset\n // includes the current calibration, which produces a feedback loop\n // (postmortem 2026-04-13, hypothesis 3).\n if (!this.ptsCalibrated) {\n const anchorUs = (this.clock.anchorTime?.() ?? this.clock.now()) * 1_000_000;\n // Reference frame for calibration: prefer the pre-rolled frame's\n // PTS over the queue head, since the pre-rolled frame is what the\n // user is *actually looking at* the moment audio starts. The queue\n // head at this point is the NEXT frame (PTS == prerolled + frameDur),\n // and calibrating against it bakes that one-frame offset into the\n // calibration permanently. With the painted-frame reference, calib\n // ≈ 0 when video keyframe lands at the seek target.\n const referencePtsUs = this.hasLastPaintedPts ? this.lastPaintedPtsUs : headTs;\n this.ptsCalibrationUs = referencePtsUs - anchorUs;\n this.ptsCalibrated = true;\n this.lastCalibrationWall = wallNow;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(\n `[avbridge:renderer] CALIB-FIRST audioAnchor=${(anchorUs / 1000).toFixed(1)}ms ` +\n `prerolledPTS=${this.hasLastPaintedPts ? (this.lastPaintedPtsUs / 1000).toFixed(1) : \"n/a\"}ms ` +\n `queueHeadPTS=${(headTs / 1000).toFixed(1)}ms ` +\n `rawAudioNow=${(rawAudioNowUs / 1000).toFixed(1)}ms ` +\n `→ calib=${(this.ptsCalibrationUs / 1000).toFixed(1)}ms`,\n );\n }\n } else if (wallNow - this.lastCalibrationWall > 10_000) {\n const oldCalib = this.ptsCalibrationUs;\n this.ptsCalibrationUs = headTs - rawAudioNowUs;\n this.lastCalibrationWall = wallNow;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(\n `[avbridge:renderer] CALIB-RESNAP ` +\n `headPTS=${(headTs / 1000).toFixed(1)}ms rawAudioNow=${(rawAudioNowUs / 1000).toFixed(1)}ms ` +\n `calib ${(oldCalib / 1000).toFixed(1)}ms → ${(this.ptsCalibrationUs / 1000).toFixed(1)}ms ` +\n `(Δ=${((this.ptsCalibrationUs - oldCalib) / 1000).toFixed(1)}ms after 10s)`,\n );\n }\n }\n\n const audioNowUs = rawAudioNowUs + this.ptsCalibrationUs;\n // Paint the frame whose PTS is at or just before audioNow. A frame\n // at PTS P should be the displayed frame from the moment audio\n // reaches P, *not* from P − frameDur. The previous code used\n // `deadline = audioNow + frameDur`, which painted frames up to one\n // source-frame ahead of audio — a steady ~40 ms video-leads-audio\n // offset that the user perceived as \"fast-forward then normal.\"\n // With `deadline = audioNow`, paints land exactly at the frame's\n // start of display interval; lip sync matches.\n const deadlineUs = audioNowUs;\n\n let bestIdx = -1;\n for (let i = 0; i < this.queue.length; i++) {\n const ts = this.queue[i].timestamp ?? 0;\n if (ts <= deadlineUs) {\n bestIdx = i;\n } else {\n break;\n }\n }\n\n if (bestIdx < 0) {\n this.ticksWaiting++;\n if (isDebug()) {\n const now = performance.now();\n if (now - lastDebugLog > 1000) {\n const headPtsMs = (headTs / 1000).toFixed(1);\n const audioMs = (audioNowUs / 1000).toFixed(1);\n const rawDriftMs = ((headTs - rawAudioNowUs) / 1000).toFixed(1);\n const calibMs = (this.ptsCalibrationUs / 1000).toFixed(1);\n // eslint-disable-next-line no-console\n console.log(\n `[avbridge:renderer] WAIT q=${this.queue.length} headPTS=${headPtsMs}ms calibAudio=${audioMs}ms ` +\n `rawDrift=${rawDriftMs}ms calib=${calibMs}ms painted=${this.framesPainted} dropped=${this.framesDroppedLate}`,\n );\n lastDebugLog = now;\n }\n }\n return;\n }\n\n // Audio-sync skip: when `bestIdx > 0` there are multiple frames in\n // the queue whose PTS ≤ deadline. Drop everything before `bestIdx`\n // and paint the latest paintable frame. See POSTMORTEMS.md\n // 2026-05-31 coda for the rationale.\n const _relaxDrop =\n (globalThis as { AVBRIDGE_RELAX_DROP?: boolean }).AVBRIDGE_RELAX_DROP === true;\n let dropped = 0;\n const initialBestIdx = bestIdx;\n if (!_relaxDrop) {\n while (bestIdx > 0) {\n this.queue.shift()?.close();\n this.framesDroppedLate++;\n bestIdx--;\n dropped++;\n }\n }\n const paintTs = this.queue[0]?.timestamp ?? 0;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[TRACE] PAINT bestIdx_initial=${initialBestIdx} dropped=${dropped} paintPts=${(paintTs / 1000).toFixed(1)}ms audioNow=${(audioNowUs / 1000).toFixed(1)}ms deadline=${(deadlineUs / 1000).toFixed(1)}ms queueLen=${this.queue.length} wall=${performance.now().toFixed(0)}`);\n }\n\n this.ticksPainted++;\n\n if (isDebug()) {\n const now = performance.now();\n if (now - lastDebugLog > 1000) {\n const paintedTs = (this.queue[0]?.timestamp ?? 0);\n const audioMs = (audioNowUs / 1000).toFixed(1);\n const ptsMs = (paintedTs / 1000).toFixed(1);\n const rawDriftMs = ((paintedTs - rawAudioNowUs) / 1000).toFixed(1);\n const calibMs = (this.ptsCalibrationUs / 1000).toFixed(1);\n // eslint-disable-next-line no-console\n console.log(\n `[avbridge:renderer] PAINT q=${this.queue.length} calibAudio=${audioMs}ms nextPTS=${ptsMs}ms ` +\n `rawDrift=${rawDriftMs}ms calib=${calibMs}ms dropped=${dropped} total_drops=${this.framesDroppedLate} painted=${this.framesPainted}`,\n );\n lastDebugLog = now;\n }\n }\n\n const frame = this.queue.shift()!;\n this.paint(frame);\n frame.close();\n this.lastPaintWall = performance.now();\n return;\n }\n\n // Wall-clock fallback: used when timestamps are unreliable (all zero).\n const wallNow = performance.now();\n if (wallNow - this.lastPaintWall < this.paintIntervalMs - 2) return;\n\n const frame = this.queue.shift()!;\n this.paint(frame);\n frame.close();\n this.lastPaintWall = wallNow;\n }\n\n private paint(frame: VideoFrame): void {\n if (\n this.canvas.width !== frame.displayWidth ||\n this.canvas.height !== frame.displayHeight\n ) {\n this.canvas.width = frame.displayWidth;\n this.canvas.height = frame.displayHeight;\n }\n try {\n this.ctx.drawImage(frame, 0, 0, this.canvas.width, this.canvas.height);\n\n // Debug overlay (gated on AVBRIDGE_DEBUG). Draws frame info on top\n // of the painted frame so the user can SEE what's actually\n // displayed and at what rate. Three time domains:\n // pts — source content time (from frame.timestamp)\n // aud — audio media clock (clock.now() × 1000)\n // wall — performance.now() (monotonic browser clock)\n // Plus the per-paint deltas. If `Δpts > Δwall` sustained across\n // multiple frames, that's real fast-forward; if it alternates\n // 33/50ms on a 25fps source, that's 3:2 pulldown judder. (See\n // POSTMORTEMS 2026-06-01 for why this overlay was load-bearing\n // when diagnosing the post-seek fast-forward.)\n if (isDebug()) {\n const wallNow = performance.now();\n const audNowMs = this.clock.now() * 1000;\n const ptsMs = (frame.timestamp ?? 0) / 1000;\n const dWall = this.lastPaintWall > 0 ? wallNow - this.lastPaintWall : 0;\n const dAud = this.lastPaintAudMs > 0 ? audNowMs - this.lastPaintAudMs : 0;\n const dPts = this.hasLastPaintedPts ? ptsMs - this.lastPaintedPtsUs / 1000 : 0;\n this.ctx.save();\n this.ctx.font = \"bold 18px monospace\";\n const lines = [\n `#${this.framesPainted + 1} pts=${ptsMs.toFixed(0)} aud=${audNowMs.toFixed(0)} wall=${wallNow.toFixed(0)}`,\n `Δpts=${dPts.toFixed(0)} Δaud=${dAud.toFixed(0)} Δwall=${dWall.toFixed(0)}`,\n ];\n const lineHeight = 22;\n const padTop = 6;\n const stripH = padTop + lineHeight * lines.length;\n this.ctx.fillStyle = \"rgba(0,0,0,0.7)\";\n this.ctx.fillRect(0, 0, this.canvas.width, stripH);\n this.ctx.fillStyle = \"#0f0\";\n for (let i = 0; i < lines.length; i++) {\n this.ctx.fillText(lines[i], 8, padTop + lineHeight * (i + 1) - 4);\n }\n this.ctx.restore();\n }\n\n // Record the just-painted frame's PTS so the next paint's overlay\n // Δpts and the next CALIB-RESNAP have a reference. Must run\n // unconditionally — `hasLastPaintedPts`/`lastPaintedPtsUs` are read\n // by the calibration path in tick() too, not just the overlay.\n this.lastPaintedPtsUs = frame.timestamp ?? 0;\n this.hasLastPaintedPts = true;\n this.lastPaintAudMs = this.clock.now() * 1000;\n\n this.framesPainted++;\n } catch (err) {\n // Log only once so a structurally broken frame format doesn't spam\n // the console at 60 Hz, but we still find out about it.\n if (this.framesPainted === 0 && this.framesDroppedLate === 0) {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] canvas drawImage failed:\", err);\n }\n }\n }\n\n /** Discard all queued frames. Used by seek to drop stale buffers. */\n flush(): void {\n const count = this.queue.length;\n while (this.queue.length > 0) this.queue.shift()?.close();\n this.prerolled = false;\n this.hasLastPaintedPts = false; // calibration ref doesn't carry across seek\n this.ptsCalibrated = false; // recalibrate at new seek position\n this.hasEverEnqueuedSinceFlush = false; // so waitForBuffer() waits for post-flush frames\n if (isDebug() && count > 0) {\n // eslint-disable-next-line no-console\n console.log(`[avbridge:renderer] FLUSH discarded=${count} painted=${this.framesPainted} drops=${this.framesDroppedLate}`);\n }\n }\n\n stats(): Record<string, unknown> {\n // Queue span — the gap between the oldest and newest queued frame's\n // PTS, in ms. If this collapses while audio keeps advancing, the\n // producer has stalled. If it stays wide with stale head, the\n // producer is bursting faster than realtime but the renderer can't\n // catch up.\n let queueSpanMs = 0;\n let queueHeadMs = 0;\n let queueTailMs = 0;\n if (this.queue.length > 0) {\n queueHeadMs = Math.round((this.queue[0].timestamp ?? 0) / 1000);\n queueTailMs = Math.round((this.queue[this.queue.length - 1].timestamp ?? 0) / 1000);\n queueSpanMs = Math.max(0, queueTailMs - queueHeadMs);\n }\n return {\n framesPainted: this.framesPainted,\n framesDroppedLate: this.framesDroppedLate,\n framesDroppedOverflow: this.framesDroppedOverflow,\n queueDepth: this.queue.length,\n queueHeadMs,\n queueTailMs,\n queueSpanMs,\n };\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.rafHandle != null) cancelAnimationFrame(this.rafHandle);\n this.flush();\n if (this.subtitleOverlay) { this.subtitleOverlay.destroy(); this.subtitleOverlay = null; }\n this.subtitleTrack = null;\n this.canvas.remove();\n this.target.style.visibility = \"\";\n }\n}\n","/**\n * Web Audio output for the fallback strategy.\n *\n * Owns the **media-time clock** for fallback playback. Audio is the master:\n * decoded video frames are presented based on what `now()` returns here.\n *\n * State machine:\n *\n * ┌──────┐ schedule() ┌──────┐ ┌────────┐\n * │ idle │ ───────────▶ │ idle │ ── start() ──▶│ playing│\n * └──────┘ (queues) └──────┘ └────┬───┘\n * ▲ │\n * │ │ pause()\n * │ ▼\n * │ ┌────────┐\n * └────────────── reset(t) ─────────────── ── │ paused │\n * └────────┘\n *\n * - **idle**: AudioContext is suspended (no playback). `schedule()` queues\n * samples in `pendingQueue`; `now()` returns `mediaTimeOfAnchor`.\n * - **playing**: AudioContext is running. `schedule()` writes directly to\n * the audio graph at the right time. `now()` advances with `ctx.currentTime`.\n * - **paused**: AudioContext is suspended. `now()` returns the media time\n * captured at pause. `start()` resumes.\n *\n * Key invariant: between any two `start()` calls, `mediaTimeOfNext` (the\n * media time of the next sample to be scheduled) must equal the media time\n * the playback is at. This is what makes the cold-start race go away — we\n * never schedule audio with a stale wall-clock anchor.\n */\n\ninterface PendingChunk {\n samples: Float32Array;\n channels: number;\n sampleRate: number;\n frameCount: number;\n durationSec: number;\n /** Source-domain content PTS in seconds. `null` for legacy callers\n * that schedule sequentially without PTS information. */\n ptsSec: number | null;\n}\n\n/** True when `globalThis.AVBRIDGE_DEBUG` is set. Used to gate [TRACE-AUD]\n * per-chunk logs that are useful for diagnosing scheduling drift but\n * unreadable in normal use. */\nfunction isDebug(): boolean {\n return typeof globalThis !== \"undefined\"\n && !!(globalThis as Record<string, unknown>).AVBRIDGE_DEBUG;\n}\n\nexport interface ClockSource {\n /** Current media time in seconds. */\n now(): number;\n /** True if media is currently playing (audio scheduler is running). */\n isPlaying(): boolean;\n /**\n * Media time at which the current playback session was anchored — i.e. the\n * seek target after the most recent `reset()`, or 0 on cold start. Used by\n * the video renderer for post-flush PTS calibration: `now()` includes any\n * decode-stall lag accumulated since playback resumed, but the anchor is\n * a stable reference that maps directly to the user's intended position.\n */\n anchorTime(): number;\n}\n\nexport class AudioOutput implements ClockSource {\n private ctx: AudioContext;\n private gain: GainNode;\n\n private state: \"idle\" | \"playing\" | \"paused\" = \"idle\";\n\n /**\n * Wall-clock fallback mode. When true, this output behaves as if audio\n * is unavailable — `now()` advances from `performance.now()` instead of\n * the audio context, `schedule()` is a no-op, and `bufferAhead()` returns\n * Infinity so the session's `waitForBuffer()` doesn't block on audio.\n *\n * Set by the decoder via {@link setNoAudio} when audio decode init fails.\n * This is what lets video play even when the audio codec isn't supported\n * by the loaded libav variant.\n */\n private noAudio = false;\n /** Wall-clock anchor (ms from `performance.now()`) for noAudio mode. */\n private wallAnchorMs = 0;\n\n /** Media time at which the next sample will be scheduled. */\n private mediaTimeOfNext = 0;\n\n /** Anchor: media time `mediaTimeOfAnchor` corresponds to ctx time `ctxTimeAtAnchor`. */\n private mediaTimeOfAnchor = 0;\n\n /**\n * Ctx time at which the first audible chunk will start playing. `-1`\n * before any chunk has been scheduled successfully (clock is frozen);\n * the actual ctx time once one has. The renderer's `clock.now()` uses\n * this to avoid advancing during the silent-gap window between\n * `audio.start()` and the first chunk that schedules without being\n * dropped — that gap is what produces the \"audio-less fast-forward\"\n * the user sees post-seek when the gate releases on video-only grace.\n */\n private firstAudibleCtxStart = -1;\n private ctxTimeAtAnchor = 0;\n\n private pendingQueue: PendingChunk[] = [];\n\n private framesScheduled = 0;\n private destroyed = false;\n\n /** User-set volume (0..1). Applied to the gain node. */\n private _volume = 1;\n /** User-set muted flag. When true, gain is forced to 0. */\n private _muted = false;\n /** Playback rate. Scales the media clock and each AudioBufferSourceNode's\n * playbackRate so audio pitches up/down accordingly (same as native\n * <video>.playbackRate). Default 1. */\n private _rate = 1;\n\n constructor() {\n this.ctx = new AudioContext();\n this.gain = this.ctx.createGain();\n this.gain.connect(this.ctx.destination);\n }\n\n /** Set volume (0..1). Applied immediately to the gain node. */\n setVolume(v: number): void {\n this._volume = Math.max(0, Math.min(1, v));\n this.applyGain();\n }\n\n getVolume(): number {\n return this._volume;\n }\n\n /** Set muted. When true, output is silenced regardless of volume. */\n setMuted(m: boolean): void {\n this._muted = m;\n this.applyGain();\n }\n\n getMuted(): boolean {\n return this._muted;\n }\n\n /** Set playback rate. Scales the media clock and pitches audio output\n * (same as native <video>.playbackRate — speed without pitch correction).\n * Rebases the anchor so the clock transition is seamless. */\n setPlaybackRate(rate: number): void {\n if (rate === this._rate) return;\n // Rebase anchor at the current media time before changing rate,\n // so the clock doesn't jump.\n const t = this.now();\n this.mediaTimeOfAnchor = t;\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.wallAnchorMs = performance.now();\n this._rate = rate;\n }\n\n getPlaybackRate(): number {\n return this._rate;\n }\n\n private applyGain(): void {\n const target = this._muted ? 0 : this._volume;\n try { this.gain.gain.value = target; } catch { /* ignore */ }\n }\n\n /**\n * Switch into wall-clock fallback mode. Called by the decoder when no\n * audio decoder could be initialized for the source. Once set, this\n * output drives playback time from `performance.now()` and ignores\n * any incoming audio samples.\n */\n setNoAudio(): void {\n this.noAudio = true;\n }\n\n // ── ClockSource ────────────────────────────────────────────────────────\n\n now(): number {\n if (this.noAudio) {\n if (this.state === \"playing\") {\n return this.mediaTimeOfAnchor + (performance.now() - this.wallAnchorMs) / 1000 * this._rate;\n }\n return this.mediaTimeOfAnchor;\n }\n if (this.state === \"playing\") {\n // Freeze the clock until the first audio chunk has actually been\n // scheduled. Without this, when `audio.start()` fires before any\n // post-seek audio packets have made it through the decoder (e.g. the\n // gate's \"video-only grace\" path released early), `clock.now()`\n // would advance from `mediaTimeOfAnchor` at 1× wall time while the\n // audio scheduler is dropping every chunk that arrives (their\n // PTS-derived `ctxStart` is already in the past). The renderer would\n // paint frames during that silent window — the user perceives that\n // as a \"fast-forward burst with no audio.\" When the first chunk\n // finally arrives and schedules normally, `firstAudibleCtxStart` is\n // set and the clock unfreezes from there in sync with the audible\n // content's PTS.\n if (this.firstAudibleCtxStart < 0) {\n return this.mediaTimeOfAnchor;\n }\n return this.mediaTimeOfAnchor + (this.ctx.currentTime - this.ctxTimeAtAnchor) * this._rate;\n }\n return this.mediaTimeOfAnchor;\n }\n\n anchorTime(): number {\n return this.mediaTimeOfAnchor;\n }\n\n isPlaying(): boolean {\n return this.state === \"playing\";\n }\n\n // ── Buffering ─────────────────────────────────────────────────────────\n\n /**\n * How many seconds of audio are buffered ahead of the current playback\n * position. While idle, this counts the pending queue. While playing,\n * it counts how far `mediaTimeOfNext` is ahead of `now()`.\n */\n bufferAhead(): number {\n // In wall-clock mode, no samples are ever scheduled — the buffer is\n // genuinely empty. Callers that want to gate cold-start should check\n // {@link isNoAudio} and skip the audio gate entirely instead.\n if (this.noAudio) return 0;\n if (this.state === \"idle\") {\n let sec = 0;\n for (const c of this.pendingQueue) sec += c.durationSec;\n return sec;\n }\n return Math.max(0, this.mediaTimeOfNext - this.now());\n }\n\n /** True if this output is in wall-clock fallback mode (no audio decode). */\n isNoAudio(): boolean {\n return this.noAudio;\n }\n\n /**\n * Schedule a chunk of decoded samples. Queues internally while idle (cold\n * start or post-seek), schedules directly to the audio graph while playing.\n * In wall-clock mode, samples are silently discarded.\n *\n * `ptsSec` is the chunk's source-domain content PTS in seconds, from\n * the demuxer. When provided, the chunk plays at the ctx-time\n * corresponding to that PTS — so pre-target audio after a seek\n * naturally drops (its computed `ctxStart` falls in the past) and\n * post-target audio plays at its true content time, without any\n * external trim or anchor rebase. When `ptsSec` is null (cold start\n * with no PTS yet, or codecs whose packet→frame mapping isn't 1:1),\n * the chunk is scheduled sequentially after `mediaTimeOfNext` — the\n * pre-refactor behavior.\n */\n schedule(\n samples: Float32Array,\n channels: number,\n sampleRate: number,\n ptsSec?: number | null,\n ): void {\n if (this.destroyed || this.noAudio) return;\n const frameCount = samples.length / channels;\n const durationSec = frameCount / sampleRate;\n const hasPts = ptsSec != null && Number.isFinite(ptsSec);\n\n // Pre-target gate: a chunk whose entire PTS span is before the\n // current media anchor will be silently dropped by `scheduleNow`\n // (its `ctxStart` falls in the past). We must apply the same drop\n // here in idle/paused state too — otherwise the chunk sits in\n // `pendingQueue`, `bufferAhead()` reports it as buffered audio,\n // `waitForBuffer()`'s gate releases on a phantom audio buffer, and\n // `audio.start()` fires with a queue full of chunks that immediately\n // drop on drain. The user sees post-seek \"sped up no audio\" while\n // the demuxer slowly chews through pre-target packets — `clock.now()`\n // is advancing on wall time and the renderer paints video against\n // it, but `node.start()` is never being called.\n if (hasPts && (ptsSec as number) + durationSec / this._rate < this.mediaTimeOfAnchor) {\n return;\n }\n\n if (this.state === \"idle\" || this.state === \"paused\") {\n this.pendingQueue.push({\n samples, channels, sampleRate, frameCount, durationSec,\n ptsSec: hasPts ? (ptsSec as number) : null,\n });\n return;\n }\n\n this.scheduleNow(\n samples, channels, sampleRate, frameCount,\n hasPts ? (ptsSec as number) : null,\n );\n }\n\n private scheduleNow(\n samples: Float32Array,\n channels: number,\n sampleRate: number,\n frameCount: number,\n ptsSec: number | null,\n ): void {\n const durationSec = frameCount / sampleRate;\n\n // Compute ctxStart. Two paths:\n //\n // PTS-known: the chunk's content PTS maps to a specific ctx time\n // via (mediaTimeOfAnchor, ctxTimeAtAnchor). If that ctx time is\n // already in the past, the chunk represents audio the user should\n // have heard before now — drop it. After a seek, this is what\n // *automatically* skips pre-target audio packets returned by a\n // keyframe-aligned demuxer seek; no manual trim needed.\n //\n // PTS-unknown (legacy): chain after the last-scheduled sample\n // via `mediaTimeOfNext`. Same behavior as before the refactor.\n let ctxStart: number;\n if (ptsSec != null) {\n ctxStart = this.ctxTimeAtAnchor + (ptsSec - this.mediaTimeOfAnchor) / this._rate;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[TRACE-AUD] PTS sched #${this.framesScheduled} pts=${ptsSec.toFixed(3)} dur=${durationSec.toFixed(4)} ctxStart=${ctxStart.toFixed(4)} ctxNow=${this.ctx.currentTime.toFixed(4)} anchor=${this.mediaTimeOfAnchor.toFixed(3)} ctxAnchor=${this.ctxTimeAtAnchor.toFixed(4)} mtNext=${this.mediaTimeOfNext.toFixed(3)} rate=${this._rate}`);\n }\n if (ctxStart < this.ctx.currentTime - 0.001) {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[TRACE-AUD] DROP late chunk pts=${ptsSec.toFixed(3)} ctxStart=${ctxStart.toFixed(4)} < ctxNow=${this.ctx.currentTime.toFixed(4)}`);\n }\n return;\n }\n // First chunk to schedule successfully unfreezes `clock.now()`.\n // We rebase the anchor onto this chunk: when ctx reaches `ctxStart`,\n // clock should equal `ptsSec` (so `audioNow` matches audible content\n // PTS exactly when the chunk plays). The renderer's deadline will\n // then advance from there, in lockstep with what's audible.\n if (this.firstAudibleCtxStart < 0) {\n this.firstAudibleCtxStart = ctxStart;\n this.mediaTimeOfAnchor = ptsSec;\n this.ctxTimeAtAnchor = ctxStart;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[TRACE-AUD] UNFREEZE clock — first audible chunk pts=${ptsSec.toFixed(3)} ctxStart=${ctxStart.toFixed(4)} → anchor=${this.mediaTimeOfAnchor.toFixed(3)} ctxAnchor=${this.ctxTimeAtAnchor.toFixed(4)}`);\n }\n }\n const endMediaTime = ptsSec + durationSec / this._rate;\n if (endMediaTime > this.mediaTimeOfNext) {\n this.mediaTimeOfNext = endMediaTime;\n }\n } else {\n ctxStart = this.ctxTimeAtAnchor + (this.mediaTimeOfNext - this.mediaTimeOfAnchor) / this._rate;\n // eslint-disable-next-line no-console\n console.warn(`[TRACE-AUD] LEGACY (no PTS) sched dur=${durationSec.toFixed(4)} ctxStart=${ctxStart.toFixed(4)} ctxNow=${this.ctx.currentTime.toFixed(4)}`);\n if (ctxStart < this.ctx.currentTime) {\n // eslint-disable-next-line no-console\n console.warn(`[TRACE-AUD] REBASE anchor was=${this.mediaTimeOfAnchor.toFixed(3)} ctxAnchor was=${this.ctxTimeAtAnchor.toFixed(4)} → anchor=${this.mediaTimeOfNext.toFixed(3)} ctxAnchor=${this.ctx.currentTime.toFixed(4)}`);\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.mediaTimeOfAnchor = this.mediaTimeOfNext;\n ctxStart = this.ctx.currentTime;\n }\n this.mediaTimeOfNext += durationSec;\n }\n\n const buffer = this.ctx.createBuffer(channels, frameCount, sampleRate);\n for (let ch = 0; ch < channels; ch++) {\n const channelData = buffer.getChannelData(ch);\n for (let i = 0; i < frameCount; i++) {\n channelData[i] = samples[i * channels + ch];\n }\n }\n const node = this.ctx.createBufferSource();\n node.buffer = buffer;\n node.connect(this.gain);\n if (this._rate !== 1) node.playbackRate.value = this._rate;\n node.start(ctxStart);\n this.framesScheduled++;\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n /**\n * Start (or resume) playback. On a cold start (or after a reset), drains\n * the pending queue scheduling all queued samples to play starting at\n * `ctx.currentTime + STARTUP_DELAY`. On resume from pause, just re-anchors\n * the media↔ctx time mapping and unsuspends the context.\n */\n async start(): Promise<void> {\n if (this.destroyed || this.state === \"playing\") return;\n\n // Wall-clock mode: no audio context involved. Anchor to performance.now()\n // and let `now()` advance from there. The renderer's tick loop will see\n // `isPlaying() === true` and start painting frames.\n if (this.noAudio) {\n this.wallAnchorMs = performance.now();\n this.state = \"playing\";\n return;\n }\n\n if (this.ctx.state === \"suspended\") {\n await this.ctx.resume();\n }\n\n // Reconnect the gain node — pause() disconnects it to cut off\n // in-flight audio instantly. Safe to call even if already connected.\n try { this.gain.connect(this.ctx.destination); } catch { /* ignore */ }\n\n if (this.state === \"paused\") {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[TRACE-AUD] START(resume) anchor=${this.mediaTimeOfAnchor.toFixed(3)} ctxAnchor=${this.ctxTimeAtAnchor.toFixed(4)} → ctxAnchor=${this.ctx.currentTime.toFixed(4)} ctxNow=${this.ctx.currentTime.toFixed(4)} pendingCount=${this.pendingQueue.length}`);\n }\n // Resume: media time should continue from where we paused. ctx.currentTime\n // is preserved across suspend/resume, so re-anchoring it to \"now\" with\n // the same mediaTimeOfAnchor gives a continuous clock.\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.state = \"playing\";\n // Drain anything that was scheduled while paused.\n const drain = this.pendingQueue;\n this.pendingQueue = [];\n for (const c of drain) {\n this.scheduleNow(c.samples, c.channels, c.sampleRate, c.frameCount, c.ptsSec);\n }\n return;\n }\n\n // Cold start (or post-seek). Anchor: the first sample we scheduled lands\n // at ctxTimeAtAnchor (a tiny bit in the future), and that ctx time\n // corresponds to media time mediaTimeOfAnchor.\n const STARTUP_DELAY = 0.05;\n this.ctxTimeAtAnchor = this.ctx.currentTime + STARTUP_DELAY;\n this.mediaTimeOfNext = this.mediaTimeOfAnchor;\n this.state = \"playing\";\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[TRACE-AUD] START(cold) anchor=${this.mediaTimeOfAnchor.toFixed(3)} ctxAnchor=${this.ctxTimeAtAnchor.toFixed(4)} mtNext=${this.mediaTimeOfNext.toFixed(3)} ctxNow=${this.ctx.currentTime.toFixed(4)} pendingCount=${this.pendingQueue.length}`);\n }\n\n const drain = this.pendingQueue;\n this.pendingQueue = [];\n for (const c of drain) {\n this.scheduleNow(c.samples, c.channels, c.sampleRate, c.frameCount, c.ptsSec);\n }\n }\n\n /** Pause playback. Suspends the audio context. */\n async pause(): Promise<void> {\n if (this.state !== \"playing\") return;\n this.mediaTimeOfAnchor = this.now();\n this.state = \"paused\";\n if (this.noAudio) return;\n // Disconnect the gain node immediately so any in-flight scheduled\n // buffers are silenced instantly. ctx.suspend() is async and\n // already-started AudioBufferSourceNodes keep playing until the\n // context actually suspends — without the disconnect, audio bleeds\n // through for ~200ms after pause().\n try { this.gain.disconnect(); } catch { /* ignore */ }\n if (this.ctx.state === \"running\") {\n await this.ctx.suspend();\n }\n }\n\n /**\n * Reset to a new media time. Discards all queued and scheduled audio,\n * disconnects the gain node so any in-flight scheduled buffers are cut\n * off, and returns to the idle state. Used by `seek()`.\n *\n * After reset, callers should re-buffer audio (the decoder will start\n * supplying new samples) and then call `start()` to resume playback.\n */\n async reset(newMediaTime: number): Promise<void> {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[TRACE-AUD] RESET to=${newMediaTime.toFixed(3)} prev_anchor=${this.mediaTimeOfAnchor.toFixed(3)} prev_mtNext=${this.mediaTimeOfNext.toFixed(3)} prev_ctxAnchor=${this.ctxTimeAtAnchor.toFixed(4)} ctxNow=${this.ctx.currentTime.toFixed(4)} state=${this.state}`);\n }\n if (this.noAudio) {\n this.pendingQueue = [];\n this.mediaTimeOfAnchor = newMediaTime;\n this.wallAnchorMs = performance.now();\n this.state = \"idle\";\n return;\n }\n\n try { this.gain.disconnect(); } catch { /* ignore */ }\n this.gain = this.ctx.createGain();\n this.gain.connect(this.ctx.destination);\n this.applyGain();\n\n this.pendingQueue = [];\n this.mediaTimeOfAnchor = newMediaTime;\n this.mediaTimeOfNext = newMediaTime;\n this.ctxTimeAtAnchor = this.ctx.currentTime;\n this.firstAudibleCtxStart = -1;\n this.state = \"idle\";\n\n if (this.ctx.state === \"running\") {\n await this.ctx.suspend();\n }\n }\n\n stats(): Record<string, unknown> {\n return {\n framesScheduled: this.framesScheduled,\n bufferAhead: this.bufferAhead(),\n audioState: this.state,\n clockMode: this.noAudio ? \"wall\" : \"audio\",\n };\n }\n\n destroy(): void {\n this.destroyed = true;\n try { this.ctx.close(); } catch { /* ignore */ }\n }\n}\n","import type { MediaContext, AudioCodec, VideoCodec } from \"../../types.js\";\nimport type { LibavVariant } from \"./libav-loader.js\";\n\n/**\n * Decide which libav.js variant to load for a given media context.\n *\n * - **webcodecs** (~5 MB, npm) — modern formats only, designed for the\n * WebCodecs bridge. Used when the codec is browser-supported and we just\n * need libav.js for demuxing or as a parser source.\n *\n * - **avbridge** (custom build, vendor/libav/) — has the AVI/ASF/FLV demuxers\n * and the legacy decoders (WMV3, MPEG-4 Part 2, VC-1, MS-MPEG4 v1/2/3,\n * AC-3, WMA*). Required for any of those formats; the npm variants ship\n * none of them.\n *\n * Rule: pick \"avbridge\" if either the container or any codec is one only the\n * custom build can handle. Otherwise pick \"webcodecs\".\n */\n\nconst LEGACY_CONTAINERS = new Set([\"avi\", \"asf\", \"flv\"]);\n\n/** Codecs the webcodecs variant can handle (native browser codecs only).\n * Anything not in these sets needs the custom avbridge variant. */\nconst WEBCODECS_AUDIO = new Set<AudioCodec>([\"aac\", \"mp3\", \"opus\", \"vorbis\", \"flac\"]);\nconst WEBCODECS_VIDEO = new Set<VideoCodec>([\"h264\", \"h265\", \"vp8\", \"vp9\", \"av1\"]);\n\nexport function pickLibavVariant(ctx: MediaContext): LibavVariant {\n if (LEGACY_CONTAINERS.has(ctx.container)) return \"avbridge\";\n for (const v of ctx.videoTracks) {\n // Any codec the webcodecs variant can't handle → need avbridge\n if (!WEBCODECS_VIDEO.has(v.codec)) return \"avbridge\";\n }\n for (const a of ctx.audioTracks) {\n if (!WEBCODECS_AUDIO.has(a.codec)) return \"avbridge\";\n }\n return \"webcodecs\";\n}\n","/**\n * Shared libav demux session. Opens a libav demuxer over a NormalizedSource\n * and provides a linear, cancellable packet pump.\n *\n * Phase 1 API: deliberately minimal. The first consumer is the AVI/ASF/FLV\n * transcode path (src/convert/transcode-libav.ts), which is strictly linear.\n * No seek, no track swapping — those were added to hybrid/fallback's\n * private pumps for playback reasons. When those paths migrate here, the\n * API will grow to cover their needs.\n *\n * The shared timestamp sanitizers (sanitizePacketTimestamp,\n * sanitizeFrameTimestamp) also live here. They were previously duplicated\n * in convert/remux.ts and strategies/hybrid/decoder.ts. The duplicates\n * stay put in Phase 1 with TODO pointers; migration is a follow-up.\n */\n\nimport { loadLibav, type LibavVariant } from \"../strategies/fallback/libav-loader.js\";\nimport { pickLibavVariant } from \"../strategies/fallback/variant-routing.js\";\nimport { prepareLibavInput } from \"./libav-http-reader.js\";\nimport type { MediaContext, TransportConfig } from \"../types.js\";\nimport type { NormalizedSource } from \"./source.js\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Structural types (mirror libav.js' shape without dragging in its types)\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\nexport interface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\nexport interface LibavFrame {\n data: unknown;\n format: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n nb_samples?: number;\n pts?: number;\n ptshi?: number;\n width?: number;\n height?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n f64toi64?(val: number): [number, number];\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Session\n// ─────────────────────────────────────────────────────────────────────────\n\nexport interface LibavDemuxSession {\n readonly libav: LibavRuntime;\n readonly fmtCtx: number;\n readonly streams: LibavStream[];\n readonly videoStream: LibavStream | null;\n readonly audioStream: LibavStream | null;\n /** True when the input is being streamed via HTTP Range requests. */\n readonly transport: \"http-range\" | \"blob\";\n /**\n * Linear read-to-EOF pump. Invokes the callbacks for each\n * ff_read_frame_multi batch (audio is handed over before video per\n * batch, matching the audio-first ordering that the hybrid/fallback\n * playback pumps use — see POSTMORTEMS.md entry 1).\n *\n * Honors the AbortSignal between batches. Invokes `onEof` once when\n * the demuxer returns EOF. Does NOT handle seek.\n */\n pump(cb: {\n onVideoPackets?: (pkts: LibavPacket[]) => Promise<void>;\n onAudioPackets?: (pkts: LibavPacket[]) => Promise<void>;\n onEof?: () => Promise<void>;\n signal?: AbortSignal;\n }): Promise<void>;\n destroy(): Promise<void>;\n}\n\nexport interface OpenLibavDemuxOptions {\n source: NormalizedSource;\n filename: string;\n context: MediaContext;\n transport?: TransportConfig;\n /** Override automatic variant picking. Defaults to pickLibavVariant(context). */\n variant?: LibavVariant;\n}\n\nexport async function openLibavDemux(opts: OpenLibavDemuxOptions): Promise<LibavDemuxSession> {\n const variant: LibavVariant = opts.variant ?? pickLibavVariant(opts.context);\n const libav = (await loadLibav(variant)) as unknown as LibavRuntime;\n\n const inputHandle = await prepareLibavInput(\n libav as unknown as Parameters<typeof prepareLibavInput>[0],\n opts.filename,\n opts.source,\n opts.transport,\n );\n\n const readPkt = await libav.av_packet_alloc();\n const [fmtCtx, streams] = await libav.ff_init_demuxer_file(opts.filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n const audioStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n let destroyed = false;\n\n async function pump(cb: Parameters<LibavDemuxSession[\"pump\"]>[0]): Promise<void> {\n while (!destroyed) {\n if (cb.signal?.aborted) return;\n\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n [readErr, packets] = await libav.ff_read_frame_multi(fmtCtx, readPkt, {\n // 16 KB batch — chosen so each read produces a handful of\n // packets, keeping downstream queues bounded. Same rationale\n // as the hybrid/fallback pumps (see CLAUDE.md note).\n limit: 16 * 1024,\n });\n } catch (err) {\n throw new Error(`libav-demux: ff_read_frame_multi failed: ${(err as Error).message}`);\n }\n\n if (destroyed || cb.signal?.aborted) return;\n\n const videoPackets = videoStream ? packets[videoStream.index] : undefined;\n const audioPackets = audioStream ? packets[audioStream.index] : undefined;\n\n // Audio-first ordering. Audio decode is cheap; video decode can\n // be expensive. Feeding audio first ensures the audio consumer\n // has samples to work with before any long video-decode block.\n if (cb.onAudioPackets && audioPackets && audioPackets.length > 0) {\n await cb.onAudioPackets(audioPackets);\n }\n if (destroyed || cb.signal?.aborted) return;\n if (cb.onVideoPackets && videoPackets && videoPackets.length > 0) {\n await cb.onVideoPackets(videoPackets);\n }\n\n if (readErr === libav.AVERROR_EOF) {\n if (cb.onEof) await cb.onEof();\n return;\n }\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n throw new Error(`libav-demux: ff_read_frame_multi returned ${readErr}`);\n }\n }\n }\n\n async function destroy(): Promise<void> {\n destroyed = true;\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmtCtx); } catch { /* ignore */ }\n try { await inputHandle.detach(); } catch { /* ignore */ }\n }\n\n return {\n libav,\n fmtCtx,\n streams,\n videoStream,\n audioStream,\n transport: inputHandle.transport,\n pump,\n destroy,\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Timestamp sanitizers (extracted from convert/remux.ts + hybrid/decoder.ts)\n//\n// libav can hand us packets/frames with pts = AV_NOPTS_VALUE (encoded as\n// ptshi = -2147483648, pts = 0) for inputs whose demuxer can't determine\n// presentation times. AVI is the canonical example. Downstream consumers\n// that treat pts as int64 overflow and throw.\n//\n// The sanitizer replaces invalid pts with a synthetic microsecond counter,\n// and normalizes valid pts to a 1/1e6 time_base so consumers don't need\n// to track the source time_base per packet.\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Sanitize a libav packet's timestamp. Mutates `pkt` in place.\n * If the packet has AV_NOPTS_VALUE, replaces pts with `nextUs()`.\n * Otherwise normalizes to µs with time_base = 1/1_000_000.\n */\nexport function sanitizePacketTimestamp(\n pkt: LibavPacket,\n nextUs: () => number,\n fallbackTimeBase?: [number, number],\n): void {\n const lo = pkt.pts ?? 0;\n const hi = pkt.ptshi ?? 0;\n const isInvalid = (hi === -2147483648 && lo === 0) || !Number.isFinite(lo);\n if (isInvalid) {\n const us = nextUs();\n pkt.pts = us;\n pkt.ptshi = 0;\n pkt.time_base_num = 1;\n pkt.time_base_den = 1_000_000;\n return;\n }\n const tb = fallbackTimeBase ?? [1, 1_000_000];\n const pts64 = hi * 0x100000000 + lo;\n const us = Math.round((pts64 * 1_000_000 * tb[0]) / tb[1]);\n if (Number.isFinite(us) && Math.abs(us) <= Number.MAX_SAFE_INTEGER) {\n pkt.pts = us;\n pkt.ptshi = us < 0 ? -1 : 0;\n pkt.time_base_num = 1;\n pkt.time_base_den = 1_000_000;\n return;\n }\n const fallback = nextUs();\n pkt.pts = fallback;\n pkt.ptshi = 0;\n pkt.time_base_num = 1;\n pkt.time_base_den = 1_000_000;\n}\n\n/**\n * Convert a raw libav packet's pts to seconds using the given stream\n * time_base, or return `null` if the packet lacks a valid pts. Used by\n * the hybrid + fallback strategies to track the demuxer's read-ahead\n * progress (the signal behind `<video>.buffered` on canvas strategies).\n *\n * Separate from `sanitizePacketTimestamp` — sanitization mutates the\n * packet and happens right before decoder feed; this peeks at the\n * timestamp earlier in the pump so we can track buffered extent without\n * perturbing the decode path.\n */\nexport function packetPtsSec(\n pkt: Pick<LibavPacket, \"pts\" | \"ptshi\">,\n timeBase: [number, number] | undefined,\n): number | null {\n const lo = pkt.pts ?? 0;\n const hi = pkt.ptshi ?? 0;\n const isInvalid = (hi === -2147483648 && lo === 0) || !Number.isFinite(lo);\n if (isInvalid) return null;\n const tb = timeBase ?? [1, 1_000_000];\n if (!tb[0] || !tb[1]) return null;\n const pts64 = hi * 0x100000000 + lo;\n const sec = (pts64 * tb[0]) / tb[1];\n return Number.isFinite(sec) ? sec : null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Audio frame → interleaved Float32 (extracted from\n// strategies/hybrid/decoder.ts + strategies/fallback/decoder.ts).\n//\n// libav hands us decoded audio frames in whichever sample format the codec\n// uses (FLTP, S16P, etc.). Most downstream consumers (Web Audio, WebCodecs\n// AudioEncoder) want interleaved Float32. This does the conversion without\n// any dependencies.\n// ─────────────────────────────────────────────────────────────────────────\n\nconst AV_SAMPLE_FMT_U8 = 0;\nconst AV_SAMPLE_FMT_S16 = 1;\nconst AV_SAMPLE_FMT_S32 = 2;\nconst AV_SAMPLE_FMT_FLT = 3;\nconst AV_SAMPLE_FMT_U8P = 5;\nconst AV_SAMPLE_FMT_S16P = 6;\nconst AV_SAMPLE_FMT_S32P = 7;\nconst AV_SAMPLE_FMT_FLTP = 8;\n\nexport interface InterleavedSamples {\n data: Float32Array;\n channels: number;\n sampleRate: number;\n}\n\nexport function libavFrameToInterleavedFloat32(frame: LibavFrame): InterleavedSamples | null {\n const channels = frame.channels ?? frame.ch_layout_nb_channels ?? 1;\n const sampleRate = frame.sample_rate ?? 44100;\n const nbSamples = frame.nb_samples ?? 0;\n if (nbSamples === 0) return null;\n\n const out = new Float32Array(nbSamples * channels);\n\n switch (frame.format) {\n case AV_SAMPLE_FMT_FLTP: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asFloat32(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = plane[i];\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_FLT: {\n const flat = asFloat32(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = flat[i];\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S16P: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asInt16(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = plane[i] / 32768;\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S16: {\n const flat = asInt16(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = flat[i] / 32768;\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S32P: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asInt32(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = plane[i] / 2147483648;\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_S32: {\n const flat = asInt32(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = flat[i] / 2147483648;\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_U8P: {\n const planes = ensurePlanes(frame.data, channels);\n for (let ch = 0; ch < channels; ch++) {\n const plane = asUint8(planes[ch]);\n for (let i = 0; i < nbSamples; i++) out[i * channels + ch] = (plane[i] - 128) / 128;\n }\n return { data: out, channels, sampleRate };\n }\n case AV_SAMPLE_FMT_U8: {\n const flat = asUint8(frame.data);\n for (let i = 0; i < nbSamples * channels; i++) out[i] = (flat[i] - 128) / 128;\n return { data: out, channels, sampleRate };\n }\n default:\n return null;\n }\n}\n\nfunction ensurePlanes(data: unknown, channels: number): unknown[] {\n if (Array.isArray(data)) return data;\n const arr = data as { length: number; subarray?: (a: number, b: number) => unknown };\n const len = arr.length;\n const perChannel = Math.floor(len / channels);\n const planes: unknown[] = [];\n for (let ch = 0; ch < channels; ch++) {\n planes.push(arr.subarray ? arr.subarray(ch * perChannel, (ch + 1) * perChannel) : arr);\n }\n return planes;\n}\n\nfunction asFloat32(x: unknown): Float32Array {\n if (x instanceof Float32Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Float32Array(ta.buffer, ta.byteOffset, ta.byteLength / 4);\n}\nfunction asInt16(x: unknown): Int16Array {\n if (x instanceof Int16Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Int16Array(ta.buffer, ta.byteOffset, ta.byteLength / 2);\n}\nfunction asInt32(x: unknown): Int32Array {\n if (x instanceof Int32Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Int32Array(ta.buffer, ta.byteOffset, ta.byteLength / 4);\n}\nfunction asUint8(x: unknown): Uint8Array {\n if (x instanceof Uint8Array) return x;\n const ta = x as { buffer: ArrayBuffer; byteOffset: number; byteLength: number };\n return new Uint8Array(ta.buffer, ta.byteOffset, ta.byteLength);\n}\n\n/**\n * Sanitize a decoded frame's timestamp. Mutates `frame` in place.\n * Returns nothing; callers that want derived metadata (e.g. a\n * VideoFrame timestamp in µs) should read `frame.pts` after calling.\n */\nexport function sanitizeFrameTimestamp(\n frame: LibavFrame,\n nextUs: () => number,\n fallbackTimeBase?: [number, number],\n): void {\n const lo = frame.pts ?? 0;\n const hi = frame.ptshi ?? 0;\n const isInvalid = (hi === -2147483648 && lo === 0) || !Number.isFinite(lo);\n if (isInvalid) {\n const us = nextUs();\n frame.pts = us;\n frame.ptshi = 0;\n return;\n }\n const tb = fallbackTimeBase ?? [1, 1_000_000];\n const pts64 = hi * 0x100000000 + lo;\n const us = Math.round((pts64 * 1_000_000 * tb[0]) / tb[1]);\n if (Number.isFinite(us) && Math.abs(us) <= Number.MAX_SAFE_INTEGER) {\n frame.pts = us;\n frame.ptshi = us < 0 ? -1 : 0;\n return;\n }\n const fallback = nextUs();\n frame.pts = fallback;\n frame.ptshi = 0;\n}\n","/**\n * Hybrid decoder: libav.js demux + WebCodecs VideoDecoder + libav audio decode.\n *\n * This is the hardware-accelerated path for files in containers mediabunny\n * can't read (AVI, ASF, FLV) but whose codecs ARE browser-supported.\n * libav.js handles demuxing, then:\n *\n * - **Video**: bridge.packetToEncodedVideoChunk → VideoDecoder (hardware)\n * - **Audio**: libav ff_decode_multi (software). Chrome's AudioDecoder\n * rejects raw MP3 packets from AVI, and audio decode is cheap enough\n * that software decode is fine.\n *\n * The demux pump loop, seek handling, and synthetic timestamp logic mirror\n * fallback/decoder.ts. The key difference is the video decode path.\n */\n\nimport { loadLibav, type LibavVariant } from \"../fallback/libav-loader.js\";\nimport { VideoRenderer } from \"../fallback/video-renderer.js\";\nimport { AudioOutput } from \"../fallback/audio-output.js\";\nimport type { MediaContext } from \"../../types.js\";\nimport { dbg } from \"../../util/debug.js\";\nimport { pickLibavVariant } from \"../fallback/variant-routing.js\";\nimport {\n sanitizePacketTimestamp,\n libavFrameToInterleavedFloat32,\n packetPtsSec,\n} from \"../../util/libav-demux.js\";\n\nexport interface HybridDecoderHandles {\n destroy(): Promise<void>;\n seek(timeSec: number): Promise<void>;\n /** Swap the active audio track — rebuilds the libav audio decoder + reseeks. */\n setAudioTrack(trackId: number, timeSec: number): Promise<void>;\n stats(): Record<string, unknown>;\n onFatalError(handler: (reason: string) => void): void;\n /**\n * The demuxer's read-ahead frontier in seconds — the highest pts\n * observed on any packet handed back from `ff_read_frame_multi`.\n * Monotonically non-decreasing: seeks don't reset it, since the\n * frontier represents \"how far we've ever demuxed through this\n * source,\" which matches what a seek-bar buffered indicator should\n * show. Backs `<video>.buffered` on canvas strategies. Returns 0\n * before any valid pts have been seen (some AVI/FLV sources may\n * never reach this — their `buffered` stays empty).\n */\n bufferedUntilSec(): number;\n}\n\nexport interface StartHybridDecoderOptions {\n /** Normalized source — either a Blob in memory or a URL we'll stream via Range requests. */\n source: import(\"../../util/source.js\").NormalizedSource;\n filename: string;\n context: MediaContext;\n renderer: VideoRenderer;\n audio: AudioOutput;\n transport?: import(\"../../types.js\").TransportConfig;\n}\n\nexport async function startHybridDecoder(opts: StartHybridDecoderOptions): Promise<HybridDecoderHandles> {\n const variant: LibavVariant = pickLibavVariant(opts.context);\n const libav = (await loadLibav(variant)) as unknown as LibavRuntime;\n const bridge = await loadBridge();\n\n // For URL sources, prepareLibavInput attaches an HTTP block reader so\n // libav demuxes via Range requests. For Blob sources, it falls back to\n // mkreadaheadfile (in-memory). The returned handle owns cleanup.\n const { prepareLibavInput } = await import(\"../../util/libav-http-reader.js\");\n const inputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], opts.filename, opts.source, opts.transport);\n\n const readPkt = await libav.av_packet_alloc();\n const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(opts.filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n // Audio stream is mutable (setAudioTrack swaps it). Prefer the id the\n // probe layer listed first so both entry points agree.\n const firstAudioTrackId = opts.context.audioTracks[0]?.id;\n let audioStream: LibavStream | null =\n (firstAudioTrackId != null\n ? streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === firstAudioTrackId)\n : undefined) ??\n streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n if (!videoStream && !audioStream) {\n throw new Error(\"hybrid decoder: file has no decodable streams\");\n }\n\n // ── Fatal error callback ──────────────────────────────────────────────\n let fatalHandler: ((reason: string) => void) | null = null;\n let fatalFired = false;\n\n function fireFatal(reason: string): void {\n if (fatalFired) return;\n fatalFired = true;\n fatalHandler?.(reason);\n }\n\n // ── WebCodecs VideoDecoder ────────────────────────────────────────────\n let videoDecoder: VideoDecoder | null = null;\n let videoTimeBase: [number, number] | undefined;\n\n if (videoStream) {\n try {\n const config = await bridge.videoStreamToConfig(libav, videoStream);\n if (!config) throw new Error(\"bridge returned null config\");\n\n const supported = await VideoDecoder.isConfigSupported(config);\n if (!supported.supported) throw new Error(`VideoDecoder does not support config: ${JSON.stringify(config)}`);\n\n videoDecoder = new VideoDecoder({\n output: (frame: VideoFrame) => {\n opts.renderer.enqueue(frame);\n videoFramesDecoded++;\n },\n error: (err: DOMException) => {\n console.error(\"[avbridge] WebCodecs VideoDecoder error:\", err);\n fireFatal(`WebCodecs VideoDecoder error: ${err.message}`);\n },\n });\n videoDecoder.configure(config);\n\n if (videoStream.time_base_num && videoStream.time_base_den) {\n videoTimeBase = [videoStream.time_base_num, videoStream.time_base_den];\n }\n } catch (err) {\n console.error(\"[avbridge] hybrid: failed to init WebCodecs VideoDecoder:\", err);\n fireFatal(`WebCodecs VideoDecoder init failed: ${(err as Error).message}`);\n // Clean up and throw — the player will escalate to fallback\n await inputHandle.detach().catch(() => {});\n throw err;\n }\n }\n\n // ── libav software AudioDecoder ───────────────────────────────────────\n let audioDec: SoftDecoder | null = null;\n let audioTimeBase: [number, number] | undefined;\n\n if (audioStream) {\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(audioStream.codec_id, {\n codecpar: audioStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n if (audioStream.time_base_num && audioStream.time_base_den) {\n audioTimeBase = [audioStream.time_base_num, audioStream.time_base_den];\n }\n } catch (err) {\n console.warn(\n \"[avbridge] hybrid: audio decoder unavailable for this codec — playing video with wall-clock timing:\",\n (err as Error).message,\n );\n }\n }\n\n // No audio decoder? Switch the audio output into wall-clock mode so the\n // video renderer doesn't stall waiting for an audio clock that never starts.\n if (!audioDec) {\n opts.audio.setNoAudio();\n }\n\n if (!videoDecoder && !audioDec) {\n await inputHandle.detach().catch(() => {});\n throw new Error(\"hybrid decoder: could not initialize any decoders\");\n }\n\n // ── Bitstream filter for MPEG-4 Part 2 packed B-frames ───────────────\n let bsfCtx: number | null = null;\n let bsfPkt: number | null = null;\n let bsfRequiredButMissing = false;\n if (videoStream && opts.context.videoTracks[0]?.codec === \"mpeg4\") {\n try {\n bsfCtx = await libav.av_bsf_list_parse_str_js(\"mpeg4_unpack_bframes\");\n if (bsfCtx != null && bsfCtx >= 0) {\n const parIn = await libav.AVBSFContext_par_in(bsfCtx);\n await libav.avcodec_parameters_copy(parIn, videoStream.codecpar);\n await libav.av_bsf_init(bsfCtx);\n bsfPkt = await libav.av_packet_alloc();\n dbg.info(\"bsf\", \"mpeg4_unpack_bframes BSF active (hybrid)\");\n } else {\n bsfRequiredButMissing = true;\n bsfCtx = null;\n }\n } catch (err) {\n bsfRequiredButMissing = true;\n bsfCtx = null;\n bsfPkt = null;\n dbg.warn(\"bsf\", `hybrid: mpeg4_unpack_bframes BSF init failed: ${(err as Error).message}`);\n }\n if (bsfRequiredButMissing) {\n // eslint-disable-next-line no-console\n console.error(\n \"[avbridge] MPEG-4 Part 2 (DivX/Xvid) detected but mpeg4_unpack_bframes \" +\n \"BSF is unavailable in this libav variant. Files with packed B-frames \" +\n \"will play with incorrect frame ordering. Rebuild the libav variant \" +\n \"with the `avbsf` fragment included.\",\n );\n }\n }\n\n async function applyBSF(packets: LibavPacket[]): Promise<LibavPacket[]> {\n if (!bsfCtx || !bsfPkt) return packets;\n const out: LibavPacket[] = [];\n for (const pkt of packets) {\n await libav.ff_copyin_packet(bsfPkt, pkt);\n const sendErr = await libav.av_bsf_send_packet(bsfCtx, bsfPkt);\n if (sendErr < 0) {\n // BSF rejected — DON'T pass the original through. Its buffer may\n // have been transferred into the worker by ff_copyin_packet, so\n // re-posting it would throw DataCloneError on a detached\n // ArrayBuffer. See fallback/decoder.ts for the full explanation.\n continue;\n }\n while (true) {\n const recvErr = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (recvErr < 0) break;\n out.push(await libav.ff_copyout_packet(bsfPkt));\n }\n }\n return out;\n }\n\n async function flushBSF(): Promise<void> {\n if (!bsfCtx || !bsfPkt) return;\n try {\n // Use av_bsf_flush to reset the BSF without putting it in EOF mode.\n // See the matching comment in src/strategies/fallback/decoder.ts —\n // sending NULL as the flush signal puts the BSF into EOF state so\n // subsequent sends fail, which corrupts the post-seek pipeline with\n // detached-buffer DataCloneErrors.\n if (libav.av_bsf_flush) {\n await libav.av_bsf_flush(bsfCtx);\n } else {\n while (true) {\n const err = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (err < 0) break;\n }\n }\n } catch { /* ignore */ }\n }\n\n // ── Mutable state ─────────────────────────────────────────────────────\n let destroyed = false;\n let pumpToken = 0;\n let pumpRunning: Promise<void> | null = null;\n\n let packetsRead = 0;\n let videoFramesDecoded = 0;\n let audioFramesDecoded = 0;\n let videoChunksFed = 0;\n let bufferedUntilSec = 0;\n\n // Synthetic video timestamp for packets with AV_NOPTS_VALUE (audio\n // uses the packet PTS directly — see decodeAudioBatch).\n let syntheticVideoUs = 0;\n\n const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);\n const videoFps = videoTrackInfo?.fps && videoTrackInfo.fps > 0 ? videoTrackInfo.fps : 30;\n const videoFrameStepUs = Math.max(1, Math.round(1_000_000 / videoFps));\n\n // ── Pump loop ─────────────────────────────────────────────────────────\n\n async function pumpLoop(myToken: number): Promise<void> {\n while (!destroyed && myToken === pumpToken) {\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n [readErr, packets] = await libav.ff_read_frame_multi(fmt_ctx, readPkt, {\n limit: 16 * 1024,\n });\n } catch (err) {\n console.error(\"[avbridge] hybrid ff_read_frame_multi failed:\", err);\n return;\n }\n\n if (myToken !== pumpToken || destroyed) return;\n\n const videoPackets = videoStream ? packets[videoStream.index] : undefined;\n const audioPackets = audioStream ? packets[audioStream.index] : undefined;\n\n // Track how far the demuxer has read through the source — the\n // signal behind `<video>.buffered` on this strategy. Peek at raw\n // packet pts using each stream's native time_base (before the\n // sanitizePacketTimestamp call later in the loop, which\n // overwrites to µs). Monotonic: we never walk it backward.\n if (videoPackets && videoTimeBase) {\n for (const pkt of videoPackets) {\n const sec = packetPtsSec(pkt, videoTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n }\n }\n if (audioPackets && audioTimeBase) {\n for (const pkt of audioPackets) {\n const sec = packetPtsSec(pkt, audioTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n }\n }\n\n // Decode audio BEFORE video. Same rationale as fallback decoder\n // (POSTMORTEMS.md entry 1, fix #2): audio decode via libav's\n // ff_decode_multi is a blocking WASM call that prevents rAF from\n // firing. For heavy codecs like DTS, a single batch can take\n // 10-50 ms. Processing audio first ensures the audio scheduler is\n // fed before video decode starts, reducing perceived stutter.\n if (audioDec && audioPackets && audioPackets.length > 0) {\n await decodeAudioBatch(audioPackets, myToken, /*flush*/ false, audioTimeBase);\n }\n if (myToken !== pumpToken || destroyed) return;\n\n // Yield to the event loop so the video renderer's rAF callback\n // can fire between the audio decode (blocking) and the video feed\n // (async). Without this, the renderer starves during DTS decode.\n await new Promise((r) => setTimeout(r, 0));\n if (myToken !== pumpToken || destroyed) return;\n\n // Feed video packets to WebCodecs VideoDecoder (after BSF if applicable)\n if (videoDecoder && videoPackets && videoPackets.length > 0) {\n const processed = await applyBSF(videoPackets);\n for (const pkt of processed) {\n if (myToken !== pumpToken || destroyed) return;\n sanitizePacketTimestamp(pkt, () => {\n const ts = syntheticVideoUs;\n syntheticVideoUs += videoFrameStepUs;\n return ts;\n }, videoTimeBase);\n try {\n const chunk = bridge.packetToEncodedVideoChunk(pkt, videoStream);\n videoDecoder.decode(chunk);\n videoChunksFed++;\n } catch (err) {\n if (videoChunksFed === 0) {\n console.warn(\"[avbridge] hybrid: packetToEncodedVideoChunk failed:\", err);\n fireFatal(`WebCodecs chunk creation failed: ${(err as Error).message}`);\n return;\n }\n }\n }\n }\n\n packetsRead += (videoPackets?.length ?? 0) + (audioPackets?.length ?? 0);\n\n // Backpressure: WebCodecs decodeQueueSize + audio buffer + renderer queue\n while (\n !destroyed &&\n myToken === pumpToken &&\n ((videoDecoder && videoDecoder.decodeQueueSize > 10) ||\n opts.audio.bufferAhead() > 2.0 ||\n opts.renderer.queueDepth() >= opts.renderer.queueHighWater)\n ) {\n await new Promise((r) => setTimeout(r, 50));\n }\n\n if (readErr === libav.AVERROR_EOF) {\n // Flush WebCodecs decoder\n if (videoDecoder && videoDecoder.state === \"configured\") {\n try { await videoDecoder.flush(); } catch { /* ignore */ }\n }\n // Flush libav audio decoder\n if (audioDec) await decodeAudioBatch([], myToken, true);\n return;\n }\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n console.warn(\"[avbridge] hybrid ff_read_frame_multi returned\", readErr);\n return;\n }\n }\n }\n\n async function decodeAudioBatch(\n pkts: LibavPacket[],\n myToken: number,\n flush = false,\n tb?: [number, number],\n ) {\n if (!audioDec || destroyed || myToken !== pumpToken) return;\n\n // Capture packet-level PTS before decode (same rationale as fallback\n // decoder — see POSTMORTEMS.md 2026-05-31: libav's reported\n // `frame.pts` is unreliable for some container/codec combinations;\n // the demuxer's packet PTS is reliable). For mp3/aac the packet→frame\n // mapping is 1:1, so the PTS array aligns with `allFrames`.\n const pktPtsSec: (number | null)[] = pkts.map((p) =>\n tb ? packetPtsSec(p, tb) : null,\n );\n\n // For heavy codecs (DTS, AC3), decode in small sub-batches and yield\n // between them so the event loop can run rAF for video painting.\n // Each ff_decode_multi call is a blocking WASM invocation.\n const AUDIO_SUB_BATCH = 4; // packets per sub-batch\n let allFrames: LibavFrame[] = [];\n\n for (let i = 0; i < pkts.length; i += AUDIO_SUB_BATCH) {\n if (myToken !== pumpToken || destroyed) return;\n const slice = pkts.slice(i, i + AUDIO_SUB_BATCH);\n const isLast = i + AUDIO_SUB_BATCH >= pkts.length;\n try {\n const frames = await libav.ff_decode_multi(\n audioDec.c,\n audioDec.pkt,\n audioDec.frame,\n slice,\n isLast && flush ? { fin: true, ignoreErrors: true } : { ignoreErrors: true },\n );\n allFrames = allFrames.concat(frames);\n } catch (err) {\n console.error(\"[avbridge] hybrid audio decode failed:\", err);\n return;\n }\n // Yield between sub-batches so rAF can fire\n if (!isLast) await new Promise((r) => setTimeout(r, 0));\n }\n\n // Handle flush-only call (empty pkts array)\n if (pkts.length === 0 && flush) {\n try {\n allFrames = await libav.ff_decode_multi(\n audioDec.c, audioDec.pkt, audioDec.frame, [],\n { fin: true, ignoreErrors: true },\n );\n } catch (err) {\n console.error(\"[avbridge] hybrid audio flush failed:\", err);\n return;\n }\n }\n\n if (myToken !== pumpToken || destroyed) return;\n const frames = allFrames;\n\n for (let i = 0; i < frames.length; i++) {\n if (myToken !== pumpToken || destroyed) return;\n const f = frames[i];\n const samples = libavFrameToInterleavedFloat32(f);\n if (samples) {\n const pts = pktPtsSec[i] ?? null;\n opts.audio.schedule(samples.data, samples.channels, samples.sampleRate, pts);\n audioFramesDecoded++;\n }\n }\n }\n\n // Kick off initial pump\n pumpToken = 1;\n pumpRunning = pumpLoop(pumpToken).catch((err) =>\n console.error(\"[avbridge] hybrid pump failed:\", err),\n );\n\n return {\n onFatalError(handler: (reason: string) => void): void {\n fatalHandler = handler;\n // If fatal already fired before handler was attached, fire immediately\n if (fatalFired) handler(\"WebCodecs decode failed (error occurred before handler attached)\");\n },\n\n async destroy() {\n destroyed = true;\n pumpToken++;\n try { await pumpRunning; } catch { /* ignore */ }\n try { if (bsfCtx) await libav.av_bsf_free(bsfCtx); } catch { /* ignore */ }\n try { if (bsfPkt) await libav.av_packet_free?.(bsfPkt); } catch { /* ignore */ }\n try { if (videoDecoder && videoDecoder.state !== \"closed\") videoDecoder.close(); } catch { /* ignore */ }\n try { if (audioDec) await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmt_ctx); } catch { /* ignore */ }\n try { await inputHandle.detach(); } catch { /* ignore */ }\n },\n\n async setAudioTrack(trackId, timeSec) {\n if (audioStream && audioStream.index === trackId) return;\n const newStream = streams.find(\n (s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === trackId,\n );\n if (!newStream) {\n console.warn(\"[avbridge] hybrid: setAudioTrack — no stream with id\", trackId);\n return;\n }\n\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n // Tear down old audio decoder, build new one.\n if (audioDec) {\n try { await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n audioDec = null;\n }\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(newStream.codec_id, {\n codecpar: newStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n audioTimeBase = newStream.time_base_num && newStream.time_base_den\n ? [newStream.time_base_num, newStream.time_base_den]\n : undefined;\n } catch (err) {\n console.warn(\n \"[avbridge] hybrid: setAudioTrack init failed — switching to no-audio:\",\n (err as Error).message,\n );\n audioDec = null;\n opts.audio.setNoAudio();\n }\n\n audioStream = newStream;\n\n // Re-seek demuxer to current time for the new track.\n try {\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] hybrid: setAudioTrack seek failed:\", err);\n }\n\n // Flush video decoder too — demuxer moved back to a keyframe.\n try {\n if (videoDecoder && videoDecoder.state === \"configured\") {\n await videoDecoder.flush();\n }\n } catch { /* ignore */ }\n await flushBSF();\n\n syntheticVideoUs = Math.round(timeSec * 1_000_000);\n\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] hybrid pump failed (post-setAudioTrack):\", err),\n );\n },\n\n async seek(timeSec) {\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n try {\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] hybrid av_seek_frame failed:\", err);\n }\n\n // Flush WebCodecs VideoDecoder\n try {\n if (videoDecoder && videoDecoder.state === \"configured\") {\n await videoDecoder.flush();\n }\n } catch { /* ignore */ }\n\n // Flush libav audio decoder\n try {\n if (audioDec) await libav.avcodec_flush_buffers?.(audioDec.c);\n } catch { /* ignore */ }\n await flushBSF();\n\n syntheticVideoUs = Math.round(timeSec * 1_000_000);\n\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] hybrid pump failed (post-seek):\", err),\n );\n },\n\n bufferedUntilSec() {\n return bufferedUntilSec;\n },\n\n stats() {\n return {\n decoderType: \"webcodecs-hybrid\",\n packetsRead,\n videoFramesDecoded,\n videoChunksFed,\n audioFramesDecoded,\n bsfApplied: bsfCtx ? [\"mpeg4_unpack_bframes\"] : [],\n bsfMissing: bsfRequiredButMissing ? [\"mpeg4_unpack_bframes\"] : [],\n videoDecodeQueueSize: videoDecoder?.decodeQueueSize ?? 0,\n // Confirmed transport info — see fallback decoder for the pattern.\n _transport: inputHandle.transport === \"http-range\" ? \"http-range\" : \"memory\",\n _rangeSupported: inputHandle.transport === \"http-range\",\n ...opts.renderer.stats(),\n ...opts.audio.stats(),\n };\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Packet timestamp sanitizer for WebCodecs chunks.\n//\n// AVI packets often have AV_NOPTS_VALUE. The bridge's packetToEncodedVideoChunk\n// uses the packet's pts + time_base. We normalize to microseconds with a 1/1e6\n// time_base to avoid overflow.\n// ─────────────────────────────────────────────────────────────────────────────\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Bridge loader\n// ─────────────────────────────────────────────────────────────────────────────\n\nasync function loadBridge(): Promise<BridgeModule> {\n try {\n const wrapper = await import(\"../fallback/libav-import.js\");\n return wrapper.libavBridge as unknown as BridgeModule;\n } catch (err) {\n throw new Error(\n `failed to load libavjs-webcodecs-bridge: ${(err as Error).message}`,\n );\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Structural types\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface SoftDecoder {\n c: number;\n pkt: number;\n frame: number;\n}\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavFrame {\n data: unknown;\n format: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n nb_samples?: number;\n pts?: number;\n ptshi?: number;\n width?: number;\n height?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n AVSEEK_FLAG_BACKWARD?: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n ff_init_decoder(\n codec: number | string,\n config?: { codecpar?: number; time_base?: [number, number] },\n ): Promise<[number, number, number, number]>;\n ff_decode_multi(\n c: number,\n pkt: number,\n frame: number,\n packets: LibavPacket[],\n opts?: { fin?: boolean; ignoreErrors?: boolean },\n ): Promise<LibavFrame[]>;\n ff_free_decoder?(c: number, pkt: number, frame: number): Promise<void>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n av_seek_frame(\n fmt_ctx: number,\n stream: number,\n tsLo: number,\n tsHi: number,\n flags: number,\n ): Promise<number>;\n avcodec_flush_buffers?(c: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n f64toi64?(val: number): [number, number];\n\n // BSF methods\n av_bsf_list_parse_str_js(str: string): Promise<number>;\n AVBSFContext_par_in(ctx: number): Promise<number>;\n avcodec_parameters_copy(dst: number, src: number): Promise<number>;\n av_bsf_init(ctx: number): Promise<number>;\n av_bsf_send_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_receive_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_flush?(ctx: number): Promise<void>;\n av_bsf_free(ctx: number): Promise<void>;\n ff_copyin_packet(pktPtr: number, packet: LibavPacket): Promise<void>;\n ff_copyout_packet(pkt: number): Promise<LibavPacket>;\n}\n\ninterface BridgeModule {\n videoStreamToConfig(libav: unknown, stream: unknown): Promise<VideoDecoderConfig | null>;\n packetToEncodedVideoChunk(pkt: unknown, stream: unknown): EncodedVideoChunk;\n}\n","/**\n * Synthesize a `TimeRanges`-shaped object for the HTMLMediaElement contract\n * on canvas strategies (hybrid/fallback). The real `TimeRanges` interface\n * is browser-only and not constructable; this object duck-types it.\n *\n * `ranges` is an array of `[start, end]` pairs in seconds, in ascending\n * order. The returned object exposes `length`, `start(i)`, `end(i)` —\n * the full surface consumers actually use.\n *\n * NOTE: Plain objects and real TimeRanges aren't `instanceof`-comparable,\n * but consumer code virtually never checks that. The methods + length\n * property are what matters.\n */\nexport function makeTimeRanges(ranges: Array<[number, number]>): TimeRanges {\n const frozen = ranges.slice();\n const impl = {\n get length(): number {\n return frozen.length;\n },\n start(index: number): number {\n if (index < 0 || index >= frozen.length) {\n throw new DOMException(\n `TimeRanges.start: index ${index} out of range (length=${frozen.length})`,\n \"IndexSizeError\",\n );\n }\n return frozen[index][0];\n },\n end(index: number): number {\n if (index < 0 || index >= frozen.length) {\n throw new DOMException(\n `TimeRanges.end: index ${index} out of range (length=${frozen.length})`,\n \"IndexSizeError\",\n );\n }\n return frozen[index][1];\n },\n };\n return impl as TimeRanges;\n}\n","import type { MediaContext, PlaybackSession, TransportConfig } from \"../../types.js\";\nimport { VideoRenderer } from \"../fallback/video-renderer.js\";\nimport { AudioOutput } from \"../fallback/audio-output.js\";\nimport { startHybridDecoder, type HybridDecoderHandles } from \"./decoder.js\";\nimport { makeTimeRanges } from \"../../util/time-ranges.js\";\n\n/**\n * Hybrid strategy session.\n *\n * Uses libav.js for demuxing + WebCodecs VideoDecoder for hardware-accelerated\n * video decode + libav.js software decode for audio. Same canvas + Web Audio\n * output as the fallback strategy.\n *\n * Falls back to the pure-WASM fallback strategy if WebCodecs fails (via the\n * onFatalError callback that the player wires to its escalation mechanism).\n */\n\nconst READY_AUDIO_BUFFER_SECONDS = 0.3;\nconst READY_TIMEOUT_SECONDS = 10;\n\nexport async function createHybridSession(\n ctx: MediaContext,\n target: HTMLVideoElement,\n transport?: TransportConfig,\n): Promise<PlaybackSession> {\n // Normalize the source so URL inputs go through the libav HTTP block\n // reader instead of being buffered into memory.\n const { normalizeSource } = await import(\"../../util/source.js\");\n const source = await normalizeSource(ctx.source);\n\n const fps = ctx.videoTracks[0]?.fps ?? 30;\n const audio = new AudioOutput();\n const renderer = new VideoRenderer(target, audio, fps);\n\n let handles: HybridDecoderHandles;\n try {\n handles = await startHybridDecoder({\n source,\n filename: ctx.name ?? \"input.bin\",\n context: ctx,\n renderer,\n audio,\n transport,\n });\n } catch (err) {\n audio.destroy();\n renderer.destroy();\n throw err;\n }\n\n // Patch <video> element for the unified player layer. The underlying\n // <video> never has its own src; all playback state lives in the audio\n // clock + canvas renderer. We expose that state via property getters\n // so standard HTMLMediaElement consumers (like <avbridge-player>'s\n // controls UI) see the real values.\n Object.defineProperty(target, \"currentTime\", {\n configurable: true,\n get: () => audio.now(),\n set: (v: number) => { void doSeek(v); },\n });\n Object.defineProperty(target, \"paused\", {\n configurable: true,\n get: () => !audio.isPlaying(),\n });\n Object.defineProperty(target, \"volume\", {\n configurable: true,\n get: () => audio.getVolume(),\n set: (v: number) => {\n audio.setVolume(v);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n Object.defineProperty(target, \"muted\", {\n configurable: true,\n get: () => audio.getMuted(),\n set: (m: boolean) => {\n audio.setMuted(m);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n if (ctx.duration && Number.isFinite(ctx.duration)) {\n Object.defineProperty(target, \"duration\", {\n configurable: true,\n get: () => ctx.duration ?? NaN,\n });\n }\n Object.defineProperty(target, \"playbackRate\", {\n configurable: true,\n get: () => audio.getPlaybackRate(),\n set: (v: number) => {\n audio.setPlaybackRate(v);\n target.dispatchEvent(new Event(\"ratechange\"));\n },\n });\n // HTMLMediaElement parity surfaces — see fallback/index.ts for rationale.\n Object.defineProperty(target, \"readyState\", {\n configurable: true,\n get: (): number => {\n if (!renderer.hasFrames()) return 0;\n if (!audio.isPlaying() && audio.bufferAhead() <= 0 && !audio.isNoAudio()) return 1;\n return 2;\n },\n });\n Object.defineProperty(target, \"seekable\", {\n configurable: true,\n get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0\n ? [[0, ctx.duration]]\n : []),\n });\n Object.defineProperty(target, \"buffered\", {\n configurable: true,\n get: () => {\n const end = handles.bufferedUntilSec();\n return makeTimeRanges(end > 0 ? [[0, end]] : []);\n },\n });\n\n async function waitForBuffer(): Promise<void> {\n const start = performance.now();\n while (true) {\n const audioReady = audio.isNoAudio() || audio.bufferAhead() >= READY_AUDIO_BUFFER_SECONDS;\n if (audioReady && renderer.hasFrames()) {\n return;\n }\n if ((performance.now() - start) / 1000 > READY_TIMEOUT_SECONDS) return;\n await new Promise((r) => setTimeout(r, 50));\n }\n }\n\n async function doSeek(timeSec: number): Promise<void> {\n const wasPlaying = audio.isPlaying();\n // HTMLMediaElement contract — see fallback/index.ts for the why.\n target.dispatchEvent(new Event(\"seeking\"));\n await audio.pause().catch(() => {});\n await handles.seek(timeSec).catch((err) =>\n console.warn(\"[avbridge] hybrid decoder seek failed:\", err),\n );\n await audio.reset(timeSec);\n renderer.flush();\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n target.dispatchEvent(new Event(\"seeked\"));\n }\n\n // HTMLMediaElement contract: `loadedmetadata` once the session is\n // ready. The inner <video> never fires this itself on the hybrid\n // path — it has no src.\n queueMicrotask(() => {\n try { target.dispatchEvent(new Event(\"loadedmetadata\")); } catch { /* element torn down */ }\n });\n\n // Store the fatal error handler so the player can wire escalation\n let fatalErrorHandler: ((reason: string) => void) | null = null;\n handles.onFatalError((reason) => fatalErrorHandler?.(reason));\n\n return {\n strategy: \"hybrid\",\n\n async play() {\n if (!audio.isPlaying()) {\n await waitForBuffer();\n await audio.start();\n // Dispatch play/playing events so HTMLMediaElement consumers\n // (e.g. <avbridge-player>'s controls UI) update their state.\n target.dispatchEvent(new Event(\"play\"));\n target.dispatchEvent(new Event(\"playing\"));\n }\n },\n\n pause() {\n void audio.pause();\n target.dispatchEvent(new Event(\"pause\"));\n },\n\n async seek(time) {\n await doSeek(time);\n },\n\n async setAudioTrack(id) {\n if (!ctx.audioTracks.some((t) => t.id === id)) {\n console.warn(\"[avbridge] hybrid: setAudioTrack — unknown track id\", id);\n return;\n }\n const wasPlaying = audio.isPlaying();\n const currentTime = audio.now();\n await audio.pause().catch(() => {});\n await handles.setAudioTrack(id, currentTime).catch((err) =>\n console.warn(\"[avbridge] hybrid: handles.setAudioTrack failed:\", err),\n );\n await audio.reset(currentTime);\n renderer.flush();\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n },\n\n async setSubtitleTrack(_id) {\n // Post-MVP for hybrid strategy\n },\n\n getCurrentTime() {\n return audio.now();\n },\n\n onFatalError(handler: (reason: string) => void) {\n fatalErrorHandler = handler;\n },\n\n async destroy() {\n await handles.destroy();\n renderer.destroy();\n audio.destroy();\n try {\n delete (target as unknown as Record<string, unknown>).currentTime;\n delete (target as unknown as Record<string, unknown>).duration;\n delete (target as unknown as Record<string, unknown>).paused;\n delete (target as unknown as Record<string, unknown>).volume;\n delete (target as unknown as Record<string, unknown>).muted;\n delete (target as unknown as Record<string, unknown>).readyState;\n delete (target as unknown as Record<string, unknown>).seekable;\n delete (target as unknown as Record<string, unknown>).playbackRate;\n } catch { /* ignore */ }\n },\n\n getRuntimeStats() {\n return handles.stats();\n },\n };\n}\n","/**\n * libav.js demux + decode loop for the fallback strategy.\n *\n * Design:\n *\n * - **Always software decode.** The fallback strategy is only entered when\n * classification has decided no browser decoder will handle the codec set,\n * so the WebCodecs hardware path is dead weight here. Going through libav\n * uniformly also avoids brittleness around `EncodedAudioChunk` framing for\n * codecs like MP3-in-AVI where the browser's AudioDecoder rejects libav's\n * raw demuxed packets.\n *\n * - **Cancellable pump loop.** Each pump iteration is gated on a token that\n * `seek()` increments. When the token changes mid-batch, the loop exits\n * and a fresh one starts at the new position. This is how seek interrupts\n * the decoder cleanly without having to await an arbitrarily long\n * `ff_decode_multi` call.\n *\n * - **Synthetic timestamps.** AVI demuxers report `AV_NOPTS_VALUE` for most\n * packets — they're frame-indexed, not time-indexed. We replace any\n * invalid pts with a per-stream synthetic counter (frame index × 1e6/fps\n * for video; sample-accurate for audio) so the bridge's chunk constructor\n * doesn't overflow int64.\n */\n\nimport { loadLibav, type LibavVariant } from \"./libav-loader.js\";\nimport { VideoRenderer } from \"./video-renderer.js\";\nimport { AudioOutput } from \"./audio-output.js\";\nimport type { MediaContext } from \"../../types.js\";\nimport { pickLibavVariant } from \"./variant-routing.js\";\nimport { dbg } from \"../../util/debug.js\";\n\n/** True when `globalThis.AVBRIDGE_DEBUG` is set. Used to gate verbose\n * per-packet / per-frame trace lines that are useful for debugging\n * post-seek pts behavior but unreadable in normal use. */\nfunction isDebug(): boolean {\n return typeof globalThis !== \"undefined\"\n && !!(globalThis as Record<string, unknown>).AVBRIDGE_DEBUG;\n}\nimport {\n libavFrameToInterleavedFloat32,\n packetPtsSec,\n} from \"../../util/libav-demux.js\";\n\nexport interface DecoderHandles {\n destroy(): Promise<void>;\n /** Seek to the given time in seconds. Returns once the new pump has been kicked off. */\n seek(timeSec: number): Promise<void>;\n /**\n * Switch the active audio track. The decoder tears down the current audio\n * decoder, initializes one for the stream whose container id matches\n * `trackId` (== libav `stream.index`), seeks the demuxer to `timeSec`, and\n * restarts the pump. No-op if the track is already active.\n */\n setAudioTrack(trackId: number, timeSec: number): Promise<void>;\n stats(): Record<string, unknown>;\n /**\n * The demuxer's read-ahead frontier in seconds. See\n * `HybridDecoderHandles.bufferedUntilSec` for the full contract —\n * same semantics, same consumer (`<video>.buffered` on canvas\n * strategies).\n */\n bufferedUntilSec(): number;\n}\n\nexport interface StartDecoderOptions {\n /** Normalized source — either a Blob in memory or a URL we'll stream via Range requests. */\n source: import(\"../../util/source.js\").NormalizedSource;\n filename: string;\n context: MediaContext;\n renderer: VideoRenderer;\n audio: AudioOutput;\n transport?: import(\"../../types.js\").TransportConfig;\n}\n\nexport async function startDecoder(opts: StartDecoderOptions): Promise<DecoderHandles> {\n // Fallback always does full software decode. The \"webcodecs\" libav\n // variant is trimmed to demuxing + WebCodecs-companion use; it lacks\n // software decoders for codecs whose browsers usually handle them\n // (e.g. h265). When we've reached fallback for those codecs, it's\n // precisely because the browser *can't* decode them — so we need\n // the full \"avbridge\" variant with software decoders. pickLibavVariant\n // is still right for the hybrid strategy (which software-decodes only\n // audio and relies on WebCodecs for video), but not here.\n const variant: LibavVariant = \"avbridge\";\n void pickLibavVariant; // kept in scope for future opt-in use\n const libav = (await loadLibav(variant)) as unknown as LibavRuntime;\n const bridge = await loadBridge();\n\n // For URL sources, prepareLibavInput attaches an HTTP block reader so\n // libav demuxes via Range requests. For Blob sources, it falls back to\n // mkreadaheadfile (in-memory). The returned handle owns cleanup.\n const { prepareLibavInput } = await import(\"../../util/libav-http-reader.js\");\n const inputHandle = await prepareLibavInput(libav as unknown as Parameters<typeof prepareLibavInput>[0], opts.filename, opts.source, opts.transport);\n\n // Pre-allocate one AVPacket for ff_read_frame_multi to reuse.\n const readPkt = await libav.av_packet_alloc();\n\n const [fmt_ctx, streams] = await libav.ff_init_demuxer_file(opts.filename);\n const videoStream = streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_VIDEO) ?? null;\n // Audio stream is mutable so setAudioTrack() can swap it. Default to the\n // track the context picked first (matches probe ordering). We resolve by\n // container id so the selection survives stream reordering.\n const firstAudioTrackId = opts.context.audioTracks[0]?.id;\n let audioStream: LibavStream | null =\n (firstAudioTrackId != null\n ? streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === firstAudioTrackId)\n : undefined) ??\n streams.find((s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO) ?? null;\n\n if (!videoStream && !audioStream) {\n throw new Error(\"fallback decoder: file has no decodable streams\");\n }\n\n // ── Set up software decoders ─────────────────────────────────────────\n let videoDec: SoftDecoder | null = null;\n let audioDec: SoftDecoder | null = null;\n let videoTimeBase: [number, number] | undefined;\n let audioTimeBase: [number, number] | undefined;\n\n if (videoStream) {\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(videoStream.codec_id, {\n codecpar: videoStream.codecpar,\n });\n videoDec = { c, pkt, frame };\n if (videoStream.time_base_num && videoStream.time_base_den) {\n videoTimeBase = [videoStream.time_base_num, videoStream.time_base_den];\n }\n } catch (err) {\n console.error(\"[avbridge] failed to init video decoder:\", err);\n }\n }\n\n if (audioStream) {\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(audioStream.codec_id, {\n codecpar: audioStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n if (audioStream.time_base_num && audioStream.time_base_den) {\n audioTimeBase = [audioStream.time_base_num, audioStream.time_base_den];\n }\n } catch (err) {\n console.warn(\n \"[avbridge] fallback: audio decoder unavailable — playing video with wall-clock timing:\",\n (err as Error).message,\n );\n }\n }\n\n // No audio decoder? Switch audio output into wall-clock mode so video can\n // play even when the audio codec isn't supported by the loaded libav variant.\n if (!audioDec) {\n opts.audio.setNoAudio();\n }\n\n if (!videoDec && !audioDec) {\n await inputHandle.detach().catch(() => {});\n const codecs = [\n videoStream ? `video: ${opts.context.videoTracks[0]?.codec ?? \"unknown\"}` : null,\n audioStream ? `audio: ${opts.context.audioTracks[0]?.codec ?? \"unknown\"}` : null,\n ].filter(Boolean).join(\", \");\n throw new Error(\n `fallback decoder: could not initialize any libav decoders (${codecs}). ` +\n `The \"${variant}\" libav variant lacks software decoders for these codecs — ` +\n `rebuild with scripts/build-libav.sh including the missing decoder, ` +\n `or use a lighter strategy (native, remux, hybrid) instead.`,\n );\n }\n\n // ── Bitstream filter for MPEG-4 Part 2 packed B-frames ───────────────\n // Applied unconditionally for mpeg4 video — the BSF is a no-op when\n // the stream doesn't actually have packed B-frames, so false positives\n // are harmless. Without it, DivX files with packed B-frames produce\n // garbled frame ordering.\n let bsfCtx: number | null = null;\n let bsfPkt: number | null = null;\n let bsfRequiredButMissing = false;\n if (videoStream && opts.context.videoTracks[0]?.codec === \"mpeg4\") {\n try {\n bsfCtx = await libav.av_bsf_list_parse_str_js(\"mpeg4_unpack_bframes\");\n if (bsfCtx != null && bsfCtx >= 0) {\n const parIn = await libav.AVBSFContext_par_in(bsfCtx);\n await libav.avcodec_parameters_copy(parIn, videoStream.codecpar);\n await libav.av_bsf_init(bsfCtx);\n bsfPkt = await libav.av_packet_alloc();\n dbg.info(\"bsf\", \"mpeg4_unpack_bframes BSF active\");\n } else {\n bsfRequiredButMissing = true;\n bsfCtx = null;\n }\n } catch (err) {\n bsfRequiredButMissing = true;\n bsfCtx = null;\n bsfPkt = null;\n dbg.warn(\"bsf\", `mpeg4_unpack_bframes BSF init failed: ${(err as Error).message}`);\n }\n if (bsfRequiredButMissing) {\n // eslint-disable-next-line no-console\n console.error(\n \"[avbridge] MPEG-4 Part 2 (DivX/Xvid) detected but mpeg4_unpack_bframes \" +\n \"BSF is unavailable in this libav variant. Files with packed B-frames \" +\n \"will play with incorrect frame ordering (backwards PTS jumps, heavy \" +\n \"late-drop stuttering). Rebuild the libav variant with the `avbsf` \" +\n \"fragment included. See docs/dev/POSTMORTEMS.md for details.\",\n );\n }\n }\n\n /** Run video packets through the BSF. Returns original packets if no BSF active. */\n async function applyBSF(packets: LibavPacket[]): Promise<LibavPacket[]> {\n if (!bsfCtx || !bsfPkt) return packets;\n const out: LibavPacket[] = [];\n for (const pkt of packets) {\n await libav.ff_copyin_packet(bsfPkt, pkt);\n const sendErr = await libav.av_bsf_send_packet(bsfCtx, bsfPkt);\n if (sendErr < 0) {\n // BSF rejected — DON'T pass the original through. `ff_copyin_packet`\n // above may have transferred pkt.data's ArrayBuffer into the worker,\n // in which case re-posting the same packet to the decoder fails\n // with DataCloneError on a detached buffer. Skipping the packet is\n // safer; the decoder's error recovery will resync at the next\n // keyframe if this was transient.\n continue;\n }\n while (true) {\n const recvErr = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (recvErr < 0) break; // EAGAIN or EOF\n out.push(await libav.ff_copyout_packet(bsfPkt));\n }\n }\n return out;\n }\n\n /** Flush the BSF (on seek or EOF) to drain any internally buffered packets. */\n async function flushBSF(): Promise<void> {\n if (!bsfCtx || !bsfPkt) return;\n try {\n // `av_bsf_flush` resets the BSF state without putting it in EOF\n // mode. The old approach — sending a NULL packet — is the EOF\n // signal; after that every subsequent `av_bsf_send_packet` fails,\n // which made `applyBSF` fall back to pushing the ORIGINAL packet\n // through (with its buffer already transferred to WASM by\n // `ff_copyin_packet`). That detached buffer then failed to\n // `postMessage` into the decoder worker with DataCloneError on\n // the first post-seek batch.\n if (libav.av_bsf_flush) {\n await libav.av_bsf_flush(bsfCtx);\n } else {\n // Fallback for older libav.js variants without av_bsf_flush:\n // drain any internal packets but DON'T send NULL-EOF.\n while (true) {\n const err = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);\n if (err < 0) break;\n }\n }\n } catch { /* ignore flush errors */ }\n }\n\n // ── Mutable state shared across pump loops ───────────────────────────\n let destroyed = false;\n let pumpToken = 0; // bumped on seek; pump loops bail when token changes\n let pumpRunning: Promise<void> | null = null;\n\n let packetsRead = 0;\n let videoFramesDecoded = 0;\n let bufferedUntilSec = 0;\n let audioFramesDecoded = 0;\n\n // Decode-rate watchdog. Samples framesDecoded every second and\n // compares against realtime expected frames for the source fps. If\n // the decoder sustains less than 60% of realtime for more than\n // 5 seconds (counting only time since the first frame emerged),\n // emits a one-shot diagnostic so users know why playback is\n // stuttering instead of guessing. A second one-shot fires if the\n // renderer's overflow-drop rate exceeds 10% of decoded frames —\n // that symptom means the decoder is BURSTING faster than the\n // renderer can drain, which is a different bug from \"decoder slow\".\n let watchdogFirstFrameMs = 0;\n let watchdogSlowSinceMs = 0;\n let watchdogSlowWarned = false;\n let watchdogOverflowWarned = false;\n\n // Content clock for video frames. Tracks the last frame's content time\n // in µs. The invariant per emit:\n // - raw libav pts valid → lastContentUs = raw_pts (sync to truth)\n // - raw libav pts NOPTS → lastContentUs += frameStep (extend by one frame)\n // This makes synthetic labels always relative to the *immediately\n // preceding* frame's real content, self-correcting at every valid pts.\n // -1 means \"unanchored\" — pre-anchor NOPTS frames are discarded outright\n // because we don't know where the decoder actually landed. The anchor\n // is established at the first valid raw pts post-seek.\n //\n // This replaced an older \"synthetic counter reset to seekTarget on seek\"\n // path which stamped NOPTS preroll frames with the user's requested seek\n // time — producing labels 4+ seconds ahead of actual content, dropping\n // every valid-pts frame as a \"regression\", and surfacing as a ~2s\n // post-seek fast-forward as the slow-advancing synthetic counter slowly\n // converged with real content. See POSTMORTEMS.md (2026-06-01).\n let lastContentUs = -1;\n let firstValidPtsLoggedSinceSeek = false;\n\n // Diagnostic: first post-seek audio packet's PTS. Logged once per seek\n // so the operator can see the demuxer's actual content alignment vs\n // the user's click. With PTS-based audio scheduling, audio packets\n // with PTS before the seek target *naturally* don't get scheduled\n // (their computed ctxStart falls in the past) — no manual trim needed.\n let seenFirstAudioPacketSinceSeek = false;\n let seekTargetSec = 0;\n // Post-seek diagnostic counters. Capture raw pts/dts/pos for the first\n // ~N packets and frames after each seek so we can tell whether libav\n // hands us a valid pts at seek landing, when (if ever) it becomes\n // valid mid-stream, and whether sanitize's NOPTS fallback is firing.\n let diagPktsLoggedSinceSeek = 0;\n let diagFramesLoggedSinceSeek = 0;\n let diagFrameKeysDumped = false;\n const DIAG_MAX_PKTS = 100;\n const DIAG_MAX_FRAMES = 300;\n\n // Throughput instrumentation — answers \"is the decoder keeping up?\".\n // All counters are cumulative since bootstrap (not reset on seek), so\n // the stats panel can compute rolling deltas. Times are wall-ms spent\n // inside the respective libav call; JS↔WASM boundary is inside the\n // worker so this is the real cost the producer pays per batch.\n let videoDecodeMsTotal = 0;\n let audioDecodeMsTotal = 0;\n let videoDecodeBatches = 0;\n let audioDecodeBatches = 0;\n let readMsTotal = 0;\n let readBatches = 0;\n let pumpThrottleMsTotal = 0;\n let pumpThrottleEntries = 0;\n let slowestVideoBatchMs = 0;\n let newestVideoPtsUs = 0; // set by decodeVideoBatch after each emitted frame\n let lastEmittedPtsUs = -1; // previous emitted frame's pts, for monotonicity check\n let ptsRegressions = 0;\n let worstPtsRegressionMs = 0;\n\n const videoTrackInfo = opts.context.videoTracks.find((t) => t.id === videoStream?.index);\n const videoFps = videoTrackInfo?.fps && videoTrackInfo.fps > 0 ? videoTrackInfo.fps : 30;\n const videoFrameStepUs = Math.max(1, Math.round(1_000_000 / videoFps));\n\n // ── Pump loop ─────────────────────────────────────────────────────────\n\n async function pumpLoop(myToken: number): Promise<void> {\n while (!destroyed && myToken === pumpToken) {\n let readErr: number;\n let packets: Record<number, LibavPacket[]>;\n try {\n // Batch size tunes the tradeoff between JS↔WASM call overhead\n // (small = more crossings per second) and queue burstiness\n // (large = decoder hands the renderer big bursts at once that\n // can blow past the renderer's 64-frame hard cap before the\n // per-batch `queueHighWater` throttle runs).\n //\n // We tried 64 KB and saw ~30% overflow drops on RMVB:rv40 at\n // 1024x768 because one decode batch regularly produced >30\n // frames. 16 KB keeps each batch ≈ 4-6 video packets at\n // typical bitrates, so the worst-case queue spike stays under\n // `queueHighWater` and the throttle has a chance to apply\n // backpressure *between* batches rather than within one.\n const _readStart = performance.now();\n [readErr, packets] = await libav.ff_read_frame_multi(fmt_ctx, readPkt, {\n limit: 16 * 1024,\n });\n readMsTotal += performance.now() - _readStart;\n readBatches++;\n } catch (err) {\n console.error(\"[avbridge] ff_read_frame_multi failed:\", err);\n return;\n }\n\n if (myToken !== pumpToken || destroyed) return;\n\n const videoPackets = videoStream ? packets[videoStream.index] : undefined;\n const audioPackets = audioStream ? packets[audioStream.index] : undefined;\n\n // Track demuxer read-ahead for <video>.buffered on this strategy.\n // Peek raw pts before sanitizePacketTimestamp (which would\n // clobber to µs and lose the source-native scale). Monotonic;\n // seeks don't reset.\n if (videoPackets && videoTimeBase) {\n for (const pkt of videoPackets) {\n const sec = packetPtsSec(pkt, videoTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n // [DIAG-PKT] Raw pre-sanitize packet fields for the first N\n // post-seek video packets. Most important question: does the\n // FIRST packet after av_seek_frame carry a valid pts? If yes,\n // we can anchor synthetic counter to that — cheap & robust.\n // If no, fall back to pkt_pos → AVI index → chunk_idx × frameDur.\n if (isDebug() && diagPktsLoggedSinceSeek < DIAG_MAX_PKTS) {\n const rawHi = (pkt as { ptshi?: number }).ptshi ?? 0;\n const rawLo = pkt.pts ?? 0;\n const isInvalidPts = (rawHi === -2147483648 && rawLo === 0);\n const rawPts64 = isInvalidPts ? null : (rawHi * 0x100000000 + rawLo);\n const rawSec = rawPts64 != null && videoTimeBase\n ? (rawPts64 * videoTimeBase[0]) / videoTimeBase[1]\n : null;\n const pktKeys = diagPktsLoggedSinceSeek === 0\n ? `[keys: ${Object.keys(pkt).join(\",\")}]`\n : \"\";\n // eslint-disable-next-line no-console\n console.log(\n `[DIAG-PKT] vidx=${diagPktsLoggedSinceSeek} ` +\n `pts=${isInvalidPts ? \"NOPTS\" : rawPts64} ` +\n `pts_sec=${rawSec != null ? rawSec.toFixed(3) : \"n/a\"} ` +\n `ptshi=${rawHi} ptslo=${rawLo} ` +\n `flags=0x${(pkt.flags ?? 0).toString(16)} ` +\n `keyframe=${((pkt.flags ?? 0) & 1) ? \"Y\" : \"N\"} ` +\n `stream=${pkt.stream_index} ` +\n `dataLen=${pkt.data?.length ?? 0} ` +\n `seekTarget=${seekTargetSec.toFixed(3)} ` +\n pktKeys,\n );\n diagPktsLoggedSinceSeek++;\n }\n }\n }\n if (audioPackets && audioTimeBase) {\n for (const pkt of audioPackets) {\n const sec = packetPtsSec(pkt, audioTimeBase);\n if (sec != null && sec > bufferedUntilSec) bufferedUntilSec = sec;\n }\n // Diagnostic: log the first post-seek audio packet's PTS. With\n // PTS-based scheduling, packets whose PTS is before the seek\n // target won't be played (AudioOutput skips them silently), so\n // this is informational only — it tells you how far off the\n // demuxer's seek granularity is from the user's click.\n if (!seenFirstAudioPacketSinceSeek && audioPackets.length > 0) {\n const firstSec = packetPtsSec(audioPackets[0], audioTimeBase);\n if (firstSec != null && Number.isFinite(firstSec)) {\n seenFirstAudioPacketSinceSeek = true;\n dbg.info(\"av-anchor\",\n `seek-target=${seekTargetSec.toFixed(3)}s, ` +\n `first-audio-pkt-pts=${firstSec.toFixed(3)}s ` +\n `(Δ=${((firstSec - seekTargetSec) * 1000).toFixed(1)}ms — ` +\n `pre-target packets will be skipped by AudioOutput)`,\n );\n }\n }\n }\n\n // Decode audio BEFORE video. On software-decode-bound content\n // (rv40/mpeg4/wmv3 @ 720p+) a single video batch can take\n // 200-400 ms of wall time; if the scheduler hasn't been fed\n // during that window, audio output runs dry and the user hears\n // clicks/gaps. Audio is time-critical; video can drop a frame\n // and nobody notices. Audio decode is also typically <1 ms per\n // packet for cook/mp3/aac, so doing it first barely delays\n // video decoding at all.\n if (audioDec && audioPackets && audioPackets.length > 0) {\n await decodeAudioBatch(audioPackets, myToken, /*flush*/ false, audioTimeBase);\n }\n if (myToken !== pumpToken || destroyed) return;\n if (videoDec && videoPackets && videoPackets.length > 0) {\n const processed = await applyBSF(videoPackets);\n await decodeVideoBatch(processed, myToken);\n }\n\n packetsRead += (videoPackets?.length ?? 0) + (audioPackets?.length ?? 0);\n\n // ── Decode-rate watchdog ──────────────────────────────────────\n if (videoFramesDecoded > 0) {\n if (watchdogFirstFrameMs === 0) {\n watchdogFirstFrameMs = performance.now();\n }\n const elapsedSinceFirst = (performance.now() - watchdogFirstFrameMs) / 1000;\n\n // 1. Slow-decode detection (sustained <60% of realtime fps).\n if (elapsedSinceFirst > 1 && !watchdogSlowWarned) {\n const expectedFrames = elapsedSinceFirst * videoFps;\n const ratio = videoFramesDecoded / expectedFrames;\n if (ratio < 0.6) {\n if (watchdogSlowSinceMs === 0) watchdogSlowSinceMs = performance.now();\n if ((performance.now() - watchdogSlowSinceMs) / 1000 > 5) {\n watchdogSlowWarned = true;\n console.warn(\n \"[avbridge:decode-rate]\",\n `decoder is running slower than realtime: ` +\n `${videoFramesDecoded} frames in ${elapsedSinceFirst.toFixed(1)}s ` +\n `(${(videoFramesDecoded / elapsedSinceFirst).toFixed(1)} fps vs ${videoFps} fps source — ` +\n `${(ratio * 100).toFixed(0)}% of realtime). ` +\n `Playback will stutter. Typical causes: software decode of a codec with no WebCodecs support ` +\n `(rv40, mpeg4 @ 720p+, wmv3), or a resolution too large for single-threaded WASM to keep up with.`,\n );\n }\n } else {\n watchdogSlowSinceMs = 0;\n }\n }\n\n // 2. Overflow-drop detection (>10% of decoded frames dropped\n // by the renderer's hard cap). This means the decoder\n // produces BURSTS — it's fast enough on average but one\n // batch delivers >30 frames at a time, overflowing before\n // the queueHighWater throttle can apply backpressure.\n // Symptom is different from \"decoder slow\": here the fps\n // ratio looks fine but the user sees choppy playback.\n if (\n !watchdogOverflowWarned &&\n videoFramesDecoded > 100 // wait for a meaningful sample\n ) {\n const rendererStats = opts.renderer.stats() as { framesDroppedOverflow?: number };\n const overflow = rendererStats.framesDroppedOverflow ?? 0;\n if (overflow / videoFramesDecoded > 0.1) {\n watchdogOverflowWarned = true;\n console.warn(\n \"[avbridge:overflow-drop]\",\n `renderer is dropping ${overflow}/${videoFramesDecoded} frames ` +\n `(${((overflow / videoFramesDecoded) * 100).toFixed(0)}%) because the decoder ` +\n `is producing bursts faster than the canvas can drain. Symptom: choppy ` +\n `playback despite decoder keeping up on average. Fix would be smaller ` +\n `read batches in the pump loop or a lower queueHighWater cap — see ` +\n `src/strategies/fallback/decoder.ts.`,\n );\n }\n }\n }\n\n // Throttle: only on audio buffer (mediaTimeOfNext - now() > 2 s).\n // Renderer queue backpressure is enforced at the *enqueue* side in\n // `decodeVideoBatch` — when the queue is at `queueHighWater`, the\n // freshly decoded VideoFrame is closed without being enqueued, so\n // the decoder keeps consuming packets in order. That preserves the\n // reference-frame state needed to decode P/B frames cleanly during\n // post-seek catch-up. Throttling the *pump* on queue depth here\n // would block demuxer reads, which would also stall audio packet\n // processing and starve `audio.bufferAhead()`.\n {\n const _throttleStart = performance.now();\n let _throttled = false;\n while (\n !destroyed &&\n myToken === pumpToken &&\n opts.audio.bufferAhead() > 2.0\n ) {\n _throttled = true;\n await new Promise((r) => setTimeout(r, 50));\n }\n if (_throttled) {\n pumpThrottleMsTotal += performance.now() - _throttleStart;\n pumpThrottleEntries++;\n }\n }\n\n if (readErr === libav.AVERROR_EOF) {\n if (videoDec) await decodeVideoBatch([], myToken, /*flush*/ true);\n if (audioDec) await decodeAudioBatch([], myToken, /*flush*/ true);\n return;\n }\n if (readErr && readErr !== 0 && readErr !== -libav.EAGAIN) {\n console.warn(\"[avbridge] ff_read_frame_multi returned\", readErr);\n return;\n }\n }\n }\n\n async function decodeVideoBatch(pkts: LibavPacket[], myToken: number, flush = false) {\n if (!videoDec || destroyed || myToken !== pumpToken) return;\n let frames: LibavFrame[];\n const _t0 = performance.now();\n try {\n frames = await libav.ff_decode_multi(\n videoDec.c,\n videoDec.pkt,\n videoDec.frame,\n pkts,\n flush ? { fin: true, ignoreErrors: true } : { ignoreErrors: true },\n );\n } catch (err) {\n console.error(\"[avbridge] video decode batch failed:\", err);\n return;\n }\n {\n const _dt = performance.now() - _t0;\n videoDecodeMsTotal += _dt;\n videoDecodeBatches++;\n if (_dt > slowestVideoBatchMs) slowestVideoBatchMs = _dt;\n }\n if (myToken !== pumpToken || destroyed) return;\n\n for (const f of frames) {\n if (myToken !== pumpToken || destroyed) return;\n // [DIAG-FRAME] Capture raw pre-sanitize fields. One-shot key dump\n // on first frame post-seek so we can see which fields libav\n // actually exposes (best_effort_timestamp? pkt_dts? pkt_pos?).\n const _diagShouldLog = isDebug() && diagFramesLoggedSinceSeek < DIAG_MAX_FRAMES;\n const _diagRawHi = f.ptshi ?? 0;\n const _diagRawLo = f.pts ?? 0;\n const _diagInvalid = (_diagRawHi === -2147483648 && _diagRawLo === 0);\n const _diagRawPts64 = _diagInvalid ? null : (_diagRawHi * 0x100000000 + _diagRawLo);\n const _diagRawSec = _diagRawPts64 != null && videoTimeBase\n ? (_diagRawPts64 * videoTimeBase[0]) / videoTimeBase[1]\n : null;\n if (_diagShouldLog && !diagFrameKeysDumped) {\n diagFrameKeysDumped = true;\n const allKeys = Object.keys(f);\n const fieldDump: Record<string, unknown> = {};\n for (const k of allKeys) {\n const v = (f as unknown as Record<string, unknown>)[k];\n // Skip the data buffer; everything else is metadata.\n if (k === \"data\") continue;\n if (typeof v === \"object\" && v !== null && \"length\" in (v as object)) continue;\n fieldDump[k] = v;\n }\n // eslint-disable-next-line no-console\n console.log(`[DIAG-FRAME] FIRST FRAME post-seek — all keys: ${allKeys.join(\",\")}`);\n // eslint-disable-next-line no-console\n console.log(`[DIAG-FRAME] FIRST FRAME field dump:`, fieldDump);\n }\n // Convert raw libav pts (in stream timebase) to µs, or null if NOPTS.\n let rawUs: number | null = null;\n if (!_diagInvalid && _diagRawPts64 != null) {\n const tb = videoTimeBase ?? [1, 1_000_000];\n const us = Math.round((_diagRawPts64 * 1_000_000 * tb[0]) / tb[1]);\n if (Number.isFinite(us) && Math.abs(us) <= Number.MAX_SAFE_INTEGER) {\n rawUs = us;\n }\n }\n\n // Forward declare _diagLog so PRE-ANCHOR-DROP can call it.\n // Final pts isn't known until after the anchor/step block, so we pass\n // it as a parameter rather than closing over a `let`.\n const _diagLog = (decision: string, finalPtsUs: number, sanFallback: boolean): void => {\n if (!_diagShouldLog) return;\n const ptsSrc = sanFallback\n ? `SYNTHETIC(${_diagInvalid ? \"NOPTS\" : \"invalid-range\"})`\n : \"LIBAV\";\n // eslint-disable-next-line no-console\n console.log(\n `[DIAG-FRAME] vidx=${diagFramesLoggedSinceSeek} ` +\n `raw_pts=${_diagInvalid ? \"NOPTS\" : _diagRawPts64} ` +\n `raw_pts_sec=${_diagRawSec != null ? _diagRawSec.toFixed(3) : \"n/a\"} ` +\n `pts_src=${ptsSrc} ` +\n `final_pts_us=${finalPtsUs} ` +\n `final_pts_sec=${(finalPtsUs / 1_000_000).toFixed(3)} ` +\n `seekTarget=${seekTargetSec.toFixed(3)} ` +\n `offset_to_target_ms=${((finalPtsUs / 1000) - (seekTargetSec * 1000)).toFixed(1)} ` +\n `lastEmittedPts_us=${lastEmittedPtsUs} ` +\n `decision=${decision}`,\n );\n diagFramesLoggedSinceSeek++;\n };\n\n // Anchor + step invariant.\n // - Unanchored (post-seek, no valid pts seen yet) AND NOPTS frame\n // → discard outright. We don't know where the decoder landed, so\n // stamping a synthetic label would be a lie (this was the source\n // of the post-seek fast-forward bug).\n // - First valid raw pts → anchor `lastContentUs` to it. The pipeline\n // below will then drop this and subsequent frames as pre-target\n // until content reaches seekTarget.\n // - Anchored AND valid → sync `lastContentUs` to truth.\n // - Anchored AND NOPTS → step `lastContentUs += frameStep`.\n let _diagSanFallbackFired = false;\n const seekTargetUs = Math.round(seekTargetSec * 1_000_000);\n if (lastContentUs < 0) {\n if (rawUs == null) {\n // Cold-start keyframe special case. At seekTargetSec === 0 the\n // demuxer guarantees the very first emitted keyframe is content\n // 0 (container start=0.000000). Anchoring there directly avoids\n // discarding the opening I-frame — without this, cold start\n // loses 1-2 frames and the first paint is ~80ms late.\n //\n // STRICTLY gated to seekTarget === 0. The seek path proved\n // correct via the offset-ground-truth experiment (POSTMORTEMS\n // 2026-06-01); this branch must not change its behavior.\n //\n // Why keyframe-pin instead of back-computing from the first\n // valid pts: the I/P/B reorder is densest at the stream head,\n // so `firstValidPts − N × frameStep` is off by however many\n // early B-frames the decoder dropped. The keyframe identity\n // (`f.key_frame === 1`) is the only signal that doesn't depend\n // on frame-spacing assumptions.\n const isColdStartKeyframe =\n seekTargetSec === 0\n && (f as { key_frame?: number }).key_frame === 1;\n if (isColdStartKeyframe) {\n lastContentUs = 0;\n _diagSanFallbackFired = true;\n // Fall through: the frame gets labeled 0 and runs through\n // the regression/pre-target/enqueue pipeline normally.\n } else {\n // Pre-anchor NOPTS: discard. Decoder retains the frame internally\n // as a reference — we just don't expose it to the renderer.\n _diagLog(\"PRE-ANCHOR-DROP\", 0, true);\n continue;\n }\n } else {\n // First valid raw pts post-seek = the anchor.\n lastContentUs = rawUs;\n if (!firstValidPtsLoggedSinceSeek) {\n firstValidPtsLoggedSinceSeek = true;\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(\n `[avbridge:decoder] post-seek anchor established: ` +\n `first valid raw pts = ${(rawUs / 1000).toFixed(1)}ms ` +\n `(seekTarget = ${(seekTargetSec * 1000).toFixed(1)}ms, ` +\n `Δ = ${((rawUs - seekTargetUs) / 1000).toFixed(1)}ms)`,\n );\n }\n // Guard: if the first valid pts is at or beyond the seek\n // target, the pre-anchor NOPTS frames we already discarded\n // may have straddled the target. In normal AVI MPEG-4 seeks,\n // the demuxer lands well before the target (previous\n // keyframe), so this shouldn't happen — log a warning if it\n // does so we know to implement a pkt_pos→AVI-index\n // back-computation path. The cold-start case (seekTarget=0)\n // is handled by the keyframe-pin branch above and shouldn't\n // reach this warning.\n if (rawUs >= seekTargetUs) {\n // eslint-disable-next-line no-console\n console.warn(\n `[avbridge:decoder] first valid raw pts ≥ seek target — ` +\n `pre-anchor NOPTS frames may have straddled the target ` +\n `and been mis-discarded. First painted frame may be late ` +\n `by up to one keyframe interval.`,\n );\n }\n }\n }\n } else {\n if (rawUs != null) {\n lastContentUs = rawUs; // sync to truth on every valid pts\n } else {\n lastContentUs += videoFrameStepUs; // extend from last truth\n _diagSanFallbackFired = true;\n }\n }\n // Write the content label into the frame so the bridge sees it.\n f.pts = lastContentUs;\n f.ptshi = lastContentUs < 0 ? -1 : 0;\n const _fPts = lastContentUs;\n if (_fPts > newestVideoPtsUs) newestVideoPtsUs = _fPts;\n if (lastEmittedPtsUs >= 0 && _fPts < lastEmittedPtsUs) {\n _diagLog(\"REGRESSED-DROP\", _fPts, _diagSanFallbackFired);\n // Decoder emitted a frame with lower PTS than the previous\n // output. Dropping out-of-order frames here is the right move:\n // the renderer's paint loop assumes monotonic queue order and\n // breaks (stale frame stuck at head, newer frames drop as late,\n // paint cadence collapses) if we let them through. Two scenarios\n // produce this in practice:\n // - Post-seek tail of a B-frame reorder buffer that survives\n // avcodec_flush_buffers + av_bsf_flush (rare but observed\n // on mpeg4 after large seeks).\n // - A BSF that doesn't repair packed B-frames perfectly and\n // lets a DTS/PTS swap through.\n // The decoder will catch up at the next I-frame.\n ptsRegressions++;\n const regressMs = (lastEmittedPtsUs - _fPts) / 1000;\n if (regressMs > worstPtsRegressionMs) worstPtsRegressionMs = regressMs;\n if (ptsRegressions <= 10) {\n // eslint-disable-next-line no-console\n console.warn(\n `[avbridge:decoder] dropped out-of-order frame #${ptsRegressions}: ` +\n `pts=${(_fPts / 1000).toFixed(1)}ms < previous=${(lastEmittedPtsUs / 1000).toFixed(1)}ms ` +\n `(regression=${regressMs.toFixed(1)}ms). Typically a post-seek B-frame reorder tail.`,\n );\n }\n continue; // skip enqueue\n }\n lastEmittedPtsUs = _fPts;\n // Decode-to-display: after a seek the demuxer lands at the\n // keyframe ≤ click target and the decoder produces frames\n // starting there. Pre-target frames are still DECODED (they're\n // reference frames for later P/B decodes) but they MUST NOT be\n // displayed — otherwise the renderer paints them in a brief\n // fast-forward burst as it catches up to audio (T_click). Drop\n // them at the enqueue boundary; the decoder doesn't care.\n //\n // Tolerance of one frame duration: source frames are quantized\n // (PTS = N × frameStep) but the user's click is arbitrary, so\n // the frame nearest the click is typically a few ms *before* it.\n // Convention (matches `<video>.currentTime = T` and ffplay):\n // display the frame at the largest PTS ≤ T.\n const targetUs = Math.round(seekTargetSec * 1_000_000);\n if (_fPts < targetUs - videoFrameStepUs) {\n _diagLog(\"PRE-TARGET-DROP\", _fPts, _diagSanFallbackFired);\n continue;\n }\n try {\n const vf = bridge.laFrameToVideoFrame(f, { timeBase: [1, 1_000_000] });\n // Renderer-queue backpressure at the enqueue side. Discarding\n // here (rather than throttling the pump on `queueHighWater`)\n // keeps the decoder consuming packets sequentially so its\n // reference-frame state stays intact — essential during\n // post-seek catch-up, when the pump must continue reading\n // packets to advance the demuxer past pre-target audio. Without\n // sequential decode, the next batch's P/B frames decode against\n // a stale reference and produce gray + glitchy output until\n // the next keyframe.\n if (opts.renderer.queueDepth() >= opts.renderer.queueHighWater) {\n vf.close();\n _diagLog(\"OVERFLOW-DROP\", _fPts, _diagSanFallbackFired);\n } else {\n opts.renderer.enqueue(vf);\n _diagLog(\"ENQUEUED\", _fPts, _diagSanFallbackFired);\n }\n videoFramesDecoded++;\n } catch (err) {\n if (videoFramesDecoded === 0) {\n console.warn(\"[avbridge] laFrameToVideoFrame failed:\", err);\n }\n _diagLog(\"BRIDGE-ERROR\", _fPts, _diagSanFallbackFired);\n }\n }\n }\n\n async function decodeAudioBatch(\n pkts: LibavPacket[],\n myToken: number,\n flush = false,\n tb?: [number, number],\n ) {\n if (!audioDec || destroyed || myToken !== pumpToken) return;\n // Capture the packet-level PTS *before* decoding. libav's reported\n // `frame.pts` after decode is unreliable for mp3-in-AVI (returns a\n // value that doesn't agree with the stream's reported time base —\n // see POSTMORTEMS.md 2026-05-31). The demuxer's packet PTS is\n // reliable, and for mp3/aac the packet→frame mapping is 1:1, so we\n // forward each packet's PTS to the matching output frame. For codecs\n // where the mapping isn't 1:1, the trailing frames fall back to a\n // synthetic running counter — same behavior as before this change.\n const pktPtsSec: (number | null)[] = pkts.map((p) =>\n tb ? packetPtsSec(p, tb) : null,\n );\n let frames: LibavFrame[];\n const _t0 = performance.now();\n try {\n frames = await libav.ff_decode_multi(\n audioDec.c,\n audioDec.pkt,\n audioDec.frame,\n pkts,\n flush ? { fin: true, ignoreErrors: true } : { ignoreErrors: true },\n );\n } catch (err) {\n console.error(\"[avbridge] audio decode batch failed:\", err);\n return;\n }\n audioDecodeMsTotal += performance.now() - _t0;\n audioDecodeBatches++;\n if (myToken !== pumpToken || destroyed) return;\n\n for (let i = 0; i < frames.length; i++) {\n if (myToken !== pumpToken || destroyed) return;\n const f = frames[i];\n const samples = libavFrameToInterleavedFloat32(f);\n if (samples) {\n const pts = pktPtsSec[i] ?? null;\n if (isDebug()) {\n const dur = samples.data.length / samples.channels / samples.sampleRate;\n // Log every frame — we need to see what happens around seeks.\n // Also surface explicitly when the per-frame PTS is null, which\n // would route the chunk to the LEGACY rebase path in AudioOutput.\n // eslint-disable-next-line no-console\n console.log(`[TRACE-DEC] audio frame #${audioFramesDecoded} pts=${pts != null ? pts.toFixed(4) : \"NULL\"} dur=${dur.toFixed(4)} samples=${samples.data.length / samples.channels} sr=${samples.sampleRate} ch=${samples.channels} pktsIn=${pkts.length} framesOut=${frames.length}`);\n }\n opts.audio.schedule(samples.data, samples.channels, samples.sampleRate, pts);\n audioFramesDecoded++;\n }\n }\n }\n\n // Kick off the initial pump.\n pumpToken = 1;\n pumpRunning = pumpLoop(pumpToken).catch((err) =>\n console.error(\"[avbridge] decoder pump failed:\", err),\n );\n\n return {\n async destroy() {\n destroyed = true;\n pumpToken++;\n try { await pumpRunning; } catch { /* ignore */ }\n try { if (bsfCtx) await libav.av_bsf_free(bsfCtx); } catch { /* ignore */ }\n try { if (bsfPkt) await libav.av_packet_free?.(bsfPkt); } catch { /* ignore */ }\n try { if (videoDec) await libav.ff_free_decoder?.(videoDec.c, videoDec.pkt, videoDec.frame); } catch { /* ignore */ }\n try { if (audioDec) await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n try { await libav.av_packet_free?.(readPkt); } catch { /* ignore */ }\n try { await libav.avformat_close_input_js(fmt_ctx); } catch { /* ignore */ }\n try { await inputHandle.detach(); } catch { /* ignore */ }\n },\n\n async setAudioTrack(trackId, timeSec) {\n if (audioStream && audioStream.index === trackId) return;\n const newStream = streams.find(\n (s) => s.codec_type === libav.AVMEDIA_TYPE_AUDIO && s.index === trackId,\n );\n if (!newStream) {\n console.warn(\"[avbridge] fallback: setAudioTrack — no stream with id\", trackId);\n return;\n }\n\n // Stop the pump before touching libav state. Same discipline as seek().\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n // Tear down the old audio decoder and init a fresh one for the new stream.\n if (audioDec) {\n try { await libav.ff_free_decoder?.(audioDec.c, audioDec.pkt, audioDec.frame); } catch { /* ignore */ }\n audioDec = null;\n }\n try {\n const [, c, pkt, frame] = await libav.ff_init_decoder(newStream.codec_id, {\n codecpar: newStream.codecpar,\n });\n audioDec = { c, pkt, frame };\n audioTimeBase = newStream.time_base_num && newStream.time_base_den\n ? [newStream.time_base_num, newStream.time_base_den]\n : undefined;\n } catch (err) {\n console.warn(\n \"[avbridge] fallback: setAudioTrack init failed — falling back to no-audio mode:\",\n (err as Error).message,\n );\n audioDec = null;\n opts.audio.setNoAudio();\n }\n\n audioStream = newStream;\n\n // Re-seek so packets resume from the user's current position for the\n // new track (and the same video position).\n try {\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] fallback: setAudioTrack seek failed:\", err);\n }\n\n // Flush the video decoder too — we just moved the demuxer back to a\n // keyframe boundary.\n try { if (videoDec) await libav.avcodec_flush_buffers?.(videoDec.c); } catch { /* ignore */ }\n await flushBSF();\n\n lastContentUs = -1;\n lastEmittedPtsUs = -1;\n firstValidPtsLoggedSinceSeek = false;\n\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] fallback pump failed (post-setAudioTrack):\", err),\n );\n },\n\n async seek(timeSec) {\n if (isDebug()) {\n // eslint-disable-next-line no-console\n console.log(`[SEEK] target=${timeSec.toFixed(3)}s (${(timeSec * 1000).toFixed(0)}ms) wall=${performance.now().toFixed(0)}`);\n }\n // Cancel the current pump and wait for it to actually exit before\n // we start moving file pointers around — concurrent ff_decode_multi\n // and av_seek_frame on the same context would be a recipe for memory\n // corruption inside libav.\n const newToken = ++pumpToken;\n if (pumpRunning) {\n try { await pumpRunning; } catch { /* ignore */ }\n }\n if (destroyed) return;\n\n try {\n // libav.js's `av_seek_frame` takes the timestamp as a *split*\n // (lo, hi) int64 pair, NOT a single number. The function signature\n // is: av_seek_frame(s, stream_index, tsLo, tsHi, flags). Passing a\n // single number put AVSEEK_FLAG_BACKWARD (1) into tsHi, which\n // produced a bogus int64 = 4.29e9 + tsLo ≈ 73 min for any small\n // seek target — seeking past EOF and stalling the pump.\n const tsUs = Math.floor(timeSec * 1_000_000);\n const [tsLo, tsHi] = libav.f64toi64\n ? libav.f64toi64(tsUs)\n : [tsUs | 0, Math.floor(tsUs / 0x100000000)];\n await libav.av_seek_frame(\n fmt_ctx,\n -1,\n tsLo,\n tsHi,\n libav.AVSEEK_FLAG_BACKWARD ?? 0,\n );\n } catch (err) {\n console.warn(\"[avbridge] av_seek_frame failed:\", err);\n }\n\n // Reset the decoder state. After the previous pump exited via the\n // EOF path it called ff_decode_multi with `fin: true`, which sends a\n // NULL packet to the decoder and puts it in drain mode — meaning all\n // subsequent decode calls return EOF. `avcodec_flush_buffers` clears\n // that state so a fresh stream of post-seek packets is accepted.\n // Also clears any internal frame reordering buffer, which is what we\n // want anyway since we just changed positions.\n try {\n if (videoDec) await libav.avcodec_flush_buffers?.(videoDec.c);\n } catch { /* ignore */ }\n try {\n if (audioDec) await libav.avcodec_flush_buffers?.(audioDec.c);\n } catch { /* ignore */ }\n await flushBSF();\n\n // Reset the content clock to \"unanchored\". The next decode loop\n // will discard NOPTS frames until the first valid libav pts\n // establishes a real anchor, then label every frame relative to\n // truth. Do NOT set anything to seekTarget here — that lie was\n // the post-seek fast-forward bug.\n lastContentUs = -1;\n lastEmittedPtsUs = -1;\n firstValidPtsLoggedSinceSeek = false;\n seenFirstAudioPacketSinceSeek = false;\n seekTargetSec = timeSec;\n diagPktsLoggedSinceSeek = 0;\n diagFramesLoggedSinceSeek = 0;\n diagFrameKeysDumped = false;\n\n // The renderer & audio output are reset by the fallback session\n // wrapper that called us — see strategies/fallback/index.ts.\n\n // Start a fresh pump for the new token.\n pumpRunning = pumpLoop(newToken).catch((err) =>\n console.error(\"[avbridge] decoder pump failed (post-seek):\", err),\n );\n },\n\n bufferedUntilSec() {\n return bufferedUntilSec;\n },\n\n stats() {\n return {\n decoderType: \"libav-wasm\",\n packetsRead,\n videoFramesDecoded,\n audioFramesDecoded,\n // Throughput instrumentation — the stats panel turns these into\n // \"decode fps actual / realtime target\" and shows slowest batch\n // + producer throttle share.\n videoDecodeMsTotal,\n videoDecodeBatches,\n audioDecodeMsTotal,\n audioDecodeBatches,\n readMsTotal,\n readBatches,\n pumpThrottleMsTotal,\n pumpThrottleEntries,\n slowestVideoBatchMs,\n newestVideoPtsMs: Math.round(newestVideoPtsUs / 1000),\n ptsRegressions,\n worstPtsRegressionMs,\n sourceFps: videoFps,\n bsfApplied: bsfCtx ? [\"mpeg4_unpack_bframes\"] : [],\n bsfMissing: bsfRequiredButMissing ? [\"mpeg4_unpack_bframes\"] : [],\n // Confirmed transport info: once prepareLibavInput returns\n // successfully, we *know* whether the source is http-range (probe\n // succeeded and returned 206) or in-memory blob. Diagnostics hoists\n // these `_`-prefixed keys to the typed fields.\n _transport: inputHandle.transport === \"http-range\" ? \"http-range\" : \"memory\",\n _rangeSupported: inputHandle.transport === \"http-range\",\n ...opts.renderer.stats(),\n ...opts.audio.stats(),\n };\n },\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Bridge loader (lazy via the static-import wrapper).\n// ─────────────────────────────────────────────────────────────────────────────\n\nasync function loadBridge(): Promise<BridgeModule> {\n try {\n const wrapper = await import(\"./libav-import.js\");\n return wrapper.libavBridge as unknown as BridgeModule;\n } catch (err) {\n throw new Error(\n `failed to load libavjs-webcodecs-bridge — install the optional peer deps with: ` +\n `npm i libavjs-webcodecs-bridge @libav.js/variant-webcodecs. ` +\n `(${(err as Error).message})`,\n );\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Structural types.\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface SoftDecoder {\n c: number;\n pkt: number;\n frame: number;\n}\n\ninterface LibavStream {\n index: number;\n codec_type: number;\n codec_id: number;\n codecpar: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavPacket {\n data: Uint8Array;\n pts: number;\n ptshi?: number;\n duration?: number;\n durationhi?: number;\n flags: number;\n stream_index: number;\n time_base_num?: number;\n time_base_den?: number;\n}\n\ninterface LibavFrame {\n data: unknown;\n format: number;\n channels?: number;\n ch_layout_nb_channels?: number;\n sample_rate?: number;\n nb_samples?: number;\n pts?: number;\n ptshi?: number;\n width?: number;\n height?: number;\n}\n\ninterface LibavRuntime {\n AVMEDIA_TYPE_VIDEO: number;\n AVMEDIA_TYPE_AUDIO: number;\n AVERROR_EOF: number;\n EAGAIN: number;\n AVSEEK_FLAG_BACKWARD?: number;\n\n mkreadaheadfile(name: string, blob: Blob): Promise<void>;\n unlinkreadaheadfile(name: string): Promise<void>;\n ff_init_demuxer_file(name: string): Promise<[number, LibavStream[]]>;\n ff_read_frame_multi(\n fmt_ctx: number,\n pkt: number,\n opts?: { limit?: number },\n ): Promise<[number, Record<number, LibavPacket[]>]>;\n ff_init_decoder(\n codec: number | string,\n config?: { codecpar?: number; time_base?: [number, number] },\n ): Promise<[number, number, number, number]>;\n ff_decode_multi(\n c: number,\n pkt: number,\n frame: number,\n packets: LibavPacket[],\n opts?: { fin?: boolean; ignoreErrors?: boolean },\n ): Promise<LibavFrame[]>;\n ff_free_decoder?(c: number, pkt: number, frame: number): Promise<void>;\n av_packet_alloc(): Promise<number>;\n av_packet_free?(pkt: number): Promise<void>;\n av_seek_frame(\n fmt_ctx: number,\n stream: number,\n tsLo: number,\n tsHi: number,\n flags: number,\n ): Promise<number>;\n avcodec_flush_buffers?(c: number): Promise<void>;\n avformat_close_input_js(ctx: number): Promise<void>;\n /** Sync helper exposed by libav.js: split a JS number into (lo, hi) int64. */\n f64toi64?(val: number): [number, number];\n\n // BSF (bitstream filter) methods — used for mpeg4_unpack_bframes\n av_bsf_list_parse_str_js(str: string): Promise<number>;\n AVBSFContext_par_in(ctx: number): Promise<number>;\n avcodec_parameters_copy(dst: number, src: number): Promise<number>;\n av_bsf_init(ctx: number): Promise<number>;\n av_bsf_send_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_receive_packet(ctx: number, pkt: number): Promise<number>;\n av_bsf_flush?(ctx: number): Promise<void>;\n av_bsf_free(ctx: number): Promise<void>;\n\n // Packet copy helpers — bridge JS packet objects to/from C-level pointers\n ff_copyin_packet(pktPtr: number, packet: LibavPacket): Promise<void>;\n ff_copyout_packet(pkt: number): Promise<LibavPacket>;\n}\n\ninterface BridgeModule {\n laFrameToVideoFrame(\n frame: LibavFrame,\n opts?: { VideoFrame?: unknown; timeBase?: [number, number]; transfer?: boolean },\n ): VideoFrame;\n laFrameToAudioData(\n frame: LibavFrame,\n opts?: { AudioData?: unknown; timeBase?: [number, number] },\n ): AudioData;\n}\n","import type { MediaContext, PlaybackSession, TransportConfig } from \"../../types.js\";\nimport { VideoRenderer } from \"./video-renderer.js\";\nimport { AudioOutput } from \"./audio-output.js\";\nimport { startDecoder, type DecoderHandles } from \"./decoder.js\";\nimport { dbg } from \"../../util/debug.js\";\nimport { makeTimeRanges } from \"../../util/time-ranges.js\";\n\n/**\n * Fallback strategy session.\n *\n * Owns the orchestration between the libav decoder, the audio scheduler,\n * and the canvas renderer. Three things make this non-trivial:\n *\n * 1. **Cold-start ready gate.** When `play()` is called, we wait until the\n * audio scheduler has buffered enough audio (≥ 300 ms) AND the renderer\n * has at least one decoded video frame, before actually telling the\n * audio context to start. Without this gate, audio and the wall clock\n * race ahead of the still-warming-up software decoder, and every video\n * frame lands \"in the past\" and gets dropped.\n *\n * 2. **Pause / resume.** The audio context is suspended on pause and\n * resumed on play. The media-time anchor is preserved across the\n * suspend so the clock is continuous.\n *\n * 3. **Seek.** Pauses the audio scheduler, asks the decoder to cancel its\n * current pump and `av_seek_frame` to the target, resets the audio\n * output's media-time anchor to the seek target, flushes the renderer\n * queue, then re-enters the ready gate. If we were playing before the\n * seek, we automatically resume once the buffer fills.\n *\n * The unified player API on top of this just sees `play() / pause() /\n * seek(t)` — none of the buffering choreography leaks out.\n */\n\n// Gate for cold-start playback. We want to start playing as soon as\n// there's any decoded output — the decoder will keep pumping during\n// playback, so more-is-better buffering only helps for fast decoders.\n//\n// For software-decode-bound content (rv40 / wmv3 / mpeg4 @ 720p+ on\n// single-threaded WASM), the decoder may run *slower* than realtime.\n// Waiting for a large audio-buffer threshold is actively wrong in that\n// case: it will never be reached, so the old gate would sit out its\n// full 10-second timeout before playing anything. An aggressive gate\n// ships the first frame to the screen fast, at the cost of the audio\n// clock racing a little ahead of video in the first few seconds —\n// which is the same situation we'd have been in after the timeout\n// anyway.\n//\n// READY_AUDIO_BUFFER_SECONDS: minimum audio queued before start. Set\n// low enough that a slow decoder still reaches it before the user\n// loses patience; 40 ms ≈ 2 cook packets or ~2 AAC packets.\n// READY_TIMEOUT_SECONDS: hard safety. If even 40 ms of audio can't be\n// produced in 3 s, give up and play whatever we have.\nconst READY_AUDIO_BUFFER_SECONDS = 0.04;\nconst READY_TIMEOUT_SECONDS = 3;\n\nexport async function createFallbackSession(\n ctx: MediaContext,\n target: HTMLVideoElement,\n transport?: TransportConfig,\n): Promise<PlaybackSession> {\n // Normalize the source so URL inputs go through the libav HTTP block\n // reader instead of being buffered into memory.\n const { normalizeSource } = await import(\"../../util/source.js\");\n const source = await normalizeSource(ctx.source);\n\n const fps = ctx.videoTracks[0]?.fps ?? 30;\n const audio = new AudioOutput();\n const renderer = new VideoRenderer(target, audio, fps);\n\n let handles: DecoderHandles;\n try {\n handles = await startDecoder({\n source,\n filename: ctx.name ?? \"input.bin\",\n context: ctx,\n renderer,\n audio,\n transport,\n });\n } catch (err) {\n audio.destroy();\n renderer.destroy();\n throw err;\n }\n\n // Patch the <video> element so the unified player layer (which polls\n // `target.currentTime` for `timeupdate` events and lets users assign to\n // it for seeks) gets the right values from the fallback strategy.\n Object.defineProperty(target, \"currentTime\", {\n configurable: true,\n get: () => audio.now(),\n set: (v: number) => {\n // Fire-and-forget — the user is expected to await player.seek() if\n // they want to know when the seek completes.\n void doSeek(v);\n },\n });\n // Mirror `paused` / `volume` / `muted` from the audio output — the\n // underlying <video> never has its own src, so its native state is\n // meaningless. This lets HTMLMediaElement consumers (<avbridge-player>\n // controls) see the real values and control volume through the audio\n // output's GainNode.\n Object.defineProperty(target, \"paused\", {\n configurable: true,\n get: () => !audio.isPlaying(),\n });\n Object.defineProperty(target, \"volume\", {\n configurable: true,\n get: () => audio.getVolume(),\n set: (v: number) => {\n audio.setVolume(v);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n Object.defineProperty(target, \"muted\", {\n configurable: true,\n get: () => audio.getMuted(),\n set: (m: boolean) => {\n audio.setMuted(m);\n target.dispatchEvent(new Event(\"volumechange\"));\n },\n });\n // Mirror duration so the demo's controls can use target.duration too.\n if (ctx.duration && Number.isFinite(ctx.duration)) {\n Object.defineProperty(target, \"duration\", {\n configurable: true,\n get: () => ctx.duration ?? NaN,\n });\n }\n // Playback rate — canvas strategies don't use the real <video>, so the\n // native playbackRate property does nothing. Patch it to drive the\n // AudioOutput clock speed + pitch.\n Object.defineProperty(target, \"playbackRate\", {\n configurable: true,\n get: () => audio.getPlaybackRate(),\n set: (v: number) => {\n audio.setPlaybackRate(v);\n target.dispatchEvent(new Event(\"ratechange\"));\n },\n });\n // Synthesize HTMLMediaElement parity surfaces that the canvas strategies\n // can't otherwise answer truthfully (the inner <video> has no src, so\n // its own readyState/seekable are zero/empty).\n //\n // readyState: HAVE_NOTHING (0) until the first frame lands; then\n // HAVE_CURRENT_DATA (2) once the cold-start gate is released (both\n // audio+video ready). Simplified from the full five-level spec — we\n // don't distinguish HAVE_FUTURE_DATA vs HAVE_ENOUGH_DATA since our\n // pump semantics make those essentially the same state.\n Object.defineProperty(target, \"readyState\", {\n configurable: true,\n get: (): number => {\n if (!renderer.hasFrames()) return 0; // HAVE_NOTHING\n if (!audio.isPlaying() && audio.bufferAhead() <= 0 && !audio.isNoAudio()) return 1; // HAVE_METADATA\n return 2; // HAVE_CURRENT_DATA (or better — but 2 is the honest lower bound)\n },\n });\n // seekable: a progressive source is fully seekable once we have duration.\n Object.defineProperty(target, \"seekable\", {\n configurable: true,\n get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0\n ? [[0, ctx.duration]]\n : []),\n });\n // buffered: demuxer's read-ahead frontier (highest pts pumped from\n // libav). Single [0, end] range — approximation of \"how far we've\n // read through the source,\" the signal the seek-bar buffered\n // indicator wants. Real MSE-style per-range tracking isn't\n // meaningful here since decoded frames are consumed in flight.\n Object.defineProperty(target, \"buffered\", {\n configurable: true,\n get: () => {\n const end = handles.bufferedUntilSec();\n return makeTimeRanges(end > 0 ? [[0, end]] : []);\n },\n });\n\n /**\n * Wait until the decoder has produced enough buffered output to start\n * playback smoothly. Returns early on timeout so we don't hang forever\n * if the decoder is producing nothing (e.g. immediately past EOF after\n * a seek to the end).\n *\n * The gate has three exit paths in order of preference:\n *\n * 1. **Fully ready** — audio buffer ≥ target AND ≥1 video frame.\n * The happy path for fast decoders (native + remux never reach\n * this function; this is fallback only).\n *\n * 2. **Video-ready, audio grace period elapsed** — we have video\n * frames but the audio scheduler is still empty. RM/AVI\n * containers commonly deliver a video GOP before their first\n * audio packet, so \"no audio yet\" ≠ \"no audio coming\". We give\n * the demuxer a 500 ms grace window from first-frame, then\n * start regardless. Audio will be scheduled at its correct\n * media time once its packets arrive.\n *\n * 3. **Hard timeout** — after {@link READY_TIMEOUT_SECONDS} seconds\n * with neither condition met, start anyway and emit an\n * unconditional diagnostic so the specific underflow is visible.\n *\n * Path #2 is what fixed the \"RMVB sits on the play button for 10 s\n * with audio=0ms, frames=N\" case — the gate was waiting on audio\n * packets that were several seconds behind in the file stream, and\n * the timeout was the only way out.\n */\n async function waitForBuffer(): Promise<void> {\n const start = performance.now();\n let firstFrameAtMs = 0;\n dbg.info(\"cold-start\",\n `gate entry: want audio ≥ ${READY_AUDIO_BUFFER_SECONDS * 1000}ms + 1 frame`,\n );\n while (true) {\n const audioAhead = audio.isNoAudio() ? Infinity : audio.bufferAhead();\n const audioReady = audio.isNoAudio() || audioAhead >= READY_AUDIO_BUFFER_SECONDS;\n const hasFrames = renderer.hasFrames();\n const nowMs = performance.now();\n\n if (hasFrames && firstFrameAtMs === 0) firstFrameAtMs = nowMs;\n\n // Happy path: both ready.\n if (audioReady && hasFrames) {\n dbg.info(\"cold-start\",\n `gate satisfied in ${(nowMs - start).toFixed(0)}ms ` +\n `(audio=${(audioAhead * 1000).toFixed(0)}ms, frames=${renderer.queueDepth()})`,\n );\n return;\n }\n\n // Grace path: have video, still waiting for audio that's\n // on its way (first 500 ms after first-frame).\n if (\n hasFrames &&\n firstFrameAtMs > 0 &&\n nowMs - firstFrameAtMs >= 500\n ) {\n dbg.info(\"cold-start\",\n `gate released on video-only grace at ${(nowMs - start).toFixed(0)}ms ` +\n `(frames=${renderer.queueDepth()}, audio=${(audioAhead * 1000).toFixed(0)}ms — ` +\n `demuxer hasn't delivered audio packets yet, starting anyway and letting ` +\n `the audio scheduler catch up at its media-time anchor)`,\n );\n return;\n }\n\n // Hard timeout.\n if ((nowMs - start) / 1000 > READY_TIMEOUT_SECONDS) {\n dbg.diag(\"cold-start\",\n `gate TIMEOUT after ${READY_TIMEOUT_SECONDS}s — ` +\n `audio=${(audioAhead * 1000).toFixed(0)}ms ` +\n `(needed ${READY_AUDIO_BUFFER_SECONDS * 1000}ms), ` +\n `frames=${renderer.queueDepth()} (needed ≥1). ` +\n `Decoder produced nothing in ${READY_TIMEOUT_SECONDS}s — either a corrupt source, ` +\n `a missing codec, or WASM is catastrophically slow on this file. ` +\n `Check getDiagnostics().runtime for decode counters.`,\n );\n return;\n }\n await new Promise((r) => setTimeout(r, 50));\n }\n }\n\n async function doSeek(timeSec: number): Promise<void> {\n const wasPlaying = audio.isPlaying();\n // HTMLMediaElement contract: dispatch `seeking` once the seek\n // operation begins. The inner <video> never fires this itself on\n // canvas strategies (no src), so we dispatch manually to preserve\n // the contract for consumers listening via `<avbridge-video>`.\n target.dispatchEvent(new Event(\"seeking\"));\n // 1. Stop audio (suspend ctx + capture media time).\n await audio.pause().catch(() => {});\n // 2. Tell the decoder to cancel its pump and seek the demuxer.\n await handles.seek(timeSec).catch((err) =>\n console.warn(\"[avbridge] decoder seek failed:\", err),\n );\n // 3. Reset audio + renderer to the new media time. New samples from\n // the decoder will queue against this anchor.\n await audio.reset(timeSec);\n renderer.flush();\n // 4. If we were playing, wait for the buffer to fill again and then\n // resume. If we were paused, leave it paused at the new position.\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n // HTMLMediaElement contract: dispatch `seeked` after the seek has\n // completed (demuxer + renderer reset + optional buffer refill).\n target.dispatchEvent(new Event(\"seeked\"));\n }\n\n // HTMLMediaElement contract: dispatch `loadedmetadata` once the\n // session is ready (duration, dimensions, tracks known via the\n // MediaContext). Dispatched on a microtask so it lands after the\n // session promise resolves and consumers have a chance to attach\n // listeners. The inner <video> never fires this itself here — it\n // has no src.\n queueMicrotask(() => {\n try { target.dispatchEvent(new Event(\"loadedmetadata\")); } catch { /* element torn down */ }\n });\n\n return {\n strategy: \"fallback\",\n\n async play() {\n // Either a cold start (very first play() call) or a resume from\n // pause. AudioOutput.start() handles both.\n if (!audio.isPlaying()) {\n await waitForBuffer();\n await audio.start();\n target.dispatchEvent(new Event(\"play\"));\n target.dispatchEvent(new Event(\"playing\"));\n }\n },\n\n pause() {\n void audio.pause();\n target.dispatchEvent(new Event(\"pause\"));\n },\n\n async seek(time) {\n await doSeek(time);\n },\n\n async setAudioTrack(id) {\n // Verify the id refers to a real track.\n if (!ctx.audioTracks.some((t) => t.id === id)) {\n console.warn(\"[avbridge] fallback: setAudioTrack — unknown track id\", id);\n return;\n }\n const wasPlaying = audio.isPlaying();\n const currentTime = audio.now();\n // Suspend audio, rebuild the decoder + seek, reset audio output, re-gate.\n await audio.pause().catch(() => {});\n await handles.setAudioTrack(id, currentTime).catch((err) =>\n console.warn(\"[avbridge] fallback: handles.setAudioTrack failed:\", err),\n );\n await audio.reset(currentTime);\n renderer.flush();\n if (wasPlaying) {\n await waitForBuffer();\n await audio.start();\n }\n },\n\n async setSubtitleTrack(_id) {\n // Subtitle overlay support is post-MVP for the fallback strategy.\n },\n\n getCurrentTime() {\n return audio.now();\n },\n async destroy() {\n await handles.destroy();\n renderer.destroy();\n audio.destroy();\n try {\n delete (target as unknown as Record<string, unknown>).currentTime;\n delete (target as unknown as Record<string, unknown>).duration;\n delete (target as unknown as Record<string, unknown>).paused;\n delete (target as unknown as Record<string, unknown>).volume;\n delete (target as unknown as Record<string, unknown>).muted;\n delete (target as unknown as Record<string, unknown>).readyState;\n delete (target as unknown as Record<string, unknown>).seekable;\n delete (target as unknown as Record<string, unknown>).playbackRate;\n } catch { /* ignore */ }\n },\n\n getRuntimeStats() {\n return handles.stats();\n },\n };\n}\n","import type { Plugin } from \"../types.js\";\nimport { createNativeSession } from \"../strategies/native.js\";\nimport { createRemuxSession } from \"../strategies/remux/index.js\";\nimport { createHybridSession } from \"../strategies/hybrid/index.js\";\nimport { createFallbackSession } from \"../strategies/fallback/index.js\";\nimport type { PluginRegistry } from \"./registry.js\";\n\nconst nativePlugin: Plugin = {\n name: \"native\",\n canHandle: () => true,\n execute: (ctx, video) => createNativeSession(ctx, video),\n};\n\nconst remuxPlugin: Plugin = {\n name: \"remux\",\n canHandle: () => true,\n execute: (ctx, video) => createRemuxSession(ctx, video),\n};\n\nconst hybridPlugin: Plugin = {\n name: \"hybrid\",\n canHandle: () => typeof VideoDecoder !== \"undefined\",\n execute: (ctx, video, transport) => createHybridSession(ctx, video, transport),\n};\n\nconst fallbackPlugin: Plugin = {\n name: \"fallback\",\n canHandle: () => true,\n execute: (ctx, video, transport) => createFallbackSession(ctx, video, transport),\n};\n\nexport function registerBuiltins(registry: PluginRegistry): void {\n registry.register(nativePlugin);\n registry.register(remuxPlugin);\n registry.register(hybridPlugin);\n registry.register(fallbackPlugin);\n}\n","import { TypedEmitter } from \"./events.js\";\nimport { probe } from \"./probe/index.js\";\nimport { classify } from \"./classify/index.js\";\nimport { Diagnostics } from \"./diagnostics.js\";\nimport { PluginRegistry } from \"./plugins/registry.js\";\nimport { registerBuiltins } from \"./plugins/builtin.js\";\nimport { discoverSidecars, attachSubtitleTracks, SubtitleResourceBag } from \"./subtitles/index.js\";\nimport { dbg } from \"./util/debug.js\";\nimport type {\n Classification,\n CreatePlayerOptions,\n DiagnosticsSnapshot,\n MediaContext,\n PlaybackSession,\n PlayerEventMap,\n PlayerEventName,\n StrategyName,\n TransportConfig,\n Listener,\n} from \"./types.js\";\nimport { AvbridgeError, ERR_PLAYER_NOT_READY, ERR_ALL_STRATEGIES_EXHAUSTED } from \"./errors.js\";\n\n/**\n * Decoded-video-frame counter reader. Prefers the standard\n * `getVideoPlaybackQuality().totalVideoFrames` (all evergreen browsers);\n * falls back to the WebKit-prefixed `webkitDecodedFrameCount` for older\n * Safari. Returns 0 for non-video elements or when nothing exposes the\n * count — the caller treats 0 as \"no signal\" (constant across samples,\n * which is fine).\n */\nexport function readDecodedFrameCount(target: HTMLMediaElement): number {\n if (typeof HTMLVideoElement === \"undefined\" || !(target instanceof HTMLVideoElement)) return 0;\n const vq = (target as HTMLVideoElement & { getVideoPlaybackQuality?: () => { totalVideoFrames: number } }).getVideoPlaybackQuality;\n if (typeof vq === \"function\") {\n try { return vq.call(target).totalVideoFrames; } catch { /* fall through */ }\n }\n const legacy = (target as HTMLVideoElement & { webkitDecodedFrameCount?: number }).webkitDecodedFrameCount;\n return typeof legacy === \"number\" ? legacy : 0;\n}\n\n/**\n * Pure decision function for the stall supervisor. Takes a snapshot of\n * the observable state and returns whether to escalate. Extracted so it\n * can be unit-tested without spinning up a real player / media element.\n *\n * - `time-stall`: `currentTime` hasn't moved for `timeStallThresholdMs`\n * despite the element being in a state where it should be playing.\n * - `silent-video`: the media has a video track, `currentTime` is\n * advancing (audio is playing), but the decoder has produced no new\n * frames for `frameStallThresholdMs`. Catches Firefox-style \"MSE\n * reports codec supported but the decoder can't actually decode it\".\n */\nexport function evaluateDecodeHealth(input: {\n hasVideoTrack: boolean;\n timeAdvanced: boolean;\n framesAdvanced: boolean;\n now: number;\n lastProgressTime: number;\n lastFrameProgressTime: number;\n timeStallThresholdMs?: number;\n frameStallThresholdMs?: number;\n}): { escalate: false } | { escalate: true; kind: \"time-stall\" | \"silent-video\" } {\n const timeThreshold = input.timeStallThresholdMs ?? 5000;\n const frameThreshold = input.frameStallThresholdMs ?? 3000;\n if (!input.timeAdvanced && input.now - input.lastProgressTime > timeThreshold) {\n return { escalate: true, kind: \"time-stall\" };\n }\n if (\n input.hasVideoTrack &&\n input.timeAdvanced &&\n !input.framesAdvanced &&\n input.now - input.lastFrameProgressTime > frameThreshold\n ) {\n return { escalate: true, kind: \"silent-video\" };\n }\n return { escalate: false };\n}\n\nexport class UnifiedPlayer {\n private emitter = new TypedEmitter<PlayerEventMap>();\n private session: PlaybackSession | null = null;\n private diag = new Diagnostics();\n private timeupdateInterval: ReturnType<typeof setInterval> | null = null;\n\n // Saved from bootstrap for strategy switching\n private mediaContext: MediaContext | null = null;\n private classification: Classification | null = null;\n\n // Stall detection\n private stallTimer: ReturnType<typeof setInterval> | null = null;\n private lastProgressTime = 0;\n private lastProgressPosition = -1;\n /** Last observed `HTMLVideoElement.getVideoPlaybackQuality().totalVideoFrames`\n * (or `webkitDecodedFrameCount` fallback). Used by the silent-video\n * watchdog — catches cases where `currentTime` advances (audio plays)\n * but the decoder produces no frames, e.g. Firefox claiming `hev1.*`\n * via MSE when the decoder actually can't decode HEVC. */\n private lastVideoFrameCount = 0;\n private lastVideoFrameProgressTime = 0;\n private errorListener: (() => void) | null = null;\n\n // Bound so we can removeEventListener in destroy(); without this the\n // listener outlives the player and accumulates on elements that swap\n // source (e.g. <avbridge-video>).\n private endedListener: (() => void) | null = null;\n\n // Background tab handling. userIntent is what the user last asked for\n // (play vs pause) — used to decide whether to auto-resume on visibility\n // return. autoPausedForVisibility tracks whether we paused because the\n // tab was hidden, so we don't resume playback the user deliberately\n // paused (e.g. via media keys while hidden).\n private userIntent: \"play\" | \"pause\" = \"pause\";\n private autoPausedForVisibility = false;\n private visibilityListener: (() => void) | null = null;\n\n // Serializes escalation / setStrategy calls\n private switchingPromise: Promise<void> = Promise.resolve();\n\n // Owns blob URLs created during sidecar discovery + SRT->VTT conversion.\n // Revoked at destroy() so repeated source swaps don't leak.\n private subtitleResources = new SubtitleResourceBag();\n\n // Transport config extracted from CreatePlayerOptions. Threaded to probe,\n // subtitle fetches, and strategy session creators. Not stored on MediaContext\n // because it's runtime config, not media analysis.\n private readonly transport: TransportConfig | undefined;\n\n /**\n * @internal Use {@link createPlayer} or {@link UnifiedPlayer.create} instead.\n */\n private constructor(\n private readonly options: CreatePlayerOptions,\n private readonly registry: PluginRegistry,\n ) {\n const { requestInit, fetchFn, cacheBytes } = options;\n if (requestInit || fetchFn || cacheBytes !== undefined) {\n this.transport = { requestInit, fetchFn, cacheBytes };\n }\n }\n\n static async create(options: CreatePlayerOptions): Promise<UnifiedPlayer> {\n const registry = new PluginRegistry();\n registerBuiltins(registry);\n if (options.plugins) {\n for (const p of options.plugins) registry.register(p, /* prepend */ true);\n }\n const player = new UnifiedPlayer(options, registry);\n try {\n await player.bootstrap();\n } catch (err) {\n (err as Error & { player?: UnifiedPlayer }).player = player;\n throw err;\n }\n return player;\n }\n\n private async bootstrap(): Promise<void> {\n const bootstrapStart = performance.now();\n try {\n dbg.info(\"bootstrap\", \"start\");\n const ctx = await dbg.timed(\"probe\", \"probe\", 3000, () => probe(this.options.source, this.transport));\n dbg.info(\"probe\",\n `container=${ctx.container} video=${ctx.videoTracks[0]?.codec ?? \"-\"} ` +\n `audio=${ctx.audioTracks[0]?.codec ?? \"-\"} probedBy=${ctx.probedBy}`,\n );\n this.diag.recordProbe(ctx);\n this.mediaContext = ctx;\n\n // Merge sidecar / explicit subtitles\n if (this.options.subtitles) {\n for (const s of this.options.subtitles) {\n ctx.subtitleTracks.push({\n id: ctx.subtitleTracks.length,\n format: s.format ?? (s.url.endsWith(\".srt\") ? \"srt\" : \"vtt\"),\n language: s.language,\n sidecarUrl: s.url,\n });\n }\n }\n if (this.options.directory && this.options.source instanceof File) {\n const found = await discoverSidecars(this.options.source, this.options.directory);\n for (const s of found) {\n // Track every blob URL we adopted from discovery so it gets\n // revoked at destroy() — otherwise repeated source changes leak.\n this.subtitleResources.track(s.url);\n ctx.subtitleTracks.push({\n id: ctx.subtitleTracks.length,\n format: s.format,\n language: s.language,\n sidecarUrl: s.url,\n });\n }\n }\n\n const decision = this.options.initialStrategy\n ? buildInitialDecision(this.options.initialStrategy, ctx)\n : classify(ctx);\n dbg.info(\"classify\",\n `strategy=${decision.strategy} class=${decision.class} reason=\"${decision.reason}\"` +\n (decision.fallbackChain ? ` fallback=${decision.fallbackChain.join(\"→\")}` : \"\"),\n );\n this.classification = decision;\n this.diag.recordClassification(decision);\n\n this.emitter.emitSticky(\"strategy\", {\n strategy: decision.strategy,\n reason: decision.reason,\n });\n\n // Try the primary strategy, falling through the chain on failure\n await this.startSession(decision.strategy, decision.reason);\n\n // Apply subtitles for all strategies. Native/remux render them via\n // the inner <video>'s native text-track engine. Hybrid/fallback\n // hide the <video> and render cues into the canvas overlay — see\n // each session's SubtitleOverlay wiring. The <track> elements are\n // attached in both cases so cues are parsed by the browser.\n await attachSubtitleTracks(\n this.options.target,\n ctx.subtitleTracks,\n this.subtitleResources,\n (err, track) => {\n // eslint-disable-next-line no-console\n console.warn(`[avbridge] subtitle ${track.id} failed: ${err.message}`);\n },\n this.transport,\n );\n\n this.emitter.emitSticky(\"tracks\", {\n video: ctx.videoTracks,\n audio: ctx.audioTracks,\n subtitle: ctx.subtitleTracks,\n });\n\n this.startTimeupdateLoop();\n this.endedListener = () => this.emitter.emit(\"ended\", undefined);\n this.options.target.addEventListener(\"ended\", this.endedListener);\n\n // Auto-pause on background tab (unless explicitly opted out).\n // Chrome throttles rAF and setTimeout in hidden tabs, so playback\n // degrades anyway — better to pause cleanly and resume on return.\n if (this.options.backgroundBehavior !== \"continue\" && typeof document !== \"undefined\") {\n this.visibilityListener = () => this.onVisibilityChange();\n document.addEventListener(\"visibilitychange\", this.visibilityListener);\n }\n\n this.emitter.emitSticky(\"ready\", undefined);\n const bootstrapElapsed = performance.now() - bootstrapStart;\n dbg.info(\"bootstrap\", `ready in ${bootstrapElapsed.toFixed(0)}ms`);\n if (bootstrapElapsed > 5000) {\n // eslint-disable-next-line no-console\n console.warn(\n \"[avbridge:bootstrap]\",\n `total bootstrap time ${bootstrapElapsed.toFixed(0)}ms — unusually slow. ` +\n `Enable globalThis.AVBRIDGE_DEBUG for a per-phase breakdown.`,\n );\n }\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n this.diag.recordError(e);\n this.emitter.emit(\"error\", e);\n throw e;\n }\n }\n\n /**\n * Try to start a session with the given strategy. On failure, walk the\n * fallback chain. Throws only if all strategies are exhausted.\n */\n private async startSession(strategy: StrategyName, reason: string): Promise<void> {\n const plugin = this.registry.findFor(this.mediaContext!, strategy);\n if (!plugin) {\n throw new Error(`no plugin available for strategy \"${strategy}\"`);\n }\n\n try {\n this.session = await plugin.execute(this.mediaContext!, this.options.target, this.transport);\n } catch (err) {\n // Try the fallback chain\n const chain = this.classification?.fallbackChain;\n if (chain && chain.length > 0) {\n const next = chain.shift()!;\n console.warn(`[avbridge] ${strategy} failed (${(err as Error).message}), escalating to ${next}`);\n this.emitter.emit(\"strategychange\", {\n from: strategy,\n to: next,\n reason: `${strategy} failed: ${(err as Error).message}`,\n currentTime: 0,\n });\n this.diag.recordStrategySwitch(next, `${strategy} failed: ${(err as Error).message}`);\n return this.startSession(next, `escalated from ${strategy}`);\n }\n throw err;\n }\n\n // Wire up fatal error handler for hybrid/fallback escalation\n this.session.onFatalError?.((fatalReason) => {\n void this.escalate(fatalReason);\n });\n\n // Attach stall supervisor\n this.attachSupervisor();\n\n // Update sticky strategy event if we ended up on a different strategy\n if (this.session.strategy !== strategy) {\n this.emitter.emitSticky(\"strategy\", {\n strategy: this.session.strategy,\n reason,\n });\n }\n }\n\n // ── Escalation ──────────────────────────────────────────────────────────\n\n private async escalate(reason: string): Promise<void> {\n // Serialize with other switch operations\n this.switchingPromise = this.switchingPromise.then(() =>\n this.doEscalate(reason),\n ).catch((err) => {\n this.emitter.emit(\"error\", err instanceof Error ? err : new Error(String(err)));\n });\n await this.switchingPromise;\n }\n\n private async doEscalate(reason: string): Promise<void> {\n const chain = this.classification?.fallbackChain;\n if (!chain || chain.length === 0) {\n this.emitter.emit(\"error\", new Error(\n `strategy \"${this.session?.strategy}\" failed: ${reason} (no fallback available)`,\n ));\n return;\n }\n\n const currentTime = this.session?.getCurrentTime() ?? 0;\n const wasPlaying = this.session ? !this.options.target.paused : false;\n const fromStrategy = this.session?.strategy ?? \"native\";\n\n // Tear down the current session before walking the chain — once we\n // commit to escalating, the existing session is going away regardless\n // of which fallback step succeeds.\n this.clearSupervisor();\n if (this.session) {\n try { await this.session.destroy(); } catch { /* ignore */ }\n this.session = null;\n }\n\n // Walk every remaining entry in the chain. Previously this method\n // popped exactly one entry and gave up if its plugin failed to start —\n // a recoverable failure in one fallback step blocked later viable\n // strategies (inconsistent with startSession() which already loops).\n const errors: string[] = [];\n while (chain.length > 0) {\n const nextStrategy = chain.shift()!;\n console.warn(`[avbridge] escalating from ${fromStrategy} to ${nextStrategy}: ${reason}`);\n\n this.emitter.emit(\"strategychange\", {\n from: fromStrategy,\n to: nextStrategy,\n reason,\n currentTime,\n });\n this.diag.recordStrategySwitch(nextStrategy, reason);\n\n const plugin = this.registry.findFor(this.mediaContext!, nextStrategy);\n if (!plugin) {\n errors.push(`${nextStrategy}: no plugin available`);\n continue;\n }\n\n try {\n this.session = await plugin.execute(this.mediaContext!, this.options.target, this.transport);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n errors.push(`${nextStrategy}: ${msg}`);\n console.warn(`[avbridge] ${nextStrategy} failed during escalation, trying next: ${msg}`);\n continue;\n }\n\n // Success — finish wiring and restore playback.\n this.emitter.emitSticky(\"strategy\", {\n strategy: nextStrategy,\n reason: `escalated: ${reason}`,\n });\n this.session.onFatalError?.((fatalReason) => {\n void this.escalate(fatalReason);\n });\n this.attachSupervisor();\n try {\n await this.session.seek(currentTime);\n if (wasPlaying) await this.session.play();\n } catch (err) {\n console.warn(\"[avbridge] failed to restore position after escalation:\", err);\n }\n return;\n }\n\n // Chain exhausted with no working strategy.\n this.emitter.emit(\"error\", new AvbridgeError(\n ERR_ALL_STRATEGIES_EXHAUSTED,\n `All playback strategies failed: ${errors.join(\"; \")}`,\n \"This file may require a codec or container that isn't available in this browser. Try the fallback strategy or check browser codec support.\",\n ));\n }\n\n // ── Stall supervision ─────────────────────────────────────────────────\n\n private attachSupervisor(): void {\n this.clearSupervisor();\n if (this.options.autoEscalate === false) return;\n if (!this.classification?.fallbackChain?.length) return;\n\n const strategy = this.session?.strategy;\n if (strategy === \"native\" || strategy === \"remux\") {\n // Monitor currentTime progress\n this.lastProgressPosition = this.options.target.currentTime;\n this.lastProgressTime = performance.now();\n this.lastVideoFrameCount = readDecodedFrameCount(this.options.target);\n this.lastVideoFrameProgressTime = performance.now();\n\n const hasVideoTrack = (this.mediaContext?.videoTracks.length ?? 0) > 0;\n\n this.stallTimer = setInterval(() => {\n const t = this.options.target;\n const now = performance.now();\n if (t.paused || t.ended || t.readyState < 2) {\n this.lastProgressPosition = t.currentTime;\n this.lastProgressTime = now;\n this.lastVideoFrameCount = readDecodedFrameCount(t);\n this.lastVideoFrameProgressTime = now;\n return;\n }\n const timeAdvanced = t.currentTime !== this.lastProgressPosition;\n const frames = readDecodedFrameCount(t);\n const framesAdvanced = frames > this.lastVideoFrameCount;\n\n const health = evaluateDecodeHealth({\n hasVideoTrack,\n timeAdvanced,\n framesAdvanced,\n now,\n lastProgressTime: this.lastProgressTime,\n lastFrameProgressTime: this.lastVideoFrameProgressTime,\n });\n\n if (timeAdvanced) {\n this.lastProgressPosition = t.currentTime;\n this.lastProgressTime = now;\n }\n if (framesAdvanced) {\n this.lastVideoFrameCount = frames;\n this.lastVideoFrameProgressTime = now;\n }\n\n if (health.escalate) {\n const reason = health.kind === \"time-stall\"\n ? `${strategy} strategy stalled for 5s at ${t.currentTime.toFixed(1)}s`\n : `${strategy} strategy: audio is advancing but the video decoder has produced no new frames for 3s — likely a silent codec failure`;\n void this.escalate(reason);\n }\n }, 1000);\n\n // Listen for media element errors\n const onError = () => {\n void this.escalate(\n `${strategy} strategy error: ${this.options.target.error?.message ?? \"unknown\"}`,\n );\n };\n this.options.target.addEventListener(\"error\", onError, { once: true });\n this.errorListener = onError;\n }\n // Hybrid/fallback escalation is handled via onFatalError callback\n }\n\n private clearSupervisor(): void {\n if (this.stallTimer) {\n clearInterval(this.stallTimer);\n this.stallTimer = null;\n }\n if (this.errorListener) {\n this.options.target.removeEventListener(\"error\", this.errorListener);\n this.errorListener = null;\n }\n }\n\n // ── Public: manual strategy switch ────────────────────────────────────\n\n /** Manually switch to a different playback strategy. Preserves current position and play/pause state. Concurrent calls are serialized. */\n async setStrategy(strategy: StrategyName, reason?: string): Promise<void> {\n if (!this.mediaContext) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n if (this.session?.strategy === strategy) return;\n\n this.switchingPromise = this.switchingPromise.then(() =>\n this.doSetStrategy(strategy, reason),\n );\n await this.switchingPromise;\n }\n\n private async doSetStrategy(strategy: StrategyName, reason?: string): Promise<void> {\n const currentTime = this.session?.getCurrentTime() ?? 0;\n const wasPlaying = this.session ? !this.options.target.paused : false;\n const fromStrategy = this.session?.strategy ?? \"native\";\n const switchReason = reason ?? `manual switch to ${strategy}`;\n\n this.emitter.emit(\"strategychange\", {\n from: fromStrategy,\n to: strategy,\n reason: switchReason,\n currentTime,\n });\n this.diag.recordStrategySwitch(strategy, switchReason);\n\n this.clearSupervisor();\n if (this.session) {\n try { await this.session.destroy(); } catch { /* ignore */ }\n this.session = null;\n }\n\n const plugin = this.registry.findFor(this.mediaContext!, strategy);\n if (!plugin) throw new Error(`no plugin available for strategy \"${strategy}\"`);\n\n this.session = await plugin.execute(this.mediaContext!, this.options.target, this.transport);\n\n this.emitter.emitSticky(\"strategy\", {\n strategy,\n reason: switchReason,\n });\n\n this.session.onFatalError?.((fatalReason) => {\n void this.escalate(fatalReason);\n });\n this.attachSupervisor();\n\n try {\n await this.session.seek(currentTime);\n if (wasPlaying) await this.session.play();\n } catch (err) {\n console.warn(\"[avbridge] failed to restore position after strategy switch:\", err);\n }\n }\n\n // ── Timeupdate loop ───────────────────────────────────────────────────\n\n private startTimeupdateLoop(): void {\n this.timeupdateInterval = setInterval(() => {\n const t = this.session?.getCurrentTime() ?? this.options.target.currentTime;\n this.emitter.emit(\"timeupdate\", { currentTime: t });\n }, 250);\n }\n\n // ── Public API ────────────────────────────────────────────────────────\n\n /** Subscribe to a player event. Returns an unsubscribe function. Sticky events (strategy, ready, tracks) replay for late subscribers. */\n on<K extends PlayerEventName>(event: K, fn: Listener<PlayerEventMap[K]>): () => void {\n return this.emitter.on(event, fn);\n }\n\n /** Remove a previously registered event listener. */\n off<K extends PlayerEventName>(event: K, fn: Listener<PlayerEventMap[K]>): void {\n this.emitter.off(event, fn);\n }\n\n /** Begin or resume playback. Throws if the player is not ready. */\n async play(): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n this.userIntent = \"play\";\n this.autoPausedForVisibility = false;\n await this.session.play();\n }\n\n /** Pause playback. No-op if the player is not ready or already paused. */\n pause(): void {\n this.userIntent = \"pause\";\n this.autoPausedForVisibility = false;\n this.session?.pause();\n }\n\n /**\n * Handle browser tab visibility changes. On hide: pause if the user\n * had been playing. On show: resume if we were the one who paused.\n * Skips when `backgroundBehavior: \"continue\"` is set (listener isn't\n * installed in that case).\n */\n private onVisibilityChange(): void {\n if (!this.session) return;\n const action = decideVisibilityAction({\n hidden: document.hidden,\n userIntent: this.userIntent,\n sessionIsPlaying: !this.options.target.paused,\n autoPausedForVisibility: this.autoPausedForVisibility,\n });\n if (action === \"pause\") {\n this.autoPausedForVisibility = true;\n dbg.info(\"visibility\", \"tab hidden — auto-paused\");\n this.session.pause();\n } else if (action === \"resume\") {\n this.autoPausedForVisibility = false;\n dbg.info(\"visibility\", \"tab visible — auto-resuming\");\n void this.session.play().catch((err) => {\n // eslint-disable-next-line no-console\n console.warn(\"[avbridge] auto-resume after tab return failed:\", err);\n });\n }\n }\n\n /** Seek to the given time in seconds. Throws if the player is not ready. */\n async seek(time: number): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n await this.session.seek(time);\n }\n\n /** Switch the active audio track by track ID. Throws if the player is not ready. */\n async setAudioTrack(id: number): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n await this.session.setAudioTrack(id);\n }\n\n /** Switch the active subtitle track by track ID, or pass `null` to disable subtitles. */\n async setSubtitleTrack(id: number | null): Promise<void> {\n if (!this.session) throw new AvbridgeError(ERR_PLAYER_NOT_READY, \"Player not ready — wait for the 'ready' event before calling playback methods.\", \"Await the 'ready' event or check player.readyState before calling play/pause/seek.\");\n await this.session.setSubtitleTrack(id);\n }\n\n /** Return a snapshot of current diagnostics: container, codecs, strategy, runtime stats, and strategy history. */\n getDiagnostics(): DiagnosticsSnapshot {\n if (this.session) {\n this.diag.recordRuntime(this.session.getRuntimeStats());\n }\n return this.diag.snapshot();\n }\n\n /** Return the total duration in seconds, or `NaN` if unknown. */\n getDuration(): number {\n const fromDiag = this.diag.snapshot().duration;\n if (typeof fromDiag === \"number\" && Number.isFinite(fromDiag)) return fromDiag;\n const fromVideo = this.options.target.duration;\n return Number.isFinite(fromVideo) ? fromVideo : NaN;\n }\n\n /** Return the current playback position in seconds. */\n getCurrentTime(): number {\n return this.session?.getCurrentTime() ?? this.options.target.currentTime ?? 0;\n }\n\n /** Tear down the player: stop timers, destroy the active session, remove all event listeners. The player is unusable after this call. */\n async destroy(): Promise<void> {\n if (this.timeupdateInterval) {\n clearInterval(this.timeupdateInterval);\n this.timeupdateInterval = null;\n }\n this.clearSupervisor();\n if (this.endedListener) {\n this.options.target.removeEventListener(\"ended\", this.endedListener);\n this.endedListener = null;\n }\n if (this.visibilityListener) {\n document.removeEventListener(\"visibilitychange\", this.visibilityListener);\n this.visibilityListener = null;\n }\n if (this.session) {\n await this.session.destroy();\n this.session = null;\n }\n // Revoke every blob URL we created for sidecar discovery / SRT->VTT\n // conversion. This is the cleanup leg of the leak fix.\n this.subtitleResources.revokeAll();\n this.emitter.removeAll();\n }\n}\n\nexport async function createPlayer(options: CreatePlayerOptions): Promise<UnifiedPlayer> {\n return UnifiedPlayer.create(options);\n}\n\n/**\n * Pure decision function for visibility-change handling. Separated from\n * the class method so it can be unit-tested without a full player\n * instance.\n *\n * @internal — exported for unit tests; not part of the public API.\n */\nexport function decideVisibilityAction(state: {\n hidden: boolean;\n userIntent: \"play\" | \"pause\";\n sessionIsPlaying: boolean;\n autoPausedForVisibility: boolean;\n}): \"pause\" | \"resume\" | \"noop\" {\n if (state.hidden) {\n // Tab hidden: pause if user had been playing and session is active\n if (state.userIntent === \"play\" && state.sessionIsPlaying) return \"pause\";\n return \"noop\";\n }\n // Tab visible: resume only if we're the one who paused\n if (state.autoPausedForVisibility) return \"resume\";\n return \"noop\";\n}\n\n/**\n * Build a synthetic classification for an explicit `initialStrategy` override.\n * The `class` is derived from the chosen strategy so diagnostics and any\n * downstream consumer of `strategyClass` see the real strategy. The fallback\n * chain is inherited from the natural classification but must never contain\n * `initial` itself — otherwise `startSession` would retry the strategy that\n * just failed before escalating.\n *\n * @internal — exported for unit tests; not part of the public API.\n */\nexport function buildInitialDecision(\n initial: StrategyName,\n ctx: MediaContext,\n): Classification {\n const natural = classify(ctx);\n const cls = strategyToClass(initial, natural);\n const inherited = natural.fallbackChain ?? defaultFallbackChain(initial);\n const fallbackChain = inherited.filter((s) => s !== initial);\n return {\n class: cls,\n strategy: initial,\n reason: `initial strategy \"${initial}\" requested via options.initialStrategy`,\n fallbackChain,\n };\n}\n\nfunction strategyToClass(\n strategy: StrategyName,\n natural: Classification,\n): Classification[\"class\"] {\n // If the natural classification picked the same strategy, use its class.\n if (natural.strategy === strategy) return natural.class;\n switch (strategy) {\n case \"native\": return \"NATIVE\";\n case \"remux\": return \"REMUX_CANDIDATE\";\n case \"hybrid\": return \"HYBRID_CANDIDATE\";\n case \"fallback\": return \"FALLBACK_REQUIRED\";\n }\n}\n\nfunction defaultFallbackChain(strategy: StrategyName): StrategyName[] {\n switch (strategy) {\n case \"native\": return [\"remux\", \"hybrid\", \"fallback\"];\n case \"remux\": return [\"hybrid\", \"fallback\"];\n case \"hybrid\": return [\"fallback\"];\n case \"fallback\": return [];\n }\n}\n","/**\n * `<avbridge-video>` — `HTMLMediaElement`-compatible primitive backed by the\n * avbridge engine. Drop-in replacement for a `<video>` element with no\n * built-in UI.\n *\n * Purpose:\n *\n * 1. Validate the public API by being a real consumer of `createPlayer()`.\n * 2. Drive lifecycle correctness in the core via adversarial integration tests.\n * 3. Give consumers a `<video>`-compatible primitive they can wrap with\n * their own UI.\n *\n * **It is not a player UI framework.** For YouTube-style chrome (seek\n * bar, play/pause, settings menu, fullscreen, auto-hiding controls) use\n * `<avbridge-player>` — it wraps this element with a full UI. See\n * `docs/dev/WEB_COMPONENT_SPEC.md` for the full spec, lifecycle invariants,\n * and edge case list.\n */\n\nimport { createPlayer, type UnifiedPlayer } from \"../player.js\";\nimport type {\n MediaInput,\n StrategyName,\n StrategyClass,\n AudioTrackInfo,\n SubtitleTrackInfo,\n DiagnosticsSnapshot,\n AvbridgeVideoElementEventMap,\n} from \"../types.js\";\n\n/** Strategy preference passed via the `preferstrategy` attribute. */\ntype PreferredStrategy = \"auto\" | StrategyName;\n\nconst PREFERRED_STRATEGY_VALUES = new Set<PreferredStrategy>([\n \"auto\",\n \"native\",\n \"remux\",\n \"hybrid\",\n \"fallback\",\n]);\n\n/** Fit mode — how the video fills the element's box. Mirrors CSS object-fit. */\ntype FitMode = \"contain\" | \"cover\" | \"fill\";\nconst FIT_VALUES = new Set<FitMode>([\"contain\", \"cover\", \"fill\"]);\nconst DEFAULT_FIT: FitMode = \"contain\";\n\n/**\n * Standard `HTMLMediaElement` events we forward from the inner `<video>`\n * to the wrapper element so consumers can `el.addEventListener(\"loadedmetadata\", ...)`\n * exactly like they would with a real `<video>`. The element also dispatches\n * its own custom events (`strategychange`, `ready`, `error`, etc.) — those\n * are NOT in this list because they're avbridge-specific.\n *\n * Note: `progress` and `timeupdate` are deliberately NOT forwarded here.\n * `progress` is dispatched by the constructor with our own `{ buffered }`\n * detail. `timeupdate` is dispatched by the player layer (so it works for\n * canvas-rendered fallback playback too, where the inner <video> never\n * fires its own timeupdate).\n */\nconst FORWARDED_VIDEO_EVENTS = [\n \"loadstart\",\n \"loadedmetadata\",\n \"loadeddata\",\n \"canplay\",\n \"canplaythrough\",\n \"play\",\n \"playing\",\n \"pause\",\n \"seeking\",\n \"seeked\",\n \"volumechange\",\n \"ratechange\",\n \"durationchange\",\n \"waiting\",\n \"stalled\",\n \"emptied\",\n \"resize\",\n \"error\",\n] as const;\n\n/**\n * `HTMLElement` is a browser-only global. SSR frameworks (Next.js, Astro,\n * Remix, etc.) commonly import library modules on the server to extract\n * types or do tree-shaking, even if the user only ends up using them in\n * the browser. If we extended `HTMLElement` directly, the `class extends`\n * expression would be evaluated at module load time and crash in Node.\n *\n * The fix: in non-browser environments, fall back to an empty stub class.\n * The element is never *constructed* server-side (the registration in\n * `element.ts` is guarded by `typeof customElements !== \"undefined\"`), so\n * the stub is never instantiated — it just lets the class declaration\n * evaluate cleanly so the module can be imported anywhere.\n */\nconst HTMLElementCtor: typeof HTMLElement =\n typeof HTMLElement !== \"undefined\"\n ? HTMLElement\n : (class {} as unknown as typeof HTMLElement);\n\n/**\n * Custom element. Lifecycle correctness is enforced via a monotonically\n * increasing `_bootstrapId`: every async bootstrap captures the ID at start\n * and discards itself if the ID has changed by the time it resolves. This\n * single pattern handles disconnect-during-bootstrap, rapid src reassignment,\n * bootstrap races, and destroy-during-bootstrap.\n */\nexport class AvbridgeVideoElement extends HTMLElementCtor {\n static readonly observedAttributes = [\n \"src\",\n \"autoplay\",\n \"muted\",\n \"loop\",\n \"preload\",\n \"poster\",\n \"playsinline\",\n \"crossorigin\",\n \"disableremoteplayback\",\n \"diagnostics\",\n \"preferstrategy\",\n \"fit\",\n \"no-orientation-lock\",\n ];\n\n // ── Internal state ─────────────────────────────────────────────────────\n\n /** The shadow DOM `<video>` element that strategies render into. */\n private _videoEl!: HTMLVideoElement;\n\n /** Active player session, if any. Cleared on teardown. */\n private _player: UnifiedPlayer | null = null;\n\n /**\n * Monotonic counter incremented on every (re)bootstrap. Async bootstrap\n * work captures the current ID; if it doesn't match by the time the work\n * resolves, the work is discarded.\n */\n private _bootstrapId = 0;\n\n /** True after destroy() — element is permanently unusable. */\n private _destroyed = false;\n\n /** Internal source state. Either string-form (src) OR rich (source). */\n private _src: string | null = null;\n private _source: MediaInput | null = null;\n\n /**\n * Set when the `source` property setter is in the middle of clearing the\n * `src` attribute as part of mutual exclusion. The attributeChangedCallback\n * checks this flag and skips its normal \"clear source\" side effect, which\n * would otherwise wipe the value we just set.\n */\n private _suppressSrcAttrCallback = false;\n\n /** Last-known runtime state surfaced via getters. */\n private _strategy: StrategyName | null = null;\n private _strategyClass: StrategyClass | null = null;\n private _audioTracks: AudioTrackInfo[] = [];\n /** Subtitle tracks reported by the active UnifiedPlayer (options.subtitles\n * + embedded container tracks + programmatic addSubtitle calls). */\n private _subtitleTracks: SubtitleTrackInfo[] = [];\n /** Subtitle tracks derived from light-DOM `<track>` children. Maintained\n * by _syncTextTracks on every mutation. Merged into the public\n * `subtitleTracks` getter so the player's settings menu sees them. */\n private _htmlTrackInfo: SubtitleTrackInfo[] = [];\n\n /**\n * External subtitle list forwarded to `createPlayer()` on the next\n * bootstrap. Setting this after bootstrap queues it for the next\n * source change; consumers that need to swap subtitles mid-playback\n * should set `source` to reload.\n */\n private _subtitles: Array<{ url: string; language?: string; format?: \"vtt\" | \"srt\" }> | null = null;\n\n /**\n * Initial strategy preference. `\"auto\"` means \"let the classifier decide\";\n * any other value is passed to `createPlayer({ initialStrategy })` and\n * skips classification on the next bootstrap. Note that this only affects\n * the *initial* pick — runtime fallback escalation still applies, so a\n * preference of `\"native\"` may still escalate to remux/hybrid/fallback if\n * native fails.\n */\n private _preferredStrategy: PreferredStrategy = \"auto\";\n\n /** Current fit mode. Applied to the inner `<video>` via object-fit, and\n * to the fallback canvas via the `--avbridge-fit` CSS custom property on\n * the stage wrapper (see `src/strategies/fallback/video-renderer.ts`). */\n private _fit: FitMode = DEFAULT_FIT;\n /** The stage wrapper — the element the canvas attaches into, and where\n * the `--avbridge-fit` CSS custom property lives. */\n private _stageEl!: HTMLDivElement;\n\n /** Set if currentTime was assigned before the player was ready. */\n private _pendingSeek: number | null = null;\n /** Set if play() was called before the player was ready. */\n private _pendingPlay = false;\n\n /** MutationObserver tracking light-DOM `<track>` children. */\n private _trackObserver: MutationObserver | null = null;\n\n /** Document-level fullscreenchange handler — installed while connected so\n * the element can lock/unlock screen orientation to match the video's\n * intrinsic aspect. */\n private _fullscreenChangeHandler: (() => void) | null = null;\n /** True if we successfully called screen.orientation.lock() on the last\n * fullscreen entry. Used to know whether to unlock on exit. */\n private _orientationLocked = false;\n\n // ── Construction & lifecycle ───────────────────────────────────────────\n\n constructor() {\n super();\n const root = this.attachShadow({ mode: \"open\" });\n\n // A positioned wrapper inside the shadow root. The fallback strategy\n // overlays a canvas on top of the <video> via `target.parentNode` —\n // that only works if the parent is a real Element with layout. Without\n // this wrapper, `target.parentElement` would be null (ShadowRoot is\n // not an Element) and the canvas would never attach to the DOM.\n const stage = document.createElement(\"div\");\n stage.setAttribute(\"part\", \"stage\");\n stage.style.cssText = `position:relative;width:100%;height:100%;display:block;--avbridge-fit:${DEFAULT_FIT};`;\n root.appendChild(stage);\n this._stageEl = stage;\n\n this._videoEl = document.createElement(\"video\");\n this._videoEl.setAttribute(\"part\", \"video\");\n this._videoEl.style.cssText = `width:100%;height:100%;display:block;background:#000;object-fit:var(--avbridge-fit, ${DEFAULT_FIT});`;\n this._videoEl.playsInline = true;\n stage.appendChild(this._videoEl);\n\n // Forward the underlying <video>'s `progress` event so consumers can\n // observe buffered-range updates without reaching into the shadow DOM.\n // This works for native + remux (real video element with buffered\n // ranges) and is a no-op for hybrid/fallback (canvas-rendered, no\n // buffered ranges yet).\n this._videoEl.addEventListener(\"progress\", () => {\n if (this._destroyed) return;\n this._dispatch(\"progress\", { buffered: this._videoEl.buffered });\n });\n\n // Forward all standard HTMLMediaElement events from the inner <video>\n // so consumers can use the element as a drop-in <video> replacement.\n // Each event is re-dispatched on the wrapper element with no detail —\n // listeners that need state should read it from the element directly.\n for (const eventName of FORWARDED_VIDEO_EVENTS) {\n this._videoEl.addEventListener(eventName, () => {\n if (this._destroyed) return;\n this.dispatchEvent(new Event(eventName, { bubbles: false }));\n });\n }\n }\n\n connectedCallback(): void {\n if (this._destroyed) return;\n // Pick up any <track> children that were declared in HTML before the\n // element upgraded, and watch for future additions/removals.\n this._syncTextTracks();\n if (!this._trackObserver) {\n this._trackObserver = new MutationObserver(() => this._syncTextTracks());\n this._trackObserver.observe(this, { childList: true, subtree: false });\n }\n if (!this._fullscreenChangeHandler) {\n this._fullscreenChangeHandler = () => this._onFullscreenChange();\n document.addEventListener(\"fullscreenchange\", this._fullscreenChangeHandler);\n }\n // Connection is the trigger for bootstrap. If we have a pending source\n // (set before connect), kick off bootstrap now.\n const source = this._activeSource();\n if (source != null) {\n void this._bootstrap(source);\n }\n }\n\n disconnectedCallback(): void {\n if (this._destroyed) return;\n if (this._trackObserver) {\n this._trackObserver.disconnect();\n this._trackObserver = null;\n }\n if (this._fullscreenChangeHandler) {\n document.removeEventListener(\"fullscreenchange\", this._fullscreenChangeHandler);\n this._fullscreenChangeHandler = null;\n }\n // If we were fullscreen via some ancestor and got disconnected, release\n // any orientation lock we had taken.\n this._releaseOrientationLock();\n // Bump the bootstrap token so any in-flight async work is invalidated\n // before we tear down. _teardown() also bumps but we want the bump to\n // happen synchronously here so any awaited promise that resolves\n // between `disconnect` and `_teardown` sees the new ID.\n this._bootstrapId++;\n void this._teardown();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void {\n if (this._destroyed) return;\n switch (name) {\n case \"src\":\n if (this._suppressSrcAttrCallback) break;\n this._setSrcInternal(newValue);\n break;\n case \"autoplay\":\n case \"muted\":\n case \"loop\":\n case \"playsinline\":\n case \"disableremoteplayback\":\n // Reflect onto the underlying <video> element.\n if (newValue == null) this._videoEl.removeAttribute(name);\n else this._videoEl.setAttribute(name, newValue);\n break;\n case \"preload\":\n case \"poster\":\n case \"crossorigin\":\n if (newValue == null) this._videoEl.removeAttribute(name);\n else this._videoEl.setAttribute(name, newValue);\n break;\n case \"diagnostics\":\n // Phase A: no UI. Property is observable for users via getDiagnostics().\n break;\n case \"preferstrategy\":\n if (newValue && PREFERRED_STRATEGY_VALUES.has(newValue as PreferredStrategy)) {\n this._preferredStrategy = newValue as PreferredStrategy;\n } else {\n this._preferredStrategy = \"auto\";\n }\n break;\n case \"fit\": {\n const next: FitMode = newValue && FIT_VALUES.has(newValue as FitMode)\n ? (newValue as FitMode)\n : DEFAULT_FIT;\n if (next === this._fit) break;\n this._fit = next;\n this._stageEl.style.setProperty(\"--avbridge-fit\", next);\n this._dispatch(\"fitchange\", { fit: next });\n break;\n }\n }\n }\n\n // ── Source handling ────────────────────────────────────────────────────\n\n /** Returns the currently-active source (src or source), whichever is set. */\n private _activeSource(): MediaInput | null {\n if (this._source != null) return this._source;\n if (this._src != null) return this._src;\n return null;\n }\n\n /**\n * Mirror light-DOM `<track>` children into the shadow `<video>` so that\n * the browser's native text-track machinery picks them up. Called on\n * connect, on every mutation of light-DOM children, and once after each\n * source change so newly-set tracks survive a fresh `<video>`.\n *\n * Strategy: clone the children. We don't move them because the user's\n * code may still hold references to the originals (e.g. to set `default`).\n * The shadow copies are throwaway — we wipe them on every sync.\n */\n private _syncTextTracks(): void {\n // Remove existing shadow tracks.\n const existing = this._videoEl.querySelectorAll(\"track\");\n for (const t of Array.from(existing)) t.remove();\n // Clone every <track> light-DOM child into the shadow video, and\n // rebuild the HTML-derived subtitle info list so the `<avbridge-player>`\n // settings menu can render them alongside options-sourced tracks.\n // HTML tracks are assigned high, stable IDs (10000+index) to avoid\n // colliding with container-embedded ids (typically < 32).\n this._htmlTrackInfo = [];\n let htmlIdx = 0;\n for (const child of Array.from(this.children)) {\n if (child.tagName === \"TRACK\") {\n const track = child as HTMLTrackElement;\n const clone = track.cloneNode(true) as HTMLTrackElement;\n this._videoEl.appendChild(clone);\n const src = track.getAttribute(\"src\") ?? undefined;\n const format = src?.toLowerCase().endsWith(\".srt\") ? \"srt\" : \"vtt\";\n this._htmlTrackInfo.push({\n id: 10000 + htmlIdx,\n format,\n language: track.srclang || track.getAttribute(\"label\") || undefined,\n sidecarUrl: src,\n });\n htmlIdx++;\n }\n }\n this._dispatch(\"trackschange\", {\n audioTracks: this._audioTracks,\n subtitleTracks: this.subtitleTracks,\n });\n }\n\n /** Internal src setter — separate from the property setter so the\n * attributeChangedCallback can use it without re-entering reflection. */\n private _setSrcInternal(value: string | null): void {\n // Same-value reassignment: no-op (#11 in the lifecycle list).\n if (value === this._src && this._source == null) return;\n this._src = value;\n this._source = null;\n this._onSourceChanged();\n }\n\n /** Called whenever the active source changes (src or source). */\n private _onSourceChanged(): void {\n if (this._destroyed) return;\n const source = this._activeSource();\n if (source == null) {\n // Null transition: tear down and stay idle.\n this._bootstrapId++;\n void this._teardown();\n return;\n }\n // Only bootstrap if we're connected to the DOM.\n if (this.isConnected) {\n void this._bootstrap(source);\n }\n }\n\n // ── Bootstrap (the only place a UnifiedPlayer is created) ──────────────\n\n private async _bootstrap(source: MediaInput): Promise<void> {\n if (this._destroyed) return;\n const id = ++this._bootstrapId;\n\n // Tear down any existing player before starting a new one. Pass the\n // bootstrap id we just claimed so teardown doesn't bump it again\n // (which would invalidate ourselves).\n await this._teardown(id);\n if (id !== this._bootstrapId || this._destroyed) return;\n\n this._dispatch(\"loadstart\", {});\n\n let player: UnifiedPlayer;\n try {\n player = await createPlayer({\n source,\n target: this._videoEl,\n // Honor the consumer's preferred initial strategy. \"auto\" means\n // \"let the classifier decide\" — the createPlayer call simply doesn't\n // pass initialStrategy in that case.\n ...(this._preferredStrategy !== \"auto\"\n ? { initialStrategy: this._preferredStrategy }\n : {}),\n ...(this._subtitles ? { subtitles: this._subtitles } : {}),\n });\n } catch (err) {\n // Stale or destroyed — silently abandon.\n if (id !== this._bootstrapId || this._destroyed) return;\n this._dispatchError(err);\n return;\n }\n\n // Race check: if anything happened during the await above, bail.\n if (id !== this._bootstrapId || this._destroyed || !this.isConnected) {\n try { await player.destroy(); } catch { /* ignore */ }\n return;\n }\n\n this._player = player;\n\n // Resync any light-DOM <track> children into the (possibly fresh) shadow\n // <video>. Strategies that swap or reset the inner video state would\n // otherwise lose the tracks the user declared in HTML.\n this._syncTextTracks();\n\n // Wire events. The unsubscribe handles are not stored individually\n // because destroy() will tear down the whole session anyway.\n player.on(\"strategy\", ({ strategy, reason }) => {\n // strategy event fires on initial classification AND any escalation.\n const cls = player.getDiagnostics().strategyClass;\n this._strategy = strategy;\n this._strategyClass = cls === \"pending\" ? null : cls;\n this._dispatch(\"strategychange\", {\n strategy,\n strategyClass: this._strategyClass,\n reason,\n diagnostics: player.getDiagnostics(),\n });\n });\n\n player.on(\"strategychange\", ({ from, to, reason, currentTime }) => {\n this._dispatch(\"strategychange\", {\n from,\n strategy: to,\n strategyClass: player.getDiagnostics().strategyClass === \"pending\" ? null : player.getDiagnostics().strategyClass,\n reason,\n currentTime,\n diagnostics: player.getDiagnostics(),\n });\n });\n\n player.on(\"tracks\", ({ video: _v, audio, subtitle }) => {\n this._audioTracks = audio;\n this._subtitleTracks = subtitle;\n this._dispatch(\"trackschange\", {\n audioTracks: audio,\n subtitleTracks: subtitle,\n });\n });\n\n player.on(\"error\", (err: Error) => {\n this._dispatchError(err);\n });\n\n player.on(\"timeupdate\", ({ currentTime }) => {\n this._dispatch(\"timeupdate\", { currentTime });\n });\n\n player.on(\"ended\", () => {\n this._dispatch(\"ended\", {});\n });\n\n player.on(\"ready\", () => {\n this._dispatch(\"ready\", { diagnostics: player.getDiagnostics() });\n // Apply any pending seek that was set before the player existed.\n if (this._pendingSeek != null) {\n const t = this._pendingSeek;\n this._pendingSeek = null;\n void player.seek(t).catch(() => { /* ignore */ });\n }\n // Honor any pending play() that was queued before bootstrap finished.\n if (this._pendingPlay) {\n this._pendingPlay = false;\n void player.play().catch(() => { /* ignore — autoplay may be blocked */ });\n } else if (this.autoplay) {\n void player.play().catch(() => { /* ignore */ });\n }\n });\n }\n\n /**\n * Tear down the active player and reset runtime state. Idempotent.\n * If `currentBootstrapId` is provided, the bootstrap counter is NOT\n * incremented (used by `_bootstrap()` to avoid invalidating itself).\n */\n private async _teardown(currentBootstrapId?: number): Promise<void> {\n if (currentBootstrapId == null) {\n // External callers (disconnect, destroy, source change) should bump\n // the counter so any in-flight bootstrap is invalidated. The internal\n // _bootstrap() call passes its own ID and we skip the bump.\n this._bootstrapId++;\n }\n const player = this._player;\n this._player = null;\n this._strategy = null;\n this._strategyClass = null;\n this._audioTracks = [];\n this._subtitleTracks = [];\n if (player) {\n try { await player.destroy(); } catch { /* ignore */ }\n }\n }\n\n // ── Public properties ──────────────────────────────────────────────────\n\n get src(): string | null {\n return this._src;\n }\n\n set src(value: string | null) {\n if (value == null) {\n this.removeAttribute(\"src\");\n } else {\n this.setAttribute(\"src\", value);\n }\n // attributeChangedCallback handles the rest.\n }\n\n get source(): MediaInput | null {\n return this._source;\n }\n\n set source(value: MediaInput | null) {\n // Same-value reassignment for rich values is identity-based.\n if (value === this._source && this._src == null) return;\n this._source = value;\n if (value != null) {\n // Setting source clears src. Suppress the attribute callback so\n // removing the src attribute doesn't wipe the source we just set.\n this._src = null;\n if (this.hasAttribute(\"src\")) {\n this._suppressSrcAttrCallback = true;\n try {\n this.removeAttribute(\"src\");\n } finally {\n this._suppressSrcAttrCallback = false;\n }\n }\n }\n this._onSourceChanged();\n }\n\n get autoplay(): boolean {\n return this.hasAttribute(\"autoplay\");\n }\n\n set autoplay(value: boolean) {\n if (value) this.setAttribute(\"autoplay\", \"\");\n else this.removeAttribute(\"autoplay\");\n }\n\n get muted(): boolean {\n // Read through to the inner <video>'s IDL property — on canvas\n // strategies the property is patched via Object.defineProperty to\n // mirror AudioOutput state, and consumers need the truthful value.\n return this._videoEl.muted;\n }\n\n set muted(value: boolean) {\n // Drive the IDL property (fires volumechange per HTML spec) rather\n // than toggling the attribute (which on most browsers is parse-time\n // only and does NOT fire volumechange when toggled runtime). On\n // canvas strategies, the property is patched via Object.defineProperty\n // which also dispatches volumechange; one code path, both worlds.\n this._videoEl.muted = value;\n // Keep the attribute in sync so CSS selectors like [muted] and\n // re-queries via getAttribute reflect current state.\n if (value) this.setAttribute(\"muted\", \"\");\n else this.removeAttribute(\"muted\");\n }\n\n get loop(): boolean {\n return this.hasAttribute(\"loop\");\n }\n\n set loop(value: boolean) {\n if (value) this.setAttribute(\"loop\", \"\");\n else this.removeAttribute(\"loop\");\n }\n\n get preload(): \"none\" | \"metadata\" | \"auto\" {\n const v = this.getAttribute(\"preload\");\n return v === \"none\" || v === \"metadata\" || v === \"auto\" ? v : \"auto\";\n }\n\n set preload(value: \"none\" | \"metadata\" | \"auto\") {\n this.setAttribute(\"preload\", value);\n }\n\n get diagnostics(): boolean {\n return this.hasAttribute(\"diagnostics\");\n }\n\n set diagnostics(value: boolean) {\n if (value) this.setAttribute(\"diagnostics\", \"\");\n else this.removeAttribute(\"diagnostics\");\n }\n\n get fit(): FitMode {\n return this._fit;\n }\n\n set fit(value: FitMode) {\n if (!FIT_VALUES.has(value)) return;\n this.setAttribute(\"fit\", value);\n }\n\n get preferredStrategy(): PreferredStrategy {\n return this._preferredStrategy;\n }\n\n set preferredStrategy(value: PreferredStrategy) {\n if (PREFERRED_STRATEGY_VALUES.has(value)) {\n this.setAttribute(\"preferstrategy\", value);\n }\n }\n\n get currentTime(): number {\n return this._player?.getCurrentTime() ?? 0;\n }\n\n set currentTime(value: number) {\n if (this._player) {\n void this._player.seek(value).catch(() => { /* ignore */ });\n } else {\n // Defer to the next bootstrap. The `ready` handler applies it.\n this._pendingSeek = value;\n }\n }\n\n get duration(): number {\n return this._player?.getDuration() ?? NaN;\n }\n\n get paused(): boolean {\n return this._videoEl.paused;\n }\n\n get ended(): boolean {\n return this._videoEl.ended;\n }\n\n get readyState(): number {\n return this._videoEl.readyState;\n }\n\n /**\n * Buffered time ranges for the active source. Mirrors the standard\n * `<video>.buffered` `TimeRanges` API.\n *\n * - **Native / remux:** pass-through to the real `<video>.buffered`\n * (reflects the browser's SourceBuffer / progressive-download state).\n * - **Hybrid / fallback:** a single `[0, frontier]` range synthesized\n * from the demuxer's read progress — \"how far libav has ever pumped\n * packets through.\" Monotonic; does not shrink on seek. This is an\n * approximation, not MSE-fidelity: decoded frames on canvas strategies\n * are consumed in flight, so we can't report per-range availability\n * the way MSE does. Enough for a seek-bar buffered indicator.\n */\n get buffered(): TimeRanges {\n return this._videoEl.buffered;\n }\n\n // ── HTMLMediaElement parity ───────────────────────────────────────────\n // Mirror the standard <video> surface so consumers can drop the element\n // in as a <video> replacement. Each property is a thin passthrough to the\n // shadow `<video>`.\n\n get poster(): string {\n return this._videoEl.poster;\n }\n set poster(value: string) {\n if (value == null || value === \"\") this.removeAttribute(\"poster\");\n else this.setAttribute(\"poster\", value);\n }\n\n get volume(): number {\n return this._videoEl.volume;\n }\n set volume(value: number) {\n this._videoEl.volume = value;\n }\n\n get playbackRate(): number {\n return this._videoEl.playbackRate;\n }\n set playbackRate(value: number) {\n this._videoEl.playbackRate = value;\n }\n\n get videoWidth(): number {\n return this._videoEl.videoWidth;\n }\n\n get videoHeight(): number {\n return this._videoEl.videoHeight;\n }\n\n get played(): TimeRanges {\n return this._videoEl.played;\n }\n\n get seekable(): TimeRanges {\n return this._videoEl.seekable;\n }\n\n get crossOrigin(): string | null {\n return this._videoEl.crossOrigin;\n }\n set crossOrigin(value: string | null) {\n if (value == null) this.removeAttribute(\"crossorigin\");\n else this.setAttribute(\"crossorigin\", value);\n }\n\n get disableRemotePlayback(): boolean {\n return this._videoEl.disableRemotePlayback;\n }\n set disableRemotePlayback(value: boolean) {\n if (value) this.setAttribute(\"disableremoteplayback\", \"\");\n else this.removeAttribute(\"disableremoteplayback\");\n }\n\n /**\n * Native `HTMLMediaElement.canPlayType()` passthrough. Note that this\n * answers about the *browser's* native support, not avbridge's full\n * capabilities — avbridge can play many formats this method returns \"\"\n * for, by routing them to the remux/hybrid/fallback strategies.\n */\n canPlayType(mimeType: string): CanPlayTypeResult {\n return this._videoEl.canPlayType(mimeType);\n }\n\n /**\n * **Escape hatch.** The underlying shadow-DOM `<video>` element.\n *\n * Use for native browser APIs the wrapper doesn't expose:\n * - `el.videoElement.requestPictureInPicture()`\n * - `el.videoElement.audioTracks` (browser native, not avbridge's track list)\n * - direct integration with libraries that need a real HTMLVideoElement\n *\n * **Caveat:** When the active strategy is `\"fallback\"` or `\"hybrid\"`,\n * frames are rendered to a canvas overlay, not into this `<video>`.\n * APIs that depend on the actual pixels (Picture-in-Picture, captureStream)\n * will not show the playing content in those modes. Check `el.strategy`\n * before using such APIs.\n */\n get videoElement(): HTMLVideoElement {\n return this._videoEl;\n }\n\n get strategy(): StrategyName | null {\n return this._strategy;\n }\n\n get strategyClass(): StrategyClass | null {\n return this._strategyClass;\n }\n\n get player(): UnifiedPlayer | null {\n return this._player;\n }\n\n get audioTracks(): AudioTrackInfo[] {\n return this._audioTracks;\n }\n\n get subtitleTracks(): SubtitleTrackInfo[] {\n // Merge player-sourced tracks with light-DOM `<track>` children.\n // Both sources coexist: options.subtitles + embedded-in-container\n // tracks contribute to _subtitleTracks; HTML `<track>` children\n // contribute _htmlTrackInfo with ids in the 10000+ range.\n return this._htmlTrackInfo.length === 0\n ? this._subtitleTracks\n : [...this._subtitleTracks, ...this._htmlTrackInfo];\n }\n\n /**\n * External subtitle files to attach when the source loads. Takes effect\n * on the next bootstrap — set before assigning `source`, or reload via\n * `load()` after changing. For dynamic post-bootstrap addition, use\n * `addSubtitle()` instead.\n *\n * @example\n * el.subtitles = [{ url: \"/en.srt\", format: \"srt\", language: \"en\" }];\n * el.src = \"/movie.mp4\";\n */\n get subtitles(): Array<{ url: string; language?: string; format?: \"vtt\" | \"srt\" }> | null {\n return this._subtitles;\n }\n\n set subtitles(value: Array<{ url: string; language?: string; format?: \"vtt\" | \"srt\" }> | null) {\n this._subtitles = value;\n }\n\n /**\n * Attach a subtitle track to the current playback without rebuilding\n * the player. Works while the element is playing — converts SRT to\n * VTT if needed, adds a `<track>` to the inner `<video>`. Canvas\n * strategies pick up the new track via their textTracks watcher.\n */\n async addSubtitle(subtitle: { url: string; language?: string; format?: \"vtt\" | \"srt\" }): Promise<void> {\n const { attachSubtitleTracks } = await import(\"../subtitles/index.js\");\n const format = subtitle.format ?? (subtitle.url.endsWith(\".srt\") ? \"srt\" : \"vtt\");\n const track = {\n id: this._subtitleTracks.length,\n format,\n language: subtitle.language,\n sidecarUrl: subtitle.url,\n };\n this._subtitleTracks.push(track);\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] addSubtitle id=${track.id} format=${format} lang=${subtitle.language ?? \"?\"}`);\n await attachSubtitleTracks(\n this._videoEl,\n this._subtitleTracks,\n undefined,\n (err, t) => {\n // eslint-disable-next-line no-console\n console.warn(`[avbridge:subs] subtitle ${t.id} failed: ${err.message}`);\n },\n );\n // Enable the newly-added track so it renders immediately. On native\n // strategy the <video>'s textTrack must be mode=\"showing\"; on canvas\n // strategies the renderer's watchTextTracks picks it up from the\n // hidden-mode textTracks.\n const textTracks = this._videoEl.textTracks;\n for (let i = 0; i < textTracks.length; i++) {\n if (textTracks[i].label === (subtitle.language ?? `Subtitle ${track.id}`)) {\n textTracks[i].mode = \"showing\";\n // eslint-disable-next-line no-console\n console.log(`[avbridge:subs] enabled textTrack[${i}] mode=showing`);\n break;\n }\n }\n // Notify the settings sheet so it rebuilds with the new track.\n this._dispatch(\"trackschange\", {\n audioTracks: this._audioTracks,\n subtitleTracks: this.subtitleTracks,\n });\n }\n\n /**\n * Disable the automatic `screen.orientation.lock()` that runs on\n * fullscreen entry. Set when you want to honor the device's native\n * auto-rotate instead of matching the video's intrinsic orientation.\n */\n get noOrientationLock(): boolean {\n return this.hasAttribute(\"no-orientation-lock\");\n }\n\n set noOrientationLock(value: boolean) {\n if (value) this.setAttribute(\"no-orientation-lock\", \"\");\n else this.removeAttribute(\"no-orientation-lock\");\n }\n\n // ── Fullscreen orientation lock ────────────────────────────────────────\n\n /** Called whenever `document.fullscreenchange` fires. If this element (or\n * any of its ancestors) is now fullscreen, derive the target orientation\n * from the video's intrinsic size and call `screen.orientation.lock()`.\n * On exit, release the lock we took. iOS Safari rejects `lock()` — we\n * swallow the rejection so nothing breaks on that path. */\n private _onFullscreenChange(): void {\n if (this._destroyed) return;\n const fsEl = document.fullscreenElement;\n const nowFullscreen = fsEl != null && this._isInsideOrEquals(fsEl);\n if (nowFullscreen && !this._orientationLocked) {\n if (this.noOrientationLock) return;\n const target = this._desiredOrientation();\n if (!target) return; // square or unknown — don't lock\n void this._lockOrientation(target);\n } else if (!nowFullscreen && this._orientationLocked) {\n this._releaseOrientationLock();\n }\n }\n\n /** Walk composed-tree ancestors to see if `target` is this element or\n * any ancestor across shadow boundaries. `Node.contains()` can't cross\n * shadow roots, so when `<avbridge-player>` (the fullscreen element)\n * hosts this `<avbridge-video>` inside its shadow DOM, `contains()`\n * returns false. */\n private _isInsideOrEquals(target: Element): boolean {\n let node: Node | null = this;\n while (node) {\n if (node === target) return true;\n const parent: Node | null = node.parentNode;\n if (parent instanceof ShadowRoot) node = parent.host;\n else node = parent;\n }\n return false;\n }\n\n /** Derive \"landscape\" / \"portrait\" from the intrinsic video dimensions.\n * Returns null when dimensions aren't known yet or the video is square.\n * Uses `videoWidth` / `videoHeight` from the inner `<video>`, which the\n * browser sets to the display-aspect-corrected size (so anamorphic\n * content is judged by its display aspect, not pixel aspect). */\n private _desiredOrientation(): \"landscape\" | \"portrait\" | null {\n const w = this._videoEl.videoWidth;\n const h = this._videoEl.videoHeight;\n if (!w || !h) return null;\n if (w === h) return null;\n return w > h ? \"landscape\" : \"portrait\";\n }\n\n /** Attempt to lock screen orientation. Swallows rejections — iOS Safari\n * doesn't implement `lock()`, and desktop / non-fullscreen contexts will\n * reject too. Records success so we know whether to unlock on exit. */\n private async _lockOrientation(target: \"landscape\" | \"portrait\"): Promise<void> {\n const so = (screen as Screen & {\n orientation?: ScreenOrientation & { lock?: (o: string) => Promise<void> };\n }).orientation;\n if (!so || typeof so.lock !== \"function\") return;\n try {\n await so.lock(target);\n this._orientationLocked = true;\n } catch {\n // iOS Safari, desktop, or user denied — ignore.\n }\n }\n\n private _releaseOrientationLock(): void {\n if (!this._orientationLocked) return;\n this._orientationLocked = false;\n const so = screen.orientation as ScreenOrientation | undefined;\n if (so && typeof so.unlock === \"function\") {\n try { so.unlock(); } catch { /* ignore */ }\n }\n }\n\n // ── Public methods ─────────────────────────────────────────────────────\n\n /** Force a (re-)bootstrap if a source is currently set. */\n async load(): Promise<void> {\n if (this._destroyed) return;\n const source = this._activeSource();\n if (source == null) return;\n await this._bootstrap(source);\n }\n\n /**\n * Begin or resume playback. If the player isn't ready yet, the call is\n * queued and applied once `ready` fires.\n */\n async play(): Promise<void> {\n if (this._destroyed) return;\n if (this._player) {\n await this._player.play();\n } else {\n this._pendingPlay = true;\n }\n }\n\n pause(): void {\n if (this._destroyed) return;\n this._pendingPlay = false;\n this._player?.pause();\n }\n\n /**\n * Tear down the element permanently. After destroy(), the element ignores\n * all method calls and attribute changes.\n */\n async destroy(): Promise<void> {\n if (this._destroyed) return;\n this._destroyed = true;\n await this._teardown();\n this._dispatch(\"destroy\", {});\n }\n\n async setAudioTrack(id: number): Promise<void> {\n if (this._destroyed || !this._player) return;\n await this._player.setAudioTrack(id);\n }\n\n async setSubtitleTrack(id: number | null): Promise<void> {\n if (this._destroyed || !this._player) return;\n await this._player.setSubtitleTrack(id);\n }\n\n getDiagnostics(): DiagnosticsSnapshot | null {\n return this._player?.getDiagnostics() ?? null;\n }\n\n // ── Typed addEventListener / removeEventListener overloads ────────────\n // Consumers using avbridge-specific events get a typed CustomEvent\n // payload; standard HTMLMediaElement events retain their native types.\n\n override addEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void {\n super.addEventListener(type, listener, options);\n }\n\n override removeEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgeVideoElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void {\n super.removeEventListener(type, listener, options);\n }\n\n // ── Event helpers ──────────────────────────────────────────────────────\n\n private _dispatch<T>(name: string, detail: T): void {\n this.dispatchEvent(new CustomEvent(name, { detail, bubbles: false }));\n }\n\n private _dispatchError(err: unknown): void {\n const error = err instanceof Error ? err : new Error(String(err));\n this._dispatch(\"error\", { error, diagnostics: this._player?.getDiagnostics() ?? null });\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"avbridge-video\": AvbridgeVideoElement;\n }\n}\n","/**\n * Shadow DOM CSS for <avbridge-player>.\n * YouTube-inspired dark theme. All controls use ::part() for external styling.\n */\n\nexport const PLAYER_STYLES = /* css */ `\n:host {\n display: block;\n position: relative;\n width: 100%;\n background: #000;\n overflow: hidden;\n user-select: none;\n -webkit-user-select: none;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n color: #fff;\n line-height: 1;\n}\n\n:host(:fullscreen),\n:host(:fullscreen) .avp {\n width: 100vw;\n height: 100vh;\n}\n\n/* ── Container ────────────────────────────────────────────────────────── */\n\n:host {\n -webkit-tap-highlight-color: transparent;\n outline: none;\n}\n\n.avp {\n position: relative;\n width: 100%;\n height: 100%;\n -webkit-tap-highlight-color: transparent;\n user-select: none;\n}\n\n.avp avbridge-video {\n display: block;\n width: 100%;\n height: 100%;\n}\n\n/* Drag-and-drop file target highlight. */\n.avp.avp-dragover::after {\n content: \"\";\n position: absolute;\n inset: 8px;\n border: 2px dashed rgba(255, 255, 255, 0.75);\n border-radius: 4px;\n background: rgba(0, 0, 0, 0.25);\n pointer-events: none;\n z-index: 10;\n}\n\n/* ── Center overlay ───────────────────────────────────────────────────── */\n\n.avp-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n z-index: 2;\n}\n\n.avp-overlay-btn {\n width: 68px;\n height: 68px;\n border-radius: 50%;\n background: rgba(0, 0, 0, 0.6);\n border: none;\n color: #fff;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: opacity 0.2s, transform 0.15s;\n opacity: 0;\n transform: scale(0.9);\n}\n\n.avp-overlay-btn svg {\n width: 36px;\n height: 36px;\n}\n\n.avp-overlay-btn:hover {\n background: rgba(0, 0, 0, 0.75);\n transform: scale(1);\n}\n\n:host([data-state=\"idle\"]) .avp-overlay-btn,\n:host([data-state=\"paused\"]) .avp-overlay-btn {\n opacity: 1;\n transform: scale(1);\n}\n\n/* ── Loading spinner ──────────────────────────────────────────────────── */\n\n.avp-spinner {\n width: 48px;\n height: 48px;\n border: 4px solid rgba(255, 255, 255, 0.3);\n border-top-color: #fff;\n border-radius: 50%;\n display: none;\n pointer-events: none;\n}\n\n:host([data-state=\"loading\"]) .avp-spinner,\n:host([data-state=\"buffering\"]) .avp-spinner {\n display: block;\n animation: avp-spin 0.8s linear infinite;\n}\n\n:host([data-state=\"loading\"]) .avp-overlay-btn,\n:host([data-state=\"buffering\"]) .avp-overlay-btn {\n display: none;\n}\n\n@keyframes avp-spin {\n to { transform: rotate(360deg); }\n}\n\n/* ── Double-tap ripple ────────────────────────────────────────────────── */\n\n.avp-ripple {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n width: 100px;\n height: 100px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n opacity: 0;\n z-index: 3;\n}\n\n.avp-ripple svg { width: 28px; height: 28px; }\n.avp-ripple-left { left: 15%; }\n.avp-ripple-right { right: 15%; }\n\n.avp-ripple.active {\n animation: avp-ripple 0.5s ease-out;\n}\n\n@keyframes avp-ripple {\n 0% { opacity: 1; transform: translateY(-50%) scale(0.5); }\n 100% { opacity: 0; transform: translateY(-50%) scale(1.5); }\n}\n\n/* ── Speed indicator (tap-and-hold) ───────────────────────────────────── */\n\n.avp-speed-indicator {\n position: absolute;\n top: 12px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(0, 0, 0, 0.7);\n padding: 6px 16px;\n border-radius: 20px;\n font-size: 14px;\n font-weight: 600;\n pointer-events: none;\n opacity: 0;\n z-index: 4;\n transition: opacity 0.15s;\n}\n\n.avp-speed-indicator.active { opacity: 1; }\n\n/* ── Controls bar ─────────────────────────────────────────────────────── */\n\n.avp-controls {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 5;\n padding: 0 12px 8px;\n background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));\n display: flex;\n flex-direction: column;\n gap: 4px;\n opacity: 1;\n transition: opacity 0.25s;\n}\n\n:host([data-controls-hidden]) .avp-controls {\n opacity: 0;\n pointer-events: none;\n}\n\n:host([data-controls-hidden]) { cursor: none; }\n\n/* ── Top toolbar (slotted consumer chrome) ─────────────────────────────\n Two named slots (top-left, top-right) let consumers place back / title /\n translate buttons inside the auto-hide chrome. Wrapper has\n pointer-events:none so empty slots don't block container clicks; each\n side re-enables pointer-events so real buttons remain interactive. */\n\n.avp-toolbar-top {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n z-index: 5;\n padding: 8px 12px 24px;\n background: linear-gradient(rgba(0, 0, 0, 0.6), transparent);\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 8px;\n opacity: 1;\n pointer-events: none;\n transition: opacity 0.25s;\n}\n\n.avp-toolbar-top-left,\n.avp-toolbar-top-right {\n display: flex;\n align-items: center;\n gap: 8px;\n pointer-events: auto;\n}\n\n/* Left slot fills remaining space so slotted text/content can grow.\n min-width: 0 prevents flex children from overflowing the toolbar. */\n.avp-toolbar-top-left {\n flex: 1;\n min-width: 0;\n}\n\n.avp-toolbar-top-right { margin-left: auto; flex-shrink: 0; }\n\n/* Hide the gradient band when no consumer has slotted anything — we\n toggle data-toolbar-empty from JS via slotchange. */\n:host([data-toolbar-empty]) .avp-toolbar-top {\n background: none;\n}\n\n:host([data-controls-hidden]) .avp-toolbar-top {\n opacity: 0;\n pointer-events: none;\n}\n\n/* ── Content overlay ─────────────────────────────────────────────────── */\n/* Consumer-provided rich content (tweet cards, media info, annotations).\n Sits above the video, below the play-button overlay and controls in\n z-order. Auto-hides with the chrome. The wrapper is pointer-events:none\n so taps fall through to the video; consumers opt in on their content\n with pointer-events:auto. */\n\n.avp-content-overlay {\n position: absolute;\n inset: 0;\n z-index: 1;\n pointer-events: none;\n opacity: 1;\n transition: opacity 0.25s;\n}\n\n.avp-content-overlay ::slotted(*) {\n pointer-events: auto;\n}\n\n:host([data-controls-hidden]) .avp-content-overlay {\n opacity: 0;\n}\n\n/* ── Seek bar ─────────────────────────────────────────────────────────── */\n\n.avp-seek {\n position: relative;\n height: 20px;\n display: flex;\n align-items: center;\n cursor: pointer;\n /* Claim all touch gestures on the seek bar. Without this, Android\n * browsers (Chrome, Samsung Internet) treat horizontal drags as\n * scroll candidates and cancel pointermove once the gesture\n * resolves, breaking scrub. touch-action must be set in CSS —\n * preventDefault() on pointerdown is too late. */\n touch-action: none;\n}\n\n.avp-seek-track {\n position: absolute;\n left: 0;\n right: 0;\n height: 3px;\n background: rgba(255, 255, 255, 0.2);\n border-radius: 2px;\n overflow: hidden;\n transition: height 0.1s;\n}\n\n.avp-seek:hover .avp-seek-track { height: 5px; }\n\n.avp-seek-buffered {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n.avp-seek-buffered-range {\n position: absolute;\n top: 0;\n height: 100%;\n background: rgba(255, 255, 255, 0.35);\n border-radius: inherit;\n}\n\n.avp-seek-progress {\n position: absolute;\n left: 0;\n height: 100%;\n background: #f00;\n border-radius: inherit;\n}\n\n.avp-seek-input {\n position: absolute;\n width: 100%;\n height: 100%;\n margin: 0;\n opacity: 0;\n /* Disable pointer events — we handle clicks/drags manually on .avp-seek\n * so the click position maps linearly across the full track width.\n * The input is still used for keyboard accessibility. */\n pointer-events: none;\n z-index: 1;\n}\n\n.avp-seek-thumb {\n position: absolute;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #f00;\n top: 50%;\n /* Thumb center follows the cursor exactly: left = pct% of track width,\n * then translate(-50%) centers the thumb on that point. Matches the\n * manual pointer-to-time mapping in _timeFromSeekPointer which is\n * also linear from 0% to 100% of the track width. */\n left: calc(var(--pct, 0) * 1%);\n transform: translate(-50%, -50%) scale(0);\n transition: transform 0.1s;\n pointer-events: none;\n}\n\n.avp-seek:hover .avp-seek-thumb { transform: translate(-50%, -50%) scale(1); }\n\n.avp-seek-tooltip {\n position: absolute;\n bottom: 24px;\n background: rgba(0, 0, 0, 0.8);\n padding: 4px 8px;\n border-radius: 3px;\n font-size: 12px;\n white-space: nowrap;\n transform: translateX(-50%);\n pointer-events: none;\n display: none;\n}\n\n.avp-seek:hover .avp-seek-tooltip { display: block; }\n\n/* Show tooltip during active drag (touch or mouse). The JS side sets\n data-seeking on .avp-seek while the user is scrubbing. */\n.avp-seek[data-seeking] .avp-seek-tooltip { display: block; }\n\n/* Enlarge thumb while scrubbing. */\n.avp-seek[data-seeking] .avp-seek-thumb {\n transform: translate(-50%, -50%) scale(1.4);\n}\n\n/* ── Bottom row ───────────────────────────────────────────────────────── */\n\n.avp-bottom {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 36px;\n}\n\n.avp-btn {\n background: none;\n border: none;\n color: #fff;\n padding: 4px;\n cursor: pointer;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.9;\n transition: opacity 0.1s;\n}\n\n.avp-btn:hover { opacity: 1; }\n.avp-btn svg { width: 24px; height: 24px; }\n\n/* ── Volume ───────────────────────────────────────────────────────────── */\n\n.avp-volume {\n display: flex;\n align-items: center;\n gap: 0;\n}\n\n.avp-volume-slider {\n width: 0;\n overflow: hidden;\n transition: width 0.15s;\n display: flex;\n align-items: center;\n /* Extra padding so the thumb isn't clipped at track edges */\n padding: 6px 0;\n margin: -6px 0;\n}\n\n.avp-volume:hover .avp-volume-slider { width: 68px; }\n\n.avp-volume-input {\n width: 60px;\n height: 4px;\n -webkit-appearance: none;\n appearance: none;\n background: rgba(255, 255, 255, 0.3);\n border-radius: 2px;\n outline: none;\n cursor: pointer;\n /* Prevent thumb clipping — the thumb is taller than the track */\n overflow: visible;\n margin: 0;\n}\n\n.avp-volume-input::-webkit-slider-thumb {\n -webkit-appearance: none;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #fff;\n cursor: pointer;\n}\n\n.avp-volume-input::-moz-range-thumb {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: #fff;\n border: none;\n cursor: pointer;\n}\n\n/* ── Time display ─────────────────────────────────────────────────────── */\n\n.avp-time {\n font-size: 13px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n opacity: 0.9;\n}\n\n/* ── Strategy badge ───────────────────────────────────────────────────── */\n\n.avp-badge {\n font-size: 11px;\n font-weight: 600;\n padding: 2px 8px;\n border-radius: 3px;\n background: rgba(255, 255, 255, 0.15);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n opacity: 0.8;\n}\n\n.avp-badge[data-strategy=\"native\"] { background: rgba(45, 106, 79, 0.7); }\n.avp-badge[data-strategy=\"remux\"] { background: rgba(30, 96, 145, 0.7); }\n.avp-badge[data-strategy=\"hybrid\"] { background: rgba(199, 125, 255, 0.4); }\n.avp-badge[data-strategy=\"fallback\"] { background: rgba(157, 78, 221, 0.5); }\n\n/* ── Spacer ───────────────────────────────────────────────────────────── */\n\n.avp-spacer { flex: 1; }\n\n/* ── Settings bottom sheet ────────────────────────────────────────────── */\n\n/* Scrim — semi-transparent overlay behind the sheet, above the video.\n Tapping it dismisses the sheet. */\n.avp-settings-scrim {\n position: absolute;\n inset: 0;\n z-index: 9;\n background: rgba(0, 0, 0, 0.4);\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n}\n\n.avp-settings-scrim.open {\n opacity: 1;\n pointer-events: auto;\n}\n\n/* Sheet container — slides up from the bottom. Height is content-driven\n up to a JS-measured max (set on open via style.maxHeight). */\n.avp-settings {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n z-index: 10;\n background: rgba(28, 28, 28, 0.97);\n border-radius: 12px 12px 0 0;\n overflow-y: auto;\n overscroll-behavior: contain;\n transform: translateY(100%);\n transition: transform 0.2s ease-out;\n max-height: 70%;\n padding-bottom: 52px;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5);\n}\n\n.avp-settings.open {\n transform: translateY(0);\n}\n\n/* Drag handle indicator at top of sheet. */\n.avp-settings-handle {\n width: 36px;\n height: 4px;\n border-radius: 2px;\n background: rgba(255, 255, 255, 0.3);\n margin: 8px auto 4px;\n}\n\n/* ── Accordion sections ──────────────────────────────────────────────── */\n\n.avp-settings-section {\n border-bottom: 1px solid rgba(255, 255, 255, 0.08);\n}\n\n.avp-settings-section:last-child { border-bottom: none; }\n\n/* Section header — clickable row showing label + current value. */\n.avp-settings-header {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 12px 16px;\n cursor: pointer;\n font-size: 14px;\n transition: background 0.1s;\n}\n\n.avp-settings-header:hover { background: rgba(255, 255, 255, 0.06); }\n\n.avp-settings-header-label {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 500;\n}\n\n.avp-settings-header-value {\n margin-left: auto;\n opacity: 0.6;\n font-size: 13px;\n text-align: right;\n}\n\n/* Invisible native <select> layered over the value portion of the row.\n Covers from the value text to the right edge so tapping the value\n opens the OS picker. The label side remains inert. */\n.avp-settings-select {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 50%;\n opacity: 0;\n cursor: pointer;\n font-size: 16px;\n direction: rtl;\n}\n\n/* Toggle-style rows (Stats for Nerds) — no select, just clickable. */\n.avp-settings-toggle {\n cursor: pointer;\n}\n.avp-settings-toggle:hover { background: rgba(255, 255, 255, 0.06); }\n\n/* ── Stats for nerds ──────────────────────────────────────────────────── */\n\n.avp-stats {\n position: absolute;\n top: 12px;\n left: 12px;\n background: rgba(0, 0, 0, 0.8);\n padding: 12px 16px;\n border-radius: 6px;\n font-size: 12px;\n font-family: \"SF Mono\", \"Menlo\", \"Consolas\", monospace;\n line-height: 1.6;\n white-space: pre;\n pointer-events: auto;\n z-index: 6;\n max-width: 400px;\n overflow: auto;\n display: none;\n}\n\n.avp-stats.open { display: block; }\n\n/* ── Mobile adjustments ───────────────────────────────────────────────── */\n\n@media (pointer: coarse) {\n .avp-btn svg { width: 28px; height: 28px; }\n .avp-btn { padding: 8px; }\n\n /* Taller touch target on mobile (44px, matching YouTube Mobile)\n while keeping the visual track thin. Negative margin collapses\n the extra space so the controls layout doesn't shift. */\n .avp-seek { height: 44px; margin-top: -12px; margin-bottom: -12px; }\n .avp-seek-track { height: 4px; }\n .avp-seek:hover .avp-seek-track { height: 4px; }\n .avp-seek-thumb {\n transform: translate(-50%, -50%) scale(1);\n width: 16px;\n height: 16px;\n }\n .avp-seek[data-seeking] .avp-seek-thumb {\n transform: translate(-50%, -50%) scale(1.5);\n }\n /* Move tooltip above the taller touch zone. */\n .avp-seek-tooltip { bottom: 32px; }\n\n .avp-volume:hover .avp-volume-slider { width: 0; }\n .avp-overlay-btn { width: 56px; height: 56px; }\n .avp-overlay-btn svg { width: 30px; height: 30px; }\n}\n`;\n","/**\n * Inline SVG icons for <avbridge-player> controls.\n * All icons are 24x24 viewBox, stroke-based where possible for\n * easy theming via CSS `color` (currentColor fill/stroke).\n */\n\nexport const ICON_PLAY = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7z\"/></svg>`;\n\nexport const ICON_PAUSE = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 19h4V5H6zm8-14v14h4V5z\"/></svg>`;\n\nexport const ICON_VOLUME_UP = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z\"/></svg>`;\n\nexport const ICON_VOLUME_OFF = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z\"/></svg>`;\n\nexport const ICON_SETTINGS = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.49.49 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54a.484.484 0 00-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96a.49.49 0 00-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z\"/></svg>`;\n\nexport const ICON_FULLSCREEN = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"/></svg>`;\n\nexport const ICON_FULLSCREEN_EXIT = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z\"/></svg>`;\n\nexport const ICON_REPLAY_10 = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M11.99 5V1l-5 5 5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6h-2c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z\"/><text x=\"10\" y=\"16\" font-size=\"8\" text-anchor=\"middle\" fill=\"currentColor\" font-family=\"sans-serif\">10</text></svg>`;\n\nexport const ICON_FORWARD_10 = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M18 13c0 3.31-2.69 6-6 6s-6-2.69-6-6 2.69-6 6-6v4l5-5-5-5v4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8h-2z\"/><text x=\"14\" y=\"16\" font-size=\"8\" text-anchor=\"middle\" fill=\"currentColor\" font-family=\"sans-serif\">10</text></svg>`;\n\nexport const ICON_SPEED = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M10 8v8l6-4-6-4zm10.77-1.67L22 7.67l-.77-1.34c-.3-.53-.8-.93-1.41-1.05l-1.7-.3c-.16-.43-.36-.84-.6-1.22l.8-1.54-.77-1.34-.77 1.34.8 1.54c-.24.38-.44.79-.6 1.22l-1.7.3c-.61.12-1.11.52-1.41 1.05L13 7.67l1.23-1.34c-.3.53-.3 1.15 0 1.67L15.46 10l-1.23 2.34c-.3.53-.3 1.15 0 1.67L15.46 16l-1.23 2.34.77 1.34.77-1.34-1.23-2.34c.3-.53.3-1.15 0-1.67L13.31 12l1.23-2.34c.3-.53.3-1.15 0-1.67z\"/></svg>`;\n","/**\n * `<avbridge-player>` — YouTube-style controls element.\n *\n * Wraps `<avbridge-video>` with a full player UI: play/pause, seek bar,\n * volume, settings menu (speed, subtitles, audio tracks), fullscreen,\n * keyboard shortcuts, touch gestures, and auto-hiding controls.\n *\n * All properties, methods, and events from `<avbridge-video>` are proxied\n * through. Consumers interact with `<avbridge-player>` exclusively.\n */\n\n// Import the class concretely and register — side-effect-only imports\n// are tree-shaken by Rollup in production builds.\nimport { AvbridgeVideoElement } from \"./avbridge-video.js\";\nif (typeof customElements !== \"undefined\" && !customElements.get(\"avbridge-video\")) {\n customElements.define(\"avbridge-video\", AvbridgeVideoElement);\n}\nimport { PLAYER_STYLES } from \"./player-styles.js\";\nimport {\n ICON_PLAY, ICON_PAUSE,\n ICON_VOLUME_UP, ICON_VOLUME_OFF,\n ICON_SETTINGS,\n ICON_FULLSCREEN, ICON_FULLSCREEN_EXIT,\n ICON_REPLAY_10, ICON_FORWARD_10,\n} from \"./player-icons.js\";\nimport type { AvbridgeVideoElementEventMap, SettingsSectionConfig } from \"../types.js\";\n\n// ── Helpers ──────────────────────────────────────────────────────────────\n\nfunction formatTime(sec: number): string {\n if (!Number.isFinite(sec) || sec < 0) sec = 0;\n const total = Math.floor(sec);\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n const mm = String(m).padStart(h > 0 ? 2 : 1, \"0\");\n const ss = String(s).padStart(2, \"0\");\n return h > 0 ? `${h}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n\nconst PLAYBACK_SPEEDS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2] as const;\nconst DEFAULT_CONTROLS_HIDE_MS = 3000;\n\ntype PlayerState = \"idle\" | \"loading\" | \"playing\" | \"paused\" | \"buffering\" | \"ended\" | \"error\";\n\n// ── Forwarded events ─────────────────────────────────────────────────────\n\nconst FORWARDED_EVENTS = [\n \"ready\", \"error\", \"strategychange\", \"trackschange\", \"loadstart\", \"destroy\",\n \"play\", \"playing\", \"pause\", \"seeking\", \"seeked\", \"volumechange\",\n \"ratechange\", \"durationchange\", \"canplay\", \"canplaythrough\",\n \"waiting\", \"stalled\", \"emptied\", \"resize\",\n \"loadedmetadata\", \"loadeddata\", \"timeupdate\", \"ended\", \"progress\",\n] as const;\n\n// ── Observed attributes ──────────────────────────────────────────────────\n\nconst PROXY_ATTRIBUTES = [\n \"src\", \"autoplay\", \"muted\", \"loop\", \"preload\", \"poster\",\n \"playsinline\", \"crossorigin\", \"disableremoteplayback\", \"preferstrategy\",\n \"fit\",\n] as const;\n\n/** Player-only attributes that don't forward to <avbridge-video>. */\nconst PLAYER_ATTRIBUTES = [\"show-fit\"] as const;\n\nconst FIT_MODES = [\"contain\", \"cover\", \"fill\"] as const;\ntype FitMode = (typeof FIT_MODES)[number];\n\n// ═══════════════════════════════════════════════════════════════════════════\n\nexport class AvbridgePlayerElement extends HTMLElement {\n static readonly observedAttributes = [...PROXY_ATTRIBUTES, ...PLAYER_ATTRIBUTES];\n\n /**\n * Returns `true` if a DOM event originated from one of the player's\n * **interactive chrome elements** (seek bar, control buttons, settings\n * menu, overlay play button) rather than the bare video surface.\n *\n * This is the escape hatch for host pages that wrap the player in a\n * gesture recognizer (e.g. TikTok-style vertical-swipe pager). For\n * bubble-phase listeners the player's own handlers already call\n * `stopPropagation()` on chrome interactions — but **capture-phase**\n * listeners run *before* the player's handlers, so they need to check\n * the event's path themselves and bail. This helper does that check\n * via `composedPath()`, which traverses shadow boundaries correctly.\n *\n * Returns `false` for events on the bare video surface — host pages\n * remain free to claim those for their own gestures (e.g. swipe-to-pan\n * to the next video). Returns `false` for events that never hit a\n * player at all.\n *\n * @example\n * // TikTok-style vertical swipe on the document, capture phase:\n * document.addEventListener(\"pointerdown\", (e) => {\n * if (AvbridgePlayerElement.isPlayerChromeEvent(e)) return;\n * startSwipeGesture(e);\n * }, { capture: true });\n */\n static isPlayerChromeEvent(event: Event): boolean {\n // Mirrors the selector used by the player's internal tap-target\n // gate (see `_onPlayerSurfaceClick` and friends): anything inside\n // these regions is \"chrome\", everything else is the bare video.\n const CHROME_SELECTOR = \".avp-controls, .avp-settings, .avp-overlay-btn\";\n for (const node of event.composedPath()) {\n if (node instanceof HTMLElement && node.matches?.(CHROME_SELECTOR)) {\n return true;\n }\n }\n return false;\n }\n\n // ── Internal DOM refs ──────────────────────────────────────────────────\n\n private _video!: AvbridgeVideoElement;\n private _playBtn!: HTMLButtonElement;\n private _overlayBtn!: HTMLButtonElement;\n private _seekInput!: HTMLInputElement;\n private _seekProgress!: HTMLDivElement;\n private _seekBuffered!: HTMLDivElement;\n private _seekThumb!: HTMLDivElement;\n private _seekTooltip!: HTMLDivElement;\n private _timeDisplay!: HTMLSpanElement;\n private _volumeBtn!: HTMLButtonElement;\n private _volumeInput!: HTMLInputElement;\n private _settingsBtn!: HTMLButtonElement;\n private _settingsMenu!: HTMLDivElement;\n private _settingsScrim!: HTMLDivElement;\n private _customSections: import(\"../types.js\").SettingsSectionConfig[] = [];\n private _fullscreenBtn!: HTMLButtonElement;\n // Strategy badge removed — visible in Stats for Nerds instead.\n // Spinner is rendered but driven entirely by CSS :host([data-state]) selectors.\n private _speedIndicator!: HTMLDivElement;\n private _rippleLeft!: HTMLDivElement;\n private _rippleRight!: HTMLDivElement;\n\n // ── State ──────────────────────────────────────────────────────────────\n\n private _state: PlayerState = \"idle\";\n private _controlsTimer: ReturnType<typeof setTimeout> | null = null;\n private _settingsOpen = false;\n private _activeAudioTrackId: number | null = null;\n private _activeSubtitleTrackId: number | null = null;\n private _userSeeking = false;\n /** Last seek target the user committed. The thumb stays here (and\n * `_updateTime` skips updating from `timeupdate`) until the underlying\n * `currentTime` actually catches up — otherwise the thumb visibly snaps\n * back to the pre-seek position while the remux pipeline rebuilds. */\n private _pendingSeekTarget: number | null = null;\n private _holdTimer: ReturnType<typeof setTimeout> | null = null;\n private _holdSpeedActive = false;\n private _savedPlaybackRate = 1;\n private _lastTapTime = 0;\n private _tapTimer: ReturnType<typeof setTimeout> | null = null;\n private _statsOpen = false;\n private _statsEl!: HTMLDivElement;\n private _statsInterval: ReturnType<typeof setInterval> | null = null;\n private _eventCleanup: (() => void)[] = [];\n private _updateToolbarEmpty: () => void = () => { /* wired in constructor */ };\n private _toolbarTop!: HTMLDivElement;\n\n // ── Constructor ────────────────────────────────────────────────────────\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = `<style>${PLAYER_STYLES}</style>${this._template()}`;\n\n // Grab refs\n this._video = shadow.querySelector(\"avbridge-video\") as AvbridgeVideoElement;\n this._playBtn = shadow.querySelector(\".avp-play\") as HTMLButtonElement;\n this._overlayBtn = shadow.querySelector(\".avp-overlay-btn\") as HTMLButtonElement;\n this._seekInput = shadow.querySelector(\".avp-seek-input\") as HTMLInputElement;\n this._seekProgress = shadow.querySelector(\".avp-seek-progress\") as HTMLDivElement;\n this._seekBuffered = shadow.querySelector(\".avp-seek-buffered\") as HTMLDivElement;\n this._seekThumb = shadow.querySelector(\".avp-seek-thumb\") as HTMLDivElement;\n this._seekTooltip = shadow.querySelector(\".avp-seek-tooltip\") as HTMLDivElement;\n this._timeDisplay = shadow.querySelector(\".avp-time\") as HTMLSpanElement;\n this._volumeBtn = shadow.querySelector(\".avp-volume-btn\") as HTMLButtonElement;\n this._volumeInput = shadow.querySelector(\".avp-volume-input\") as HTMLInputElement;\n this._settingsBtn = shadow.querySelector(\".avp-settings-btn\") as HTMLButtonElement;\n this._settingsMenu = shadow.querySelector(\".avp-settings\") as HTMLDivElement;\n this._settingsScrim = shadow.querySelector(\".avp-settings-scrim\") as HTMLDivElement;\n this._fullscreenBtn = shadow.querySelector(\".avp-fullscreen\") as HTMLButtonElement;\n // Badge removed from controls bar — strategy visible in Stats for Nerds.\n // Spinner is rendered in shadow DOM, driven by CSS :host([data-state]).\n this._speedIndicator = shadow.querySelector(\".avp-speed-indicator\") as HTMLDivElement;\n this._statsEl = shadow.querySelector(\".avp-stats\") as HTMLDivElement;\n this._rippleLeft = shadow.querySelector(\".avp-ripple-left\") as HTMLDivElement;\n this._rippleRight = shadow.querySelector(\".avp-ripple-right\") as HTMLDivElement;\n this._toolbarTop = shadow.querySelector('[part=\"toolbar-top\"]') as HTMLDivElement;\n // Start visible — controls are shown until the auto-hide timer fires.\n this._toolbarTop.setAttribute(\"data-visible\", \"true\");\n\n // Track whether the top toolbar has any slotted content. Used to hide\n // its gradient when empty (see data-toolbar-empty in player-styles.ts).\n // MUST defer the initial attribute write to connectedCallback — the\n // Custom Elements spec forbids constructors from adding attributes.\n const slots = shadow.querySelectorAll<HTMLSlotElement>('slot[name=\"top-left\"], slot[name=\"top-right\"]');\n this._updateToolbarEmpty = () => {\n const hasContent = Array.from(slots).some((s) => s.assignedNodes({ flatten: true }).length > 0);\n if (hasContent) this.removeAttribute(\"data-toolbar-empty\");\n else this.setAttribute(\"data-toolbar-empty\", \"\");\n };\n for (const s of slots) s.addEventListener(\"slotchange\", this._updateToolbarEmpty);\n\n this._bindEvents();\n }\n\n private _template(): string {\n return `\n<div part=\"container\" class=\"avp\">\n <avbridge-video part=\"video\"></avbridge-video>\n <div part=\"toolbar-top\" class=\"avp-toolbar-top\">\n <div part=\"toolbar-top-left\" class=\"avp-toolbar-top-left\"><slot name=\"top-left\"></slot></div>\n <div part=\"toolbar-top-right\" class=\"avp-toolbar-top-right\"><slot name=\"top-right\"></slot></div>\n </div>\n <div part=\"content-overlay\" class=\"avp-content-overlay\"><slot name=\"content-overlay\"></slot></div>\n <div part=\"overlay\" class=\"avp-overlay\">\n <button class=\"avp-overlay-btn\" aria-label=\"Play\">${ICON_PLAY}</button>\n <div class=\"avp-spinner\"></div>\n </div>\n <div class=\"avp-speed-indicator\">2x</div>\n <div class=\"avp-stats\" part=\"stats-panel\"></div>\n <div class=\"avp-ripple avp-ripple-left\">${ICON_REPLAY_10}</div>\n <div class=\"avp-ripple avp-ripple-right\">${ICON_FORWARD_10}</div>\n <div part=\"controls\" class=\"avp-controls\">\n <div class=\"avp-seek\" part=\"seek-bar\">\n <div class=\"avp-seek-track\">\n <div class=\"avp-seek-buffered\"></div>\n <div class=\"avp-seek-progress\"></div>\n </div>\n <div class=\"avp-seek-thumb\"></div>\n <div class=\"avp-seek-tooltip\">0:00</div>\n <input class=\"avp-seek-input\" type=\"range\" min=\"0\" max=\"0\" step=\"any\" value=\"0\" aria-label=\"Seek\">\n </div>\n <div class=\"avp-bottom\">\n <button class=\"avp-btn avp-play\" part=\"play-button\" aria-label=\"Play\">${ICON_PLAY}</button>\n <div class=\"avp-volume\">\n <button class=\"avp-btn avp-volume-btn\" part=\"volume-button\" aria-label=\"Mute\">${ICON_VOLUME_UP}</button>\n <div class=\"avp-volume-slider\">\n <input class=\"avp-volume-input\" part=\"volume-slider\" type=\"range\" min=\"0\" max=\"1\" step=\"0.05\" value=\"1\" aria-label=\"Volume\">\n </div>\n </div>\n <span class=\"avp-time\" part=\"time-display\">0:00 / 0:00</span>\n <span class=\"avp-spacer\"></span>\n <button class=\"avp-btn avp-settings-btn\" part=\"settings-button\" aria-label=\"Settings\">${ICON_SETTINGS}</button>\n <button class=\"avp-btn avp-fullscreen\" part=\"fullscreen-button\" aria-label=\"Fullscreen\">${ICON_FULLSCREEN}</button>\n </div>\n <div class=\"avp-settings-scrim\"></div>\n <div class=\"avp-settings\" part=\"settings-menu\"><div class=\"avp-settings-handle\"></div></div>\n </div>\n</div>`;\n }\n\n // ── Event wiring ───────────────────────────────────────────────────────\n\n private _bindEvents(): void {\n const on = <K extends keyof HTMLElementEventMap>(\n el: EventTarget, event: K | string, fn: (e: Event) => void, opts?: AddEventListenerOptions,\n ) => {\n el.addEventListener(event, fn, opts);\n this._eventCleanup.push(() => el.removeEventListener(event, fn, opts));\n };\n\n // Forward events from inner video\n for (const name of FORWARDED_EVENTS) {\n on(this._video, name, (e) => {\n const detail = (e as CustomEvent).detail;\n this.dispatchEvent(\n detail !== undefined\n ? new CustomEvent(name, { detail, bubbles: e.bubbles, composed: true })\n : new Event(name, { bubbles: e.bubbles }),\n );\n });\n }\n\n // State tracking\n on(this._video, \"loadstart\", () => {\n this._pendingSeekTarget = null;\n this._setState(\"loading\");\n });\n on(this._video, \"ready\", () => {\n this._setState(this._video.paused ? \"paused\" : \"playing\");\n this._seekInput.max = String(this._video.duration || 0);\n this._updateTime();\n this._buildSettingsMenu();\n });\n on(this._video, \"play\", () => this._setState(\"playing\"));\n on(this._video, \"playing\", () => this._setState(\"playing\"));\n on(this._video, \"pause\", () => this._setState(\"paused\"));\n on(this._video, \"waiting\", () => this._setState(\"buffering\"));\n on(this._video, \"ended\", () => this._setState(\"ended\"));\n on(this._video, \"error\", () => this._setState(\"error\"));\n on(this._video, \"timeupdate\", () => this._updateTime());\n // `progress` fires as the inner element's buffered ranges grow — keep the\n // seek bar's buffered indicator fresh even when paused or filling ahead\n // without timeupdate advancing. `<avbridge-video>` dispatches this on\n // all strategies (including the synthesized ranges for canvas strategies).\n on(this._video, \"progress\", () => this._updateBuffered());\n on(this._video, \"volumechange\", () => this._updateVolume());\n // Strategy changes are visible in Stats for Nerds.\n on(this._video, \"trackschange\", () => this._buildSettingsMenu());\n on(this._video, \"durationchange\", () => {\n this._seekInput.max = String(this._video.duration || 0);\n });\n\n // Play / pause\n on(this._playBtn, \"click\", (e) => { e.stopPropagation(); this._togglePlay(); });\n on(this._overlayBtn, \"click\", (e) => { e.stopPropagation(); this._togglePlay(); });\n\n // Seek bar — manual pointer handling so the click position maps\n // linearly across the FULL track width (native <input type=\"range\">\n // clamps the thumb center inside [thumbWidth/2, trackWidth -\n // thumbWidth/2], which causes a visible click-to-thumb offset at\n // the edges). The input is still used for keyboard accessibility\n // (arrow keys, home/end) via its 'input' event.\n on(this._seekInput, \"input\", () => {\n // Only accept keyboard-driven input events (not synthesized\n // from pointer, which we handle manually below).\n if (this._userSeeking) return;\n this._onSeekInput();\n });\n on(this._seekInput, \"change\", () => {\n if (this._userSeeking) return;\n this._onSeekCommit();\n });\n const seekBar = this.shadowRoot!.querySelector(\".avp-seek\") as HTMLElement;\n on(seekBar, \"pointerdown\", (e) => this._onSeekPointerDown(e as PointerEvent));\n on(seekBar, \"pointermove\", (e) => this._onSeekHover(e as PointerEvent));\n\n // Volume\n on(this._volumeBtn, \"click\", (e) => { e.stopPropagation(); this._toggleMute(); });\n on(this._volumeInput, \"input\", () => {\n const vol = Number(this._volumeInput.value);\n this._video.volume = vol;\n this._video.videoElement.volume = vol;\n this._video.muted = false;\n this._video.videoElement.muted = false;\n this._updateVolume();\n });\n\n // Settings\n on(this._settingsBtn, \"click\", (e) => { e.stopPropagation(); this._toggleSettings(); });\n on(this._settingsScrim, \"click\", () => this._closeSettings());\n\n // Fullscreen\n on(this._fullscreenBtn, \"click\", (e) => { e.stopPropagation(); this._toggleFullscreen(); });\n on(document, \"fullscreenchange\", () => this._updateFullscreenIcon());\n\n // Click / tap on video area — uses a delayed-tap pattern (like YouTube)\n // to distinguish single-tap (play/pause) from double-tap (seek ±10s).\n // On mouse: single click → play/pause, dblclick → fullscreen.\n // On touch: single tap (after 250ms) → play/pause, double tap → seek.\n const container = this.shadowRoot!.querySelector(\".avp\")!;\n on(container, \"click\", (e) => this._onContainerClick(e as MouseEvent));\n on(container, \"dblclick\", (e) => this._onContainerDblClick(e as MouseEvent));\n\n // Dismiss settings sheet when clicking outside it. The scrim handles\n // most of this (its own click handler calls _closeSettings), but we\n // also catch clicks outside the player element entirely.\n on(document, \"click\", (e) => {\n if (this._settingsOpen && !this.contains(e.target as Node)) {\n this._closeSettings();\n }\n });\n\n // Auto-hide controls\n on(container, \"pointermove\", () => this._showControls());\n on(container, \"pointerleave\", () => this._scheduleHide());\n\n // Touch gestures: hold for 2x speed\n on(container, \"pointerdown\", (e) => this._onPointerDown(e as PointerEvent));\n on(container, \"pointerup\", (e) => this._onPointerUp(e as PointerEvent));\n on(container, \"pointercancel\", () => this._cancelHold());\n\n // Drag-and-drop file input. Drop a video file onto the player area\n // and it loads + plays. Files of non-video types are rejected silently\n // (no MIME sniffing — we let probe() decide). The dragover listener\n // calls preventDefault so the drop event actually fires.\n on(container, \"dragenter\", (e) => {\n e.preventDefault();\n const dt = (e as DragEvent).dataTransfer;\n if (!dt || !Array.from(dt.types).includes(\"Files\")) return;\n (container as HTMLElement).classList.add(\"avp-dragover\");\n });\n on(container, \"dragover\", (e) => {\n e.preventDefault();\n const dt = (e as DragEvent).dataTransfer;\n if (dt) dt.dropEffect = \"copy\";\n });\n on(container, \"dragleave\", (e) => {\n // dragleave fires on every child — only clear when we leave the container.\n if ((e as DragEvent).target === container) {\n (container as HTMLElement).classList.remove(\"avp-dragover\");\n }\n });\n on(container, \"drop\", (e) => {\n e.preventDefault();\n (container as HTMLElement).classList.remove(\"avp-dragover\");\n const file = (e as DragEvent).dataTransfer?.files?.[0];\n if (!file) return;\n // Reuse the existing source-assignment path. play() errors are\n // reported via the normal error event; don't swallow here.\n (this._video as unknown as { source: unknown }).source = file;\n void this._video.play().catch(() => { /* error event already fired */ });\n });\n\n // Keyboard\n on(this, \"keydown\", (e) => this._onKeydown(e as KeyboardEvent));\n }\n\n // ── Lifecycle ──────────────────────────────────────────────────────────\n\n connectedCallback(): void {\n this._setState(\"idle\");\n // Attribute writes the Custom Elements spec forbids in constructors\n // — document.createElement rejects with \"The result must not have\n // attributes\" — deferred here. Surfaced by the Playwright\n // cross-browser tests.\n if (!this.hasAttribute(\"tabindex\")) {\n this.setAttribute(\"tabindex\", \"0\");\n }\n this._updateToolbarEmpty();\n }\n\n disconnectedCallback(): void {\n this._clearTimers();\n }\n\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n if (!this._video) return;\n // Player-only attributes — not forwarded to the inner <avbridge-video>.\n if ((PLAYER_ATTRIBUTES as readonly string[]).includes(name)) {\n if (name === \"show-fit\" && this._settingsOpen) {\n this._buildSettingsMenu();\n }\n return;\n }\n // Proxy everything else down.\n if (value == null) this._video.removeAttribute(name);\n else this._video.setAttribute(name, value);\n }\n\n // ── State management ───────────────────────────────────────────────────\n\n private _setState(state: PlayerState): void {\n this._state = state;\n this.dataset.state = state;\n\n // Update play/pause icons\n const playing = state === \"playing\" || state === \"buffering\";\n this._playBtn.innerHTML = playing ? ICON_PAUSE : ICON_PLAY;\n this._playBtn.ariaLabel = playing ? \"Pause\" : \"Play\";\n this._overlayBtn.innerHTML = ICON_PLAY;\n\n // Auto-hide logic\n if (playing) this._scheduleHide();\n else this._showControls();\n }\n\n // ── Controls: play/pause ───────────────────────────────────────────────\n\n private _togglePlay(): void {\n if (this._state === \"idle\" || this._state === \"error\") return;\n if (this._video.paused) void this._video.play();\n else this._video.pause();\n }\n\n // ── Controls: seek ─────────────────────────────────────────────────────\n\n private _onSeekInput(): void {\n const t = Number(this._seekInput.value);\n this._updateSeekVisuals(t);\n this._timeDisplay.textContent = `${formatTime(t)} / ${formatTime(this._video.duration)}`;\n }\n\n private _onSeekCommit(): void {\n const target = Number(this._seekInput.value);\n this._pendingSeekTarget = target;\n this._video.currentTime = target;\n this._userSeeking = false;\n }\n\n /** Linear click-to-time mapping across the full track width (no edge clamping). */\n private _timeFromSeekPointer(clientX: number): number {\n const seekBar = this.shadowRoot!.querySelector(\".avp-seek\") as HTMLElement;\n const rect = seekBar.getBoundingClientRect();\n const frac = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n return frac * (this._video.duration || 0);\n }\n\n private _onSeekPointerDown(e: PointerEvent): void {\n // Ignore synthetic clicks originating from the input's own handling\n if (e.button !== 0 && e.pointerType === \"mouse\") return;\n e.preventDefault();\n // Consume the event so host pages can layer the player inside a\n // swipe-driven UI (e.g. TikTok-style vertical pager) without the\n // pointerdown bubbling out and latching their gesture recognizer.\n // The seekbar's CSS sets `touch-action: none` to suppress native\n // browser pan/zoom — this complements that on the JS side, since\n // swipe handlers built on PointerEvents wouldn't honor touch-action.\n e.stopPropagation();\n this._userSeeking = true;\n const seekBar = this.shadowRoot!.querySelector(\".avp-seek\") as HTMLElement;\n seekBar.setPointerCapture(e.pointerId);\n seekBar.setAttribute(\"data-seeking\", \"\");\n\n // Two seek modes, picked by `(pointer: coarse)`:\n // - **fine** (mouse / trackpad / stylus): absolute mapping —\n // pointer X maps directly to seek time, thumb jumps under\n // cursor. Standard desktop YouTube behavior.\n // - **coarse** (touch): relative drag — initial tap doesn't move\n // the thumb; finger Δx maps to a Δt added to the time at\n // pointerdown. Standard YouTube-mobile behavior; matters because\n // finger positioning is too imprecise for absolute on a small bar.\n // Both modes commit live during drag (throttled to ~4 Hz so we don't\n // overwhelm the seek pipeline — every commit restarts the decoder\n // pump on canvas strategies) and once more on pointerup.\n const coarse = typeof matchMedia !== \"undefined\"\n && matchMedia(\"(pointer: coarse)\").matches;\n const startTime = coarse ? (this._video.currentTime || 0) : 0;\n const startClientX = e.clientX;\n let lastCommit = 0;\n\n const timeAt = (clientX: number): number => {\n if (coarse) {\n const rect = seekBar.getBoundingClientRect();\n const dx = clientX - startClientX;\n const dt = (dx / rect.width) * (this._video.duration || 0);\n return Math.max(0, Math.min(this._video.duration || 0, startTime + dt));\n }\n return this._timeFromSeekPointer(clientX);\n };\n\n const showTooltip = (t: number, clientX: number): void => {\n if (coarse) this._updateSeekTooltipAtTime(t);\n else this._updateSeekTooltip(clientX);\n };\n\n // Fine mode: tap commits immediately (thumb jumps under pointer).\n // Coarse mode: tap parks at the current time; only drag moves it.\n if (!coarse) {\n const initial = timeAt(e.clientX);\n this._seekInput.value = String(initial);\n this._onSeekInput();\n showTooltip(initial, e.clientX);\n this._onSeekCommit();\n this._userSeeking = true; // commit clears it; we're still seeking\n } else {\n showTooltip(startTime, e.clientX);\n }\n\n const onMove = (ev: PointerEvent) => {\n // Belt-and-suspenders for the host's swipe handler. Pointer capture\n // changes the *target* of subsequent pointermove events to seekBar,\n // but they still bubble through ancestors — a swipe listener\n // attached to document/window would otherwise see every drag tick.\n ev.stopPropagation();\n const t = timeAt(ev.clientX);\n this._seekInput.value = String(t);\n this._onSeekInput();\n showTooltip(t, ev.clientX);\n const now = performance.now();\n if (now - lastCommit > 250) {\n lastCommit = now;\n this._onSeekCommit();\n this._userSeeking = true;\n }\n };\n const onUp = (ev: PointerEvent) => {\n ev.stopPropagation();\n const t = timeAt(ev.clientX);\n this._seekInput.value = String(t);\n this._onSeekCommit();\n this._seekInput.focus();\n seekBar.removeAttribute(\"data-seeking\");\n seekBar.removeEventListener(\"pointermove\", onMove);\n seekBar.removeEventListener(\"pointerup\", onUp);\n seekBar.removeEventListener(\"pointercancel\", onUp);\n try { seekBar.releasePointerCapture(e.pointerId); } catch { /* ignore */ }\n };\n seekBar.addEventListener(\"pointermove\", onMove);\n seekBar.addEventListener(\"pointerup\", onUp);\n seekBar.addEventListener(\"pointercancel\", onUp);\n }\n\n private _onSeekHover(e: PointerEvent): void {\n this._updateSeekTooltip(e.clientX);\n }\n\n private _updateSeekTooltip(clientX: number): void {\n const rect = this._seekInput.getBoundingClientRect();\n const frac = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\n const t = frac * (this._video.duration || 0);\n this._seekTooltip.textContent = formatTime(t);\n this._seekTooltip.style.left = `${frac * 100}%`;\n }\n\n /** Position the tooltip over a specific time (vs. pointer X). Used by\n * relative-drag scrub on coarse pointers, where the displayed time\n * is decoupled from the finger position. */\n private _updateSeekTooltipAtTime(t: number): void {\n const dur = this._video.duration || 0;\n const frac = dur > 0 ? Math.max(0, Math.min(1, t / dur)) : 0;\n this._seekTooltip.textContent = formatTime(t);\n this._seekTooltip.style.left = `${frac * 100}%`;\n }\n\n private _updateSeekVisuals(t: number): void {\n const dur = this._video.duration || 0;\n const pct = dur > 0 ? (t / dur) * 100 : 0;\n this._seekProgress.style.width = `${pct}%`;\n // Thumb position uses a CSS calc that matches the native range input's\n // click-to-value math (thumb stays within track bounds). See player-styles.ts.\n this._seekThumb.style.setProperty(\"--pct\", String(pct));\n }\n\n // ── Controls: time ─────────────────────────────────────────────────────\n\n private _updateTime(): void {\n if (this._userSeeking) return;\n const t = this._video.currentTime;\n const d = this._video.duration;\n // While a committed seek is still settling, keep the thumb at the\n // target so it doesn't snap back to the pre-seek position. Clear once\n // currentTime has landed within 0.5s of the target.\n if (this._pendingSeekTarget !== null) {\n if (Math.abs(t - this._pendingSeekTarget) < 0.5) {\n this._pendingSeekTarget = null;\n } else {\n this._timeDisplay.textContent = `${formatTime(this._pendingSeekTarget)} / ${formatTime(d)}`;\n this._updateBuffered();\n return;\n }\n }\n this._seekInput.value = String(t);\n this._updateSeekVisuals(t);\n this._timeDisplay.textContent = `${formatTime(t)} / ${formatTime(d)}`;\n this._updateBuffered();\n }\n\n /**\n * Render every buffered range as its own segment so gaps (common on MSE\n * after seeks) are visible. Not gated by `_userSeeking` — ranges should\n * keep updating while the user scrubs, and runs cheaply on `progress`.\n */\n private _updateBuffered(): void {\n const d = this._video.duration;\n if (!(d > 0)) return;\n let buf: TimeRanges;\n try { buf = this._video.buffered; } catch { return; }\n const count = buf ? buf.length : 0;\n const host = this._seekBuffered;\n // Reconcile child count. Segment divs are styled via .avp-seek-buffered-range.\n while (host.childElementCount > count) host.lastElementChild!.remove();\n while (host.childElementCount < count) {\n const seg = document.createElement(\"div\");\n seg.className = \"avp-seek-buffered-range\";\n host.appendChild(seg);\n }\n for (let i = 0; i < count; i++) {\n let start: number; let end: number;\n try { start = buf.start(i); end = buf.end(i); } catch { continue; }\n const s = Math.max(0, start);\n const e = Math.min(d, end);\n if (e <= s) continue;\n const seg = host.children[i] as HTMLElement;\n seg.style.left = `${(s / d) * 100}%`;\n seg.style.width = `${((e - s) / d) * 100}%`;\n }\n }\n\n // ── Controls: volume ───────────────────────────────────────────────────\n\n private _toggleMute(): void {\n // Set both the element attribute AND the inner <video> property directly,\n // because avbridge-video's attribute-based muted toggling can diverge\n // from the <video> property on a running element.\n const newMuted = !this._video.muted;\n this._video.muted = newMuted;\n this._video.videoElement.muted = newMuted;\n this._updateVolume();\n }\n\n private _updateVolume(): void {\n const muted = this._video.muted || this._video.videoElement.muted || this._video.volume === 0;\n this._volumeBtn.innerHTML = muted ? ICON_VOLUME_OFF : ICON_VOLUME_UP;\n this._volumeInput.value = muted ? \"0\" : String(this._video.volume);\n }\n\n // ── Controls: settings ─────────────────────────────────────────────────\n\n private _toggleSettings(): void {\n this._settingsOpen = !this._settingsOpen;\n this._settingsMenu.classList.toggle(\"open\", this._settingsOpen);\n this._settingsScrim.classList.toggle(\"open\", this._settingsOpen);\n if (this._settingsOpen) {\n this._fitSettingsToPlayer();\n this._showControls();\n }\n }\n\n private _fitSettingsToPlayer(): void {\n const container = this.shadowRoot?.querySelector(\".avp\") as HTMLElement | null;\n if (!container) return;\n const rect = container.getBoundingClientRect();\n // Bottom sheet can use up to 70% of the player height, leaving room\n // to see the video behind the scrim. Floor at 120px so it's always\n // usable.\n const maxH = Math.max(120, Math.floor(rect.height * 0.7));\n this._settingsMenu.style.maxHeight = `${maxH}px`;\n }\n\n private _closeSettings(): void {\n this._settingsOpen = false;\n this._settingsMenu.classList.remove(\"open\");\n this._settingsScrim.classList.remove(\"open\");\n }\n\n private _buildSettingsMenu(): void {\n const sections: string[] = [];\n\n // Helper: a row with an invisible native <select> layered on top of\n // a styled label+value. Tapping opens the OS picker (escapes the\n // shadow DOM — intentional for small players). The visible label\n // updates on change.\n const selectRow = (label: string, currentValue: string, options: string, selectAttrs: string): string =>\n `<div class=\"avp-settings-section\">` +\n `<div class=\"avp-settings-header\">` +\n `<span class=\"avp-settings-header-label\">${label}</span>` +\n `<span class=\"avp-settings-header-value\">${currentValue}</span>` +\n `<select class=\"avp-settings-select\" ${selectAttrs}>${options}</select>` +\n `</div>` +\n `</div>`;\n\n // Speed\n const currentRate = this._video.playbackRate ?? 1;\n const speedValue = Math.abs(currentRate - 1) < 0.01 ? \"Normal\" : `${currentRate}x`;\n let speedOpts = \"\";\n for (const spd of PLAYBACK_SPEEDS) {\n const sel = Math.abs(spd - currentRate) < 0.01 ? \" selected\" : \"\";\n const label = spd === 1 ? \"Normal\" : `${spd}x`;\n speedOpts += `<option value=\"${spd}\"${sel}>${label}</option>`;\n }\n sections.push(selectRow(\"Speed\", speedValue, speedOpts, `data-action=\"speed\"`));\n\n // Audio tracks\n const audios = this._video.audioTracks ?? [];\n if (audios.length > 1) {\n const activeAudioId = this._activeAudioTrackId ?? audios[0]?.id;\n const activeAudio = audios.find((t: { id: number }) => t.id === activeAudioId) ?? audios[0];\n const audioValue = activeAudio?.language ?? `Track ${activeAudio?.id ?? 1}`;\n let audioOpts = \"\";\n for (const t of audios) {\n const sel = t.id === activeAudioId ? \" selected\" : \"\";\n audioOpts += `<option value=\"${t.id}\"${sel}>${t.language ?? `Track ${t.id}`}</option>`;\n }\n sections.push(selectRow(\"Audio\", audioValue, audioOpts, `data-action=\"audio\"`));\n }\n\n // Subtitle tracks\n const subs = this._video.subtitleTracks ?? [];\n if (subs.length > 0) {\n const activeSubId = this._activeSubtitleTrackId;\n const activeSub = activeSubId != null ? subs.find((t: { id: number }) => t.id === activeSubId) : null;\n const subValue = activeSub ? (activeSub.language ?? `Track ${activeSub.id}`) : \"Off\";\n let subOpts = `<option value=\"-1\"${activeSubId == null ? \" selected\" : \"\"}>Off</option>`;\n for (const t of subs) {\n const sel = t.id === activeSubId ? \" selected\" : \"\";\n subOpts += `<option value=\"${t.id}\"${sel}>${t.language ?? `Track ${t.id}`}</option>`;\n }\n sections.push(selectRow(\"Subtitles\", subValue, subOpts, `data-action=\"subtitle\"`));\n }\n\n // Fit mode — opt-in via the `show-fit` attribute\n if (this.hasAttribute(\"show-fit\")) {\n const currentFit = (this._video.fit ?? \"contain\") as FitMode;\n const fitValue = currentFit[0].toUpperCase() + currentFit.slice(1);\n let fitOpts = \"\";\n for (const mode of FIT_MODES) {\n const sel = mode === currentFit ? \" selected\" : \"\";\n const label = mode[0].toUpperCase() + mode.slice(1);\n fitOpts += `<option value=\"${mode}\"${sel}>${label}</option>`;\n }\n sections.push(selectRow(\"Fit\", fitValue, fitOpts, `data-action=\"fit\"`));\n }\n\n // Consumer-added sections\n for (const cfg of this._customSections) {\n const activeItem = cfg.items.find((i) => i.active);\n let customOpts = \"\";\n for (const item of cfg.items) {\n const sel = item.active ? \" selected\" : \"\";\n customOpts += `<option value=\"${item.id}\"${sel}>${item.label}</option>`;\n }\n sections.push(selectRow(cfg.label, activeItem?.label ?? \"\", customOpts, `data-action=\"custom\" data-custom-id=\"${cfg.id}\"`));\n }\n\n // Stats for nerds — toggle row (no select)\n sections.push(\n `<div class=\"avp-settings-section\">` +\n `<div class=\"avp-settings-header avp-settings-toggle\" data-stats>` +\n `<span class=\"avp-settings-header-label\">Stats for Nerds</span>` +\n `</div>` +\n `</div>`,\n );\n\n // Rebuild sheet content (preserve the handle).\n const handle = this._settingsMenu.querySelector(\".avp-settings-handle\");\n this._settingsMenu.innerHTML = \"\";\n if (handle) this._settingsMenu.appendChild(handle);\n else this._settingsMenu.insertAdjacentHTML(\"afterbegin\", `<div class=\"avp-settings-handle\"></div>`);\n this._settingsMenu.insertAdjacentHTML(\"beforeend\", sections.join(\"\"));\n\n // ── <select> change handlers ──\n for (const sel of this._settingsMenu.querySelectorAll<HTMLSelectElement>(\".avp-settings-select\")) {\n sel.addEventListener(\"change\", (e) => {\n e.stopPropagation();\n const action = sel.dataset.action;\n const val = sel.value;\n switch (action) {\n case \"speed\":\n this._video.playbackRate = Number(val);\n break;\n case \"audio\":\n this._activeAudioTrackId = Number(val);\n void this._video.setAudioTrack(Number(val));\n break;\n case \"subtitle\": {\n const subId = Number(val);\n this._activeSubtitleTrackId = subId >= 0 ? subId : null;\n void this._video.setSubtitleTrack(subId >= 0 ? subId : null);\n break;\n }\n case \"fit\":\n this.setAttribute(\"fit\", val);\n break;\n case \"custom\": {\n const cfgId = sel.dataset.customId!;\n const cfg = this._customSections.find((s) => s.id === cfgId);\n cfg?.onSelect(val);\n break;\n }\n }\n this._buildSettingsMenu();\n });\n }\n\n // Stats toggle (no select — just a clickable row)\n const statsRow = this._settingsMenu.querySelector(\"[data-stats]\");\n if (statsRow) {\n statsRow.addEventListener(\"click\", (e) => {\n e.stopPropagation();\n this._toggleStats();\n this._closeSettings();\n });\n }\n }\n\n // ── Stats for nerds ────────────────────────────────────────────────────\n\n private _statsPrev: { ts: number; rt: Record<string, unknown> } | null = null;\n\n private _toggleStats(): void {\n this._statsOpen = !this._statsOpen;\n this._statsEl.classList.toggle(\"open\", this._statsOpen);\n if (this._statsOpen) {\n this._statsPrev = null; // reset delta baseline\n this._updateStats();\n this._statsInterval = setInterval(() => this._updateStats(), 1000);\n } else {\n if (this._statsInterval) { clearInterval(this._statsInterval); this._statsInterval = null; }\n }\n }\n\n private _updateStats(): void {\n const d = this._video.getDiagnostics() as Record<string, unknown> | null;\n if (!d) { this._statsEl.textContent = \"No diagnostics\"; return; }\n const rt = (d.runtime ?? {}) as Record<string, unknown>;\n const now = performance.now();\n const prev = this._statsPrev;\n const dtSec = prev ? Math.max(0.001, (now - prev.ts) / 1000) : 0;\n const delta = (key: string): number | null => {\n if (!prev) return null;\n const a = rt[key];\n const b = prev.rt[key];\n if (typeof a === \"number\" && typeof b === \"number\") return a - b;\n return null;\n };\n const rate = (key: string): number | null => {\n const d_ = delta(key);\n return d_ != null ? d_ / dtSec : null;\n };\n const fmt = (n: number | null, digits = 1) => (n == null ? \"?\" : n.toFixed(digits));\n\n const sourceFps = (typeof rt.sourceFps === \"number\" ? rt.sourceFps : d.fps) as number | undefined;\n const lines: string[] = [];\n\n // ── Identity ──────────────────────────────────────────────────────\n lines.push(`Container: ${d.container ?? \"?\"} Strategy: ${d.strategy ?? \"?\"} (${d.strategyClass ?? \"?\"})`);\n lines.push(`Video: ${d.videoCodec ?? \"?\"} ${d.width ?? \"?\"}×${d.height ?? \"?\"}${sourceFps ? ` @ ${sourceFps.toFixed(3)} fps` : \"\"}`);\n lines.push(`Audio: ${d.audioCodec ?? \"none\"} Transport: ${d.transport ?? \"?\"}${d.rangeSupported === true ? \"/range\" : \"\"}`);\n lines.push(`Duration: ${typeof d.duration === \"number\" ? d.duration.toFixed(1) + \"s\" : \"?\"} Playback rate: ${this._video.playbackRate.toFixed(2)}x`);\n\n // ── Realtime rates (deltas per second) ─────────────────────────────\n if (rt.videoFramesDecoded != null) {\n const decFps = rate(\"videoFramesDecoded\");\n const paintFps = rate(\"framesPainted\");\n const dropLateFps = rate(\"framesDroppedLate\");\n const dropOverflowFps = rate(\"framesDroppedOverflow\");\n const pct = sourceFps && decFps != null ? ` (${((decFps / sourceFps) * 100).toFixed(0)}% of realtime)` : \"\";\n lines.push(`Decode fps: ${fmt(decFps)}${pct} Paint fps: ${fmt(paintFps)}`);\n lines.push(`Drops/sec: late=${fmt(dropLateFps)} overflow=${fmt(dropOverflowFps)} Totals: painted=${rt.framesPainted} dropped=${rt.framesDroppedLate}`);\n }\n\n // ── Decode-time breakdown (wall ms spent inside libav) ────────────\n if (typeof rt.videoDecodeMsTotal === \"number\") {\n const msDelta = delta(\"videoDecodeMsTotal\");\n const batchesDelta = delta(\"videoDecodeBatches\");\n const perBatch = msDelta != null && batchesDelta && batchesDelta > 0 ? msDelta / batchesDelta : null;\n const share = msDelta != null && dtSec > 0 ? (msDelta / (dtSec * 1000)) * 100 : null;\n lines.push(\n `Video decode: ${fmt(perBatch)}ms/batch avg ${fmt(share)}% of wall slowest=${fmt(rt.slowestVideoBatchMs as number)}ms`,\n );\n }\n if (typeof rt.audioDecodeMsTotal === \"number\") {\n const msDelta = delta(\"audioDecodeMsTotal\");\n const share = msDelta != null && dtSec > 0 ? (msDelta / (dtSec * 1000)) * 100 : null;\n lines.push(`Audio decode: ${fmt(share)}% of wall`);\n }\n if (typeof rt.pumpThrottleMsTotal === \"number\") {\n const msDelta = delta(\"pumpThrottleMsTotal\");\n const share = msDelta != null && dtSec > 0 ? (msDelta / (dtSec * 1000)) * 100 : null;\n lines.push(`Producer throttled: ${fmt(share)}% of wall`);\n }\n\n // ── Queue health ──────────────────────────────────────────────────\n if (rt.queueDepth != null) {\n lines.push(\n `Queue: depth=${rt.queueDepth} span=${fmt(rt.queueSpanMs as number)}ms ` +\n `head=${fmt(rt.queueHeadMs as number)}ms tail=${fmt(rt.queueTailMs as number)}ms`,\n );\n }\n if (typeof rt.newestVideoPtsMs === \"number\") {\n lines.push(`Newest decoded PTS: ${(rt.newestVideoPtsMs / 1000).toFixed(2)}s`);\n }\n\n // ── Audio ─────────────────────────────────────────────────────────\n if (rt.audioState != null) {\n lines.push(`Audio state: ${rt.audioState} bufferAhead=${fmt(rt.bufferAhead as number, 2)}s clock=${rt.clockMode ?? \"?\"}`);\n }\n\n // ── BSF + warnings ────────────────────────────────────────────────\n if (typeof rt.ptsRegressions === \"number\" && rt.ptsRegressions > 0) {\n lines.push(`PTS REGRESSIONS: ${rt.ptsRegressions} (worst=${fmt(rt.worstPtsRegressionMs as number)}ms) — decoder emitting out of order`);\n }\n if (rt.bsfApplied && (rt.bsfApplied as string[]).length > 0) lines.push(`BSF active: ${(rt.bsfApplied as string[]).join(\", \")}`);\n if (rt.bsfMissing && (rt.bsfMissing as string[]).length > 0) {\n lines.push(`BSF MISSING: ${(rt.bsfMissing as string[]).join(\", \")} (rebuild libav with avbsf)`);\n }\n\n if (d.probedBy) lines.push(`Probed by: ${d.probedBy}`);\n\n this._statsEl.textContent = lines.join(\"\\n\");\n this._statsPrev = { ts: now, rt: { ...rt } };\n }\n\n // ── Controls: fullscreen ───────────────────────────────────────────────\n\n private _toggleFullscreen(): void {\n if (document.fullscreenElement === this) {\n void document.exitFullscreen();\n } else {\n void this.requestFullscreen();\n }\n }\n\n private _updateFullscreenIcon(): void {\n const fs = document.fullscreenElement === this;\n this._fullscreenBtn.innerHTML = fs ? ICON_FULLSCREEN_EXIT : ICON_FULLSCREEN;\n }\n\n // ── Controls: auto-hide ────────────────────────────────────────────────\n\n /**\n * Reveal the auto-hiding chrome (top toolbar + bottom controls) and\n * re-start the auto-hide timer. Call this from app-level code to\n * briefly surface the player UI — e.g. to confirm \"you just swiped to\n * this video\" in a carousel, or to flash the title on focus change.\n *\n * @param durationMs How long the chrome stays visible before fading.\n * Defaults to the player's normal 3 s auto-hide.\n * Pointer movement or any other interaction resets\n * the timer, so a user hovering during the flash\n * sees no flicker.\n */\n showControls(durationMs?: number): void {\n this.removeAttribute(\"data-controls-hidden\");\n this._toolbarTop.setAttribute(\"data-visible\", \"true\");\n this._scheduleHide(durationMs);\n }\n\n private _showControls(): void {\n this.showControls();\n }\n\n private _scheduleHide(durationMs?: number): void {\n const ms = durationMs ?? this._getControlsTimeout();\n if (this._controlsTimer) clearTimeout(this._controlsTimer);\n if (this._state !== \"playing\" && this._state !== \"buffering\") return;\n if (this._settingsOpen) return;\n // A timeout of 0 or negative means \"never hide\" (controls always visible).\n if (ms <= 0) return;\n this._controlsTimer = setTimeout(() => {\n if (this._state === \"playing\") {\n this.setAttribute(\"data-controls-hidden\", \"\");\n this._toolbarTop.setAttribute(\"data-visible\", \"false\");\n }\n }, ms);\n }\n\n /** Read the controls-timeout attribute. 0 or negative = never hide.\n * Unset = default 3000ms. */\n private _getControlsTimeout(): number {\n const attr = this.getAttribute(\"controls-timeout\");\n if (attr == null) return DEFAULT_CONTROLS_HIDE_MS;\n const n = Number(attr);\n return Number.isFinite(n) ? n : DEFAULT_CONTROLS_HIDE_MS;\n }\n\n // Strategy is visible in Stats for Nerds, no badge in controls bar.\n\n // ── Click / tap handling (YouTube delayed-tap pattern) ──────────────────\n //\n // Problem: single click toggles play, double click toggles fullscreen (or\n // seek on touch). Firing play on the first click causes a play→pause\n // glitch on every double-click. YouTube solves this by delaying the\n // single-click action by ~250ms; if a second click arrives in that window\n // it's treated as a double-click and the single-click action is cancelled.\n\n /** Track whether the last interaction was touch so click handler can skip. */\n private _lastPointerTypeWasTouch = false;\n /** True for ~50ms after a touch double-tap was handled, so the\n * synthetic dblclick from the browser doesn't also fire fullscreen. */\n private _touchDoubleTapConsumed = false;\n\n /** True if the event's composed path passes through consumer-slotted\n * content (toolbar or content-overlay). Slotted content lives in the\n * light DOM so `.closest(\".avp-toolbar-top\")` on the event target won't\n * find the shadow-DOM wrapper — `composedPath()` does. */\n private _isSlottedContentEvent(e: Event): boolean {\n for (const node of e.composedPath()) {\n if (node instanceof HTMLElement &&\n (node.classList.contains(\"avp-toolbar-top\") ||\n node.classList.contains(\"avp-content-overlay\"))) return true;\n }\n return false;\n }\n\n private _onContainerClick(e: MouseEvent): void {\n // Ignore clicks on controls and slotted content\n if ((e.target as HTMLElement).closest?.(\".avp-controls, .avp-settings, .avp-overlay-btn\")) return;\n if (this._isSlottedContentEvent(e)) return;\n\n // If the bottom sheet is open, any click outside it dismisses\n // instead of toggling play/pause.\n if (this._settingsOpen) {\n this._closeSettings();\n return;\n }\n\n // Touch taps are handled by _onPointerUp (show/hide controls + double-tap).\n // The browser fires a synthetic click after touchend — skip it.\n if (this._lastPointerTypeWasTouch) {\n this._lastPointerTypeWasTouch = false;\n return;\n }\n\n // Mouse: delay single-click to let dblclick cancel it\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n this._tapTimer = setTimeout(() => {\n this._tapTimer = null;\n this._togglePlay();\n }, 250);\n }\n\n private _onContainerDblClick(e: MouseEvent): void {\n if ((e.target as HTMLElement).closest?.(\".avp-controls, .avp-settings\")) return;\n if (this._isSlottedContentEvent(e)) return;\n // On touch devices, the browser synthesizes a dblclick after two\n // rapid taps. But we already handled the double-tap in _onPointerUp\n // (which does ff/rw on sides, fullscreen in center). Skip the\n // synthetic dblclick so both don't fire.\n if (this._touchDoubleTapConsumed) return;\n // Cancel the pending single-click play/pause\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n this._toggleFullscreen();\n }\n\n // ── Touch gestures ─────────────────────────────────────────────────────\n\n private _onPointerDown(e: PointerEvent): void {\n if (e.pointerType !== \"touch\") return;\n // Tap-and-hold for 2x speed\n this._holdTimer = setTimeout(() => {\n this._holdSpeedActive = true;\n this._savedPlaybackRate = this._video.playbackRate;\n this._video.playbackRate = 2;\n this._speedIndicator.classList.add(\"active\");\n }, 500);\n }\n\n private _onPointerUp(e: PointerEvent): void {\n this._cancelHold();\n if (e.pointerType !== \"touch\") return;\n this._lastPointerTypeWasTouch = true;\n\n // Ignore touches on controls — buttons have their own handlers\n if ((e.target as HTMLElement).closest?.(\".avp-controls, .avp-settings, .avp-overlay-btn\")) return;\n if (this._isSlottedContentEvent(e)) return;\n\n // If the bottom sheet is open, dismiss it on any touch outside.\n if (this._settingsOpen) {\n this._closeSettings();\n return;\n }\n\n // Double-tap detection\n const now = Date.now();\n if (now - this._lastTapTime < 300) {\n // Double tap — cancel pending single tap and seek\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n const rect = this.getBoundingClientRect();\n const x = e.clientX - rect.left;\n if (x < rect.width / 3) {\n this._doDoubleTap(\"left\");\n } else if (x > (rect.width * 2) / 3) {\n this._doDoubleTap(\"right\");\n } else {\n this._toggleFullscreen();\n }\n // Prevent the synthetic dblclick (fired ~50ms later by the\n // browser) from also toggling fullscreen.\n this._touchDoubleTapConsumed = true;\n setTimeout(() => { this._touchDoubleTapConsumed = false; }, 100);\n this._lastTapTime = 0;\n return;\n }\n // Single tap on touch — toggle controls visibility (NOT play/pause).\n // YouTube mobile: tap shows/hides controls. Play button toggles playback.\n this._lastTapTime = now;\n this._tapTimer = setTimeout(() => {\n this._tapTimer = null;\n if (this.hasAttribute(\"data-controls-hidden\")) {\n this._showControls();\n } else {\n this.setAttribute(\"data-controls-hidden\", \"\");\n }\n }, 250);\n }\n\n private _cancelHold(): void {\n if (this._holdTimer) {\n clearTimeout(this._holdTimer);\n this._holdTimer = null;\n }\n if (this._holdSpeedActive) {\n this._holdSpeedActive = false;\n this._video.playbackRate = this._savedPlaybackRate;\n this._speedIndicator.classList.remove(\"active\");\n }\n }\n\n private _doDoubleTap(side: \"left\" | \"right\"): void {\n const ripple = side === \"left\" ? this._rippleLeft : this._rippleRight;\n ripple.classList.remove(\"active\");\n // Force reflow to restart animation\n void ripple.offsetWidth;\n ripple.classList.add(\"active\");\n\n const delta = side === \"left\" ? -10 : 10;\n this._video.currentTime = Math.max(0, this._video.currentTime + delta);\n }\n\n // ── Keyboard shortcuts ─────────────────────────────────────────────────\n\n /** Duration of one frame in seconds, derived from diagnostics fps or\n * a 30fps default. Used for frame-step shortcuts (`,` / `.`). */\n private _frameDuration(): number {\n const diag = this._video.getDiagnostics() as { fps?: number } | null;\n const fps = diag?.fps && diag.fps > 0 ? diag.fps : 30;\n return 1 / fps;\n }\n\n private _onKeydown(e: KeyboardEvent): void {\n // Don't intercept if the user is typing in an input\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;\n\n switch (e.key) {\n case \" \":\n case \"k\":\n e.preventDefault();\n this._togglePlay();\n break;\n case \"f\":\n e.preventDefault();\n this._toggleFullscreen();\n break;\n case \"m\":\n e.preventDefault();\n this._toggleMute();\n break;\n case \"ArrowLeft\":\n case \"j\":\n e.preventDefault();\n this._video.currentTime = Math.max(0, this._video.currentTime - 5);\n break;\n case \"ArrowRight\":\n case \"l\":\n e.preventDefault();\n this._video.currentTime = Math.min(this._video.duration || 0, this._video.currentTime + 5);\n break;\n case \"ArrowUp\":\n e.preventDefault();\n this._video.volume = Math.min(1, this._video.volume + 0.1);\n break;\n case \"ArrowDown\":\n e.preventDefault();\n this._video.volume = Math.max(0, this._video.volume - 0.1);\n break;\n case \">\":\n e.preventDefault();\n this._video.playbackRate = Math.min(2, this._video.playbackRate + 0.25);\n this._buildSettingsMenu();\n break;\n case \"<\":\n e.preventDefault();\n this._video.playbackRate = Math.max(0.25, this._video.playbackRate - 0.25);\n this._buildSettingsMenu();\n break;\n case \",\":\n // Frame-back (YouTube-style: , while paused steps back one frame)\n e.preventDefault();\n if (!this._video.paused) this._video.pause();\n this._video.currentTime = Math.max(0, this._video.currentTime - this._frameDuration());\n break;\n case \".\":\n // Frame-forward (YouTube-style: . while paused steps forward one frame)\n e.preventDefault();\n if (!this._video.paused) this._video.pause();\n this._video.currentTime = Math.min(\n this._video.duration || 0,\n this._video.currentTime + this._frameDuration(),\n );\n break;\n case \"Escape\":\n if (this._settingsOpen) {\n e.preventDefault();\n this._closeSettings();\n }\n break;\n }\n this._showControls();\n }\n\n // ── Cleanup ────────────────────────────────────────────────────────────\n\n private _clearTimers(): void {\n if (this._controlsTimer) { clearTimeout(this._controlsTimer); this._controlsTimer = null; }\n if (this._holdTimer) { clearTimeout(this._holdTimer); this._holdTimer = null; }\n if (this._tapTimer) { clearTimeout(this._tapTimer); this._tapTimer = null; }\n if (this._statsInterval) { clearInterval(this._statsInterval); this._statsInterval = null; }\n }\n\n // ── Property proxies ───────────────────────────────────────────────────\n\n get src(): string { return this._video.src ?? \"\"; }\n set src(v: string) { this._video.src = v; }\n\n get source(): unknown { return this._video.source; }\n set source(v: unknown) { (this._video as unknown as { source: unknown }).source = v; }\n\n get currentTime(): number { return this._video.currentTime; }\n set currentTime(v: number) { this._video.currentTime = v; }\n\n get duration(): number { return this._video.duration; }\n get paused(): boolean { return this._video.paused; }\n get ended(): boolean { return this._video.ended; }\n get readyState(): number { return this._video.readyState; }\n\n get volume(): number { return this._video.volume; }\n set volume(v: number) { this._video.volume = v; this._updateVolume(); }\n\n get muted(): boolean { return this._video.muted; }\n set muted(v: boolean) { this._video.muted = v; this._updateVolume(); }\n\n get playbackRate(): number { return this._video.playbackRate; }\n set playbackRate(v: number) { this._video.playbackRate = v; }\n\n get autoplay(): boolean { return this._video.autoplay; }\n set autoplay(v: boolean) { this._video.autoplay = v; }\n\n get loop(): boolean { return this._video.loop; }\n set loop(v: boolean) { this._video.loop = v; }\n\n get videoWidth(): number { return this._video.videoWidth; }\n get videoHeight(): number { return this._video.videoHeight; }\n get buffered(): TimeRanges { return this._video.buffered; }\n get played(): TimeRanges { return this._video.played; }\n get seekable(): TimeRanges { return this._video.seekable; }\n\n get strategy(): string | undefined { return this._video.strategy ?? undefined; }\n get strategyClass(): string | undefined { return this._video.strategyClass ?? undefined; }\n get audioTracks(): unknown[] { return this._video.audioTracks ?? []; }\n get subtitleTracks(): unknown[] { return this._video.subtitleTracks ?? []; }\n\n /**\n * External subtitle files to attach when the source loads. Forwarded\n * to the inner <avbridge-video>. Takes effect on next bootstrap.\n */\n get subtitles(): unknown {\n return (this._video as unknown as { subtitles: unknown }).subtitles;\n }\n set subtitles(value: unknown) {\n (this._video as unknown as { subtitles: unknown }).subtitles = value;\n }\n\n /** Attach a subtitle track to the current playback without a reload. */\n async addSubtitle(subtitle: { url: string; language?: string; format?: \"vtt\" | \"srt\" }): Promise<void> {\n return (this._video as unknown as { addSubtitle: (s: unknown) => Promise<void> }).addSubtitle(subtitle);\n }\n get player(): unknown { return this._video.player; }\n get videoElement(): HTMLVideoElement { return this._video.videoElement; }\n\n // ── Method proxies ─────────────────────────────────────────────────────\n\n async play(): Promise<void> { return this._video.play(); }\n pause(): void { this._video.pause(); }\n async load(): Promise<void> { return this._video.load(); }\n async destroy(): Promise<void> {\n this._clearTimers();\n for (const fn of this._eventCleanup) fn();\n this._eventCleanup = [];\n return this._video.destroy();\n }\n async setAudioTrack(id: number): Promise<void> { return this._video.setAudioTrack(id); }\n\n addSettingsSection(config: SettingsSectionConfig): void {\n this._customSections = this._customSections.filter((s) => s.id !== config.id);\n this._customSections.push(config);\n this._buildSettingsMenu();\n }\n\n removeSettingsSection(id: string): void {\n this._customSections = this._customSections.filter((s) => s.id !== id);\n this._buildSettingsMenu();\n }\n async setSubtitleTrack(id: number | null): Promise<void> { return this._video.setSubtitleTrack(id); }\n getDiagnostics(): unknown { return this._video.getDiagnostics(); }\n canPlayType(mime: string): string { return this._video.canPlayType(mime); }\n\n // ── Typed addEventListener / removeEventListener overloads ────────────\n // Forwarded events from the inner <avbridge-video> preserve their\n // typed CustomEvent detail. Standard HTMLMediaElement events retain\n // their native typing via HTMLElementEventMap.\n\n override addEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void;\n override addEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): void {\n super.addEventListener(type, listener, options);\n }\n\n override removeEventListener<K extends keyof AvbridgeVideoElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: AvbridgeVideoElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener<K extends keyof HTMLElementEventMap>(\n type: K,\n listener: (this: AvbridgePlayerElement, ev: HTMLElementEventMap[K]) => unknown,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void;\n override removeEventListener(\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ): void {\n super.removeEventListener(type, listener, options);\n }\n}\n","/**\n * Registration entry point for `<avbridge-player>`.\n *\n * Import `\"avbridge/player\"` to register the element. This also registers\n * `<avbridge-video>` (which `<avbridge-player>` wraps internally).\n *\n * Separate from `\"avbridge/element\"` so consumers who only need the bare\n * `<avbridge-video>` primitive don't pay for the controls CSS/JS.\n */\n\nimport { AvbridgePlayerElement } from \"./element/avbridge-player.js\";\n\nexport { AvbridgePlayerElement } from \"./element/avbridge-player.js\";\nexport type { AvbridgeVideoElement } from \"./element/avbridge-video.js\";\n\nif (!customElements.get(\"avbridge-player\")) {\n customElements.define(\"avbridge-player\", AvbridgePlayerElement);\n}\n"]}