@rubytech/taskmaster 1.25.1 → 1.26.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.
@@ -1 +0,0 @@
1
- {"version":3,"mappings":"slEAKA,MAAMA,GAAE,WAAWC,GAAED,GAAE,aAAsBA,GAAE,WAAX,QAAqBA,GAAE,SAAS,eAAe,uBAAuB,SAAS,WAAW,YAAY,cAAc,UAAUE,GAAE,OAAM,EAAGC,GAAE,IAAI,QAAO,IAAAC,GAAC,KAAO,CAAC,YAAY,EAAEH,EAAEE,EAAE,CAAC,GAAG,KAAK,aAAa,GAAGA,IAAID,GAAE,MAAM,MAAM,mEAAmE,EAAE,KAAK,QAAQ,EAAE,KAAK,EAAED,CAAC,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,MAAMC,EAAE,KAAK,EAAE,GAAGD,IAAY,IAAT,OAAW,CAAC,MAAMA,EAAWC,IAAT,QAAgBA,EAAE,SAAN,EAAaD,IAAI,EAAEE,GAAE,IAAID,CAAC,GAAY,IAAT,UAAc,KAAK,EAAE,EAAE,IAAI,eAAe,YAAY,KAAK,OAAO,EAAED,GAAGE,GAAE,IAAID,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,OAAO,KAAK,OAAO,CAAC,EAAC,MAAMG,GAAEL,GAAG,IAAIM,GAAY,OAAON,GAAjB,SAAmBA,EAAEA,EAAE,GAAG,OAAOE,EAAC,EAAEK,GAAE,CAACP,KAAKC,IAAI,CAAC,MAAME,EAAMH,EAAE,SAAN,EAAaA,EAAE,CAAC,EAAEC,EAAE,OAAO,CAACA,EAAE,EAAE,IAAIA,GAAGD,GAAG,CAAC,GAAQA,EAAE,eAAP,GAAoB,OAAOA,EAAE,QAAQ,GAAa,OAAOA,GAAjB,SAAmB,OAAOA,EAAE,MAAM,MAAM,mEAAmEA,EAAE,sFAAsF,CAAC,GAAG,CAAC,EAAEA,EAAE,EAAE,CAAC,EAAEA,EAAE,CAAC,CAAC,EAAE,OAAO,IAAIM,GAAEH,EAAEH,EAAEE,EAAC,CAAC,EAAEM,GAAE,CAACN,EAAEC,IAAI,CAAC,GAAGF,GAAEC,EAAE,mBAAmBC,EAAE,IAAIH,GAAGA,aAAa,cAAcA,EAAEA,EAAE,UAAU,MAAO,WAAUC,KAAKE,EAAE,CAAC,MAAMA,EAAE,SAAS,cAAc,OAAO,EAAEG,EAAEN,GAAE,SAAkBM,IAAT,QAAYH,EAAE,aAAa,QAAQG,CAAC,EAAEH,EAAE,YAAYF,EAAE,QAAQC,EAAE,YAAYC,CAAC,CAAC,CAAC,EAAEM,GAAER,GAAED,GAAGA,EAAEA,GAAGA,aAAa,eAAe,GAAG,CAAC,IAAIC,EAAE,GAAG,UAAUC,KAAK,EAAE,SAASD,GAAGC,EAAE,QAAQ,OAAOG,GAAEJ,CAAC,CAAC,GAAGD,CAAC,EAAEA,ECApzC,KAAK,CAAC,GAAGO,GAAE,eAAeN,GAAE,yBAAyBS,GAAE,oBAAoBL,GAAE,sBAAsBF,GAAE,eAAeG,EAAC,EAAE,OAAOK,GAAE,WAAWF,GAAEE,GAAE,aAAaC,GAAEH,GAAEA,GAAE,YAAY,GAAGI,GAAEF,GAAE,+BAA+BG,GAAE,CAACd,EAAEE,IAAIF,EAAEe,GAAE,CAAC,YAAYf,EAAEE,EAAE,CAAC,OAAOA,EAAC,CAAE,KAAK,QAAQF,EAAEA,EAAEY,GAAE,KAAK,MAAM,KAAK,OAAO,KAAK,MAAMZ,EAAQA,GAAN,KAAQA,EAAE,KAAK,UAAUA,CAAC,CAAC,CAAC,OAAOA,CAAC,EAAE,cAAcA,EAAEE,EAAE,CAAC,IAAIK,EAAEP,EAAE,OAAOE,EAAC,CAAE,KAAK,QAAQK,EAASP,IAAP,KAAS,MAAM,KAAK,OAAOO,EAASP,IAAP,KAAS,KAAK,OAAOA,CAAC,EAAE,MAAM,KAAK,OAAO,KAAK,MAAM,GAAG,CAACO,EAAE,KAAK,MAAMP,CAAC,CAAC,MAAS,CAACO,EAAE,IAAI,CAAC,CAAC,OAAOA,CAAC,CAAC,EAAES,GAAE,CAAChB,EAAEE,IAAI,CAACK,GAAEP,EAAEE,CAAC,EAAEe,GAAE,CAAC,UAAU,GAAG,KAAK,OAAO,UAAUF,GAAE,QAAQ,GAAG,WAAW,GAAG,WAAWC,EAAC,EAAE,OAAO,WAAP,OAAO,SAAW,OAAO,UAAU,GAAEL,GAAE,sBAAFA,GAAE,oBAAsB,IAAI,SAAO,IAAAO,GAAC,cAAgB,WAAW,CAAC,OAAO,eAAe,EAAE,CAAC,KAAK,KAAI,GAAI,KAAK,IAAL,KAAK,EAAI,KAAI,KAAK,CAAC,CAAC,CAAC,WAAW,oBAAoB,CAAC,OAAO,KAAK,SAAQ,EAAG,KAAK,MAAM,CAAC,GAAG,KAAK,KAAK,KAAI,CAAE,CAAC,CAAC,OAAO,eAAe,EAAEhB,EAAEe,GAAE,CAAC,GAAGf,EAAE,QAAQA,EAAE,UAAU,IAAI,KAAK,KAAI,EAAG,KAAK,UAAU,eAAe,CAAC,KAAKA,EAAE,OAAO,OAAOA,CAAC,GAAG,QAAQ,IAAI,KAAK,kBAAkB,IAAI,EAAEA,CAAC,EAAE,CAACA,EAAE,WAAW,CAAC,MAAM,EAAE,OAAM,EAAGQ,EAAE,KAAK,sBAAsB,EAAE,EAAER,CAAC,EAAWQ,IAAT,QAAYT,GAAE,KAAK,UAAU,EAAES,CAAC,CAAC,CAAC,CAAC,OAAO,sBAAsB,EAAER,EAAE,EAAE,CAAC,KAAK,CAAC,IAAID,EAAE,IAAII,CAAC,EAAEK,GAAE,KAAK,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,KAAKR,CAAC,CAAC,EAAE,IAAIF,EAAE,CAAC,KAAKE,CAAC,EAAEF,CAAC,CAAC,EAAE,MAAM,CAAC,IAAIC,EAAE,IAAIC,EAAE,CAAC,MAAMQ,EAAET,GAAA,YAAAA,EAAG,KAAK,MAAMI,GAAA,MAAAA,EAAG,KAAK,KAAKH,GAAG,KAAK,cAAc,EAAEQ,EAAE,CAAC,CAAC,EAAE,aAAa,GAAG,WAAW,EAAE,CAAC,CAAC,OAAO,mBAAmB,EAAE,CAAC,OAAO,KAAK,kBAAkB,IAAI,CAAC,GAAGO,EAAC,CAAC,OAAO,MAAM,CAAC,GAAG,KAAK,eAAeH,GAAE,mBAAmB,CAAC,EAAE,OAAO,MAAM,EAAER,GAAE,IAAI,EAAE,EAAE,SAAQ,EAAY,EAAE,IAAX,SAAe,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,KAAK,kBAAkB,IAAI,IAAI,EAAE,iBAAiB,CAAC,CAAC,OAAO,UAAU,CAAC,GAAG,KAAK,eAAeQ,GAAE,WAAW,CAAC,EAAE,OAAO,GAAG,KAAK,UAAU,GAAG,KAAK,KAAI,EAAG,KAAK,eAAeA,GAAE,YAAY,CAAC,EAAE,CAAC,MAAMd,EAAE,KAAK,WAAWE,EAAE,CAAC,GAAGG,GAAEL,CAAC,EAAE,GAAGG,GAAEH,CAAC,CAAC,EAAE,UAAUO,KAAKL,EAAE,KAAK,eAAeK,EAAEP,EAAEO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,OAAO,QAAQ,EAAE,GAAU,IAAP,KAAS,CAAC,MAAML,EAAE,oBAAoB,IAAI,CAAC,EAAE,GAAYA,IAAT,OAAW,SAAS,CAACF,EAAEO,CAAC,IAAIL,EAAE,KAAK,kBAAkB,IAAIF,EAAEO,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,IAAI,SAAS,CAACP,EAAEE,CAAC,IAAI,KAAK,kBAAkB,CAAC,MAAMK,EAAE,KAAK,KAAKP,EAAEE,CAAC,EAAWK,IAAT,QAAY,KAAK,KAAK,IAAIA,EAAEP,CAAC,CAAC,CAAC,KAAK,cAAc,KAAK,eAAe,KAAK,MAAM,CAAC,CAAC,OAAO,eAAeE,EAAE,CAAC,MAAMK,EAAE,GAAG,GAAG,MAAM,QAAQL,CAAC,EAAE,CAAC,MAAMD,EAAE,IAAI,IAAIC,EAAE,KAAK,GAAG,EAAE,QAAO,CAAE,EAAE,UAAU,KAAKD,EAAEM,EAAE,QAAQP,GAAE,CAAC,CAAC,CAAC,MAAeE,IAAT,QAAYK,EAAE,KAAKP,GAAEE,CAAC,CAAC,EAAE,OAAOK,CAAC,CAAC,OAAO,KAAK,EAAEL,EAAE,CAAC,MAAM,EAAEA,EAAE,UAAU,OAAW,IAAL,GAAO,OAAiB,OAAO,GAAjB,SAAmB,EAAY,OAAO,GAAjB,SAAmB,EAAE,YAAW,EAAG,MAAM,CAAC,aAAa,CAAC,MAAK,EAAG,KAAK,KAAK,OAAO,KAAK,gBAAgB,GAAG,KAAK,WAAW,GAAG,KAAK,KAAK,KAAK,KAAK,KAAI,CAAE,CAAC,MAAM,OAAC,KAAK,KAAK,IAAI,QAAQF,GAAG,KAAK,eAAeA,CAAC,EAAE,KAAK,KAAK,IAAI,IAAI,KAAK,KAAI,EAAG,KAAK,cAAa,GAAGmB,EAAA,KAAK,YAAY,IAAjB,MAAAA,EAAoB,QAAQnB,GAAGA,EAAE,IAAI,EAAE,CAAC,cAAc,EAAE,QAAE,KAAK,OAAL,KAAK,KAAO,IAAI,MAAK,IAAI,CAAC,EAAW,KAAK,aAAd,QAA0B,KAAK,eAAamB,EAAA,EAAE,gBAAF,MAAAA,EAAA,QAAmB,CAAC,iBAAiB,EAAE,QAACA,EAAA,KAAK,OAAL,MAAAA,EAAW,OAAO,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,IAAIjB,EAAE,KAAK,YAAY,kBAAkB,UAAU,KAAKA,EAAE,KAAI,EAAG,KAAK,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC,kBAAkB,CAAC,MAAM,EAAE,KAAK,YAAY,KAAK,aAAa,KAAK,YAAY,iBAAiB,EAAE,OAAOA,GAAE,EAAE,KAAK,YAAY,aAAa,EAAE,CAAC,CAAC,mBAAmB,OAAC,KAAK,aAAL,KAAK,WAAa,KAAK,iBAAgB,GAAG,KAAK,eAAe,EAAE,GAAEiB,EAAA,KAAK,OAAL,MAAAA,EAAW,QAAQnB,GAAC,OAAE,OAAAmB,EAAAnB,EAAE,gBAAF,YAAAmB,EAAA,KAAAnB,IAAoB,CAAC,eAAe,EAAE,CAAC,CAAC,sBAAsB,QAACmB,EAAA,KAAK,OAAL,MAAAA,EAAW,QAAQnB,GAAC,OAAE,OAAAmB,EAAAnB,EAAE,mBAAF,YAAAmB,EAAA,KAAAnB,IAAuB,CAAC,yBAAyB,EAAEE,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,EAAEA,EAAE,OAAC,MAAM,EAAE,KAAK,YAAY,kBAAkB,IAAI,CAAC,EAAED,EAAE,KAAK,YAAY,KAAK,EAAE,CAAC,EAAE,GAAYA,IAAT,QAAiB,EAAE,UAAP,GAAe,CAAC,MAAMS,KAAYS,EAAA,EAAE,YAAF,YAAAA,EAAa,eAAtB,OAAkC,EAAE,UAAUJ,IAAG,YAAYb,EAAE,EAAE,IAAI,EAAE,KAAK,KAAK,EAAQQ,GAAN,KAAQ,KAAK,gBAAgBT,CAAC,EAAE,KAAK,aAAaA,EAAES,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,KAAK,EAAER,EAAE,SAAC,MAAM,EAAE,KAAK,YAAYD,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE,GAAYA,IAAT,QAAY,KAAK,OAAOA,EAAE,CAAC,MAAMD,EAAE,EAAE,mBAAmBC,CAAC,EAAES,EAAc,OAAOV,EAAE,WAArB,WAA+B,CAAC,cAAcA,EAAE,SAAS,IAAWmB,EAAAnB,EAAE,YAAF,YAAAmB,EAAa,iBAAtB,OAAoCnB,EAAE,UAAUe,GAAE,KAAK,KAAKd,EAAE,MAAMI,EAAEK,EAAE,cAAcR,EAAEF,EAAE,IAAI,EAAE,KAAKC,CAAC,EAAEI,KAAGe,EAAA,KAAK,OAAL,YAAAA,EAAW,IAAInB,KAAII,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,cAAc,EAAEH,EAAE,EAAED,EAAE,GAAGS,EAAE,OAAC,GAAY,IAAT,OAAW,CAAC,MAAM,EAAE,KAAK,YAAY,GAAQT,IAAL,KAASS,EAAE,KAAK,CAAC,GAAG,MAAI,EAAE,mBAAmB,CAAC,GAAE,GAAG,EAAE,YAAYM,IAAGN,EAAER,CAAC,GAAG,EAAE,YAAY,EAAE,SAASQ,MAAIS,EAAA,KAAK,OAAL,YAAAA,EAAW,IAAI,KAAI,CAAC,KAAK,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,OAAO,KAAK,EAAE,EAAEjB,EAAE,CAAC,CAAC,CAAM,KAAK,kBAAV,KAA4B,KAAK,KAAK,KAAK,KAAI,EAAG,CAAC,EAAE,EAAEA,EAAE,CAAC,WAAW,EAAE,QAAQD,EAAE,QAAQS,CAAC,EAAEL,EAAE,CAAC,GAAG,EAAE,KAAK,OAAL,KAAK,KAAO,IAAI,MAAK,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,EAAEA,GAAGH,GAAG,KAAK,CAAC,CAAC,EAAOQ,IAAL,IAAiBL,IAAT,UAAc,KAAK,KAAK,IAAI,CAAC,IAAI,KAAK,YAAY,IAAIH,EAAE,QAAQ,KAAK,KAAK,IAAI,EAAEA,CAAC,GAAQD,IAAL,IAAQ,KAAK,OAAO,IAAI,KAAK,OAAL,KAAK,KAAO,IAAI,MAAK,IAAI,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,KAAK,gBAAgB,GAAG,GAAG,CAAC,MAAM,KAAK,IAAI,OAAOD,EAAE,CAAC,QAAQ,OAAOA,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,eAAc,EAAG,OAAa,GAAN,MAAS,MAAM,EAAE,CAAC,KAAK,eAAe,CAAC,gBAAgB,CAAC,OAAO,KAAK,cAAa,CAAE,CAAC,eAAe,OAAC,GAAG,CAAC,KAAK,gBAAgB,OAAO,GAAG,CAAC,KAAK,WAAW,CAAC,GAAG,KAAK,aAAL,KAAK,WAAa,KAAK,iBAAgB,GAAG,KAAK,KAAK,CAAC,SAAS,CAACA,EAAEE,CAAC,IAAI,KAAK,KAAK,KAAKF,CAAC,EAAEE,EAAE,KAAK,KAAK,MAAM,CAAC,MAAMF,EAAE,KAAK,YAAY,kBAAkB,GAAGA,EAAE,KAAK,EAAE,SAAS,CAACE,EAAEK,CAAC,IAAIP,EAAE,CAAC,KAAK,CAAC,QAAQA,CAAC,EAAEO,EAAEN,EAAE,KAAKC,CAAC,EAAOF,IAAL,IAAQ,KAAK,KAAK,IAAIE,CAAC,GAAYD,IAAT,QAAY,KAAK,EAAEC,EAAE,OAAOK,EAAEN,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,MAAMC,EAAE,KAAK,KAAK,GAAG,CAAC,EAAE,KAAK,aAAaA,CAAC,EAAE,GAAG,KAAK,WAAWA,CAAC,GAAEiB,EAAA,KAAK,OAAL,MAAAA,EAAW,QAAQnB,GAAC,OAAE,OAAAmB,EAAAnB,EAAE,aAAF,YAAAmB,EAAA,KAAAnB,KAAkB,KAAK,OAAOE,CAAC,GAAG,KAAK,KAAI,CAAE,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,KAAI,EAAG,CAAC,CAAC,GAAG,KAAK,KAAKA,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,KAAK,EAAE,QAACiB,EAAA,KAAK,OAAL,MAAAA,EAAW,QAAQnB,GAAC,OAAE,OAAAmB,EAAAnB,EAAE,cAAF,YAAAmB,EAAA,KAAAnB,KAAmB,KAAK,aAAa,KAAK,WAAW,GAAG,KAAK,aAAa,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC,IAAI,gBAAgB,CAAC,OAAO,KAAK,kBAAiB,CAAE,CAAC,mBAAmB,CAAC,OAAO,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,OAAL,KAAK,KAAO,KAAK,KAAK,QAAQA,GAAG,KAAK,KAAKA,EAAE,KAAKA,CAAC,CAAC,CAAC,GAAE,KAAK,KAAI,CAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,EAACqB,GAAE,cAAc,GAAGA,GAAE,kBAAkB,CAAC,KAAK,MAAM,EAAEA,GAAEP,GAAE,mBAAmB,CAAC,EAAE,IAAI,IAAIO,GAAEP,GAAE,WAAW,CAAC,EAAE,IAAI,IAAID,aAAI,CAAC,gBAAgBQ,EAAC,IAAIV,GAAE,0BAAFA,GAAE,wBAA0B,KAAI,KAAK,OAAO,ECA3xL,MAACX,GAAE,WAAWO,GAAEP,GAAGA,EAAEE,GAAEF,GAAE,aAAaC,GAAEC,GAAEA,GAAE,aAAa,WAAW,CAAC,WAAWF,GAAGA,CAAC,CAAC,EAAE,OAAOU,GAAE,QAAQP,GAAE,OAAO,KAAK,OAAM,EAAG,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC,IAAIG,GAAE,IAAIH,GAAEE,GAAE,IAAIC,EAAC,IAAIM,GAAE,SAASH,GAAE,IAAIG,GAAE,cAAc,EAAE,EAAED,GAAEX,GAAUA,IAAP,MAAoB,OAAOA,GAAjB,UAAgC,OAAOA,GAAnB,WAAqBe,GAAE,MAAM,QAAQD,GAAEd,GAAGe,GAAEf,CAAC,GAAe,OAAOA,GAAA,YAAAA,EAAI,OAAO,YAA9B,WAAwCgB,GAAE;AAAA,OAAcM,GAAE,sDAAsDC,GAAE,OAAOC,GAAE,KAAKX,GAAE,OAAO,KAAKG,EAAC,qBAAqBA,EAAC,KAAKA,EAAC;AAAA,0BAAsC,GAAG,EAAES,GAAE,KAAKC,GAAE,KAAKL,GAAE,qCAAqCM,GAAE3B,GAAG,CAACO,KAAKL,KAAK,CAAC,WAAWF,EAAE,QAAQO,EAAE,OAAOL,CAAC,GAAGe,EAAEU,GAAE,CAAC,EAAgBC,GAAE,OAAO,IAAI,cAAc,EAAEC,EAAE,OAAO,IAAI,aAAa,EAAEC,GAAE,IAAI,QAAQC,GAAEnB,GAAE,iBAAiBA,GAAE,GAAG,EAAE,SAASoB,GAAEhC,EAAEO,EAAE,CAAC,GAAG,CAACQ,GAAEf,CAAC,GAAG,CAACA,EAAE,eAAe,KAAK,EAAE,MAAM,MAAM,gCAAgC,EAAE,OAAgBC,KAAT,OAAWA,GAAE,WAAWM,CAAC,EAAEA,CAAC,CAAC,MAAM0B,GAAE,CAACjC,EAAEO,IAAI,CAAC,MAAML,EAAEF,EAAE,OAAO,EAAEC,EAAE,GAAG,IAAIK,EAAEM,EAAML,IAAJ,EAAM,QAAYA,IAAJ,EAAM,SAAS,GAAGE,EAAEa,GAAE,QAAQf,EAAE,EAAEA,EAAEL,EAAEK,IAAI,CAAC,MAAML,EAAEF,EAAEO,CAAC,EAAE,IAAII,EAAEI,EAAED,EAAE,GAAGE,EAAE,EAAE,KAAKA,EAAEd,EAAE,SAASO,EAAE,UAAUO,EAAED,EAAEN,EAAE,KAAKP,CAAC,EAASa,IAAP,OAAWC,EAAEP,EAAE,UAAUA,IAAIa,GAAUP,EAAE,CAAC,IAAX,MAAaN,EAAEc,GAAWR,EAAE,CAAC,IAAZ,OAAcN,EAAEe,GAAWT,EAAE,CAAC,IAAZ,QAAeM,GAAE,KAAKN,EAAE,CAAC,CAAC,IAAIT,EAAE,OAAO,KAAKS,EAAE,CAAC,EAAE,GAAG,GAAGN,EAAEI,IAAYE,EAAE,CAAC,IAAZ,SAAgBN,EAAEI,IAAGJ,IAAII,GAAQE,EAAE,CAAC,IAAT,KAAYN,EAAEH,GAAGgB,GAAER,EAAE,IAAaC,EAAE,CAAC,IAAZ,OAAcD,EAAE,IAAIA,EAAEL,EAAE,UAAUM,EAAE,CAAC,EAAE,OAAOJ,EAAEI,EAAE,CAAC,EAAEN,EAAWM,EAAE,CAAC,IAAZ,OAAcF,GAAQE,EAAE,CAAC,IAAT,IAAWW,GAAED,IAAGhB,IAAIiB,IAAGjB,IAAIgB,GAAEhB,EAAEI,GAAEJ,IAAIc,IAAGd,IAAIe,GAAEf,EAAEa,IAAGb,EAAEI,GAAEP,EAAE,QAAQ,MAAMqB,EAAElB,IAAII,IAAGb,EAAEO,EAAE,CAAC,EAAE,WAAW,IAAI,EAAE,IAAI,GAAGK,GAAGH,IAAIa,GAAEpB,EAAEG,GAAES,GAAG,GAAGb,EAAE,KAAKU,CAAC,EAAET,EAAE,MAAM,EAAEY,CAAC,EAAEJ,GAAER,EAAE,MAAMY,CAAC,EAAEX,GAAEwB,GAAGzB,EAAEC,IAAQW,IAAL,GAAOP,EAAEoB,EAAE,CAAC,MAAM,CAACK,GAAEhC,EAAEY,GAAGZ,EAAEE,CAAC,GAAG,QAAYK,IAAJ,EAAM,SAAaA,IAAJ,EAAM,UAAU,GAAG,EAAEN,CAAC,CAAC,EAAC,IAAAiC,GAAC,MAAM1B,EAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,WAAWD,CAAC,EAAEN,EAAE,CAAC,IAAII,EAAE,KAAK,MAAM,GAAG,IAAIO,EAAE,EAAE,EAAE,EAAE,MAAMG,EAAE,EAAE,OAAO,EAAED,EAAE,KAAK,MAAM,CAACE,EAAEM,CAAC,EAAEW,GAAE,EAAE1B,CAAC,EAAE,GAAG,KAAK,GAAGC,GAAE,cAAcQ,EAAEf,CAAC,EAAE8B,GAAE,YAAY,KAAK,GAAG,QAAYxB,IAAJ,GAAWA,IAAJ,EAAM,CAAC,MAAMP,EAAE,KAAK,GAAG,QAAQ,WAAWA,EAAE,YAAY,GAAGA,EAAE,UAAU,CAAC,CAAC,MAAaK,EAAE0B,GAAE,SAAQ,KAApB,MAAyBjB,EAAE,OAAOC,GAAG,CAAC,GAAOV,EAAE,WAAN,EAAe,CAAC,GAAGA,EAAE,gBAAgB,UAAUL,KAAKK,EAAE,kBAAiB,EAAG,GAAGL,EAAE,SAASU,EAAC,EAAE,CAAC,MAAMH,EAAEe,EAAE,GAAG,EAAEpB,EAAEG,EAAE,aAAaL,CAAC,EAAE,MAAMG,EAAC,EAAEF,EAAE,eAAe,KAAKM,CAAC,EAAEO,EAAE,KAAK,CAAC,KAAK,EAAE,MAAMF,EAAE,KAAKX,EAAE,CAAC,EAAE,QAAQC,EAAE,KAAWD,EAAE,CAAC,IAAT,IAAWkC,GAAQlC,EAAE,CAAC,IAAT,IAAWmC,GAAQnC,EAAE,CAAC,IAAT,IAAWoC,GAAEC,EAAC,CAAC,EAAEjC,EAAE,gBAAgBL,CAAC,CAAC,MAAMA,EAAE,WAAWG,EAAC,IAAIW,EAAE,KAAK,CAAC,KAAK,EAAE,MAAMF,CAAC,CAAC,EAAEP,EAAE,gBAAgBL,CAAC,GAAG,GAAGqB,GAAE,KAAKhB,EAAE,OAAO,EAAE,CAAC,MAAML,EAAEK,EAAE,YAAY,MAAMF,EAAC,EAAEI,EAAEP,EAAE,OAAO,EAAE,GAAGO,EAAE,EAAE,CAACF,EAAE,YAAYH,GAAEA,GAAE,YAAY,GAAG,QAAQA,EAAE,EAAEA,EAAEK,EAAEL,IAAIG,EAAE,OAAOL,EAAEE,CAAC,EAAEO,GAAC,CAAE,EAAEsB,GAAE,SAAQ,EAAGjB,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAEF,CAAC,CAAC,EAAEP,EAAE,OAAOL,EAAEO,CAAC,EAAEE,GAAC,CAAE,CAAC,CAAC,CAAC,SAAaJ,EAAE,WAAN,EAAe,GAAGA,EAAE,OAAOC,GAAEQ,EAAE,KAAK,CAAC,KAAK,EAAE,MAAMF,CAAC,CAAC,MAAM,CAAC,IAAIZ,EAAE,GAAG,MAAWA,EAAEK,EAAE,KAAK,QAAQF,GAAEH,EAAE,CAAC,KAA5B,IAAgCc,EAAE,KAAK,CAAC,KAAK,EAAE,MAAMF,CAAC,CAAC,EAAEZ,GAAGG,GAAE,OAAO,CAAC,CAACS,GAAG,CAAC,CAAC,OAAO,cAAc,EAAEL,EAAE,CAAC,MAAML,EAAEU,GAAE,cAAc,UAAU,EAAE,OAAOV,EAAE,UAAU,EAAEA,CAAC,CAAC,EAAC,SAASqC,GAAEvC,EAAEO,EAAEL,EAAEF,EAAEC,EAAE,SAAC,GAAGM,IAAIqB,GAAE,OAAOrB,EAAE,IAAIG,EAAWT,IAAT,QAAWkB,EAAAjB,EAAE,OAAF,YAAAiB,EAASlB,GAAGC,EAAE,KAAK,MAAM,EAAES,GAAEJ,CAAC,EAAE,OAAOA,EAAE,gBAAgB,OAAOG,GAAA,YAAAA,EAAG,eAAc,KAAIU,EAAAV,GAAA,YAAAA,EAAG,OAAH,MAAAU,EAAA,KAAAV,EAAU,IAAa,IAAT,OAAWA,EAAE,QAAQA,EAAE,IAAI,EAAEV,CAAC,EAAEU,EAAE,KAAKV,EAAEE,EAAED,CAAC,GAAYA,IAAT,QAAYC,EAAE,OAAFA,EAAE,KAAO,KAAID,CAAC,EAAES,EAAER,EAAE,KAAKQ,GAAYA,IAAT,SAAaH,EAAEgC,GAAEvC,EAAEU,EAAE,KAAKV,EAAEO,EAAE,MAAM,EAAEG,EAAET,CAAC,GAAGM,CAAC,CAAC,MAAMiC,EAAC,CAAC,YAAY,EAAEjC,EAAE,CAAC,KAAK,KAAK,GAAG,KAAK,KAAK,OAAO,KAAK,KAAK,EAAE,KAAK,KAAKA,CAAC,CAAC,IAAI,YAAY,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQA,CAAC,EAAE,MAAML,CAAC,EAAE,KAAK,KAAKD,IAAG,iBAAG,gBAAeW,IAAG,WAAWL,EAAE,EAAE,EAAEwB,GAAE,YAAY9B,EAAE,IAAIS,EAAEqB,GAAE,WAAW5B,EAAE,EAAEG,EAAE,EAAED,EAAEH,EAAE,CAAC,EAAE,KAAcG,IAAT,QAAY,CAAC,GAAGF,IAAIE,EAAE,MAAM,CAAC,IAAIE,EAAMF,EAAE,OAAN,EAAWE,EAAE,IAAIkC,GAAE/B,EAAEA,EAAE,YAAY,KAAK,CAAC,EAAML,EAAE,OAAN,EAAWE,EAAE,IAAIF,EAAE,KAAKK,EAAEL,EAAE,KAAKA,EAAE,QAAQ,KAAK,CAAC,EAAMA,EAAE,OAAN,IAAaE,EAAE,IAAImC,GAAEhC,EAAE,KAAK,CAAC,GAAG,KAAK,KAAK,KAAKH,CAAC,EAAEF,EAAEH,EAAE,EAAEI,CAAC,CAAC,CAACH,KAAIE,GAAA,YAAAA,EAAG,SAAQK,EAAEqB,GAAE,SAAQ,EAAG5B,IAAI,CAAC,OAAO4B,GAAE,YAAYnB,GAAEX,CAAC,CAAC,EAAE,EAAE,CAAC,IAAIM,EAAE,EAAE,UAAUL,KAAK,KAAK,KAAcA,IAAT,SAAsBA,EAAE,UAAX,QAAoBA,EAAE,KAAK,EAAEA,EAAEK,CAAC,EAAEA,GAAGL,EAAE,QAAQ,OAAO,GAAGA,EAAE,KAAK,EAAEK,CAAC,CAAC,GAAGA,GAAG,CAAC,QAAC,MAAMkC,EAAC,CAAC,IAAI,MAAM,OAAC,QAAOtB,EAAA,KAAK,OAAL,YAAAA,EAAW,OAAM,KAAK,IAAI,CAAC,YAAY,EAAEZ,EAAEL,EAAED,EAAE,CAAC,KAAK,KAAK,EAAE,KAAK,KAAK4B,EAAE,KAAK,KAAK,OAAO,KAAK,KAAK,EAAE,KAAK,KAAKtB,EAAE,KAAK,KAAKL,EAAE,KAAK,QAAQD,EAAE,KAAK,MAAKA,GAAA,YAAAA,EAAG,cAAa,EAAE,CAAC,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,KAAK,WAAW,MAAMM,EAAE,KAAK,KAAK,OAAgBA,IAAT,SAAiB,iBAAG,YAAR,KAAmB,EAAEA,EAAE,YAAY,CAAC,CAAC,IAAI,WAAW,CAAC,OAAO,KAAK,IAAI,CAAC,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,EAAEA,EAAE,KAAK,CAAC,EAAEgC,GAAE,KAAK,EAAEhC,CAAC,EAAEI,GAAE,CAAC,EAAE,IAAIkB,GAAS,GAAN,MAAc,IAAL,IAAQ,KAAK,OAAOA,GAAG,KAAK,KAAI,EAAG,KAAK,KAAKA,GAAG,IAAI,KAAK,MAAM,IAAID,IAAG,KAAK,EAAE,CAAC,EAAW,EAAE,aAAX,OAAsB,KAAK,EAAE,CAAC,EAAW,EAAE,WAAX,OAAoB,KAAK,EAAE,CAAC,EAAEd,GAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,WAAW,aAAa,EAAE,KAAK,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,IAAI,KAAK,KAAI,EAAG,KAAK,KAAK,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,OAAOe,GAAGlB,GAAE,KAAK,IAAI,EAAE,KAAK,KAAK,YAAY,KAAK,EAAE,KAAK,EAAEC,GAAE,eAAe,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,EAAE,EAAE,OAAC,KAAK,CAAC,OAAOL,EAAE,WAAWL,CAAC,EAAE,EAAED,EAAY,OAAOC,GAAjB,SAAmB,KAAK,KAAK,CAAC,GAAYA,EAAE,KAAX,SAAgBA,EAAE,GAAGM,GAAE,cAAcwB,GAAE9B,EAAE,EAAEA,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,OAAO,GAAGA,GAAG,KAAGiB,EAAA,KAAK,OAAL,YAAAA,EAAW,QAAOlB,EAAE,KAAK,KAAK,EAAEM,CAAC,MAAM,CAAC,MAAMP,EAAE,IAAIwC,GAAEvC,EAAE,IAAI,EAAEC,EAAEF,EAAE,EAAE,KAAK,OAAO,EAAEA,EAAE,EAAEO,CAAC,EAAE,KAAK,EAAEL,CAAC,EAAE,KAAK,KAAKF,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAIO,EAAEuB,GAAE,IAAI,EAAE,OAAO,EAAE,OAAgBvB,IAAT,QAAYuB,GAAE,IAAI,EAAE,QAAQvB,EAAE,IAAIC,GAAE,CAAC,CAAC,EAAED,CAAC,CAAC,EAAE,EAAE,CAACQ,GAAE,KAAK,IAAI,IAAI,KAAK,KAAK,GAAG,KAAK,QAAQ,MAAMR,EAAE,KAAK,KAAK,IAAIL,EAAED,EAAE,EAAE,UAAUS,KAAK,EAAET,IAAIM,EAAE,OAAOA,EAAE,KAAKL,EAAE,IAAIuC,GAAE,KAAK,EAAEhC,GAAC,CAAE,EAAE,KAAK,EAAEA,IAAG,EAAE,KAAK,KAAK,OAAO,CAAC,EAAEP,EAAEK,EAAEN,CAAC,EAAEC,EAAE,KAAKQ,CAAC,EAAET,IAAIA,EAAEM,EAAE,SAAS,KAAK,KAAKL,GAAGA,EAAE,KAAK,YAAYD,CAAC,EAAEM,EAAE,OAAON,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,YAAYC,EAAE,OAAC,KAAIiB,EAAA,KAAK,OAAL,YAAAA,EAAA,UAAY,GAAG,GAAGjB,GAAG,IAAI,KAAK,MAAM,CAAC,MAAM,EAAEK,GAAE,CAAC,EAAE,YAAYA,GAAE,CAAC,EAAE,OAAM,EAAG,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,OAAU,KAAK,OAAd,SAAqB,KAAK,KAAK,GAAEY,EAAA,KAAK,OAAL,MAAAA,EAAA,UAAY,GAAG,CAAC,EAAC,MAAMmB,EAAC,CAAC,IAAI,SAAS,CAAC,OAAO,KAAK,QAAQ,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,YAAY,EAAE/B,EAAEL,EAAED,EAAES,EAAE,CAAC,KAAK,KAAK,EAAE,KAAK,KAAKmB,EAAE,KAAK,KAAK,OAAO,KAAK,QAAQ,EAAE,KAAK,KAAKtB,EAAE,KAAK,KAAKN,EAAE,KAAK,QAAQS,EAAER,EAAE,OAAO,GAAQA,EAAE,CAAC,IAAR,IAAgBA,EAAE,CAAC,IAAR,IAAW,KAAK,KAAK,MAAMA,EAAE,OAAO,CAAC,EAAE,KAAK,IAAI,MAAM,EAAE,KAAK,QAAQA,GAAG,KAAK,KAAK2B,CAAC,CAAC,KAAK,EAAEtB,EAAE,KAAKL,EAAED,EAAE,CAAC,MAAMS,EAAE,KAAK,QAAQ,IAAIP,EAAE,GAAG,GAAYO,IAAT,OAAW,EAAE6B,GAAE,KAAK,EAAEhC,EAAE,CAAC,EAAEJ,EAAE,CAACQ,GAAE,CAAC,GAAG,IAAI,KAAK,MAAM,IAAIiB,GAAEzB,IAAI,KAAK,KAAK,OAAO,CAAC,MAAMF,EAAE,EAAE,IAAIK,EAAED,EAAE,IAAI,EAAEK,EAAE,CAAC,EAAEJ,EAAE,EAAEA,EAAEI,EAAE,OAAO,EAAEJ,IAAID,EAAEkC,GAAE,KAAKtC,EAAEC,EAAEI,CAAC,EAAEC,EAAED,CAAC,EAAED,IAAIuB,KAAIvB,EAAE,KAAK,KAAKC,CAAC,GAAGH,MAAI,CAACQ,GAAEN,CAAC,GAAGA,IAAI,KAAK,KAAKC,CAAC,GAAED,IAAIwB,EAAE,EAAEA,EAAE,IAAIA,IAAI,IAAIxB,GAAG,IAAIK,EAAEJ,EAAE,CAAC,GAAG,KAAK,KAAKA,CAAC,EAAED,CAAC,CAACF,GAAG,CAACF,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI4B,EAAE,KAAK,QAAQ,gBAAgB,KAAK,IAAI,EAAE,KAAK,QAAQ,aAAa,KAAK,KAAK,GAAG,EAAE,CAAC,CAAC,KAAAc,GAAC,cAAgBL,EAAC,CAAC,aAAa,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,QAAQ,KAAK,IAAI,EAAE,IAAIT,EAAE,OAAO,CAAC,CAAC,KAAC,cAAgBS,EAAC,CAAC,aAAa,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,QAAQ,gBAAgB,KAAK,KAAK,CAAC,CAAC,GAAG,IAAIT,CAAC,CAAC,CAAC,KAAC,cAAgBS,EAAC,CAAC,YAAY,EAAE/B,EAAEL,EAAED,EAAES,EAAE,CAAC,MAAM,EAAEH,EAAEL,EAAED,EAAES,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,KAAK,EAAEH,EAAE,KAAK,CAAC,IAAI,EAAEgC,GAAE,KAAK,EAAEhC,EAAE,CAAC,GAAGsB,KAAKD,GAAE,OAAO,MAAM1B,EAAE,KAAK,KAAKD,EAAE,IAAI4B,GAAG3B,IAAI2B,GAAG,EAAE,UAAU3B,EAAE,SAAS,EAAE,OAAOA,EAAE,MAAM,EAAE,UAAUA,EAAE,QAAQQ,EAAE,IAAImB,IAAI3B,IAAI2B,GAAG5B,GAAGA,GAAG,KAAK,QAAQ,oBAAoB,KAAK,KAAK,KAAKC,CAAC,EAAEQ,GAAG,KAAK,QAAQ,iBAAiB,KAAK,KAAK,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,YAAY,EAAE,OAAa,OAAO,KAAK,MAAxB,WAA6B,KAAK,KAAK,OAAKS,EAAA,KAAK,UAAL,YAAAA,EAAc,OAAM,KAAK,QAAQ,CAAC,EAAE,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,EAAAyB,GAAC,KAAO,CAAC,YAAY,EAAErC,EAAEL,EAAE,CAAC,KAAK,QAAQ,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,OAAO,KAAK,KAAKK,EAAE,KAAK,QAAQL,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAACqC,GAAE,KAAK,CAAC,CAAC,CAAC,EAAC,MAAMM,GAAE,CAA+B,EAAEJ,EAAmB,EAAEK,GAAE9C,GAAE,uBAAuB8C,aAAItC,GAAEiC,KAAIzC,GAAE,kBAAFA,GAAE,gBAAkB,KAAI,KAAK,OAAO,EAAE,MAAM+C,GAAE,CAAC/C,EAAEO,EAAEL,IAAI,CAAC,MAAMD,GAAEC,GAAA,YAAAA,EAAG,eAAcK,EAAE,IAAIG,EAAET,EAAE,WAAW,GAAYS,IAAT,OAAW,CAAC,MAAMV,GAAEE,GAAA,YAAAA,EAAG,eAAc,KAAKD,EAAE,WAAWS,EAAE,IAAI+B,GAAElC,EAAE,aAAaE,GAAC,EAAGT,CAAC,EAAEA,EAAE,OAAOE,GAAG,EAAE,CAAC,CAAC,OAAOQ,EAAE,KAAKV,CAAC,EAAEU,CAAC,ECAh7N,MAAMR,GAAE,kBAAW,cAAgBF,EAAC,CAAC,aAAa,CAAC,MAAM,GAAG,SAAS,EAAE,KAAK,cAAc,CAAC,KAAK,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC,kBAAkB,OAAC,MAAM,EAAE,MAAM,iBAAgB,EAAG,OAAOmB,EAAA,KAAK,eAAc,eAAnBA,EAAmB,aAAe,EAAE,YAAW,CAAC,CAAC,OAAO,EAAE,CAAC,MAAMd,EAAE,KAAK,OAAM,EAAG,KAAK,aAAa,KAAK,cAAc,YAAY,KAAK,aAAa,MAAM,OAAO,CAAC,EAAE,KAAK,KAAKJ,GAAEI,EAAE,KAAK,WAAW,KAAK,aAAa,CAAC,CAAC,mBAAmB,OAAC,MAAM,kBAAiB,GAAGc,EAAA,KAAK,OAAL,MAAAA,EAAW,aAAa,GAAG,CAAC,sBAAsB,OAAC,MAAM,qBAAoB,GAAGA,EAAA,KAAK,OAAL,MAAAA,EAAW,aAAa,GAAG,CAAC,QAAQ,CAAC,OAAOd,EAAC,CAAC,SAACE,GAAE,cAAc,GAAGA,GAAE,UAAa,IAAGL,MAAE,2BAAFA,iBAA6B,CAAC,WAAWK,EAAC,GAAG,MAAMJ,GAAED,GAAE,0BAA0BC,aAAI,CAAC,WAAWI,EAAC,IAAyDL,GAAE,qBAAFA,GAAE,mBAAqB,KAAI,KAAK,OAAO,ECA/xB,MAAMF,GAAEA,GAAG,CAACC,EAAEE,IAAI,CAAUA,WAAEA,EAAE,eAAe,IAAI,CAAC,eAAe,OAAOH,EAAEC,CAAC,CAAC,CAAC,EAAE,eAAe,OAAOD,EAAEC,CAAC,CAAC,ECAxG,MAAME,GAAE,CAAC,UAAU,GAAG,KAAK,OAAO,UAAUF,GAAE,QAAQ,GAAG,WAAWD,EAAC,EAAEK,GAAE,CAACL,EAAEG,GAAEF,EAAEI,IAAI,CAAC,KAAK,CAAC,KAAKC,EAAE,SAASC,CAAC,EAAEF,EAAE,IAAIH,EAAE,WAAW,oBAAoB,IAAIK,CAAC,EAAE,GAAYL,IAAT,QAAY,WAAW,oBAAoB,IAAIK,EAAEL,EAAE,IAAI,GAAG,EAAaI,IAAX,YAAgBN,EAAE,OAAO,OAAOA,CAAC,GAAG,QAAQ,IAAIE,EAAE,IAAIG,EAAE,KAAKL,CAAC,EAAeM,IAAb,WAAe,CAAC,KAAK,CAAC,KAAKH,CAAC,EAAEE,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,MAAMC,EAAEL,EAAE,IAAI,KAAK,IAAI,EAAEA,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,KAAK,cAAcE,EAAEG,EAAEN,EAAE,GAAG,CAAC,CAAC,EAAE,KAAKC,EAAE,CAAC,OAAgBA,IAAT,QAAY,KAAK,EAAEE,EAAE,OAAOH,EAAEC,CAAC,EAAEA,CAAC,CAAC,CAAC,CAAC,GAAcK,IAAX,SAAa,CAAC,KAAK,CAAC,KAAKH,CAAC,EAAEE,EAAE,OAAO,SAAS,EAAE,CAAC,MAAMC,EAAE,KAAKH,CAAC,EAAEF,EAAE,KAAK,KAAK,CAAC,EAAE,KAAK,cAAcE,EAAEG,EAAEN,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,MAAM,mCAAmCM,CAAC,CAAC,EAAE,SAASA,GAAEN,EAAE,CAAC,MAAM,CAACC,EAAEE,IAAc,OAAOA,GAAjB,SAAmBE,GAAEL,EAAEC,EAAEE,CAAC,GAAG,CAACH,EAAEC,EAAE,IAAI,CAAC,MAAMI,EAAEJ,EAAE,eAAe,CAAC,EAAE,OAAOA,EAAE,YAAY,eAAe,EAAED,CAAC,EAAEK,EAAE,OAAO,yBAAyBJ,EAAE,CAAC,EAAE,MAAM,GAAGD,EAAEC,EAAEE,CAAC,CAAC,CCA5yB,SAASE,EAAEA,EAAE,CAAC,OAAOL,GAAE,CAAC,GAAGK,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC,CAAC,CCLvD,MAAM2C,GAAqB,GACrBC,GAAuB,IAEhBC,GAAyB,YAgBtC,SAASC,GAAoBC,EAA2BC,EAAuC,CAC7F,GAAI,OAAOD,GAAU,SAAU,OAC/B,MAAME,EAAUF,EAAM,OACtB,GAAKE,EACL,OAAIA,EAAQ,QAAUD,EAAkBC,EACjCA,EAAQ,MAAM,EAAGD,CAAS,CACnC,CAEO,SAASE,GACdC,EACmB,CACnB,MAAMC,EACJN,GAAoBK,GAAA,YAAAA,EAAO,KAAMR,EAAkB,GAAKE,GACpDQ,EAASP,IAAoBK,GAAA,YAAAA,EAAO,SAAU,OAAWP,EAAoB,GAAK,KAKxF,MAAO,CAAE,QAHP,OAAOO,GAAA,YAAAA,EAAO,UAAY,UAAYA,EAAM,QAAQ,OAChDA,EAAM,QAAQ,OACd,KACY,KAAAC,EAAM,OAAAC,CAAA,CAC1B,CAEO,SAASC,IAAsD,CACpE,OACSJ,GADL,OAAO,OAAW,IACc,GAEF,CAChC,KAAM,OAAO,8BACb,OAAQ,OAAO,gCAJqB,CAMxC,CCbA,MAAMK,GAAqB,aACrBC,GAAyB,uBACzBC,GAAuB,UACvBC,GAA2B,GAEjC,IAAIC,GAA+B,KAG5B,SAASC,IAA8B,CAC5C,OAAID,KACJA,GAAS,CACP,KAAM,OAAO,2BAA6BJ,GAC1C,QAAS,OAAO,+BAAiCC,GACjD,YAAa,OAAO,6BAA+BC,GACnD,gBAAiB,OAAO,iCAAmCC,EAAA,EAEtDC,GACT,CAGO,SAASE,IAA0D,CACxE,OAAO,OAAO,iCAAmC,EACnD,CAMA,SAASC,GAASC,EAA4B,CAC5C,MAAM5C,EAAI,8CAA8C,KAAK4C,CAAG,EAChE,OAAK5C,EACE,GAAG,SAASA,EAAE,CAAC,EAAG,EAAE,CAAC,KAAK,SAASA,EAAE,CAAC,EAAG,EAAE,CAAC,KAAK,SAASA,EAAE,CAAC,EAAG,EAAE,CAAC,GAD3D,IAEjB,CAGA,SAAS6C,GAAkBD,EAAqB,CAC9C,MAAM5C,EAAI,8CAA8C,KAAK4C,CAAG,EAChE,GAAI,CAAC5C,EAAG,MAAO,GACf,KAAM,CAACnB,EAAGoB,EAAGR,CAAC,EAAI,CAACO,EAAE,CAAC,EAAGA,EAAE,CAAC,EAAGA,EAAE,CAAC,CAAC,EAAE,IAAKf,GAAM,CAC9C,MAAMa,EAAI,SAASb,EAAG,EAAE,EAAI,IAC5B,OAAOa,GAAK,OAAUA,EAAI,MAAQ,KAAK,KAAKA,EAAI,MAAS,MAAO,GAAG,CACrE,CAAC,EACD,MAAO,OAASjB,EAAI,MAASoB,EAAI,MAASR,CAC5C,CAMO,SAASqD,GAAsBC,EAAqB,CACzD,MAAMC,EAAML,GAASI,CAAK,EAC1B,GAAI,CAACC,EAAK,OAEV,MAAMC,EAAO,SAAS,gBACtBA,EAAK,MAAM,YAAY,WAAYF,CAAK,EACxCE,EAAK,MAAM,YAAY,iBAAkBF,CAAK,EAC9CE,EAAK,MAAM,YAAY,iBAAkBF,CAAK,EAC9CE,EAAK,MAAM,YAAY,YAAaF,CAAK,EACzCE,EAAK,MAAM,YAAY,SAAUF,CAAK,EACtCE,EAAK,MAAM,YAAY,kBAAmB,QAAQD,CAAG,SAAS,EAC9DC,EAAK,MAAM,YAAY,gBAAiB,QAAQD,CAAG,SAAS,EAC5DC,EAAK,MAAM,YAAY,kBAAmBF,CAAK,EAC/CE,EAAK,MAAM,YAAY,wBAAyBF,CAAK,EACrDE,EAAK,MAAM,YAAY,uBAAwB,QAAQD,CAAG,SAAS,EAGnE,MAAME,EAAKL,GAAkBE,CAAK,EAAI,GAAM,UAAY,UACxDE,EAAK,MAAM,YAAY,sBAAuBC,CAAE,EAChDD,EAAK,MAAM,YAAY,uBAAwBC,CAAE,CACnD,CAMA,SAASC,GAASC,EAAcC,EAAcC,EAAyB,CACrE,MAAMC,EAAK,8CAA8C,KAAKH,CAAI,EAC5DI,EAAK,8CAA8C,KAAKH,CAAI,EAClE,GAAI,CAACE,GAAM,CAACC,EAAI,OAAOJ,EACvB,MAAMK,EAAQ,CAACC,EAAYC,IACzB,KAAK,MAAM,SAASJ,EAAGG,CAAE,EAAG,EAAE,GAAK,EAAIJ,GAAW,SAASE,EAAGG,CAAE,EAAG,EAAE,EAAIL,CAAO,EAC5EzE,EAAI4E,EAAM,EAAG,CAAC,EACdxD,EAAIwD,EAAM,EAAG,CAAC,EACdhE,EAAIgE,EAAM,EAAG,CAAC,EACpB,MAAO,IAAI5E,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,GAAGoB,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,GAAGR,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAChH,CAGA,MAAMmE,GAAc,CAClB,OAAQ,UACR,aAAc,UACd,SAAU,UACV,cAAe,SACjB,EAMO,SAASC,GAA0Bd,EAAqB,CAC7D,MAAME,EAAO,SAAS,gBACtB,GAAI,CAACF,EAAO,CAEV,SAAW,CAACe,EAAMC,CAAG,IAAK,OAAO,QAAQH,EAAW,EAClDX,EAAK,MAAM,YAAYa,EAAMC,CAAG,EAElCd,EAAK,MAAM,eAAe,YAAY,EACtCA,EAAK,MAAM,eAAe,mBAAmB,EAC7CA,EAAK,MAAM,eAAe,iBAAiB,EAC3C,MACF,CAEA,MAAMD,EAAML,GAASI,CAAK,EACrBC,IAGLC,EAAK,MAAM,YAAY,OAAQE,GAASS,GAAY,MAAM,EAAGb,EAAO,GAAI,CAAC,EACzEE,EAAK,MAAM,YAAY,aAAcE,GAASS,GAAY,YAAY,EAAGb,EAAO,EAAI,CAAC,EACrFE,EAAK,MAAM,YAAY,SAAUE,GAASS,GAAY,QAAQ,EAAGb,EAAO,GAAI,CAAC,EAC7EE,EAAK,MAAM,YAAY,cAAeE,GAASS,GAAY,aAAa,EAAGb,EAAO,EAAI,CAAC,EAGvFE,EAAK,MAAM,YAAY,aAAcF,CAAK,EAC1CE,EAAK,MAAM,YAAY,oBAAqB,QAAQD,CAAG,SAAS,EAChEC,EAAK,MAAM,YAAY,kBAAmB,QAAQD,CAAG,SAAS,EAChE,CAOO,SAASgB,GAAoBC,EAAoC,CACtE,MAAMC,EAAczB,GAAA,EACd0B,EAAWzB,GAAA,EACX0B,EAAKH,EAAgBE,EAASF,CAAa,EAAI,OAG/CI,GAASD,GAAA,YAAAA,EAAI,cAAeF,EAAY,YAC9CpB,GAAsBuB,CAAM,EAG5B,MAAMC,GAAKF,GAAA,YAAAA,EAAI,kBAAmBF,EAAY,gBAC9CL,GAA0BS,CAAE,CAC9B,CCnLA,MAAMC,GAAa,iCACbC,GAAiB,+BAyBvB,SAASC,IAA4B,CAEnC,MAAO,GADO,SAAS,WAAa,SAAW,MAAQ,IACxC,MAAM,SAAS,IAAI,EACpC,CAEA,MAAMC,GAAkC,CACtC,WAAYD,GAAA,EACZ,MAAO,GACP,MAAO,SACP,aAAc,GACd,mBAAoB,EACtB,EAEME,GAAoC,CACxC,WAAY,OACZ,qBAAsB,OACtB,cAAe,GACf,iBAAkB,GAClB,WAAY,EACd,EAEA,SAASC,IAA6B,CACpC,GAAI,CACF,MAAMC,EAAM,aAAa,QAAQN,EAAU,EAC3C,GAAI,CAACM,EAAK,MAAO,CAAE,GAAGH,GAAiB,WAAYD,IAAkB,EACrE,MAAMpF,EAAI,KAAK,MAAMwF,CAAG,EACxB,MAAO,CACL,WACE,OAAOxF,EAAE,YAAe,UAAYA,EAAE,WAAW,OAC7CA,EAAE,WAAW,OACboF,GAAA,EACN,MAAO,OAAOpF,EAAE,OAAU,SAAWA,EAAE,MAAQqF,GAAgB,MAC/D,MACErF,EAAE,QAAU,SAAWA,EAAE,QAAU,QAAUA,EAAE,QAAU,SACrDA,EAAE,MACFqF,GAAgB,MACtB,aACE,OAAOrF,EAAE,cAAiB,UACtBA,EAAE,aACFqF,GAAgB,aACtB,mBACE,OAAOrF,EAAE,oBAAuB,UAAYA,EAAE,qBAAuB,KACjEA,EAAE,mBACFqF,GAAgB,mBAE1B,MAAQ,CACN,MAAO,CAAE,GAAGA,GAAiB,WAAYD,IAAkB,CAC7D,CACF,CAEA,SAASK,GAAYC,EAA2C,CAC9D,GAAI,CAACA,EAAW,MAAO,CAAE,GAAGJ,EAAA,EAC5B,GAAI,CACF,MAAME,EAAM,aAAa,QAAQL,GAAiBO,CAAS,EAC3D,GAAI,CAACF,EAAK,MAAO,CAAE,GAAGF,EAAA,EACtB,MAAMtF,EAAI,KAAK,MAAMwF,CAAG,EACxB,MAAO,CACL,WACE,OAAOxF,EAAE,YAAe,UAAYA,EAAE,WAAW,OAC7CA,EAAE,WAAW,OACbsF,GAAiB,WACvB,qBACE,OAAOtF,EAAE,sBAAyB,UAAYA,EAAE,qBAAqB,OACjEA,EAAE,qBAAqB,OACtB,OAAOA,EAAE,YAAe,UAAYA,EAAE,WAAW,QAClDsF,GAAiB,qBACvB,cACE,OAAOtF,EAAE,eAAkB,UACvBA,EAAE,cACFsF,GAAiB,cACvB,iBACE,OAAOtF,EAAE,kBAAqB,UAC1BA,EAAE,iBACFsF,GAAiB,iBACvB,WACE,OAAOtF,EAAE,YAAe,UAAYA,EAAE,YAAc,IAAOA,EAAE,YAAc,GACvEA,EAAE,WACFsF,GAAiB,WAE3B,MAAQ,CACN,MAAO,CAAE,GAAGA,EAAA,CACd,CACF,CAGA,IAAIK,GAAiC,KAG9B,SAASC,GAAmBF,EAA0B,CAC3DC,GAAkBD,CACpB,CAGO,SAASG,IAA2B,CACzC,MAAO,CAAE,GAAGN,GAAA,EAAc,GAAGE,GAAYE,EAAe,EAC1D,CAGO,SAASG,GAAaC,EAAkB,CAC7C,MAAMC,EAAyB,CAC7B,WAAYD,EAAK,WACjB,MAAOA,EAAK,MACZ,MAAOA,EAAK,MACZ,aAAcA,EAAK,aACnB,mBAAoBA,EAAK,oBAI3B,GAFA,aAAa,QAAQb,GAAY,KAAK,UAAUc,CAAM,CAAC,EAEnDL,GAAiB,CACnB,MAAMM,EAA2B,CAC/B,WAAYF,EAAK,WACjB,qBAAsBA,EAAK,qBAC3B,cAAeA,EAAK,cACpB,iBAAkBA,EAAK,iBACvB,WAAYA,EAAK,YAEnB,aAAa,QAAQZ,GAAiBQ,GAAiB,KAAK,UAAUM,CAAO,CAAC,CAChF,CACF,CAIA,MAAMC,GAAe,oBAErB,SAASC,GAAST,EAAmBU,EAA4B,CAC/D,OAAOF,GAAeR,EAAY,IAAMU,CAC1C,CAGO,SAASC,GAAUX,EAAmBU,EAAoBE,EAAc,CAC7E,GAAI,CACF,MAAMC,EAAMJ,GAAST,EAAWU,CAAU,EACrCE,EAGH,aAAa,QAAQC,EAAKD,CAAI,EAF9B,aAAa,WAAWC,CAAG,CAI/B,MAAQ,CAER,CACF,CAGO,SAASC,GAAUd,EAAmBU,EAA4B,CACvE,GAAI,CACF,OAAO,aAAa,QAAQD,GAAST,EAAWU,CAAU,CAAC,GAAK,EAClE,MAAQ,CACN,MAAO,EACT,CACF,CAGO,SAASK,GAAWf,EAAmBU,EAAoB,CAChE,GAAI,CACF,aAAa,WAAWD,GAAST,EAAWU,CAAU,CAAC,CACzD,MAAQ,CAER,CACF,CAEA,IAAIM,GAAoD,KACpDC,GAAgF,KAG7E,SAASC,GAAkBlB,EAAmBU,EAAoBE,EAAc,CACrFK,GAAgB,CAAE,UAAAjB,EAAW,WAAAU,EAAY,KAAAE,CAAA,EACrCI,IAAe,MAAM,aAAaA,EAAW,EACjDA,GAAc,WAAW,IAAM,CACzBC,IAAeN,GAAUM,GAAc,UAAWA,GAAc,WAAYA,GAAc,IAAI,EAClGA,GAAgB,KAChBD,GAAc,IAChB,EAAG,GAAG,CACR,CAGO,SAASG,IAAiB,CAC3BH,IAAe,MAAM,aAAaA,EAAW,EACjDA,GAAc,KACVC,KACFN,GAAUM,GAAc,UAAWA,GAAc,WAAYA,GAAc,IAAI,EAC/EA,GAAgB,KAEpB,EAGC,UAAyB,CACxB,GAAI,CACF,MAAMnB,EAAM,aAAa,QAAQN,EAAU,EAC3C,GAAI,CAACM,EAAK,OACV,MAAMxF,EAAI,KAAK,MAAMwF,CAAG,EAExB,GAAI,EAAE,eAAgBxF,GAAI,OAE1B,MAAMgG,EAAyB,CAC7B,WAAY,OAAOhG,EAAE,YAAe,SAAWA,EAAE,WAAaoF,GAAA,EAC9D,MAAO,OAAOpF,EAAE,OAAU,SAAWA,EAAE,MAAQ,GAC/C,MAAQA,EAAE,QAAU,SAAWA,EAAE,QAAU,QAAUA,EAAE,QAAU,SAAYA,EAAE,MAAQ,SACvF,aAAc,OAAOA,EAAE,cAAiB,UAAYA,EAAE,aAAe,GACrE,mBACE,OAAOA,EAAE,oBAAuB,UAAYA,EAAE,qBAAuB,KAChEA,EAAE,mBACH,EAAC,EAET,aAAa,QAAQkF,GAAY,KAAK,UAAUc,CAAM,CAAC,CAEzD,MAAQ,CAER,CACF,KCrOO,SAASc,GACdV,EAC8B,OAC9B,MAAMZ,GAAOY,GAAc,IAAI,OAC/B,GAAI,CAACZ,EAAK,OAAO,KACjB,MAAMuB,EAAQvB,EAAI,MAAM,GAAG,EAAE,OAAO,OAAO,EAE3C,GADIuB,EAAM,OAAS,GACfA,EAAM,CAAC,IAAM,QAAS,OAAO,KACjC,MAAMC,GAAU1G,EAAAyG,EAAM,CAAC,IAAP,YAAAzG,EAAU,OACpB2G,EAAOF,EAAM,MAAM,CAAC,EAAE,KAAK,GAAG,EACpC,MAAI,CAACC,GAAW,CAACC,EAAa,KACvB,CAAE,QAAAD,EAAS,KAAAC,CAAA,CACpB,CCdA,MAAMC,GAAe,2DACfC,GAAe,4BACfC,GAAkB,8DAExB,SAASC,GAAU9E,EAAe+E,EAAgC,CAE1C,OAAO/E,EAAM,WAErC,CAEO,SAASgF,GACdjB,EACAkB,EAIQ,CAER,GADI,CAAClB,GACD,CAACY,GAAa,KAAKZ,CAAI,EAAG,OAAOA,EAKrC,IAAImB,EAAUnB,EACVa,GAAa,KAAKM,CAAO,GAC3BN,GAAa,UAAY,EACzBM,EAAUA,EAAQ,QAAQN,GAAc,EAAE,GAE1CA,GAAa,UAAY,EAG3BC,GAAgB,UAAY,EAC5B,IAAIM,EAAS,GACTC,EAAY,EACZC,EAAa,GAEjB,UAAWC,KAASJ,EAAQ,SAASL,EAAe,EAAG,CACrD,MAAMU,EAAMD,EAAM,OAAS,EACrBE,EAAUF,EAAM,CAAC,IAAM,IAExBD,EAKMG,IACTH,EAAa,KALbF,GAAUD,EAAQ,MAAME,EAAWG,CAAG,EACjCC,IACHH,EAAa,KAMjBD,EAAYG,EAAMD,EAAM,CAAC,EAAE,MAC7B,CAGE,OAAAH,GAAUD,EAAQ,MAAME,CAAS,EAG5BN,GAAUK,CAAgB,CACnC,CC1DO,SAASM,GAASC,EAA4B,CACnD,MAAI,CAACA,GAAMA,IAAO,EAAU,MACrB,IAAI,KAAKA,CAAE,EAAE,eAAe,OAAW,CAC5C,UAAW,SACX,UAAW,SACZ,CACH,CAEO,SAASC,GAAUD,EAA4B,CACpD,GAAI,CAACA,GAAMA,IAAO,EAAG,MAAO,MAC5B,MAAME,EAAO,KAAK,MAAQF,EAC1B,GAAIE,EAAO,EAAG,CAEZ,MAAMC,EAAQ,CAACD,EACTE,EAAM,KAAK,MAAMD,EAAQ,GAAI,EACnC,GAAIC,EAAM,GAAI,MAAO,MAAMA,CAAG,IAC9B,MAAMC,EAAM,KAAK,MAAMD,EAAM,EAAE,EAC/B,GAAIC,EAAM,GAAI,MAAO,MAAMA,CAAG,IAC9B,MAAMC,EAAK,KAAK,MAAMD,EAAM,EAAE,EAC9B,OAAIC,EAAK,GAAW,MAAMA,CAAE,IAErB,MADK,KAAK,MAAMA,EAAK,EAAE,CACd,GAClB,CACA,MAAMF,EAAM,KAAK,MAAMF,EAAO,GAAI,EAClC,GAAIE,EAAM,GAAI,MAAO,GAAGA,CAAG,QAC3B,MAAMC,EAAM,KAAK,MAAMD,EAAM,EAAE,EAC/B,GAAIC,EAAM,GAAI,MAAO,GAAGA,CAAG,QAC3B,MAAMC,EAAK,KAAK,MAAMD,EAAM,EAAE,EAC9B,OAAIC,EAAK,GAAW,GAAGA,CAAE,QAElB,GADK,KAAK,MAAMA,EAAK,EAAE,CACjB,OACf,CAEO,SAASC,GAAiBP,EAA4B,CAC3D,GAAI,CAACA,GAAMA,IAAO,EAAG,MAAO,MAC5B,GAAIA,EAAK,IAAM,MAAO,GAAGA,CAAE,KAC3B,MAAMI,EAAM,KAAK,MAAMJ,EAAK,GAAI,EAChC,GAAII,EAAM,GAAI,MAAO,GAAGA,CAAG,IAC3B,MAAMC,EAAM,KAAK,MAAMD,EAAM,EAAE,EAC/B,GAAIC,EAAM,GAAI,MAAO,GAAGA,CAAG,IAC3B,MAAMC,EAAK,KAAK,MAAMD,EAAM,EAAE,EAC9B,OAAIC,EAAK,GAAW,GAAGA,CAAE,IAElB,GADK,KAAK,MAAMA,EAAK,EAAE,CACjB,GACf,CAOO,SAASE,GAAUlG,EAAemG,EAAM,IAAa,CAC1D,OAAInG,EAAM,QAAUmG,EAAYnG,EACzB,GAAGA,EAAM,MAAM,EAAG,KAAK,IAAI,EAAGmG,EAAM,CAAC,CAAC,CAAC,GAChD,CAEO,SAASC,GAAapG,EAAemG,EAI1C,CACA,OAAInG,EAAM,QAAUmG,EACX,CAAE,KAAMnG,EAAO,UAAW,GAAO,MAAOA,EAAM,QAEhD,CACL,KAAMA,EAAM,MAAM,EAAG,KAAK,IAAI,EAAGmG,CAAG,CAAC,EACrC,UAAW,GACX,MAAOnG,EAAM,OAEjB,CAEO,SAASqG,GAASrG,EAAesG,EAA0B,CAChE,MAAM,EAAI,OAAOtG,CAAK,EACtB,OAAO,OAAO,SAAS,CAAC,EAAI,EAAIsG,CAClC,CASO,SAASC,GAAkBvG,EAAuB,CACvD,OAAOgF,GAA2BhF,CAA0C,CAC9E,CCrFA,MAAMwG,GAAkB,mBAClBC,GAAoB,CACxB,UACA,WACA,WACA,SACA,QACA,UACA,WACA,QACA,SACA,OACA,gBACA,aACF,EAEMC,OAAgB,QAChBC,OAAoB,QAE1B,SAASC,GAAwBC,EAAyB,CAExD,MADI,mCAAmC,KAAKA,CAAM,GAC9C,kCAAkC,KAAKA,CAAM,EAAU,GACpDJ,GAAkB,KAAMK,GAAUD,EAAO,WAAW,GAAGC,CAAK,GAAG,CAAC,CACzE,CAEO,SAASC,GAAchD,EAAsB,CAClD,MAAMuB,EAAQvB,EAAK,MAAMyC,EAAe,EACxC,GAAI,CAAClB,EAAO,OAAOvB,EACnB,MAAM8C,EAASvB,EAAM,CAAC,GAAK,GAC3B,OAAKsB,GAAwBC,CAAM,EAC5B9C,EAAK,MAAMuB,EAAM,CAAC,EAAE,MAAM,EADYvB,CAE/C,CAEO,SAASiD,GAAYC,EAAiC,CAC3D,MAAM7I,EAAI6I,EACJC,EAAO,OAAO9I,EAAE,MAAS,SAAWA,EAAE,KAAO,GAC7C+I,EAAU/I,EAAE,QAClB,GAAI,OAAO+I,GAAY,SAErB,OADkBD,IAAS,YAAcX,GAAkBY,CAAO,EAAIJ,GAAcI,CAAO,EAG7F,GAAI,MAAM,QAAQA,CAAO,EAAG,CAC1B,MAAM3C,EAAQ2C,EACX,IAAK1J,GAAM,CACV,MAAM2J,EAAO3J,EACb,OAAI2J,EAAK,OAAS,QAAU,OAAOA,EAAK,MAAS,SAAiBA,EAAK,KAChE,IACT,CAAC,EACA,OAAQlJ,GAAmB,OAAOA,GAAM,QAAQ,EACnD,GAAIsG,EAAM,OAAS,EAAG,CACpB,MAAM6C,EAAS7C,EAAM,KAAK;AAAA,CAAI,EAE9B,OADkB0C,IAAS,YAAcX,GAAkBc,CAAM,EAAIN,GAAcM,CAAM,CAE3F,CACF,CACA,OAAI,OAAOjJ,EAAE,MAAS,SACF8I,IAAS,YAAcX,GAAkBnI,EAAE,IAAI,EAAI2I,GAAc3I,EAAE,IAAI,EAGpF,IACT,CAEO,SAASkJ,GAAkBL,EAAiC,CACjE,GAAI,CAACA,GAAW,OAAOA,GAAY,SAAU,OAAOD,GAAYC,CAAO,EACvE,MAAMM,EAAMN,EACZ,GAAIP,GAAU,IAAIa,CAAG,SAAUb,GAAU,IAAIa,CAAG,GAAK,KACrD,MAAMvH,EAAQgH,GAAYC,CAAO,EACjC,OAAAP,GAAU,IAAIa,EAAKvH,CAAK,EACjBA,CACT,CAEO,SAASwH,GAAgBP,EAAiC,CAE/D,MAAME,EADIF,EACQ,QACZzC,EAAkB,GACxB,GAAI,MAAM,QAAQ2C,CAAO,EACvB,UAAW1J,KAAK0J,EAAS,CACvB,MAAMC,EAAO3J,EACb,GAAI2J,EAAK,OAAS,YAAc,OAAOA,EAAK,UAAa,SAAU,CACjE,MAAMlC,EAAUkC,EAAK,SAAS,OAC1BlC,GAASV,EAAM,KAAKU,CAAO,CACjC,CACF,CAEF,GAAIV,EAAM,OAAS,EAAG,OAAOA,EAAM,KAAK;AAAA,CAAI,EAG5C,MAAMiD,EAAUC,GAAeT,CAAO,EACtC,GAAI,CAACQ,EAAS,OAAO,KAMrB,MAAME,EALU,CACd,GAAGF,EAAQ,SACT,8DACF,EAGC,IAAKrJ,IAAOA,EAAE,CAAC,GAAK,IAAI,MAAM,EAC9B,OAAO,OAAO,EACjB,OAAOuJ,EAAU,OAAS,EAAIA,EAAU,KAAK;AAAA,CAAI,EAAI,IACvD,CAEO,SAASC,GAAsBX,EAAiC,CACrE,GAAI,CAACA,GAAW,OAAOA,GAAY,SAAU,OAAOO,GAAgBP,CAAO,EAC3E,MAAMM,EAAMN,EACZ,GAAIN,GAAc,IAAIY,CAAG,SAAUZ,GAAc,IAAIY,CAAG,GAAK,KAC7D,MAAMvH,EAAQwH,GAAgBP,CAAO,EACrC,OAAAN,GAAc,IAAIY,EAAKvH,CAAK,EACrBA,CACT,CAEO,SAAS0H,GAAeT,EAAiC,CAC9D,MAAM7I,EAAI6I,EACJE,EAAU/I,EAAE,QAClB,GAAI,OAAO+I,GAAY,SAAU,OAAOA,EACxC,GAAI,MAAM,QAAQA,CAAO,EAAG,CAC1B,MAAM3C,EAAQ2C,EACX,IAAK1J,GAAM,CACV,MAAM2J,EAAO3J,EACb,OAAI2J,EAAK,OAAS,QAAU,OAAOA,EAAK,MAAS,SAAiBA,EAAK,KAChE,IACT,CAAC,EACA,OAAQlJ,GAAmB,OAAOA,GAAM,QAAQ,EACnD,GAAIsG,EAAM,OAAS,EAAG,OAAOA,EAAM,KAAK;AAAA,CAAI,CAC9C,CACA,OAAI,OAAOpG,EAAE,MAAS,SAAiBA,EAAE,KAClC,IACT,CAEO,SAASyJ,GAAwB9D,EAAsB,CAC5D,MAAM7D,EAAU6D,EAAK,OACrB,GAAI,CAAC7D,EAAS,MAAO,GACrB,MAAM4H,EAAQ5H,EACX,MAAM,OAAO,EACb,IAAK6H,GAASA,EAAK,MAAM,EACzB,OAAO,OAAO,EACd,IAAKA,GAAS,IAAIA,CAAI,GAAG,EAC5B,OAAOD,EAAM,OAAS,CAAC,eAAgB,GAAGA,CAAK,EAAE,KAAK;AAAA,CAAI,EAAI,EAChE,CChIA,MAAME,GAA2B,sDAC3BC,GAA6B,kCAG7BC,GAAuB,8BAGvBC,GAA0B,oDAMzB,SAASC,GAAmBnB,EAA2B,CAC5D,MAAM7I,EAAI6I,EACJC,EAAO,OAAO9I,EAAE,MAAS,SAAWA,EAAE,KAAO,GAGnD,IAAI2F,EAAO,GACP,OAAO3F,EAAE,SAAY,SACvB2F,EAAO3F,EAAE,QACA,MAAM,QAAQA,EAAE,OAAO,EAChC2F,EAAO3F,EAAE,QACN,OAAQgJ,GAAkB,OAAOA,GAAS,UAAYA,IAAS,IAAI,EACnE,IAAKA,GAAkCA,EAAK,MAAQ,EAAE,EACtD,KAAK,GAAG,EACF,OAAOhJ,EAAE,MAAS,WAC3B2F,EAAO3F,EAAE,MAGX,MAAM8B,EAAU6D,EAAK,OACrB,OAAK7D,EAGD,GAAAgH,IAAS,QAAUc,GAAyB,KAAK9H,CAAO,GAKxDgH,IAAS,aAAee,GAA2B,KAAK/H,CAAO,GAK/DgH,IAAS,QAAUiB,GAAwB,KAAKjI,CAAO,GAKvDgH,IAAS,aAAegB,GAAqB,KAAKhI,CAAO,GAlBxC,EAuBvB,CAKO,SAASmI,GAA2BC,EAAoB,CAC7D,OAAOA,EAAS,OAAQC,GAAQ,CAACH,GAAmBG,CAAG,CAAC,CAC1D,CAKO,SAASC,GAAiBvB,EAAqC,CACpE,MAAM7I,EAAI6I,EACV,IAAIC,EAAO,OAAO9I,EAAE,MAAS,SAAWA,EAAE,KAAO,UAIjD,MAAMqK,EACJ,OAAOrK,EAAE,YAAe,UAAY,OAAOA,EAAE,cAAiB,SAE1DsK,EAAatK,EAAE,QACfuK,EAAe,MAAM,QAAQD,CAAU,EAAIA,EAAa,KACxDE,EACJ,MAAM,QAAQD,CAAY,GAC1BA,EAAa,KAAMvB,GAAS,CAE1B,MAAMxK,EAAI,OADAwK,EACS,MAAQ,EAAE,EAAE,cAC/B,OAAOxK,IAAM,cAAgBA,IAAM,aACrC,CAAC,EAEGiM,EACJ,OAAQzK,EAA8B,UAAa,UACnD,OAAQA,EAA8B,WAAc,UAElDqK,GAAaG,GAAkBC,KACjC3B,EAAO,cAIT,IAAIC,EAAgC,GAEhC,OAAO/I,EAAE,SAAY,SACvB+I,EAAU,CAAC,CAAE,KAAM,OAAQ,KAAM/I,EAAE,QAAS,EACnC,MAAM,QAAQA,EAAE,OAAO,EAChC+I,EAAU/I,EAAE,QAAQ,IAAKgJ,IAAmC,CAC1D,KAAOA,EAAK,MAAuC,OACnD,KAAMA,EAAK,KACX,KAAMA,EAAK,KACX,KAAMA,EAAK,MAAQA,EAAK,WACxB,EACO,OAAOhJ,EAAE,MAAS,WAC3B+I,EAAU,CAAC,CAAE,KAAM,OAAQ,KAAM/I,EAAE,KAAM,GAG3C,MAAM0K,EAAY,OAAO1K,EAAE,WAAc,SAAWA,EAAE,UAAY,KAAK,MACjE2K,EAAK,OAAO3K,EAAE,IAAO,SAAWA,EAAE,GAAK,OAE7C,MAAO,CAAE,KAAA8I,EAAM,QAAAC,EAAS,UAAA2B,EAAW,GAAAC,CAAA,CACrC,CAKO,SAASC,GAAyB9B,EAAsB,CAC7D,MAAM+B,EAAQ/B,EAAK,cAEnB,OAAIA,IAAS,QAAUA,IAAS,OAAeA,EAC3CA,IAAS,YAAoB,YAC7BA,IAAS,SAAiB,SAG5B+B,IAAU,cACVA,IAAU,eACVA,IAAU,QACVA,IAAU,WAEH,OAEF/B,CACT,CAKO,SAASgC,GAAoBjC,EAA2B,CAC7D,MAAM7I,EAAI6I,EACJC,EAAO,OAAO9I,EAAE,MAAS,SAAWA,EAAE,KAAK,cAAgB,GACjE,OAAO8I,IAAS,cAAgBA,IAAS,aAC3C,CCpJA,SAASiC,GAAcC,EAA2B,CAChDA,EAAM,CAAC,EAAKA,EAAM,CAAC,EAAI,GAAQ,GAC/BA,EAAM,CAAC,EAAKA,EAAM,CAAC,EAAI,GAAQ,IAE/B,IAAIpI,EAAM,GACV,QAAS7D,EAAI,EAAGA,EAAIiM,EAAM,OAAQjM,IAChC6D,GAAOoI,EAAMjM,CAAC,EAAG,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EAG/C,MAAO,GAAG6D,EAAI,MAAM,EAAG,CAAC,CAAC,IAAIA,EAAI,MAAM,EAAG,EAAE,CAAC,IAAIA,EAAI,MAAM,GAAI,EAAE,CAAC,IAAIA,EAAI,MACxE,GACA,GACD,IAAIA,EAAI,MAAM,EAAE,CAAC,EACpB,CAEA,SAASqI,IAA8B,CACrC,MAAMD,EAAQ,IAAI,WAAW,EAAE,EACzBE,EAAM,KAAK,MACjB,QAASnM,EAAI,EAAGA,EAAIiM,EAAM,OAAQjM,IAAKiM,EAAMjM,CAAC,EAAI,KAAK,MAAM,KAAK,SAAW,GAAG,EAChF,OAAAiM,EAAM,CAAC,GAAKE,EAAM,IAClBF,EAAM,CAAC,GAAME,IAAQ,EAAK,IAC1BF,EAAM,CAAC,GAAME,IAAQ,GAAM,IAC3BF,EAAM,CAAC,GAAME,IAAQ,GAAM,IACpBF,CACT,CAEO,SAASG,GAAaC,EAAgC,WAAW,OAAgB,CACtF,GAAIA,GAAc,OAAOA,EAAW,YAAe,WAAY,OAAOA,EAAW,aAEjF,GAAIA,GAAc,OAAOA,EAAW,iBAAoB,WAAY,CAClE,MAAMJ,EAAQ,IAAI,WAAW,EAAE,EAC/B,OAAAI,EAAW,gBAAgBJ,CAAK,EACzBD,GAAcC,CAAK,CAC5B,CAEA,OAAOD,GAAcE,IAAiB,CACxC,CClCO,MAAMI,GAAiB,GA8C9B,eAAsBC,GAAgBC,EAAkBC,EAA2B,CACjF,GAAI,CAACD,EAAM,QAAU,CAACA,EAAM,UAAW,OACvCA,EAAM,YAAc,GACpBA,EAAM,UAAY,KAClB,MAAME,GAAQD,GAAA,YAAAA,EAAM,QAASH,GAC7B,GAAI,CACF,MAAMK,EAAO,MAAMH,EAAM,OAAO,QAAQ,eAAgB,CACtD,WAAYA,EAAM,WAClB,MAAAE,CAAA,CACD,EACKE,EAAc,MAAM,QAAQD,EAAI,QAAQ,EAAIA,EAAI,SAAW,GAC3DE,EAAQ,OAAOF,EAAI,eAAkB,SAAWA,EAAI,cAAgBC,EAAY,OAEhFE,EAAW5B,GAAwB0B,CAAW,EACpDJ,EAAM,aAAeM,EACrBN,EAAM,iBAAmBK,EACzBL,EAAM,mBAAqBK,EAAQD,EAAY,OAC/CJ,EAAM,iBAAmB,OAAOG,EAAI,cAAiB,SAAWA,EAAI,aAAe,IACrF,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,YAAc,EACtB,CACF,CAMA,eAAsBQ,GAAqBR,EAAoC,CAE7E,GADI,CAACA,EAAM,QAAU,CAACA,EAAM,WACxBA,EAAM,kBAAoB,CAACA,EAAM,mBAAoB,MAAO,GAChEA,EAAM,iBAAmB,GACzB,GAAI,CACF,MAAMS,EAAeT,EAAM,aAAa,OAClCG,EAAO,MAAMH,EAAM,OAAO,QAAQ,eAAgB,CACtD,WAAYA,EAAM,WAClB,MAAOF,GACP,OAAQW,CAAA,CACT,EACKL,EAAc,MAAM,QAAQD,EAAI,QAAQ,EAAIA,EAAI,SAAW,GAC3DE,EAAQ,OAAOF,EAAI,eAAkB,SAAWA,EAAI,cAAgB,EAC1E,GAAIC,EAAY,SAAW,EACzB,OAAAJ,EAAM,mBAAqB,GACpB,GAET,MAAMM,EAAW5B,GAAwB0B,CAAW,EACpD,OAAAJ,EAAM,aAAe,CAAC,GAAGM,EAAU,GAAGN,EAAM,YAAY,EACxDA,EAAM,iBAAmBK,EACzBL,EAAM,mBAAqBK,EAAQI,EAAeL,EAAY,OACvD,EACT,OAASG,EAAK,CACZ,OAAAP,EAAM,UAAY,OAAOO,CAAG,EACrB,EACT,SACEP,EAAM,iBAAmB,EAC3B,CACF,CAEA,SAASU,GAAgBC,EAA+D,CAGtF,MAAMhF,EAAQ,2BAA2B,KAAKgF,CAAO,EACrD,OAAKhF,EACE,CAAE,SAAUA,EAAM,CAAC,EAAG,QAASA,EAAM,CAAC,GAD1B,IAErB,CAEA,eAAsBiF,GACpBZ,EACA1C,EACAuD,EACkB,CAElB,GADAb,EAAM,gBAAkB,GACpB,CAACA,EAAM,QAAU,CAACA,EAAM,UAAW,MAAO,GAC9C,MAAMpB,EAAMtB,EAAQ,OACdwD,EAAiBD,GAAeA,EAAY,OAAS,EAC3D,GAAI,CAACjC,GAAO,CAACkC,EAAgB,MAAO,GAEpC,MAAMnB,EAAM,KAAK,MAGXoB,GAAaF,GAAe,IAAI,OAAQjN,GAAM,CAACA,EAAE,QAAQ,EACzDoN,GAAYH,GAAe,IAAI,OAAQjN,GAAMA,EAAE,QAAQ,EAGvDqN,EAA0E,GAC1EC,EAAYF,EAAS,IAAK/M,GAAMA,EAAE,QAAQ,EAAE,OAAO,OAAO,EAChE,GAAIiN,EAAU,OAAS,EAAG,CACxB,MAAMC,EAAcvC,EAAM,GAAGsC,EAAU,KAAK,IAAI,CAAC;;AAAA,EAAOtC,CAAG,GAAKsC,EAAU,KAAK,IAAI,EACnFD,EAAc,KAAK,CAAE,KAAM,OAAQ,KAAME,EAAa,CACxD,MAAWvC,GACTqC,EAAc,KAAK,CAAE,KAAM,OAAQ,KAAMrC,EAAK,EAEhD,UAAWwC,KAAOL,EAChBE,EAAc,KAAK,CACjB,KAAM,QACN,OAAQ,CAAE,KAAM,SAAU,WAAYG,EAAI,SAAU,KAAMA,EAAI,QAAQ,CACvE,EAGHpB,EAAM,aAAe,CACnB,GAAGA,EAAM,aACT,CACE,KAAM,OACN,QAASiB,EACT,UAAWtB,CAAA,CACb,EAGFK,EAAM,YAAc,GACpBA,EAAM,UAAY,KAClB,MAAMqB,EAAQzB,GAAA,EACdI,EAAM,UAAYqB,EAClBrB,EAAM,WAAa,GACnBA,EAAM,oBAAsBL,EAG5B,MAAM2B,EAAU,CAAC,GAAGP,EAAW,GAAGC,CAAQ,EACpCO,EAAiBD,EAAQ,OAAS,EACpCA,EACG,IAAKF,GAAQ,CAEZ,GAAIA,EAAI,YACN,MAAO,CACL,KAAM,WACN,SAAUA,EAAI,UAAY,aAC1B,SAAUA,EAAI,SACd,QAAS,KAAK,SAAS,mBAAmBA,EAAI,WAAW,CAAC,CAAC,GAI/D,MAAMI,EAASd,GAAgBU,EAAI,OAAO,EAC1C,OAAKI,EACE,CACL,KAAMJ,EAAI,SAAY,WAAwB,QAC9C,SAAUI,EAAO,SACjB,SAAUJ,EAAI,SACd,QAASI,EAAO,SALE,IAOtB,CAAC,EACA,OAAQ5N,GAAkCA,IAAM,IAAI,EACvD,OAEJ,GAAI,CACF,aAAMoM,EAAM,OAAO,QAAQ,YAAa,CACtC,WAAYA,EAAM,WAClB,QAASpB,EACT,QAAS,GACT,eAAgByC,EAChB,YAAaE,CAAA,CACd,EACM,EACT,OAAShB,EAAK,CACZ,MAAMkB,EAAQ,OAAOlB,CAAG,EACxB,OAAAP,EAAM,UAAY,KAClBA,EAAM,WAAa,KACnBA,EAAM,oBAAsB,KAC5BA,EAAM,UAAYyB,EAClBzB,EAAM,aAAe,CACnB,GAAGA,EAAM,aACT,CACE,KAAM,YACN,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM,UAAYyB,EAAO,EACnD,UAAW,KAAK,KAAI,CACtB,EAEK,EACT,SACEzB,EAAM,YAAc,EACtB,CACF,CAEA,eAAsB0B,GAAa1B,EAAoC,CACrE,GAAI,CAACA,EAAM,QAAU,CAACA,EAAM,UAAW,MAAO,GAC9C,MAAMqB,EAAQrB,EAAM,UACpB,GAAI,CACF,aAAMA,EAAM,OAAO,QACjB,aACAqB,EACI,CAAE,WAAYrB,EAAM,WAAY,MAAAqB,GAChC,CAAE,WAAYrB,EAAM,WAAW,EAE9B,EACT,OAASO,EAAK,CACZ,OAAAP,EAAM,UAAY,OAAOO,CAAG,EACrB,EACT,CACF,CAEO,SAASoB,GACd3B,EACA4B,EACA,SAEA,GADI,CAACA,GACDA,EAAQ,aAAe5B,EAAM,WAAY,OAAO,KAGpD,GACE4B,EAAQ,OACR5B,EAAM,WACN4B,EAAQ,QAAU5B,EAAM,UAExB,OAAI4B,EAAQ,QAAU,QAAgB,QAC/B,KAGT,GAAIA,EAAQ,QAAU,UAAW,CAM/B,MAAMC,GADaD,EAAQ,SAAUxN,EAAAiJ,GAAYuE,EAAQ,OAAO,IAA3B,YAAAxN,EAA8B,OAAS,WAC9CC,EAAA2L,EAAM,aAAN,YAAA3L,EAAkB,QAChD,GAAIwN,EACF,GAAI,CAAC7B,EAAM,gBACTA,EAAM,gBAAkB6B,MACnB,CACL,MAAMC,EAAiBD,EAAQ,OACzBE,EAAkB/B,EAAM,gBAAgB,OAC1C8B,IAAmBC,GAEZA,EAAgB,SAASD,CAAc,IAEvCA,EAAe,WAAWC,CAAe,EAElD/B,EAAM,gBAAkB6B,EAGxB7B,EAAM,gBAAkB,GAAGA,EAAM,eAAe;;AAAA,EAAO6B,CAAO,GAElE,CAEF,OAAA7B,EAAM,WAAa,GACZ,SACT,SAAW4B,EAAQ,QAAU,QAAS,CAEpC,MAAMxH,EAAOiD,GAAYuE,EAAQ,OAAO,EACxC,OAAI,OAAOxH,GAAS,UAAYA,EAAK,SACnC4F,EAAM,aAAe,CACnB,GAAGA,EAAM,aACT,CACE,KAAM,YACN,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAM5F,EAAK,OAAQ,EAC7C,UAAW,KAAK,MAChB,OAAQ,GACV,GAGG,OACT,SAAWwH,EAAQ,QAAU,QAAS,CACpC5B,EAAM,gBAAkB,GACxB,MAAMnG,EAAOwD,GAAYuE,EAAQ,OAAO,EACxC,GAAI,OAAO/H,GAAS,SAAU,CAE5B,GAAIA,EAAK,SAAW,WAAY,OAAO,KACvC,MAAMgI,EAAU7B,EAAM,YAAc,IAChC,CAAC6B,GAAWhI,EAAK,QAAUgI,EAAQ,UACrC7B,EAAM,WAAanG,EAEvB,CACF,MAAW+H,EAAQ,QAAU,SAKlBA,EAAQ,QAAU,WAJ3B5B,EAAM,WAAa,KACnBA,EAAM,UAAY,KAClBA,EAAM,oBAAsB,KAC5BA,EAAM,gBAAkB,MAMf4B,EAAQ,QAAU,UAC3B5B,EAAM,WAAa,KACnBA,EAAM,UAAY,KAClBA,EAAM,oBAAsB,KAC5BA,EAAM,gBAAkB,KACxBA,EAAM,UAAY4B,EAAQ,cAAgB,cAE5C,OAAOA,EAAQ,KACjB,wNC3TA,eAAsBI,GAAahC,EAAsB,CACvD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,gBACV,CAAAA,EAAM,gBAAkB,GACxBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMiC,EAAkC,CACtC,cAAejC,EAAM,uBAAyB,GAC9C,eAAgBA,EAAM,wBAA0B,IAE5CkC,EAAgBxF,GAASsD,EAAM,sBAAwB,GAAI,CAAC,EAC5DE,EAAQxD,GAASsD,EAAM,qBAAuB,GAAI,CAAC,EACrDkC,EAAgB,IAAGD,EAAO,cAAgBC,GAC1ChC,EAAQ,IAAG+B,EAAO,MAAQ/B,GAC9B,MAAMC,EAAO,MAAMH,EAAM,OAAO,QAAQ,gBAAiBiC,CAAM,EAG3D9B,MAAW,eAAiBA,EAClC,OAASI,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,gBAAkB,EAC1B,EACF,CCrCA,MAAMmC,GAAoB,GACpBC,GAA0B,GAC1BC,GAAyB,KAgC/B,SAASC,GAAsBjM,EAA+B,CAC5D,GAAI,CAACA,GAAS,OAAOA,GAAU,SAAU,OAAO,KAChD,MAAMkM,EAASlM,EACf,GAAI,OAAOkM,EAAO,MAAS,gBAAiBA,EAAO,KACnD,MAAM/E,EAAU+E,EAAO,QACvB,GAAI,CAAC,MAAM,QAAQ/E,CAAO,EAAG,OAAO,KACpC,MAAM3C,EAAQ2C,EACX,IAAKC,GAAS,CACb,GAAI,CAACA,GAAQ,OAAOA,GAAS,SAAU,OAAO,KAC9C,MAAM+E,EAAQ/E,EACd,OAAI+E,EAAM,OAAS,QAAU,OAAOA,EAAM,MAAS,SAAiBA,EAAM,KACnE,IACT,CAAC,EACA,OAAQC,GAAyB,EAAQA,CAAK,EACjD,OAAI5H,EAAM,SAAW,EAAU,KACxBA,EAAM,KAAK;AAAA,CAAI,CACxB,CAEA,SAAS6H,GAAiBrM,EAA+B,CACvD,GAAIA,GAAU,KAA6B,OAAO,KAClD,GAAI,OAAOA,GAAU,UAAY,OAAOA,GAAU,UAChD,OAAO,OAAOA,CAAK,EAErB,MAAMsM,EAAcL,GAAsBjM,CAAK,EAC/C,IAAI+D,EACJ,GAAI,OAAO/D,GAAU,SACnB+D,EAAO/D,UACEsM,EACTvI,EAAOuI,MAEP,IAAI,CACFvI,EAAO,KAAK,UAAU/D,EAAO,KAAM,CAAC,CACtC,MAAQ,CACN+D,EAAO,OAAO/D,CAAK,CACrB,CAEF,MAAMuM,EAAYnG,GAAarC,EAAMiI,EAAsB,EAC3D,OAAKO,EAAU,UACR,GAAGA,EAAU,IAAI;;AAAA,eAAoBA,EAAU,KAAK,yBAAyBA,EAAU,KAAK,MAAM,KADxEA,EAAU,IAE7C,CAEA,SAASC,GAAuBL,EAAiD,CAC/E,MAAMhF,EAA0C,GAChD,OAAAA,EAAQ,KAAK,CACX,KAAM,WACN,KAAMgF,EAAM,KACZ,UAAWA,EAAM,MAAQ,EAAC,CAC3B,EACGA,EAAM,QACRhF,EAAQ,KAAK,CACX,KAAM,aACN,KAAMgF,EAAM,KACZ,KAAMA,EAAM,OACb,EAEI,CACL,KAAM,YACN,WAAYA,EAAM,WAClB,MAAOA,EAAM,MACb,QAAAhF,EACA,UAAWgF,EAAM,UAErB,CAEA,SAASM,GAAeC,EAAsB,CAC5C,GAAIA,EAAK,gBAAgB,QAAUZ,GAAmB,OACtD,MAAMa,EAAWD,EAAK,gBAAgB,OAASZ,GACzCc,EAAUF,EAAK,gBAAgB,OAAO,EAAGC,CAAQ,EACvD,UAAW5D,KAAM6D,EAASF,EAAK,eAAe,OAAO3D,CAAE,CACzD,CAEA,SAAS8D,GAAuBH,EAAsB,CACpDA,EAAK,iBAAmBA,EAAK,gBAC1B,IAAK3D,GAAA,OAAO,OAAAhL,EAAA2O,EAAK,eAAe,IAAI3D,CAAE,IAA1B,YAAAhL,EAA6B,QAAO,EAChD,OAAQwK,GAAwC,EAAQA,CAAI,CACjE,CAEO,SAASuE,GAAoBJ,EAAsB,CACpDA,EAAK,qBAAuB,OAC9B,aAAaA,EAAK,mBAAmB,EACrCA,EAAK,oBAAsB,MAE7BG,GAAuBH,CAAI,CAC7B,CAEO,SAASK,GAAuBL,EAAsBM,EAAQ,GAAO,CAC1E,GAAIA,EAAO,CACTF,GAAoBJ,CAAI,EACxB,MACF,CACIA,EAAK,qBAAuB,OAChCA,EAAK,oBAAsB,OAAO,WAChC,IAAMI,GAAoBJ,CAAI,EAC9BX,EAAA,EAEJ,CAEO,SAASkB,GAAgBP,EAAsB,CACpDA,EAAK,eAAe,QACpBA,EAAK,gBAAkB,GACvBA,EAAK,iBAAmB,GACxBI,GAAoBJ,CAAI,CAC1B,CAaA,MAAMQ,GAA+B,IAE9B,SAASC,GAAsBT,EAAsBnB,EAA4B,OACtF,MAAM6B,EAAO7B,EAAQ,MAAQ,GACvB8B,EAAQ,OAAOD,EAAK,OAAU,SAAWA,EAAK,MAAQ,GAGxDV,EAAK,sBAAwB,OAC/B,OAAO,aAAaA,EAAK,oBAAoB,EAC7CA,EAAK,qBAAuB,MAG1BW,IAAU,QACZX,EAAK,iBAAmB,CACtB,OAAQ,GACR,UAAW,KAAK,MAChB,YAAa,MAENW,IAAU,QACnBX,EAAK,iBAAmB,CACtB,OAAQ,GACR,YAAW3O,EAAA2O,EAAK,mBAAL,YAAA3O,EAAuB,YAAa,KAC/C,YAAa,KAAK,KAAI,EAGxB2O,EAAK,qBAAuB,OAAO,WAAW,IAAM,CAClDA,EAAK,iBAAmB,KACxBA,EAAK,qBAAuB,IAC9B,EAAGQ,EAA4B,EAEnC,CAEO,SAASI,GAAiBZ,EAAsBnB,EAA6B,CAClF,GAAI,CAACA,EAAS,OAGd,GAAIA,EAAQ,SAAW,aAAc,CACnC4B,GAAsBT,EAAwBnB,CAAO,EACrD,MACF,CAEA,GAAIA,EAAQ,SAAW,OAAQ,OAC/B,MAAM1H,EACJ,OAAO0H,EAAQ,YAAe,SAAWA,EAAQ,WAAa,OAKhE,GAJI1H,GAAcA,IAAe6I,EAAK,YAElC,CAAC7I,GAAc6I,EAAK,WAAanB,EAAQ,QAAUmB,EAAK,WACxDA,EAAK,WAAanB,EAAQ,QAAUmB,EAAK,WACzC,CAACA,EAAK,UAAW,OAErB,MAAMU,EAAO7B,EAAQ,MAAQ,GACvBgC,EAAa,OAAOH,EAAK,YAAe,SAAWA,EAAK,WAAa,GAC3E,GAAI,CAACG,EAAY,OACjB,MAAMlN,EAAO,OAAO+M,EAAK,MAAS,SAAWA,EAAK,KAAO,OACnDC,EAAQ,OAAOD,EAAK,OAAU,SAAWA,EAAK,MAAQ,GACtDI,EAAOH,IAAU,QAAUD,EAAK,KAAO,OACvCK,EACJJ,IAAU,SACNhB,GAAiBe,EAAK,aAAa,EACnCC,IAAU,SACRhB,GAAiBe,EAAK,MAAM,EAC5B,OAEF9D,EAAM,KAAK,MACjB,IAAI6C,EAAQO,EAAK,eAAe,IAAIa,CAAU,EACzCpB,GAeHA,EAAM,KAAO9L,EACTmN,IAAS,SAAWrB,EAAM,KAAOqB,GACjCC,IAAW,SAAWtB,EAAM,OAASsB,GACzCtB,EAAM,UAAY7C,IAjBlB6C,EAAQ,CACN,WAAAoB,EACA,MAAOhC,EAAQ,MACf,WAAA1H,EACA,KAAAxD,EACA,KAAAmN,EACA,OAAAC,EACA,UAAW,OAAOlC,EAAQ,IAAO,SAAWA,EAAQ,GAAKjC,EACzD,UAAWA,EACX,QAAS,EAAC,EAEZoD,EAAK,eAAe,IAAIa,EAAYpB,CAAK,EACzCO,EAAK,gBAAgB,KAAKa,CAAU,GAQtCpB,EAAM,QAAUK,GAAuBL,CAAK,EAC5CM,GAAeC,CAAI,EACnBK,GAAuBL,EAAMW,IAAU,QAAQ,CACjD,CC/NA,IAAIK,GAAY,EAET,SAASC,GAAmBjB,EAAkBM,EAAQ,GAAO,CAC9DN,EAAK,iBAAiB,qBAAqBA,EAAK,eAAe,EAC/DA,EAAK,mBAAqB,OAC5B,aAAaA,EAAK,iBAAiB,EACnCA,EAAK,kBAAoB,MAE3B,MAAMkB,EAAM,EAAEF,GACRG,EAAmB,IAAM,CAC7B,MAAMC,EAAYpB,EAAK,cAAc,cAAc,EACnD,GAAIoB,EAAW,CACb,MAAMC,EAAY,iBAAiBD,CAAS,EAAE,UAK9C,GAHEC,IAAc,QACdA,IAAc,UACdD,EAAU,aAAeA,EAAU,aAAe,EACrC,OAAOA,CACxB,CACA,OAAQ,SAAS,kBAAoB,SAAS,eAChD,EAEKpB,EAAK,eAAe,KAAK,IAAM,CAC9BkB,IAAQF,KACZhB,EAAK,gBAAkB,sBAAsB,IAAM,CAEjD,GADAA,EAAK,gBAAkB,KACnBkB,IAAQF,GAAW,OACvB,MAAMM,EAASH,EAAA,EACf,GAAI,CAACG,EAAQ,OACb,MAAMC,EACJD,EAAO,aAAeA,EAAO,UAAYA,EAAO,aAElD,GAAI,EADgBhB,GAASN,EAAK,oBAAsBuB,EAAqB,KAC3D,OACdjB,MAAY,oBAAsB,IACtCgB,EAAO,UAAYA,EAAO,aAC1BtB,EAAK,mBAAqB,GAC1B,MAAMwB,EAAalB,EAAQ,IAAM,IACjCN,EAAK,kBAAoB,OAAO,WAAW,IAAM,CAE/C,GADAA,EAAK,kBAAoB,KACrBkB,IAAQF,GAAW,OACvB,MAAMS,EAASN,EAAA,EACf,GAAI,CAACM,EAAQ,OACb,MAAMC,EACJD,EAAO,aAAeA,EAAO,UAAYA,EAAO,cAEhDnB,GAASN,EAAK,oBAAsB0B,EAA2B,OAEjED,EAAO,UAAYA,EAAO,aAC1BzB,EAAK,mBAAqB,GAC5B,EAAGwB,CAAU,CACf,CAAC,EACH,CAAC,CACH,CAEO,SAASG,GAAmB3B,EAAkBM,EAAQ,GAAO,CAC9DN,EAAK,iBAAiB,qBAAqBA,EAAK,eAAe,EAC9DA,EAAK,eAAe,KAAK,IAAM,CAClCA,EAAK,gBAAkB,sBAAsB,IAAM,CACjDA,EAAK,gBAAkB,KACvB,MAAMoB,EAAYpB,EAAK,cAAc,aAAa,EAC9C,CAACoB,GAGD,EADgBd,GAASc,EAAU,UAAY,MAEnDA,EAAU,UAAY,EACxB,CAAC,CACH,CAAC,CACH,CAEO,SAASQ,GAAiB5B,EAAkB6B,EAAc,CAC/D,MAAMT,EAAYS,EAAM,cACxB,GAAI,CAACT,EAAW,OAChB,MAAMG,EACJH,EAAU,aAAeA,EAAU,UAAYA,EAAU,aAC3DpB,EAAK,mBAAqBuB,EAAqB,IAG3CH,EAAU,UAAY,KAAOpB,EAAK,aACpCA,EAAK,aAET,CAOO,SAAS8B,GAAwB9B,EAAuC,CAC7E,MAAMoB,EAAYpB,EAAK,cAAc,cAAc,EACnD,GAAI,CAACoB,EAAW,OAAO,KACvB,MAAMW,EAAmBX,EAAU,aAC7BY,EAAgBZ,EAAU,UAChC,MAAO,IAAM,CACX,MAAMa,EAAQb,EAAU,aAAeW,EACvCX,EAAU,UAAYY,EAAgBC,CACxC,CACF,CAEO,SAASC,GAAiBlC,EAAkB6B,EAAc,CAC/D,MAAMT,EAAYS,EAAM,cACnBT,IAELpB,EAAK,aAAeoB,EAAU,UAAY,GAC5C,CAEO,SAASe,GAAwBnC,EAAkB6B,EAAc,CACtE,MAAMT,EAAYS,EAAM,cACnBT,IACLpB,EAAK,aAAeoB,EAAU,UAAY,GAC5C,CAEO,SAASgB,GAAgBpC,EAAkB,CAChDA,EAAK,oBAAsB,GAC3BA,EAAK,mBAAqB,EAC5B,CAEO,SAASqC,GAAWjH,EAAiBhB,EAAe,CACzD,GAAIgB,EAAM,SAAW,EAAG,OACxB,MAAMkH,EAAO,IAAI,KAAK,CAAC,GAAGlH,EAAM,KAAK;AAAA,CAAI,CAAC;AAAA,CAAI,EAAG,CAAE,KAAM,aAAc,EACjEmH,EAAM,IAAI,gBAAgBD,CAAI,EAC9BE,EAAS,SAAS,cAAc,GAAG,EACnCC,EAAQ,IAAI,OAAO,cAAc,MAAM,EAAG,EAAE,EAAE,QAAQ,QAAS,GAAG,EACxED,EAAO,KAAOD,EACdC,EAAO,SAAW,mBAAmBpI,CAAK,IAAIqI,CAAK,OACnDD,EAAO,QACP,IAAI,gBAAgBD,CAAG,CACzB,CAEO,SAASG,GAAkBtH,EAAiBhB,EAAe,CAChE,GAAIgB,EAAM,SAAW,EAAG,OACxB,MAAMkH,EAAO,IAAI,KAAK,CAAC,GAAGlH,EAAM,KAAK;AAAA,CAAI,CAAC;AAAA,CAAI,EAAG,CAAE,KAAM,aAAc,EACjEmH,EAAM,IAAI,gBAAgBD,CAAI,EAC9BE,EAAS,SAAS,cAAc,GAAG,EACnCC,EAAQ,IAAI,OAAO,cAAc,MAAM,EAAG,EAAE,EAAE,QAAQ,QAAS,GAAG,EACxED,EAAO,KAAOD,EACdC,EAAO,SAAW,2BAA2BpI,CAAK,IAAIqI,CAAK,OAC3DD,EAAO,QACP,IAAI,gBAAgBD,CAAG,CACzB,CAEO,SAASI,GAAc3C,EAAkB,CAC9C,GAAI,OAAO,eAAmB,IAAa,OAC3C,MAAM4C,EAAS5C,EAAK,cAAc,SAAS,EAC3C,GAAI,CAAC4C,EAAQ,OACb,MAAMC,EAAS,IAAM,CACnB,KAAM,CAAE,OAAAC,CAAA,EAAWF,EAAO,wBAC1B5C,EAAK,MAAM,YAAY,kBAAmB,GAAG8C,CAAM,IAAI,CACzD,EACAD,EAAA,EACA7C,EAAK,eAAiB,IAAI,eAAe,IAAM6C,GAAQ,EACvD7C,EAAK,eAAe,QAAQ4C,CAAM,CACpC,CCxKO,SAASG,GAAqBzP,EAAa,CAChD,OAAI,OAAO,iBAAoB,WACtB,gBAAgBA,CAAK,EAEvB,KAAK,MAAM,KAAK,UAAUA,CAAK,CAAC,CACzC,CAEO,SAAS0P,GAAoBC,EAAuC,CACzE,MAAO,GAAG,KAAK,UAAUA,EAAM,KAAM,CAAC,EAAE,SAAS;AAAA,CACnD,CAEO,SAASC,GACdrI,EACAsI,EACA7P,EACA,CACA,GAAI6P,EAAK,SAAW,EAAG,OACvB,IAAIrE,EAA+CjE,EACnD,QAASpK,EAAI,EAAGA,EAAI0S,EAAK,OAAS,EAAG1S,GAAK,EAAG,CAC3C,MAAM6G,EAAM6L,EAAK1S,CAAC,EACZ2S,EAAUD,EAAK1S,EAAI,CAAC,EAC1B,GAAI,OAAO6G,GAAQ,SAAU,CAC3B,GAAI,CAAC,MAAM,QAAQwH,CAAO,EAAG,OACzBA,EAAQxH,CAAG,GAAK,OAClBwH,EAAQxH,CAAG,EACT,OAAO8L,GAAY,SAAW,GAAM,IAExCtE,EAAUA,EAAQxH,CAAG,CACvB,KAAO,CACL,GAAI,OAAOwH,GAAY,UAAYA,GAAW,KAAM,OACpD,MAAMU,EAASV,EACXU,EAAOlI,CAAG,GAAK,OACjBkI,EAAOlI,CAAG,EACR,OAAO8L,GAAY,SAAW,GAAM,IAExCtE,EAAUU,EAAOlI,CAAG,CACtB,CACF,CACA,MAAM+L,EAAUF,EAAKA,EAAK,OAAS,CAAC,EACpC,GAAI,OAAOE,GAAY,SAAU,CAC3B,MAAM,QAAQvE,CAAO,IAAGA,EAAQuE,CAAO,EAAI/P,GAC/C,MACF,CACI,OAAOwL,GAAY,UAAYA,GAAW,OAC3CA,EAAoCuE,CAAO,EAAI/P,EAEpD,CCNA,eAAsBgQ,GAAWrG,EAAoB,CACnD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,cAAgB,GACtBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,aAAc,EAAE,EACxDsG,GAAoBtG,EAAOG,CAAG,CAChC,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,cAAgB,EACxB,EACF,CAEA,eAAsBuG,GAAiBvG,EAAoB,CACzD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,oBACV,CAAAA,EAAM,oBAAsB,GAC5B,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAC9B,gBACA,EAAC,EAEHwG,GAAkBxG,EAAOG,CAAG,CAC9B,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,oBAAsB,EAC9B,EACF,CAEO,SAASwG,GACdxG,EACAG,EACA,CACAH,EAAM,aAAeG,EAAI,QAAU,KACnCH,EAAM,cAAgBG,EAAI,SAAW,GACrCH,EAAM,oBAAsBG,EAAI,SAAW,IAC7C,CAEO,SAASmG,GAAoBtG,EAAoByG,EAA0B,CAChFzG,EAAM,eAAiByG,EACvB,MAAMC,EACJ,OAAOD,EAAS,KAAQ,SACpBA,EAAS,IACTA,EAAS,QAAU,OAAOA,EAAS,QAAW,SAC5CV,GAAoBU,EAAS,MAAiC,EAC9DzG,EAAM,UACV,CAACA,EAAM,iBAAmBA,EAAM,iBAAmB,MACrDA,EAAM,UAAY0G,EACT1G,EAAM,WACfA,EAAM,UAAY+F,GAAoB/F,EAAM,UAAU,EAEtDA,EAAM,UAAY0G,EAEpB1G,EAAM,YAAc,OAAOyG,EAAS,OAAU,UAAYA,EAAS,MAAQ,KAC3EzG,EAAM,aAAe,MAAM,QAAQyG,EAAS,MAAM,EAAIA,EAAS,OAAS,GAEnEzG,EAAM,kBACTA,EAAM,WAAa8F,GAAkBW,EAAS,QAAU,EAAE,EAC1DzG,EAAM,mBAAqB8F,GAAkBW,EAAS,QAAU,EAAE,EAClEzG,EAAM,kBAAoB0G,EAE9B,CAEA,eAAsBC,GAAW3G,EAAoB,OACnD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,aAAe,GACrBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAM1G,EACJ0G,EAAM,iBAAmB,QAAUA,EAAM,WACrC+F,GAAoB/F,EAAM,UAAU,EACpCA,EAAM,UACN4G,GAAWxS,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,KACvC,GAAI,CAACwS,EAAU,CACb5G,EAAM,UAAY,yCAClB,MACF,CACA,MAAMA,EAAM,OAAO,QAAQ,aAAc,CAAE,IAAA1G,EAAK,SAAAsN,EAAU,EAC1D5G,EAAM,gBAAkB,GACxB,MAAMqG,GAAWrG,CAAK,CACxB,OAASO,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,aAAe,EACvB,EACF,CChGA,eAAsB6G,GAAe7G,EAAkB,CACrD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,cAAe,EAAE,EACzDA,EAAM,WAAaG,CACrB,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,CACF,CAEA,eAAsBuG,GAAa9G,EAAkB,CACnD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,YACV,CAAAA,EAAM,YAAc,GACpBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAM+G,EAAsC,CAAE,gBAAiB,IAC3D,MAAM,QAAQ/G,EAAM,iBAAiB,GAAKA,EAAM,kBAAkB,OAAS,IAC7E+G,EAAW,SAAW/G,EAAM,mBAE1BA,EAAM,YACR+G,EAAW,UAAY/G,EAAM,WAE/B,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,YAAa+G,CAAU,EAC/D/G,EAAM,SAAW,MAAM,QAAQG,EAAI,IAAI,EAAIA,EAAI,KAAO,EACxD,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,YAAc,EACtB,EACF,CAEO,SAASgH,GAAkBhB,EAAqB,CACrD,GAAIA,EAAK,eAAiB,KAAM,CAC9B,MAAMjK,EAAK,KAAK,MAAMiK,EAAK,UAAU,EACrC,GAAI,CAAC,OAAO,SAASjK,CAAE,EAAG,MAAM,IAAI,MAAM,mBAAmB,EAC7D,MAAO,CAAE,KAAM,KAAe,KAAMA,CAAA,CACtC,CACA,GAAIiK,EAAK,eAAiB,QAAS,CACjC,MAAMiB,EAASvK,GAASsJ,EAAK,YAAa,CAAC,EAC3C,GAAIiB,GAAU,EAAG,MAAM,IAAI,MAAM,0BAA0B,EAC3D,MAAMC,EAAOlB,EAAK,UAElB,MAAO,CAAE,KAAM,QAAkB,QAASiB,GAD7BC,IAAS,UAAY,IAASA,IAAS,QAAU,KAAY,MACvB,CACrD,CACA,MAAMC,EAAOnB,EAAK,SAAS,OAC3B,GAAI,CAACmB,EAAM,MAAM,IAAI,MAAM,2BAA2B,EACtD,MAAO,CAAE,KAAM,OAAiB,KAAAA,EAAM,GAAInB,EAAK,OAAO,QAAU,OAClE,CAEO,SAASoB,GAAiBpB,EAAqB,CACpD,GAAIA,EAAK,cAAgB,cAAe,CACtC,MAAM5L,EAAO4L,EAAK,YAAY,OAC9B,GAAI,CAAC5L,EAAM,MAAM,IAAI,MAAM,6BAA6B,EACxD,MAAO,CAAE,KAAM,cAAwB,KAAAA,CAAA,CACzC,CACA,MAAMkD,EAAU0I,EAAK,YAAY,OACjC,GAAI,CAAC1I,EAAS,MAAM,IAAI,MAAM,yBAAyB,EACvD,MAAMsE,EAOF,CAAE,KAAM,YAAa,QAAAtE,CAAA,EACrB0I,EAAK,UAASpE,EAAQ,QAAU,IAChCoE,EAAK,UAASpE,EAAQ,QAAUoE,EAAK,SAEzC,MAAMqB,EAAoB,GACtBrB,EAAK,UAAUqB,EAAQ,KAAK,QAAQ,EACxC,UAAW/T,KAAK0S,EAAK,WAAY,CAC/B,MAAMzP,EAAUjD,EAAE,OACdiD,GAAS8Q,EAAQ,KAAK9Q,CAAO,CACnC,CACI8Q,EAAQ,OAAS,MAAW,GAAKA,EAAQ,KAAK,GAAG,GACrD,MAAMC,EAAiB5K,GAASsJ,EAAK,eAAgB,CAAC,EACtD,OAAIsB,EAAiB,IAAG1F,EAAQ,eAAiB0F,GAC1C1F,CACT,CAEA,eAAsB2F,GAAWvH,EAAkB,OACjD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,UAC/C,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMwH,EAAWR,GAAkBhH,EAAM,QAAQ,EAC3C4B,EAAUwF,GAAiBpH,EAAM,QAAQ,EACzClF,EAAUkF,EAAM,SAAS,QAAQ,OACjCyH,GAAYrT,EAAA4L,EAAM,SAAS,YAAf,YAAA5L,EAA0B,OACtCsT,EAAM,CACV,KAAM1H,EAAM,SAAS,KAAK,OAC1B,YAAaA,EAAM,SAAS,YAAY,QAAU,OAClD,QAASlF,GAAW,OACpB,UAAW2M,GAAa,OACxB,QAASzH,EAAM,SAAS,QACxB,SAAAwH,EACA,cAAexH,EAAM,SAAS,cAC9B,SAAUA,EAAM,SAAS,SACzB,QAAA4B,EACA,UACE5B,EAAM,SAAS,iBAAiB,QAChCA,EAAM,SAAS,gBAAkB,WAC7B,CAAE,iBAAkBA,EAAM,SAAS,iBAAiB,QACpD,QAER,GAAI,CAAC0H,EAAI,KAAM,MAAM,IAAI,MAAM,gBAAgB,EAC/C,MAAM1H,EAAM,OAAO,QAAQ,WAAY0H,CAAG,EAC1C1H,EAAM,SAAW,CACf,GAAGA,EAAM,SACT,KAAM,GACN,YAAa,GACb,YAAa,IAEf,MAAM8G,GAAa9G,CAAK,EACxB,MAAM6G,GAAe7G,CAAK,CAC5B,OAASO,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,SAAW,EACnB,EACF,CAEA,eAAsB2H,GACpB3H,EACA0H,EACAE,EACA,CACA,GAAI,GAAC5H,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,UAC/C,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,cAAe,CAAE,GAAI0H,EAAI,GAAI,MAAO,CAAE,QAAAE,CAAA,CAAQ,CAAG,EAC5E,MAAMd,GAAa9G,CAAK,EACxB,MAAM6G,GAAe7G,CAAK,CAC5B,OAASO,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,SAAW,EACnB,EACF,CAEA,eAAsB6H,GAAW7H,EAAkB0H,EAAc,CAC/D,GAAI,GAAC1H,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,UAC/C,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAElBA,EAAM,kBAAoB0H,EAAI,GAC9B1H,EAAM,oBAAsB0H,EAAI,MAAQ,WACxC1H,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,WAAY,CAAE,GAAI0H,EAAI,GAAI,KAAM,QAAS,EACpE,MAAMI,GAAa9H,EAAO0H,EAAI,EAAE,CAClC,OAASnH,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,EAC5BP,EAAM,cAAgB,CAAE,OAAQ,QAAS,MAAO,OAAOO,CAAG,EAC5D,SACEP,EAAM,SAAW,EACnB,EACF,CAGO,SAAS+H,GACd/H,EACA4B,EACA,CAEE5B,EAAM,mBACN4B,EAAQ,QAAU5B,EAAM,mBACxB4B,EAAQ,SAAW,aAEnB5B,EAAM,cAAgB,CACpB,OAAQ4B,EAAQ,QAAU,UAC1B,WAAYA,EAAQ,WACpB,QAASA,EAAQ,QACjB,WAAYA,EAAQ,WACpB,MAAOA,EAAQ,OAGrB,CAQA,eAAsBoG,GAAchI,EAAkB0H,EAAc,CAClE,GAAI,GAAC1H,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,UAC/C,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,cAAe,CAAE,GAAI0H,EAAI,GAAI,EACpD1H,EAAM,gBAAkB0H,EAAI,KAC9B1H,EAAM,cAAgB,KACtBA,EAAM,SAAW,IAEnB,MAAM8G,GAAa9G,CAAK,EACxB,MAAM6G,GAAe7G,CAAK,CAC5B,OAASO,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,SAAW,EACnB,EACF,CAMO,SAASiI,GAAmBP,EAA6B,OAC9D,MAAM1B,EAAsB,CAC1B,KAAM0B,EAAI,MAAQ,GAClB,YAAaA,EAAI,aAAe,GAChC,QAASA,EAAI,SAAW,GACxB,QAASA,EAAI,QACb,aAAcA,EAAI,SAAS,KAC3B,WAAY,GACZ,YAAa,KACb,UAAW,UACX,SAAU,GACV,OAAQ,GACR,cAAeA,EAAI,eAAiB,OACpC,SAAUA,EAAI,UAAY,iBAC1B,YAAaA,EAAI,QAAQ,KACzB,YAAa,GACb,QAAS,GACT,QAAS,OACT,WAAY,GACZ,SAAU,GACV,eAAgB,GAChB,iBAAkB,IAIpB,GAAIA,EAAI,SAAS,OAAS,KAAM,CAC9B,MAAM3T,EAAI,IAAI,KAAK2T,EAAI,SAAS,IAAI,EAE9BQ,EAAO3U,GAAc,OAAOA,CAAC,EAAE,SAAS,EAAG,GAAG,EACpDyS,EAAK,WAAa,GAAGjS,EAAE,aAAa,IAAImU,EAAInU,EAAE,WAAa,CAAC,CAAC,IAAImU,EAAInU,EAAE,SAAS,CAAC,IAAImU,EAAInU,EAAE,UAAU,CAAC,IAAImU,EAAInU,EAAE,YAAY,CAAC,EAC/H,SAAW2T,EAAI,SAAS,OAAS,QAAS,CACxC,MAAM3L,EAAK2L,EAAI,SAAS,QACpB3L,EAAK,QAAe,GACtBiK,EAAK,YAAc,OAAOjK,EAAK,KAAU,EACzCiK,EAAK,UAAY,QACRjK,EAAK,OAAc,GAC5BiK,EAAK,YAAc,OAAOjK,EAAK,IAAS,EACxCiK,EAAK,UAAY,UAEjBA,EAAK,YAAc,OAAOjK,EAAK,GAAM,EACrCiK,EAAK,UAAY,UAErB,MAAW0B,EAAI,SAAS,OAAS,SAC/B1B,EAAK,SAAW0B,EAAI,SAAS,KAC7B1B,EAAK,OAAS0B,EAAI,SAAS,IAAM,IAInC,GAAIA,EAAI,QAAQ,OAAS,cACvB1B,EAAK,YAAc0B,EAAI,QAAQ,aACtBA,EAAI,QAAQ,OAAS,YAAa,CAC3C1B,EAAK,YAAc0B,EAAI,QAAQ,QAC/B1B,EAAK,QAAU0B,EAAI,QAAQ,SAAW,GACtC1B,EAAK,eAAiB0B,EAAI,QAAQ,eAAiB,OAAOA,EAAI,QAAQ,cAAc,EAAI,GAExF,MAAMS,EAAWT,EAAI,QAAoC,SAAWA,EAAI,QAAQ,SAChF1B,EAAK,QAAWmC,GAAsB,OAEtC,MAAMC,EAAQV,EAAI,QAAQ,IAAM,GAChC,GAAIU,EAAO,CACT,MAAMvN,EAAQuN,EAAM,MAAM,GAAG,EAAE,IAAKjV,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,EAClE6S,EAAK,SAAWnL,EAAM,KAAM/G,GAAMA,EAAE,gBAAkB,QAAQ,EAC9DkS,EAAK,WAAanL,EAAM,OAAQ/G,GAAMA,EAAE,gBAAkB,QAAQ,CACpE,CACF,CAGA,OAAIM,EAAAsT,EAAI,YAAJ,MAAAtT,EAAe,mBACjB4R,EAAK,iBAAmB0B,EAAI,UAAU,kBAGjC1B,CACT,CAEA,eAAsBqC,GAAcrI,EAAkBsI,EAAe,CACnE,GAAI,GAACtI,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,UAC/C,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMwH,EAAWR,GAAkBhH,EAAM,QAAQ,EAC3C4B,EAAUwF,GAAiBpH,EAAM,QAAQ,EACzCuI,EAAiC,CACrC,KAAMvI,EAAM,SAAS,KAAK,OAC1B,YAAaA,EAAM,SAAS,YAAY,QAAU,OAClD,QAASA,EAAM,SAAS,QAAQ,QAAU,OAC1C,QAASA,EAAM,SAAS,QACxB,SAAAwH,EACA,cAAexH,EAAM,SAAS,cAC9B,SAAUA,EAAM,SAAS,SACzB,QAAA4B,CAAA,EAOF,GALI5B,EAAM,SAAS,iBAAiB,QAAUA,EAAM,SAAS,gBAAkB,WAC7EuI,EAAM,UAAY,CAAE,iBAAkBvI,EAAM,SAAS,iBAAiB,MAAK,EAE3EuI,EAAM,UAAY,OAEhB,CAACA,EAAM,KAAM,MAAM,IAAI,MAAM,gBAAgB,EACjD,MAAMvI,EAAM,OAAO,QAAQ,cAAe,CAAE,GAAIsI,EAAO,MAAAC,EAAO,EAC9D,MAAMzB,GAAa9G,CAAK,EACxB,MAAM6G,GAAe7G,CAAK,CAC5B,OAASO,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,SAAW,EACnB,EACF,CAEA,eAAsB8H,GAAa9H,EAAkBsI,EAAe,CAClE,GAAI,GAACtI,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,YAAa,CACnD,GAAIsI,EACJ,MAAO,GACR,EACDtI,EAAM,cAAgBsI,EACtBtI,EAAM,SAAW,MAAM,QAAQG,EAAI,OAAO,EAAIA,EAAI,QAAU,EAC9D,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,CACF,CClWA,eAAsBiI,EAAaxI,EAAsByI,EAAgB,CACvE,GAAI,GAACzI,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,gBACV,CAAAA,EAAM,gBAAkB,GACxBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,kBAAmB,CACzD,MAAAyI,EACA,UAAW,IACZ,EACDzI,EAAM,iBAAmBG,EACzBH,EAAM,oBAAsB,KAAK,KACnC,OAASO,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,gBAAkB,EAC1B,EACF,CAEA,eAAsB0I,GAAmB1I,EAAsBqD,EAAgBoE,EAAoB,CACjG,GAAI,GAACzH,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,cAG/C,CAAAA,EAAM,aAAe,GACrBA,EAAM,0BAA4ByH,GAAa,KAC/C,GAAI,CACF,MAAMtH,EAAO,MAAMH,EAAM,OAAO,QAAQ,kBAAmB,CACzD,MAAAqD,EACA,UAAW,IACX,UAAAoE,CAAA,CACD,EACDzH,EAAM,qBAAuBG,EAAI,SAAW,KAC5CH,EAAM,uBAAyBG,EAAI,WAAa,KAChDH,EAAM,uBAAyB,IACjC,OAASO,EAAK,CACZP,EAAM,qBAAuB,OAAOO,CAAG,EACvCP,EAAM,uBAAyB,KAC/BA,EAAM,uBAAyB,IACjC,SACEA,EAAM,aAAe,EACvB,EACF,CAEA,eAAsB2I,GAAkB3I,EAAsByH,EAAoB,CAChF,GAAI,GAACzH,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,cAC/C,CAAAA,EAAM,aAAe,GACrB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,iBAAkB,CACxD,UAAW,KACX,UAAAyH,CAAA,CACD,EACDzH,EAAM,qBAAuBG,EAAI,SAAW,KAC5CH,EAAM,uBAAyBG,EAAI,WAAa,KAC5CA,EAAI,YACNH,EAAM,uBAAyB,KAC/BA,EAAM,0BAA4B,KAClCA,EAAM,oBAAsBG,EAAI,WAAa,KAEjD,OAASI,EAAK,CACZP,EAAM,qBAAuB,OAAOO,CAAG,EACvCP,EAAM,uBAAyB,IACjC,SACEA,EAAM,aAAe,EACvB,EACF,CAEA,eAAsB4I,GAAe5I,EAAsByH,EAAoB,CAC7E,GAAI,GAACzH,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,cAC/C,CAAAA,EAAM,aAAe,GACrB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,kBAAmB,CAAE,QAAS,WAAY,UAAAyH,EAAW,EAChFzH,EAAM,qBAAuB,cAC7BA,EAAM,uBAAyB,KAC/BA,EAAM,uBAAyB,KAC/BA,EAAM,0BAA4B,IACpC,OAASO,EAAK,CACZP,EAAM,qBAAuB,OAAOO,CAAG,CACzC,SACEP,EAAM,aAAe,EACvB,EACF,CAMA,eAAsB6I,GAAmB7I,EAAsBtJ,EAAc,CAE3E,GADI,CAACsJ,EAAM,QAAU,CAACA,EAAM,WACxBA,EAAM,sBAAuB,OAEjC,MAAMzJ,EAAUG,EAAK,OACrB,GAAI,CAACH,EAAS,CACZyJ,EAAM,qBAAuB,4BAC7B,MACF,CAGA,MAAMyH,EAAYlR,EACf,cACA,QAAQ,cAAe,GAAG,EAC1B,QAAQ,SAAU,EAAE,EAEvB,GAAI,CAACkR,EAAW,CACdzH,EAAM,qBAAuB,wBAC7B,MACF,CAEAA,EAAM,sBAAwB,GAC9BA,EAAM,qBAAuB,KAC7B,GAAI,CAEF,MAAM8I,EAAa,MAAM9I,EAAM,OAAO,QAAQ,aAAc,EAAE,EAC9DA,EAAM,eAAiB8I,EACvB,MAAMC,EAASjD,GAAmBgD,EAAU,QAAU,EAA8B,GAGhF,CAACC,EAAO,UAAY,OAAOA,EAAO,UAAa,YACjDA,EAAO,SAAW,IAEpB,MAAMC,EAAWD,EAAO,UACpB,CAACC,EAAS,UAAY,OAAOA,EAAS,UAAa,YACrDA,EAAS,SAAW,IAEtB,MAAMC,EAAWD,EAAS,UACtB,CAACC,EAAS,UAAY,OAAOA,EAAS,UAAa,YACrDA,EAAS,SAAW,IAEtB,MAAMC,EAAWD,EAAS,SAG1B,GAAIC,EAASzB,CAAS,EAAG,CACvBzH,EAAM,qBAAuB,YAAYyH,CAAS,oBAClD,MACF,CAGAyB,EAASzB,CAAS,EAAI,CAAE,KAAMlR,EAAS,SAAU,WAEjD,MAAMqQ,EAAWkC,EAAU,KAC3B,GAAI,CAAClC,EAAU,CACb5G,EAAM,qBAAuB,yCAC7B,MACF,CACA,MAAM1G,EAAMyM,GAAoBgD,CAAM,EACtC,MAAM/I,EAAM,OAAO,QAAQ,aAAc,CAAE,IAAA1G,EAAK,SAAAsN,EAAU,EAG1D5G,EAAM,sBAAwB,GAC9BA,EAAM,uBAAyB,GAG/B,MAAMwI,EAAaxI,EAAO,EAAI,EAG9B,MAAM0I,GAAmB1I,EAAO,GAAMyH,CAAS,CACjD,OAASlH,EAAK,CACZP,EAAM,qBAAuB,OAAOO,CAAG,CACzC,SACEP,EAAM,sBAAwB,EAChC,CACF,CAMA,eAAsBmJ,GAAsBnJ,EAAsByH,EAAmB,CACnF,GAAI,GAACzH,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,sBAEV,CAAAA,EAAM,sBAAwB,GAC9BA,EAAM,qBAAuB,KAC7B,GAAI,CAEF,MAAM8I,EAAa,MAAM9I,EAAM,OAAO,QAAQ,aAAc,EAAE,EAC9DA,EAAM,eAAiB8I,EACvB,MAAMC,EAASjD,GAAmBgD,EAAU,QAAU,EAA8B,EAE9EE,EAAWD,EAAO,SAClBE,EAAWD,GAAA,YAAAA,EAAU,SACrBE,EAAWD,GAAA,YAAAA,EAAU,SAE3B,GAAI,CAACC,EAAU,CACblJ,EAAM,qBAAuB,+BAC7B,MACF,CAGA,GADoB,OAAO,KAAKkJ,CAAQ,EACxB,QAAU,EAAG,CAC3BlJ,EAAM,qBAAuB,kCAC7B,MACF,CAEA,GAAI,CAACkJ,EAASzB,CAAS,EAAG,CACxBzH,EAAM,qBAAuB,YAAYyH,CAAS,eAClD,MACF,CAGA,GAAI,CACF,MAAMzH,EAAM,OAAO,QAAQ,kBAAmB,CAAE,QAAS,WAAY,UAAAyH,EAAW,CAClF,MAAQ,CAER,CAGA,OAAOyB,EAASzB,CAAS,EAGrB,MAAM,QAAQsB,EAAO,QAAQ,IAC/BA,EAAO,SAAYA,EAAO,SAA4C,OAAQK,GAAY,CACxF,MAAMzN,EAAQyN,EAAQ,MAEtB,MADI,CAACzN,GACDA,EAAM,UAAY,WAAmB,GAClCA,EAAM,YAAc8L,CAC7B,CAAC,GAGH,MAAMb,EAAWkC,EAAU,KAC3B,GAAI,CAAClC,EAAU,CACb5G,EAAM,qBAAuB,yCAC7B,MACF,CACA,MAAM1G,EAAMyM,GAAoBgD,CAAM,EACtC,MAAM/I,EAAM,OAAO,QAAQ,aAAc,CAAE,IAAA1G,EAAK,SAAAsN,EAAU,EAGtD5G,EAAM,4BAA8ByH,IACtCzH,EAAM,0BAA4B,KAClCA,EAAM,uBAAyB,KAC/BA,EAAM,qBAAuB,MAI/B,MAAMwI,EAAaxI,EAAO,EAAI,CAChC,OAASO,EAAK,CACZP,EAAM,qBAAuB,OAAOO,CAAG,CACzC,SACEP,EAAM,sBAAwB,EAChC,EACF,gOCrOA,eAAsBqJ,GAAUrJ,EAAmB,CACjD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,aACV,CAAAA,EAAM,aAAe,GACrB,GAAI,CACF,KAAM,CAACsJ,EAAQC,EAAQC,EAAQC,CAAS,EAAI,MAAM,QAAQ,IAAI,CAC5DzJ,EAAM,OAAO,QAAQ,SAAU,EAAE,EACjCA,EAAM,OAAO,QAAQ,SAAU,EAAE,EACjCA,EAAM,OAAO,QAAQ,cAAe,EAAE,EACtCA,EAAM,OAAO,QAAQ,iBAAkB,EAAE,EAC1C,EACDA,EAAM,YAAcsJ,EACpBtJ,EAAM,YAAcuJ,EACpB,MAAMG,EAAeF,EACrBxJ,EAAM,YAAc,MAAM,QAAQ0J,GAAA,YAAAA,EAAc,MAAM,EAClDA,GAAA,YAAAA,EAAc,OACd,GACJ1J,EAAM,eAAiByJ,CACzB,OAASlJ,EAAK,CACZP,EAAM,eAAiB,OAAOO,CAAG,CACnC,SACEP,EAAM,aAAe,EACvB,EACF,CCtCA,MAAM2J,GAAqB,4BA4BdC,GAAoC,CAC/C,QAAS,GACT,QAAS,GACT,aAAc,GACd,cAAe,GACf,UAAW,KACX,OAAQ,GACR,SAAU,GACV,MAAO,KACP,KAAM,EACR,EAEO,SAASC,IAAuC,CACrD,GAAI,CACF,OAAO,aAAa,QAAQF,EAAkB,CAChD,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAASG,GAAkBC,EAAqB,CAC9C,GAAI,CACF,aAAa,QAAQJ,GAAoBI,CAAK,CAChD,MAAQ,CAER,CACF,CAEA,SAASC,IAA0B,CACjC,GAAI,CACF,aAAa,WAAWL,EAAkB,CAC5C,MAAQ,CAER,CACF,CAWA,eAAsBM,GAAkBlH,EAAiC,CACvE,GAAKA,EAAK,OACV,GAAI,CACF,MAAMgH,EAAQF,GAAA,EACRrO,EAAU,MAAMuH,EAAK,OAAO,QAAQ,gBAAiB,CAAE,MAAAgH,EAAO,EAQpEhH,EAAK,YAAc,CACjB,GAAGA,EAAK,YACR,QAAS,GACT,QAASvH,EAAO,QAChB,aAAcA,EAAO,aACrB,SAAUA,EAAO,UAAY,GAC7B,cAAeA,EAAO,cACtB,UAAWA,EAAO,UAClB,OAAQA,EAAO,OACf,MAAO,KAEX,MAAQ,CAENuH,EAAK,YAAc,CACjB,GAAGA,EAAK,YACR,QAAS,GACT,QAAS,GACT,aAAc,GACd,SAAU,GACV,cAAe,GACf,MAAO,KAEX,CACF,CAKA,eAAsBmH,GACpBnH,EACAhJ,EACAoQ,EACe,CACf,GAAKpH,EAAK,OACV,CAAAA,EAAK,YAAc,CAAE,GAAGA,EAAK,YAAa,KAAM,GAAM,MAAO,MAC7D,GAAI,CACF,MAAMvH,EAAU,MAAMuH,EAAK,OAAO,QAAQ,gBAAiB,CAAE,QAAAhJ,EAAS,IAAAoQ,EAAK,EAOvE3O,EAAO,IAAMA,EAAO,OACtBsO,GAAkBtO,EAAO,KAAK,EAC9BuH,EAAK,YAAc,CACjB,GAAGA,EAAK,YACR,cAAe,GACf,UAAWvH,EAAO,WAAa,KAC/B,OAAQA,EAAO,QAAU,GACzB,KAAM,GACN,MAAO,OAGTuH,EAAK,YAAc,CACjB,GAAGA,EAAK,YACR,KAAM,GACN,MAAOvH,EAAO,SAAW,gBAG/B,MAAQ,CACNuH,EAAK,YAAc,CACjB,GAAGA,EAAK,YACR,KAAM,GACN,MAAO,uBAEX,EACF,CAKA,eAAsBqH,GAAarH,EAAkBoH,EAA4B,CAC/E,GAAKpH,EAAK,OACV,CAAAA,EAAK,YAAc,CAAE,GAAGA,EAAK,YAAa,KAAM,GAAM,MAAO,MAC7D,GAAI,CACF,MAAMvH,EAAU,MAAMuH,EAAK,OAAO,QAAQ,sBAAuB,CAAE,IAAAoH,EAAK,EAIpE3O,EAAO,IAAMA,EAAO,OACtBsO,GAAkBtO,EAAO,KAAK,EAC9BuH,EAAK,YAAc,CACjB,GAAGA,EAAK,YACR,QAAS,GACT,QAAS,GACT,aAAc,GACd,cAAe,GACf,UAAW,KACX,OAAQ,GACR,KAAM,GACN,MAAO,OAGTA,EAAK,YAAc,CAAE,GAAGA,EAAK,YAAa,KAAM,GAAO,MAAO,oBAElE,MAAQ,CACNA,EAAK,YAAc,CAAE,GAAGA,EAAK,YAAa,KAAM,GAAO,MAAO,oBAChE,EACF,CAKA,eAAsBsH,GACpBtH,EACAvJ,EACA2Q,EACkB,CAClB,GAAI,CAACpH,EAAK,OAAQ,MAAO,GACzB,GAAI,CAIF,OAHgB,MAAMA,EAAK,OAAO,QAAQ,uBAAwB,CAAE,UAAAvJ,EAAW,IAAA2Q,EAAK,GAGtE,EAChB,MAAQ,CACN,MAAO,EACT,CACF,CAKA,eAAsBG,GAAOvH,EAAiC,CAC5D,MAAMgH,EAAQF,GAAA,EACd,GAAI9G,EAAK,QAAUgH,EACjB,GAAI,CACF,MAAMhH,EAAK,OAAO,QAAQ,gBAAiB,CAAE,MAAAgH,EAAO,CACtD,MAAQ,CAER,CAEFC,GAAA,EACAjH,EAAK,YAAc,CACjB,GAAG6G,GACH,QAAS,GACT,QAAS,GACT,aAAc7G,EAAK,YAAY,aAC/B,SAAUA,EAAK,YAAY,SAE/B,CC7MA,MAAMwH,GAAmB,IACnBC,OAAa,IAAc,CAC/B,QACA,QACA,OACA,OACA,QACA,OACF,CAAC,EAED,SAASC,GAAqBpU,EAAgB,CAC5C,GAAI,OAAOA,GAAU,SAAU,OAAO,KACtC,MAAME,EAAUF,EAAM,OACtB,GAAI,CAACE,EAAQ,WAAW,GAAG,GAAK,CAACA,EAAQ,SAAS,GAAG,EAAG,OAAO,KAC/D,GAAI,CACF,MAAMiL,EAAS,KAAK,MAAMjL,CAAO,EACjC,MAAI,CAACiL,GAAU,OAAOA,GAAW,SAAiB,KAC3CA,CACT,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAASkJ,GAAerU,EAAiC,CACvD,GAAI,OAAOA,GAAU,SAAU,OAAO,KACtC,MAAMsU,EAAUtU,EAAM,cACtB,OAAOmU,GAAO,IAAIG,CAAO,EAAIA,EAAU,IACzC,CAEO,SAASC,GAAaxM,EAAwB,CACnD,GAAI,CAACA,EAAK,aAAe,CAAE,IAAKA,EAAM,QAASA,CAAA,EAC/C,GAAI,CACF,MAAMR,EAAM,KAAK,MAAMQ,CAAI,EACrByM,EACJjN,GAAO,OAAOA,EAAI,OAAU,UAAYA,EAAI,QAAU,KACjDA,EAAI,MACL,KACAkN,EACJ,OAAOlN,EAAI,MAAS,SAChBA,EAAI,KACJ,OAAOiN,GAAA,YAAAA,EAAM,OAAS,SACpBA,GAAA,YAAAA,EAAM,KACN,KACFE,EAAQL,IAAeG,GAAA,YAAAA,EAAM,gBAAgBA,GAAA,YAAAA,EAAM,MAAK,EAExDG,EACJ,OAAOpN,EAAI,CAAG,GAAM,SACfA,EAAI,CAAG,EACR,OAAOiN,GAAA,YAAAA,EAAM,OAAS,SACnBA,GAAA,YAAAA,EAAM,KACP,KACFI,EAAaR,GAAqBO,CAAgB,EACxD,IAAIE,EAA2B,KAC3BD,IACE,OAAOA,EAAW,WAAc,WAAsBA,EAAW,UAC5D,OAAOA,EAAW,QAAW,aAAsBA,EAAW,SAErE,CAACC,GAAaF,GAAoBA,EAAiB,OAAS,MAC9DE,EAAYF,GAGd,IAAI1N,EAAyB,KAC7B,OAAI,OAAOM,EAAI,CAAG,GAAM,SAAUN,EAAUM,EAAI,CAAG,EAC1C,CAACqN,GAAc,OAAOrN,EAAI,CAAG,GAAM,SAAUN,EAAUM,EAAI,CAAG,EAC9D,OAAOA,EAAI,SAAY,aAAoBA,EAAI,SAEjD,CACL,IAAKQ,EACL,KAAA0M,EACA,MAAAC,EACA,UAAAG,EACA,QAAS5N,GAAWc,EACpB,KAAMyM,GAAQ,OAElB,MAAQ,CACN,MAAO,CAAE,IAAKzM,EAAM,QAASA,CAAA,CAC/B,CACF,CAEA,eAAsB+M,GACpBnL,EACAC,EACA,CACA,GAAI,GAACD,EAAM,QAAU,CAACA,EAAM,YACxB,EAAAA,EAAM,aAAe,EAACC,GAAA,MAAAA,EAAM,QAChC,CAAKA,GAAA,MAAAA,EAAM,QAAOD,EAAM,YAAc,IACtCA,EAAM,UAAY,KAClB,GAAI,CAQF,MAAM4B,EAPM,MAAM5B,EAAM,OAAO,QAAQ,YAAa,CAClD,OAAQC,GAAA,MAAAA,EAAM,MAAQ,OAAYD,EAAM,YAAc,OACtD,MAAOA,EAAM,UACb,SAAUA,EAAM,aAChB,KAAMA,EAAM,UAAY,OACxB,YAAa6J,MAA2B,OACzC,EAaKuB,GAHQ,MAAM,QAAQxJ,EAAQ,KAAK,EACpCA,EAAQ,MAAM,OAAQxD,GAAS,OAAOA,GAAS,QAAQ,EACxD,IACkB,IAAIwM,EAAY,EAChCS,EAAc,GAAQpL,GAAA,MAAAA,EAAM,OAAS2B,EAAQ,OAAS5B,EAAM,YAAc,MAChFA,EAAM,YAAcqL,EAChBD,EACA,CAAC,GAAGpL,EAAM,YAAa,GAAGoL,CAAO,EAAE,MAAM,CAACb,EAAgB,EAC1D,OAAO3I,EAAQ,QAAW,WAAU5B,EAAM,WAAa4B,EAAQ,QAC/D,OAAOA,EAAQ,MAAS,WAAU5B,EAAM,SAAW4B,EAAQ,MAC3D,MAAM,QAAQA,EAAQ,cAAc,IACtC5B,EAAM,mBAAqB4B,EAAQ,eAAe,OAC/C7N,GAAM,OAAOA,GAAM,WAGxBiM,EAAM,cAAgB,EAAQ4B,EAAQ,UACtC5B,EAAM,gBAAkB,KAAK,KAC/B,OAASO,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACON,GAAA,MAAAA,EAAM,QAAOD,EAAM,YAAc,GACxC,EACF,iIC1HA,MAAMsL,GAAgB,CAClB,EAAG,oEACH,EAAG,oEACH,EAAG,GACH,EAAG,oEACH,EAAG,oEACH,GAAI,oEACJ,GAAI,mEACR,EACM,CAAE,EAAGtW,GAAG,EAAGE,GAAG,GAAAqW,GAAI,GAAAC,GAAI,EAAGpX,GAAI,EAAGqX,GAAE,EAAE9X,EAAC,EAAK2X,GAC1CjW,GAAI,GACJqW,GAAK,GAILC,GAAe,IAAI9H,IAAS,CAC1B,sBAAuB,OAAS,OAAO,MAAM,mBAAsB,YACnE,MAAM,kBAAkB,GAAGA,CAAI,CAEvC,EACMtD,GAAM,CAACjD,EAAU,KAAO,CAC1B,MAAMpK,EAAI,IAAI,MAAMoK,CAAO,EAC3B,MAAAqO,GAAazY,EAAGqN,EAAG,EACbrN,CACV,EACM0Y,GAASrY,GAAM,OAAOA,GAAM,SAC5BsY,GAAS1Y,GAAM,OAAOA,GAAM,SAC5B2Y,GAAWlY,GAAMA,aAAa,YAAe,YAAY,OAAOA,CAAC,GAAKA,EAAE,YAAY,OAAS,aAE7FmY,GAAS,CAAC1V,EAAO2V,EAAQC,EAAQ,KAAO,CAC1C,MAAMxM,EAAQqM,GAAQzV,CAAK,EACrB6V,EAAM7V,GAAA,YAAAA,EAAO,OACb8V,EAAWH,IAAW,OAC5B,GAAI,CAACvM,GAAU0M,GAAYD,IAAQF,EAAS,CACxC,MAAMI,EAASH,GAAS,IAAIA,CAAK,KAC3BI,EAAQF,EAAW,cAAcH,CAAM,GAAK,GAC5CM,EAAM7M,EAAQ,UAAUyM,CAAG,GAAK,QAAQ,OAAO7V,CAAK,GAC1DkK,GAAI6L,EAAS,sBAAwBC,EAAQ,SAAWC,CAAG,CAC/D,CACA,OAAOjW,CACX,EAEMkW,GAAOL,GAAQ,IAAI,WAAWA,CAAG,EACjCM,GAAQC,GAAQ,WAAW,KAAKA,CAAG,EACnCC,GAAO,CAACnZ,EAAG2U,IAAQ3U,EAAE,SAAS,EAAE,EAAE,SAAS2U,EAAK,GAAG,EACnDyE,GAAczY,GAAM,MAAM,KAAK6X,GAAO7X,CAAC,CAAC,EACzC,IAAKhB,GAAMwZ,GAAKxZ,EAAG,CAAC,CAAC,EACrB,KAAK,EAAE,EACN6B,GAAI,CAAE,GAAI,GAAI,GAAI,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,EAAG,GAAG,EACjD6X,GAAOC,GAAO,CAChB,GAAIA,GAAM9X,GAAE,IAAM8X,GAAM9X,GAAE,GACtB,OAAO8X,EAAK9X,GAAE,GAClB,GAAI8X,GAAM9X,GAAE,GAAK8X,GAAM9X,GAAE,EACrB,OAAO8X,GAAM9X,GAAE,EAAI,IACvB,GAAI8X,GAAM9X,GAAE,GAAK8X,GAAM9X,GAAE,EACrB,OAAO8X,GAAM9X,GAAE,EAAI,GAE3B,EACM+X,GAAczV,GAAQ,CACxB,MAAMnE,EAAI,cACV,GAAI,CAAC2Y,GAAMxU,CAAG,EACV,OAAOkJ,GAAIrN,CAAC,EAChB,MAAM6Z,EAAK1V,EAAI,OACT2V,EAAKD,EAAK,EAChB,GAAIA,EAAK,EACL,OAAOxM,GAAIrN,CAAC,EAChB,MAAM+Z,EAAQV,GAAIS,CAAE,EACpB,QAASE,EAAK,EAAGC,EAAK,EAAGD,EAAKF,EAAIE,IAAMC,GAAM,EAAG,CAE7C,MAAMC,EAAKR,GAAIvV,EAAI,WAAW8V,CAAE,CAAC,EAC3BE,EAAKT,GAAIvV,EAAI,WAAW8V,EAAK,CAAC,CAAC,EACrC,GAAIC,IAAO,QAAaC,IAAO,OAC3B,OAAO9M,GAAIrN,CAAC,EAChB+Z,EAAMC,CAAE,EAAIE,EAAK,GAAKC,CAC1B,CACA,OAAOJ,CACX,EACMK,GAAK,IAAM,mCAAY,OACvBC,GAAS,WAAM,QAAAnZ,EAAAkZ,GAAE,IAAF,YAAAlZ,EAAM,SAAUmM,GAAI,kDAAkD,GAErFiN,GAAc,IAAIC,IAAS,CAC7B,MAAMna,EAAIiZ,GAAIkB,EAAK,OAAO,CAACC,EAAK9Z,IAAM8Z,EAAM3B,GAAOnY,CAAC,EAAE,OAAQ,CAAC,CAAC,EAChE,IAAIsU,EAAM,EACV,OAAAuF,EAAK,QAAQ7Z,GAAK,CAAEN,EAAE,IAAIM,EAAGsU,CAAG,EAAGA,GAAOtU,EAAE,MAAQ,CAAC,EAC9CN,CACX,EAEMqa,GAAc,CAACzB,EAAM7W,KACbiY,GAAE,EACH,gBAAgBf,GAAIL,CAAG,CAAC,EAE/B0B,GAAM,OACNC,GAAc,CAACta,EAAG6I,EAAKI,EAAKoC,EAAM,6BAAgCgN,GAAMrY,CAAC,GAAK6I,GAAO7I,GAAKA,EAAIiJ,EAAMjJ,EAAIgN,GAAI3B,CAAG,EAE/GpJ,EAAI,CAAC5B,EAAGM,EAAIc,KAAM,CACpB,MAAM1B,EAAIM,EAAIM,EACd,OAAOZ,GAAK,GAAKA,EAAIY,EAAIZ,CAC7B,EACMwa,GAAQla,GAAM4B,EAAE5B,EAAGsB,EAAC,EAGpB6Y,GAAS,CAACC,EAAKC,IAAO,EACpBD,IAAQ,IAAMC,GAAM,KACpB1N,GAAI,gBAAkByN,EAAM,QAAUC,CAAE,EACzC,IAACra,EAAI4B,EAAEwY,EAAKC,CAAE,EAAG/Z,EAAI+Z,EAAIrZ,EAAI,GAAYZ,EAAI,GAChD,KAAOJ,IAAM,IAAI,CACb,MAAMsa,EAAIha,EAAIN,EAAG,EAAIM,EAAIN,EACnBa,EAAIG,EAAIZ,EAAIka,EAClBha,EAAIN,EAAGA,EAAI,EAAGgB,EAAIZ,EAAUA,EAAIS,CACpC,CACA,OAAOP,IAAM,GAAKsB,EAAEZ,EAAGqZ,CAAE,EAAI1N,GAAI,YAAY,CACjD,EACM4N,GAAYzX,GAAS,CAEvB,MAAM0X,EAAKC,GAAO3X,CAAI,EACtB,OAAI,OAAO0X,GAAO,YACd7N,GAAI,UAAY7J,EAAO,UAAU,EAC9B0X,CACX,EAEME,GAAUxa,GAAOA,aAAaya,GAAQza,EAAIyM,GAAI,gBAAgB,EAG9DiO,GAAO,IAAM,KAEbC,GAAN,MAAMA,EAAM,CAOR,YAAYC,EAAGC,EAAGhZ,EAAGiZ,EAAG,CAJxBC,EAAA,UACAA,EAAA,UACAA,EAAA,UACAA,EAAA,UAEI,MAAMrS,EAAMgS,GACZ,KAAK,EAAIX,GAAYa,EAAG,GAAIlS,CAAG,EAC/B,KAAK,EAAIqR,GAAYc,EAAG,GAAInS,CAAG,EAC/B,KAAK,EAAIqR,GAAYlY,EAAG,GAAI6G,CAAG,EAC/B,KAAK,EAAIqR,GAAYe,EAAG,GAAIpS,CAAG,EAC/B,OAAO,OAAO,IAAI,CACtB,CACA,OAAO,OAAQ,CACX,OAAO8O,EACX,CACA,OAAO,WAAWxX,EAAG,CACjB,OAAO,IAAI2a,GAAM3a,EAAE,EAAGA,EAAE,EAAG,GAAI0B,EAAE1B,EAAE,EAAIA,EAAE,CAAC,CAAC,CAC/C,CAEA,OAAO,UAAUuD,EAAKyX,EAAS,GAAO,CAClC,MAAM/a,EAAI0X,GAEJsD,EAASvC,GAAKT,GAAO1U,EAAKhC,EAAC,CAAC,EAE5B2Z,EAAW3X,EAAI,EAAE,EACvB0X,EAAO,EAAE,EAAIC,EAAW,KACxB,MAAM1a,EAAI2a,GAAaF,CAAM,EAI7BlB,GAAYvZ,EAAG,GADHwa,EAASN,GAAOxZ,EACN,EACtB,MAAMka,EAAK1Z,EAAElB,EAAIA,CAAC,EACZN,EAAIwB,EAAE0Z,EAAK,EAAE,EACb3a,EAAIiB,EAAEzB,EAAImb,EAAK,EAAE,EACvB,GAAI,CAAE,QAAAC,EAAS,MAAOva,CAAC,EAAKwa,GAAQpb,EAAGO,CAAC,EACnC4a,GACD5O,GAAI,uBAAuB,EAC/B,MAAM8O,GAAUza,EAAI,MAAQ,GACtB0a,GAAiBN,EAAW,OAAU,EAC5C,MAAI,CAACF,GAAUla,IAAM,IAAM0a,GACvB/O,GAAI,gCAAgC,EACpC+O,IAAkBD,IAClBza,EAAIY,EAAE,CAACZ,CAAC,GACL,IAAI6Z,GAAM7Z,EAAGN,EAAG,GAAIkB,EAAEZ,EAAIN,CAAC,CAAC,CACvC,CACA,OAAO,QAAQ+C,EAAKyX,EAAQ,CACxB,OAAOL,GAAM,UAAU3B,GAAWzV,CAAG,EAAGyX,CAAM,CAClD,CACA,IAAI,GAAI,CACJ,OAAO,KAAK,SAAQ,EAAG,CAC3B,CACA,IAAI,GAAI,CACJ,OAAO,KAAK,SAAQ,EAAG,CAC3B,CAEA,gBAAiB,CACb,MAAMlb,EAAIQ,GACJL,EAAI0X,GACJ3X,EAAI,KACV,GAAIA,EAAE,IAAG,EACL,OAAOyM,GAAI,iBAAiB,EAGhC,KAAM,CAAE,EAAAmO,EAAG,EAAAC,EAAG,EAAAhZ,EAAG,EAAAiZ,CAAC,EAAK9a,EACjByb,EAAK/Z,EAAEkZ,EAAIA,CAAC,EACZc,EAAKha,EAAEmZ,EAAIA,CAAC,EACZc,EAAKja,EAAEG,EAAIA,CAAC,EACZ+Z,EAAKla,EAAEia,EAAKA,CAAE,EACdE,EAAMna,EAAE+Z,EAAK3b,CAAC,EACdgc,EAAOpa,EAAEia,EAAKja,EAAEma,EAAMH,CAAE,CAAC,EACzBK,EAAQra,EAAEka,EAAKla,EAAEzB,EAAIyB,EAAE+Z,EAAKC,CAAE,CAAC,CAAC,EACtC,GAAII,IAASC,EACT,OAAOtP,GAAI,uCAAuC,EAEtD,MAAMuP,EAAKta,EAAEkZ,EAAIC,CAAC,EACZoB,EAAKva,EAAEG,EAAIiZ,CAAC,EAClB,OAAIkB,IAAOC,EACAxP,GAAI,uCAAuC,EAC/C,IACX,CAEA,OAAOyP,EAAO,CACV,KAAM,CAAE,EAAGC,EAAI,EAAGC,EAAI,EAAGC,CAAE,EAAK,KAC1B,CAAE,EAAGZ,EAAI,EAAGC,EAAI,EAAGC,CAAE,EAAKnB,GAAO0B,CAAK,EACtCI,EAAO5a,EAAEya,EAAKR,CAAE,EAChBY,EAAO7a,EAAE+Z,EAAKY,CAAE,EAChBG,EAAO9a,EAAE0a,EAAKT,CAAE,EAChBc,EAAO/a,EAAEga,EAAKW,CAAE,EACtB,OAAOC,IAASC,GAAQC,IAASC,CACrC,CACA,KAAM,CACF,OAAO,KAAK,OAAOnb,EAAC,CACxB,CAEA,QAAS,CACL,OAAO,IAAIqZ,GAAMjZ,EAAE,CAAC,KAAK,CAAC,EAAG,KAAK,EAAG,KAAK,EAAGA,EAAE,CAAC,KAAK,CAAC,CAAC,CAC3D,CAEA,QAAS,CACL,KAAM,CAAE,EAAGya,EAAI,EAAGC,EAAI,EAAGC,CAAE,EAAK,KAC1Bvc,EAAIQ,GAEJU,EAAIU,EAAEya,EAAKA,CAAE,EACbla,EAAIP,EAAE0a,EAAKA,CAAE,EACbnb,EAAIS,EAAE,GAAKA,EAAE2a,EAAKA,CAAE,CAAC,EACrBna,EAAIR,EAAE5B,EAAIkB,CAAC,EACX0b,EAAOP,EAAKC,EACZrb,EAAIW,EAAEA,EAAEgb,EAAOA,CAAI,EAAI1b,EAAIiB,CAAC,EAC5B0a,EAAIza,EAAID,EACR2a,EAAID,EAAI1b,EACRQ,EAAIS,EAAID,EACR4a,EAAKnb,EAAEX,EAAI6b,CAAC,EACZE,EAAKpb,EAAEib,EAAIlb,CAAC,EACZsb,EAAKrb,EAAEX,EAAIU,CAAC,EACZub,EAAKtb,EAAEkb,EAAID,CAAC,EAClB,OAAO,IAAIhC,GAAMkC,EAAIC,EAAIE,EAAID,CAAE,CACnC,CAEA,IAAIb,EAAO,CACP,KAAM,CAAE,EAAGC,EAAI,EAAGC,EAAI,EAAGC,EAAI,EAAGY,CAAE,EAAK,KACjC,CAAE,EAAGxB,EAAI,EAAGC,EAAI,EAAGC,EAAI,EAAGuB,CAAE,EAAK1C,GAAO0B,CAAK,EAC7Cpc,EAAIQ,GACJL,EAAI0X,GAEJ3W,EAAIU,EAAEya,EAAKV,CAAE,EACbxZ,EAAIP,EAAE0a,EAAKV,CAAE,EACbza,EAAIS,EAAEub,EAAKhd,EAAIid,CAAE,EACjBhb,EAAIR,EAAE2a,EAAKV,CAAE,EACb5a,EAAIW,GAAGya,EAAKC,IAAOX,EAAKC,GAAM1a,EAAIiB,CAAC,EACnC2a,EAAIlb,EAAEQ,EAAIjB,CAAC,EACX0b,EAAIjb,EAAEQ,EAAIjB,CAAC,EACXQ,EAAIC,EAAEO,EAAInC,EAAIkB,CAAC,EACf6b,EAAKnb,EAAEX,EAAI6b,CAAC,EACZE,EAAKpb,EAAEib,EAAIlb,CAAC,EACZsb,EAAKrb,EAAEX,EAAIU,CAAC,EACZub,EAAKtb,EAAEkb,EAAID,CAAC,EAClB,OAAO,IAAIhC,GAAMkC,EAAIC,EAAIE,EAAID,CAAE,CACnC,CACA,SAASb,EAAO,CACZ,OAAO,KAAK,IAAI1B,GAAO0B,CAAK,EAAE,OAAM,CAAE,CAC1C,CAQA,SAASzc,EAAG0d,EAAO,GAAM,CACrB,GAAI,CAACA,IAAS1d,IAAM,IAAM,KAAK,IAAG,GAC9B,OAAO6B,GAEX,GADAyY,GAAYta,EAAG,GAAI2B,EAAC,EAChB3B,IAAM,GACN,OAAO,KACX,GAAI,KAAK,OAAOkd,EAAC,EACb,OAAOS,GAAK3d,CAAC,EAAE,EAEnB,IAAIO,EAAIsB,GACJnB,EAAIwc,GACR,QAAS1c,EAAI,KAAMR,EAAI,GAAIQ,EAAIA,EAAE,OAAM,EAAIR,IAAM,GAGzCA,EAAI,GACJO,EAAIA,EAAE,IAAIC,CAAC,EACNkd,IACLhd,EAAIA,EAAE,IAAIF,CAAC,GAEnB,OAAOD,CACX,CACA,eAAeqd,EAAQ,CACnB,OAAO,KAAK,SAASA,EAAQ,EAAK,CACtC,CAEA,UAAW,CACP,KAAM,CAAE,EAAAzC,EAAG,EAAAC,EAAG,EAAAhZ,CAAC,EAAK,KAEpB,GAAI,KAAK,OAAOP,EAAC,EACb,MAAO,CAAE,EAAG,GAAI,EAAG,EAAE,EACzB,MAAMgc,EAAKrD,GAAOpY,EAAGX,EAAC,EAElBQ,EAAEG,EAAIyb,CAAE,IAAM,IACd7Q,GAAI,iBAAiB,EAEzB,MAAM3L,EAAIY,EAAEkZ,EAAI0C,CAAE,EACZ9c,EAAIkB,EAAEmZ,EAAIyC,CAAE,EAClB,MAAO,CAAE,EAAAxc,EAAG,EAAAN,CAAC,CACjB,CACA,SAAU,CACN,KAAM,CAAE,EAAAM,EAAG,EAAAN,CAAC,EAAK,KAAK,eAAc,EAAG,SAAQ,EACzCJ,EAAImd,GAAW/c,CAAC,EAEtB,OAAAJ,EAAE,EAAE,GAAKU,EAAI,GAAK,IAAO,EAClBV,CACX,CACA,OAAQ,CACJ,OAAOyY,GAAW,KAAK,SAAS,CACpC,CACA,eAAgB,CACZ,OAAO,KAAK,SAASiB,GAAIja,EAAC,EAAG,EAAK,CACtC,CACA,cAAe,CACX,OAAO,KAAK,cAAa,EAAG,IAAG,CACnC,CACA,eAAgB,CAEZ,IAAIG,EAAI,KAAK,SAASoB,GAAI,GAAI,EAAK,EAAE,OAAM,EAC3C,OAAIA,GAAI,KACJpB,EAAIA,EAAE,IAAI,IAAI,GACXA,EAAE,IAAG,CAChB,CACJ,EApNI+a,EADEJ,GACK,QACPI,EAFEJ,GAEK,QAFX,IAAMF,GAANE,GAuNA,MAAMgC,GAAI,IAAIlC,GAAMhD,GAAIC,GAAI,GAAIhW,EAAE+V,GAAKC,EAAE,CAAC,EAEpCpW,GAAI,IAAImZ,GAAM,GAAI,GAAI,GAAI,EAAE,EAElCA,GAAM,KAAOkC,GACblC,GAAM,KAAOnZ,GACb,MAAMic,GAAcrD,GAAQlB,GAAWJ,GAAKmB,GAAYG,EAAK,GAAIQ,EAAI,EAAG9C,EAAE,CAAC,EAAE,QAAO,EAC9EuD,GAAgB/a,GAAM0Z,GAAI,KAAOjB,GAAWH,GAAKT,GAAO7X,CAAC,CAAC,EAAE,QAAO,CAAE,CAAC,EACtEod,GAAO,CAAC1c,EAAG2c,IAAU,CAEvB,IAAIje,EAAIsB,EACR,KAAO2c,KAAU,IACbje,GAAKA,EACLA,GAAK0B,GAET,OAAO1B,CACX,EAEMke,GAAe5c,GAAM,CAEvB,MAAM6c,EADM7c,EAAIA,EAAKI,GACJJ,EAAKI,GAChB0c,EAAMJ,GAAKG,EAAI,EAAE,EAAIA,EAAMzc,GAC3B2c,EAAML,GAAKI,EAAI,EAAE,EAAI9c,EAAKI,GAC1B4c,EAAON,GAAKK,EAAI,EAAE,EAAIA,EAAM3c,GAC5B6c,EAAOP,GAAKM,EAAK,GAAG,EAAIA,EAAO5c,GAC/B8c,EAAOR,GAAKO,EAAK,GAAG,EAAIA,EAAO7c,GAC/B+c,EAAOT,GAAKQ,EAAK,GAAG,EAAIA,EAAO9c,GAC/Bgd,EAAQV,GAAKS,EAAK,GAAG,EAAIA,EAAO/c,GAChCid,EAAQX,GAAKU,EAAM,GAAG,EAAID,EAAO/c,GACjCkd,EAAQZ,GAAKW,EAAM,GAAG,EAAIL,EAAO5c,GAEvC,MAAO,CAAE,UADUsc,GAAKY,EAAM,EAAE,EAAItd,EAAKI,GACrB,GAAAyc,CAAE,CAC1B,EACMU,GAAM,oEAGN/C,GAAU,CAACpb,EAAGO,IAAM,CACtB,MAAM6d,EAAK5c,EAAEjB,EAAIA,EAAIA,CAAC,EAChB8d,EAAK7c,EAAE4c,EAAKA,EAAK7d,CAAC,EAClB+d,EAAMd,GAAYxd,EAAIqe,CAAE,EAAE,UAChC,IAAIzd,EAAIY,EAAExB,EAAIoe,EAAKE,CAAG,EACtB,MAAMC,EAAM/c,EAAEjB,EAAIK,EAAIA,CAAC,EACjB4d,EAAQ5d,EACR6d,EAAQjd,EAAEZ,EAAIud,EAAG,EACjBO,EAAWH,IAAQve,EACnB2e,EAAWJ,IAAQ/c,EAAE,CAACxB,CAAC,EACvB4e,EAASL,IAAQ/c,EAAE,CAACxB,EAAIme,EAAG,EACjC,OAAIO,IACA9d,EAAI4d,IACJG,GAAYC,KACZhe,EAAI6d,IACHjd,EAAEZ,CAAC,EAAI,MAAQ,KAChBA,EAAIY,EAAE,CAACZ,CAAC,GACL,CAAE,QAAS8d,GAAYC,EAAU,MAAO/d,CAAC,CACpD,EAEMie,GAAWC,GAAShF,GAAKmB,GAAa6D,CAAI,CAAC,EAG3CC,GAAU,IAAIte,IAAM4Z,GAAO,YAAYb,GAAY,GAAG/Y,CAAC,CAAC,EACxDue,GAAU,IAAIve,IAAM0Z,GAAS,QAAQ,EAAEX,GAAY,GAAG/Y,CAAC,CAAC,EAExDwe,GAAaC,GAAW,CAE1B,MAAMC,EAAOD,EAAO,MAAM,EAAG7d,EAAC,EAC9B8d,EAAK,CAAC,GAAK,IACXA,EAAK,EAAE,GAAK,IACZA,EAAK,EAAE,GAAK,GACZ,MAAM/G,EAAS8G,EAAO,MAAM7d,GAAGqW,EAAE,EAC3ByF,EAAS0B,GAAQM,CAAI,EACrBC,EAAQ3C,GAAE,SAASU,CAAM,EACzBkC,EAAaD,EAAM,UACzB,MAAO,CAAE,KAAAD,EAAM,OAAA/G,EAAQ,OAAA+E,EAAQ,MAAAiC,EAAO,WAAAC,CAAU,CACpD,EAEMC,GAA6BC,GAAcR,GAAQhH,GAAOwH,EAAWle,EAAC,CAAC,EAAE,KAAK4d,EAAS,EACvFO,GAAwBD,GAAcN,GAAUD,GAAQjH,GAAOwH,EAAWle,EAAC,CAAC,CAAC,EAE7Eoe,GAAqBF,GAAcD,GAA0BC,CAAS,EAAE,KAAMzf,GAAMA,EAAE,UAAU,EAGhG4f,GAAevT,GAAQ4S,GAAQ5S,EAAI,QAAQ,EAAE,KAAKA,EAAI,MAAM,EAG5DwT,GAAQ,CAAC,EAAGC,EAAQhV,IAAQ,CAC9B,KAAM,CAAE,WAAY5J,EAAG,OAAQ,CAAC,EAAK,EAC/B1B,EAAIuf,GAAQe,CAAM,EAClBne,EAAIgb,GAAE,SAASnd,CAAC,EAAE,QAAO,EAO/B,MAAO,CAAE,SANQka,GAAY/X,EAAGT,EAAG4J,CAAG,EAMnB,OALHsU,GAAW,CAEvB,MAAMzf,EAAIqa,GAAKxa,EAAIuf,GAAQK,CAAM,EAAI,CAAC,EACtC,OAAOnH,GAAOyB,GAAY/X,EAAG4b,GAAW5d,CAAC,CAAC,EAAGiY,EAAE,CACnD,CACyB,CAC7B,EAKMmI,GAAY,MAAOvW,EAASiW,IAAc,CAC5C,MAAM9e,EAAIsX,GAAOzO,CAAO,EAClBpK,EAAI,MAAMogB,GAA0BC,CAAS,EAC7CK,EAAS,MAAMb,GAAQ7f,EAAE,OAAQuB,CAAC,EACxC,OAAOif,GAAYC,GAAMzgB,EAAG0gB,EAAQnf,CAAC,CAAC,CAC1C,EAuDM4Z,GAAS,CACX,YAAa,MAAO/Q,GAAY,CAC5B,MAAMnK,EAAIoa,GAAM,EACV9Y,EAAI+Y,GAAYlQ,CAAO,EAC7B,OAAOiP,GAAI,MAAMpZ,EAAE,OAAO,UAAWsB,EAAE,MAAM,CAAC,CAClD,EACA,OAAQ,MACZ,EAGMqf,GAAkB,CAACC,EAAOpG,GAAYtY,EAAC,IAAM0e,EAY7CC,GAAQ,CACV,0BAA2BV,GAC3B,qBAAsBE,GACtB,gBAAiBM,EACrB,EAGMG,GAAI,EACJC,GAAa,IACbC,GAAW,KAAK,KAAKD,GAAaD,EAAC,EAAI,EACvCG,GAAc,IAAMH,GAAI,GACxBI,GAAa,IAAM,CACrB,MAAMC,EAAS,GACf,IAAIxgB,EAAI2c,GACJvc,EAAIJ,EACR,QAASygB,EAAI,EAAGA,EAAIJ,GAAUI,IAAK,CAC/BrgB,EAAIJ,EACJwgB,EAAO,KAAKpgB,CAAC,EACb,QAASV,EAAI,EAAGA,EAAI4gB,GAAa5gB,IAC7BU,EAAIA,EAAE,IAAIJ,CAAC,EACXwgB,EAAO,KAAKpgB,CAAC,EAEjBJ,EAAII,EAAE,OAAM,CAChB,CACA,OAAOogB,CACX,EACA,IAAIE,GAEJ,MAAMC,GAAQ,CAACC,EAAK5gB,IAAM,CACtB,MAAM,EAAIA,EAAE,OAAM,EAClB,OAAO4gB,EAAM,EAAI5gB,CACrB,EAYMod,GAAQ3d,GAAM,CAChB,MAAMohB,EAAOH,KAAUA,GAAQH,GAAU,GACzC,IAAIvgB,EAAIsB,GACJnB,EAAIwc,GACR,MAAMmE,EAAU,GAAKX,GACfY,EAASD,EACTE,EAAOlH,GAAIgH,EAAU,CAAC,EACtBG,EAAUnH,GAAIqG,EAAC,EACrB,QAASM,EAAI,EAAGA,EAAIJ,GAAUI,IAAK,CAC/B,IAAIS,EAAQ,OAAOzhB,EAAIuhB,CAAI,EAC3BvhB,IAAMwhB,EAMFC,EAAQZ,KACRY,GAASH,EACTthB,GAAK,IAET,MAAM0hB,EAAMV,EAAIH,GACVc,EAAOD,EACPE,EAAOF,EAAM,KAAK,IAAID,CAAK,EAAI,EAC/BI,EAASb,EAAI,IAAM,EACnBc,EAAQL,EAAQ,EAClBA,IAAU,EAEV/gB,EAAIA,EAAE,IAAIwgB,GAAMW,EAAQT,EAAKO,CAAI,CAAC,CAAC,EAGnCphB,EAAIA,EAAE,IAAI2gB,GAAMY,EAAOV,EAAKQ,CAAI,CAAC,CAAC,CAE1C,CACA,OAAI5hB,IAAM,IACNgN,GAAI,cAAc,EACf,CAAE,EAAAzM,EAAG,EAAAG,EAChB,ECnmBMqhB,GAAc,gCAEpB,SAASC,GAAgB9V,EAA2B,CAClD,IAAI+V,EAAS,GACb,UAAWC,KAAQhW,EAAO+V,GAAU,OAAO,aAAaC,CAAI,EAC5D,OAAO,KAAKD,CAAM,EAAE,QAAQ,MAAO,GAAG,EAAE,QAAQ,MAAO,GAAG,EAAE,QAAQ,OAAQ,EAAE,CAChF,CAEA,SAASE,GAAgBjf,EAA2B,CAClD,MAAMkf,EAAalf,EAAM,QAAQ,KAAM,GAAG,EAAE,QAAQ,KAAM,GAAG,EACvDmf,EAASD,EAAa,IAAI,QAAQ,EAAKA,EAAW,OAAS,GAAM,CAAC,EAClEH,EAAS,KAAKI,CAAM,EACpBC,EAAM,IAAI,WAAWL,EAAO,MAAM,EACxC,QAAShiB,EAAI,EAAGA,EAAIgiB,EAAO,OAAQhiB,GAAK,EAAGqiB,EAAIriB,CAAC,EAAIgiB,EAAO,WAAWhiB,CAAC,EACvE,OAAOqiB,CACT,CAEA,SAASlJ,GAAWlN,EAA2B,CAC7C,OAAO,MAAM,KAAKA,CAAK,EACpB,IAAKvL,GAAMA,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,CAAC,EAC1C,KAAK,EAAE,CACZ,CAEA,eAAe4hB,GAAqBC,EAAwC,CAC1E,MAAMjD,EAAO,MAAM,OAAO,OAAO,OAAO,UAAWiD,CAAS,EAC5D,OAAOpJ,GAAW,IAAI,WAAWmG,CAAI,CAAC,CACxC,CAEA,eAAekD,IAA4C,CACzD,MAAMC,EAAajC,GAAM,kBACnB+B,EAAY,MAAMtC,GAAkBwC,CAAU,EAEpD,MAAO,CACL,SAFe,MAAMH,GAAqBC,CAAS,EAGnD,UAAWR,GAAgBQ,CAAS,EACpC,WAAYR,GAAgBU,CAAU,EAE1C,CAEA,eAAsBC,IAAsD,CAC1E,GAAI,CACF,MAAM5c,EAAM,aAAa,QAAQgc,EAAW,EAC5C,GAAIhc,EAAK,CACP,MAAMkI,EAAS,KAAK,MAAMlI,CAAG,EAC7B,IACEkI,GAAA,YAAAA,EAAQ,WAAY,GACpB,OAAOA,EAAO,UAAa,UAC3B,OAAOA,EAAO,WAAc,UAC5B,OAAOA,EAAO,YAAe,SAC7B,CACA,MAAM2U,EAAY,MAAML,GAAqBJ,GAAgBlU,EAAO,SAAS,CAAC,EAC9E,GAAI2U,IAAc3U,EAAO,SAAU,CACjC,MAAM4U,EAA0B,CAC9B,GAAG5U,EACH,SAAU2U,CAAA,EAEZ,oBAAa,QAAQb,GAAa,KAAK,UAAUc,CAAO,CAAC,EAClD,CACL,SAAUD,EACV,UAAW3U,EAAO,UAClB,WAAYA,EAAO,WAEvB,CACA,MAAO,CACL,SAAUA,EAAO,SACjB,UAAWA,EAAO,UAClB,WAAYA,EAAO,WAEvB,CACF,CACF,MAAQ,CAER,CAEA,MAAM6U,EAAW,MAAML,GAAA,EACjBM,EAAyB,CAC7B,QAAS,EACT,SAAUD,EAAS,SACnB,UAAWA,EAAS,UACpB,WAAYA,EAAS,WACrB,YAAa,KAAK,KAAI,EAExB,oBAAa,QAAQf,GAAa,KAAK,UAAUgB,CAAM,CAAC,EACjDD,CACT,CAEA,eAAsBE,GAAkBC,EAA6B5U,EAAiB,CACpF,MAAMvH,EAAMqb,GAAgBc,CAAmB,EACzC/S,EAAO,IAAI,cAAc,OAAO7B,CAAO,EACvC6U,EAAM,MAAM5C,GAAUpQ,EAAMpJ,CAAG,EACrC,OAAOkb,GAAgBkB,CAAG,CAC5B,CC9FA,MAAMnB,GAAc,4BAEpB,SAASoB,GAAcnZ,EAAsB,CAC3C,OAAOA,EAAK,MACd,CAEA,SAASoZ,GAAgBC,EAAwC,CAC/D,GAAI,CAAC,MAAM,QAAQA,CAAM,QAAU,GACnC,MAAMf,MAAU,IAChB,UAAWgB,KAASD,EAAQ,CAC1B,MAAMrgB,EAAUsgB,EAAM,OAClBtgB,GAASsf,EAAI,IAAItf,CAAO,CAC9B,CACA,MAAO,CAAC,GAAGsf,CAAG,EAAE,MAClB,CAEA,SAASiB,IAAoC,CAC3C,GAAI,CACF,MAAMxd,EAAM,OAAO,aAAa,QAAQgc,EAAW,EACnD,GAAI,CAAChc,EAAK,OAAO,KACjB,MAAMkI,EAAS,KAAK,MAAMlI,CAAG,EAG7B,MAFI,CAACkI,GAAUA,EAAO,UAAY,GAC9B,CAACA,EAAO,UAAY,OAAOA,EAAO,UAAa,UAC/C,CAACA,EAAO,QAAU,OAAOA,EAAO,QAAW,SAAiB,KACzDA,CACT,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAASuV,GAAWC,EAAwB,CAC1C,GAAI,CACF,OAAO,aAAa,QAAQ1B,GAAa,KAAK,UAAU0B,CAAK,CAAC,CAChE,MAAQ,CAER,CACF,CAEO,SAASC,GAAoBhV,EAGT,CACzB,MAAM+U,EAAQF,GAAA,EACd,GAAI,CAACE,GAASA,EAAM,WAAa/U,EAAO,SAAU,OAAO,KACzD,MAAM1E,EAAOmZ,GAAczU,EAAO,IAAI,EAChCO,EAAQwU,EAAM,OAAOzZ,CAAI,EAC/B,MAAI,CAACiF,GAAS,OAAOA,EAAM,OAAU,SAAiB,KAC/CA,CACT,CAEO,SAAS0U,GAAqBjV,EAKjB,CAClB,MAAM1E,EAAOmZ,GAAczU,EAAO,IAAI,EAChCpI,EAAwB,CAC5B,QAAS,EACT,SAAUoI,EAAO,SACjB,OAAQ,EAAC,EAELkV,EAAWL,GAAA,EACbK,GAAYA,EAAS,WAAalV,EAAO,WAC3CpI,EAAK,OAAS,CAAE,GAAGsd,EAAS,SAE9B,MAAM3U,EAAyB,CAC7B,MAAOP,EAAO,MACd,KAAA1E,EACA,OAAQoZ,GAAgB1U,EAAO,MAAM,EACrC,YAAa,KAAK,KAAI,EAExB,OAAApI,EAAK,OAAO0D,CAAI,EAAIiF,EACpBuU,GAAWld,CAAI,EACR2I,CACT,CAEO,SAAS4U,GAAqBnV,EAA4C,CAC/E,MAAM+U,EAAQF,GAAA,EACd,GAAI,CAACE,GAASA,EAAM,WAAa/U,EAAO,SAAU,OAClD,MAAM1E,EAAOmZ,GAAczU,EAAO,IAAI,EACtC,GAAI,CAAC+U,EAAM,OAAOzZ,CAAI,EAAG,OACzB,MAAM1D,EAAO,CAAE,GAAGmd,EAAO,OAAQ,CAAE,GAAGA,EAAM,OAAO,EACnD,OAAOnd,EAAK,OAAO0D,CAAI,EACvBwZ,GAAWld,CAAI,CACjB,CCnDA,eAAsBwd,GAAYrX,EAAqBC,EAA4B,CACjF,GAAI,GAACD,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,eACV,CAAAA,EAAM,eAAiB,GAClBC,GAAA,MAAAA,EAAM,QAAOD,EAAM,aAAe,MACvC,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,mBAAoB,EAAE,EAC9DA,EAAM,YAAc,CAClB,QAAS,MAAM,QAAQG,GAAA,YAAAA,EAAK,OAAO,EAAIA,EAAK,QAAU,GACtD,OAAQ,MAAM,QAAQA,GAAA,YAAAA,EAAK,MAAM,EAAIA,EAAK,OAAS,EAAC,CAExD,OAASI,EAAK,CACPN,GAAA,MAAAA,EAAM,QAAOD,EAAM,aAAe,OAAOO,CAAG,EACnD,SACEP,EAAM,eAAiB,EACzB,EACF,CCrDA,eAAsBsX,GACpBtX,EACAC,EACA,CACA,GAAI,GAACD,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,aACV,CAAAA,EAAM,aAAe,GAChBC,GAAA,MAAAA,EAAM,QAAOD,EAAM,UAAY,MACpC,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,YAAa,EAAE,EAGvDA,EAAM,MAAQ,MAAM,QAAQG,EAAI,KAAK,EAAIA,EAAI,MAAQ,EACvD,OAASI,EAAK,CACPN,GAAA,MAAAA,EAAM,QAAOD,EAAM,UAAY,OAAOO,CAAG,EAChD,SACEP,EAAM,aAAe,EACvB,EACF,CCwBA,SAASuX,GAAwBlT,EAGxB,CAEL,MAAO,CAAE,OAAQ,qBAAsB,OAAQ,EAAC,CAKpD,CAcA,eAAsBmT,GACpBxX,EACAqE,EACA,CACA,GAAI,GAACrE,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,qBACV,CAAAA,EAAM,qBAAuB,GAC7BA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMyX,EAAMF,GAAwBlT,CAAM,EAC1C,GAAI,CAACoT,EAAK,CACRzX,EAAM,UAAY,+CAClB,MACF,CACA,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQyX,EAAI,OAAQA,EAAI,MAAM,EAC9DC,GAA2B1X,EAAOG,CAAG,CACvC,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,qBAAuB,EAC/B,EACF,CAEO,SAAS0X,GACd1X,EACAyG,EACA,CACAzG,EAAM,sBAAwByG,EACzBzG,EAAM,qBACTA,EAAM,kBAAoB8F,GAAkBW,EAAS,MAAQ,EAAE,EAEnE,CC/FA,eAAsBkR,GAAa3X,EAAsB,CACvD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,gBACV,CAAAA,EAAM,gBAAkB,GACxBA,EAAM,cAAgB,KACtBA,EAAM,eAAiB,KACvB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,kBAAmB,EAAE,EAGzD,MAAM,QAAQG,CAAG,GACnBH,EAAM,gBAAkBG,EACxBH,EAAM,eAAiBG,EAAI,SAAW,EAAI,oBAAsB,OAEhEH,EAAM,gBAAkB,GACxBA,EAAM,eAAiB,uBAE3B,OAASO,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,gBAAkB,EAC1B,EACF,CCoBA,SAAS4X,GAAgB5X,EAAoB3F,EAAaiD,EAAwB,CAChF,GAAI,CAACjD,EAAI,OAAQ,OACjB,MAAMR,EAAO,CAAE,GAAGmG,EAAM,eACpB1C,EAASzD,EAAKQ,CAAG,EAAIiD,EACpB,OAAOzD,EAAKQ,CAAG,EACpB2F,EAAM,cAAgBnG,CACxB,CAEA,SAASge,GAAgBtX,EAAc,CACrC,OAAIA,aAAe,MAAcA,EAAI,QAC9B,OAAOA,CAAG,CACnB,CAEO,SAASuX,IAA6B,CAC3C,MAAO,CAAE,KAAM,GAAI,aAAc,GAAI,WAAY,GAAI,aAAc,GACrE,CAEA,eAAsBC,GAAW/X,EAAoB1E,EAA6B,CAIhF,GAHIA,GAAA,MAAAA,EAAS,eAAiB,OAAO,KAAK0E,EAAM,aAAa,EAAE,OAAS,IACtEA,EAAM,cAAgB,IAEpB,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,cACV,CAAAA,EAAM,cAAgB,GACtBA,EAAM,YAAc,KACpB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,gBAAiB,EAAE,EAGvDG,MAAW,aAAeA,EAChC,OAASI,EAAK,CACZP,EAAM,YAAc6X,GAAgBtX,CAAG,CACzC,SACEP,EAAM,cAAgB,EACxB,EACF,CAEO,SAASgY,GACdhY,EACAiY,EACA5hB,EACA,CACA2J,EAAM,WAAa,CAAE,GAAGA,EAAM,WAAY,CAACiY,CAAQ,EAAG5hB,CAAA,CACxD,CAEA,eAAsB6hB,GACpBlY,EACAiY,EACArQ,EACA,CACA,GAAI,GAAC5H,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,cAAgBiY,EACtBjY,EAAM,YAAc,KACpB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,gBAAiB,CAAE,SAAAiY,EAAU,QAAArQ,EAAS,EACjE,MAAMmQ,GAAW/X,CAAK,EACtB4X,GAAgB5X,EAAOiY,EAAU,CAC/B,KAAM,UACN,QAASrQ,EAAU,gBAAkB,iBACtC,CACH,OAASrH,EAAK,CACZ,MAAMjD,EAAUua,GAAgBtX,CAAG,EACnCP,EAAM,YAAc1C,EACpBsa,GAAgB5X,EAAOiY,EAAU,CAC/B,KAAM,QACN,QAAA3a,CAAA,CACD,CACH,SACE0C,EAAM,cAAgB,IACxB,EACF,CAEA,eAAsBmY,GAAgBnY,EAAoBiY,EAAkB,CAC1E,GAAI,GAACjY,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,cAAgBiY,EACtBjY,EAAM,YAAc,KACpB,GAAI,CACF,MAAMoY,EAASpY,EAAM,WAAWiY,CAAQ,GAAK,GAC7C,MAAMjY,EAAM,OAAO,QAAQ,gBAAiB,CAAE,SAAAiY,EAAU,OAAAG,EAAQ,EAChE,MAAML,GAAW/X,CAAK,EACtB4X,GAAgB5X,EAAOiY,EAAU,CAC/B,KAAM,UACN,QAAS,gBACV,CACH,OAAS1X,EAAK,CACZ,MAAMjD,EAAUua,GAAgBtX,CAAG,EACnCP,EAAM,YAAc1C,EACpBsa,GAAgB5X,EAAOiY,EAAU,CAC/B,KAAM,QACN,QAAA3a,CAAA,CACD,CACH,SACE0C,EAAM,cAAgB,IACxB,EACF,CAEA,eAAsBqY,GACpBrY,EACAiY,EACAvhB,EACA4hB,EACA,CACA,GAAI,GAACtY,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,cAAgBiY,EACtBjY,EAAM,YAAc,KACpB,GAAI,CACF,MAAMxE,EAAU,MAAMwE,EAAM,OAAO,QAAQ,iBAAkB,CAC3D,KAAAtJ,EACA,UAAA4hB,EACA,UAAW,KACZ,EACD,MAAMP,GAAW/X,CAAK,EACtB4X,GAAgB5X,EAAOiY,EAAU,CAC/B,KAAM,UACN,SAASzc,GAAA,YAAAA,EAAQ,UAAW,YAC7B,CACH,OAAS+E,EAAK,CACZ,MAAMjD,EAAUua,GAAgBtX,CAAG,EACnCP,EAAM,YAAc1C,EACpBsa,GAAgB5X,EAAOiY,EAAU,CAC/B,KAAM,QACN,QAAA3a,CAAA,CACD,CACH,SACE0C,EAAM,cAAgB,IACxB,EACF,CAIA,eAAsBuY,GAAgBvY,EAAoBtJ,EAAc,CACtE,GAAI,GAACsJ,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMxE,EAAU,MAAMwE,EAAM,OAAO,QAAQ,cAAe,CAAE,KAAAtJ,EAAM,EAC9D8E,IACFwE,EAAM,YAAcxE,EACpBwE,EAAM,eAAiB,WAE3B,OAASO,EAAK,CACZP,EAAM,YAAc6X,GAAgBtX,CAAG,CACzC,CACF,CAEO,SAASiY,GAAiBxY,EAAoB,CACnDA,EAAM,YAAc,KACpBA,EAAM,eAAiB,EACzB,CAEO,SAASyY,GAAkBzY,EAAoB0Y,EAAa,CACjE1Y,EAAM,eAAiB0Y,CACzB,CAIA,eAAsBC,GAAkB3Y,EAAoB,CAM1D,GALAA,EAAM,cAAgB,GACtBA,EAAM,aAAe8X,GAAA,EACrB9X,EAAM,mBAAqB,QAC3BA,EAAM,aAAe,WACrBA,EAAM,YAAc,GAChB,GAACA,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMxE,EAAU,MAAMwE,EAAM,OAAO,QAAQ,gBAAiB,EAAE,EAG1DxE,IAAQwE,EAAM,YAAcxE,EAAO,OACzC,MAAQ,CAER,CACF,CAEO,SAASod,GAAmB5Y,EAAoB,CACrDA,EAAM,cAAgB,GACtBA,EAAM,aAAe8X,GAAA,EACrB9X,EAAM,mBAAqB,QAC3BA,EAAM,aAAe,WACrBA,EAAM,YAAc,EACtB,CAEO,SAAS6Y,GAAY7Y,EAAoB8Y,EAAmB,CACjE9Y,EAAM,aAAe,CACnB,KAAM8Y,EAAM,KACZ,aAAcA,EAAM,aACpB,WAAYA,EAAM,WAAW,IAAKxlB,IAAO,CAAE,GAAGA,CAAA,EAAI,EAClD,aAAc,IAEhB0M,EAAM,mBAAqB,OAC7B,CAEA,eAAsB+Y,GAAa/Y,EAAoB8Y,EAAmB,CACxE9Y,EAAM,aAAe,CACnB,KAAM8Y,EAAM,KACZ,aAAcA,EAAM,aACpB,WAAYA,EAAM,WAAW,IAAKxlB,IAAO,CAAE,GAAGA,CAAA,EAAI,EAClD,aAAc,IAEhB0M,EAAM,mBAAqB,YAC3B,MAAMgZ,GAAahZ,CAAK,CAC1B,CAEA,eAAsBgZ,GAAahZ,EAAoB,CACrD,GAAI,CAACA,EAAM,QAAU,CAACA,EAAM,UAAW,OACvC,MAAMgG,EAAOhG,EAAM,aACnB,GAAI,GAACgG,EAAK,KAAK,QAAU,CAACA,EAAK,aAAa,QAC5C,CAAAhG,EAAM,cAAgB,UACtBA,EAAM,YAAc,KACpB,GAAI,CACF,MAAMiZ,EAAOjT,EAAK,WACf,OAAQ1S,GAAMA,EAAE,KAAK,QAAUA,EAAE,QAAQ,MAAM,EAC/C,IAAKA,IAAO,CAAE,KAAMA,EAAE,KAAK,OAAQ,QAASA,EAAE,SAAU,EACrD4lB,EAAYlT,EAAK,KAAK,OAExBhG,EAAM,qBAAuB,aAE/B,MAAMA,EAAM,OAAO,QAAQ,gBAAiB,CAC1C,KAAMkZ,EACN,aAAclT,EAAK,aACnB,WAAYiT,EAAK,OAAS,EAAIA,EAAO,OACrC,aAAcjT,EAAK,aACpB,EACDhG,EAAM,cAAgB,GACtBA,EAAM,aAAe8X,GAAA,EACrB9X,EAAM,mBAAqB,QAC3BA,EAAM,YAAc,GACpB,MAAM+X,GAAW/X,CAAK,EACtB4X,GAAgB5X,EAAOkZ,EAAW,CAChC,KAAM,UACN,QAAS,uCACV,IAGD,MAAMlZ,EAAM,OAAO,QAAQ,mBAAoB,CAC7C,KAAMkZ,EACN,aAAclT,EAAK,aACnB,WAAYiT,EAAK,OAAS,EAAIA,EAAO,OACtC,EACDjZ,EAAM,cAAgB,GACtBA,EAAM,aAAe8X,GAAA,EACrB9X,EAAM,mBAAqB,QAC3BA,EAAM,YAAc,GACpB4X,GAAgB5X,EAAOkZ,EAAW,CAChC,KAAM,UACN,QAAS,cACV,EAEL,OAAS3Y,EAAK,CACZP,EAAM,YAAc6X,GAAgBtX,CAAG,CACzC,SACEP,EAAM,cAAgB,IACxB,EACF,CAIA,eAAsBmZ,GAAYnZ,EAAoBtJ,EAAc,CAClE,GAAI,GAACsJ,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,qBAAsB,CAAE,KAAAtJ,EAAM,EACzDsJ,EAAM,YAAcA,EAAM,YAAY,OAAQjM,GAAMA,EAAE,OAAS2C,CAAI,CACrE,OAAS6J,EAAK,CACZP,EAAM,YAAc6X,GAAgBtX,CAAG,CACzC,CACF,CAIA,eAAsB6Y,GAAUpZ,EAAoBtJ,EAAc,CAChE,GAAI,GAACsJ,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMxE,EAAU,MAAMwE,EAAM,OAAO,QAAQ,cAAe,CAAE,KAAAtJ,EAAM,EAClE,GAAI,CAAC8E,EAAQ,OACbwE,EAAM,aAAe,CACnB,KAAMxE,EAAO,KACb,aAAcA,EAAO,QACrB,WAAYA,EAAO,WAAW,IAAKlI,IAAO,CAAE,GAAGA,CAAA,EAAI,EACnD,aAAckI,EAAO,cAAgB,IAEvCwE,EAAM,mBAAqB,YAC3BA,EAAM,cAAgB,GACtBA,EAAM,YAAc,EACtB,OAASO,EAAK,CACZP,EAAM,YAAc6X,GAAgBtX,CAAG,CACzC,CACF,CAIO,SAAS8Y,GAAgBrZ,EAAoBsZ,EAAoB,CACtE,MAAMC,EAASvZ,EAAM,YAChBuZ,IACLvZ,EAAM,aAAe,CACnB,KAAMuZ,EAAO,KACb,aAAcA,EAAO,QACrB,WAAYA,EAAO,WAAW,IAAKjmB,IAAO,CAAE,GAAGA,CAAA,EAAI,EACnD,aAAcimB,EAAO,cAAgB,IAEvCvZ,EAAM,mBAAqB,YAC3BA,EAAM,aAAesZ,GAAaA,IAAc,WAAaA,EAAY,WACzEtZ,EAAM,YAAc,KACpBA,EAAM,eAAiB,GACvBA,EAAM,cAAgB,GACtBA,EAAM,YAAc,GACtB,CAIO,SAASwZ,GAAoBxZ,EAAoByZ,EAAiBjc,EAAiB,CACxFwC,EAAM,aAAe,CACnB,GAAGA,EAAM,aACT,WAAYA,EAAM,aAAa,WAAW,IAAK1M,GAC7CA,EAAE,OAASmmB,EAAU,CAAE,GAAGnmB,EAAG,QAAAkK,GAAYlK,CAAA,CAC3C,CAEJ,CAIO,SAASomB,GAAW1Z,EAAoB0Y,EAAa,CAC1D1Y,EAAM,aAAe0Y,CACvB,CAIA,eAAsBiB,GAAmB3Z,EAAoBtJ,EAAckjB,EAAuB,CAChG,GAAI,GAAC5Z,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,cAAgBtJ,EACtBsJ,EAAM,YAAc,KACpB,GAAI,CACF,MAAMxE,EAAU,MAAMwE,EAAM,OAAO,QAAQ,cAAe,CAAE,KAAAtJ,EAAM,EAClE,GAAI,CAAC8E,EAAQ,OACb,MAAMyd,EAAOzd,EAAO,WACjB,OAAQlI,GAAMA,EAAE,KAAK,QAAUA,EAAE,QAAQ,MAAM,EAC/C,IAAKA,IAAO,CAAE,KAAMA,EAAE,KAAK,OAAQ,QAASA,EAAE,SAAU,EAC3D,MAAM0M,EAAM,OAAO,QAAQ,gBAAiB,CAC1C,KAAAtJ,EACA,aAAc8E,EAAO,QACrB,WAAYyd,EAAK,OAAS,EAAIA,EAAO,OACrC,aAAAW,CAAA,CACD,EACD,MAAM7B,GAAW/X,CAAK,EACtB4X,GAAgB5X,EAAOtJ,EAAM,CAC3B,KAAM,UACN,QAASkjB,EAAe,6BAA+B,wBACxD,CACH,OAASrZ,EAAK,CACZP,EAAM,YAAc6X,GAAgBtX,CAAG,EACvCqX,GAAgB5X,EAAOtJ,EAAM,CAAE,KAAM,QAAS,QAASmhB,GAAgBtX,CAAG,EAAG,CAC/E,SACEP,EAAM,cAAgB,IACxB,EACF,CAIA,eAAsB6Z,GACpB7Z,EACAiY,EACA6B,EACA,CACA,GAAI,GAAC9Z,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,cAAgBiY,EACtBjY,EAAM,YAAc,KACpB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,gBAAiB,CAAE,SAAAiY,EAAU,OAAA6B,EAAQ,EAChE,MAAM/B,GAAW/X,CAAK,EACtB4X,GAAgB5X,EAAOiY,EAAU,CAC/B,KAAM,UACN,QAAS,uBACV,CACH,OAAS1X,EAAK,CACZ,MAAMjD,EAAUua,GAAgBtX,CAAG,EACnCP,EAAM,YAAc1C,EACpBsa,GAAgB5X,EAAOiY,EAAU,CAAE,KAAM,QAAS,QAAA3a,EAAS,CAC7D,SACE0C,EAAM,cAAgB,IACxB,EACF,CAIA,eAAsB+Z,GAAY/Z,EAAoBtJ,EAAc,CAClE,GAAI,GAACsJ,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,cAAgBtJ,EACtBsJ,EAAM,YAAc,KACpB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,gBAAiB,CAAE,KAAAtJ,EAAM,EACpD,MAAMqhB,GAAW/X,CAAK,CACxB,OAASO,EAAK,CACZP,EAAM,YAAc6X,GAAgBtX,CAAG,CACzC,SACEP,EAAM,cAAgB,IACxB,EACF,mfCraMga,GAAiC,CACrC,SAAU,YACV,SAAU,YACV,UAAW,aACX,KAAM,QACN,OAAQ,UACR,MAAO,SACP,KAAM,QACN,OAAQ,UACR,OAAQ,UACR,MAAO,SACP,KAAM,OACR,EAEMC,GAAc,IAAI,IACtB,OAAO,QAAQD,EAAS,EAAE,IAAI,CAAC,CAACtB,EAAKxS,CAAI,IAAM,CAACA,EAAMwS,CAAU,CAAC,CACnE,EAEO,SAASwB,GAAkBC,EAA0B,CAC1D,GAAI,CAACA,EAAU,MAAO,GACtB,IAAItiB,EAAOsiB,EAAS,OAEpB,OADKtiB,EAAK,WAAW,GAAG,IAAGA,EAAO,IAAIA,CAAI,IACtCA,IAAS,IAAY,IACrBA,EAAK,SAAS,GAAG,MAAUA,EAAK,MAAM,EAAG,EAAE,GACxCA,EACT,CAEO,SAASuiB,GAAclU,EAAsB,CAClD,GAAI,CAACA,EAAM,MAAO,IAClB,IAAIyP,EAAazP,EAAK,OACtB,OAAKyP,EAAW,WAAW,GAAG,IAAGA,EAAa,IAAIA,CAAU,IACxDA,EAAW,OAAS,GAAKA,EAAW,SAAS,GAAG,IAClDA,EAAaA,EAAW,MAAM,EAAG,EAAE,GAE9BA,CACT,CAEO,SAAS0E,GAAW3B,EAAUyB,EAAW,GAAY,CAC1D,MAAMtiB,EAAOqiB,GAAkBC,CAAQ,EACjCjU,EAAO8T,GAAUtB,CAAG,EAC1B,OAAO7gB,EAAO,GAAGA,CAAI,GAAGqO,CAAI,GAAKA,CACnC,CAEO,SAASoU,GAAYC,EAAkBJ,EAAW,GAAgB,CACvE,MAAMtiB,EAAOqiB,GAAkBC,CAAQ,EACvC,IAAIjU,EAAOqU,GAAY,IACnB1iB,IACEqO,IAASrO,EACXqO,EAAO,IACEA,EAAK,WAAW,GAAGrO,CAAI,GAAG,IACnCqO,EAAOA,EAAK,MAAMrO,EAAK,MAAM,IAGjC,IAAI8d,EAAayE,GAAclU,CAAI,EAAE,cAErC,OADIyP,EAAW,SAAS,aAAa,IAAGA,EAAa,KACjDA,IAAe,IAAY,OACxBsE,GAAY,IAAItE,CAAU,GAAK,IACxC,CAEO,SAAS6E,GAA0BD,EAA0B,CAClE,IAAI5E,EAAayE,GAAcG,CAAQ,EAIvC,GAHI5E,EAAW,SAAS,aAAa,IACnCA,EAAayE,GAAczE,EAAW,MAAM,EAAG,GAAqB,CAAC,GAEnEA,IAAe,IAAK,MAAO,GAC/B,MAAM8E,EAAW9E,EAAW,MAAM,GAAG,EAAE,OAAO,OAAO,EACrD,GAAI8E,EAAS,SAAW,EAAG,MAAO,GAClC,QAAS,EAAI,EAAG,EAAIA,EAAS,OAAQ,IAAK,CACxC,MAAMC,EAAY,IAAID,EAAS,MAAM,CAAC,EAAE,KAAK,GAAG,CAAC,GAAG,cACpD,GAAIR,GAAY,IAAIS,CAAS,EAAG,CAC9B,MAAMtO,EAASqO,EAAS,MAAM,EAAG,CAAC,EAClC,OAAOrO,EAAO,OAAS,IAAIA,EAAO,KAAK,GAAG,CAAC,GAAK,EAClD,CACF,CACA,MAAO,IAAIqO,EAAS,KAAK,GAAG,CAAC,EAC/B,CCjGO,SAASE,IAAgC,CAC9C,OAAI,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,YAG3D,OAAO,WAAW,8BAA8B,EAAE,QAFhD,OAIL,OACN,CAEO,SAASC,GAAaxf,EAAgC,CAC3D,OAAIA,IAAS,SAAiBuf,GAAA,EACvBvf,CACT,CCIA,MAAMyf,GAAWxkB,GACX,OAAO,MAAMA,CAAK,EAAU,GAC5BA,GAAS,EAAU,EACnBA,GAAS,EAAU,EAChBA,EAGHykB,GAA6B,IAC7B,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,WACzD,GAEF,OAAO,WAAW,kCAAkC,EAAE,SAAW,GAGpEC,GAA0BrjB,GAAsB,CACpDA,EAAK,UAAU,OAAO,kBAAkB,EACxCA,EAAK,MAAM,eAAe,kBAAkB,EAC5CA,EAAK,MAAM,eAAe,kBAAkB,CAC9C,EAEasjB,GAAuB,CAAC,CACnC,UAAAC,EACA,WAAAC,EACA,QAAAC,EACA,aAAAC,CACF,IAA8B,OAC5B,GAAIA,IAAiBH,EAAW,OAEhC,MAAMI,EAAoB,WAAW,UAAY,KACjD,GAAI,CAACA,EAAmB,CACtBH,EAAA,EACA,MACF,CAEA,MAAMxjB,EAAO2jB,EAAkB,gBACzBC,EAAYD,EACZE,EAAuBT,GAAA,EAK7B,GAFE,EAAQQ,EAAU,qBAAwB,CAACC,EAEnB,CACxB,IAAIC,EAAW,GACXC,EAAW,GAEf,IACEN,GAAA,YAAAA,EAAS,kBAAmB,SAC5BA,GAAA,YAAAA,EAAS,kBAAmB,QAC5B,OAAO,OAAW,IAElBK,EAAWX,GAAQM,EAAQ,eAAiB,OAAO,UAAU,EAC7DM,EAAWZ,GAAQM,EAAQ,eAAiB,OAAO,WAAW,UACrDA,GAAA,MAAAA,EAAS,QAAS,CAC3B,MAAMO,EAAOP,EAAQ,QAAQ,wBAE3BO,EAAK,MAAQ,GACbA,EAAK,OAAS,GACd,OAAO,OAAW,MAElBF,EAAWX,IAASa,EAAK,KAAOA,EAAK,MAAQ,GAAK,OAAO,UAAU,EACnED,EAAWZ,IAASa,EAAK,IAAMA,EAAK,OAAS,GAAK,OAAO,WAAW,EAExE,CAEAhkB,EAAK,MAAM,YAAY,mBAAoB,GAAG8jB,EAAW,GAAG,GAAG,EAC/D9jB,EAAK,MAAM,YAAY,mBAAoB,GAAG+jB,EAAW,GAAG,GAAG,EAC/D/jB,EAAK,UAAU,IAAI,kBAAkB,EAErC,GAAI,CACF,MAAMikB,GAAavnB,EAAAknB,EAAU,sBAAV,YAAAlnB,EAAA,KAAAknB,EAAgC,IAAM,CACvDJ,EAAA,CACF,GACIS,GAAA,MAAAA,EAAY,SACTA,EAAW,SAAS,QAAQ,IAAMZ,GAAuBrjB,CAAI,CAAC,EAEnEqjB,GAAuBrjB,CAAI,CAE/B,MAAQ,CACNqjB,GAAuBrjB,CAAI,EAC3BwjB,EAAA,CACF,CACA,MACF,CAEAA,EAAA,EACAH,GAAuBrjB,CAAI,CAC7B,EC1FMkkB,GAA2B,IAEjC,eAAsBC,GACpB7b,EACAC,EACA,CACA,GAAI,GAACD,EAAM,QAAU,CAACA,EAAM,YACxB,EAAAA,EAAM,oBAAsB,EAACC,GAAA,MAAAA,EAAM,QACvC,CAAKA,GAAA,MAAAA,EAAM,QAAOD,EAAM,mBAAqB,IAC7CA,EAAM,iBAAmB,KACzB,GAAI,CACF,MAAM8b,EAAqC,CACzC,QAAS7b,GAAA,MAAAA,EAAM,MAAQ,OAAYD,EAAM,mBACzC,MAAO,KAEL,MAAM,QAAQA,EAAM,iBAAiB,GAAKA,EAAM,kBAAkB,OAAS,IAC7E8b,EAAU,OAAS9b,EAAM,mBAG3B,MAAM4B,EADM,MAAM5B,EAAM,OAAO,QAAQ,sBAAuB8b,CAAS,EAMjE1Q,EAAU,MAAM,QAAQxJ,EAAQ,OAAO,EACxCA,EAAQ,QACT,GACEyJ,EAAc,GAClBpL,GAAA,MAAAA,EAAM,OAAS,OAAO,KAAKD,EAAM,kBAAkB,EAAE,SAAW,GAElEA,EAAM,mBAAqBqL,EACvBD,EACA,CAAC,GAAGpL,EAAM,mBAAoB,GAAGoL,CAAO,EAAE,MAAM,CAACwQ,EAAwB,EACzEha,EAAQ,UAAS5B,EAAM,mBAAqB4B,EAAQ,SACpD,MAAM,QAAQA,EAAQ,MAAM,IAAG5B,EAAM,kBAAoB4B,EAAQ,QACrE5B,EAAM,uBAAyB,KAAK,KACtC,OAASO,EAAK,CACZP,EAAM,iBAAmB,OAAOO,CAAG,CACrC,SACON,GAAA,MAAAA,EAAM,QAAOD,EAAM,mBAAqB,GAC/C,EACF,wHCzCA,eAAsB+b,GAAiB/b,EAAmBlF,EAAkB,CAC1E,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMiC,EAAkC,GAElC9B,EAAO,MAAMH,EAAM,OAAO,QAAQ,eAAgBiC,CAAM,EAI1D9B,GAAA,MAAAA,EAAK,KACPH,EAAM,aAAeG,EAAI,SAAW,GAExC,MAAQ,CAER,CACF,CAEA,eAAsB6b,GAAWhc,EAAmBlF,EAAkB,CACpE,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMiC,EAAkC,GAExC,MAAMjC,EAAM,OAAO,QAAQ,oBAAqBiC,CAAM,EACtDjC,EAAM,aAAe,EACvB,MAAQ,CAER,CACF,CCGA,SAAS6X,GAAgBtX,EAAsB,CAC7C,OAAIA,aAAe,MAAcA,EAAI,QAC9B,OAAOA,CAAG,CACnB,CAEA,IAAI0b,GAAqD,KAEzD,SAASC,GAAkBlc,EAAmB5F,EAAc,CACtD6hB,iBAA2BA,EAAY,EAC3Cjc,EAAM,aAAe,CAAE,KAAM,UAAW,KAAA5F,CAAA,EACxC6hB,GAAe,WAAW,IAAM,CAC9Bjc,EAAM,aAAe,KACrBic,GAAe,IACjB,EAAG,GAAI,CACT,CAEA,eAAsBE,GAAanc,EAAmBlF,EAAkB,CACtE,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,IAAI,CAAClF,EAAS,CAEZkF,EAAM,UAAY,GAClBA,EAAM,UAAY,GAClB,MACF,CACA,GAAI,CAAAA,EAAM,aACV,CAAAA,EAAM,aAAe,GACrBA,EAAM,WAAa,KACnB,GAAI,CACF,MAAMiC,EAAkC,GACpCnH,MAAgB,QAAUA,GAC9B,MAAMqF,EAAO,MAAMH,EAAM,OAAO,QAAQ,aAAciC,CAAM,EAIxD9B,GAAA,MAAAA,EAAK,OACPH,EAAM,UAAYG,EAAI,KACtBH,EAAM,UAAYG,EAAI,MAAQ,GAElC,OAASI,EAAK,CACZP,EAAM,WAAa6X,GAAgBtX,CAAG,CACxC,SACEP,EAAM,aAAe,EACvB,GACF,CAGA,eAAsBoc,GAAWpc,EAAmBqc,EAAkBvhB,EAAkB,CACtFkF,EAAM,mBAAqB,IAAI,IAAI,CAACqc,CAAQ,CAAC,EAC7C,MAAMC,GAAYtc,EAAOqc,EAAUvhB,CAAO,CAC5C,CAGA,eAAsByhB,GAAiBvc,EAAmBqc,EAAkBvhB,EAAkB,CAC5F,MAAMjB,EAAO,IAAI,IAAImG,EAAM,kBAAkB,EAQ7C,GAPInG,EAAK,IAAIwiB,CAAQ,EACnBxiB,EAAK,OAAOwiB,CAAQ,EAEpBxiB,EAAK,IAAIwiB,CAAQ,EAEnBrc,EAAM,mBAAqBnG,EAEvBA,EAAK,OAAS,EAAG,CACnB,MAAM2iB,EAAY,CAAC,GAAG3iB,CAAI,EAAE,CAAC,EAC7B,MAAMyiB,GAAYtc,EAAOwc,EAAW1hB,CAAO,CAC7C,MACEkF,EAAM,kBAAoB,KAC1BA,EAAM,oBAAsB,KAC5BA,EAAM,iBAAmB,KACzBA,EAAM,mBAAqB,EAE/B,CAGA,eAAsByc,GAAkBzc,EAAmBlF,EAAkB,CAC3E,GAAI,CAACkF,EAAM,QAAU,CAACA,EAAM,UAAW,OACvC,MAAM0c,EAAQ,CAAC,GAAG1c,EAAM,kBAAkB,EAC1C,GAAI0c,EAAM,SAAW,EAAG,OACxB,IAAIC,EAAe,EACfC,EAAW,GACf,UAAWP,KAAYK,EACrB,GAAI,CACF,MAAMG,GAAa7c,EAAOqc,EAAUvhB,CAAO,EAC3C6hB,GACF,OAASpc,EAAK,CACZqc,EAAW/E,GAAgBtX,CAAG,CAChC,CAEEqc,EACF5c,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM,GAAG2c,CAAY,uBAAuBC,CAAQ,IAE1FV,GAAkBlc,EAAO,GAAG2c,CAAY,QAAQA,IAAiB,EAAI,IAAM,EAAE,aAAa,CAE9F,CAGA,eAAsBG,GAAc9c,EAAmBqc,EAAkBU,EAAmBjiB,EAAkB,CAC5G,MAAMkiB,EAAWX,EAAS,MAAM,GAAG,EAAE,OAASA,EACxCY,EAAOF,IAAc,IAAMC,EAAW,GAAGD,CAAS,IAAIC,CAAQ,GAChEC,IAASZ,GACb,MAAMa,GAASld,EAAOqc,EAAUY,EAAMniB,CAAO,CAC/C,CAEA,eAAsBwhB,GAAYtc,EAAmBqc,EAAkBvhB,EAAkB,CACvF,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,kBAAoBqc,EAC1Brc,EAAM,oBAAsB,GAC5BA,EAAM,oBAAsB,KAC5BA,EAAM,mBAAqB,GAC3BA,EAAM,iBAAmB,KACzB,GAAI,CACF,MAAMiC,EAAkC,CAAE,KAAMoa,CAAA,EAC5CvhB,MAAgB,QAAUA,GAC9B,MAAMqF,EAAO,MAAMH,EAAM,OAAO,QAAQ,aAAciC,CAAM,EAK5DjC,EAAM,qBAAsBG,GAAA,YAAAA,EAAK,UAAW,KAC5CH,EAAM,oBAAqBG,GAAA,YAAAA,EAAK,SAAU,GAC1CH,EAAM,kBAAmBG,GAAA,YAAAA,EAAK,OAAQ,IACxC,OAASI,EAAK,CACZP,EAAM,WAAa6X,GAAgBtX,CAAG,CACxC,SACEP,EAAM,oBAAsB,EAC9B,EACF,CAEA,eAAsB6c,GAAa7c,EAAmBqc,EAAkBvhB,EAAkB,CACxF,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMiC,EAAkC,CAAE,KAAMoa,CAAA,EAC5CvhB,MAAgB,QAAUA,GAC9B,MAAMqF,EAAO,MAAMH,EAAM,OAAO,QAAQ,iBAAkBiC,CAAM,EAIhE,GAAI,EAAC9B,GAAA,MAAAA,EAAK,QAAQ,CAChBH,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM,4BAC5C,MACF,CAEA,MAAMP,EAAQ,WAAW,KAAK,KAAKU,EAAI,MAAM,EAAIzM,GAAMA,EAAE,WAAW,CAAC,CAAC,EAChE2R,EAAO,IAAI,KAAK,CAAC5F,CAAK,CAAC,EACvB6F,EAAM,IAAI,gBAAgBD,CAAI,EAC9BzR,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAO0R,EACT1R,EAAE,SAAWuM,EAAI,MAAQkc,EAAS,MAAM,GAAG,EAAE,OAAS,WACtD,SAAS,KAAK,YAAYzoB,CAAC,EAC3BA,EAAE,QACF,SAAS,KAAK,YAAYA,CAAC,EAC3B,IAAI,gBAAgB0R,CAAG,CACzB,OAAS/E,EAAK,CACZP,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM6X,GAAgBtX,CAAG,EACjE,CACF,CAEA,eAAsB4c,GACpBnd,EACAod,EACAC,EACAviB,EACA,CACA,GAAI,CAACkF,EAAM,QAAU,CAACA,EAAM,UAAW,OACvCA,EAAM,gBAAkB,GACxBA,EAAM,aAAe,KACrB,IAAI2c,EAAe,EACfC,EAAW,GACf,UAAWU,KAAQD,EACjB,GAAI,CACF,MAAME,EAAS,MAAMD,EAAK,cACpBE,EAAS,KACb,IAAI,WAAWD,CAAM,EAAE,OAAO,CAAC9Z,EAAMgS,IAAShS,EAAO,OAAO,aAAagS,CAAI,EAAG,EAAE,GAE9ExT,EAAkC,CACtC,KAAMmb,EACN,KAAME,EAAK,KACX,KAAME,CAAA,EAEJ1iB,MAAgB,QAAUA,GAC9B,MAAMkF,EAAM,OAAO,QAAQ,eAAgBiC,CAAM,EACjD0a,GACF,OAASpc,EAAK,CACZqc,EAAW/E,GAAgBtX,CAAG,CAChC,CAEFP,EAAM,gBAAkB,GACpB4c,EACF5c,EAAM,aAAe,CACnB,KAAM,QACN,KAAM2c,EAAe,EAAI,GAAGA,CAAY,qBAAqBC,CAAQ,GAAKA,CAAA,EAG5EV,GAAkBlc,EAAO,GAAG2c,CAAY,QAAQA,IAAiB,EAAI,IAAM,EAAE,WAAW,EAE1F,MAAMR,GAAanc,EAAOlF,CAAO,CACnC,CAEA,eAAsB2iB,GAAazd,EAAmB0d,EAAmBC,EAAoB7iB,EAAkB,CAC7G,GAAI,CAACkF,EAAM,QAAU,CAACA,EAAM,UAAW,OACvCA,EAAM,aAAe,KACrB,MAAMod,EAAUM,IAAc,IAAMC,EAAa,GAAGD,CAAS,IAAIC,CAAU,GAC3E,GAAI,CACF,MAAM1b,EAAkC,CAAE,KAAMmb,CAAA,EAC5CtiB,MAAgB,QAAUA,GAC9B,MAAMkF,EAAM,OAAO,QAAQ,cAAeiC,CAAM,EAChDia,GAAkBlc,EAAO,WAAWod,CAAO,EAAE,EAC7C,MAAMjB,GAAanc,EAAOlF,CAAO,EAEjCkF,EAAM,sBAAwB,IAAI,CAAC,GAAGA,EAAM,kBAAmBod,CAAO,CAAC,EACvEpd,EAAM,gBAAkBod,CAC1B,OAAS7c,EAAK,CACZP,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM6X,GAAgBtX,CAAG,EACjE,CACF,CAEA,eAAsBqd,GAAW5d,EAAmBqc,EAAkBvhB,EAAkB,CACtF,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,aAAe,KACrB,GAAI,CACF,MAAMiC,EAAkC,CAAE,KAAMoa,CAAA,EAC5CvhB,MAAgB,QAAUA,GAC9B,MAAMkF,EAAM,OAAO,QAAQ,eAAgBiC,CAAM,EACjDia,GAAkBlc,EAAO,cAAc,EACnCA,EAAM,oBAAsBqc,IAC9Brc,EAAM,kBAAoB,KAC1BA,EAAM,oBAAsB,MAE9B,MAAMmc,GAAanc,EAAOlF,CAAO,CACnC,OAASyF,EAAK,CACZP,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM6X,GAAgBtX,CAAG,EACjE,EACF,CAEA,eAAsB2c,GAASld,EAAmB6d,EAAcC,EAAYhjB,EAAkB,CAC5F,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,aAAe,KACrB,GAAI,CACF,MAAMiC,EAAkC,CAAE,KAAA4b,EAAM,GAAAC,CAAA,EAC5ChjB,MAAgB,QAAUA,GAC9B,MAAMkF,EAAM,OAAO,QAAQ,aAAciC,CAAM,EAC/Cia,GAAkBlc,EAAO,YAAY,EACjCA,EAAM,oBAAsB6d,IAC9B7d,EAAM,kBAAoB8d,GAE5B,MAAM3B,GAAanc,EAAOlF,CAAO,CACnC,OAASyF,EAAK,CACZP,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM6X,GAAgBtX,CAAG,EACjE,EACF,CAEA,eAAsBwd,GAAiB/d,EAAmBlF,EAAkB,CAC1E,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMiC,EAAkC,GACpCnH,MAAgB,QAAUA,GAC9B,MAAMqF,EAAO,MAAMH,EAAM,OAAO,QAAQ,gBAAiBiC,CAAM,EAU3D9B,GAAA,MAAAA,EAAK,KACPH,EAAM,kBAAoB,CACxB,MAAOG,EAAI,OAAS,GACpB,QAASA,EAAI,QACb,aAAcA,EAAI,aAClB,MAAOA,EAAI,OAAS,EACpB,OAAQA,EAAI,QAAU,EACtB,MAAOA,EAAI,MACX,eAAgBA,EAAI,gBAG1B,MAAQ,CAER,CACF,CAEA,eAAsB6d,GAAche,EAAmBlF,EAAkB,CACvE,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,iBACV,CAAAA,EAAM,iBAAmB,GACzBA,EAAM,aAAe,KACrB,GAAI,CACF,MAAMiC,EAAkC,CAAE,MAAO,IAC7CnH,MAAgB,QAAUA,GAC9B,MAAMqF,EAAO,MAAMH,EAAM,OAAO,QAAQ,iBAAkBiC,CAAM,EAK1Dob,GAAQld,GAAA,YAAAA,EAAK,QAAS,EACtB8d,GAAS9d,GAAA,YAAAA,EAAK,SAAU,EAC9B+b,GAAkBlc,EAAO,eAAeqd,CAAK,WAAWY,CAAM,SAAS,EAEvE,MAAMF,GAAiB/d,EAAOlF,CAAO,CACvC,OAASyF,EAAK,CACZP,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM6X,GAAgBtX,CAAG,EACjE,SACEP,EAAM,iBAAmB,EAC3B,EACF,CAEO,SAASke,GAAgBle,EAAmBod,EAAiB,CAClE,MAAMvjB,EAAO,IAAI,IAAImG,EAAM,iBAAiB,EACxCnG,EAAK,IAAIujB,CAAO,EAClBvjB,EAAK,OAAOujB,CAAO,EAEnBvjB,EAAK,IAAIujB,CAAO,EAElBpd,EAAM,kBAAoBnG,EAE1BmG,EAAM,gBAAkBod,CAC1B,CAEA,eAAsBe,GAAane,EAAmBoe,EAAetjB,EAAkB,CACrF,GAAI,GAACkF,EAAM,QAAU,CAACA,EAAM,WAC5B,IAAI,CAACoe,EAAM,OAAQ,CACjBpe,EAAM,mBAAqB,KAC3B,MACF,CACAA,EAAM,mBAAqB,GAC3BA,EAAM,mBAAqB,KAC3B,GAAI,CACF,MAAMiC,EAAkC,CAAE,MAAOmc,EAAM,OAAQ,WAAY,IACvEtjB,MAAgB,QAAUA,GAC9B,MAAMqF,EAAO,MAAMH,EAAM,OAAO,QAAQ,gBAAiBiC,CAAM,EAK/DjC,EAAM,oBAAqBG,GAAA,YAAAA,EAAK,UAAW,EAC7C,OAASI,EAAK,CACZP,EAAM,aAAe,CAAE,KAAM,QAAS,KAAM6X,GAAgBtX,CAAG,GAC/DP,EAAM,mBAAqB,IAC7B,SACEA,EAAM,mBAAqB,EAC7B,EACF,CAEO,SAASqe,GAAYre,EAAmB,CAC7CA,EAAM,iBAAmB,GACzBA,EAAM,mBAAqB,IAC7B,CCtXO,SAASse,GAAkBvb,EAAmB,CAC/CA,EAAK,mBAAqB,OAC9BA,EAAK,kBAAoB,OAAO,YAC9B,KAAWuU,GAAUvU,EAAkC,CAAE,MAAO,GAAM,GACtE,KAEJ,CAEO,SAASwb,GAAiBxb,EAAmB,CAC9CA,EAAK,mBAAqB,OAC9B,cAAcA,EAAK,iBAAiB,EACpCA,EAAK,kBAAoB,KAC3B,CAEO,SAASyb,GAAiBzb,EAA2F,CACtHA,EAAK,kBAAoB,OAC7BA,EAAK,iBAAmB,OAAO,YAAY,IAAM,EAC7BA,EAAK,aACnBA,EAAK,cAAgB,OACrBA,EAAK,MAAQ,SAGbA,EAAK,aAAe,WAEnBA,EAAgD,UAAY,MAC5DoI,GAASpI,EAAkC,CAAE,MAAO,GAAM,CACjE,EAAG,GAAI,EACT,CAEO,SAAS0b,GAAgB1b,EAAmB,CAC7CA,EAAK,kBAAoB,OAC7B,cAAcA,EAAK,gBAAgB,EACnCA,EAAK,iBAAmB,KAC1B,CAEO,SAAS2b,GAAwB3b,EAAoI,CACtKA,EAAK,yBAA2B,OACpCA,EAAK,wBAA0B,OAAO,YAAY,IAAM,CAKlD,EAHcA,EAAK,aACnBA,EAAK,cAAgB,OACrBA,EAAK,MAAQ,SACCA,EAAK,aAAe,WACjC8Y,GAAgB9Y,EAAkC,CAAE,MAAO,GAAM,MAAO,GAAM,CACrF,EAAG,GAAI,EACT,CAEO,SAAS4b,GAAuB5b,EAAmD,CACpFA,EAAK,yBAA2B,OACpC,cAAcA,EAAK,uBAAuB,EAC1CA,EAAK,wBAA0B,KACjC,CAEO,SAAS6b,GAAkB7b,EAAmB,CAC/CA,EAAK,mBAAqB,OAC9BA,EAAK,kBAAoB,OAAO,YAAY,IAAM,CAC5CA,EAAK,MAAQ,SACZsG,GAAUtG,CAAgC,CACjD,EAAG,GAAI,EACT,CAEO,SAAS8b,GAAiB9b,EAAmB,CAC9CA,EAAK,mBAAqB,OAC9B,cAAcA,EAAK,iBAAiB,EACpCA,EAAK,kBAAoB,KAC3B,CAEO,SAAS+b,GAAkB/b,EAAmB,CAC/CA,EAAK,mBAAqB,OAE9BA,EAAK,kBAAoB,OAAO,YAAY,IAAM,CAC3CgZ,GAAiBhZ,CAAgC,CACxD,EAAG,GAAM,EACX,CAEO,SAASgc,GAAiBhc,EAAmB,CAC9CA,EAAK,mBAAqB,OAC9B,cAAcA,EAAK,iBAAiB,EACpCA,EAAK,kBAAoB,KAC3B,CAEO,SAASic,GAAyBjc,EAAmB,CACtDA,EAAK,0BAA4B,OACrCA,EAAK,yBAA2B,OAAO,YAAY,IAAM,CACvD,MAAMkc,EAAMlc,EACPkc,EAAI,WACJlB,GAAiBkB,EAAKA,EAAI,oBAAoB,CACrD,EAAG,GAAK,EACV,CAEO,SAASC,GAAwBnc,EAAkE,CACpGA,EAAK,0BAA4B,OACrC,cAAcA,EAAK,wBAAwB,EAC3CA,EAAK,yBAA2B,KAClC,CCxEO,SAASoc,GAAcpc,EAAoBlJ,EAAkB,OAClE,MAAM8b,EAAa,CACjB,GAAG9b,EACH,uBAAsBzF,EAAAyF,EAAK,uBAAL,YAAAzF,EAA2B,SAAUyF,EAAK,WAAW,QAAU,QAEvFkJ,EAAK,SAAW4S,EAChB/b,GAAa+b,CAAU,EACnB9b,EAAK,QAAUkJ,EAAK,QACtBA,EAAK,MAAQlJ,EAAK,MAClBulB,GAAmBrc,EAAM6X,GAAa/gB,EAAK,KAAK,CAAC,GAEnDkJ,EAAK,gBAAkBA,EAAK,SAAS,oBACvC,CAEO,SAASsc,GAAwBtc,EAAoBlJ,EAAc,CACxE,MAAMtD,EAAUsD,EAAK,OAChBtD,GACDwM,EAAK,SAAS,uBAAyBxM,GAC3C4oB,GAAcpc,EAAM,CAAE,GAAGA,EAAK,SAAU,qBAAsBxM,EAAS,CACzE,CAEO,SAAS+oB,GAAqBvc,EAAoB,CACvD,GAAI,CAAC,OAAO,SAAS,OAAQ,OAC7B,MAAMd,EAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM,EACnDsd,EAAWtd,EAAO,IAAI,OAAO,EAC7Bud,EAAcvd,EAAO,IAAI,UAAU,EACnCwd,EAAaxd,EAAO,IAAI,SAAS,EACjCyd,EAAgBzd,EAAO,IAAI,YAAY,EAC7C,IAAI0d,EAAiB,GAErB,GAAIJ,GAAY,KAAM,CACpB,MAAMxV,EAAQwV,EAAS,OACnBxV,GAASA,IAAUhH,EAAK,SAAS,OACnCoc,GAAcpc,EAAM,CAAE,GAAGA,EAAK,SAAU,MAAAgH,EAAO,EAEjD9H,EAAO,OAAO,OAAO,EACrB0d,EAAiB,EACnB,CAEA,GAAIH,GAAe,KAAM,CACvB,MAAMI,EAAWJ,EAAY,OACzBI,IACD7c,EAA8B,SAAW6c,GAE5C3d,EAAO,OAAO,UAAU,EACxB0d,EAAiB,EACnB,CAEA,GAAIF,GAAc,KAAM,CACtB,MAAMI,EAAUJ,EAAW,OACvBI,IACF9c,EAAK,WAAa8c,EAClBV,GAAcpc,EAAM,CAClB,GAAGA,EAAK,SACR,WAAY8c,EACZ,qBAAsBA,CAAA,CACvB,EAEL,CAEA,GAAIH,GAAiB,KAAM,CACzB,MAAMI,EAAaJ,EAAc,OAC7BI,GAAcA,IAAe/c,EAAK,SAAS,YAC7Coc,GAAcpc,EAAM,CAAE,GAAGA,EAAK,SAAU,WAAA+c,EAAY,EAEtD7d,EAAO,OAAO,YAAY,EAC1B0d,EAAiB,EACnB,CAEA,GAAI,CAACA,EAAgB,OACrB,MAAMra,EAAM,IAAI,IAAI,OAAO,SAAS,IAAI,EACxCA,EAAI,OAASrD,EAAO,WACpB,OAAO,QAAQ,aAAa,GAAI,GAAIqD,EAAI,UAAU,CACpD,CAEO,SAASya,GAAOhd,EAAoBlJ,EAAW,CAChDkJ,EAAK,MAAQlJ,IAAMkJ,EAAK,IAAMlJ,GAC9BA,IAAS,SAAQkJ,EAAK,oBAAsB,IAC5ClJ,IAAS,OACKkJ,EAA4C,aAC7C,UACb2b,GAAwB3b,CAAgE,EAExFyb,GAAiBzb,CAAyD,GAG5E0b,GAAgB1b,CAAwD,EACxE4b,GAAuB5b,CAA+D,GAEpFlJ,IAAS,QACX+kB,GAAkB7b,CAA0D,KACxDA,CAAyD,EAC1Eid,GAAiBjd,CAAI,EAC1Bkd,GAAeld,EAAMlJ,EAAM,EAAK,CAClC,CAEO,SAASqmB,GACdnd,EACAlJ,EACAshB,EACA,CAMAH,GAAqB,CACnB,UAAWnhB,EACX,WAPiB,IAAM,CACvBkJ,EAAK,MAAQlJ,EACbslB,GAAcpc,EAAM,CAAE,GAAGA,EAAK,SAAU,MAAOlJ,EAAM,EACrDulB,GAAmBrc,EAAM6X,GAAa/gB,CAAI,CAAC,CAC7C,EAIE,QAAAshB,EACA,aAAcpY,EAAK,MACpB,CACH,CAEA,eAAsBid,GAAiBjd,EAAoB,CA8BzD,GA7BIA,EAAK,MAAQ,YAAY,MAAMod,GAAapd,CAAI,EAChDA,EAAK,MAAQ,YAAY,MAAMqd,GAAgBrd,CAAI,EACnDA,EAAK,MAAQ,aAAa,MAAM4U,GAAa5U,CAAgC,EAC7EA,EAAK,MAAQ,QAAQ,MAAMsd,GAAStd,CAAI,EACxCA,EAAK,MAAQ,UAAU,MAAMgV,GAAWhV,CAAgC,EACxEA,EAAK,MAAQ,UACf,MAAMuU,GAAUvU,CAAgC,EAChD,MAAMsU,GAAYtU,CAAgC,EAClD,MAAMsD,GAAWtD,CAAgC,EACjD,MAAMyU,GAAkBzU,CAAgC,GAKtDA,EAAK,MAAQ,QAAU,CAACA,EAAK,cAAgB,CAACA,EAAK,WACrD,MAAMud,GAAYvd,CAAoD,EACtEiB,GACEjB,EACA,CAACA,EAAK,sBAGNA,EAAK,MAAQ,WACf,MAAMwD,GAAiBxD,CAAgC,EACvD,MAAMsD,GAAWtD,CAAgC,GAE/CA,EAAK,MAAQ,UACf,MAAMsG,GAAUtG,CAAgC,EAChDA,EAAK,SAAWA,EAAK,gBAEnBA,EAAK,MAAQ,OAAQ,CAGvB,GAFAA,EAAK,aAAe,GACJA,EAA4C,aAC7C,UAAW,CACxB,KAAM,CAAE,gBAAA8Y,CAAA,EAAoB,MAAA0E,GAAA,gCAAA1E,CAAA,QAAM,2BAAA2E,EAAA,EAAmC,uBAAA3E,CAAA,2BACrE,MAAMA,EAAgB9Y,EAA0D,CAAE,MAAO,GAAM,CACjG,MACE,MAAMoI,GAASpI,EAAkC,CAAE,MAAO,GAAM,EAElE2B,GACE3B,EACA,GAEJ,CACF,CAEO,SAAS0d,IAAgB,CAC9B,GAAI,OAAO,OAAW,IAAa,MAAO,GAC1C,MAAMC,EAAa,OAAO,oCAC1B,OAAI,OAAOA,GAAe,UAAYA,EAAW,OACxCxG,GAAkBwG,CAAU,EAE9BlG,GAA0B,OAAO,SAAS,QAAQ,CAC3D,CAEO,SAASmG,GAAsB5d,EAAoB,CACxDA,EAAK,MAAQA,EAAK,SAAS,OAAS,SACpCqc,GAAmBrc,EAAM6X,GAAa7X,EAAK,KAAK,CAAC,CACnD,CAEO,SAASqc,GAAmBrc,EAAoB6d,EAAyB,CAE9E,GADA7d,EAAK,cAAgB6d,EACjB,OAAO,SAAa,IAAa,OACrC,MAAMlpB,EAAO,SAAS,gBACtBA,EAAK,QAAQ,MAAQkpB,EACrBlpB,EAAK,MAAM,YAAckpB,CAC3B,CAEO,SAASC,GAAoB9d,EAAoB,CACtD,GAAI,OAAO,OAAW,KAAe,OAAO,OAAO,YAAe,WAAY,OAM9E,GALAA,EAAK,WAAa,OAAO,WAAW,8BAA8B,EAClEA,EAAK,kBAAqB6B,GAAU,CAC9B7B,EAAK,QAAU,UACnBqc,GAAmBrc,EAAM6B,EAAM,QAAU,OAAS,OAAO,CAC3D,EACI,OAAO7B,EAAK,WAAW,kBAAqB,WAAY,CAC1DA,EAAK,WAAW,iBAAiB,SAAUA,EAAK,iBAAiB,EACjE,MACF,CACeA,EAAK,WAGb,YAAYA,EAAK,iBAAiB,CAC3C,CAEO,SAAS+d,GAAoB/d,EAAoB,CACtD,GAAI,CAACA,EAAK,YAAc,CAACA,EAAK,kBAAmB,OACjD,GAAI,OAAOA,EAAK,WAAW,qBAAwB,WAAY,CAC7DA,EAAK,WAAW,oBAAoB,SAAUA,EAAK,iBAAiB,EACpE,MACF,CACeA,EAAK,WAGb,eAAeA,EAAK,iBAAiB,EAC5CA,EAAK,WAAa,KAClBA,EAAK,kBAAoB,IAC3B,CAEO,SAASge,GAAoBhe,EAAoBie,EAAkB,CACxE,GAAI,OAAO,OAAW,IAAa,OACnC,MAAMJ,EAAWtG,GAAY,OAAO,SAAS,SAAUvX,EAAK,QAAQ,GAAK,OACzEke,GAAgBle,EAAM6d,CAAQ,EAC9BX,GAAeld,EAAM6d,EAAUI,CAAO,CACxC,CAEO,SAASE,GAAWne,EAAoB,OAC7C,GAAI,OAAO,OAAW,IAAa,OACnC,MAAM6d,EAAWtG,GAAY,OAAO,SAAS,SAAUvX,EAAK,QAAQ,EACpE,GAAI,CAAC6d,EAAU,OAGf,MAAMf,GAAUzrB,EADJ,IAAI,IAAI,OAAO,SAAS,IAAI,EACpB,aAAa,IAAI,SAAS,IAA9B,YAAAA,EAAiC,OAC7CyrB,IACF9c,EAAK,WAAa8c,EAClBV,GAAcpc,EAAM,CAClB,GAAGA,EAAK,SACR,WAAY8c,EACZ,qBAAsBA,CAAA,CACvB,GAGHoB,GAAgBle,EAAM6d,CAAQ,CAChC,CAEO,SAASK,GAAgBle,EAAoBlJ,EAAW,CACzDkJ,EAAK,MAAQlJ,IAAMkJ,EAAK,IAAMlJ,GAC9BA,IAAS,SAAQkJ,EAAK,oBAAsB,IAC5ClJ,IAAS,OACKkJ,EAA4C,aAC7C,UACb2b,GAAwB3b,CAAgE,EAExFyb,GAAiBzb,CAAyD,GAG5E0b,GAAgB1b,CAAwD,EACxE4b,GAAuB5b,CAA+D,GAEpFlJ,IAAS,QACX+kB,GAAkB7b,CAA0D,KACxDA,CAAyD,EAC3EA,EAAK,WAAgBid,GAAiBjd,CAAI,CAChD,CAEO,SAASkd,GAAeld,EAAoB2V,EAAUsI,EAAkB,CAC7E,GAAI,OAAO,OAAW,IAAa,OACnC,MAAMG,EAAa/G,GAAcC,GAAW3B,EAAK3V,EAAK,QAAQ,CAAC,EACzDqe,EAAchH,GAAc,OAAO,SAAS,QAAQ,EACpD9U,EAAM,IAAI,IAAI,OAAO,SAAS,IAAI,EAEpCoT,IAAQ,QAAU3V,EAAK,WACzBuC,EAAI,aAAa,IAAI,UAAWvC,EAAK,UAAU,EAE/CuC,EAAI,aAAa,OAAO,SAAS,EAG/B8b,IAAgBD,IAClB7b,EAAI,SAAW6b,GAGbH,EACF,OAAO,QAAQ,aAAa,GAAI,GAAI1b,EAAI,UAAU,EAElD,OAAO,QAAQ,UAAU,GAAI,GAAIA,EAAI,UAAU,CAEnD,CAcA,eAAsB6a,GAAapd,EAAoB,CACrD,MAAM,QAAQ,IAAI,CAChByF,EAAazF,EAAkC,EAAK,EACpD4U,GAAa5U,CAAgC,EAC7Cf,GAAae,CAAgC,EAC7C8D,GAAe9D,CAAgC,EAC/CsG,GAAUtG,CAAgC,EAC3C,CACH,CAEA,eAAsBqd,GAAgBrd,EAAoB,CACxD,MAAM,QAAQ,IAAI,CAChByF,EAAazF,EAAkC,EAAI,EACnDwD,GAAiBxD,CAAgC,EACjDsD,GAAWtD,CAAgC,EAC5C,CACH,CAEA,eAAsBsd,GAAStd,EAAoB,CACjD,MAAM,QAAQ,IAAI,CAChByF,EAAazF,EAAkC,EAAK,EACpD8D,GAAe9D,CAAgC,EAC/C+D,GAAa/D,CAAgC,EAC9C,CACH,CC1UO,SAASse,GAAWte,EAAgB,CACzC,OAAOA,EAAK,aAAe,EAAQA,EAAK,SAC1C,CAEO,SAASue,GAAkBlnB,EAAc,CAC9C,MAAM7D,EAAU6D,EAAK,OACrB,GAAI,CAAC7D,EAAS,MAAO,GACrB,MAAMof,EAAapf,EAAQ,cAC3B,OAAIof,IAAe,QAAgB,GAEjCA,IAAe,QACfA,IAAe,OACfA,IAAe,SACfA,IAAe,QACfA,IAAe,MAEnB,CAEA,eAAsB4L,GAAgBxe,EAAgB,CAC/CA,EAAK,YACVA,EAAK,YAAc,GACnB,MAAMrB,GAAaqB,CAAgC,EACrD,CAEA,SAASye,GAAmBze,EAAgB3I,EAAcyG,EAAgC,CACxF,MAAMtK,EAAU6D,EAAK,OACf0G,EAAiB,GAAQD,GAAeA,EAAY,OAAS,GAC/D,CAACtK,GAAW,CAACuK,IACjBiC,EAAK,UAAY,CACf,GAAGA,EAAK,UACR,CACE,GAAInD,GAAA,EACJ,KAAMrJ,EACN,UAAW,KAAK,MAChB,YAAauK,EAAiBD,GAAA,YAAAA,EAAa,IAAKO,IAAS,CAAE,GAAGA,CAAA,IAAU,OAC1E,EAEF4C,GAAmBjB,CAA2D,EAChF,CAEA,eAAe0e,GACb1e,EACAzF,EACA2C,EAOA,SACAqD,GAAgBP,CAAwD,EACxE,MAAM2e,EAAK,MAAM9gB,GAAgBmC,EAAkCzF,EAAS2C,GAAA,YAAAA,EAAM,WAAW,EAC7F,MAAI,CAACyhB,IAAMzhB,GAAA,YAAAA,EAAM,gBAAiB,OAChC8C,EAAK,YAAc9C,EAAK,eAEtB,CAACyhB,IAAMzhB,GAAA,MAAAA,EAAM,uBACf8C,EAAK,gBAAkB9C,EAAK,qBAE1ByhB,GACFrC,GAAwBtc,EAAkEA,EAAK,UAAU,EAEvG2e,IAAMzhB,GAAA,MAAAA,EAAM,iBAAgB7L,EAAA6L,EAAK,gBAAL,MAAA7L,EAAoB,UAClD2O,EAAK,YAAc9C,EAAK,eAEtByhB,IAAMzhB,GAAA,MAAAA,EAAM,uBAAsB5L,EAAA4L,EAAK,sBAAL,MAAA5L,EAA0B,UAC9D0O,EAAK,gBAAkB9C,EAAK,qBAE9B+D,GAAmBjB,CAA2D,EAC1E2e,GAAM,CAAC3e,EAAK,WACT4e,GAAe5e,CAAI,EAEnB2e,CACT,CAEA,eAAeC,GAAe5e,EAAgB,CAC5C,GAAI,CAACA,EAAK,WAAase,GAAWte,CAAI,EAAG,OACzC,KAAM,CAAClJ,EAAM,GAAGkB,CAAI,EAAIgI,EAAK,UAC7B,GAAI,CAAClJ,EAAM,OACXkJ,EAAK,UAAYhI,EACN,MAAM0mB,GAAmB1e,EAAMlJ,EAAK,KAAM,CAAE,YAAaA,EAAK,YAAa,IAEpFkJ,EAAK,UAAY,CAAClJ,EAAM,GAAGkJ,EAAK,SAAS,EAE7C,CAEO,SAAS6e,GAAoB7e,EAAgB3D,EAAY,CAC9D2D,EAAK,UAAYA,EAAK,UAAU,OAAQtF,GAASA,EAAK,KAAO2B,CAAE,CACjE,CAEA,eAAsByiB,GACpB9e,EACA+e,EACA7hB,EACA,CACA,GAAI,CAAC8C,EAAK,UAAW,OACrB,MAAMgf,EAAgBhf,EAAK,YACrBzF,GAAWwkB,GAAmB/e,EAAK,aAAa,OAChDlC,EAAckC,EAAK,iBAAmB,GACtCif,EAAoBF,GAAmB,KAAOjhB,EAAc,GAC5DC,EAAiBkhB,EAAkB,OAAS,EAGlD,GAAI,GAAC1kB,GAAW,CAACwD,GAEjB,IAAIwgB,GAAkBhkB,CAAO,EAAG,CAC9B,MAAMikB,GAAgBxe,CAAI,EAC1B,MACF,CASA,GAPI+e,GAAmB,OACrB/e,EAAK,YAAc,GACnBA,EAAK,gBAAkB,GAEvBxI,GAAWwI,EAAK,mBAAqB,GAAIA,EAAK,UAAU,GAGtDse,GAAWte,CAAI,EAAG,CACpBye,GAAmBze,EAAMzF,EAAS0kB,CAAiB,EACnD,MACF,CAEA,MAAMP,GAAmB1e,EAAMzF,EAAS,CACtC,cAAewkB,GAAmB,KAAOC,EAAgB,OACzD,aAAc,GAAQD,IAAmB7hB,GAAA,MAAAA,EAAM,eAC/C,YAAaa,EAAiBkhB,EAAoB,OAClD,oBAAqBF,GAAmB,KAAOjhB,EAAc,OAC7D,mBAAoB,GAAQihB,IAAmB7hB,GAAA,MAAAA,EAAM,cAAY,CAClE,EACH,CAEA,eAAsBqgB,GAAYvd,EAAgB,OAChD,MAAMkc,EAAMlc,EACNkf,EAAc,KAAK,OAAK7tB,EAAA6qB,EAAI,eAAJ,YAAA7qB,EAAkB,SAAU,GAAK,GAAI0L,EAAc,EACjF,MAAM,QAAQ,IAAI,CAChBC,GAAgBkf,EAAK,CAAE,MAAOgD,EAAa,EAC3CjgB,GAAaid,CAAG,EAChBiD,GAAkBnf,CAAI,EACvB,EACDiB,GAAmBjB,EAA6D,EAAI,CACtF,CAEO,MAAMof,GAAyBR,GAMtC,SAASS,GAAyBrf,EAA+B,WAC/D,MAAMvB,EAAS5G,GAAqBmI,EAAK,UAAU,EACnD,GAAIvB,GAAA,MAAAA,EAAQ,QAAS,OAAOA,EAAO,QACnC,MAAMiF,GAAWrS,EAAA2O,EAAK,QAAL,YAAA3O,EAAY,SAE7B,QADiBiuB,GAAAhuB,EAAAoS,GAAA,YAAAA,EAAU,kBAAV,YAAApS,EAA2B,iBAA3B,YAAAguB,EAA2C,SACzC,MACrB,CAEA,SAASC,GAAmBnI,EAAkBrf,EAAyB,CACrE,MAAMjD,EAAOqiB,GAAkBC,CAAQ,EACjCoI,EAAU,mBAAmBznB,CAAO,EAC1C,OAAOjD,EAAO,GAAGA,CAAI,WAAW0qB,CAAO,UAAY,WAAWA,CAAO,SACvE,CAEA,eAAsBL,GAAkBnf,EAAgB,CACtD,GAAI,CAACA,EAAK,UAAW,CACnBA,EAAK,cAAgB,KACrB,MACF,CACA,MAAMjI,EAAUsnB,GAAyBrf,CAAI,EAC7C,GAAI,CAACjI,EAAS,CACZiI,EAAK,cAAgB,KACrB,MACF,CACAA,EAAK,cAAgB,KACrB,MAAMuC,EAAMgd,GAAmBvf,EAAK,SAAUjI,CAAO,EACrD,GAAI,CACF,MAAMqF,EAAM,MAAM,MAAMmF,EAAK,CAAE,OAAQ,MAAO,EAC9C,GAAI,CAACnF,EAAI,GAAI,CACX4C,EAAK,cAAgB,KACrB,MACF,CACA,MAAMU,EAAQ,MAAMtD,EAAI,OAClBqiB,EAAY,OAAO/e,EAAK,WAAc,SAAWA,EAAK,UAAU,OAAS,GAC/EV,EAAK,cAAgByf,GAAa,IACpC,MAAQ,CACNzf,EAAK,cAAgB,IACvB,CACF,CChNO,MAAM0f,EAAQ,CAEnB,cAAeC,4GACf,SAAUA,qJACV,KAAMA,kLACN,OAAQA,4XACR,MAAOA,iMACP,SAAUA,uQACV,IAAKA,6FACL,QAASA,iKACT,SAAUA,moBACV,IAAKA,obACL,WAAYA,4LACZ,OAAQA,qKACR,MAAOA,gMACP,KAAMA,sHAGN,KAAMA,mJACN,EAAGA,+EACH,MAAOA,8DACP,KAAMA,8JACN,OAAQA,4FACR,MAAOA,yhBACP,KAAMA,6GACN,OAAQA,qOACR,SAAUA,sHACV,UAAWA,2MACX,SAAUA,mKAGV,OAAQA,uMACR,SAAUA,2MACV,KAAMA,4KACN,QAASA,0HACT,UAAWA,8JACX,MAAOA,kJACP,SAAUA,0SACV,MAAOA,6KACP,WAAYA,iHACZ,KAAMA,kJACN,OAAQA,mEACR,YAAaA,4FACb,QAASA,4GACT,OAAQA,83BACR,KAAMA,6GACN,KAAMA,yFACN,MAAOA,oLACP,kBAAmBA,sXACnB,OAAQA,oFACR,IAAKA,0HACL,OAAQA,4RACR,MAAOA,qJACP,IAAKA,gLACL,YAAaA,2DACb,YAAaA,6DACb,aAAcA,4DACd,KAAMA,mOACN,KAAMA,wKACN,QAASA,oTACT,MAAOA,kHACP,SAAUA,iKACZ,EC9DMC,GAAWD,wSAEXE,GAAWF,wSAEXG,GAAYH,0RAElB,IAAII,GAAsB,GAC1B,SAASC,IAAmC,CACtCD,KACJA,GAAsB,GACtB,SAAS,iBAAiB,QAAU,GAAkB,CACpD,MAAME,EAAK,SAAS,eAAe,mBAAmB,EACtD,GAAI,EAACA,GAAA,MAAAA,EAAI,SAAS,OAClB,MAAM9lB,EAAS8lB,EAAG,QAAQ,eAAe,EACrC9lB,GAAA,MAAAA,EAAQ,SAAS,EAAE,UACvB8lB,EAAG,QAAU,GACf,CAAC,EACH,CAiCO,SAASC,GAAcC,EAAqBC,EAA6B,OAC9E,MAAMC,EAAO,CAACjmB,EAAekmB,IAC3BlmB,IAAU+lB,EACNR,sCAAyCvlB,CAAK,UAC9CulB,YAAeW,CAAI,IAAIlmB,CAAK,OAE5BmmB,EAAQZ;AAAAA,MACVU,EAAK,QAAS,QAAQ,CAAC;AAAA,MACvBA,EAAK,OAAQ,OAAO,CAAC;AAAA,MACrBA,EAAK,SAAU,SAAS,CAAC;AAAA,MACzBA,EAAK,WAAY,WAAW,CAAC;AAAA,MAC7BA,EAAK,QAAS,QAAQ,CAAC;AAAA,MACvBA,EAAK,UAAW,UAAU,CAAC;AAAA,MAC3BA,EAAK,WAAY,WAAW,CAAC;AAAA,IAK3BG,EADeJ,IAAYA,EAAQ,WAAa,IAAS,CAACA,EAAQ,SAEpEK,GAAwBL,CAAQ,EAChCM,EAEEC,EAAWP,GAAA,MAAAA,EAAS,SAAWA,EAAQ,SACzCT,0CAA6CS,EAAQ,QAAQ,iBAAiBR,EAAQ,YACtFc,EAEEE,EAAYR,GAAA,MAAAA,EAAS,iBACvBS,GAAoBT,EAAQ,gBAAgB,EAC5CM,EAEEI,GAAaV,GAAA,YAAAA,EAAS,aAAc,EACpCW,EAAUD,EAAa,IAAKV,GAAA,MAAAA,EAAS,cACvCT,yCAA4CS,EAAQ,YAAY;AAAA,UAC5DP,EAAQ;AAAA,wCACsBiB,EAAa,GAAK,MAAQA,CAAU;AAAA,iBAEtEJ,EAEEM,EAAc,IAAM,CACxB,MAAMf,EAAK,SAAS,eAAe,mBAAmB,EAClDA,MAAO,QAAU,GACvB,EAGA,OAAAD,GAAA,EAEOL;AAAAA;AAAAA;AAAAA;AAAAA,+CAIsCS,GAAA,YAAAA,EAAS,sBAAqB/uB,EAAA+C,GAAA,EAAqBgsB,EAAQ,iBAAiB,IAA9C,YAAA/uB,EAAiD,UAAY8C,GAAA,EAAe,OAAO,UAAUA,GAAA,EAAe,IAAI;AAAA;AAAA,YAEjLosB,CAAK;AAAA;AAAA;AAAA,YAGLC,IAAeE,EACbf,sCAAyCa,CAAU,UACnDE,CAAO;AAAA,YACTK,CAAO;AAAA,YACPJ,CAAQ;AAAA,YACRC,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kDAM6BI,CAAW;AAAA,UACnDR,IAAeE,EACbf,qCAAwCa,CAAU,SAClDE,CAAO;AAAA,UACTH,CAAK;AAAA;AAAA;AAAA,GAIf,CAEA,SAASM,GAAoBI,EAAuB,CAClD,IAAIC,EAAc,GA2BlB,OAAOvB;AAAAA;AAAAA,+CAzBcxvB,GAAa,CAEhC,MAAMiR,EADOjR,EAAE,cACO,QAAQ,wBAAwB,EACtD,GAAI,CAACiR,EAAW,OAChB,MAAM+f,EAAQ/f,EAAU,cAAc,sBAAsB,EACvD+f,IACLD,EAAc,CAACA,EACfC,EAAM,MAAM,QAAUD,EAAc,OAAS,OAC/C,CAmBwD;AAAA,UAChDpB,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA,2DAlBM3vB,GAAa,CAClC,MAAMiR,EAAajR,EAAE,cAA8B,QAAQ,wBAAwB,EAC7EgxB,EAAQ/f,GAAA,YAAAA,EAAW,cAAc,wBACnC+f,IAAOA,EAAM,MAAM,QAAU,QACjCD,EAAc,GACdD,EAAA,CACF,CAiBsE;AAAA,0DAfhD9wB,GAAa,CACjC,MAAMiR,EAAajR,EAAE,cAA8B,QAAQ,wBAAwB,EAC7EgxB,EAAQ/f,GAAA,YAAAA,EAAW,cAAc,wBACnC+f,IAAOA,EAAM,MAAM,QAAU,QACjCD,EAAc,EAChB,CAWoE;AAAA;AAAA;AAAA;AAAA,GAKtE,CAEA,SAAST,GAAwBL,EAA4B,CAC3D,KAAM,CAAE,WAAAgB,EAAY,kBAAAC,EAAmB,kBAAAC,CAAA,EAAsBlB,EAkB7D,OAAOT;AAAAA;AAAAA;AAAAA,eAGM0B,GAAqB,EAAE;AAAA,gBAnBdlxB,GAAa,CACjC,MAAMoxB,EAASpxB,EAAE,OACXmD,EAAQiuB,EAAO,MACrB,GAAIjuB,IAAU,UAAW,CAEvBiuB,EAAO,MAAQF,GAAqB,GAChCjB,EAAQ,aACVA,EAAQ,eAER,OAAO,SAAS,KAAO,SAEzB,MACF,CACAkB,EAAkBhuB,CAAK,CACzB,CAM0B;AAAA;AAAA,QAEpB8tB,EAAW,IACVtrB,GAAO6pB;AAAAA,0BACU7pB,EAAG,IAAI,cAAcA,EAAG,OAASurB,CAAiB;AAAA,cAC9DvrB,EAAG,aAAeA,EAAG,IAAI;AAAA;AAAA,UAGhC;AAAA;AAAA;AAAA;AAAA,GAKP,CCzLO,SAAS0rB,GAAoBC,EAA2B,CAC7D,OAAKA,EAAM,UAWPA,EAAM,YAAcA,EAAM,OACrB9B;AAAAA;AAAAA;AAAAA;AAAAA,kCAIuB8B,EAAM,UAAY,UAAY,WAAW;AAAA;AAAA,qBAEtDA,EAAM,aAAa;AAAA;AAAA,cAE1BA,EAAM,UAAY,YAAc,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKrCA,EAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAOrBA,EAAM,OAAO;AAAA,qBAChBA,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,gDAKeA,EAAM,UAAY,kBAAoB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,yBAK9DtxB,GAAkBsxB,EAAM,kBAAkBtxB,CAAC,CAAC;AAAA,uBAC9CA,GAAkBsxB,EAAM,gBAAgBtxB,CAAC,CAAC;AAAA,yBACxCA,GAAkBsxB,EAAM,kBAAkBtxB,CAAC,CAAC;AAAA,uBAC9CA,GAAqB,CAC/BA,EAAE,iBACFsxB,EAAM,gBAAgBtxB,CAAC,CACzB,CAAC;AAAA,qBACSA,GAAqB,CAC7BA,EAAE,iBACFsxB,EAAM,cAActxB,CAAC,CACvB,CAAC;AAAA,2BACeA,GAAaA,EAAE,gBAAgB;AAAA;AAAA;AAAA;AAAA,MAOlDwvB;AAAAA;AAAAA,QAEDO,GAAc,SAAS,CAAC;AAAA;AAAA;AAAA;;AAAA;AAAA,YAMpBuB,EAAM,OACJ9B;AAAAA;AAAAA,wCAE0B8B,EAAM,UAAY,UAAY,WAAW;AAAA;AAAA,2BAEtDA,EAAM,aAAa;AAAA;AAAA,oBAE1BA,EAAM,UAAY,YAAc,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKrCA,EAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAOrBA,EAAM,OAAO;AAAA,2BAChBA,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA,gBAKzB9B;AAAAA;AAAAA;AAAAA;AAAAA,8BAIgB8B,EAAM,OAAO;AAAA,2BAChBA,EAAM,OAAO;AAAA;AAAA,oBAEpBA,EAAM,QAAU,cAAgB,OAAO;AAAA;AAAA,eAE5C;AAAA;;AAAA,UAGLA,EAAM,MACJ9B,uDAA0D8B,EAAM,KAAK,SACrEf,CAAO;;AAAA,UAETe,EAAM,eACJ9B;AAAAA;AAAAA;AAAAA,sDAG0C8B,EAAM,eAAiB,2DAA2D;AAAA;AAAA,2HAEbA,EAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA,cAKtIf,CAAO;;AAAA;AAAA,YAGPe,EAAM,OACJ9B;AAAAA,6CAC+B8B,EAAM,UAAY,kBAAoB,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,iCAKnDtxB,GAAkBsxB,EAAM,kBAAkBtxB,CAAC,CAAC;AAAA,+BAC9CA,GAAkBsxB,EAAM,gBAAgBtxB,CAAC,CAAC;AAAA,iCACxCA,GAAkBsxB,EAAM,kBAAkBtxB,CAAC,CAAC;AAAA,+BAC9CA,GAAqB,CAC/BA,EAAE,iBACFsxB,EAAM,gBAAgBtxB,CAAC,CACzB,CAAC;AAAA,6BACSA,GAAqB,CAC7BA,EAAE,iBACFsxB,EAAM,cAActxB,CAAC,CACvB,CAAC;AAAA,mCACeA,GAAaA,EAAE,gBAAgB;AAAA;AAAA;AAAA,gBAIrDwvB;AAAAA;AAAAA,4DAE8CD,EAAM,KAAK;AAAA;AAAA;AAAA,eAGxD;AAAA;;AAAA,UAGL+B,EAAM,QAAUA,EAAM,UACpB9B;AAAAA;AAAAA,kBAGAe,CAAO;;AAAA;AAAA;AAAA,IA7JRf;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,KAkKX,CCvLA,MAAM+B,GAAqB,qCAG3B,IAAIC,GAA2D,KA6C/D,SAASC,GAAWllB,EAAmC,CACrD,OAA2BA,GAAU,KAAa,GAC9CA,EAAQ,KAAa,GAAGA,CAAK,KAC7BA,EAAQ,KAAO,KAAa,IAAIA,EAAQ,MAAM,QAAQ,CAAC,CAAC,MACrD,IAAIA,GAAS,KAAO,OAAO,QAAQ,CAAC,CAAC,KAC9C,CAGA,SAASie,GAAUrB,EAA0B,CAC3C,MAAMxhB,EAAQwhB,EAAS,MAAM,GAAG,EAChC,OAAOxhB,EAAM,OAAS,EAAIA,EAAM,MAAM,EAAG,EAAE,EAAE,KAAK,GAAG,EAAI,GAC3D,CAEA,SAAS+pB,GAAc,EAAcxH,EAAiBoH,EAAmB,SACvE,EAAE,iBACF,EAAE,kBACD,EAAE,cAA8B,UAAU,OAAO,gBAAgB,EAGlE,MAAMK,GAAezwB,EAAA,EAAE,eAAF,YAAAA,EAAgB,QAAQqwB,IAC7C,GAAII,EAAc,CAEZnH,GAAUmH,CAAY,IAAMzH,GAC9BoH,EAAM,YAAYK,EAAczH,CAAO,EAEzC,MACF,CAGA,MAAMC,GAAQhpB,EAAA,EAAE,eAAF,YAAAA,EAAgB,MAC9B,GAAIgpB,GAASA,EAAM,OAAS,EAAG,CAC7B,MAAMyH,EAAU,MAAM,KAAKzH,CAAK,EAAE,OAAQppB,GAAMA,EAAE,KAAK,cAAc,SAAS,KAAK,CAAC,EAChF6wB,EAAQ,OAAS,GAAGN,EAAM,SAASpH,EAAS0H,CAAO,CACzD,CACF,CAEA,SAASC,GACPviB,EACAgiB,EACAQ,EACS,OACT,MAAMC,EAAQziB,EAAM,OAAS,aAAgBA,EAAM,OAAS,WAAaA,EAAM,UAAY,KACrF0iB,EAAaV,EAAM,aAAa,IAAIhiB,EAAM,IAAI,EAC9C2iB,EAAaX,EAAM,cAAc,IAAIhiB,EAAM,IAAI,EAC/C4iB,EAAYZ,EAAM,aAAehiB,EAAM,KACvC6iB,EAASL,EAAQ,GAAK,GAE5B,OAAIC,EACKvC;AAAAA;AAAAA,0CAE+BwC,EAAa,WAAa,EAAE,IAAIE,EAAY,UAAY,EAAE;AAAA,+BACrEC,CAAM;AAAA,iBACpB,IAAMb,EAAM,YAAYhiB,EAAM,IAAI,CAAC;AAAA,oBAC/BtP,GAAiB,CAC5BA,EAAE,iBACFA,EAAE,kBACEA,EAAE,eAAcA,EAAE,aAAa,WAAa,QAC/CA,EAAE,cAA8B,UAAU,IAAI,gBAAgB,CACjE,CAAC;AAAA,qBACaA,GAAiB,CAC5BA,EAAE,cAA8B,UAAU,OAAO,gBAAgB,CACpE,CAAC;AAAA,gBACQA,GAAiB0xB,GAAc1xB,EAAGsP,EAAM,KAAMgiB,CAAK,CAAC;AAAA;AAAA,wCAE7BU,EAAa,IAAM,GAAG;AAAA,qCACzBzC,EAAM,MAAM;AAAA,qCACZjgB,EAAM,IAAI;AAAA,UACrC0iB,KAAc9wB,EAAAoO,EAAM,WAAN,YAAApO,EAAgB,UAAW,EACvCsuB;AAAAA;AAAAA;AAAAA,uBAGYxvB,GAAkB,CAC1BA,EAAE,kBACFsxB,EAAM,SAAShiB,EAAM,IAAI,CAC3B,CAAC;AAAA,uBAEHihB,CAAO;AAAA;AAAA,QAEXyB,GAAc1iB,EAAM,SAClBA,EAAM,SAAS,IAAK8iB,GAAUP,GAAgBO,EAAOd,EAAOQ,EAAQ,CAAC,CAAC,EACtEvB,CAAO;AAAA,MAIRf;AAAAA;AAAAA,yCAEgCyC,EAAa,WAAa,EAAE;AAAA,6BACxCE,CAAM;AAAA;AAAA,eAEnBnyB,GAAkB,CACtBA,EAAE,SAAWA,EAAE,QACjBsxB,EAAM,mBAAmBhiB,EAAM,IAAI,EAEnCgiB,EAAM,aAAahiB,EAAM,IAAI,CAEjC,CAAC;AAAA,mBACatP,GAAiB,CACxBA,EAAE,eACPA,EAAE,aAAa,cAAgB,OAC/BA,EAAE,aAAa,QAAQuxB,GAAoBjiB,EAAM,IAAI,EACrDtP,EAAE,aAAa,QAAQ,aAAcsP,EAAM,IAAI,EACjD,CAAC;AAAA;AAAA,mCAE4BigB,EAAM,QAAQ;AAAA,mCACdjgB,EAAM,IAAI;AAAA,mCACVmiB,GAAWniB,EAAM,IAAI,CAAC;AAAA;AAAA,GAGzD,CAEA,SAAS+iB,GAAkBf,EAAmB,CAC5C,MAAMgB,EAAQhB,EAAM,cAAc,KAClC,OAAIgB,EAAQ,EAAU/B,EAEff;AAAAA;AAAAA,wEAE+D8C,CAAK;AAAA;AAAA;AAAA;AAAA,iBAI5DhB,EAAM,cAAc;AAAA;AAAA,mBAElBgB,CAAK;AAAA;AAAA;AAAA,GAIxB,CAEA,SAASC,GAAcjB,EAAmB,CAGxC,GADIA,EAAM,cAAc,OAAS,GAC7B,CAACA,EAAM,aAAc,OAAOf,EAEhC,GAAIe,EAAM,eACR,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,MAOT,MAAM1F,EAAWwH,EAAM,aAAa,MAAM,GAAG,EAAE,OAASA,EAAM,aAE9D,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,oBAIW1F,CAAQ;AAAA;AAAA,cAEdwH,EAAM,YAAY,GAAGA,EAAM,aAAe,KAAO,MAAMG,GAAWH,EAAM,WAAW,CAAC,GAAK,EAAE;AAAA;AAAA;AAAA;AAAA,sGAIH,IAAMA,EAAM,WAAWA,EAAM,YAAa,CAAC;AAAA;AAAA;AAAA,mGAG9C,IAAM,CACzFA,EAAM,oBAAsBA,EAAM,cAEhCE,iBAAiCA,EAAkB,EACvDA,GAAqB,KACrBF,EAAM,SAASA,EAAM,YAAa,IAGlCA,EAAM,YAAYA,EAAM,YAAa,EACjCE,iBAAiCA,EAAkB,EACvDA,GAAqB,WAAW,IAAM,CACpCF,EAAM,YAAY,EAAE,EACpBE,GAAqB,IACvB,EAAG,GAAI,EAEX,CAAC;AAAA,cACGF,EAAM,oBAAsBA,EAAM,aAAe,kBAAoB,QAAQ;AAAA;AAAA;AAAA;AAAA,QAInFA,EAAM,cACJ9B,+HACA8B,EAAM,gBAAkB,KACtB9B,gEAAmE8B,EAAM,cAAc,eACvF9B,qIAAwI;AAAA;AAAA,GAGpJ,CAmBA,SAASgD,GAAgBlB,EAAmB,CAC1C,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,iBAMQ8B,EAAM,WAAW;AAAA,iBAChBtxB,GAAasxB,EAAM,oBAAqBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA,mBAC1EA,GAAqB,CAC3BA,EAAE,MAAQ,SAASsxB,EAAM,SAASA,EAAM,WAAW,CACzD,CAAC;AAAA;AAAA,QAEDA,EAAM,SAAS,OAAS,EACtB9B;AAAAA;AAAAA,sBAEaxvB,GAAasxB,EAAM,oBAAqBtxB,EAAE,OAA6B,KAAK,CAAC;AAAA;AAAA,cAEtFsxB,EAAM,SAAS,IACdplB,GAAOsjB,kBAAqBtjB,CAAE,cAAcA,IAAOolB,EAAM,aAAa,IAAIplB,CAAE,YAC9E;AAAA,qBAEHqkB,CAAO;AAAA;AAAA;AAAA;AAAA,oBAIGe,EAAM,eAAiB,CAACA,EAAM,YAAY,MAAM;AAAA,iBACnD,IAAMA,EAAM,SAASA,EAAM,WAAW,CAAC;AAAA;AAAA,UAE9CA,EAAM,cAAgB,eAAiB,QAAQ;AAAA;AAAA,QAEjDA,EAAM,gBAAkB,KACtB9B;AAAAA;AAAAA;AAAAA,qBAGW8B,EAAM,aAAa;AAAA;AAAA;AAAA,qBAI9Bf,CAAO;AAAA;AAAA,GAGjB,CAEA,SAASkC,GAAoBnB,EAAmB,CAC9C,OAAKA,EAAM,cAEPA,EAAM,cAAc,SAAW,EAC1B9B;AAAAA;AAAAA,YAKFA;AAAAA;AAAAA,QAED8B,EAAM,cAAc,IACnBlxB,GAAMovB;AAAAA;AAAAA,sCAEuB8B,EAAM,eAAiBlxB,EAAE,KAAO,WAAa,EAAE;AAAA,qBAChE,IAAMkxB,EAAM,aAAalxB,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA,oDAGDA,EAAE,IAAI;AAAA,sDACJA,EAAE,MAAQ,KAAK,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA,sBAGzDA,EAAE,SAAS,SAASA,EAAE,OAAO,WAAWA,EAAE,MAAM;AAAA;AAAA,oDAElBA,EAAE,OAAO;AAAA;AAAA,UAGtD;AAAA;AAAA,IA1B4BmwB,CA6BnC,CAEO,SAASmC,GAAYpB,EAAmB,CAC7C,MAAMqB,EAAerB,EAAM,WAE3B,OAAKA,EAAM,UAWJ9B;AAAAA;AAAAA,QAEDO,GAAc,QAASuB,EAAM,OAAO,CAAC;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,oBAOzBqB,IAAiB,IAAMnD,YAAemD,CAAY,QAAUpC,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAM9DvwB,GAAa,CACtB,MAAMuD,EAAQvD,EAAE,OACZuD,EAAM,OAASA,EAAM,MAAM,OAAS,IACtC+tB,EAAM,SAASqB,EAAc,MAAM,KAAKpvB,EAAM,KAAK,CAAC,EACpDA,EAAM,MAAQ,GAElB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMM,IAAM,CACb,MAAMC,EAAO,OAAO,cAAc,EAC9BA,GAAA,MAAAA,EAAM,QAAQ8tB,EAAM,YAAYqB,EAAcnvB,EAAK,MAAM,CAC/D,CAAC;AAAA;AAAA,wBAEWmvB,IAAiB,IAAMnD,YAAemD,CAAY,QAAUpC,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA,wBAKnEe,EAAM,OAAO;AAAA,qBAChBA,EAAM,SAAS;AAAA;AAAA,cAEtBA,EAAM,QAAU,aAAe,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,wBAK9BA,EAAM,WAAW;AAAA,qBACpBA,EAAM,SAAS;AAAA;AAAA,cAEtBA,EAAM,YAAc,iBAAmB,UAAU;AAAA;AAAA,YAEnDA,EAAM,aACJA,EAAM,aAAa,iBAAmB,cACpC9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,yBAOAA;AAAAA;AAAAA;AAAAA,oEAGoD8B,EAAM,aAAa,QAAU,UAAYA,EAAM,aAAa,MAAQ,UAAY,SAAS;AAAA;AAAA,qBAExI,IAAM,OAEP,GAAIA,EAAM,aAAc,SAAWA,EAAM,aAAc,aAAc,CACnE,KAAM,CAAE,UAAAsB,EAAW,MAAAzlB,EAAO,MAAAlD,CAAA,EAAUqnB,EAAM,aAAc,aACxD,OAAIrnB,IACGkD,EAAQ,EAAI,YAAYylB,CAAS,IAAIzlB,CAAK,UAAiB,YACpE,CACA,MAAM0lB,EAAUvB,EAAM,aAAc,MAC9BvG,EAASuG,EAAM,aAAc,OAC7BwB,EAAW,GAAGD,CAAO,QAAQA,IAAY,EAAI,IAAM,EAAE,KAAK9H,CAAM,UAChEgI,GAAQ7xB,EAAAowB,EAAM,eAAN,YAAApwB,EAAoB,MAClC,GAAI,CAAC6xB,EAAO,OAAOD,EAGnB,MAAME,GADWD,EAAM,SAAS,GAAG,EAAIA,EAAM,MAAM,GAAG,EAAE,MAASA,GACvC,QAAQ,cAAe,EAAE,EAAE,QAAQ,WAAY,EAAE,EAC3E,MAAO,GAAGD,CAAQ,MAAME,CAAQ,EAClC,IAAI;AAAA,yBAERzC,CAAO;AAAA;;AAAA,UAGXe,EAAM,MACJ9B,uDAA0D8B,EAAM,KAAK,SACrEf,CAAO;;AAAA,UAETe,EAAM,QACJ9B,gBAAmB8B,EAAM,QAAQ,OAAS,QAAU,cAAgB,uBAAuB;AAAA,gBACvFA,EAAM,QAAQ,IAAI;AAAA,oBAEtBf,CAAO;;AAAA,UAETe,EAAM,WACJ9B,qHACAe,CAAO;;AAAA,UAETiC,GAAgBlB,CAAK,CAAC;;AAAA,UAEtBA,EAAM,gBAAkB,KACtBmB,GAAoBnB,CAAK,EACzB9B;AAAAA;AAAAA,0BAEexvB,GAAiB,CAC5BA,EAAE,iBACEA,EAAE,eAAcA,EAAE,aAAa,WAAaA,EAAE,aAAa,MAAM,SAASuxB,EAAkB,EAAI,OAAS,OAC/G,CAAC;AAAA,sBACQvxB,GAAiB,SACxBA,EAAE,iBAEF,MAAM2xB,GAAezwB,EAAAlB,EAAE,eAAF,YAAAkB,EAAgB,QAAQqwB,IAC7C,GAAII,EAAc,CACZnH,GAAUmH,CAAY,IAAM,KAC9BL,EAAM,YAAYK,EAAc,GAAG,EAErC,MACF,CAEA,MAAMxH,GAAQhpB,EAAAnB,EAAE,eAAF,YAAAmB,EAAgB,MAC9B,GAAIgpB,GAASA,EAAM,OAAS,EAAG,CAC7B,MAAMyH,EAAU,MAAM,KAAKzH,CAAK,EAAE,OAAQppB,GAAMA,EAAE,KAAK,cAAc,SAAS,KAAK,CAAC,EAChF6wB,EAAQ,OAAS,GAAGN,EAAM,SAASqB,EAAcf,CAAO,CAC9D,CACF,CAAC;AAAA;AAAA,gBAECN,EAAM,KAAK,SAAW,GAAK,CAACA,EAAM,QAChC9B,yIACA8B,EAAM,KAAK,IAAKhiB,GAAUuiB,GAAgBviB,EAAOgiB,EAAO,CAAC,CAAC,CAAC;AAAA,mBAC1D;;AAAA,UAETe,GAAkBf,CAAK,CAAC;AAAA,UACxBiB,GAAcjB,CAAK,CAAC;AAAA;AAAA;AAAA,IA/InB9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,KAmJX,CCxdA,MAAMyD,GAAqB,4BAa3B,eAAsBC,GAAapmB,EAAsC,SACvE,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,cAEV,CAAAA,EAAM,cAAgB,GACtBA,EAAM,eAAiB,MACvB5L,EAAA4L,EAAM,gBAAN,MAAA5L,EAAA,KAAA4L,GAGAqmB,GAAA,EAEA,GAAI,CACF,MAAMrmB,EAAM,OAAO,QAAQ,mBAAoB,CAC7C,OAAQ,CAAC,UAAW,QAAS,WAAW,EACxC,MAAO,GACR,CACH,MAAQ,CAER,CAEAA,EAAM,cAAgB,GACtBA,EAAM,cAAgB,IACtB3L,EAAA2L,EAAM,gBAAN,MAAA3L,EAAA,KAAA2L,GACF,CAEO,SAASsmB,IAA8B,CAC5C,GAAI,CACF,OAAO,aAAa,QAAQH,EAAkB,IAAM,GACtD,MAAQ,CACN,MAAO,EACT,CACF,CAEO,SAASI,IAA2B,CACzC,GAAI,CACF,aAAa,WAAWJ,EAAkB,CAC5C,MAAQ,CAAe,CACzB,CAEA,SAASE,IAA0B,CACjC,GAAI,CACF,aAAa,QAAQF,GAAoB,GAAG,CAC9C,MAAQ,CAAe,CACzB,iKCyQA,SAASK,EAAkBld,EAAgD,CAOzE,OAAOoZ;AAAAA;AAAAA;AAAAA,2BANQ,CACb,KAAM,UACN,IAAK,UACL,QAAS,UACT,QAAS,WAKqBpZ,CAAM,CAAC;AAAA;AAAA,GAGzC,CAGA,SAASmd,GAAiBrnB,EAAYY,EAAuB,CAC3D,OAAO0iB;AAAAA;AAAAA;AAAAA,eAGM,IAAM1iB,EAAM,gBAAgBZ,CAAE,CAAC;AAAA;AAAA;AAAA,QAGtCqjB,EAAM,IAAI;AAAA;AAAA,GAGlB,CAGA,SAASiE,GAAgB1mB,EAAuB,OAC9C,GAAI,CAACA,EAAM,cAAe,OAAOyjB,EAEjC,IAAIxX,EAAQ,GACR0a,EAAoE,GACpEC,EAA0DnD,EAE9D,OAAQzjB,EAAM,eACZ,IAAK,UAAW,CACd,MAAM6mB,EAAO,OAAO,OAAW,IAAc,OAAO,SAAS,KAAO,UACpE5a,EAAQ,UACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAO3mB,EAAM,iBAAmB,GAAQ,UAAY,WACvE,CAAE,MAAO,OAAQ,MAAO,mHACxB,CAAE,MAAO,UAAW,MAAO6mB,CAAA,EAC3B,CAAE,MAAO,SAAU,MAAO7mB,EAAM,sBAAwB,KAAK,EAE/D,KACF,CACA,IAAK,SAAU,CACb,MAAM8mB,EAAO9mB,EAAM,cACnB,IAAI+mB,EAAa,MACjB,GAAID,GAAQ,MAAQA,EAAO,EACzB,GAAIA,EAAO,GAAI,CACb,MAAMnzB,EAAI,KAAK,MAAMmzB,EAAO,EAAE,EACxBryB,EAAIqyB,EAAO,GACjBC,EAAatyB,EAAI,EAAI,GAAGd,CAAC,KAAKc,CAAC,IAAM,GAAGd,CAAC,GAC3C,MACEozB,EAAa,GAAGD,CAAI,IAWxB,GARA7a,EAAQ,SACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAO3mB,EAAM,cAAgB,YAAc,gBAC9D,CAAE,MAAO,OAAQ,MAAO,8EACxB,CAAE,MAAO,MAAO,MAAO,2EACvB,CAAE,MAAO,eAAgB,MAAO+mB,CAAA,EAChC,GAAI/mB,EAAM,YAAc,CAAC,CAAE,MAAO,UAAW,MAAOA,EAAM,YAAa,EAAI,EAAC,EAE1EA,EAAM,iBAAkB,CAC1B,MAAM+J,EAAQ/J,EAAM,iBACd4C,EAAYmH,EAAM,OAAS,GAC7B,GAAGA,EAAM,MAAM,EAAG,CAAC,CAAC,MAAMA,EAAM,MAAM,EAAE,CAAC,GACzCA,EACJ6c,EAAgBlE;AAAAA;AAAAA;AAAAA,yGAGiF9f,CAAS;AAAA,+EACnC,MAAO1P,GAAa,CACrF,MAAM8zB,EAAM9zB,EAAE,cACd,GAAI,CAAE,MAAM,UAAU,UAAU,UAAU6W,CAAK,CAAG,MAAQ,CACxD,MAAMkd,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQld,EAAOkd,EAAG,MAAM,SAAW,QAASA,EAAG,MAAM,QAAU,IAClE,SAAS,KAAK,YAAYA,CAAE,EAAGA,EAAG,SAAU,SAAS,YAAY,MAAM,EAAG,SAAS,KAAK,YAAYA,CAAE,CACxG,CACAD,EAAI,UAAU,IAAI,QAAQ,EAC1B,WAAW,IAAMA,EAAI,UAAU,OAAO,QAAQ,EAAG,IAAI,CACvD,CAAC,IAAIvE,EAAM,IAAI;AAAA;AAAA,SAGrB,CACA,KACF,CACA,IAAK,UAAW,CACd,MAAMyE,EAAYlnB,EAAM,iBACpB,IAASA,EAAM,iBAAiB,MAAM,GAAG,CAAC,GAC1C,MACJiM,EAAQ,UACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAO3mB,EAAM,aAAe,SAAW,YAC1D,CAAE,MAAO,OAAQ,MAAO,6DACxB,CAAE,MAAO,MAAO,MAAOknB,CAAA,EACvB,CAAE,MAAO,OAAQ,MAAOlnB,EAAM,aAAe,YAC7C,CAAE,MAAO,YAAa,MAAOA,EAAM,iBAAmB,MAAO,SAAU,CAAC,CAACA,EAAM,gBAAgB,EAEjG,KACF,CACA,IAAK,WAAY,CACf,MAAMnH,EAAKsuB,GAAqBnnB,CAAK,EAC/BjG,EAAUlB,EAAKuuB,GAAyBvuB,EAAImH,CAAK,EAAI,KAC3DiM,EAAQ,WACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAO5sB,GAAA,MAAAA,EAAS,UAAY,YAAc,gBAC7D,CAAE,MAAO,OAAQ,MAAO,oFACxB,CAAE,MAAO,MAAO,MAAO,mGACvB,CAAE,MAAO,UAAW,OAAOA,GAAA,YAAAA,EAAS,QAAQA,GAAA,YAAAA,EAAS,YAAa,WAClE,CAAE,MAAO,QAAS,QAAO3F,EAAA2F,GAAA,YAAAA,EAAS,OAAT,YAAA3F,EAAe,OAAQ,cAChD,CAAE,MAAO,SAAU,MAAO2F,GAAA,MAAAA,EAAS,OAAS,MAAQ,MACpD,GAAIA,GAAA,MAAAA,EAAS,UAAY,CAAC,CAAE,MAAO,aAAc,MAAOstB,GAAmBttB,EAAQ,SAAS,EAAG,EAAI,EAAC,EAEtG,KACF,CACA,IAAK,WAAY,CACf,KAAM,CAAE,WAAYutB,GAAcC,GAAqBvnB,CAAK,EAC5DiM,EAAQ,WACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAOW,GAAatnB,EAAM,kBAAoB,YAAc,gBAC/E,CAAE,MAAO,OAAQ,MAAO,oFACxB,CAAE,MAAO,MAAO,MAAO,iGACvB,CAAE,MAAO,cAAe,MAAOA,EAAM,wBAA0B,gBAC/D,CAAE,MAAO,OAAQ,MAAO,kBACxB,GAAIA,EAAM,kBAAoB,CAAC,CAAE,MAAO,aAAc,MAAOA,EAAM,kBAAmB,EAAI,EAAC,EAE7F,KACF,CACA,IAAK,SAAU,CACbiM,EAAQ,kBACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAO3mB,EAAM,kBAAoB,KAAO,cAAgBA,EAAM,gBAAkB,mBAAqB,cACxH,CAAE,MAAO,OAAQ,MAAO,oFACxB,CAAE,MAAO,UAAW,MAAOA,EAAM,eAAiB,IAAIA,EAAM,cAAc,GAAK,WAC/E,CAAE,MAAO,SAAU,MAAOA,EAAM,cAAgB,IAAIA,EAAM,aAAa,GAAK,WAC5E,GAAIA,EAAM,cAAgB,CAAC,CAAE,MAAO,UAAW,MAAOA,EAAM,cAAe,EAAI,EAAC,EAElF,KACF,CACA,IAAK,gBAAiB,CACpB,MAAMwnB,EAAKxnB,EAAM,gBACXsJ,EAAUke,EAEXA,EAAG,UAEDA,EAAG,SAEFA,EAAG,cAAgBA,EAAG,YACpB,SACAA,EAAG,cAAgB,CAACA,EAAG,YACrB,yBACA,MALJ,gBAFF,gBAFF,cAmBJ,GATAvb,EAAQ,gBACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAOrd,CAAA,EAC1B,CAAE,MAAO,OAAQ,MAAO,mGACxB,CAAE,MAAO,MAAO,MAAO,mHACvB,CAAE,MAAO,WAAY,MAAO,8IAC5B,CAAE,MAAO,kBAAmB,MAAO,kFACnC,CAAE,MAAO,OAAQ,MAAO,yDAAyD,EAE/Eke,GAAA,MAAAA,EAAI,WAAY,CAClB,MAAMliB,EAAMkiB,EAAG,WACfZ,EAAgBlE;AAAAA,YACZ1iB,EAAM,sBACJ0iB;AAAAA,2BACa1iB,EAAM,qBAAqB;AAAA,sBAExCyjB,CAAO;AAAA;AAAA,uBAEEne,CAAG;AAAA;AAAA,eAEXA,CAAG;AAAA,qEACmD,MAAOpS,GAAa,CAC3E,MAAM8zB,EAAM9zB,EAAE,cACd,GAAI,CAAE,MAAM,UAAU,UAAU,UAAUoS,CAAG,CAAG,MAAQ,CACtD,MAAM2hB,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQ3hB,EAAK2hB,EAAG,MAAM,SAAW,QAASA,EAAG,MAAM,QAAU,IAChE,SAAS,KAAK,YAAYA,CAAE,EAAGA,EAAG,SAAU,SAAS,YAAY,MAAM,EAAG,SAAS,KAAK,YAAYA,CAAE,CACxG,CACAD,EAAI,UAAU,IAAI,QAAQ,EAC1B,WAAW,IAAMA,EAAI,UAAU,OAAO,QAAQ,EAAG,IAAI,CACvD,CAAC,IAAIvE,EAAM,IAAI;AAAA;AAAA,SAGrB,CACA,KACF,CACA,IAAK,cAAe,CAYlB,GAXAxW,EAAQ,cACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAO3mB,EAAM,kBAAoB,UAAY,YAChE,CAAE,MAAO,OAAQ,MAAO,4EACxB,CAAE,MAAO,WAAY,MAAO,4GAC5B,CAAE,MAAO,cAAe,MAAOynB,GAAiBznB,EAAM,kBAAkB,GAAK,eAC7E,CAAE,MAAO,WAAY,MAAO,iFAC5B,CAAE,MAAO,MAAO,MAAO,sIACvB,CAAE,MAAO,QAAS,MAAO,8IACzB,CAAE,MAAO,WAAY,MAAO,kHAAkH,EAE5IA,EAAM,mBAAqBA,EAAM,kBAAmB,CACtD,MAAMsF,EAAMtF,EAAM,kBAClB4mB,EAAgBlE;AAAAA,YACZ1iB,EAAM,oBACJ0iB;AAAAA,2BACa1iB,EAAM,mBAAmB;AAAA,sBAEtCyjB,CAAO;AAAA;AAAA,uBAEEne,CAAG;AAAA;AAAA,eAEXA,CAAG;AAAA,qEACmD,MAAOpS,GAAa,CAC3E,MAAM8zB,EAAM9zB,EAAE,cACd,GAAI,CAAE,MAAM,UAAU,UAAU,UAAUoS,CAAG,CAAG,MAAQ,CACtD,MAAM2hB,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQ3hB,EAAK2hB,EAAG,MAAM,SAAW,QAASA,EAAG,MAAM,QAAU,IAChE,SAAS,KAAK,YAAYA,CAAE,EAAGA,EAAG,SAAU,SAAS,YAAY,MAAM,EAAG,SAAS,KAAK,YAAYA,CAAE,CACxG,CACAD,EAAI,UAAU,IAAI,QAAQ,EAC1B,WAAW,IAAMA,EAAI,UAAU,OAAO,QAAQ,EAAG,IAAI,CACvD,CAAC,IAAIvE,EAAM,IAAI;AAAA;AAAA,SAGrB,CACA,KACF,CACA,IAAK,eAAgB,CACnBxW,EAAQ,eACR0a,EAAO,CACL,CAAE,MAAO,OAAQ,MAAO,+EACxB,CAAE,MAAO,WAAY,MAAO,uDAC5B,CAAE,MAAO,YAAa,MAAO,+EAC7B,CAAE,MAAO,QAAS,MAAO,6FAA6F,EAExH,KACF,CACA,IAAK,cAAe,CAClB1a,EAAQ,cACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAO3mB,EAAM,cAAgB,MAAQ,WACxD,CAAE,MAAO,OAAQ,MAAO,iEACxB,CAAE,MAAO,cAAe,MAAO,wEAC/B,CAAE,MAAO,SAAU,MAAO,gBAAgB,EAE5C,KACF,CACA,IAAK,WAAY,CACf,MAAM0nB,EAAS,GAAQ1nB,EAAM,kBAAoBA,EAAM,sBAAwBA,EAAM,cACrFiM,EAAQ,WACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAOe,EAAS,aAAe,WAClD,CAAE,MAAO,OAAQ,MAAO,8FACxB,CAAE,MAAO,OAAQ,MAAO,2DACxB,CAAE,MAAO,gBAAiB,MAAO,qDACjC,CAAE,MAAO,kBAAmB,MAAO,6DACnC,CAAE,MAAO,QAAS,MAAO,uFAAuF,EAElH,KACF,CACA,IAAK,WAAY,CAEf,MAAMC,EADc3nB,EAAM,gBACO,OAAQlM,GAAMA,EAAE,MAAM,EAAE,OACzDmY,EAAQ,WACR0a,EAAO,CACL,CAAE,MAAO,SAAU,MAAOgB,EAAe,EAAI,GAAGA,CAAY,cAAgB,mBAC5E,CAAE,MAAO,OAAQ,MAAO,qHACxB,CAAE,MAAO,WAAY,MAAO,oEAC5B,CAAE,MAAO,QAAS,MAAO,yDAAyD,EAEpF,KACF,CACA,IAAK,UAAW,CACd1b,EAAQ,UACR0a,EAAO,CACL,CAAE,MAAO,UAAW,MAAO3mB,EAAM,gBAAkB,GAAGA,EAAM,eAAe,UAAUA,EAAM,WAAW,GAAK,QAAQA,EAAM,WAAW,IACpI,CAAE,MAAO,OAAQ,MAAO,gEACxB,CAAE,MAAO,iBAAkB,MAAO,iHAClC,CAAE,MAAO,eAAgB,MAAO,qEAAqE,EAEvG,KACF,CACA,QACE,OAAOyjB,CAAA,CAGX,OAAOf;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,kBAEV,CAAC;AAAA;AAAA,cAESiM,CAAK;AAAA,UACT2a,CAAa;AAAA,UACbD,EAAK,IACJiB,GAAQlF;AAAAA;AAAAA,+CAE4BkF,EAAI,KAAK;AAAA,+CACTA,EAAI,KAAK;AAAA,gBACxCA,EAAI,SACFlF;AAAAA;AAAAA,kCAEgBkF,EAAI,KAAK;AAAA,6BACd,MAAO10B,GAAa,CAC3B,MAAM8zB,EAAM9zB,EAAE,cACd,GAAI,CACF,MAAM,UAAU,UAAU,UAAU00B,EAAI,KAAK,EAC7CZ,EAAI,YAAc,UAClB,WAAW,IAAM,CAAEA,EAAI,YAAc,MAAQ,EAAG,IAAI,CACtD,MAAQ,CACN,MAAMC,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQW,EAAI,MACfX,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,QAAU,IACnB,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,SACH,SAAS,YAAY,MAAM,EAC3B,SAAS,KAAK,YAAYA,CAAE,EAC5BD,EAAI,YAAc,UAClB,WAAW,IAAM,CAAEA,EAAI,YAAc,MAAQ,EAAG,IAAI,CACtD,CACF,CAAC;AAAA,kCAEHvD,CAAO;AAAA;AAAA,YAGhB;AAAA;AAAA;AAAA;AAAA,mBAIUzjB,EAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAOzC,CAEA,SAAS6nB,GAAoBC,EAAwB,CACnD,MAAMC,EAAQ,CACZ,CAAE,GAAI,UAAW,MAAO,uBACxB,CAAE,GAAI,OAAQ,MAAO,qBACrB,CAAE,GAAI,QAAS,MAAO,mBAAmB,EAGrCC,EAAY,CAAC,UAAW,OAAQ,OAAO,EACvCC,EAAeD,EAAU,QAAQF,CAAW,EAElD,OAAOpF;AAAAA;AAAAA,QAEDqF,EAAM,IAAKG,GAAS,CACpB,MAAMC,EAAYH,EAAU,QAAQE,EAAK,EAAE,EACrCE,EAAWN,IAAgBI,EAAK,GAChCG,EAAcJ,EAAeE,EACnC,OAAOzF;AAAAA;AAAAA,gCAEiB0F,EAAW,SAAW,EAAE,IAAIC,EAAc,YAAc,EAAE;AAAA;AAAA;AAAA,6CAG7CH,EAAK,KAAK;AAAA;AAAA,SAGjD,CAAC,CAAC;AAAA;AAAA,GAGR,CAEA,SAASI,GAAkBtoB,EAAuB,CAChD,KAAM,CACJ,WAAAuoB,EACA,YAAAC,EACA,aAAAC,EACA,eAAAC,EACA,gBAAAC,EACA,mBAAAC,EACA,kBAAAC,CAAA,EACE7oB,EAGJ,OAAIyoB,IAAiB,GACZ/F;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,SAAS,CAAC;AAAA;AAAA,cAE5BrB,EAAkB,MAAM,CAAC;AAAA;AAAA;AAAA,eAGxBkC,GAAkB,yBAAyB;AAAA;AAAA;AAAA,MAOpDF,GAAe,CAACD,EACX7F;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MASjCnF;AAAAA;AAAAA;AAAAA,UAGCmF,GAAoB,SAAS,CAAC;AAAA;AAAA;AAAA,UAG9Bc,EACEjG;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,sDAM0CiG,CAAe;AAAA;AAAA;AAAA;AAAA,2BAI1C,MAAOz1B,GAAa,CAC3B,MAAM8zB,EAAM9zB,EAAE,cACd,GAAI,CACF,MAAM,UAAU,UAAU,UAAUy1B,CAAe,EACnD3B,EAAI,YAAc,UAClB,WAAW,IAAM,CAAEA,EAAI,YAAc,MAAQ,EAAG,IAAI,CACtD,MAAQ,CAEN,MAAMC,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQ0B,EACX1B,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,QAAU,IACnB,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,SACH,SAAS,YAAY,MAAM,EAC3B,SAAS,KAAK,YAAYA,CAAE,EAC5BD,EAAI,YAAc,UAClB,WAAW,IAAM,CAAEA,EAAI,YAAc,MAAQ,EAAG,IAAI,CACtD,CACF,CAAC;AAAA;AAAA;AAAA,cAIPvD,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKE8E,CAAU;AAAA,qBACTr1B,GACR01B,EAAoB11B,EAAE,OAA4B,KAAK,CAAC;AAAA,uBAC9CA,GAAqB,CAC3BA,EAAE,MAAQ,SAAWq1B,EAAW,QAClCM,EAAA,CAEJ,CAAC;AAAA;AAAA;AAAA;AAAA,wBAIW,CAACN,EAAW,QAAUC,CAAW;AAAA,qBACpCK,CAAiB;AAAA;AAAA,cAExBL,EAAc,gBAAkB,UAAU;AAAA;AAAA;AAAA,UAG9CC,IAAiB,IAASC,EACxBhG;AAAAA;AAAAA,kBAEM8D,EAAkB,KAAK,CAAC;AAAA,4CACEkC,CAAc;AAAA;AAAA,cAG9CjF,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAUnB,CAEA,SAASqF,GAAe9oB,EAAuB,CAC7C,KAAM,CACJ,cAAA+oB,EACA,SAAAC,EACA,YAAAC,EACA,QAAAC,EACA,cAAAC,EACA,cAAAC,EACA,YAAAC,EACA,iBAAAC,EACA,iBAAAC,CAAA,EACEvpB,EAGJ,OAAI+oB,IAAkB,GACbrG;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,MAAM,CAAC;AAAA;AAAA,cAEzBrB,EAAkB,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,cAKzB4C,EACE1G;AAAAA,kCACkB0G,CAAa;AAAA,qBAE/B3F,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcjBuF,GAAY,CAACE,EACRxG;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MASjCqB,EACKxG;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA,mBAIpBqB,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAcHC,CAAa;AAAA,uBACZj2B,GACRq2B,EAAkBr2B,EAAE,OAA4B,KAAK,CAAC;AAAA,yBAC5CA,GAAqB,CAC3BA,EAAE,MAAQ,SAAWi2B,EAAc,QACrCG,EAAiBH,EAAc,MAAM,CAEzC,CAAC;AAAA;AAAA;AAAA;AAAA,0BAIW,CAACA,EAAc,QAAUH,CAAQ;AAAA,uBACpC,IAAMM,EAAiBH,EAAc,MAAM,CAAC;AAAA;AAAA,gBAEnDH,EAAW,eAAiB,QAAQ;AAAA;AAAA;AAAA,YAGxCC,EACEvG,0BAA6BuG,CAAW,OACxCxF,CAAO;AAAA;AAAA,oDAEgCvwB,GAAa,CAAEA,EAAE,iBAAkB8M,EAAM,oBAAsB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAU/GA,EAAM,eACD0iB;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAOhB7nB,EAAM,eAAe;AAAA,uBACpB9M,GAAa8M,EAAM,mBAAoB9M,EAAE,OAA4B,KAAK,CAAC;AAAA,yBACzEA,GAAqB,CAC3BA,EAAE,MAAQ,SAAW8M,EAAM,gBAAgB,QAC7CA,EAAM,oBAEV,CAAC;AAAA,0BACWA,EAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,0BAKpB,CAACA,EAAM,gBAAgB,QAAUA,EAAM,cAAc;AAAA,uBACxD,IAAMA,EAAM,oBAAoB;AAAA,eACxCA,EAAM,eAAiB,YAAc,MAAM;AAAA;AAAA,YAE9CA,EAAM,gBACJ0iB,2BAA8B1iB,EAAM,eAAe,OACnDyjB,CAAO;AAAA;AAAA,oDAEgCvwB,GAAa,CAAEA,EAAE,iBAAkB8M,EAAM,oBAAsB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgB5G0iB;AAAAA;AAAAA;AAAAA,UAGCmF,GAAoB,MAAM,CAAC;AAAA;AAAA,UAE3BkB,IAAkB,IAASE,EACzBvG,2BAA8BuG,CAAW,OACzCvG;AAAAA;AAAAA;AAAAA,iBAGK;AAAA,sDACqC2G,CAAW;AAAA;AAAA;AAAA;AAAA,kDAIdn2B,GAAa,CAAEA,EAAE,iBAAkB8M,EAAM,oBAAsB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAanH,CAGA,SAASonB,GACPvuB,EACAmH,EAC+B,CAC/B,MAAMwpB,EAAa,IAAI,IACrBxpB,EAAM,iBAAiB,IAAKpM,GAAM,CAACA,EAAE,UAAWA,CAAC,CAAC,GAEpD,OAAIiF,EAAG,kBACE2wB,EAAW,IAAI3wB,EAAG,iBAAiB,GAAK,KAG7CA,EAAG,WAAamH,EAAM,iBAAiB,SAAW,EAC7CA,EAAM,iBAAiB,CAAC,GAAK,KAE/B,IACT,CAGA,SAASmnB,GAAqBnnB,EAA6C,OACzE,MAAMypB,GAAWr1B,EAAA4L,EAAM,UAAN,YAAA5L,EAAe,kBAChC,OAAKq1B,EACEzpB,EAAM,WAAW,KAAMnH,GAAOA,EAAG,OAAS4wB,CAAQ,GAAK,KADxCzpB,EAAM,WAAW,CAAC,GAAK,IAE/C,CAGA,SAAS0pB,GAAsB1pB,EAAuB,CACpD,MAAMnH,EAAKsuB,GAAqBnnB,CAAK,EAC/B2pB,GAAe9wB,GAAA,YAAAA,EAAI,eAAeA,GAAA,YAAAA,EAAI,OAAQ3B,KAAe,KAGnE,GAAI8I,EAAM,mBAAqBnH,EAAI,CACjC,MAAM+wB,EAAa,IAAM,CACvB,MAAMpxB,EAAMwH,EAAM,oBAAoB,OAClCxH,GAAKwH,EAAM,kBAAkBnH,EAAG,KAAML,CAAG,CAC/C,EACA,OAAOkqB;AAAAA;AAAAA;AAAAA;AAAAA,mBAIQ1iB,EAAM,mBAAmB;AAAA,mBACxB9M,GAAa,CAAE8M,EAAM,oBAAuB9M,EAAE,OAA4B,KAAO,CAAC;AAAA,qBAChFA,GAAqB,CAC3BA,EAAE,MAAQ,SAAS02B,EAAA,EACnB12B,EAAE,MAAQ,UAAU8M,EAAM,yBAChC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMQ4pB,CAAU;AAAA;AAAA;AAAA,WAGlBnH,EAAM,KAAK;AAAA;AAAA;AAAA,mBAGHziB,EAAM,uBAAuB;AAAA;AAAA,WAErCyiB,EAAM,CAAC;AAAA;AAAA,KAGhB,CAGA,OAAOC;AAAAA;AAAAA,8FAEqFiH,CAAY;AAAA;AAAA;AAAA,iBAGzF3pB,EAAM,sBAAsB;AAAA;AAAA;AAAA,SAGpCyiB,EAAM,IAAI;AAAA;AAAA,GAGnB,CAGA,SAASoH,GAAuB7pB,EAAuB,CACrD,OAAO0iB;AAAAA;AAAAA,QAED8D,EAAkBxmB,EAAM,iBAAmB,GAAQ,MAAQ,MAAM,CAAC;AAAA;AAAA;AAAA,gBAG1DA,EAAM,sBAAwB,SAAS;AAAA;AAAA,QAE/CymB,GAAiB,UAAWzmB,CAAK,CAAC;AAAA;AAAA,qCAELA,EAAM,qBAAuB,WAAa,EAAE;AAAA,oBAC7DA,EAAM,oBAAoB;AAAA,iBAC7BA,EAAM,sBAAsB;AAAA;AAAA;AAAA,UAGnCyiB,EAAM,QAAQ;AAAA;AAAA;AAAA,GAIxB,CAGA,SAASqH,GAAsB9pB,EAAuB,CACpD,MAAM+pB,EAAc/pB,EAAM,gBAAkB,GAC5C,OAAO0iB;AAAAA;AAAAA,QAED8D,EAAkBuD,EAAc,OAAS,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA,YAI3CA,EAAc,YAAc,eAAe,GAAGA,GAAe/pB,EAAM,cACjE0iB,qEAAwE1iB,EAAM,cAAgB,GAAK,GAAG,KAAK,MAAMA,EAAM,cAAgB,EAAE,CAAC,KAAKA,EAAM,cAAgB,EAAE,IAAM,GAAGA,EAAM,aAAa,GAAG,WACtMyjB,CAAO;AAAA;AAAA;AAAA,QAGbgD,GAAiB,SAAUzmB,CAAK,CAAC;AAAA,QACjC+pB,EACErH;AAAAA;AAAAA,2CAEiC1iB,EAAM,SAAW,WAAa,EAAE;AAAA,0BACjDA,EAAM,QAAQ;AAAA,uBACjBA,EAAM,qBAAqB;AAAA;AAAA;AAAA,gBAGlCyiB,EAAM,SAAS;AAAA;AAAA,YAGrBC;AAAAA;AAAAA;AAAAA,uBAGa1iB,EAAM,qBAAqB;AAAA;AAAA;AAAA,gBAGlCyiB,EAAM,SAAS;AAAA;AAAA,WAEpB;AAAA;AAAA,GAGX,CAGA,SAASuH,GAAuBhqB,EAAuB,CACrD,OAAO0iB;AAAAA;AAAAA,QAED8D,EAAkB,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKzBC,GAAiB,UAAWzmB,CAAK,CAAC;AAAA;AAAA;AAAA,iBAGzB,IAAM,CACTA,EAAM,qBACRA,EAAM,wBAENA,EAAM,wBAEV,CAAC;AAAA;AAAA;AAAA,UAGCyiB,EAAM,SAAS;AAAA;AAAA,QAEjBziB,EAAM,qBACJ0iB;AAAAA;AAAAA;AAAAA,qDAG2CxrB,GAAA,EAAe,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAM1C8I,EAAM,WAAW;AAAA,2BACpBA,EAAM,eAAe;AAAA;AAAA,oBAE5BA,EAAM,YAAc,YAAmB,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKhDA,EAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAO5CyjB,CAAO;AAAA;AAAA,GAGjB,CAGA,SAAS4D,GAAmB/tB,EAAqB,SAC/C,GAAI,CACF,MAAMsE,EAAM,KAAK,MAAMtE,CAAG,EAEpB2wB,GAAOrsB,GAAA,YAAAA,EAAK,QAASA,EACrBgB,IAAMvK,GAAAD,EAAA61B,GAAA,YAAAA,EAAM,SAAN,YAAA71B,EAAc,UAAd,YAAAC,EAAuB,WAAW41B,GAAA,YAAAA,EAAM,WAAWrsB,GAAA,YAAAA,EAAK,SACpE,GAAIgB,GAAO,OAAOA,GAAQ,SAAU,OAAOA,CAC7C,MAAQ,CAER,CACA,OAAOtF,CACT,CAGA,SAAS4wB,GAAwBlqB,EAAuB,OACtD,MAAMnH,EAAKsuB,GAAqBnnB,CAAK,EACrC,GAAI,CAACnH,EAAI,OAAO4qB,EAEhB,MAAM1pB,EAAUqtB,GAAyBvuB,EAAImH,CAAK,EAC5C+pB,GAAchwB,GAAA,YAAAA,EAAS,WAAWA,GAAA,YAAAA,EAAS,WAC3CowB,GAAWpwB,GAAA,YAAAA,EAAS,SAAU,CAACgwB,EAC/BK,EAAa,EAAQrwB,EACrBswB,EAAmDN,EACrD,OACAI,EACE,UACAC,EACE,MACA,UACFE,EAAeP,EACjB,YACAI,EACE,wBACAC,EACGrwB,GAAA,MAAAA,EAAS,UAAYstB,GAAmBttB,EAAQ,SAAS,EAAI,gBAC9D,aACFwwB,EAAY,EAACxwB,GAAA,MAAAA,EAAS,YAAYA,GAAA,YAAAA,EAAS,YAAa,UACxD0N,EAAY5O,EAAG,oBAAsBA,EAAG,WAAamH,EAAM,iBAAiB,SAAW,GAAI5L,EAAA4L,EAAM,iBAAiB,CAAC,IAAxB,YAAA5L,EAA2B,UAAY,QAClIo2B,EAAa/iB,GAAa,MAAQzH,EAAM,4BAA8ByH,EAE5E,OAAOib;AAAAA;AAAAA,QAED8D,EAAkB6D,CAAQ,CAAC;AAAA;AAAA;AAAA,gBAGnBC,CAAY;AAAA;AAAA,QAEpB7D,GAAiB,WAAYzmB,CAAK,CAAC;AAAA,QACnCoqB,EACE1H;AAAAA;AAAAA,qBAEW1iB,EAAM,sBAAsB;AAAA;AAAA,aAEpCyiB,EAAM,QAAQ,YACjBgB,CAAO;AAAA,QACT8G,GAAa9iB,EACXib;AAAAA;AAAAA,qBAEW1iB,EAAM,uBAAuB;AAAA;AAAA,aAErCyiB,EAAM,QAAQ,YACjBgB,CAAO;AAAA,QACT+G,GAAcxqB,EAAM,uBAClB0iB;AAAAA;AAAAA;AAAAA;AAAAA,wBAIc1iB,EAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,gBAKpCA,EAAM,qBACJ0iB,mDAAsD1iB,EAAM,oBAAoB,OAChFyjB,CAAO;AAAA;AAAA,YAGfA,CAAO;AAAA;AAAA,GAGjB,CAGA,SAASgH,GAA4BzqB,EAAuB,SAC1D,GAAI,CAACA,EAAM,qBAAsB,OAAOyjB,EAExC,MAAM5qB,EAAKsuB,GAAqBnnB,CAAK,EACrC,GAAI,CAACnH,EAAI,OAAO4qB,EAChB,MAAM1pB,EAAUqtB,GAAyBvuB,EAAImH,CAAK,EAClD,GAAI,CAACjG,EAAS,OAAO0pB,EAErB,MAAMsG,EAAchwB,EAAQ,SAAWA,EAAQ,UACzCwwB,EAAY,CAACxwB,EAAQ,UAAYA,EAAQ,WAAa,UACtD0N,EAAY5O,EAAG,oBAAsBA,EAAG,WAAamH,EAAM,iBAAiB,SAAW,GAAI5L,EAAA4L,EAAM,iBAAiB,CAAC,IAAxB,YAAA5L,EAA2B,UAAY,QAClIs2B,EAAa,IAAM1qB,EAAM,0BAGzB2qB,EAAY,kEACZC,EAAa,kCACbC,EAAa,iDAEnB,OAAOnI;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GAAGw3B,EAAA,CAC1E,CAAC;AAAA;AAAA;AAAA;AAAA,wBAImBC,CAAS,kBAAkBC,CAAU,gCAAgCC,CAAU,KAAK9wB,EAAQ,MAAQA,EAAQ,WAAa,SAAS;AAAA,wBAClI4wB,CAAS,kBAAkBC,CAAU,8BAA8BC,CAAU,OAAKx2B,EAAA0F,EAAQ,OAAR,YAAA1F,EAAc,OAAQ,YAAY;AAAA,wBACpHs2B,CAAS,kBAAkBC,CAAU,kCAAkCC,CAAU,KAAKd,EAAc,MAAQ,IAAI;AAAA,wBAChHY,CAAS,kBAAkBC,CAAU,+BAA+BC,CAAU,KAAK9wB,EAAQ,OAAS,MAAQ,IAAI;AAAA,YAC5HA,EAAQ,UAAY2oB,8CAAiDkI,CAAU,gFAAgFvD,GAAmBttB,EAAQ,SAAS,CAAC,eAAiB0pB,CAAO;AAAA;AAAA,UAE9N8G,GAAa9iB,EACXib;AAAAA;AAAAA,gBAEI3oB,EAAQ,OACN2oB;AAAAA;AAAAA;AAAAA,gCAGc1iB,EAAM,YAAY;AAAA,6BACrB,IAAM,CAAEA,EAAM,iBAAiByH,CAAS,EAAGijB,EAAA,CAAc,CAAC;AAAA,6CAErEhI;AAAAA;AAAAA;AAAAA,gCAGc1iB,EAAM,YAAY;AAAA,6BACrB,IAAM,CAAEA,EAAM,iBAAiByH,CAAS,EAAGijB,EAAA,CAAc,CAAC;AAAA,0CAC7C;AAAA,cAE9BjH,CAAO;AAAA,UACTsG,EACErH;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,+BAMmB1iB,EAAM,mBAAqB,YAAcA,EAAM,mBAAqB,IAAI;AAAA,8BACzEA,EAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAYvBA,EAAM,sBAAwB,MAAM;AAAA,8BACrCA,EAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAQvCA,EAAM,sBAAwB,OAC5B0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,uCAMmB1iB,EAAM,2BAA2B;AAAA,sCAClC,IAAMA,EAAM,6BAA6B,EAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uCAY7C,CAACA,EAAM,2BAA2B;AAAA,sCACnC,IAAMA,EAAM,6BAA6B,EAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAUjEyjB,CAAO;AAAA;AAAA,cAGfA,CAAO;AAAA;AAAA;AAAA;AAAA,mBAIAiH,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAO7B,CAGA,SAASnD,GAAqBvnB,EAAuB,CACnD,MAAM8qB,EAAa3D,GAAqBnnB,CAAK,EACvC+qB,EAAU/qB,EAAM,uBAChBgrB,EAAa,GAAQF,GAAcC,IAAYD,EAAW,MAC1DG,EAAgB,GAAQF,GAAWD,GAAcC,IAAYD,EAAW,MAC9E,MAAO,CAAE,WAAAA,EAAY,QAAAC,EAAS,WAAAC,EAAY,cAAAC,CAAA,CAC5C,CAEA,SAASC,GAAwBlrB,EAAuB,CACtD,KAAM,CAAE,QAAA+qB,EAAS,WAAAC,EAAY,cAAAC,CAAA,EAAkB1D,GAAqBvnB,CAAK,EAGzE,IAAIsJ,EACA6hB,EACJ,OAAIF,GACF3hB,EAAS,UACT6hB,EAAa,gBAAgBJ,CAAO,IAC3BC,GAAchrB,EAAM,mBAC7BsJ,EAAS,OACT6hB,EAAa,aACJH,GAAchrB,EAAM,iBAC7BsJ,EAAS,UACT6hB,EAAa,0BACJH,GACT1hB,EAAS,MACT6hB,EAAa,eACJnrB,EAAM,oBACfsJ,EAAS,UACT6hB,EAAa,kBAEb7hB,EAAS,MACT6hB,EAAa,kBAGRzI;AAAAA;AAAAA,QAED8D,EAAkBld,CAAM,CAAC;AAAA;AAAA;AAAA,gBAGjB6hB,CAAU;AAAA;AAAA,QAElB1E,GAAiB,WAAYzmB,CAAK,CAAC;AAAA;AAAA,qCAENA,EAAM,iBAAmB,WAAa,EAAE;AAAA,oBACzDA,EAAM,gBAAgB;AAAA,iBACzBA,EAAM,gBAAgB;AAAA,iBACtBgrB,EAAa,kBAAoB,kBAAkB;AAAA;AAAA,UAE1DvI,EAAM,SAAS;AAAA;AAAA,QAEjBgB,CAAO;AAAA;AAAA,GAGf,CAEA,SAAS2H,GAA0BprB,EAAuB,CACxD,GAAI,CAACA,EAAM,sBAAuB,OAAOyjB,EACzC,KAAM,CAAE,QAAAsH,EAAS,WAAAC,EAAY,cAAAC,CAAA,EAAkB1D,GAAqBvnB,CAAK,EAEnE0qB,EAAa,IAAM,CAAE1qB,EAAM,wBAA0B,EAG3D,OAAIgrB,EACKtI;AAAAA,+CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GAAGw3B,EAAA,CAC1E,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAYiB1qB,EAAM,gBAAgB;AAAA,qBACzB,IAAM,CAAEA,EAAM,sBAAwB,CAAC;AAAA;AAAA,cAE9CA,EAAM,iBAAmB,iBAAwB,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,qBAK/D0qB,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUzBO,EACKvI;AAAAA,+CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GAAGw3B,EAAA,CAC1E,CAAC;AAAA;AAAA;AAAA;AAAA,6FAIsFK,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAM5E/qB,EAAM,gBAAgB;AAAA,qBACzB,IAAM,CAAEA,EAAM,oBAAsB,CAAC;AAAA;AAAA,cAE5CA,EAAM,iBAAmB,cAAqB,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKjE0qB,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUtBhI;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GAAGw3B,EAAA,CAC1E,CAAC;AAAA;AAAA;AAAA;AAAA,YAIOxzB,GAAA,EAAe,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKT8I,EAAM,gBAAgB;AAAA,mBACzB,IAAM,CAAEA,EAAM,yBAA2B,CAAC;AAAA;AAAA,YAEjDA,EAAM,iBAAmB,cAAqB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKhD0qB,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAO7B,CAIA,SAASW,GAAqBrrB,EAAuB,CACnD,GAAI,CAACA,EAAM,SAAU,OAAOyjB,EAG5B,MAAM/C,EADY1gB,EAAM,gBACK,OAAQlM,GAAMA,EAAE,MAAM,EAAE,OAErD,OAAO4uB;AAAAA;AAAAA;AAAAA,UAGC8D,EAAkB9F,EAAa,EAAI,OAAS,KAAK,CAAC;AAAA;AAAA;AAAA,kBAG1CA,CAAU;AAAA;AAAA,UAElB+F,GAAiB,WAAYzmB,CAAK,CAAC;AAAA;AAAA;AAAA,mBAG1B,IAAMA,EAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA,MAI5CsrB,GAAmBtrB,CAAK,CAAC;AAAA,GAE/B,CAGA,SAASsrB,GAAmBtrB,EAAuB,CACjD,GAAI,CAACA,EAAM,gBAAiB,OAAOyjB,EAEnC,MAAM8H,EAAYvrB,EAAM,gBAGlBwrB,EAAqC,GAC3C,UAAW13B,KAAKy3B,EAAez3B,EAAE,MAAK03B,EAAW13B,EAAE,EAAE,EAAIA,EAAE,KAE3D,MAAM81B,EAAa,CAAC6B,EAAoBxE,IAAqB,CAC3D,MAAMW,EAAMX,GAAA,YAAAA,EAAI,QAAQ,uBAClBxwB,EAAQmxB,GAAA,YAAAA,EAAK,cAAc,SAC3BvxB,EAAQI,GAAA,YAAAA,EAAO,MAAM,OACvB,CAACJ,GAASA,IAAUm1B,EAAWC,CAAU,GAC7CzrB,EAAM,aAAayrB,EAAYp1B,CAAK,CACtC,EAEMq1B,EAAoBx4B,GAAa,CACrC,MAAM8zB,EAAO9zB,EAAE,cACT00B,EAAMZ,EAAI,QAAQ,qBAAqB,EACvCvwB,EAAQmxB,GAAA,YAAAA,EAAK,cAAc,SACjC,GAAI,CAACnxB,EAAO,OACZ,MAAMk1B,EAAUl1B,EAAM,OAAS,OAC/BA,EAAM,KAAOk1B,EAAU,WAAa,OACpC3E,EAAI,UAAU,OAAO,SAAU,CAAC2E,CAAO,CACzC,EAEMC,EAAc,CAACH,EAAoBv4B,IAAa,CACpD,MAAMuD,EAAQvD,EAAE,OACV00B,EAAMnxB,EAAM,QAAQ,qBAAqB,EACzCJ,EAAQI,EAAM,MAAM,OACpBo1B,EAAUx1B,EAAM,OAAS,GAAKA,IAAUm1B,EAAWC,CAAU,EAE7DK,EAAUlE,GAAA,YAAAA,EAAK,cAAc,sBAC/BkE,IAASA,EAAQ,MAAM,QAAUD,EAAU,GAAK,QAEpD,MAAME,EAASnE,GAAA,YAAAA,EAAK,cAAc,qBAC9BmE,IAAQA,EAAO,MAAM,QAAU11B,EAAM,OAAS,EAAI,GAAK,OAC7D,EAEM21B,EAAUT,EAAU,OAAQz3B,GAAMA,EAAE,OAAO,EAC3Cm4B,EAAWV,EAAU,OAAQz3B,GAAM,CAACA,EAAE,OAAO,EAE7Co4B,EAAqBp4B,GAA2B,CACpD,MAAMq4B,EAAWnsB,EAAM,uBAAyBlM,EAAE,IAAMkM,EAAM,WACxDosB,EAAY,CAACpsB,EAAM,YAAcA,EAAM,gBAAkB,GAAGlM,EAAE,EAAE,aAChEu4B,EAAc,CAACrsB,EAAM,YAAcA,EAAM,gBAAkB,GAAGlM,EAAE,EAAE,eAClEw4B,EAAe,CAACtsB,EAAM,YAAcA,EAAM,gBAAkB,GAAGlM,EAAE,EAAE,YACnEy4B,EAAc,CAACvsB,EAAM,YAAcA,EAAM,gBAAkB,GAAGlM,EAAE,EAAE,WAExE,OAAO4uB;AAAAA,qCAC0B5uB,EAAE,SAAW,WAAa,EAAE;AAAA;AAAA,oBAE7CA,EAAE,IAAI;AAAA,gDACsBA,EAAE,QAAQ;AAAA,YAC9Cs4B,EAAY1J,uDAA4De,CAAO;AAAA,YAC/E4I,EAAc3J,2DAAgEe,CAAO;AAAA,YACrF6I,EAAe5J,4DAAiEe,CAAO;AAAA,YACvF8I,EAAc7J,yDAA8De,CAAO;AAAA,YACnF3vB,EAAE,UAAY,CAACy4B,EAAc7J,+DAAoEe,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA,qBAK/F3vB,EAAE,KAAO,EAAE;AAAA;AAAA,wBAERkM,EAAM,YAAclM,EAAE,QAAQ;AAAA,qBAChCZ,GAAa04B,EAAY93B,EAAE,GAAIZ,CAAC,CAAC;AAAA,uBAC/BA,GAAqB,CAAMA,EAAE,MAAQ,WAAoBY,EAAE,GAAIZ,EAAE,MAAqB,CAAG,CAAC;AAAA;AAAA;AAAA;AAAA,oBAI9FY,EAAE,OAAS,GAAK,gBAAgB;AAAA;AAAA,qBAE/B43B,CAAgB;AAAA,aACxBjJ,EAAM,GAAG;AAAA,YACV0J,EACEzJ,+DACAA;AAAAA;AAAAA;AAAAA,4BAGc1iB,EAAM,UAAU;AAAA,yBAClB9M,GAAa02B,EAAW91B,EAAE,GAAIZ,EAAE,aAA4B,CAAC;AAAA,6BAE7E;AAAA,YACEY,EAAE,QAAU,CAACq4B,EAAWzJ;AAAAA;AAAAA,6CAES5uB,EAAE,SAAW,GAAK,QAAQ;AAAA,uBAChDA,EAAE,SAAW,SAAW,SAAS;AAAA,0BAC9BkM,EAAM,UAAU;AAAA,uBACnB,IAAMA,EAAM,gBAAgBlM,EAAE,GAAI,CAACA,EAAE,QAAQ,CAAC;AAAA,eACtD2uB,EAAM,KAAK;AAAA;AAAA;AAAA;AAAA,0BAIAziB,EAAM,UAAU;AAAA,uBACnB,IAAMA,EAAM,eAAelM,EAAE,EAAE,CAAC;AAAA,eACxC2uB,EAAM,KAAK;AAAA,YACZgB,CAAO;AAAA;AAAA;AAAA,KAInB,EAEA,OAAOf;AAAAA,iGACyFxvB,GAAa,CACpGA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,oBAEV,CAAC;AAAA;AAAA;AAAA;AAAA,YAIOA,EAAM,YAAc0iB,8CAAiD1iB,EAAM,WAAW,OAASyjB,CAAO;AAAA,YACtGuI,EAAQ,IAAIE,CAAiB,CAAC;AAAA,YAC9BD,EAAS,OAAS,EAAIvJ;AAAAA;AAAAA;AAAAA,gBAGlBuJ,EAAS,IAAIC,CAAiB,CAAC;AAAA;AAAA,YAEjCzI,CAAO;AAAA;AAAA;AAAA;AAAA,GAKrB,CAGA,SAAS+I,GAAgBxsB,EAAuB,CAC9C,MAAMysB,EACJzsB,EAAM,kBAAoB,KACtB,UACAA,EAAM,gBACJ,UACA,OAEF0sB,EACJ1sB,EAAM,iBAAmBA,EAAM,cAC3B,IAAIA,EAAM,cAAc,OAAOA,EAAM,aAAa,GAClDA,EAAM,eACJ,IAAIA,EAAM,cAAc,GACxB,UAEF2sB,EAAS3sB,EAAM,gBAAkBA,EAAM,cAE7C,OAAO0iB;AAAAA;AAAAA,QAED8D,EAAkBiG,CAAW,CAAC;AAAA;AAAA;AAAA,gBAGtBC,CAAW;AAAA;AAAA,QAEnBjG,GAAiB,SAAUzmB,CAAK,CAAC;AAAA,QACjCA,EAAM,gBACJ0iB;AAAAA;AAAAA,2CAEiCiK,EAAS,WAAa,EAAE;AAAA,0BACzCA,CAAM;AAAA,uBACT3sB,EAAM,WAAW;AAAA;AAAA;AAAA,gBAGxBA,EAAM,cAAgByiB,EAAM,OAASA,EAAM,QAAQ;AAAA;AAAA,YAGzDC;AAAAA;AAAAA,2CAEiCiK,EAAS,WAAa,EAAE;AAAA,0BACzCA,CAAM;AAAA,uBACT3sB,EAAM,aAAa;AAAA;AAAA;AAAA,gBAG1ByiB,EAAM,QAAQ;AAAA;AAAA,WAEnB;AAAA;AAAA,GAGX,CAGA,MAAMgF,GAA2C,CAC/C,UAAW,cACX,SAAU,YACV,OAAQ,iBACV,EAGA,SAASmF,GAAoB5sB,EAAuB,CAClD,MAAM4H,EAAU5H,EAAM,kBAEtB,OAAO0iB;AAAAA;AAAAA,QAED8D,EAH6B5e,EAAU,OAAS,SAGxB,CAAC;AAAA;AAAA;AAAA,gBAGjBA,EAAU,UAAY,UAAU;AAAA;AAAA,QAExC6e,GAAiB,cAAezmB,CAAK,CAAC;AAAA,QACtC4H,EAAU8a;AAAAA;AAAAA,iBAED1iB,EAAM,wBAAwB;AAAA;AAAA,SAEtCyiB,EAAM,QAAQ,YAAcgB,CAAO;AAAA;AAAA;AAAA,iBAG3B7b,EAAU,sBAAwB,oBAAoB;AAAA,oBACnD5H,EAAM,cAAc;AAAA,iBACvBA,EAAM,kBAAkB;AAAA,SAChC4H,EAAU6a,EAAM,SAAWA,EAAM,KAAK;AAAA;AAAA,GAG/C,CAGA,SAASoK,GAA8B7sB,EAAuB,CAC5D,GAAI,CAACA,EAAM,uBAAwB,OAAOyjB,EAE1C,MAAMiH,EAAa,IAAM1qB,EAAM,4BACzB8sB,EAAc,EAAQ9sB,EAAM,mBAC5B+sB,EAAa/sB,EAAM,qBAAuB,YAAcA,EAAM,qBAAuB,SACrFgtB,EAAgBhtB,EAAM,wBAAwB,OAAS,EAAIA,EAAM,wBAA0B,CAAC,WAAY,KAAK,EAC7GitB,EAAcD,EAAc,SAAS,UAAU,EAC/CE,EAASF,EAAc,SAAS,KAAK,EACrCG,EAAWH,EAAc,SAAS,OAAO,EAGzCn0B,EAAKsuB,GAAqBnnB,CAAK,EAC/BotB,EAAYv0B,EAAKuuB,GAAyBvuB,EAAImH,CAAK,EAAI,KACvDqtB,EAAoB,CAAC,EAAED,GAAA,MAAAA,EAAW,WAExC,OAAO1K;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GAAGw3B,EAAA,CAC1E,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMgBA,CAAU;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAYL1qB,EAAM,cAAc;AAAA,wBACrB9M,GAAa,CACtB,MAAMsF,EAAOtF,EAAE,OAA6B,MAC5C8M,EAAM,2BAA2BxH,CAA0C,CAC7E,CAAC;AAAA;AAAA,oDAEqCwH,EAAM,qBAAuB,WAAW;AAAA,mDACzCA,EAAM,qBAAuB,UAAU;AAAA,iDACzCA,EAAM,qBAAuB,QAAQ;AAAA;AAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAYzD8sB,CAAW;AAAA,8BACV9sB,EAAM,sBAAsB;AAAA,4BAC9BA,EAAM,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA,gBAK5C8sB,EAAcpK;AAAAA;AAAAA;AAAAA,4BAGF1iB,EAAM,sBAAsB;AAAA,yBAC/BA,EAAM,8BAA8B;AAAA,iBAC5CA,EAAM,uBAAyByiB,EAAM,OAASA,EAAM,SAAS,YAAcgB,CAAO;AAAA;AAAA,cAErFqJ,GAAe9sB,EAAM,uBAAyB0iB;AAAAA;AAAAA;AAAAA,4BAGhC1iB,EAAM,sBAAsB;AAAA,yBAC/BA,EAAM,uBAAyB,gBAAkBA,EAAM,kBAAkB;AAAA,wBACzE9M,GAAa,CACpB,MAAMkH,EAAQlH,EAAE,OAA+B,MAAM,OACjDkH,GAAQA,IAAS4F,EAAM,oBACzBA,EAAM,yBAAyB5F,CAAI,CAEvC,CAAC;AAAA;AAAA,cAEDsoB;AAAAA;AAAAA;AAAAA;AAAAA,aAIH;AAAA;;AAAA,YAGDqK,EAAarK;AAAAA;;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,kFAOyD2K,EAAoB,mBAAqB,oCAAoC;AAAA;AAAA;AAAA,+BAGhIJ,GAAeI,CAAiB;AAAA,gCAC/B,CAACA,GAAqBrtB,EAAM,qBAAwB,CAACktB,GAAU,CAACC,GAAYF,CAAY;AAAA,8BACzF/5B,GAAa,CAEtB,MAAM2G,EADW3G,EAAE,OAA4B,QAE3C,CAAC,GAAG85B,EAAc,OAAQv4B,GAAcA,IAAM,UAAU,EAAG,UAAU,EACrEu4B,EAAc,OAAQv4B,GAAcA,IAAM,UAAU,EACpDoF,EAAK,OAAS,KAAS,sBAAsBmG,EAAM,oBAAqBnG,CAAI,CAClF,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMGwzB,EAAoB,yBAA2B,+CAA+C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAOvFH,CAAM;AAAA,gCACLltB,EAAM,qBAAwB,CAACitB,GAAe,CAACE,GAAYD,CAAO;AAAA,8BACnEh6B,GAAa,CAEtB,MAAM2G,EADW3G,EAAE,OAA4B,QAE3C,CAAC,GAAG85B,EAAc,OAAQv4B,GAAcA,IAAM,KAAK,EAAG,KAAK,EAC3Du4B,EAAc,OAAQv4B,GAAcA,IAAM,KAAK,EAC/CoF,EAAK,OAAS,KAAS,sBAAsBmG,EAAM,oBAAqBnG,CAAI,CAClF,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAWUszB,CAAQ;AAAA,gCACPntB,EAAM,qBAAwB,CAACitB,GAAe,CAACC,GAAUC,CAAS;AAAA,8BACnEj6B,GAAa,CAEtB,MAAM2G,EADW3G,EAAE,OAA4B,QAE3C,CAAC,GAAG85B,EAAc,OAAQv4B,GAAcA,IAAM,OAAO,EAAG,OAAO,EAC/Du4B,EAAc,OAAQv4B,GAAcA,IAAM,OAAO,EACjDoF,EAAK,OAAS,KAAS,sBAAsBmG,EAAM,oBAAqBnG,CAAI,CAClF,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,YAWP4pB,CAAO;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,qBAQA,IAAM,CAAEiH,EAAA,EAAc1qB,EAAM,6BAA+B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,GAMjF,CAGA,SAASstB,GAAyBttB,EAAuB,SACvD,GAAI,CAACA,EAAM,0BAA2B,OAAOyjB,EAE7C,MAAM8J,IAAYn5B,EAAA4L,EAAM,kBAAN,YAAA5L,EAAuB,cAAaC,EAAA2L,EAAM,kBAAN,YAAA3L,EAAuB,aAAc,KACrFoT,EAAYzH,EAAM,qBAAuB,kBACzCwtB,EAAYD,GAAa,0BAEzBE,EAAU,gBAAgBD,CAAS;AAAA;AAAA;AAAA,eAG5BA,CAAS;AAAA,kBACN/lB,CAAS;AAAA;AAAA,YAInBimB,EAAa,MAAOx6B,GAAa,CACrC,MAAM8zB,EAAM9zB,EAAE,cACd,GAAI,CACF,MAAM,UAAU,UAAU,UAAUu6B,CAAO,CAC7C,MAAQ,CACN,MAAMxG,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQwG,EACXxG,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,QAAU,IACnB,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,SACH,SAAS,YAAY,MAAM,EAC3B,SAAS,KAAK,YAAYA,CAAE,CAC9B,CACA,MAAM0G,EAAO3G,EAAI,YACjBA,EAAI,YAAc,UAClB,WAAW,IAAM,CAAEA,EAAI,YAAc2G,CAAM,EAAG,IAAI,CACpD,EAEMC,EAAiB,IAAM,CAC3B,MAAMh6B,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAO,iCAAmC,mBAAmB65B,CAAO,EACtE75B,EAAE,SAAW,wBACbA,EAAE,OACJ,EAEA,OAAO8uB;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,8BAEV,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMgB,IAAMA,EAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAOpDutB,EAEK9J,EAFOf;AAAAA;AAAAA,aAEA;AAAA,qPAC8N+K,CAAO;AAAA;AAAA,gEAE5LC,CAAU;AAAA,wDAClBE,CAAc;AAAA;AAAA;AAAA;AAAA,GAKtE,CAMA,MAAMC,GAAsF,CAC1F,CAAE,GAAI,kBAA8B,UAAW,OAAU,YAAa,gBACtE,CAAE,GAAI,6BAA8B,UAAW,SAAU,YAAa,kBACtE,CAAE,GAAI,4BAA8B,UAAW,QAAU,YAAa,UACxE,EAEMC,GAAiE,CACrE,CAAE,MAAO,MAAW,MAAO,OAC3B,CAAE,MAAO,UAAW,MAAO,WAC3B,CAAE,MAAO,MAAW,MAAO,OAC3B,CAAE,MAAO,SAAW,MAAO,UAC3B,CAAE,MAAO,OAAW,MAAO,OAC7B,EAGMC,GAA0B,uCAEhC,SAASC,GAAuBhuB,EAAuB,CACrD,MAAM8Z,EAAS9Z,EAAM,qBAAuB,GACtCiuB,EAAUnU,EAAO,OAAS,EAC5BA,EAAO,IAAKlmB,GAAM,OAIhB,OAHmBA,EAAE,QACjBQ,EAAAy5B,GAAqB,KAAMp5B,GAAMb,EAAE,QAAU,aAAaa,EAAE,EAAE,EAAE,IAAhE,YAAAL,EAAmE,YAAaR,EAAE,MAAM,MAAM,GAAG,EAAE,MACnG,QAEN,CAAC,EAAE,KAAK,KAAK,EACb,UAEJ,OAAO8uB;AAAAA;AAAAA,QAED8D,EAAkB,MAAM,CAAC;AAAA;AAAA;AAAA,gBAGjByH,CAAO;AAAA;AAAA,8CAEuBjuB,EAAM,qBAAqB;AAAA;AAAA,GAGzE,CAEA,SAASkuB,GAAyBluB,EAAuB,CACvD,GAAI,CAACA,EAAM,kBAAmB,OAAOyjB,EAErC,MAAM3J,EAAS9Z,EAAM,qBAAuB,GAC5C,GAAI8Z,EAAO,SAAW,EAAG,OAAO2J,EAEhC,MAAM0K,EAAUnuB,EAAM,2BAA6B,GAC7CouB,EAAY,IAAI,IAAID,EAAQ,OAAQ15B,GAAMA,EAAE,WAAa,WAAW,EAAE,IAAKA,GAAMA,EAAE,EAAE,CAAC,EACtF+U,EAASqkB,GAAqB,OAAQp5B,GAAM25B,EAAU,IAAI35B,EAAE,EAAE,CAAC,EAE/Di2B,EAAa,IAAM1qB,EAAM,wBAE/B,OAAO0iB;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GAAGw3B,EAAA,CAC1E,CAAC;AAAA;AAAA;AAAA;AAAA,YAIO5Q,EAAO,IAAKuU,GAAU,CACtB,MAAMC,EAAkBD,EAAM,OAASN,GACjCQ,EAAkBF,EAAM,eAAiB,MACzCG,EAAUH,EAAM,GAAG,SAAS,QAAQ,GAAKA,EAAM,KAAO,QAE5D,OAAO3L;AAAAA;AAAAA;AAAAA,oBAGC2L,EAAM,QAAUG,EAAU,QAAU,SAAS;AAAA;AAAA,kBAE/ChlB,EAAO,OAAS,EACdkZ;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mCAMe4L,CAAe;AAAA,oCACbp7B,GAAa,CACtB8M,EAAM,mBAAmBquB,EAAM,GAAKn7B,EAAE,OAA6B,KAAK,CAC1E,CAAC;AAAA;AAAA,4BAECsW,EAAO,IACN/U,GAAMiuB;AAAAA,8CACW,aAAejuB,EAAE,EAAE,cAAc65B,IAAoB,aAAe75B,EAAE,EAAE;AAAA,kCACpFA,EAAE,SAAS,MAAMA,EAAE,WAAW;AAAA;AAAA,8BAGrC;AAAA;AAAA;AAAA,sBAIPgvB,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAME8K,CAAe;AAAA,8BACbr7B,GAAa,CACtB8M,EAAM,sBAAsBquB,EAAM,GAAKn7B,EAAE,OAA6B,KAAK,CAC7E,CAAC;AAAA;AAAA,sBAEC46B,GAAsB,IACrBj6B,GAAM6uB;AAAAA,wCACW7uB,EAAE,KAAK,cAAc06B,IAAoB16B,EAAE,KAAK;AAAA,4BAC5DA,EAAE,KAAK;AAAA;AAAA,wBAGd;AAAA;AAAA;AAAA,kBAGHw6B,IAAUvU,EAAOA,EAAO,OAAS,CAAC,EAChC4I,sFACAe,CAAO;AAAA;AAAA,aAGjB,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAUazjB,EAAM,cAAc;AAAA,0BAClB9M,GAAa,CACtB8M,EAAM,uBAAwB9M,EAAE,OAA6B,KAAK,CACpE,CAAC;AAAA;AAAA,kDAEiC8M,EAAM,iBAAmB,OAAO;AAAA,iDACjCA,EAAM,iBAAmB,MAAM;AAAA,mDAC7BA,EAAM,iBAAmB,QAAQ;AAAA,mDACjCA,EAAM,iBAAmB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAQ3DA,EAAM,cAAc;AAAA,0BAClB9M,GAAa,CACtB8M,EAAM,uBAAwB9M,EAAE,OAA6B,KAAK,CACpE,CAAC;AAAA;AAAA,iDAEgC8M,EAAM,iBAAmB,MAAM;AAAA,kDAC9BA,EAAM,iBAAmB,OAAO;AAAA,mDAC/BA,EAAM,iBAAmB,QAAQ;AAAA,mDACjCA,EAAM,iBAAmB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAQjE0qB,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAO7B,CAIA,SAAS+D,GAAkBzuB,EAAuB,CAChD,MAAM0nB,EAAS,GAAQ1nB,EAAM,kBAAoBA,EAAM,sBAAwBA,EAAM,cAC/EsJ,EAA6Boe,EAAS,OAAS,UAC/CgH,EAAO1uB,EAAM,aAEnB,OAAO0iB;AAAAA;AAAAA,QAED8D,EAAkBld,CAAM,CAAC;AAAA;AAAA;AAAA,gBAGjBoe,EAAS,aAAe,SAAS;AAAA;AAAA,QAEzCjB,GAAiB,WAAYzmB,CAAK,CAAC;AAAA;AAAA;AAAA,oBAGvB0uB,CAAI;AAAA,iBACP1uB,EAAM,gBAAgB;AAAA,SAC9B0uB,EAAO,MAAQ,MAAM;AAAA;AAAA,GAG9B,CAEA,SAASC,GAAoB3uB,EAAuB,OAClD,GAAI,CAACA,EAAM,iBAAkB,OAAOyjB,EAEpC,MAAMiL,EAAO1uB,EAAM,aACbxG,GAAYpF,EAAA4L,EAAM,UAAN,YAAA5L,EAAe,kBAC3Bw6B,EAAU5uB,EAAM,cAAgBxG,EAAY,eAAe,mBAAmBA,CAAS,CAAC,GAAK,GAEnG,OAAOkpB;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,kBAEV,CAAC;AAAA;AAAA;AAAA,sDAGiDA,EAAM,gBAAgB;;AAAA;AAAA;AAAA;AAAA;AAAA,cAM9D4uB,EACElM;AAAAA,4DAC4CkM,CAAO,MAAM,KAAK,KAAK;AAAA,kEACjBF,CAAI,WAAW1uB,EAAM,iBAAiB;AAAA,kBAExF0iB,gDAAmD;AAAA,gDACnBgM,EAAO,WAAa,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAM1CA,CAAI;AAAA,0BACLx7B,GAAa,OACtB,MAAMuD,EAAQvD,EAAE,OACVoqB,GAAOlpB,EAAAqC,EAAM,QAAN,YAAArC,EAAc,GACvBkpB,GAAMtd,EAAM,kBAAkBsd,CAAI,EACtC7mB,EAAM,MAAQ,EAChB,CAAC;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAYMuJ,EAAM,kBAAoB,SAAS;AAAA,0BAChC0uB,CAAI;AAAA,wBACLx7B,GAAa,CACtB8M,EAAM,yBAA0B9M,EAAE,OAA4B,KAAK,CACrE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,uBAKQ8M,EAAM,kBAAoB,SAAS;AAAA,0BAChC0uB,CAAI;AAAA;AAAA,yBAEJx7B,GAAqB,CAC/B,GAAIA,EAAE,MAAQ,QAAS,CACrB,MAAMsF,EAAOtF,EAAE,OAA4B,MAAM,OAC7C,oBAAoB,KAAKsF,CAAG,GAAGwH,EAAM,yBAAyBxH,CAAG,CACvE,CACF,CAAC;AAAA,sBACQtF,GAAa,CACpB,MAAMsF,EAAOtF,EAAE,OAA4B,MAAM,OAC7C,oBAAoB,KAAKsF,CAAG,GAAKA,KAASwH,EAAM,kBAAoB,YACtEA,EAAM,yBAAyBxH,CAAG,CAEtC,CAAC;AAAA;AAAA,cAEDwH,EAAM,iBACJ0iB,iDAAoDgM,CAAI,WAAW,IAAM1uB,EAAM,yBAAyB,EAAE,CAAC,kBAC3GyjB,CAAO;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAUAzjB,EAAM,sBAAwB,SAAS;AAAA,0BACpC0uB,CAAI;AAAA,wBACLx7B,GAAa,CACtB8M,EAAM,6BAA8B9M,EAAE,OAA4B,KAAK,CACzE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,uBAKQ8M,EAAM,sBAAwB,SAAS;AAAA,0BACpC0uB,CAAI;AAAA;AAAA,yBAEJx7B,GAAqB,CAC/B,GAAIA,EAAE,MAAQ,QAAS,CACrB,MAAMsF,EAAOtF,EAAE,OAA4B,MAAM,OAC7C,oBAAoB,KAAKsF,CAAG,GAAGwH,EAAM,6BAA6BxH,CAAG,CAC3E,CACF,CAAC;AAAA,sBACQtF,GAAa,CACpB,MAAMsF,EAAOtF,EAAE,OAA4B,MAAM,OAC7C,oBAAoB,KAAKsF,CAAG,GAAKA,KAASwH,EAAM,sBAAwB,YAC1EA,EAAM,6BAA6BxH,CAAG,CAE1C,CAAC;AAAA;AAAA,cAEDwH,EAAM,qBACJ0iB,iDAAoDgM,CAAI,WAAW,IAAM1uB,EAAM,6BAA6B,EAAE,CAAC,kBAC/GyjB,CAAO;AAAA;AAAA;;AAAA,UAIbzjB,EAAM,kBAAoBA,EAAM,sBAAwBA,EAAM,aAC5D0iB;AAAAA,6DACiDgM,CAAI,WAAW1uB,EAAM,YAAY;AAAA;AAAA;AAAA,cAIlFyjB,CAAO;;AAAA;AAAA;AAAA,GAKnB,CAGA,SAASoL,GAA4B7uB,EAAuB,CAC1D,MAAM0uB,EAAO1uB,EAAM,cACbkpB,EAAUlpB,EAAM,iBAChByB,EAAQzB,EAAM,eACd8uB,EAAU9uB,EAAM,wBAChB+uB,EAAW/uB,EAAM,yBACjB1C,EAAU0C,EAAM,wBAGtB,MAAI,CAAC0uB,GAAQ,CAACI,GAAW,CAACrtB,EAAcgiB,EAGpChiB,GAAS,CAACitB,EACLhM;AAAAA,+CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,KAAS,yBAChF,CAAC;AAAA;AAAA;AAAA;AAAA,0EAImEuO,CAAK;AAAA;AAAA;AAAA;AAAA,uBAIxD,IAAM,CAAEzB,EAAM,mBAAqB,CAAC;AAAA;AAAA;AAAA;AAAA,uBAIpCA,EAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,MAS9C8uB,EACKpM;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAYLwG,EACKxG;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,iEAKsDqM,CAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mFAOU,mBAAmB7F,CAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAOxFA,CAAO;AAAA;AAAA;AAAA;AAAA,eAIdA,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWbxG;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,+DAMsDqM,CAAQ;AAAA;AAAA,wFAEiBzxB,CAAO;AAAA;AAAA;AAAA,GAI/F,CAGA,SAAS0xB,GAAsBhvB,EAAuB,CACpD,GAAI,CAACA,EAAM,SAAU,OAAOyjB,EAE5B,MAAM+D,EAAKxnB,EAAM,gBACX0uB,EAAO1uB,EAAM,cACbkpB,EAAUlpB,EAAM,iBAGtB,GAAI,CAACwnB,EACH,OAAO9E;AAAAA;AAAAA,UAED8D,EAAkB,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,UAK5BC,GAAiB,gBAAiBzmB,CAAK,CAAC;AAAA;AAAA,MAMhD,GAAI,CAACwnB,EAAG,UACN,OAAO9E;AAAAA;AAAAA,UAED8D,EAAkB,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,UAK5BC,GAAiB,gBAAiBzmB,CAAK,CAAC;AAAA;AAAA,MAMhD,GAAIkpB,GAAW,CAAC1B,EAAG,SACjB,OAAO9E;AAAAA;AAAAA,UAED8D,EAAkB,SAAS,CAAC;AAAA;AAAA;AAAA,kBAGpBkI,EAAO,gBAAkB,eAAe;AAAA;AAAA,UAEhDjI,GAAiB,gBAAiBzmB,CAAK,CAAC;AAAA;AAAA;AAAA,sBAG5B0uB,CAAI;AAAA,mBACP1uB,EAAM,iBAAiB;AAAA,WAC/B0uB,EAAO,MAAQ,SAAS;AAAA;AAAA,MAMjC,GAAI,CAAClH,EAAG,aAAc,CACpB,MAAMyH,EAAiBjvB,EAAM,wBAC7B,OAAO0iB;AAAAA;AAAAA,UAED8D,EAAkB,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,UAK5BC,GAAiB,gBAAiBzmB,CAAK,CAAC;AAAA;AAAA;AAAA;AAAA,sBAI5B0uB,CAAI;AAAA,mBACP1uB,EAAM,sBAAsB;AAAA,WACpCyiB,EAAM,KAAK;AAAA,UACZwM,EACEvM;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,wBAKYuM,CAAc;AAAA;AAAA;AAAA;AAAA;AAAA,oBAM1BjvB,EAAM,eACJ0iB,mFAAsF1iB,EAAM,cAAc,OAC1GyjB,CAAO;AAAA;AAAA,KAGnB,CAGA,GAAI,CAAC+D,EAAG,YACN,OAAO9E;AAAAA;AAAAA,UAED8D,EAAkB,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,UAKxBC,GAAiB,gBAAiBzmB,CAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAW7BwnB,EAAG,YAAyB,GAAAA,EAAG,WAClD,MAAM0H,EAAYlvB,EAAM,yBAGlBmvB,EAAiBnvB,EAAM,wBACzB0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,sBAKgBgM,CAAI;AAAA,mBACP1uB,EAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,mBAK7BA,EAAM,+BAA+B;AAAA;AAAA,cAGlDkvB,EACExM;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,oBAKYwM,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA,gBAMrBlvB,EAAM,eACJ0iB,mFAAsF1iB,EAAM,cAAc,OAC1GyjB,EAER,OAAOf;AAAAA;AAAAA,QAED8D,EAAkB,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKzBC,GAAiB,gBAAiBzmB,CAAK,CAAC;AAAA,QACxCwnB,EAAG,cACD9E;AAAAA;AAAAA;AAAAA,wBAGcgM,CAAI;AAAA,qBACP1uB,EAAM,wBAAwB;AAAA,aACtCyiB,EAAM,QAAQ,YACjBC;AAAAA;AAAAA;AAAAA,wBAGcgM,CAAI;AAAA,qBACP1uB,EAAM,uBAAuB;AAAA,aACrCyiB,EAAM,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA,oBAIfiM,CAAI;AAAA,iBACP1uB,EAAM,+BAA+B;AAAA,SAC7CyiB,EAAM,QAAQ;AAAA,QACf0M,CAAc;AAAA;AAAA,GAGtB,CAOA,SAASC,GAAiBC,EAAgB,CACxC,MAAMC,EAAaD,GAAU,GAAK,EAAIA,GAAU,GAAK,EAAIA,GAAU,GAAK,EAAI,EAE5E,OAAO3M;AAAAA;AAAAA,QADS,CAAC,EAAG,EAAG,GAAI,EAAE,EAGf,IACR,CAAC/uB,EAAGH,IAAMkvB;AAAAA;AAAAA,oBAEE/uB,CAAC;AAAA;AAAA,wBAEGH,EAAI87B,EAAa,gCAAkC,wBAAwB;AAAA,mBAE5F;AAAA;AAAA,GAGP,CAEA,SAASC,GAAcvvB,EAAuB,CAE5C,GAAIA,EAAM,iBAAmB,QAAS,OAAOyjB,EAE7C,MAAM5qB,EAAKmH,EAAM,WACX0uB,EAAO1uB,EAAM,SAGnB,GAAI,CAACnH,EACH,OAAO6pB;AAAAA;AAAAA,UAED8D,EAAkB,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUpC,GAAI,CAAC3tB,EAAG,UACN,OAAO6pB;AAAAA;AAAAA,UAED8D,EAAkB,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASpC,MAAMgJ,EAAW,CAAC,CAAC32B,EAAG,WAAa,CAACA,EAAG,UACjC4zB,EAAc5zB,EAAG,UAAY,OAAS,UACtCsyB,EAAatyB,EAAG,UAClB6pB,IAAO7pB,EAAG,IAAI,IAAIA,EAAG,QAAU,KAAO6pB,oCAAuC0M,GAAiBv2B,EAAG,MAAM,CAAC,UAAY4qB,CAAO,GAC3H+L,EACE9M,IAAO7pB,EAAG,SAAS,gEACnB,gBAEN,OAAO6pB;AAAAA;AAAAA,QAED8D,EAAkBiG,CAAW,CAAC;AAAA;AAAA;AAAA,gBAGtBtB,CAAU;AAAA,UAChBtyB,EAAG,WAAaA,EAAG,GACjB6pB,iDAAoD7pB,EAAG,EAAE,UACzD4qB,CAAO;AAAA;AAAA;AAAA;AAAA,oBAICiL,CAAI;AAAA,iBACP1uB,EAAM,iBAAiB;AAAA,SAC/B0uB,EAAO,MAAQ,MAAM;AAAA;AAAA,GAG9B,CAGA,SAASe,GAAgBzvB,EAAuB,CAC9C,GAAI,CAACA,EAAM,cAAe,OAAOyjB,EAEjC,MAAM5qB,EAAKmH,EAAM,WACX0uB,EAAO1uB,EAAM,SACb0vB,EAAW1vB,EAAM,aACjBypB,EAAWzpB,EAAM,iBAEvB,OAAO0iB;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,mBAEV,CAAC;AAAA;AAAA;AAAA,sDAGiDA,EAAM,iBAAiB;;AAAA;AAAA,UAGnEnH,GAAA,MAAAA,EAAI,UACF6pB;AAAAA;AAAAA,8CAEkCD,EAAM,IAAI;AAAA,+CACT5pB,EAAG,IAAI,GAAGA,EAAG,QAAU,KAAO6pB,KAAQ0M,GAAiBv2B,EAAG,MAAM,CAAC,GAAK4qB,CAAO,GAAG5qB,EAAG,GAAK6pB,kCAAqC7pB,EAAG,EAAE,WAAa4qB,CAAO;AAAA;AAAA;AAAA;AAAA,4BAIzKiL,CAAI;AAAA,yBACP1uB,EAAM,gBAAgB;AAAA;AAAA;AAAA,YAInCnH,GAAA,MAAAA,EAAI,UACF6pB;AAAAA;AAAAA,8DAEgDD,EAAM,IAAI;AAAA,+DACT5pB,EAAG,SAAS;AAAA;AAAA,cAG7D4qB,CAAO;;AAAA;AAAA;AAAA;AAAA;AAAA,sBAMCiL,CAAI;AAAA,mBACP1uB,EAAM,UAAU;AAAA,WACxB0uB,GAAQgB,EAAS,SAAW,EAAI,cAAgB,mBAAmB;;AAAA,UAEpE1vB,EAAM,UACJ0iB,iEAAoE1iB,EAAM,SAAS,OACnFyjB,CAAO;;AAAA;AAAA,UAGTiM,EAAS,OAAS,EAChBhN;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,gBAQIgN,EAAS,IAAKn8B,GAAM,CACpB,MAAMo8B,GAAU92B,GAAA,YAAAA,EAAI,aAActF,EAAE,KACpC,OAAOmvB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,oCAQa+G,IAAal2B,EAAE,KAAO,wBAA0B,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAQpE,IAAM,CACTA,EAAE,QACNyM,EAAM,iBAAiBypB,IAAal2B,EAAE,KAAO,KAAOA,EAAE,IAAI,CAC5D,CAAC;AAAA;AAAA;AAAA,wBAGGA,EAAE,OACAmvB,iEACAiN,EACEjN,4EACAe,CAAO;AAAA,8BACLlwB,EAAE,IAAI;AAAA;AAAA;AAAA,wBAGZA,EAAE,WAAa,OACbmvB,wDAA2DnvB,EAAE,QAAQ,wBACrEkwB,CAAO;AAAA,6CACYlwB,EAAE,MAAM,MAAM67B,GAAiB77B,EAAE,MAAM,CAAC;AAAA;AAAA;AAAA,iBAIvE,CAAC,CAAC;AAAA;;AAAA,cAGFk2B,GAAY,CAACiG,EAAS,KAAMn8B,GAAMA,EAAE,OAASk2B,GAAYl2B,EAAE,MAAM,EAC/DmvB;AAAAA;AAAAA,qBAEK,IAAM,CACP,MAAMkN,EAAMF,EAAS,KAAMn8B,GAAMA,EAAE,OAASk2B,CAAQ,EAC9CoG,GAAgBD,GAAA,YAAAA,EAAK,YAAa,OAClCD,GAAU92B,GAAA,YAAAA,EAAI,aAAc4wB,EAClC,OAAIoG,GAAiB,CAACF,EACbjN;AAAAA;AAAAA;AAAAA;AAAAA,mCAIM1iB,EAAM,YAAY;AAAA,mCACjB9M,GACR8M,EAAM,qBAAsB9M,EAAE,OAA4B,KAAK,CAAC;AAAA,qCACtDA,GAAqB,CAC3BA,EAAE,MAAQ,SAAS8M,EAAM,eAC/B,CAAC;AAAA,sCACW0uB,CAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAafjL,CACT,IAAI;AAAA;AAAA;AAAA;AAAA,gCAIUiL,CAAI;AAAA,6BACP1uB,EAAM,aAAa;AAAA,qBAC3B0uB,EAAO,gBAAkB,SAAS;AAAA,qBACnC71B,GAAA,YAAAA,EAAI,aAAc4wB,EAChB/G;AAAAA;AAAAA,oCAEcgM,CAAI;AAAA,iCACP1uB,EAAM,YAAY;AAAA;AAAA,wCAG7ByjB,CAAO;AAAA;AAAA,gBAGbA,CAAO;AAAA,YAEXA,CAAO;AAAA;AAAA;AAAA,GAInB,CAGA,SAASqM,GAAiB9vB,EAAuB,CAC/C,OAAKA,EAAM,SAGPA,EAAM,aAAe,KAChB0iB;AAAAA;AAAAA,UAED8D,EAAkB,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAS7B9D;AAAAA;AAAAA,QAED8D,EAAkB,MAAM,CAAC;AAAA;AAAA;AAAA,gBAGjBxmB,EAAM,eAAe,UAAUA,EAAM,WAAW;AAAA;AAAA,QAExDymB,GAAiB,UAAWzmB,CAAK,CAAC;AAAA;AAAA;AAAA,iBAGzBA,EAAM,oBAAoB;AAAA;AAAA;AAAA,IAzBbyjB,CA6B9B,CAGA,SAASsM,GAAmB/vB,EAAuB,CACjD,GAAI,CAACA,EAAM,iBAAkB,OAAOyjB,EAEpC,MAAMiL,EAAO1uB,EAAM,YACbgwB,EAAchwB,EAAM,mBAAqB,OAAOA,EAAM,WAAW,EACjEiwB,EAAkBjwB,EAAM,uBAAyBA,EAAM,gBACvDkwB,EAAaF,GAAeC,EAElC,OAAOvN;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,sBAEV,CAAC;AAAA;AAAA;AAAA,sDAGiDA,EAAM,oBAAoB;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAQzDA,EAAM,oBAAoB;AAAA,0BACvB0uB,CAAI;AAAA,uBACNx7B,GACR8M,EAAM,wBAAyB9M,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAwB5D8M,EAAM,gBAAgB;AAAA,0BACnB0uB,CAAI;AAAA,uBACNx7B,GACR8M,EAAM,oBAAqB9M,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,UAgBrE8M,EAAM,aACJ0iB,iEAAoE1iB,EAAM,YAAY,OACtFyjB,CAAO;AAAA,UACTzjB,EAAM,eACJ0iB,iEAAoE1iB,EAAM,cAAc,OACxFyjB,CAAO;;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMKiL,GAAQ,CAACwB,CAAU;AAAA,qBACtBlwB,EAAM,aAAa;AAAA,aAC3B0uB,EAAO,YAAc,MAAM;AAAA,YAC5BwB,EACExN,4EACAe,CAAO;AAAA;AAAA;AAAA;AAAA,GAKrB,CAGA,SAAS0M,GAAkBnwB,EAAuB,WAChD,MAAMowB,EAAepwB,EAAM,cACrBxE,EAASwE,EAAM,iBACrB,GAAI,CAACowB,GAAgB,CAAC50B,EAAQ,OAAOioB,EAGrC,GAAI2M,EACF,OAAO1N;AAAAA;AAAAA;AAAAA;AAAAA,YAIC1iB,EAAM,oBAAoB,OAAS,EACjC0iB;AAAAA;AAAAA,oBAEM1iB,EAAM,oBAAoB,IACzBkoB,GAASxF;AAAAA,sDACwBwF,EAAK,MAAM;AAAA;AAAA,4BAErCA,EAAK,SAAW,UACdxF,8CACAwF,EAAK,SAAW,OACdxF,uCAA0CD,EAAM,KAAK,UACrDC,yCAA4CD,EAAM,CAAC,SAAS;AAAA;AAAA,+DAE7ByF,EAAK,IAAI;AAAA,0BAC9CA,EAAK,YAAc,KACjBxF,yCAA4C2N,GAAenI,EAAK,UAAU,CAAC,UAC3EzE,CAAO;AAAA;AAAA,sBAGhB;AAAA;AAAA,gBAGLf,+DAAkE;AAAA,YACpE1iB,EAAM,cACJ0iB,sGAAyG1iB,EAAM,aAAa,OAC5HyjB,CAAO;AAAA;AAAA;AAAA,MAOnB,GAAIjoB,EAAQ,CACV,MAAM80B,EAAY90B,EAAO,SAAW,KACpC,IAAI8B,EACJ,GAAIgzB,EAAW,CACb,MAAMC,GAASn8B,EAAAoH,EAAO,SAAP,YAAApH,EAAe,QACxBo8B,IAAQn8B,EAAAmH,EAAO,QAAP,YAAAnH,EAAc,UAAWmH,EAAO,eAC9C8B,EAAUizB,EAAS,IAAIA,CAAM,OAAYC,CAAK,GAAK,eAAeA,CAAK,EACzE,MAEElzB,EADe9B,EAAO,UAAU6mB,EAAA7mB,EAAO,aAAP,YAAA6mB,EAAmB,OAAQ,gBAG7D,MAAMoO,EAAej1B,EAAO,YAAc,KAAO60B,GAAe70B,EAAO,UAAU,EAAI,KAErF,OAAOknB;AAAAA,+CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,uBAEV,CAAC;AAAA;AAAA,iDAE0CswB,EAAY,KAAO,MAAM,KAAKA,EAAY7N,EAAM,YAAcA,EAAM,OAAO;AAAA,8BAC9F6N,EAAY,UAAY,SAAS;AAAA,cACjDA,EAAY,kBAAoB,eAAe;AAAA;AAAA;AAAA,cAG/ChzB,CAAO;AAAA;AAAA,YAETmzB,EACE/N,+EAAkF+N,CAAY,OAC9FhN,CAAO;AAAA;AAAA;AAAA;AAAA,qBAIAzjB,EAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAO9C,CAEA,OAAOyjB,CACT,CAEA,SAAS4M,GAAet0B,EAAoB,CAC1C,GAAIA,EAAK,IAAM,MAAO,GAAGA,CAAE,KAC3B,MAAM5I,EAAI,KAAK,MAAM4I,EAAK,GAAI,EAC9B,GAAI5I,EAAI,GAAI,MAAO,GAAGA,CAAC,IACvB,MAAMsB,EAAI,KAAK,MAAMtB,EAAI,EAAE,EACrBu9B,EAAMv9B,EAAI,GAChB,OAAOu9B,EAAM,EAAI,GAAGj8B,CAAC,KAAKi8B,CAAG,IAAM,GAAGj8B,CAAC,GACzC,CAEA,SAASk8B,GAAoB3wB,EAAuB,CAClD,MAAM4wB,EAAS5wB,EAAM,cAGrB,OAAO0iB;AAAAA;AAAAA,QAED8D,EAJyBoK,EAAS,OAAS,KAInB,CAAC;AAAA;AAAA;AAAA,gBAGjBA,EAAS,MAAQ,SAAS;AAAA;AAAA,QAElCnK,GAAiB,cAAezmB,CAAK,CAAC;AAAA;AAAA;AAAA,iBAG7B,IAAMA,EAAM,uBAAuB;AAAA,SAC3C4wB,EAAS,SAAW,SAAS;AAAA;AAAA,GAGtC,CAGA,SAASC,GAAsB7wB,EAAuB,CACpD,GAAI,CAACA,EAAM,oBAAqB,OAAOyjB,EAEvC,MAAMmN,EAAS5wB,EAAM,cACf0uB,EAAO1uB,EAAM,eAEnB,IAAI8wB,EAAS,GACTC,EAAS,GACTC,EAAa,GAEjB,MAAMC,EAAmBC,GAAiCh+B,GAAa,CACrE,MAAMuD,EAAQvD,EAAE,OAChBuD,EAAM,MAAQA,EAAM,MAAM,QAAQ,MAAO,EAAE,EAAE,MAAM,EAAG,CAAC,EACvDy6B,EAAOz6B,EAAM,KAAK,CACpB,EAEM06B,EAAsB,CAACnrB,EAAuBpH,IAAgB,OAClE,IAAIqoB,EAAKjhB,EAAK,cAAc,uBAAuB,EAC9CihB,IACHA,EAAK,SAAS,cAAc,GAAG,EAC/BA,EAAG,UAAY,oCACf7yB,EAAA4R,EAAK,cAAc,qBAAqB,IAAxC,MAAA5R,EAA2C,OAAO6yB,IAEpDA,EAAG,YAAcroB,CACnB,EAEMwyB,EAAgBl+B,GAAa,CACjCA,EAAE,iBACF,MAAM8S,EAAO9S,EAAE,OACf,GAAI,CAAAw7B,EACJ,IAAIkC,GAAU,CAACE,EAAQ,CAAEK,EAAoBnrB,EAAM,wBAAwB,EAAG,MAAQ,CACtF,GAAI,CAAC+qB,EAAQ,CAAEI,EAAoBnrB,EAAM,iBAAiB,EAAG,MAAQ,CACrE,GAAI,CAACgrB,EAAY,CAAEG,EAAoBnrB,EAAM,sBAAsB,EAAG,MAAQ,CAC9E,GAAI+qB,IAAWC,EAAY,CAAEG,EAAoBnrB,EAAM,mBAAmB,EAAG,MAAQ,CACrF,GAAI+qB,EAAO,OAAS,EAAG,CAAEI,EAAoBnrB,EAAM,wBAAwB,EAAG,MAAQ,CACtFhG,EAAM,iBAAiB4wB,EAASE,EAAS,KAAMC,CAAM,EACvD,EAEA,OAAOrO;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GACnE8M,EAAM,wBAEV,CAAC;AAAA;AAAA;AAAA,gBAGW4wB,EAAS,qBAAuB,iBAAiB;AAAA,oDACb,IAAM5wB,EAAM,wBAAwB;AAAA,cAC1EyiB,EAAM,KAAK;AAAA;AAAA;AAAA,wBAGD2O,CAAY;AAAA,YACxBR,EAASlO;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,0BASKgM,CAAI;AAAA,uBACPuC,EAAiB18B,GAAc,CAAEu8B,EAASv8B,CAAG,CAAC,CAAC;AAAA;AAAA;AAAA,YAGxDkvB,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBASGiL,CAAI;AAAA,qBACPuC,EAAiB18B,GAAc,CAAEw8B,EAASx8B,CAAG,CAAC,CAAC;AAAA,cACtDq8B,EAASnN,EAAUf,YAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAUxBgM,CAAI;AAAA,qBACPuC,EAAiB18B,GAAc,CAAEy8B,EAAaz8B,CAAG,CAAC,CAAC;AAAA;AAAA,YAE5DyL,EAAM,gBACJ0iB,2BAA8B1iB,EAAM,eAAe,OACnDyjB,CAAO;AAAA,YACTzjB,EAAM,kBACJ0iB,6BAAgC1iB,EAAM,iBAAiB,OACvDyjB,CAAO;AAAA;AAAA;AAAA;AAAA,wBAIGiL,CAAI;AAAA,aACfA,EAAOhM,uCAA4CkO,EAAS,aAAe,SAAS;AAAA;AAAA;AAAA;AAAA,GAKjG,CAGA,SAASS,GAAqBrxB,EAAuB,CACnD,GAAI,CAACA,EAAM,gBAAiB,OAAOyjB,EACnC,KAAM,CAAE,gBAAA6N,GAAoBtxB,EAEtBuxB,EAAa,IAAM,CACnBvxB,EAAM,iBAAiB,QAAUA,EAAM,gBAAgB,MAAM,WAAW,GAC1EA,EAAM,kBACJA,EAAM,iBACNA,EAAM,kBAAoB,OAGhC,EAEMwxB,EAAuBt+B,GAAa,CACxC,MAAM8zB,EAAO9zB,EAAE,cACTu+B,EAAUzK,EAAI,QAAQ,oBAAoB,EAC1CvwB,EAAQg7B,GAAA,YAAAA,EAAS,cAAc,SACrC,GAAI,CAACh7B,EAAO,OACZ,MAAMk1B,EAAUl1B,EAAM,OAAS,OAC/BA,EAAM,KAAOk1B,EAAU,WAAa,OACpC3E,EAAI,UAAU,OAAO,SAAU,CAAC2E,CAAO,CACzC,EAEA,OAAOjJ;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBASU1iB,EAAM,gBAAgB;AAAA,mBACrB9M,GAAa8M,EAAM,sBAAuB9M,EAAE,OAA4B,KAAK,CAAC;AAAA,qBAC5EA,GAAqB,CAAMA,EAAE,MAAQ,SAASq+B,EAAA,CAAc,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAa9DvxB,EAAM,eAAe;AAAA,qBACpB9M,GAAa,CACrB,MAAMuD,EAAQvD,EAAE,OAChBuD,EAAM,MAAQA,EAAM,MAAM,QAAQ,MAAO,EAAE,EAAE,MAAM,EAAG,CAAC,EACvDuJ,EAAM,qBAAqBvJ,EAAM,KAAK,CACxC,CAAC;AAAA,uBACWvD,GAAqB,CAAMA,EAAE,MAAQ,SAASq+B,EAAA,CAAc,CAAC;AAAA;AAAA,kEAEnBC,CAAmB;AAAA,yCAC5C/O,EAAM,GAAG;AAAA,yCACTA,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAYhCziB,EAAM,gBAAgB;AAAA,qBACrB9M,GAAa8M,EAAM,sBAAuB9M,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAM5Eo+B,GAAmB,CAACtxB,EAAM,iBAAiB,QAAU,CAACA,EAAM,gBAAgB,MAAM,WAAW,CAAC;AAAA,qBACjGuxB,CAAU;AAAA;AAAA,cAEjBD,EAAkB,YAAmB,QAAQ;AAAA;AAAA;AAAA;AAAA,qBAItC,IAAM,CACbtxB,EAAM,qBAAqB,EAAK,EAChCA,EAAM,sBAAsB,EAAE,EAC9BA,EAAM,sBAAsB,EAAE,EAC9BA,EAAM,qBAAqB,EAAE,CAC/B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQb,CAGA,SAAS0xB,GAA2B1xB,EAAuB,CACzD,MAAMnH,EAAKsuB,GAAqBnnB,CAAK,EACrC,MAAI,CAACnH,GAAMA,EAAG,UAAkB4qB,EAERzjB,EAAM,yBAA2BnH,EAAG,KAEnD6pB;AAAAA;AAAAA;AAAAA,wEAG6D7pB,EAAG,aAAeA,EAAG,IAAI;AAAA;AAAA;AAAA;AAAA,wBAIzEmH,EAAM,eAAe;AAAA,qBACxB,IAAMA,EAAM,kBAAkBnH,EAAG,IAAI,CAAC;AAAA;AAAA,cAE7CmH,EAAM,gBAAkB,YAAmB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,qBAK5C,IAAMA,EAAM,4BAA4B,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASzD0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,iBAKSxvB,GAAa,CACrBA,EAAE,iBACF8M,EAAM,4BAA4BnH,EAAG,IAAI,CAC3C,CAAC;AAAA;AAAA;AAAA,GAIT,CAGA,SAAS84B,GAAuB3xB,EAAuB,CAErD,GAAIA,EAAM,cACR,OAAO0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAcT,GAAI1iB,EAAM,iBAAkB,CAC1B,MAAM4xB,EAAY5xB,EAAM,uBAAyB,YACjD,OAAO0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,qBAaU1iB,EAAM,oBAAoB;AAAA,wBACvBA,EAAM,aAAa;AAAA,qBACrB9M,GAAa8M,EAAM,6BAA8B9M,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMnF,CAAC0+B,GAAa5xB,EAAM,aAAa;AAAA,qBACpCA,EAAM,cAAc;AAAA;AAAA,cAE3BA,EAAM,cAAgB,gBAAuB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,wBAK9CA,EAAM,aAAa;AAAA,qBACtBA,EAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,UAKlCA,EAAM,eACJ0iB,qEAAwE1iB,EAAM,cAAc,OAC5FyjB,CAAO;AAAA;AAAA,KAGjB,CAGA,OAAOf;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,iBAKSxvB,GAAa,CACrBA,EAAE,iBACF8M,EAAM,oBACR,CAAC;AAAA;AAAA;AAAA,GAIT,CAEA,SAAS6xB,IAAoB,CAC3B,OAAOnP;AAAAA;AAAAA;AAAAA;AAAAA,GAKT,CAEA,SAASoP,GAAmB9xB,EAAuB,CACjD,KAAM,CACJ,aAAA+xB,EACA,qBAAAC,EACA,uBAAAC,EACA,uBAAAC,EACA,sBAAAC,CAAA,EACEnyB,EAGJ,GAAIiyB,EACF,OAAOvP;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,uBAQYuP,CAAsB;AAAA;AAAA,YAEjCF,EACErP,oDACAA;AAAAA;AAAAA,mBAEK;AAAA;AAAA,sDAEmCxrB,GAAA,EAAe,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAMlD8I,EAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWzC,GAAI+xB,EACF,OAAOrP;AAAAA;AAAAA;AAAAA;AAAAA,eAIIsP,GAAwB,2BAA2B;AAAA;AAAA;AAAA,MAOhE,MAAMI,GACJD,GAAA,YAAAA,EAAuB,WAAWA,GAAA,YAAAA,EAAuB,WAG3D,GAAIA,EAAuB,CAQzB,MAAME,GAPsBryB,EAAM,iBAAiB,OAAS,EAIxDA,EAAM,iBAAiB,MAAOpM,GAAMA,EAAE,SAAWA,EAAE,SAAS,EAC5Dw+B,IAE4BpyB,EAAM,cAEtC,OAAO0iB;AAAAA;AAAAA,iCAEsB2P,EAAU,gBAAkB,EAAE;AAAA,YACnD3I,GAAsB1pB,CAAK,CAAC;AAAA;AAAA,cAE1B6pB,GAAuB7pB,CAAK,CAAC;AAAA,cAC7B8pB,GAAsB9pB,CAAK,CAAC;AAAA,cAC5BgqB,GAAuBhqB,CAAK,CAAC;AAAA,cAC7BkqB,GAAwBlqB,CAAK,CAAC;AAAA,cAC9BA,EAAM,iBAAmB,SAAWkrB,GAAwBlrB,CAAK,EAAIyjB,CAAO;AAAA,cAC5EuK,GAAuBhuB,CAAK,CAAC;AAAA,cAC7B2wB,GAAoB3wB,CAAK,CAAC;AAAA,cAC1BwsB,GAAgBxsB,CAAK,CAAC;AAAA,cACtB4sB,GAAoB5sB,CAAK,CAAC;AAAA,cAC1ByuB,GAAkBzuB,CAAK,CAAC;AAAA,cACxBgvB,GAAsBhvB,CAAK,CAAC;AAAA,cAC5B8vB,GAAiB9vB,CAAK,CAAC;AAAA,cACvBuvB,GAAcvvB,CAAK,CAAC;AAAA;;AAAA,YAGtBkuB,GAAyBluB,CAAK,CAAC;AAAA,YAC/B6wB,GAAsB7wB,CAAK,CAAC;AAAA,YAC5B2uB,GAAoB3uB,CAAK,CAAC;AAAA,YAC1B6sB,GAA8B7sB,CAAK,CAAC;AAAA,YACpC+vB,GAAmB/vB,CAAK,CAAC;AAAA,YACzByvB,GAAgBzvB,CAAK,CAAC;AAAA,YACtB6uB,GAA4B7uB,CAAK,CAAC;AAAA,YAClCqrB,GAAqBrrB,CAAK,CAAC;AAAA,YAC3BqxB,GAAqBrxB,CAAK,CAAC;AAAA,YAC3B0xB,GAA2B1xB,CAAK,CAAC;AAAA,YACjC2xB,GAAuB3xB,CAAK,CAAC;AAAA,YAC7B6xB,IAAmB;AAAA,YACnB7xB,EAAM,gBACJ0iB,oDAAuD1iB,EAAM,eAAe,OAC5EyjB,CAAO;AAAA;AAAA;AAAA,KAInB,CAIA,OAAK0O,EAqBHD,IAA2B,IAASF,GAAwB,CAACD,EAEtDrP;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,OAAO,CAAC;AAAA;AAAA,cAE1BrB,EAAkB,KAAK,CAAC;AAAA;AAAA;AAAA,mCAGHwL,CAAoB;AAAA;AAAA;AAAA,wBAG/BD,CAAY;AAAA,qBACf/xB,EAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYlC0iB;AAAAA;AAAAA;AAAAA,UAGCmF,GAAoB,OAAO,CAAC;AAAA,UAC5BmK,EACEtP,2BAA8BsP,CAAoB,OAClDtP;AAAAA,kCACsB;AAAA;AAAA;AAAA,IArDvBA;AAAAA;AAAAA;AAAAA,YAGCmF,GAAoB,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMnB7nB,EAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAgD1C,CAEA,SAASsyB,GAAsBtyB,EAAuB,CACpD,GAAI,CAACA,EAAM,oBAAqB,OAAOyjB,EAEvC,MAAMiH,EAAa,IAAM1qB,EAAM,yBACzB+pB,EAAc/pB,EAAM,gBAAkB,GAE5C,OAAO0iB;AAAAA,6CACqCxvB,GAAa,CAChDA,EAAE,OAAuB,UAAU,SAAS,oBAAoB,GAAGw3B,EAAA,CAC1E,CAAC;AAAA;AAAA,cAESX,EAAc,mBAAqB,mBAAmB;;AAAA,UAE1DA,EACErH;AAAAA;AAAAA;AAAAA,oBAGQ8D,EAAkB,MAAM,CAAC;AAAA;AAAA,oBAEzBxmB,EAAM,cACJ0iB,+EAAkF1iB,EAAM,aAAa,YACrGyjB,CAAO;AAAA;AAAA,kBAEXzjB,EAAM,YACJ0iB,kFAAqF1iB,EAAM,WAAW,OACtGyjB,CAAO;AAAA,qFAC0DzjB,EAAM,WAAW;AAAA;AAAA;AAAA;AAAA,cAK1FyjB,CAAO;;AAAA,UAET,CAACsG,GAAe,CAAC/pB,EAAM,QACrB0iB;AAAAA;AAAAA;AAAAA;AAAAA,gBAII1iB,EAAM,YACJ0iB,wDAA2D1iB,EAAM,WAAW,OAC5EyjB,CAAO;AAAA;AAAA;AAAA;AAAA,4BAIGzjB,EAAM,QAAQ;AAAA,yBACjBA,EAAM,WAAW;AAAA;AAAA,kBAExBA,EAAM,SAAW,cAAgB,mBAAmB;AAAA;AAAA,cAG1DyjB,CAAO;;AAAA,UAETzjB,EAAM,QACJ0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,0BAKc1iB,EAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAOVA,EAAM,aAAa;AAAA,6BAClB9M,GAAa8M,EAAM,iBAAkB9M,EAAE,OAA4B,KAAK,CAAC;AAAA,+BACvEA,GAAqB,CAC3BA,EAAE,MAAQ,SAAW8M,EAAM,cAAc,QAC3CA,EAAM,iBAAiBA,EAAM,cAAc,MAAM,CAErD,CAAC;AAAA;AAAA;AAAA;AAAA,gCAIW,CAACA,EAAM,cAAc,QAAUA,EAAM,QAAQ;AAAA,6BAChD,IAAMA,EAAM,iBAAiBA,EAAM,cAAc,MAAM,CAAC;AAAA;AAAA,sBAE/DA,EAAM,SAAW,eAAiB,QAAQ;AAAA;AAAA;AAAA;AAAA,cAKpDyjB,CAAO;;AAAA,UAERsG,EAgCCtG,EA/BAf;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,6BASiB1iB,EAAM,qBAAqB;AAAA,6BAC1B9M,GAAa8M,EAAM,0BAA2B9M,EAAE,OAA4B,KAAK,CAAC;AAAA,+BAChFA,GAAqB,CAC3BA,EAAE,MAAQ,SAAW8M,EAAM,sBAAsB,QACnDA,EAAM,sBAEV,CAAC;AAAA,gCACWA,EAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA,gCAI1B,CAACA,EAAM,sBAAsB,QAAUA,EAAM,oBAAoB;AAAA,6BACpEA,EAAM,oBAAoB;AAAA;AAAA,sBAEjCA,EAAM,qBAAuB,eAAiB,SAAS;AAAA;AAAA;AAAA,kBAG3DA,EAAM,sBACJ0iB,oDAAuD1iB,EAAM,qBAAqB,OAClFyjB,CAAO;AAAA;AAAA,aAGR;;AAAA;AAAA;AAAA;AAAA,mBAKAiH,CAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAO7B,CAEO,SAAS6H,GAAYvyB,EAAuB,CACjD,KAAM,CAAE,UAAAwyB,EAAW,YAAA1K,CAAA,EAAgB9nB,EAanC,GARIwyB,GAAalM,MACfC,GAAA,EAOEvmB,EAAM,eAAkB,CAACwyB,GAAalM,KACxC,OAAO5D;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAoBT,GAAI,CAAC8P,EAAW,CACd,MAAMC,EAAazyB,EAAM,cACzB,OAAO0iB;AAAAA;AAAAA;AAAAA;AAAAA,eAII+P,EAAa,mCAA0C,0BAA0B;AAAA;AAAA;AAAA,KAI9F,CAGA,IAAIC,EACJ,OAAQ5K,EAAA,CACN,IAAK,UACH4K,EAAcpK,GAAkBtoB,CAAK,EACrC,MACF,IAAK,OACH0yB,EAAc5J,GAAe9oB,CAAK,EAClC,MACF,IAAK,QACH0yB,EAAcZ,GAAmB9xB,CAAK,EACtC,MACF,QACE0yB,EAAcpK,GAAkBtoB,CAAK,EAGzC,MAAM2yB,EAAU1P,GAAc,QAASjjB,EAAM,OAAO,EACpD,OAAO0iB,IAAOgQ,CAAW,GAAGhM,GAAgB1mB,CAAK,CAAC,GAAGsyB,GAAsBtyB,CAAK,CAAC,GAAGorB,GAA0BprB,CAAK,CAAC,GAAGyqB,GAA4BzqB,CAAK,CAAC,GAAGmwB,GAAkBnwB,CAAK,CAAC,GAAGstB,GAAyBttB,CAAK,CAAC,GAAG2yB,CAAO,EAClO,CCnwHA,SAASC,GAAiBpwB,EAAwBgiB,EAAoB,CACpE,MAAMqO,EAAWrwB,EAAM,OACnB,uCACA,+BAEJ,OAAOkgB;AAAAA;AAAAA;AAAAA,0CAGiClgB,EAAM,KAAK;AAAA,wCACbqwB,CAAQ;AAAA;AAAA,QAExCrwB,EAAM,OACJkgB,iGACAA;AAAAA;AAAAA;AAAAA,wBAGc8B,EAAM,MAAM;AAAA,qBACf,IAAMA,EAAM,SAAShiB,EAAM,KAAK,CAAC;AAAA;AAAA;AAAA,oBAGlC;AAAA;AAAA,GAGpB,CAKO,SAASswB,GAAiBtO,EAAoB,CACnD,GAAI,CAACA,EAAM,UACT,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAUT,MAAM0O,EAAgBl+B,GAAa,CACjCA,EAAE,iBACEsxB,EAAM,SAAS,QACjBA,EAAM,MAAMA,EAAM,QAAQ,CAE9B,EAEA,OAAO9B;AAAAA;AAAAA,QAEDO,GAAc,SAAUuB,EAAM,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,wBAWtBA,EAAM,OAAO;AAAA,qBAChBA,EAAM,SAAS;AAAA;AAAA,cAEtBA,EAAM,QAAU,aAAe,SAAS;AAAA;AAAA;;AAAA,UAI5CA,EAAM,MACJ9B,uDAA0D8B,EAAM,KAAK,SACrEf,CAAO;;AAAA,uHAEoG2N,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA,qBAK9G5M,EAAM,QAAQ;AAAA,qBACbtxB,GAAasxB,EAAM,iBAAkBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA,wBACvEsxB,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMZA,EAAM,QAAU,CAACA,EAAM,SAAS,MAAM;AAAA;AAAA,cAEhDA,EAAM,OAAS,YAAc,KAAK;AAAA;AAAA;;AAAA;AAAA,YAKpCA,EAAM,OAAO,SAAW,EACtB9B,oEACA8B,EAAM,OAAO,IAAKhiB,GAAUowB,GAAiBpwB,EAAOgiB,CAAK,CAAC,CAAC;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,GAYzE,CCzHA,MAAMuO,GAAQrQ,+EAuCd,SAASsQ,GAAWzwB,EAA+B,CACjD,OAAO,OAAO,KAAKA,EAAO,MAAM,EAAE,MACpC,CAEA,SAAS0wB,GAAyB1wB,EAAuBiiB,EAAsB,CAC7E,OAAO9B;AAAAA,8CACqC8B,EAAM,oBAAoB;AAAA,yEACEtxB,GAAaA,EAAE,iBAAiB;AAAA;AAAA;AAAA,sDAGpDsxB,EAAM,oBAAoB;AAAA,cAClEuO,EAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+CAO4BxwB,EAAO,IAAI;AAAA,gDACVA,EAAO,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKpCiiB,EAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAM1B,IAAM,CACbA,EAAM,SAASjiB,EAAO,EAAE,EACxBiiB,EAAM,sBACR,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQb,CAEA,SAAS0O,GAAoB3wB,EAAuBiiB,EAAsB,CACxE,MAAM2O,EAAY3O,EAAM,YAAY,OAAO,OAAS,EAE9C4M,EAAgBl+B,GAAa,CACjCA,EAAE,iBACEigC,KAAiB,kBACvB,EAEA,OAAOzQ;AAAAA,8CACqC8B,EAAM,eAAe;AAAA,yEACOtxB,GAAaA,EAAE,iBAAiB;AAAA;AAAA;AAAA,sDAGpDsxB,EAAM,eAAe;AAAA,cAC7DuO,EAAK;AAAA;AAAA;AAAA;AAAA,wEAIqDxwB,EAAO,IAAI;AAAA;AAAA,wBAE3D6uB,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAMb5M,EAAM,WAAW;AAAA,uBAChBtxB,GAAasxB,EAAM,oBAAqBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAS7EsxB,EAAM,aAAa;AAAA,uBAClBtxB,GAAasxB,EAAM,sBAAuBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAO/EsxB,EAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAOlB,CAAC2O,CAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASpC,CAEA,SAASC,GAAkB7wB,EAAuBiiB,EAAsB,CACtE,MAAMpZ,EAAU,OAAO,QAAQ7I,EAAO,MAAM,EAE5C,OAAOmgB;AAAAA;AAAAA,QAEDtX,EAAQ,SAAW,EACjBsX,qHACAtX,EAAQ,IACN,CAAC,CAAC/Q,EAAKhE,CAAK,IAAMqsB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,2BAKHroB,CAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAOHhE,CAAK;AAAA,4BACHnD,GACTsxB,EAAM,WAAWjiB,EAAO,GAAIlI,EAAMnH,EAAE,OAA4B,KAAK,CAAC;AAAA,8BAC5DsxB,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,8BAKZA,EAAM,MAAM;AAAA,2BACf,IAAMA,EAAM,cAAcjiB,EAAO,GAAIlI,CAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,cAMzD;AAAA;AAAA;AAAA;AAAA;AAAA,sBAKWmqB,EAAM,MAAM;AAAA,mBACf,IAAMA,EAAM,eAAejiB,EAAO,EAAE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAOlCiiB,EAAM,MAAM;AAAA,mBACf,IAAMA,EAAM,oBAAoBjiB,EAAO,EAAE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAO7D,CAEA,SAAS8wB,GAAa9wB,EAAuBiiB,EAAsB,CACjE,MAAM8O,EAAW9O,EAAM,YAAcjiB,EAAO,GACtCgxB,EAASP,GAAWzwB,CAAM,EAC1BixB,EAAaD,IAAW,EAAI,YAAc,GAAGA,CAAM,SAASA,EAAS,EAAI,IAAM,EAAE,GAEvF,OAAO7Q;AAAAA;AAAAA;AAAAA;AAAAA,iBAIQ,IAAM8B,EAAM,eAAejiB,EAAO,EAAE,CAAC;AAAA;AAAA;AAAA,+CAGPA,EAAO,IAAI;AAAA,gDACVA,EAAO,EAAE;AAAA;AAAA,6CAEZixB,CAAU;AAAA;AAAA,QAE/CF,EAAWF,GAAkB7wB,EAAQiiB,CAAK,EAAIf,CAAO;AAAA;AAAA,GAG7D,CAEO,SAASgQ,GAAmBjP,EAAsB,CACvD,GAAI,CAACA,EAAM,UACT,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAUT,MAAMgR,EAAsBxgC,GAAa,CACvCA,EAAE,iBACFsxB,EAAM,gBACR,EAEMmP,EAAmBzgC,GAAa,CACpCA,EAAE,iBACEsxB,EAAM,eAAe,QAAUA,EAAM,cAAc,QACrDA,EAAM,MAAMA,EAAM,eAAgBA,EAAM,aAAa,CAEzD,EAGMoP,EAAepP,EAAM,gBACvBA,EAAM,QAAQ,KAAMlxB,GAAMA,EAAE,KAAOkxB,EAAM,eAAe,EACxD,KACEqP,EAAiBrP,EAAM,cACzBA,EAAM,QAAQ,KAAMlxB,GAAMA,EAAE,KAAOkxB,EAAM,aAAa,EACtD,KAEJ,OAAO9B;AAAAA;AAAAA,QAEDO,GAAc,WAAYuB,EAAM,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,wBAWxBA,EAAM,OAAO;AAAA,qBAChBA,EAAM,SAAS;AAAA;AAAA,cAEtBA,EAAM,QAAU,aAAe,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKjCA,EAAM,aAAa;AAAA;AAAA;AAAA;AAAA;;AAAA,UAM9BA,EAAM,MACJ9B,uDAA0D8B,EAAM,KAAK,SACrEf,CAAO;;AAAA,UAETe,EAAM,YACJ9B;AAAAA,wDAC4CiR,CAAe;AAAA;AAAA;AAAA;AAAA,2BAI5CnP,EAAM,cAAc;AAAA,2BACnBtxB,GACRsxB,EAAM,uBAAwBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA,8BACxDsxB,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKfA,EAAM,aAAa;AAAA,2BAClBtxB,GACRsxB,EAAM,sBAAuBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA,8BACvDsxB,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gCAOVA,EAAM,QAAU,CAACA,EAAM,eAAe,QAAU,CAACA,EAAM,cAAc,MAAM;AAAA;AAAA,sBAErFA,EAAM,OAAS,YAAc,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAM3BA,EAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,cAOtCf,CAAO;;AAAA;AAAA;AAAA;AAAA,oBAKCiQ,CAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKjBlP,EAAM,WAAW;AAAA,qBAChBtxB,GAAasxB,EAAM,SAAUtxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,YAY3EsxB,EAAM,QAAQ,SAAW,EACvB9B;AAAAA,kBACI8B,EAAM,YAAY,OAChB,wBAAwBA,EAAM,WAAW,KACzC,iDAAiD;AAAA,sBAEvDA,EAAM,QAAQ,IAAKjiB,GAAW8wB,GAAa9wB,EAAQiiB,CAAK,CAAC,CAAC;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,MAYlEoP,EAAeX,GAAyBW,EAAcpP,CAAK,EAAIf,CAAO;AAAA,MACtEoQ,EAAiBX,GAAoBW,EAAgBrP,CAAK,EAAIf,CAAO;AAAA,GAE3E,CCjXA,MAAMxwB,GAAE,CAAa,MAAM,CAAkD,EAAEC,GAAED,GAAG,IAAIC,KAAK,CAAC,gBAAgBD,EAAE,OAAOC,CAAC,GAAE,IAAA4gC,GAAC,KAAO,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE5gC,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,KAAK,KAAKA,EAAE,KAAK,KAAK,CAAC,CAAC,KAAK,EAAEA,EAAE,CAAC,OAAO,KAAK,OAAO,EAAEA,CAAC,CAAC,CAAC,OAAO,EAAEA,EAAE,CAAC,OAAO,KAAK,OAAO,GAAGA,CAAC,CAAC,CAAC,ECApS,KAAC,CAAC,EAAED,EAAC,EAAEG,GAAEI,GAAEJ,GAAGA,EAA8PD,GAAE,IAAI,SAAS,cAAc,EAAE,EAAEoB,GAAE,CAACnB,EAAEG,EAAEL,IAAI,OAAC,MAAMW,EAAET,EAAE,KAAK,WAAWW,EAAWR,IAAT,OAAWH,EAAE,KAAKG,EAAE,KAAK,GAAYL,IAAT,OAAW,CAAC,MAAMM,EAAEK,EAAE,aAAaV,GAAC,EAAGY,CAAC,EAAER,EAAEM,EAAE,aAAaV,GAAC,EAAGY,CAAC,EAAEb,EAAE,IAAID,GAAEO,EAAED,EAAEH,EAAEA,EAAE,OAAO,CAAC,KAAK,CAAC,MAAMH,EAAEC,EAAE,KAAK,YAAYK,EAAEL,EAAE,KAAKQ,EAAEH,IAAIH,EAAE,GAAGM,EAAE,CAAC,IAAIT,GAAEmB,EAAAlB,EAAE,OAAF,MAAAkB,EAAA,KAAAlB,EAASE,GAAGF,EAAE,KAAKE,EAAWF,EAAE,OAAX,SAAkBD,EAAEG,EAAE,QAAQG,EAAE,MAAML,EAAE,KAAKD,CAAC,CAAC,CAAC,GAAGA,IAAIc,GAAGL,EAAE,CAAC,IAAIN,EAAEF,EAAE,KAAK,KAAKE,IAAIH,GAAG,CAAC,MAAMA,EAAEO,GAAEJ,CAAC,EAAE,YAAYI,GAAEK,CAAC,EAAE,aAAaT,EAAEW,CAAC,EAAEX,EAAEH,CAAC,CAAC,CAAC,CAAC,OAAOC,CAAC,EAAEc,GAAE,CAACZ,EAAE,EAAEI,EAAEJ,KAAKA,EAAE,KAAK,EAAEI,CAAC,EAAEJ,GAAGqB,GAAE,GAAGX,GAAE,CAACV,EAAE,EAAEqB,KAAIrB,EAAE,KAAK,EAAEoC,GAAEpC,GAAGA,EAAE,KAAKO,GAAEP,GAAG,CAACA,EAAE,KAAI,EAAGA,EAAE,KAAK,QAAQ,ECC5xB,MAAMY,GAAE,CAAC,EAAEb,EAAEF,IAAI,CAAC,MAAMK,EAAE,IAAI,IAAI,QAAQO,EAAEV,EAAEU,GAAGZ,EAAEY,IAAIP,EAAE,IAAI,EAAEO,CAAC,EAAEA,CAAC,EAAE,OAAOP,CAAC,EAAEI,GAAEP,GAAE,cAAcF,EAAC,CAAC,YAAY,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,EAAE,OAAOK,GAAE,MAAM,MAAM,MAAM,+CAA+C,CAAC,CAAC,GAAG,EAAEH,EAAEF,EAAE,CAAC,IAAIK,EAAWL,IAAT,OAAWA,EAAEE,EAAWA,IAAT,SAAaG,EAAEH,GAAG,MAAMU,EAAE,GAAG,EAAE,GAAG,IAAIL,EAAE,EAAE,UAAUL,KAAK,EAAEU,EAAEL,CAAC,EAAEF,EAAEA,EAAEH,EAAEK,CAAC,EAAEA,EAAE,EAAEA,CAAC,EAAEP,EAAEE,EAAEK,CAAC,EAAEA,IAAI,MAAM,CAAC,OAAO,EAAE,KAAKK,CAAC,CAAC,CAAC,OAAO,EAAEV,EAAEF,EAAE,CAAC,OAAO,KAAK,GAAG,EAAEE,EAAEF,CAAC,EAAE,MAAM,CAAC,OAAOE,EAAE,CAAC,EAAEG,EAAEI,CAAC,EAAE,CAAC,MAAMK,EAAEF,GAAEV,CAAC,EAAE,CAAC,OAAOW,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,EAAER,EAAEI,CAAC,EAAE,GAAG,CAAC,MAAM,QAAQK,CAAC,EAAE,OAAO,KAAK,GAAG,EAAED,EAAE,MAAMH,EAAE,KAAK,KAAL,KAAK,GAAK,IAAGY,EAAE,GAAG,IAAIE,EAAEH,EAAEM,EAAE,EAAEkB,EAAE/B,EAAE,OAAO,EAAE2B,EAAE,EAAE6e,EAAEzgB,EAAE,OAAO,EAAE,KAAKc,GAAGkB,GAAGJ,GAAG6e,GAAG,GAAUxgB,EAAEa,CAAC,IAAV,KAAYA,YAAmBb,EAAE+B,CAAC,IAAV,KAAYA,YAAYnC,EAAEiB,CAAC,IAAI,EAAEc,CAAC,EAAEnB,EAAEmB,CAAC,EAAEtC,GAAEW,EAAEa,CAAC,EAAEd,EAAE4B,CAAC,CAAC,EAAEd,IAAIc,YAAY/B,EAAEmC,CAAC,IAAI,EAAEye,CAAC,EAAEhgB,EAAEggB,CAAC,EAAEnhB,GAAEW,EAAE+B,CAAC,EAAEhC,EAAEygB,CAAC,CAAC,EAAEze,IAAIye,YAAY5gB,EAAEiB,CAAC,IAAI,EAAE2f,CAAC,EAAEhgB,EAAEggB,CAAC,EAAEnhB,GAAEW,EAAEa,CAAC,EAAEd,EAAEygB,CAAC,CAAC,EAAE/gB,GAAEL,EAAEoB,EAAEggB,EAAE,CAAC,EAAExgB,EAAEa,CAAC,CAAC,EAAEA,IAAI2f,YAAY5gB,EAAEmC,CAAC,IAAI,EAAEJ,CAAC,EAAEnB,EAAEmB,CAAC,EAAEtC,GAAEW,EAAE+B,CAAC,EAAEhC,EAAE4B,CAAC,CAAC,EAAElC,GAAEL,EAAEY,EAAEa,CAAC,EAAEb,EAAE+B,CAAC,CAAC,EAAEA,IAAIJ,YAAqBjB,IAAT,SAAaA,EAAET,GAAE,EAAE0B,EAAE6e,CAAC,EAAEjgB,EAAEN,GAAEL,EAAEiB,EAAEkB,CAAC,GAAGrB,EAAE,IAAId,EAAEiB,CAAC,CAAC,EAAE,GAAGH,EAAE,IAAId,EAAEmC,CAAC,CAAC,EAAE,CAAC,MAAM5C,EAAEoB,EAAE,IAAI,EAAEoB,CAAC,CAAC,EAAEzC,EAAWC,IAAT,OAAWa,EAAEb,CAAC,EAAE,KAAK,GAAUD,IAAP,KAAS,CAAC,MAAMC,EAAEM,GAAEL,EAAEY,EAAEa,CAAC,CAAC,EAAExB,GAAEF,EAAEY,EAAE4B,CAAC,CAAC,EAAEnB,EAAEmB,CAAC,EAAExC,CAAC,MAAMqB,EAAEmB,CAAC,EAAEtC,GAAEH,EAAEa,EAAE4B,CAAC,CAAC,EAAElC,GAAEL,EAAEY,EAAEa,CAAC,EAAE3B,CAAC,EAAEc,EAAEb,CAAC,EAAE,KAAKwC,GAAG,MAAMnC,GAAEQ,EAAE+B,CAAC,CAAC,EAAEA,SAASvC,GAAEQ,EAAEa,CAAC,CAAC,EAAEA,IAAI,KAAKc,GAAG6e,GAAG,CAAC,MAAMrhB,EAAEM,GAAEL,EAAEoB,EAAEggB,EAAE,CAAC,CAAC,EAAEnhB,GAAEF,EAAEY,EAAE4B,CAAC,CAAC,EAAEnB,EAAEmB,GAAG,EAAExC,CAAC,CAAC,KAAK0B,GAAGkB,GAAG,CAAC,MAAM5C,EAAEa,EAAEa,GAAG,EAAS1B,IAAP,MAAUK,GAAEL,CAAC,CAAC,CAAC,OAAO,KAAK,GAAG,EAAEe,GAAEd,EAAEoB,CAAC,EAAErB,EAAC,CAAC,CAAC,ECDjrC,MAAMA,WAAUC,EAAC,CAAC,YAAYK,EAAE,CAAC,GAAG,MAAMA,CAAC,EAAE,KAAK,GAAGP,EAAEO,EAAE,OAAOD,GAAE,MAAM,MAAM,MAAM,KAAK,YAAY,cAAc,uCAAuC,CAAC,CAAC,OAAOD,EAAE,CAAC,GAAGA,IAAIL,GAASK,GAAN,KAAQ,OAAO,KAAK,GAAG,OAAO,KAAK,GAAGA,EAAE,GAAGA,IAAIE,GAAE,OAAOF,EAAE,GAAa,OAAOA,GAAjB,SAAmB,MAAM,MAAM,KAAK,YAAY,cAAc,mCAAmC,EAAE,GAAGA,IAAI,KAAK,GAAG,OAAO,KAAK,GAAG,KAAK,GAAGA,EAAE,MAAMH,EAAE,CAACG,CAAC,EAAE,OAAOH,EAAE,IAAIA,EAAE,KAAK,GAAG,CAAC,WAAW,KAAK,YAAY,WAAW,QAAQA,EAAE,OAAO,EAAE,CAAC,CAAC,CAACD,GAAE,cAAc,aAAaA,GAAE,WAAW,EAAE,MAAME,GAAEE,GAAEJ,EAAC,ECHnhB,KAAM,CACJ,QAAAkY,GACA,eAAA2oB,GACA,SAAAC,GACA,eAAAC,GACA,yBAAAC,EACF,EAAI,OACJ,GAAI,CACF,OAAAC,GACA,KAAAC,GACA,OAAAC,EACF,EAAI,OACA,CACF,MAAAC,GACA,UAAAC,EACF,EAAI,OAAO,QAAY,KAAe,QACjCJ,KACHA,GAAS,SAAgBv/B,EAAG,CAC1B,OAAOA,CACT,GAEGw/B,KACHA,GAAO,SAAcx/B,EAAG,CACtB,OAAOA,CACT,GAEG0/B,KACHA,GAAQ,SAAeE,EAAMC,EAAS,CACpC,QAASC,EAAO,UAAU,OAAQ7wB,EAAO,IAAI,MAAM6wB,EAAO,EAAIA,EAAO,EAAI,CAAC,EAAGC,EAAO,EAAGA,EAAOD,EAAMC,IAClG9wB,EAAK8wB,EAAO,CAAC,EAAI,UAAUA,CAAI,EAEjC,OAAOH,EAAK,MAAMC,EAAS5wB,CAAI,CACjC,GAEG0wB,KACHA,GAAY,SAAmBK,EAAM,CACnC,QAASC,EAAQ,UAAU,OAAQhxB,EAAO,IAAI,MAAMgxB,EAAQ,EAAIA,EAAQ,EAAI,CAAC,EAAGC,EAAQ,EAAGA,EAAQD,EAAOC,IACxGjxB,EAAKixB,EAAQ,CAAC,EAAI,UAAUA,CAAK,EAEnC,OAAO,IAAIF,EAAK,GAAG/wB,CAAI,CACzB,GAEF,MAAMkxB,GAAeC,GAAQ,MAAM,UAAU,OAAO,EAC9CC,GAAmBD,GAAQ,MAAM,UAAU,WAAW,EACtDE,GAAWF,GAAQ,MAAM,UAAU,GAAG,EACtCG,GAAYH,GAAQ,MAAM,UAAU,IAAI,EACxCI,GAAcJ,GAAQ,MAAM,UAAU,MAAM,EAC5CK,GAAoBL,GAAQ,OAAO,UAAU,WAAW,EACxDM,GAAiBN,GAAQ,OAAO,UAAU,QAAQ,EAClDO,GAAcP,GAAQ,OAAO,UAAU,KAAK,EAC5CQ,GAAgBR,GAAQ,OAAO,UAAU,OAAO,EAChDS,GAAgBT,GAAQ,OAAO,UAAU,OAAO,EAChDU,GAAaV,GAAQ,OAAO,UAAU,IAAI,EAC1CW,GAAuBX,GAAQ,OAAO,UAAU,cAAc,EAC9DY,GAAaZ,GAAQ,OAAO,UAAU,IAAI,EAC1Ca,GAAkBC,GAAY,SAAS,EAO7C,SAASd,GAAQR,EAAM,CACrB,OAAO,SAAUC,EAAS,CACpBA,aAAmB,SACrBA,EAAQ,UAAY,GAEtB,QAASsB,EAAQ,UAAU,OAAQlyB,EAAO,IAAI,MAAMkyB,EAAQ,EAAIA,EAAQ,EAAI,CAAC,EAAGC,EAAQ,EAAGA,EAAQD,EAAOC,IACxGnyB,EAAKmyB,EAAQ,CAAC,EAAI,UAAUA,CAAK,EAEnC,OAAO1B,GAAME,EAAMC,EAAS5wB,CAAI,CAClC,CACF,CAOA,SAASiyB,GAAYlB,EAAM,CACzB,OAAO,UAAY,CACjB,QAASqB,EAAQ,UAAU,OAAQpyB,EAAO,IAAI,MAAMoyB,CAAK,EAAGC,EAAQ,EAAGA,EAAQD,EAAOC,IACpFryB,EAAKqyB,CAAK,EAAI,UAAUA,CAAK,EAE/B,OAAO3B,GAAUK,EAAM/wB,CAAI,CAC7B,CACF,CASA,SAASsyB,EAASC,EAAKnpB,EAAO,CAC5B,IAAIopB,EAAoB,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAIhB,GACxFtB,IAIFA,GAAeqC,EAAK,IAAI,EAE1B,IAAIviC,EAAIoZ,EAAM,OACd,KAAOpZ,KAAK,CACV,IAAIyiC,EAAUrpB,EAAMpZ,CAAC,EACrB,GAAI,OAAOyiC,GAAY,SAAU,CAC/B,MAAMC,EAAYF,EAAkBC,CAAO,EACvCC,IAAcD,IAEXtC,GAAS/mB,CAAK,IACjBA,EAAMpZ,CAAC,EAAI0iC,GAEbD,EAAUC,EAEd,CACAH,EAAIE,CAAO,EAAI,EACjB,CACA,OAAOF,CACT,CAOA,SAASI,GAAWvpB,EAAO,CACzB,QAASwpB,EAAQ,EAAGA,EAAQxpB,EAAM,OAAQwpB,IAChBd,GAAqB1oB,EAAOwpB,CAAK,IAEvDxpB,EAAMwpB,CAAK,EAAI,MAGnB,OAAOxpB,CACT,CAOA,SAASypB,GAAMC,EAAQ,CACrB,MAAMC,EAAYvC,GAAO,IAAI,EAC7B,SAAW,CAACwC,EAAUxgC,CAAK,IAAK+U,GAAQurB,CAAM,EACpBhB,GAAqBgB,EAAQE,CAAQ,IAEvD,MAAM,QAAQxgC,CAAK,EACrBugC,EAAUC,CAAQ,EAAIL,GAAWngC,CAAK,EAC7BA,GAAS,OAAOA,GAAU,UAAYA,EAAM,cAAgB,OACrEugC,EAAUC,CAAQ,EAAIH,GAAMrgC,CAAK,EAEjCugC,EAAUC,CAAQ,EAAIxgC,GAI5B,OAAOugC,CACT,CAQA,SAASE,GAAaH,EAAQp+B,EAAM,CAClC,KAAOo+B,IAAW,MAAM,CACtB,MAAMI,EAAO7C,GAAyByC,EAAQp+B,CAAI,EAClD,GAAIw+B,EAAM,CACR,GAAIA,EAAK,IACP,OAAO/B,GAAQ+B,EAAK,GAAG,EAEzB,GAAI,OAAOA,EAAK,OAAU,WACxB,OAAO/B,GAAQ+B,EAAK,KAAK,CAE7B,CACAJ,EAAS1C,GAAe0C,CAAM,CAChC,CACA,SAASK,GAAgB,CACvB,OAAO,IACT,CACA,OAAOA,CACT,CAEA,MAAMC,GAAS9C,GAAO,CAAC,IAAK,OAAQ,UAAW,UAAW,OAAQ,UAAW,QAAS,QAAS,IAAK,MAAO,MAAO,MAAO,QAAS,aAAc,OAAQ,KAAM,SAAU,SAAU,UAAW,SAAU,OAAQ,OAAQ,MAAO,WAAY,UAAW,OAAQ,WAAY,KAAM,YAAa,MAAO,UAAW,MAAO,SAAU,MAAO,MAAO,KAAM,KAAM,UAAW,KAAM,WAAY,aAAc,SAAU,OAAQ,SAAU,OAAQ,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,OAAQ,SAAU,SAAU,KAAM,OAAQ,IAAK,MAAO,QAAS,MAAO,MAAO,QAAS,SAAU,KAAM,OAAQ,MAAO,OAAQ,UAAW,OAAQ,WAAY,QAAS,MAAO,OAAQ,KAAM,WAAY,SAAU,SAAU,IAAK,UAAW,MAAO,WAAY,IAAK,KAAM,KAAM,OAAQ,IAAK,OAAQ,SAAU,UAAW,SAAU,SAAU,OAAQ,QAAS,SAAU,SAAU,OAAQ,SAAU,SAAU,QAAS,MAAO,UAAW,MAAO,QAAS,QAAS,KAAM,WAAY,WAAY,QAAS,KAAM,QAAS,OAAQ,KAAM,QAAS,KAAM,IAAK,KAAM,MAAO,QAAS,KAAK,CAAC,EAC3/B+C,GAAQ/C,GAAO,CAAC,MAAO,IAAK,WAAY,cAAe,eAAgB,eAAgB,gBAAiB,mBAAoB,SAAU,WAAY,OAAQ,OAAQ,UAAW,eAAgB,cAAe,SAAU,OAAQ,IAAK,QAAS,WAAY,QAAS,QAAS,YAAa,OAAQ,iBAAkB,SAAU,OAAQ,WAAY,QAAS,OAAQ,OAAQ,UAAW,UAAW,WAAY,iBAAkB,OAAQ,OAAQ,QAAS,SAAU,SAAU,OAAQ,WAAY,QAAS,OAAQ,QAAS,OAAQ,OAAO,CAAC,EACvgBgD,GAAahD,GAAO,CAAC,UAAW,gBAAiB,sBAAuB,cAAe,mBAAoB,oBAAqB,oBAAqB,iBAAkB,eAAgB,UAAW,UAAW,UAAW,UAAW,UAAW,iBAAkB,UAAW,UAAW,cAAe,eAAgB,WAAY,eAAgB,qBAAsB,cAAe,SAAU,cAAc,CAAC,EAK/YiD,GAAgBjD,GAAO,CAAC,UAAW,gBAAiB,SAAU,UAAW,YAAa,mBAAoB,iBAAkB,gBAAiB,gBAAiB,gBAAiB,QAAS,YAAa,OAAQ,eAAgB,YAAa,UAAW,gBAAiB,SAAU,MAAO,aAAc,UAAW,KAAK,CAAC,EACtTkD,GAAWlD,GAAO,CAAC,OAAQ,WAAY,SAAU,UAAW,QAAS,SAAU,KAAM,aAAc,gBAAiB,KAAM,KAAM,QAAS,UAAW,WAAY,QAAS,OAAQ,KAAM,SAAU,QAAS,SAAU,OAAQ,OAAQ,UAAW,SAAU,MAAO,QAAS,MAAO,SAAU,aAAc,aAAa,CAAC,EAGtTmD,GAAmBnD,GAAO,CAAC,UAAW,cAAe,aAAc,WAAY,YAAa,UAAW,UAAW,SAAU,SAAU,QAAS,YAAa,aAAc,iBAAkB,cAAe,MAAM,CAAC,EAClN/5B,GAAO+5B,GAAO,CAAC,OAAO,CAAC,EAEvBzR,GAAOyR,GAAO,CAAC,SAAU,SAAU,QAAS,MAAO,iBAAkB,eAAgB,uBAAwB,WAAY,aAAc,UAAW,SAAU,UAAW,cAAe,cAAe,UAAW,OAAQ,QAAS,QAAS,QAAS,OAAQ,UAAW,WAAY,eAAgB,SAAU,cAAe,WAAY,WAAY,UAAW,MAAO,WAAY,0BAA2B,wBAAyB,WAAY,YAAa,UAAW,eAAgB,cAAe,OAAQ,MAAO,UAAW,SAAU,SAAU,OAAQ,OAAQ,WAAY,KAAM,QAAS,YAAa,YAAa,QAAS,OAAQ,QAAS,OAAQ,OAAQ,UAAW,OAAQ,MAAO,MAAO,YAAa,QAAS,SAAU,MAAO,YAAa,WAAY,QAAS,OAAQ,QAAS,UAAW,aAAc,SAAU,OAAQ,UAAW,OAAQ,UAAW,cAAe,cAAe,UAAW,gBAAiB,sBAAuB,SAAU,UAAW,UAAW,aAAc,WAAY,MAAO,WAAY,MAAO,WAAY,OAAQ,OAAQ,UAAW,aAAc,QAAS,WAAY,QAAS,OAAQ,QAAS,OAAQ,OAAQ,UAAW,QAAS,MAAO,SAAU,OAAQ,QAAS,UAAW,WAAY,QAAS,YAAa,OAAQ,SAAU,SAAU,QAAS,QAAS,OAAQ,QAAS,MAAM,CAAC,EAC3wCoD,GAAMpD,GAAO,CAAC,gBAAiB,aAAc,WAAY,qBAAsB,YAAa,SAAU,gBAAiB,gBAAiB,UAAW,gBAAiB,iBAAkB,QAAS,OAAQ,KAAM,QAAS,OAAQ,gBAAiB,YAAa,YAAa,QAAS,sBAAuB,8BAA+B,gBAAiB,kBAAmB,KAAM,KAAM,IAAK,KAAM,KAAM,kBAAmB,YAAa,UAAW,UAAW,MAAO,WAAY,YAAa,MAAO,WAAY,OAAQ,eAAgB,YAAa,SAAU,cAAe,cAAe,gBAAiB,cAAe,YAAa,mBAAoB,eAAgB,aAAc,eAAgB,cAAe,KAAM,KAAM,KAAM,KAAM,aAAc,WAAY,gBAAiB,oBAAqB,SAAU,OAAQ,KAAM,kBAAmB,KAAM,MAAO,YAAa,IAAK,KAAM,KAAM,KAAM,KAAM,UAAW,YAAa,aAAc,WAAY,OAAQ,eAAgB,iBAAkB,eAAgB,mBAAoB,iBAAkB,QAAS,aAAc,aAAc,eAAgB,eAAgB,cAAe,cAAe,mBAAoB,YAAa,MAAO,OAAQ,YAAa,QAAS,SAAU,OAAQ,MAAO,OAAQ,aAAc,SAAU,WAAY,UAAW,QAAS,SAAU,cAAe,SAAU,WAAY,cAAe,OAAQ,aAAc,sBAAuB,mBAAoB,eAAgB,SAAU,gBAAiB,sBAAuB,iBAAkB,IAAK,KAAM,KAAM,SAAU,OAAQ,OAAQ,cAAe,YAAa,UAAW,SAAU,SAAU,QAAS,OAAQ,kBAAmB,QAAS,mBAAoB,mBAAoB,eAAgB,cAAe,eAAgB,cAAe,aAAc,eAAgB,mBAAoB,oBAAqB,iBAAkB,kBAAmB,oBAAqB,iBAAkB,SAAU,eAAgB,QAAS,eAAgB,iBAAkB,WAAY,cAAe,UAAW,UAAW,YAAa,mBAAoB,cAAe,kBAAmB,iBAAkB,aAAc,OAAQ,KAAM,KAAM,UAAW,SAAU,UAAW,aAAc,UAAW,aAAc,gBAAiB,gBAAiB,QAAS,eAAgB,OAAQ,eAAgB,mBAAoB,mBAAoB,IAAK,KAAM,KAAM,QAAS,IAAK,KAAM,KAAM,IAAK,YAAY,CAAC,EACt1EqD,GAASrD,GAAO,CAAC,SAAU,cAAe,QAAS,WAAY,QAAS,eAAgB,cAAe,aAAc,aAAc,QAAS,MAAO,UAAW,eAAgB,WAAY,QAAS,QAAS,SAAU,OAAQ,KAAM,UAAW,SAAU,gBAAiB,SAAU,SAAU,iBAAkB,YAAa,WAAY,cAAe,UAAW,UAAW,gBAAiB,WAAY,WAAY,OAAQ,WAAY,WAAY,aAAc,UAAW,SAAU,SAAU,cAAe,gBAAiB,uBAAwB,YAAa,YAAa,aAAc,WAAY,iBAAkB,iBAAkB,YAAa,UAAW,QAAS,OAAO,CAAC,EAC7pBsD,GAAMtD,GAAO,CAAC,aAAc,SAAU,cAAe,YAAa,aAAa,CAAC,EAGhFuD,GAAgBtD,GAAK,2BAA2B,EAChDuD,GAAWvD,GAAK,uBAAuB,EACvCwD,GAAcxD,GAAK,eAAe,EAClCyD,GAAYzD,GAAK,8BAA8B,EAC/C0D,GAAY1D,GAAK,gBAAgB,EACjC2D,GAAiB3D,GAAK,kGAC5B,EACM4D,GAAoB5D,GAAK,uBAAuB,EAChD6D,GAAkB7D,GAAK,6DAC7B,EACM8D,GAAe9D,GAAK,SAAS,EAC7B+D,GAAiB/D,GAAK,0BAA0B,EAEtD,IAAIgE,GAA2B,OAAO,OAAO,CAC3C,UAAW,KACX,UAAWN,GACX,gBAAiBG,GACjB,eAAgBE,GAChB,UAAWN,GACX,aAAcK,GACd,SAAUP,GACV,eAAgBI,GAChB,kBAAmBC,GACnB,cAAeN,GACf,YAAaE,EACf,CAAC,EAID,MAAMS,GAAY,CAChB,QAAS,EAET,KAAM,EAMN,uBAAwB,EACxB,QAAS,EACT,SAAU,CAIZ,EACMC,GAAY,UAAqB,CACrC,OAAO,OAAO,OAAW,IAAc,KAAO,MAChD,EASMC,GAA4B,SAAmCC,EAAcC,EAAmB,CACpG,GAAI,OAAOD,GAAiB,UAAY,OAAOA,EAAa,cAAiB,WAC3E,OAAO,KAKT,IAAIE,EAAS,KACb,MAAMC,EAAY,wBACdF,GAAqBA,EAAkB,aAAaE,CAAS,IAC/DD,EAASD,EAAkB,aAAaE,CAAS,GAEnD,MAAMC,EAAa,aAAeF,EAAS,IAAMA,EAAS,IAC1D,GAAI,CACF,OAAOF,EAAa,aAAaI,EAAY,CAC3C,WAAWlW,EAAM,CACf,OAAOA,CACT,EACA,gBAAgBmW,EAAW,CACzB,OAAOA,CACT,CACN,CAAK,CACH,MAAY,CAIV,eAAQ,KAAK,uBAAyBD,EAAa,wBAAwB,EACpE,IACT,CACF,EACME,GAAkB,UAA2B,CACjD,MAAO,CACL,wBAAyB,GACzB,sBAAuB,GACvB,uBAAwB,GACxB,yBAA0B,GAC1B,uBAAwB,GACxB,wBAAyB,GACzB,sBAAuB,GACvB,oBAAqB,GACrB,uBAAwB,EAC5B,CACA,EACA,SAASC,IAAkB,CACzB,IAAIC,EAAS,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAIV,GAAS,EAC1F,MAAMW,EAAYvhC,GAAQqhC,GAAgBrhC,CAAI,EAG9C,GAFAuhC,EAAU,QAAU,QACpBA,EAAU,QAAU,GAChB,CAACD,GAAU,CAACA,EAAO,UAAYA,EAAO,SAAS,WAAaX,GAAU,UAAY,CAACW,EAAO,QAG5F,OAAAC,EAAU,YAAc,GACjBA,EAET,GAAI,CACF,SAAAC,CACJ,EAAMF,EACJ,MAAMG,EAAmBD,EACnBE,EAAgBD,EAAiB,cACjC,CACJ,iBAAAE,EACA,oBAAAC,EACA,KAAAC,EACA,QAAAC,EACA,WAAAC,EACA,aAAAC,EAAeV,EAAO,cAAgBA,EAAO,gBAC7C,gBAAAW,EACA,UAAAC,EACA,aAAApB,CACJ,EAAMQ,EACEa,EAAmBL,EAAQ,UAC3BM,EAAYhD,GAAa+C,EAAkB,WAAW,EACtDE,EAASjD,GAAa+C,EAAkB,QAAQ,EAChDG,EAAiBlD,GAAa+C,EAAkB,aAAa,EAC7DI,EAAgBnD,GAAa+C,EAAkB,YAAY,EAC3DK,EAAgBpD,GAAa+C,EAAkB,YAAY,EAOjE,GAAI,OAAOP,GAAwB,WAAY,CAC7C,MAAMa,EAAWjB,EAAS,cAAc,UAAU,EAC9CiB,EAAS,SAAWA,EAAS,QAAQ,gBACvCjB,EAAWiB,EAAS,QAAQ,cAEhC,CACA,IAAIC,EACAC,EAAY,GAChB,KAAM,CACJ,eAAAC,EACA,mBAAAC,EACA,uBAAAC,EACA,qBAAAC,CACJ,EAAMvB,EACE,CACJ,WAAAwB,CACJ,EAAMvB,EACJ,IAAIwB,EAAQ7B,GAAe,EAI3BG,EAAU,YAAc,OAAO7tB,IAAY,YAAc,OAAO8uB,GAAkB,YAAcI,GAAkBA,EAAe,qBAAuB,OACxJ,KAAM,CACJ,cAAA5C,GACA,SAAAC,GACA,YAAAC,GACA,UAAAC,GACA,UAAAC,GACA,kBAAAE,GACA,gBAAAC,GACA,eAAAE,EACJ,EAAMC,GACJ,GAAI,CACF,eAAgBwC,EACpB,EAAMxC,GAMAyC,GAAe,KACnB,MAAMC,GAAuB3E,EAAS,GAAI,CAAC,GAAGc,GAAQ,GAAGC,GAAO,GAAGC,GAAY,GAAGE,GAAU,GAAGj9B,EAAI,CAAC,EAEpG,IAAI2gC,GAAe,KACnB,MAAMC,GAAuB7E,EAAS,GAAI,CAAC,GAAGzT,GAAM,GAAG6U,GAAK,GAAGC,GAAQ,GAAGC,EAAG,CAAC,EAO9E,IAAIwD,EAA0B,OAAO,KAAK5G,GAAO,KAAM,CACrD,aAAc,CACZ,SAAU,GACV,aAAc,GACd,WAAY,GACZ,MAAO,IACb,EACI,mBAAoB,CAClB,SAAU,GACV,aAAc,GACd,WAAY,GACZ,MAAO,IACb,EACI,+BAAgC,CAC9B,SAAU,GACV,aAAc,GACd,WAAY,GACZ,MAAO,EACb,CACA,CAAG,CAAC,EAEE6G,GAAc,KAEdC,GAAc,KAElB,MAAMC,GAAyB,OAAO,KAAK/G,GAAO,KAAM,CACtD,SAAU,CACR,SAAU,GACV,aAAc,GACd,WAAY,GACZ,MAAO,IACb,EACI,eAAgB,CACd,SAAU,GACV,aAAc,GACd,WAAY,GACZ,MAAO,IACb,CACA,CAAG,CAAC,EAEF,IAAIgH,GAAkB,GAElBC,EAAkB,GAElBC,EAA0B,GAG1BC,EAA2B,GAI3BC,EAAqB,GAIrBC,GAAe,GAEfC,EAAiB,GAEjBC,GAAa,GAGbC,GAAa,GAKbC,GAAa,GAGbC,GAAsB,GAGtBC,GAAsB,GAItBC,GAAe,GAcfC,GAAuB,GAC3B,MAAMC,GAA8B,gBAEpC,IAAIC,GAAe,GAGfC,GAAW,GAEXC,GAAe,GAEfC,GAAkB,KACtB,MAAMC,GAA0BrG,EAAS,GAAI,CAAC,iBAAkB,QAAS,WAAY,OAAQ,gBAAiB,OAAQ,SAAU,OAAQ,KAAM,KAAM,KAAM,KAAM,QAAS,UAAW,WAAY,WAAY,YAAa,SAAU,QAAS,MAAO,WAAY,QAAS,QAAS,QAAS,KAAK,CAAC,EAEhS,IAAIsG,GAAgB,KACpB,MAAMC,GAAwBvG,EAAS,GAAI,CAAC,QAAS,QAAS,MAAO,SAAU,QAAS,OAAO,CAAC,EAEhG,IAAIwG,GAAsB,KAC1B,MAAMC,GAA8BzG,EAAS,GAAI,CAAC,MAAO,QAAS,MAAO,KAAM,QAAS,OAAQ,UAAW,cAAe,OAAQ,UAAW,QAAS,QAAS,QAAS,OAAO,CAAC,EAC1K0G,GAAmB,qCACnBC,GAAgB,6BAChBC,GAAiB,+BAEvB,IAAIC,GAAYD,GACZE,GAAiB,GAEjBC,GAAqB,KACzB,MAAMC,GAA6BhH,EAAS,GAAI,CAAC0G,GAAkBC,GAAeC,EAAc,EAAGzH,EAAc,EACjH,IAAI8H,GAAiCjH,EAAS,GAAI,CAAC,KAAM,KAAM,KAAM,KAAM,OAAO,CAAC,EAC/EkH,GAA0BlH,EAAS,GAAI,CAAC,gBAAgB,CAAC,EAK7D,MAAMmH,GAA+BnH,EAAS,GAAI,CAAC,QAAS,QAAS,OAAQ,IAAK,QAAQ,CAAC,EAE3F,IAAIoH,GAAoB,KACxB,MAAMC,GAA+B,CAAC,wBAAyB,WAAW,EACpEC,GAA4B,YAClC,IAAIpH,GAAoB,KAEpBqH,GAAS,KAGb,MAAMC,GAAczE,EAAS,cAAc,MAAM,EAC3C0E,GAAoB,SAA2BC,EAAW,CAC9D,OAAOA,aAAqB,QAAUA,aAAqB,QAC7D,EAOMC,GAAe,UAAwB,CAC3C,IAAIC,EAAM,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,GAC9E,GAAI,EAAAL,IAAUA,KAAWK,GAoIzB,KAhII,CAACA,GAAO,OAAOA,GAAQ,YACzBA,EAAM,IAGRA,EAAMrH,GAAMqH,CAAG,EACfR,GAEAC,GAA6B,QAAQO,EAAI,iBAAiB,IAAM,GAAKN,GAA4BM,EAAI,kBAErG1H,GAAoBkH,KAAsB,wBAA0BjI,GAAiBD,GAErFwF,GAAelF,GAAqBoI,EAAK,cAAc,EAAI5H,EAAS,GAAI4H,EAAI,aAAc1H,EAAiB,EAAIyE,GAC/GC,GAAepF,GAAqBoI,EAAK,cAAc,EAAI5H,EAAS,GAAI4H,EAAI,aAAc1H,EAAiB,EAAI2E,GAC/GkC,GAAqBvH,GAAqBoI,EAAK,oBAAoB,EAAI5H,EAAS,GAAI4H,EAAI,mBAAoBzI,EAAc,EAAI6H,GAC9HR,GAAsBhH,GAAqBoI,EAAK,mBAAmB,EAAI5H,EAASO,GAAMkG,EAA2B,EAAGmB,EAAI,kBAAmB1H,EAAiB,EAAIuG,GAChKH,GAAgB9G,GAAqBoI,EAAK,mBAAmB,EAAI5H,EAASO,GAAMgG,EAAqB,EAAGqB,EAAI,kBAAmB1H,EAAiB,EAAIqG,GACpJH,GAAkB5G,GAAqBoI,EAAK,iBAAiB,EAAI5H,EAAS,GAAI4H,EAAI,gBAAiB1H,EAAiB,EAAImG,GACxHtB,GAAcvF,GAAqBoI,EAAK,aAAa,EAAI5H,EAAS,GAAI4H,EAAI,YAAa1H,EAAiB,EAAIK,GAAM,EAAE,EACpHyE,GAAcxF,GAAqBoI,EAAK,aAAa,EAAI5H,EAAS,GAAI4H,EAAI,YAAa1H,EAAiB,EAAIK,GAAM,EAAE,EACpH4F,GAAe3G,GAAqBoI,EAAK,cAAc,EAAIA,EAAI,aAAe,GAC9E1C,GAAkB0C,EAAI,kBAAoB,GAC1CzC,EAAkByC,EAAI,kBAAoB,GAC1CxC,EAA0BwC,EAAI,yBAA2B,GACzDvC,EAA2BuC,EAAI,2BAA6B,GAC5DtC,EAAqBsC,EAAI,oBAAsB,GAC/CrC,GAAeqC,EAAI,eAAiB,GACpCpC,EAAiBoC,EAAI,gBAAkB,GACvCjC,GAAaiC,EAAI,YAAc,GAC/BhC,GAAsBgC,EAAI,qBAAuB,GACjD/B,GAAsB+B,EAAI,qBAAuB,GACjDlC,GAAakC,EAAI,YAAc,GAC/B9B,GAAe8B,EAAI,eAAiB,GACpC7B,GAAuB6B,EAAI,sBAAwB,GACnD3B,GAAe2B,EAAI,eAAiB,GACpC1B,GAAW0B,EAAI,UAAY,GAC3BnD,GAAmBmD,EAAI,oBAAsBhG,GAC7CiF,GAAYe,EAAI,WAAahB,GAC7BK,GAAiCW,EAAI,gCAAkCX,GACvEC,GAA0BU,EAAI,yBAA2BV,GACzDpC,EAA0B8C,EAAI,yBAA2B,GACrDA,EAAI,yBAA2BH,GAAkBG,EAAI,wBAAwB,YAAY,IAC3F9C,EAAwB,aAAe8C,EAAI,wBAAwB,cAEjEA,EAAI,yBAA2BH,GAAkBG,EAAI,wBAAwB,kBAAkB,IACjG9C,EAAwB,mBAAqB8C,EAAI,wBAAwB,oBAEvEA,EAAI,yBAA2B,OAAOA,EAAI,wBAAwB,gCAAmC,YACvG9C,EAAwB,+BAAiC8C,EAAI,wBAAwB,gCAEnFtC,IACFH,EAAkB,IAEhBS,KACFD,GAAa,IAGXQ,KACFzB,GAAe1E,EAAS,GAAI/7B,EAAI,EAChC2gC,GAAe,GACXuB,GAAa,OAAS,KACxBnG,EAAS0E,GAAc5D,EAAM,EAC7Bd,EAAS4E,GAAcrY,EAAI,GAEzB4Z,GAAa,MAAQ,KACvBnG,EAAS0E,GAAc3D,EAAK,EAC5Bf,EAAS4E,GAAcxD,EAAG,EAC1BpB,EAAS4E,GAActD,EAAG,GAExB6E,GAAa,aAAe,KAC9BnG,EAAS0E,GAAc1D,EAAU,EACjChB,EAAS4E,GAAcxD,EAAG,EAC1BpB,EAAS4E,GAActD,EAAG,GAExB6E,GAAa,SAAW,KAC1BnG,EAAS0E,GAAcxD,EAAQ,EAC/BlB,EAAS4E,GAAcvD,EAAM,EAC7BrB,EAAS4E,GAActD,EAAG,IAI1BsG,EAAI,WACF,OAAOA,EAAI,UAAa,WAC1B3C,GAAuB,SAAW2C,EAAI,UAElClD,KAAiBC,KACnBD,GAAenE,GAAMmE,EAAY,GAEnC1E,EAAS0E,GAAckD,EAAI,SAAU1H,EAAiB,IAGtD0H,EAAI,WACF,OAAOA,EAAI,UAAa,WAC1B3C,GAAuB,eAAiB2C,EAAI,UAExChD,KAAiBC,KACnBD,GAAerE,GAAMqE,EAAY,GAEnC5E,EAAS4E,GAAcgD,EAAI,SAAU1H,EAAiB,IAGtD0H,EAAI,mBACN5H,EAASwG,GAAqBoB,EAAI,kBAAmB1H,EAAiB,EAEpE0H,EAAI,kBACFxB,KAAoBC,KACtBD,GAAkB7F,GAAM6F,EAAe,GAEzCpG,EAASoG,GAAiBwB,EAAI,gBAAiB1H,EAAiB,GAE9D0H,EAAI,sBACFxB,KAAoBC,KACtBD,GAAkB7F,GAAM6F,EAAe,GAEzCpG,EAASoG,GAAiBwB,EAAI,oBAAqB1H,EAAiB,GAGlE+F,KACFvB,GAAa,OAAO,EAAI,IAGtBc,GACFxF,EAAS0E,GAAc,CAAC,OAAQ,OAAQ,MAAM,CAAC,EAG7CA,GAAa,QACf1E,EAAS0E,GAAc,CAAC,OAAO,CAAC,EAChC,OAAOK,GAAY,OAEjB6C,EAAI,qBAAsB,CAC5B,GAAI,OAAOA,EAAI,qBAAqB,YAAe,WACjD,MAAMlI,GAAgB,6EAA6E,EAErG,GAAI,OAAOkI,EAAI,qBAAqB,iBAAoB,WACtD,MAAMlI,GAAgB,kFAAkF,EAG1GuE,EAAqB2D,EAAI,qBAEzB1D,EAAYD,EAAmB,WAAW,EAAE,CAC9C,MAEMA,IAAuB,SACzBA,EAAqB7B,GAA0BC,EAAcY,CAAa,GAGxEgB,IAAuB,MAAQ,OAAOC,GAAc,WACtDA,EAAYD,EAAmB,WAAW,EAAE,GAK5CjG,IACFA,GAAO4J,CAAG,EAEZL,GAASK,EACX,EAIMC,GAAe7H,EAAS,GAAI,CAAC,GAAGe,GAAO,GAAGC,GAAY,GAAGC,EAAa,CAAC,EACvE6G,GAAkB9H,EAAS,GAAI,CAAC,GAAGkB,GAAU,GAAGC,EAAgB,CAAC,EAOjE4G,GAAuB,SAA8B5H,EAAS,CAClE,IAAI6H,EAASjE,EAAc5D,CAAO,GAG9B,CAAC6H,GAAU,CAACA,EAAO,WACrBA,EAAS,CACP,aAAcnB,GACd,QAAS,UACjB,GAEI,MAAMoB,EAAU/I,GAAkBiB,EAAQ,OAAO,EAC3C+H,EAAgBhJ,GAAkB8I,EAAO,OAAO,EACtD,OAAKjB,GAAmB5G,EAAQ,YAAY,EAGxCA,EAAQ,eAAiBwG,GAIvBqB,EAAO,eAAiBpB,GACnBqB,IAAY,MAKjBD,EAAO,eAAiBtB,GACnBuB,IAAY,QAAUC,IAAkB,kBAAoBjB,GAA+BiB,CAAa,GAI1G,EAAQL,GAAaI,CAAO,EAEjC9H,EAAQ,eAAiBuG,GAIvBsB,EAAO,eAAiBpB,GACnBqB,IAAY,OAIjBD,EAAO,eAAiBrB,GACnBsB,IAAY,QAAUf,GAAwBgB,CAAa,EAI7D,EAAQJ,GAAgBG,CAAO,EAEpC9H,EAAQ,eAAiByG,GAIvBoB,EAAO,eAAiBrB,IAAiB,CAACO,GAAwBgB,CAAa,GAG/EF,EAAO,eAAiBtB,IAAoB,CAACO,GAA+BiB,CAAa,EACpF,GAIF,CAACJ,GAAgBG,CAAO,IAAMd,GAA6Bc,CAAO,GAAK,CAACJ,GAAaI,CAAO,GAGjG,GAAAb,KAAsB,yBAA2BL,GAAmB5G,EAAQ,YAAY,GAlDnF,EA0DX,EAMMgI,GAAe,SAAsBC,EAAM,CAC/CpJ,GAAU8D,EAAU,QAAS,CAC3B,QAASsF,CACf,CAAK,EACD,GAAI,CAEFrE,EAAcqE,CAAI,EAAE,YAAYA,CAAI,CACtC,MAAY,CACVxE,EAAOwE,CAAI,CACb,CACF,EAOMC,GAAmB,SAA0B9nC,EAAM4/B,EAAS,CAChE,GAAI,CACFnB,GAAU8D,EAAU,QAAS,CAC3B,UAAW3C,EAAQ,iBAAiB5/B,CAAI,EACxC,KAAM4/B,CACd,CAAO,CACH,MAAY,CACVnB,GAAU8D,EAAU,QAAS,CAC3B,UAAW,KACX,KAAM3C,CACd,CAAO,CACH,CAGA,GAFAA,EAAQ,gBAAgB5/B,CAAI,EAExBA,IAAS,KACX,GAAIolC,IAAcC,GAChB,GAAI,CACFuC,GAAahI,CAAO,CACtB,MAAY,CAAC,KAEb,IAAI,CACFA,EAAQ,aAAa5/B,EAAM,EAAE,CAC/B,MAAY,CAAC,CAGnB,EAOM+nC,GAAgB,SAAuBC,EAAO,CAElD,IAAIC,EAAM,KACNC,EAAoB,KACxB,GAAI/C,GACF6C,EAAQ,oBAAsBA,MACzB,CAEL,MAAMG,GAAUtJ,GAAYmJ,EAAO,aAAa,EAChDE,EAAoBC,IAAWA,GAAQ,CAAC,CAC1C,CACItB,KAAsB,yBAA2BP,KAAcD,KAEjE2B,EAAQ,iEAAmEA,EAAQ,kBAErF,MAAMI,EAAe1E,EAAqBA,EAAmB,WAAWsE,CAAK,EAAIA,EAKjF,GAAI1B,KAAcD,GAChB,GAAI,CACF4B,EAAM,IAAI/E,EAAS,EAAG,gBAAgBkF,EAAcvB,EAAiB,CACvE,MAAY,CAAC,CAGf,GAAI,CAACoB,GAAO,CAACA,EAAI,gBAAiB,CAChCA,EAAMrE,EAAe,eAAe0C,GAAW,WAAY,IAAI,EAC/D,GAAI,CACF2B,EAAI,gBAAgB,UAAY1B,GAAiB5C,EAAYyE,CAC/D,MAAY,CAEZ,CACF,CACA,MAAMC,GAAOJ,EAAI,MAAQA,EAAI,gBAK7B,OAJID,GAASE,GACXG,GAAK,aAAa7F,EAAS,eAAe0F,CAAiB,EAAGG,GAAK,WAAW,CAAC,GAAK,IAAI,EAGtF/B,KAAcD,GACTtC,EAAqB,KAAKkE,EAAKhD,EAAiB,OAAS,MAAM,EAAE,CAAC,EAEpEA,EAAiBgD,EAAI,gBAAkBI,EAChD,EAOMC,GAAsB,SAA6BtnC,EAAM,CAC7D,OAAO6iC,EAAmB,KAAK7iC,EAAK,eAAiBA,EAAMA,EAE3D+hC,EAAW,aAAeA,EAAW,aAAeA,EAAW,UAAYA,EAAW,4BAA8BA,EAAW,mBAAoB,IAAI,CACzJ,EAOMwF,GAAe,SAAsB3I,EAAS,CAClD,OAAOA,aAAmBqD,IAAoB,OAAOrD,EAAQ,UAAa,UAAY,OAAOA,EAAQ,aAAgB,UAAY,OAAOA,EAAQ,aAAgB,YAAc,EAAEA,EAAQ,sBAAsBoD,IAAiB,OAAOpD,EAAQ,iBAAoB,YAAc,OAAOA,EAAQ,cAAiB,YAAc,OAAOA,EAAQ,cAAiB,UAAY,OAAOA,EAAQ,cAAiB,YAAc,OAAOA,EAAQ,eAAkB,WAC3b,EAOM4I,GAAU,SAAiB7oC,EAAO,CACtC,OAAO,OAAOkjC,GAAS,YAAcljC,aAAiBkjC,CACxD,EACA,SAAS4F,GAAcxE,EAAOyE,EAAa37B,EAAM,CAC/CsxB,GAAa4F,EAAO0E,GAAQ,CAC1BA,EAAK,KAAKpG,EAAWmG,EAAa37B,EAAMi6B,EAAM,CAChD,CAAC,CACH,CAUA,MAAM4B,GAAoB,SAA2BF,EAAa,CAChE,IAAI5hC,EAAU,KAId,GAFA2hC,GAAcxE,EAAM,uBAAwByE,EAAa,IAAI,EAEzDH,GAAaG,CAAW,EAC1B,OAAAd,GAAac,CAAW,EACjB,GAGT,MAAMhB,EAAU/H,GAAkB+I,EAAY,QAAQ,EAiBtD,GAfAD,GAAcxE,EAAM,oBAAqByE,EAAa,CACpD,QAAAhB,EACA,YAAavD,EACnB,CAAK,EAEGa,IAAgB0D,EAAY,cAAa,GAAM,CAACF,GAAQE,EAAY,iBAAiB,GAAKxJ,GAAW,WAAYwJ,EAAY,SAAS,GAAKxJ,GAAW,WAAYwJ,EAAY,WAAW,GAKzLA,EAAY,WAAa/G,GAAU,wBAKnCqD,IAAgB0D,EAAY,WAAa/G,GAAU,SAAWzC,GAAW,UAAWwJ,EAAY,IAAI,EACtG,OAAAd,GAAac,CAAW,EACjB,GAGT,GAAI,EAAEhE,GAAuB,oBAAoB,UAAYA,GAAuB,SAASgD,CAAO,KAAO,CAACvD,GAAauD,CAAO,GAAKlD,GAAYkD,CAAO,GAAI,CAE1J,GAAI,CAAClD,GAAYkD,CAAO,GAAKmB,GAAsBnB,CAAO,IACpDnD,EAAwB,wBAAwB,QAAUrF,GAAWqF,EAAwB,aAAcmD,CAAO,GAGlHnD,EAAwB,wBAAwB,UAAYA,EAAwB,aAAamD,CAAO,GAC1G,MAAO,GAIX,GAAIhC,IAAgB,CAACG,GAAgB6B,CAAO,EAAG,CAC7C,MAAMoB,EAAatF,EAAckF,CAAW,GAAKA,EAAY,WACvDK,GAAaxF,EAAcmF,CAAW,GAAKA,EAAY,WAC7D,GAAIK,IAAcD,EAAY,CAC5B,MAAME,GAAaD,GAAW,OAC9B,QAASjsC,GAAIksC,GAAa,EAAGlsC,IAAK,EAAG,EAAEA,GAAG,CACxC,MAAMmsC,GAAa7F,EAAU2F,GAAWjsC,EAAC,EAAG,EAAI,EAChDmsC,GAAW,gBAAkBP,EAAY,gBAAkB,GAAK,EAChEI,EAAW,aAAaG,GAAY3F,EAAeoF,CAAW,CAAC,CACjE,CACF,CACF,CACA,OAAAd,GAAac,CAAW,EACjB,EACT,CAOA,OALIA,aAAuB5F,GAAW,CAAC0E,GAAqBkB,CAAW,IAKlEhB,IAAY,YAAcA,IAAY,WAAaA,IAAY,aAAexI,GAAW,8BAA+BwJ,EAAY,SAAS,GAChJd,GAAac,CAAW,EACjB,KAGL3D,GAAsB2D,EAAY,WAAa/G,GAAU,OAE3D76B,EAAU4hC,EAAY,YACtBrK,GAAa,CAAC2C,GAAeC,GAAUC,EAAW,EAAGzwB,GAAQ,CAC3D3J,EAAUg4B,GAAch4B,EAAS2J,EAAM,GAAG,CAC5C,CAAC,EACGi4B,EAAY,cAAgB5hC,IAC9B23B,GAAU8D,EAAU,QAAS,CAC3B,QAASmG,EAAY,UAAS,CACxC,CAAS,EACDA,EAAY,YAAc5hC,IAI9B2hC,GAAcxE,EAAM,sBAAuByE,EAAa,IAAI,EACrD,GACT,EAUMQ,GAAoB,SAA2BC,EAAOC,EAAQzpC,EAAO,CAEzE,GAAI4lC,KAAiB6D,IAAW,MAAQA,IAAW,UAAYzpC,KAAS6iC,GAAY7iC,KAASsnC,IAC3F,MAAO,GAMT,GAAI,EAAArC,GAAmB,CAACH,GAAY2E,CAAM,GAAKlK,GAAWiC,GAAWiI,CAAM,IAAU,GAAI,EAAAzE,IAAmBzF,GAAWkC,GAAWgI,CAAM,IAAU,GAAI,EAAA1E,GAAuB,0BAA0B,UAAYA,GAAuB,eAAe0E,EAAQD,CAAK,IAAU,GAAI,CAAC9E,GAAa+E,CAAM,GAAK3E,GAAY2E,CAAM,GAC7T,GAIA,EAAAP,GAAsBM,CAAK,IAAM5E,EAAwB,wBAAwB,QAAUrF,GAAWqF,EAAwB,aAAc4E,CAAK,GAAK5E,EAAwB,wBAAwB,UAAYA,EAAwB,aAAa4E,CAAK,KAAO5E,EAAwB,8BAA8B,QAAUrF,GAAWqF,EAAwB,mBAAoB6E,CAAM,GAAK7E,EAAwB,8BAA8B,UAAYA,EAAwB,mBAAmB6E,EAAQD,CAAK,IAG/fC,IAAW,MAAQ7E,EAAwB,iCAAmCA,EAAwB,wBAAwB,QAAUrF,GAAWqF,EAAwB,aAAc5kC,CAAK,GAAK4kC,EAAwB,wBAAwB,UAAYA,EAAwB,aAAa5kC,CAAK,IACvS,MAAO,WAGA,CAAAsmC,GAAoBmD,CAAM,GAAU,GAAI,CAAAlK,GAAWgF,GAAkBpF,GAAcn/B,EAAO4hC,GAAiB,EAAE,CAAC,GAAU,GAAK,GAAA6H,IAAW,OAASA,IAAW,cAAgBA,IAAW,SAAWD,IAAU,UAAYpK,GAAcp/B,EAAO,OAAO,IAAM,GAAKomC,GAAcoD,CAAK,IAAU,GAAI,EAAAtE,GAA2B,CAAC3F,GAAWoC,GAAmBxC,GAAcn/B,EAAO4hC,GAAiB,EAAE,CAAC,IAAU,GAAI5hC,EAC1Z,MAAO,SAET,MAAO,EACT,EASMkpC,GAAwB,SAA+BnB,EAAS,CACpE,OAAOA,IAAY,kBAAoB7I,GAAY6I,EAASjG,EAAc,CAC5E,EAWM4H,GAAsB,SAA6BX,EAAa,CAEpED,GAAcxE,EAAM,yBAA0ByE,EAAa,IAAI,EAC/D,KAAM,CACJ,WAAAY,CACN,EAAQZ,EAEJ,GAAI,CAACY,GAAcf,GAAaG,CAAW,EACzC,OAEF,MAAMa,EAAY,CAChB,SAAU,GACV,UAAW,GACX,SAAU,GACV,kBAAmBlF,GACnB,cAAe,MACrB,EACI,IAAIlnC,EAAImsC,EAAW,OAEnB,KAAOnsC,KAAK,CACV,MAAMqsC,GAAOF,EAAWnsC,CAAC,EACnB,CACJ,KAAA6C,GACA,aAAAypC,GACA,MAAOC,EACf,EAAUF,GACEJ,GAASzJ,GAAkB3/B,EAAI,EAC/B2pC,GAAYD,GAClB,IAAI/pC,GAAQK,KAAS,QAAU2pC,GAAY3K,GAAW2K,EAAS,EAkB/D,GAhBAJ,EAAU,SAAWH,GACrBG,EAAU,UAAY5pC,GACtB4pC,EAAU,SAAW,GACrBA,EAAU,cAAgB,OAC1Bd,GAAcxE,EAAM,sBAAuByE,EAAaa,CAAS,EACjE5pC,GAAQ4pC,EAAU,UAId/D,KAAyB4D,KAAW,MAAQA,KAAW,UAEzDtB,GAAiB9nC,GAAM0oC,CAAW,EAElC/oC,GAAQ8lC,GAA8B9lC,IAGpCqlC,IAAgB9F,GAAW,yCAA0Cv/B,EAAK,EAAG,CAC/EmoC,GAAiB9nC,GAAM0oC,CAAW,EAClC,QACF,CAEA,GAAIU,KAAW,iBAAmBvK,GAAYl/B,GAAO,MAAM,EAAG,CAC5DmoC,GAAiB9nC,GAAM0oC,CAAW,EAClC,QACF,CAEA,GAAIa,EAAU,cACZ,SAGF,GAAI,CAACA,EAAU,SAAU,CACvBzB,GAAiB9nC,GAAM0oC,CAAW,EAClC,QACF,CAEA,GAAI,CAAC5D,GAA4B5F,GAAW,OAAQv/B,EAAK,EAAG,CAC1DmoC,GAAiB9nC,GAAM0oC,CAAW,EAClC,QACF,CAEI3D,GACF1G,GAAa,CAAC2C,GAAeC,GAAUC,EAAW,EAAGzwB,IAAQ,CAC3D9Q,GAAQm/B,GAAcn/B,GAAO8Q,GAAM,GAAG,CACxC,CAAC,EAGH,MAAM04B,GAAQxJ,GAAkB+I,EAAY,QAAQ,EACpD,GAAI,CAACQ,GAAkBC,GAAOC,GAAQzpC,EAAK,EAAG,CAC5CmoC,GAAiB9nC,GAAM0oC,CAAW,EAClC,QACF,CAEA,GAAIhF,GAAsB,OAAO5B,GAAiB,UAAY,OAAOA,EAAa,kBAAqB,YACjG,CAAA2H,GACF,OAAQ3H,EAAa,iBAAiBqH,GAAOC,EAAM,EAAC,CAClD,IAAK,cACH,CACEzpC,GAAQ+jC,EAAmB,WAAW/jC,EAAK,EAC3C,KACF,CACF,IAAK,mBACH,CACEA,GAAQ+jC,EAAmB,gBAAgB/jC,EAAK,EAChD,KACF,CACd,CAIM,GAAIA,KAAUgqC,GACZ,GAAI,CACEF,GACFf,EAAY,eAAee,GAAczpC,GAAML,EAAK,EAGpD+oC,EAAY,aAAa1oC,GAAML,EAAK,EAElC4oC,GAAaG,CAAW,EAC1Bd,GAAac,CAAW,EAExBlK,GAAS+D,EAAU,OAAO,CAE9B,MAAY,CACVuF,GAAiB9nC,GAAM0oC,CAAW,CACpC,CAEJ,CAEAD,GAAcxE,EAAM,wBAAyByE,EAAa,IAAI,CAChE,EAMMkB,GAAqB,SAASA,EAAmBC,EAAU,CAC/D,IAAIC,EAAa,KACjB,MAAMC,EAAiBzB,GAAoBuB,CAAQ,EAGnD,IADApB,GAAcxE,EAAM,wBAAyB4F,EAAU,IAAI,EACpDC,EAAaC,EAAe,YAEjCtB,GAAcxE,EAAM,uBAAwB6F,EAAY,IAAI,EAE5DlB,GAAkBkB,CAAU,EAE5BT,GAAoBS,CAAU,EAE1BA,EAAW,mBAAmBnH,GAChCiH,EAAmBE,EAAW,OAAO,EAIzCrB,GAAcxE,EAAM,uBAAwB4F,EAAU,IAAI,CAC5D,EAEA,OAAAtH,EAAU,SAAW,SAAUyF,EAAO,CACpC,IAAIX,EAAM,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,GAC1EgB,EAAO,KACP2B,EAAe,KACftB,EAAc,KACduB,GAAa,KASjB,GALA1D,GAAiB,CAACyB,EACdzB,KACFyB,EAAQ,SAGN,OAAOA,GAAU,UAAY,CAACQ,GAAQR,CAAK,EAC7C,GAAI,OAAOA,EAAM,UAAa,YAE5B,GADAA,EAAQA,EAAM,SAAQ,EAClB,OAAOA,GAAU,SACnB,MAAM7I,GAAgB,iCAAiC,MAGzD,OAAMA,GAAgB,4BAA4B,EAItD,GAAI,CAACoD,EAAU,YACb,OAAOyF,EAYT,GATK9C,IACHkC,GAAaC,CAAG,EAGlB9E,EAAU,QAAU,GAEhB,OAAOyF,GAAU,WACnBrC,GAAW,IAETA,IAEF,GAAIqC,EAAM,SAAU,CAClB,MAAMN,GAAU/H,GAAkBqI,EAAM,QAAQ,EAChD,GAAI,CAAC7D,GAAauD,EAAO,GAAKlD,GAAYkD,EAAO,EAC/C,MAAMvI,GAAgB,yDAAyD,CAEnF,UACS6I,aAAiBnF,EAG1BwF,EAAON,GAAc,SAAS,EAC9BiC,EAAe3B,EAAK,cAAc,WAAWL,EAAO,EAAI,EACpDgC,EAAa,WAAarI,GAAU,SAAWqI,EAAa,WAAa,QAGlEA,EAAa,WAAa,OADnC3B,EAAO2B,EAKP3B,EAAK,YAAY2B,CAAY,MAE1B,CAEL,GAAI,CAAC5E,IAAc,CAACL,GAAsB,CAACE,GAE3C+C,EAAM,QAAQ,GAAG,IAAM,GACrB,OAAOtE,GAAsB4B,GAAsB5B,EAAmB,WAAWsE,CAAK,EAAIA,EAK5F,GAFAK,EAAON,GAAcC,CAAK,EAEtB,CAACK,EACH,OAAOjD,GAAa,KAAOE,GAAsB3B,EAAY,EAEjE,CAEI0E,GAAQlD,IACVyC,GAAaS,EAAK,UAAU,EAG9B,MAAM6B,GAAe5B,GAAoB3C,GAAWqC,EAAQK,CAAI,EAEhE,KAAOK,EAAcwB,GAAa,YAEhCtB,GAAkBF,CAAW,EAE7BW,GAAoBX,CAAW,EAE3BA,EAAY,mBAAmB/F,GACjCiH,GAAmBlB,EAAY,OAAO,EAI1C,GAAI/C,GACF,OAAOqC,EAGT,GAAI5C,GAAY,CACd,GAAIC,GAEF,IADA4E,GAAanG,EAAuB,KAAKuE,EAAK,aAAa,EACpDA,EAAK,YAEV4B,GAAW,YAAY5B,EAAK,UAAU,OAGxC4B,GAAa5B,EAEf,OAAIhE,GAAa,YAAcA,GAAa,kBAQ1C4F,GAAajG,EAAW,KAAKvB,EAAkBwH,GAAY,EAAI,GAE1DA,EACT,CACA,IAAIE,GAAiBlF,EAAiBoD,EAAK,UAAYA,EAAK,UAE5D,OAAIpD,GAAkBd,GAAa,UAAU,GAAKkE,EAAK,eAAiBA,EAAK,cAAc,SAAWA,EAAK,cAAc,QAAQ,MAAQnJ,GAAWsC,GAAc6G,EAAK,cAAc,QAAQ,IAAI,IAC/L8B,GAAiB,aAAe9B,EAAK,cAAc,QAAQ,KAAO;AAAA,EAAQ8B,IAGxEpF,GACF1G,GAAa,CAAC2C,GAAeC,GAAUC,EAAW,EAAGzwB,IAAQ,CAC3D05B,GAAiBrL,GAAcqL,GAAgB15B,GAAM,GAAG,CAC1D,CAAC,EAEIizB,GAAsB4B,GAAsB5B,EAAmB,WAAWyG,EAAc,EAAIA,EACrG,EACA5H,EAAU,UAAY,UAAY,CAChC,IAAI8E,EAAM,UAAU,OAAS,GAAK,UAAU,CAAC,IAAM,OAAY,UAAU,CAAC,EAAI,GAC9ED,GAAaC,CAAG,EAChBnC,GAAa,EACf,EACA3C,EAAU,YAAc,UAAY,CAClCyE,GAAS,KACT9B,GAAa,EACf,EACA3C,EAAU,iBAAmB,SAAU6H,EAAKZ,EAAM7pC,EAAO,CAElDqnC,IACHI,GAAa,EAAE,EAEjB,MAAM+B,EAAQxJ,GAAkByK,CAAG,EAC7BhB,EAASzJ,GAAkB6J,CAAI,EACrC,OAAON,GAAkBC,EAAOC,EAAQzpC,CAAK,CAC/C,EACA4iC,EAAU,QAAU,SAAU8H,EAAYC,EAAc,CAClD,OAAOA,GAAiB,YAG5B7L,GAAUwF,EAAMoG,CAAU,EAAGC,CAAY,CAC3C,EACA/H,EAAU,WAAa,SAAU8H,EAAYC,EAAc,CACzD,GAAIA,IAAiB,OAAW,CAC9B,MAAMvK,EAAQxB,GAAiB0F,EAAMoG,CAAU,EAAGC,CAAY,EAC9D,OAAOvK,IAAU,GAAK,OAAYrB,GAAYuF,EAAMoG,CAAU,EAAGtK,EAAO,CAAC,EAAE,CAAC,CAC9E,CACA,OAAOvB,GAASyF,EAAMoG,CAAU,CAAC,CACnC,EACA9H,EAAU,YAAc,SAAU8H,EAAY,CAC5CpG,EAAMoG,CAAU,EAAI,EACtB,EACA9H,EAAU,eAAiB,UAAY,CACrC0B,EAAQ7B,GAAe,CACzB,EACOG,CACT,CACA,IAAIgI,GAASlI,GAAe,EC11C5B,SAAS1jC,IAAG,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,GAAG,WAAW,KAAK,IAAI,GAAG,MAAM,KAAK,SAAS,GAAG,SAAS,KAAK,OAAO,GAAG,UAAU,KAAK,WAAW,IAAI,CAAC,CAAC,IAAIuZ,GAAEvZ,GAAC,EAAG,SAASM,GAAE3B,EAAE,CAAC4a,GAAE5a,CAAC,CAAC,IAAIe,GAAE,CAAC,KAAK,IAAI,IAAI,EAAE,SAASW,EAAE1B,EAAEd,EAAE,GAAG,CAAC,IAAID,EAAE,OAAOe,GAAG,SAASA,EAAEA,EAAE,OAAOT,EAAE,CAAC,QAAQ,CAACD,EAAEE,IAAI,CAAC,IAAIL,EAAE,OAAOK,GAAG,SAASA,EAAEA,EAAE,OAAO,OAAOL,EAAEA,EAAE,QAAQsB,GAAE,MAAM,IAAI,EAAExB,EAAEA,EAAE,QAAQK,EAAEH,CAAC,EAAEI,CAAC,EAAE,SAAS,IAAI,IAAI,OAAON,EAAEC,CAAC,CAAC,EAAE,OAAOK,CAAC,CAAC,IAAI2tC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,GAAC,EAAIzsC,GAAE,CAAC,iBAAiB,yBAAyB,kBAAkB,cAAc,uBAAuB,gBAAgB,eAAe,OAAO,WAAW,KAAK,kBAAkB,KAAK,gBAAgB,KAAK,aAAa,OAAO,kBAAkB,MAAM,cAAc,MAAM,oBAAoB,OAAO,UAAU,WAAW,gBAAgB,oBAAoB,gBAAgB,WAAW,wBAAwB,iCAAiC,yBAAyB,mBAAmB,gBAAgB,OAAO,mBAAmB,0BAA0B,WAAW,iBAAiB,gBAAgB,eAAe,iBAAiB,YAAY,QAAQ,SAAS,aAAa,WAAW,eAAe,OAAO,gBAAgB,aAAa,kBAAkB,YAAY,gBAAgB,YAAY,iBAAiB,aAAa,eAAe,YAAY,UAAU,QAAQ,QAAQ,UAAU,kBAAkB,iCAAiC,gBAAgB,mCAAmC,kBAAkB,KAAK,gBAAgB,KAAK,kBAAkB,gCAAgC,oBAAoB,gBAAgB,WAAW,UAAU,cAAc,WAAW,mBAAmB,oDAAoD,sBAAsB,qDAAqD,aAAa,6CAA6C,MAAM,eAAe,cAAc,OAAO,SAAS,MAAM,UAAU,MAAM,UAAU,QAAQ,eAAe,WAAW,UAAU,SAAS,cAAc,OAAO,cAAc,MAAM,cAAcT,GAAG,IAAI,OAAO,WAAWA,CAAC,8BAA8B,EAAE,gBAAgBA,GAAG,IAAI,OAAO,QAAQ,KAAK,IAAI,EAAEA,EAAE,CAAC,CAAC,oDAAoD,EAAE,QAAQA,GAAG,IAAI,OAAO,QAAQ,KAAK,IAAI,EAAEA,EAAE,CAAC,CAAC,oDAAoD,EAAE,iBAAiBA,GAAG,IAAI,OAAO,QAAQ,KAAK,IAAI,EAAEA,EAAE,CAAC,CAAC,iBAAiB,EAAE,kBAAkBA,GAAG,IAAI,OAAO,QAAQ,KAAK,IAAI,EAAEA,EAAE,CAAC,CAAC,IAAI,EAAE,eAAeA,GAAG,IAAI,OAAO,QAAQ,KAAK,IAAI,EAAEA,EAAE,CAAC,CAAC,qBAAqB,GAAG,CAAC,EAAEmtC,GAAG,uBAAuBC,GAAG,wDAAwDC,GAAG,8GAA8GjsC,GAAE,qEAAqEksC,GAAG,uCAAuCpsC,GAAE,wBAAwBqsC,GAAG,iKAAiKC,GAAG9rC,EAAE6rC,EAAE,EAAE,QAAQ,QAAQrsC,EAAC,EAAE,QAAQ,aAAa,mBAAmB,EAAE,QAAQ,UAAU,uBAAuB,EAAE,QAAQ,cAAc,SAAS,EAAE,QAAQ,WAAW,cAAc,EAAE,QAAQ,QAAQ,mBAAmB,EAAE,QAAQ,WAAW,EAAE,EAAE,SAAQ,EAAGusC,GAAG/rC,EAAE6rC,EAAE,EAAE,QAAQ,QAAQrsC,EAAC,EAAE,QAAQ,aAAa,mBAAmB,EAAE,QAAQ,UAAU,uBAAuB,EAAE,QAAQ,cAAc,SAAS,EAAE,QAAQ,WAAW,cAAc,EAAE,QAAQ,QAAQ,mBAAmB,EAAE,QAAQ,SAAS,mCAAmC,EAAE,SAAQ,EAAGwsC,GAAE,uFAAuFC,GAAG,UAAUjxB,GAAE,mCAAmCkxB,GAAGlsC,EAAE,6GAA6G,EAAE,QAAQ,QAAQgb,EAAC,EAAE,QAAQ,QAAQ,8DAA8D,EAAE,SAAQ,EAAGmxB,GAAGnsC,EAAE,sCAAsC,EAAE,QAAQ,QAAQR,EAAC,EAAE,SAAQ,EAAGX,GAAE,gWAAgWuB,GAAE,gCAAgCgsC,GAAGpsC,EAAE,4dAA4d,GAAG,EAAE,QAAQ,UAAUI,EAAC,EAAE,QAAQ,MAAMvB,EAAC,EAAE,QAAQ,YAAY,0EAA0E,EAAE,SAAQ,EAAGwtC,GAAGrsC,EAAEgsC,EAAC,EAAE,QAAQ,KAAKtsC,EAAC,EAAE,QAAQ,UAAU,uBAAuB,EAAE,QAAQ,YAAY,EAAE,EAAE,QAAQ,SAAS,EAAE,EAAE,QAAQ,aAAa,SAAS,EAAE,QAAQ,SAAS,gDAAgD,EAAE,QAAQ,OAAO,wBAAwB,EAAE,QAAQ,OAAO,6DAA6D,EAAE,QAAQ,MAAMb,EAAC,EAAE,SAAQ,EAAGytC,GAAGtsC,EAAE,yCAAyC,EAAE,QAAQ,YAAYqsC,EAAE,EAAE,SAAQ,EAAGE,GAAE,CAAC,WAAWD,GAAG,KAAKZ,GAAG,IAAIQ,GAAG,OAAOP,GAAG,QAAQC,GAAG,GAAGlsC,GAAE,KAAK0sC,GAAG,SAASN,GAAG,KAAKK,GAAG,QAAQV,GAAG,UAAUY,GAAG,MAAMhtC,GAAE,KAAK4sC,EAAE,EAAEO,GAAGxsC,EAAE,6JAA6J,EAAE,QAAQ,KAAKN,EAAC,EAAE,QAAQ,UAAU,uBAAuB,EAAE,QAAQ,aAAa,SAAS,EAAE,QAAQ,OAAO,wBAAwB,EAAE,QAAQ,SAAS,gDAAgD,EAAE,QAAQ,OAAO,wBAAwB,EAAE,QAAQ,OAAO,6DAA6D,EAAE,QAAQ,MAAMb,EAAC,EAAE,SAAQ,EAAG4tC,GAAG,CAAC,GAAGF,GAAE,SAASR,GAAG,MAAMS,GAAG,UAAUxsC,EAAEgsC,EAAC,EAAE,QAAQ,KAAKtsC,EAAC,EAAE,QAAQ,UAAU,uBAAuB,EAAE,QAAQ,YAAY,EAAE,EAAE,QAAQ,QAAQ8sC,EAAE,EAAE,QAAQ,aAAa,SAAS,EAAE,QAAQ,SAAS,gDAAgD,EAAE,QAAQ,OAAO,wBAAwB,EAAE,QAAQ,OAAO,6DAA6D,EAAE,QAAQ,MAAM3tC,EAAC,EAAE,SAAQ,CAAE,EAAE6tC,GAAG,CAAC,GAAGH,GAAE,KAAKvsC,EAAE,wIAAwI,EAAE,QAAQ,UAAUI,EAAC,EAAE,QAAQ,OAAO,mKAAmK,EAAE,SAAQ,EAAG,IAAI,oEAAoE,QAAQ,yBAAyB,OAAOf,GAAE,SAAS,mCAAmC,UAAUW,EAAEgsC,EAAC,EAAE,QAAQ,KAAKtsC,EAAC,EAAE,QAAQ,UAAU;AAAA,EACn3N,EAAE,QAAQ,WAAWosC,EAAE,EAAE,QAAQ,SAAS,EAAE,EAAE,QAAQ,aAAa,SAAS,EAAE,QAAQ,UAAU,EAAE,EAAE,QAAQ,QAAQ,EAAE,EAAE,QAAQ,QAAQ,EAAE,EAAE,QAAQ,OAAO,EAAE,EAAE,SAAQ,CAAE,EAAEa,GAAG,8CAA8CC,GAAG,sCAAsCC,GAAG,wBAAwBC,GAAG,8EAA8ExsC,GAAE,gBAAgBysC,GAAE,kBAAkBC,GAAG,mBAAmBC,GAAGjtC,EAAE,wBAAwB,GAAG,EAAE,QAAQ,cAAc+sC,EAAC,EAAE,SAAQ,EAAGG,GAAG,qBAAqBC,GAAG,uBAAuBC,GAAG,yBAAyBC,GAAGrtC,EAAE,yBAAyB,GAAG,EAAE,QAAQ,OAAO,mGAAmG,EAAE,QAAQ,WAAWwrC,GAAG,WAAW,WAAW,EAAE,QAAQ,OAAO,yBAAyB,EAAE,QAAQ,OAAO,gBAAgB,EAAE,WAAW8B,GAAG,gEAAgEC,GAAGvtC,EAAEstC,GAAG,GAAG,EAAE,QAAQ,SAAShtC,EAAC,EAAE,SAAQ,EAAGktC,GAAGxtC,EAAEstC,GAAG,GAAG,EAAE,QAAQ,SAASJ,EAAE,EAAE,SAAQ,EAAGO,GAAG,wQAAwQC,GAAG1tC,EAAEytC,GAAG,IAAI,EAAE,QAAQ,iBAAiBT,EAAE,EAAE,QAAQ,cAAcD,EAAC,EAAE,QAAQ,SAASzsC,EAAC,EAAE,SAAQ,EAAGqtC,GAAG3tC,EAAEytC,GAAG,IAAI,EAAE,QAAQ,iBAAiBL,EAAE,EAAE,QAAQ,cAAcD,EAAE,EAAE,QAAQ,SAASD,EAAE,EAAE,SAAQ,EAAGU,GAAG5tC,EAAE,mNAAmN,IAAI,EAAE,QAAQ,iBAAiBgtC,EAAE,EAAE,QAAQ,cAAcD,EAAC,EAAE,QAAQ,SAASzsC,EAAC,EAAE,SAAQ,EAAGutC,GAAG7tC,EAAE,YAAY,IAAI,EAAE,QAAQ,SAASM,EAAC,EAAE,SAAQ,EAAGwtC,GAAG9tC,EAAE,qCAAqC,EAAE,QAAQ,SAAS,8BAA8B,EAAE,QAAQ,QAAQ,8IAA8I,EAAE,SAAQ,EAAG+tC,GAAG/tC,EAAEI,EAAC,EAAE,QAAQ,YAAY,KAAK,EAAE,SAAQ,EAAG4tC,GAAGhuC,EAAE,0JAA0J,EAAE,QAAQ,UAAU+tC,EAAE,EAAE,QAAQ,YAAY,6EAA6E,EAAE,SAAQ,EAAGv1B,GAAE,wEAAwEy1B,GAAGjuC,EAAE,mEAAmE,EAAE,QAAQ,QAAQwY,EAAC,EAAE,QAAQ,OAAO,yCAAyC,EAAE,QAAQ,QAAQ,6DAA6D,EAAE,WAAW01B,GAAGluC,EAAE,yBAAyB,EAAE,QAAQ,QAAQwY,EAAC,EAAE,QAAQ,MAAMwC,EAAC,EAAE,SAAQ,EAAGmzB,GAAGnuC,EAAE,uBAAuB,EAAE,QAAQ,MAAMgb,EAAC,EAAE,WAAWozB,GAAGpuC,EAAE,wBAAwB,GAAG,EAAE,QAAQ,UAAUkuC,EAAE,EAAE,QAAQ,SAASC,EAAE,EAAE,SAAQ,EAAGE,GAAG,qCAAqC9vB,GAAE,CAAC,WAAWlf,GAAE,eAAewuC,GAAG,SAASC,GAAG,UAAUT,GAAG,GAAGR,GAAG,KAAKD,GAAG,IAAIvtC,GAAE,eAAekuC,GAAG,kBAAkBG,GAAG,kBAAkBE,GAAG,OAAOjB,GAAG,KAAKsB,GAAG,OAAOE,GAAG,YAAYlB,GAAG,QAAQiB,GAAG,cAAcE,GAAG,IAAIJ,GAAG,KAAKlB,GAAG,IAAIztC,EAAC,EAAEivC,GAAG,CAAC,GAAG/vB,GAAE,KAAKve,EAAE,yBAAyB,EAAE,QAAQ,QAAQwY,EAAC,EAAE,SAAQ,EAAG,QAAQxY,EAAE,+BAA+B,EAAE,QAAQ,QAAQwY,EAAC,EAAE,SAAQ,CAAE,EAAEuC,GAAE,CAAC,GAAGwD,GAAE,kBAAkBovB,GAAG,eAAeH,GAAG,IAAIxtC,EAAE,gEAAgE,EAAE,QAAQ,WAAWquC,EAAE,EAAE,QAAQ,QAAQ,2EAA2E,EAAE,SAAQ,EAAG,WAAW,6EAA6E,IAAI,0EAA0E,KAAKruC,EAAE,qNAAqN,EAAE,QAAQ,WAAWquC,EAAE,EAAE,SAAQ,CAAE,EAAEE,GAAG,CAAC,GAAGxzB,GAAE,GAAG/a,EAAE6sC,EAAE,EAAE,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK7sC,EAAE+a,GAAE,IAAI,EAAE,QAAQ,OAAO,eAAe,EAAE,QAAQ,UAAU,GAAG,EAAE,SAAQ,CAAE,EAAE5b,GAAE,CAAC,OAAOotC,GAAE,IAAIE,GAAG,SAASC,EAAE,EAAE5sC,GAAE,CAAC,OAAOye,GAAE,IAAIxD,GAAE,OAAOwzB,GAAG,SAASD,EAAE,EAAME,GAAG,CAAC,IAAI,QAAQ,IAAI,OAAO,IAAI,OAAO,IAAI,SAAS,IAAI,OAAO,EAAEC,GAAGnwC,GAAGkwC,GAAGlwC,CAAC,EAAE,SAASugB,GAAEvgB,EAAEd,EAAE,CAAC,GAAGA,GAAG,GAAGuB,GAAE,WAAW,KAAKT,CAAC,EAAE,OAAOA,EAAE,QAAQS,GAAE,cAAc0vC,EAAE,UAAU1vC,GAAE,mBAAmB,KAAKT,CAAC,EAAE,OAAOA,EAAE,QAAQS,GAAE,sBAAsB0vC,EAAE,EAAE,OAAOnwC,CAAC,CAAC,SAAS0a,GAAE1a,EAAE,CAAC,GAAG,CAACA,EAAE,UAAUA,CAAC,EAAE,QAAQS,GAAE,cAAc,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,OAAOT,CAAC,CAAC,SAASowC,GAAEpwC,EAAEd,EAAE,OAAC,IAAID,EAAEe,EAAE,QAAQS,GAAE,SAAS,CAACjB,EAAEL,EAAES,IAAI,CAAC,IAAIR,EAAE,GAAGS,EAAEV,EAAE,KAAK,EAAEU,GAAG,GAAGD,EAAEC,CAAC,IAAI,MAAMT,EAAE,CAACA,EAAE,OAAOA,EAAE,IAAI,IAAI,CAAC,EAAEG,EAAEN,EAAE,MAAMwB,GAAE,SAAS,EAAEnB,EAAE,EAAE,GAAGC,EAAE,CAAC,EAAE,KAAI,GAAIA,EAAE,MAAK,EAAGA,EAAE,OAAO,GAAG,GAACa,EAAAb,EAAE,GAAG,EAAE,IAAP,MAAAa,EAAU,SAAQb,EAAE,IAAG,EAAGL,EAAE,GAAGK,EAAE,OAAOL,EAAEK,EAAE,OAAOL,CAAC,MAAO,MAAKK,EAAE,OAAOL,GAAGK,EAAE,KAAK,EAAE,EAAE,KAAKD,EAAEC,EAAE,OAAOD,IAAIC,EAAED,CAAC,EAAEC,EAAED,CAAC,EAAE,OAAO,QAAQmB,GAAE,UAAU,GAAG,EAAE,OAAOlB,CAAC,CAAC,SAAS+B,GAAEtB,EAAEd,EAAED,EAAE,CAAC,IAAIM,EAAES,EAAE,OAAO,GAAGT,IAAI,EAAE,MAAM,GAAG,IAAID,EAAE,EAAE,KAAKA,EAAEC,GAAUS,EAAE,OAAOT,EAAED,EAAE,CAAC,IAASJ,GAAMI,IAAoC,OAAOU,EAAE,MAAM,EAAET,EAAED,CAAC,CAAC,CAAC,SAAS+wC,GAAGrwC,EAAEd,EAAE,CAAC,GAAGc,EAAE,QAAQd,EAAE,CAAC,CAAC,IAAI,GAAG,MAAM,GAAG,IAAID,EAAE,EAAE,QAAQM,EAAE,EAAEA,EAAES,EAAE,OAAOT,IAAI,GAAGS,EAAET,CAAC,IAAI,KAAKA,YAAYS,EAAET,CAAC,IAAIL,EAAE,CAAC,EAAED,YAAYe,EAAET,CAAC,IAAIL,EAAE,CAAC,IAAID,IAAIA,EAAE,GAAG,OAAOM,EAAE,OAAON,EAAE,EAAE,GAAG,EAAE,CAAC,SAASqxC,GAAGtwC,EAAEd,EAAED,EAAEM,EAAED,EAAE,CAAC,IAAIE,EAAEN,EAAE,KAAKC,EAAED,EAAE,OAAO,KAAKU,EAAEI,EAAE,CAAC,EAAE,QAAQV,EAAE,MAAM,kBAAkB,IAAI,EAAEC,EAAE,MAAM,OAAO,GAAG,IAAIH,EAAE,CAAC,KAAKY,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,IAAI,QAAQ,OAAO,IAAIf,EAAE,KAAKO,EAAE,MAAML,EAAE,KAAKS,EAAE,OAAOL,EAAE,aAAaK,CAAC,CAAC,EAAE,OAAOL,EAAE,MAAM,OAAO,GAAGH,CAAC,CAAC,SAASmxC,GAAGvwC,EAAEd,EAAED,EAAE,CAAC,IAAIM,EAAES,EAAE,MAAMf,EAAE,MAAM,sBAAsB,EAAE,GAAGM,IAAI,KAAK,OAAOL,EAAE,IAAII,EAAEC,EAAE,CAAC,EAAE,OAAOL,EAAE,MAAM;AAAA,CACtiL,EAAE,IAAIM,GAAG,CAAC,IAAIL,EAAEK,EAAE,MAAMP,EAAE,MAAM,cAAc,EAAE,GAAGE,IAAI,KAAK,OAAOK,EAAE,GAAG,CAACI,CAAC,EAAET,EAAE,OAAOS,EAAE,QAAQN,EAAE,OAAOE,EAAE,MAAMF,EAAE,MAAM,EAAEE,CAAC,CAAC,EAAE,KAAK;AAAA,CACnI,CAAC,CAAC,IAAIc,GAAE,KAAK,CAAqB,YAAY,EAAE,CAAlCua,EAAA,gBAAQA,EAAA,cAAMA,EAAA,cAAqB,KAAK,QAAQ,GAAGD,EAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,QAAQ,KAAK,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,KAAK,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,MAAM,iBAAiB,EAAE,EAAE,MAAM,CAAC,KAAK,OAAO,IAAI,EAAE,CAAC,EAAE,eAAe,WAAW,KAAK,KAAK,QAAQ,SAAS,EAAEtZ,GAAE,EAAE;AAAA,CACvW,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,OAAO,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAEhC,EAAEixC,GAAG,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,KAAK,EAAE,MAAM,CAAC,KAAK,OAAO,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,KAAI,EAAG,QAAQ,KAAK,MAAM,OAAO,eAAe,IAAI,EAAE,EAAE,CAAC,EAAE,KAAKjxC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,QAAQ,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAI,EAAG,GAAG,KAAK,MAAM,MAAM,WAAW,KAAK,CAAC,EAAE,CAAC,IAAIA,EAAEgC,GAAE,EAAE,GAAG,GAAG,KAAK,QAAQ,UAAU,CAAChC,GAAG,KAAK,MAAM,MAAM,gBAAgB,KAAKA,CAAC,KAAK,EAAEA,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,UAAU,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,KAAK,IAAIgC,GAAE,EAAE,CAAC,EAAE;AAAA,CACjkB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,WAAW,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAEA,GAAE,EAAE,CAAC,EAAE;AAAA,CAC9E,EAAE,MAAM;AAAA,CACR,EAAEhC,EAAE,GAAGE,EAAE,GAAGL,EAAE,GAAG,KAAK,EAAE,OAAO,GAAG,CAAC,IAAI,EAAE,GAAGC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,OAAO,IAAI,GAAG,KAAK,MAAM,MAAM,gBAAgB,KAAK,EAAE,CAAC,CAAC,EAAEA,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,WAAW,CAAC,EAAEA,EAAE,KAAK,EAAE,CAAC,CAAC,MAAO,OAAM,EAAE,EAAE,MAAM,CAAC,EAAE,IAAIU,EAAEV,EAAE,KAAK;AAAA,CACxM,EAAEM,EAAEI,EAAE,QAAQ,KAAK,MAAM,MAAM,wBAAwB;AAAA,OACjD,EAAE,QAAQ,KAAK,MAAM,MAAM,yBAAyB,EAAE,EAAER,EAAEA,EAAE,GAAGA,CAAC;AAAA,EACrEQ,CAAC,GAAGA,EAAEN,EAAEA,EAAE,GAAGA,CAAC;AAAA,EACdE,CAAC,GAAGA,EAAE,IAAIgB,EAAE,KAAK,MAAM,MAAM,IAAI,GAAG,KAAK,MAAM,MAAM,IAAI,GAAG,KAAK,MAAM,YAAYhB,EAAEP,EAAE,EAAE,EAAE,KAAK,MAAM,MAAM,IAAIuB,EAAE,EAAE,SAAS,EAAE,MAAM,IAAIf,EAAER,EAAE,GAAG,EAAE,EAAE,IAAGQ,GAAA,YAAAA,EAAG,QAAO,OAAO,MAAM,IAAGA,GAAA,YAAAA,EAAG,QAAO,aAAa,CAAC,IAAI8B,EAAE9B,EAAEM,EAAEwB,EAAE,IAAI;AAAA,EACzN,EAAE,KAAK;AAAA,CACR,EAAE+uC,EAAE,KAAK,WAAWvwC,CAAC,EAAEd,EAAEA,EAAE,OAAO,CAAC,EAAEqxC,EAAElxC,EAAEA,EAAE,UAAU,EAAEA,EAAE,OAAOmC,EAAE,IAAI,MAAM,EAAE+uC,EAAE,IAAIhxC,EAAEA,EAAE,UAAU,EAAEA,EAAE,OAAOiC,EAAE,KAAK,MAAM,EAAE+uC,EAAE,KAAK,KAAK,UAAS7wC,GAAA,YAAAA,EAAG,QAAO,OAAO,CAAC,IAAI8B,EAAE9B,EAAEM,EAAEwB,EAAE,IAAI;AAAA,EAClL,EAAE,KAAK;AAAA,CACR,EAAE+uC,EAAE,KAAK,KAAKvwC,CAAC,EAAEd,EAAEA,EAAE,OAAO,CAAC,EAAEqxC,EAAElxC,EAAEA,EAAE,UAAU,EAAEA,EAAE,OAAOK,EAAE,IAAI,MAAM,EAAE6wC,EAAE,IAAIhxC,EAAEA,EAAE,UAAU,EAAEA,EAAE,OAAOiC,EAAE,IAAI,MAAM,EAAE+uC,EAAE,IAAI,EAAEvwC,EAAE,UAAUd,EAAE,GAAG,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM;AAAA,CACpK,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,aAAa,IAAIG,EAAE,OAAOH,EAAE,KAAKK,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,SAAC,IAAI,EAAE,KAAK,MAAM,MAAM,KAAK,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAID,EAAE,EAAE,CAAC,EAAE,KAAI,EAAGD,EAAEC,EAAE,OAAO,EAAEC,EAAE,CAAC,KAAK,OAAO,IAAI,GAAG,QAAQF,EAAE,MAAMA,EAAE,CAACC,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,GAAG,MAAM,EAAE,EAAEA,EAAED,EAAE,aAAaC,EAAE,MAAM,EAAE,CAAC,GAAG,KAAKA,CAAC,GAAG,KAAK,QAAQ,WAAWA,EAAED,EAAEC,EAAE,SAAS,IAAIJ,EAAE,KAAK,MAAM,MAAM,cAAcI,CAAC,EAAEK,EAAE,GAAG,KAAK,GAAG,CAAC,IAAIC,EAAE,GAAGC,EAAE,GAAGJ,EAAE,GAAG,GAAG,EAAE,EAAEP,EAAE,KAAK,CAAC,IAAI,KAAK,MAAM,MAAM,GAAG,KAAK,CAAC,EAAE,MAAMW,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,UAAUA,EAAE,MAAM,EAAE,IAAIY,EAAE,EAAE,CAAC,EAAE,MAAM;AAAA,EACvd,CAAC,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,MAAM,gBAAgB8vC,GAAG,IAAI,OAAO,EAAEA,EAAE,MAAM,CAAC,EAAE7wC,EAAE,EAAE,MAAM;AAAA,EACpF,CAAC,EAAE,CAAC,EAAE8B,EAAE,CAACf,EAAE,KAAI,EAAGT,EAAE,EAAE,GAAG,KAAK,QAAQ,UAAUA,EAAE,EAAEP,EAAEgB,EAAE,UAAS,GAAIe,EAAExB,EAAE,EAAE,CAAC,EAAE,OAAO,GAAGA,EAAE,EAAE,CAAC,EAAE,OAAO,KAAK,MAAM,MAAM,YAAY,EAAEA,EAAEA,EAAE,EAAE,EAAEA,EAAEP,EAAEgB,EAAE,MAAMT,CAAC,EAAEA,GAAG,EAAE,CAAC,EAAE,QAAQwB,GAAG,KAAK,MAAM,MAAM,UAAU,KAAK9B,CAAC,IAAIG,GAAGH,EAAE;AAAA,EACzN,EAAE,EAAE,UAAUA,EAAE,OAAO,CAAC,EAAEE,EAAE,IAAI,CAACA,EAAE,CAAC,IAAI2wC,EAAE,KAAK,MAAM,MAAM,gBAAgBvwC,CAAC,EAAEgB,EAAE,KAAK,MAAM,MAAM,QAAQhB,CAAC,EAAE0a,EAAE,KAAK,MAAM,MAAM,iBAAiB1a,CAAC,EAAEwwC,EAAG,KAAK,MAAM,MAAM,kBAAkBxwC,CAAC,EAAEywC,EAAG,KAAK,MAAM,MAAM,eAAezwC,CAAC,EAAE,KAAK,GAAG,CAAC,IAAIsB,EAAE,EAAE,MAAM;AAAA,EACzP,CAAC,EAAE,CAAC,EAAET,EAAE,GAAGnB,EAAE4B,EAAE,KAAK,QAAQ,UAAU5B,EAAEA,EAAE,QAAQ,KAAK,MAAM,MAAM,mBAAmB,IAAI,EAAEmB,EAAEnB,GAAGmB,EAAEnB,EAAE,QAAQ,KAAK,MAAM,MAAM,cAAc,MAAM,EAAEgb,EAAE,KAAKhb,CAAC,GAAG8wC,EAAG,KAAK9wC,CAAC,GAAG+wC,EAAG,KAAK/wC,CAAC,GAAG6wC,EAAE,KAAK7wC,CAAC,GAAGsB,EAAE,KAAKtB,CAAC,EAAE,MAAM,GAAGmB,EAAE,OAAO,KAAK,MAAM,MAAM,YAAY,GAAGb,GAAG,CAACN,EAAE,KAAI,EAAGD,GAAG;AAAA,EAC9QoB,EAAE,MAAMb,CAAC,MAAM,CAAC,GAAGwB,GAAGf,EAAE,QAAQ,KAAK,MAAM,MAAM,cAAc,MAAM,EAAE,OAAO,KAAK,MAAM,MAAM,YAAY,GAAG,GAAGia,EAAE,KAAKja,CAAC,GAAG+vC,EAAG,KAAK/vC,CAAC,GAAGO,EAAE,KAAKP,CAAC,EAAE,MAAMhB,GAAG;AAAA,EAC3JC,CAAC,CAAC,CAAC8B,GAAG,CAAC9B,EAAE,SAAS8B,EAAE,IAAI3B,GAAGyB,EAAE;AAAA,EAC7B,EAAE,EAAE,UAAUA,EAAE,OAAO,CAAC,EAAEb,EAAEI,EAAE,MAAMb,CAAC,CAAC,CAAC,CAACT,EAAE,QAAQI,EAAEJ,EAAE,MAAM,GAAG,KAAK,MAAM,MAAM,gBAAgB,KAAKM,CAAC,IAAIF,EAAE,KAAKJ,EAAE,MAAM,KAAK,CAAC,KAAK,YAAY,IAAIM,EAAE,KAAK,CAAC,CAAC,KAAK,QAAQ,KAAK,KAAK,MAAM,MAAM,WAAW,KAAKJ,CAAC,EAAE,MAAM,GAAG,KAAKA,EAAE,OAAO,EAAE,CAAC,EAAEF,EAAE,KAAKM,CAAC,CAAC,IAAIV,EAAEI,EAAE,MAAM,GAAG,EAAE,EAAE,GAAGJ,EAAEA,EAAE,IAAIA,EAAE,IAAI,QAAO,EAAGA,EAAE,KAAKA,EAAE,KAAK,QAAO,MAAQ,QAAOI,EAAE,IAAIA,EAAE,IAAI,QAAO,EAAG,QAAQK,KAAKL,EAAE,MAAM,CAAC,GAAG,KAAK,MAAM,MAAM,IAAI,GAAGK,EAAE,OAAO,KAAK,MAAM,YAAYA,EAAE,KAAK,EAAE,EAAEA,EAAE,KAAK,CAAC,GAAGA,EAAE,KAAKA,EAAE,KAAK,QAAQ,KAAK,MAAM,MAAM,gBAAgB,EAAE,IAAEO,EAAAP,EAAE,OAAO,CAAC,IAAV,YAAAO,EAAa,QAAO,UAAQC,EAAAR,EAAE,OAAO,CAAC,IAAV,YAAAQ,EAAa,QAAO,YAAY,CAACR,EAAE,OAAO,CAAC,EAAE,IAAIA,EAAE,OAAO,CAAC,EAAE,IAAI,QAAQ,KAAK,MAAM,MAAM,gBAAgB,EAAE,EAAEA,EAAE,OAAO,CAAC,EAAE,KAAKA,EAAE,OAAO,CAAC,EAAE,KAAK,QAAQ,KAAK,MAAM,MAAM,gBAAgB,EAAE,EAAE,QAAQH,EAAE,KAAK,MAAM,YAAY,OAAO,EAAEA,GAAG,EAAEA,IAAI,GAAG,KAAK,MAAM,MAAM,WAAW,KAAK,KAAK,MAAM,YAAYA,CAAC,EAAE,GAAG,EAAE,CAAC,KAAK,MAAM,YAAYA,CAAC,EAAE,IAAI,KAAK,MAAM,YAAYA,CAAC,EAAE,IAAI,QAAQ,KAAK,MAAM,MAAM,gBAAgB,EAAE,EAAE,KAAK,CAAC,CAAC,IAAII,EAAE,KAAK,MAAM,MAAM,iBAAiB,KAAKD,EAAE,GAAG,EAAE,GAAGC,EAAE,CAAC,IAAIJ,EAAE,CAAC,KAAK,WAAW,IAAII,EAAE,CAAC,EAAE,IAAI,QAAQA,EAAE,CAAC,IAAI,KAAK,EAAED,EAAE,QAAQH,EAAE,QAAQF,EAAE,MAAMK,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,EAAE,SAASA,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,WAAWA,EAAE,OAAO,CAAC,GAAGA,EAAE,OAAO,CAAC,EAAE,QAAQA,EAAE,OAAO,CAAC,EAAE,IAAIH,EAAE,IAAIG,EAAE,OAAO,CAAC,EAAE,IAAIA,EAAE,OAAO,CAAC,EAAE,KAAKH,EAAE,IAAIG,EAAE,OAAO,CAAC,EAAE,KAAKA,EAAE,OAAO,CAAC,EAAE,OAAO,QAAQH,CAAC,GAAGG,EAAE,OAAO,QAAQ,CAAC,KAAK,YAAY,IAAIH,EAAE,IAAI,KAAKA,EAAE,IAAI,OAAO,CAACA,CAAC,CAAC,CAAC,EAAEG,EAAE,OAAO,QAAQH,CAAC,CAAC,CAAC,CAAC,GAAG,CAACF,EAAE,MAAM,CAAC,IAAIM,EAAED,EAAE,OAAO,OAAOa,GAAGA,EAAE,OAAO,OAAO,EAAEhB,EAAEI,EAAE,OAAO,GAAGA,EAAE,KAAKY,GAAG,KAAK,MAAM,MAAM,QAAQ,KAAKA,EAAE,GAAG,CAAC,EAAElB,EAAE,MAAME,CAAC,CAAC,CAAC,GAAGF,EAAE,MAAM,QAAQK,KAAKL,EAAE,MAAM,CAACK,EAAE,MAAM,GAAG,QAAQC,KAAKD,EAAE,OAAOC,EAAE,OAAO,SAASA,EAAE,KAAK,YAAY,CAAC,OAAON,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,KAAK,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,OAAO,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,IAAI,UAAU,EAAE,CAAC,IAAI,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,YAAW,EAAG,QAAQ,KAAK,MAAM,MAAM,oBAAoB,GAAG,EAAEF,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,MAAM,aAAa,IAAI,EAAE,QAAQ,KAAK,MAAM,OAAO,eAAe,IAAI,EAAE,GAAGE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,KAAK,MAAM,OAAO,eAAe,IAAI,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,MAAM,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,KAAKF,EAAE,MAAME,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,OAAC,IAAI,EAAE,KAAK,MAAM,MAAM,MAAM,KAAK,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK,MAAM,MAAM,eAAe,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,IAAI,EAAE4wC,GAAE,EAAE,CAAC,CAAC,EAAE9wC,EAAE,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,MAAM,gBAAgB,EAAE,EAAE,MAAM,GAAG,EAAEE,GAAEY,EAAA,EAAE,CAAC,IAAH,MAAAA,EAAM,OAAO,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,MAAM,kBAAkB,EAAE,EAAE,MAAM;AAAA,CAC53E,EAAE,GAAGjB,EAAE,CAAC,KAAK,QAAQ,IAAI,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,SAASG,EAAE,OAAO,CAAC,QAAQM,KAAKN,EAAE,KAAK,MAAM,MAAM,gBAAgB,KAAKM,CAAC,EAAET,EAAE,MAAM,KAAK,OAAO,EAAE,KAAK,MAAM,MAAM,iBAAiB,KAAKS,CAAC,EAAET,EAAE,MAAM,KAAK,QAAQ,EAAE,KAAK,MAAM,MAAM,eAAe,KAAKS,CAAC,EAAET,EAAE,MAAM,KAAK,MAAM,EAAEA,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQS,EAAE,EAAEA,EAAE,EAAE,OAAOA,IAAIT,EAAE,OAAO,KAAK,CAAC,KAAK,EAAES,CAAC,EAAE,OAAO,KAAK,MAAM,OAAO,EAAEA,CAAC,CAAC,EAAE,OAAO,GAAG,MAAMT,EAAE,MAAMS,CAAC,CAAC,CAAC,EAAE,QAAQA,KAAKJ,EAAEL,EAAE,KAAK,KAAKixC,GAAExwC,EAAET,EAAE,OAAO,MAAM,EAAE,IAAI,CAACC,EAAES,KAAK,CAAC,KAAKT,EAAE,OAAO,KAAK,MAAM,OAAOA,CAAC,EAAE,OAAO,GAAG,MAAMD,EAAE,MAAMU,CAAC,CAAC,EAAE,CAAC,EAAE,OAAOV,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,SAAS,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,UAAU,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,UAAU,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI;AAAA,EACzyB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,YAAY,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,KAAK,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,OAAO,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,OAAO,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,SAAS,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,MAAM,MAAM,QAAQ,KAAK,MAAM,MAAM,UAAU,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,MAAM,MAAM,OAAO,GAAG,KAAK,MAAM,MAAM,QAAQ,KAAK,MAAM,MAAM,QAAQ,KAAK,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,MAAM,OAAO,IAAI,CAAC,KAAK,MAAM,MAAM,YAAY,KAAK,MAAM,MAAM,kBAAkB,KAAK,EAAE,CAAC,CAAC,EAAE,KAAK,MAAM,MAAM,WAAW,GAAG,KAAK,MAAM,MAAM,YAAY,KAAK,MAAM,MAAM,gBAAgB,KAAK,EAAE,CAAC,CAAC,IAAI,KAAK,MAAM,MAAM,WAAW,IAAI,CAAC,KAAK,OAAO,IAAI,EAAE,CAAC,EAAE,OAAO,KAAK,MAAM,MAAM,OAAO,WAAW,KAAK,MAAM,MAAM,WAAW,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAI,EAAG,GAAG,CAAC,KAAK,QAAQ,UAAU,KAAK,MAAM,MAAM,kBAAkB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,MAAM,MAAM,gBAAgB,KAAK,CAAC,EAAE,OAAO,IAAIA,EAAEmC,GAAE,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAOnC,EAAE,QAAQ,IAAI,EAAE,MAAM,KAAK,CAAC,IAAIA,EAAEkxC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,GAAGlxC,IAAI,GAAG,OAAO,GAAGA,EAAE,GAAG,CAAC,IAAIC,GAAG,EAAE,CAAC,EAAE,QAAQ,GAAG,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,OAAOD,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,UAAU,EAAEA,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,UAAU,EAAEC,CAAC,EAAE,KAAI,EAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAIE,EAAE,EAAE,CAAC,EAAEE,EAAE,GAAG,GAAG,KAAK,QAAQ,SAAS,CAAC,IAAIL,EAAE,KAAK,MAAM,MAAM,kBAAkB,KAAKG,CAAC,EAAEH,IAAIG,EAAEH,EAAE,CAAC,EAAEK,EAAEL,EAAE,CAAC,EAAE,MAAMK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAOF,EAAEA,EAAE,KAAI,EAAG,KAAK,MAAM,MAAM,kBAAkB,KAAKA,CAAC,IAAI,KAAK,QAAQ,UAAU,CAAC,KAAK,MAAM,MAAM,gBAAgB,KAAK,CAAC,EAAEA,EAAEA,EAAE,MAAM,CAAC,EAAEA,EAAEA,EAAE,MAAM,EAAE,EAAE,GAAGgxC,GAAG,EAAE,CAAC,KAAKhxC,GAAGA,EAAE,QAAQ,KAAK,MAAM,OAAO,eAAe,IAAI,EAAE,MAAME,GAAGA,EAAE,QAAQ,KAAK,MAAM,OAAO,eAAe,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,MAAM,OAAO,QAAQ,KAAK,CAAC,KAAK,EAAE,KAAK,MAAM,OAAO,OAAO,KAAK,CAAC,GAAG,CAAC,IAAIF,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,QAAQ,KAAK,MAAM,MAAM,oBAAoB,GAAG,EAAEE,EAAE,EAAEF,EAAE,YAAW,CAAE,EAAE,GAAG,CAACE,EAAE,CAAC,IAAIL,EAAE,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,KAAK,OAAO,IAAIA,EAAE,KAAKA,CAAC,CAAC,CAAC,OAAOmxC,GAAG,EAAE9wC,EAAE,EAAE,CAAC,EAAE,KAAK,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,IAAIF,EAAE,KAAK,MAAM,OAAO,eAAe,KAAK,CAAC,EAAE,GAAG,GAACA,GAAGA,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,MAAM,mBAAmB,KAAY,EAAEA,EAAE,CAAC,GAAGA,EAAE,CAAC,IAAQ,CAAC,GAAG,KAAK,MAAM,OAAO,YAAY,KAAK,CAAC,GAAE,CAAC,IAAI,EAAE,CAAC,GAAGA,EAAE,CAAC,CAAC,EAAE,OAAO,EAAEM,EAAER,EAAES,EAAE,EAAEC,EAAE,EAAEJ,EAAEJ,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,KAAK,MAAM,OAAO,kBAAkB,KAAK,MAAM,OAAO,kBAAkB,IAAII,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,EAAE,OAAO,CAAC,GAAGJ,EAAEI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,GAAGE,EAAEN,EAAE,CAAC,GAAGA,EAAE,CAAC,GAAGA,EAAE,CAAC,GAAGA,EAAE,CAAC,GAAGA,EAAE,CAAC,GAAGA,EAAE,CAAC,EAAE,CAACM,EAAE,SAAS,GAAGR,EAAE,CAAC,GAAGQ,CAAC,EAAE,OAAON,EAAE,CAAC,GAAGA,EAAE,CAAC,EAAE,CAACO,GAAGT,EAAE,QAAQ,UAAUE,EAAE,CAAC,GAAGA,EAAE,CAAC,IAAI,EAAE,GAAG,GAAG,EAAEF,GAAG,GAAG,CAACU,GAAGV,EAAE,QAAQ,CAAC,GAAGS,GAAGT,EAAES,EAAE,EAAE,SAAST,EAAE,KAAK,IAAIA,EAAEA,EAAES,EAAEC,CAAC,EAAE,IAAIY,EAAE,CAAC,GAAGpB,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,OAAOK,EAAE,EAAE,MAAM,EAAE,EAAEL,EAAE,MAAMoB,EAAEtB,CAAC,EAAE,GAAG,KAAK,IAAI,EAAEA,CAAC,EAAE,EAAE,CAAC,IAAIa,EAAEN,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,KAAK,IAAIA,EAAE,KAAKM,EAAE,OAAO,KAAK,MAAM,aAAaA,CAAC,CAAC,CAAC,CAAC,IAAIwB,EAAE9B,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,SAAS,IAAIA,EAAE,KAAK8B,EAAE,OAAO,KAAK,MAAM,aAAaA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,QAAQ,KAAK,MAAM,MAAM,kBAAkB,GAAG,EAAEnC,EAAE,KAAK,MAAM,MAAM,aAAa,KAAK,CAAC,EAAEE,EAAE,KAAK,MAAM,MAAM,kBAAkB,KAAK,CAAC,GAAG,KAAK,MAAM,MAAM,gBAAgB,KAAK,CAAC,EAAE,OAAOF,GAAGE,IAAI,EAAE,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,WAAW,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,MAAM,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,KAAK,MAAM,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,SAAS,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAEF,EAAE,OAAO,EAAE,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC,EAAEA,EAAE,UAAU,IAAI,EAAE,EAAE,CAAC,EAAEA,EAAE,GAAG,CAAC,KAAK,OAAO,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,KAAKA,EAAE,OAAO,CAAC,CAAC,KAAK,OAAO,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAC,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC,IAAIC,EAAED,EAAE,GAAG,EAAE,CAAC,IAAI,IAAIC,EAAE,EAAE,CAAC,EAAED,EAAE,UAAUC,MAAM,CAAC,IAAIC,EAAE,GAAGA,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,IAAEY,EAAA,KAAK,MAAM,OAAO,WAAW,KAAK,EAAE,CAAC,CAAC,IAAtC,YAAAA,EAA0C,KAAI,SAASZ,IAAI,EAAE,CAAC,GAAGD,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,OAAOD,EAAE,UAAU,EAAE,CAAC,EAAEA,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,OAAO,IAAI,EAAE,CAAC,EAAE,KAAKC,EAAE,KAAKD,EAAE,OAAO,CAAC,CAAC,KAAK,OAAO,IAAIC,EAAE,KAAKA,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,MAAM,MAAM,WAAW,MAAM,CAAC,KAAK,OAAO,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAMqB,GAAE,MAAMZ,EAAC,CAA4C,YAAYd,EAAE,CAAzD2b,EAAA,eAAOA,EAAA,gBAAQA,EAAA,cAAMA,EAAA,oBAAYA,EAAA,kBAAyB,KAAK,OAAO,GAAG,KAAK,OAAO,MAAM,OAAO,OAAO,IAAI,EAAE,KAAK,QAAQ3b,GAAG0b,GAAE,KAAK,QAAQ,UAAU,KAAK,QAAQ,WAAW,IAAIta,GAAE,KAAK,UAAU,KAAK,QAAQ,UAAU,KAAK,UAAU,QAAQ,KAAK,QAAQ,KAAK,UAAU,MAAM,KAAK,KAAK,YAAY,GAAG,KAAK,MAAM,CAAC,OAAO,GAAG,WAAW,GAAG,IAAI,EAAE,EAAE,IAAIrB,EAAE,CAAC,MAAMwB,GAAE,MAAMI,GAAE,OAAO,OAAOW,GAAE,MAAM,EAAE,KAAK,QAAQ,UAAUvC,EAAE,MAAM4B,GAAE,SAAS5B,EAAE,OAAOuC,GAAE,UAAU,KAAK,QAAQ,MAAMvC,EAAE,MAAM4B,GAAE,IAAI,KAAK,QAAQ,OAAO5B,EAAE,OAAOuC,GAAE,OAAOvC,EAAE,OAAOuC,GAAE,KAAK,KAAK,UAAU,MAAMvC,CAAC,CAAC,WAAW,OAAO,CAAC,MAAM,CAAC,MAAM4B,GAAE,OAAOW,EAAC,CAAC,CAAC,OAAO,IAAItC,EAAED,EAAE,CAAC,OAAO,IAAIe,GAAEf,CAAC,EAAE,IAAIC,CAAC,CAAC,CAAC,OAAO,UAAUA,EAAED,EAAE,CAAC,OAAO,IAAIe,GAAEf,CAAC,EAAE,aAAaC,CAAC,CAAC,CAAC,IAAIA,EAAE,CAACA,EAAEA,EAAE,QAAQuB,GAAE,eAAe;AAAA,CACvqJ,EAAE,KAAK,YAAYvB,EAAE,KAAK,MAAM,EAAE,QAAQD,EAAE,EAAEA,EAAE,KAAK,YAAY,OAAOA,IAAI,CAAC,IAAIM,EAAE,KAAK,YAAYN,CAAC,EAAE,KAAK,aAAaM,EAAE,IAAIA,EAAE,MAAM,CAAC,CAAC,OAAO,KAAK,YAAY,GAAG,KAAK,MAAM,CAAC,YAAYL,EAAED,EAAE,GAAGM,EAAE,GAAG,WAAC,IAAI,KAAK,QAAQ,WAAWL,EAAEA,EAAE,QAAQuB,GAAE,cAAc,MAAM,EAAE,QAAQA,GAAE,UAAU,EAAE,GAAGvB,GAAG,CAAC,IAAI,EAAE,IAAGmB,GAAAD,EAAA,KAAK,QAAQ,aAAb,YAAAA,EAAyB,QAAzB,MAAAC,EAAgC,KAAKlB,IAAI,EAAEA,EAAE,KAAK,CAAC,MAAM,IAAI,EAAED,EAAED,CAAC,IAAIC,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,SAAS,GAAG,EAAE,KAAK,UAAU,MAAMC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,IAAIC,EAAEF,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,SAAS,GAAGE,IAAI,OAAOA,EAAE,KAAK;AAAA,EACxhBF,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,KAAKC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,IAAIC,EAAEF,EAAE,GAAG,EAAE,GAAEE,GAAA,YAAAA,EAAG,QAAO,cAAaA,GAAA,YAAAA,EAAG,QAAO,QAAQA,EAAE,MAAMA,EAAE,IAAI,SAAS;AAAA,CAC5J,EAAE,GAAG;AAAA,GACH,EAAE,IAAIA,EAAE,MAAM;AAAA,EACf,EAAE,KAAK,KAAK,YAAY,GAAG,EAAE,EAAE,IAAIA,EAAE,MAAMF,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,OAAOC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,QAAQC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,GAAGC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,WAAWC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,KAAKC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,KAAKC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,IAAIC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,IAAIC,EAAEF,EAAE,GAAG,EAAE,GAAEE,GAAA,YAAAA,EAAG,QAAO,cAAaA,GAAA,YAAAA,EAAG,QAAO,QAAQA,EAAE,MAAMA,EAAE,IAAI,SAAS;AAAA,CACvpB,EAAE,GAAG;AAAA,GACH,EAAE,IAAIA,EAAE,MAAM;AAAA,EACf,EAAE,IAAI,KAAK,YAAY,GAAG,EAAE,EAAE,IAAIA,EAAE,MAAM,KAAK,OAAO,MAAM,EAAE,GAAG,IAAI,KAAK,OAAO,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,MAAM,EAAE,KAAK,EAAEF,EAAE,KAAK,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,MAAMC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,SAASC,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAED,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,IAAIO,EAAEN,EAAE,IAAGmvB,EAAA,KAAK,QAAQ,aAAb,MAAAA,EAAyB,WAAW,CAAC,IAAIlvB,EAAE,IAAIS,EAAEV,EAAE,MAAM,CAAC,EAAEE,EAAE,KAAK,QAAQ,WAAW,WAAW,QAAQS,GAAG,CAACT,EAAES,EAAE,KAAK,CAAC,MAAM,IAAI,EAAED,CAAC,EAAE,OAAOR,GAAG,UAAUA,GAAG,IAAID,EAAE,KAAK,IAAIA,EAAEC,CAAC,EAAE,CAAC,EAAED,EAAE,KAAKA,GAAG,IAAIK,EAAEN,EAAE,UAAU,EAAEC,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,MAAM,MAAM,EAAE,KAAK,UAAU,UAAUK,CAAC,GAAG,CAAC,IAAIL,EAAEF,EAAE,GAAG,EAAE,EAAEM,IAAGJ,GAAA,YAAAA,EAAG,QAAO,aAAaA,EAAE,MAAMA,EAAE,IAAI,SAAS;AAAA,CACnoB,EAAE,GAAG;AAAA,GACH,EAAE,IAAIA,EAAE,MAAM;AAAA,EACf,EAAE,KAAK,KAAK,YAAY,IAAG,EAAG,KAAK,YAAY,GAAG,EAAE,EAAE,IAAIA,EAAE,MAAMF,EAAE,KAAK,CAAC,EAAEM,EAAEC,EAAE,SAASN,EAAE,OAAOA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,UAAU,KAAKA,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAU,EAAE,IAAI,MAAM,EAAE,IAAIC,EAAEF,EAAE,GAAG,EAAE,GAAEE,GAAA,YAAAA,EAAG,QAAO,QAAQA,EAAE,MAAMA,EAAE,IAAI,SAAS;AAAA,CACzP,EAAE,GAAG;AAAA,GACH,EAAE,IAAIA,EAAE,MAAM;AAAA,EACf,EAAE,KAAK,KAAK,YAAY,IAAG,EAAG,KAAK,YAAY,GAAG,EAAE,EAAE,IAAIA,EAAE,MAAMF,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,GAAGC,EAAE,CAAC,IAAIC,EAAE,0BAA0BD,EAAE,WAAW,CAAC,EAAE,GAAG,KAAK,QAAQ,OAAO,CAAC,QAAQ,MAAMC,CAAC,EAAE,KAAK,KAAM,OAAM,IAAI,MAAMA,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,IAAI,GAAGF,CAAC,CAAC,OAAOC,EAAED,EAAE,GAAG,CAAC,OAAO,KAAK,YAAY,KAAK,CAAC,IAAIC,EAAE,OAAOD,CAAC,CAAC,EAAEA,CAAC,CAAC,aAAaC,EAAED,EAAE,GAAG,eAAC,IAAIM,EAAEL,EAAEI,EAAE,KAAK,GAAG,KAAK,OAAO,MAAM,CAAC,IAAIF,EAAE,OAAO,KAAK,KAAK,OAAO,KAAK,EAAE,GAAGA,EAAE,OAAO,EAAE,MAAME,EAAE,KAAK,UAAU,MAAM,OAAO,cAAc,KAAKC,CAAC,IAAI,MAAMH,EAAE,SAASE,EAAE,CAAC,EAAE,MAAMA,EAAE,CAAC,EAAE,YAAY,GAAG,EAAE,EAAE,EAAE,CAAC,IAAIC,EAAEA,EAAE,MAAM,EAAED,EAAE,KAAK,EAAE,IAAI,IAAI,OAAOA,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,IAAIC,EAAE,MAAM,KAAK,UAAU,MAAM,OAAO,cAAc,SAAS,EAAE,CAAC,MAAMD,EAAE,KAAK,UAAU,MAAM,OAAO,eAAe,KAAKC,CAAC,IAAI,MAAMA,EAAEA,EAAE,MAAM,EAAED,EAAE,KAAK,EAAE,KAAKC,EAAE,MAAM,KAAK,UAAU,MAAM,OAAO,eAAe,SAAS,EAAE,IAAIC,EAAE,MAAMF,EAAE,KAAK,UAAU,MAAM,OAAO,UAAU,KAAKC,CAAC,IAAI,MAAMC,EAAEF,EAAE,CAAC,EAAEA,EAAE,CAAC,EAAE,OAAO,EAAEC,EAAEA,EAAE,MAAM,EAAED,EAAE,MAAME,CAAC,EAAE,IAAI,IAAI,OAAOF,EAAE,CAAC,EAAE,OAAOE,EAAE,CAAC,EAAE,IAAID,EAAE,MAAM,KAAK,UAAU,MAAM,OAAO,UAAU,SAAS,EAAEA,IAAEc,GAAAD,EAAA,KAAK,QAAQ,QAAb,YAAAA,EAAoB,eAApB,YAAAC,EAAkC,KAAK,CAAC,MAAM,IAAI,EAAEd,KAAIA,EAAE,IAAIJ,EAAE,GAAGS,EAAE,GAAG,KAAKV,GAAG,CAACC,IAAIS,EAAE,IAAIT,EAAE,GAAG,IAAIC,EAAE,IAAGqY,GAAA4W,EAAA,KAAK,QAAQ,aAAb,YAAAA,EAAyB,SAAzB,MAAA5W,EAAiC,KAAK3X,IAAIV,EAAEU,EAAE,KAAK,CAAC,MAAM,IAAI,EAAEZ,EAAED,CAAC,IAAIC,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,IAAI,IAAI,SAAS,GAAGA,EAAE,KAAK,UAAU,OAAOF,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,IAAIF,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,KAAKF,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,QAAQF,EAAE,KAAK,OAAO,KAAK,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAE,IAAIU,EAAEb,EAAE,GAAG,EAAE,EAAEG,EAAE,OAAO,SAAQU,GAAA,YAAAA,EAAG,QAAO,QAAQA,EAAE,KAAKV,EAAE,IAAIU,EAAE,MAAMV,EAAE,MAAMH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,SAASF,EAAEK,EAAEK,CAAC,EAAE,CAACV,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,SAASF,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,GAAGF,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,IAAIF,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGA,EAAE,KAAK,UAAU,SAASF,CAAC,EAAE,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,KAAK,MAAM,SAASA,EAAE,KAAK,UAAU,IAAIF,CAAC,GAAG,CAACA,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,IAAIS,EAAEX,EAAE,IAAGivC,EAAA,KAAK,QAAQ,aAAb,MAAAA,EAAyB,YAAY,CAAC,IAAIruC,EAAE,IAAIJ,EAAER,EAAE,MAAM,CAAC,EAAEwB,EAAE,KAAK,QAAQ,WAAW,YAAY,QAAQf,GAAG,CAACe,EAAEf,EAAE,KAAK,CAAC,MAAM,IAAI,EAAED,CAAC,EAAE,OAAOgB,GAAG,UAAUA,GAAG,IAAIZ,EAAE,KAAK,IAAIA,EAAEY,CAAC,EAAE,CAAC,EAAEZ,EAAE,KAAKA,GAAG,IAAID,EAAEX,EAAE,UAAU,EAAEY,EAAE,CAAC,EAAE,CAAC,GAAGV,EAAE,KAAK,UAAU,WAAWS,CAAC,EAAE,CAACX,EAAEA,EAAE,UAAUE,EAAE,IAAI,MAAM,EAAEA,EAAE,IAAI,MAAM,EAAE,IAAI,MAAMQ,EAAER,EAAE,IAAI,MAAM,EAAE,GAAGD,EAAE,GAAG,IAAIW,EAAEb,EAAE,GAAG,EAAE,GAAEa,GAAA,YAAAA,EAAG,QAAO,QAAQA,EAAE,KAAKV,EAAE,IAAIU,EAAE,MAAMV,EAAE,MAAMH,EAAE,KAAKG,CAAC,EAAE,QAAQ,CAAC,GAAGF,EAAE,CAAC,IAAIY,EAAE,0BAA0BZ,EAAE,WAAW,CAAC,EAAE,GAAG,KAAK,QAAQ,OAAO,CAAC,QAAQ,MAAMY,CAAC,EAAE,KAAK,KAAM,OAAM,IAAI,MAAMA,CAAC,CAAC,CAAC,CAAC,OAAOb,CAAC,CAAC,EAAM+B,GAAE,KAAK,CAAgB,YAAY,EAAE,CAA7B6Z,EAAA,gBAAQA,EAAA,eAAsB,KAAK,QAAQ,GAAGD,EAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,CAAC,EAAE,OAAC,IAAItb,GAAGc,GAAA,GAAG,IAAI,MAAMK,GAAE,aAAa,IAA5B,YAAAL,EAAgC,GAAGZ,EAAE,EAAE,QAAQiB,GAAE,cAAc,EAAE,EAAE;AAAA,EAC7zF,OAAOnB,EAAE,8BAA8BihB,GAAEjhB,CAAC,EAAE,MAAM,EAAEE,EAAE+gB,GAAE/gB,EAAE,EAAE,GAAG;AAAA,EAC/D,eAAe,EAAEA,EAAE+gB,GAAE/gB,EAAE,EAAE,GAAG;AAAA,CAC7B,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM;AAAA,EAC7B,KAAK,OAAO,MAAM,CAAC,CAAC;AAAA,CACrB,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC;AAAA,CACtH,CAAC,GAAG,EAAE,CAAC,MAAM;AAAA,CACb,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAMF,EAAE,GAAG,QAAQ,EAAE,EAAE,EAAE,EAAE,MAAM,OAAO,IAAI,CAAC,IAAIF,EAAE,EAAE,MAAM,CAAC,EAAEE,GAAG,KAAK,SAASF,CAAC,CAAC,CAAC,IAAII,EAAE,EAAE,KAAK,KAAKL,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,IAAI,GAAG,MAAM,IAAIK,EAAEL,EAAE;AAAA,EAC7KG,EAAE,KAAKE,EAAE;AAAA,CACV,CAAC,SAAS,EAAE,CAAC,MAAM,OAAO,KAAK,OAAO,MAAM,EAAE,MAAM,CAAC;AAAA,CACrD,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,WAAW,EAAE,cAAc,IAAI,+BAA+B,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,MAAM,KAAK,OAAO,YAAY,CAAC,CAAC;AAAA,CACxJ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,QAAQA,EAAE,EAAEA,EAAE,EAAE,OAAO,OAAOA,IAAI,GAAG,KAAK,UAAU,EAAE,OAAOA,CAAC,CAAC,EAAE,GAAG,KAAK,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,IAAIF,EAAE,GAAG,QAAQE,EAAE,EAAEA,EAAE,EAAE,KAAK,OAAOA,IAAI,CAAC,IAAIL,EAAE,EAAE,KAAKK,CAAC,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,EAAEL,EAAE,OAAO,IAAI,GAAG,KAAK,UAAUA,EAAE,CAAC,CAAC,EAAEG,GAAG,KAAK,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAOA,IAAIA,EAAE,UAAUA,CAAC,YAAY;AAAA;AAAA,EAEpS,EAAE;AAAA,EACFA,EAAE;AAAA,CACH,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM;AAAA,EACzB,CAAC;AAAA,CACF,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,OAAO,YAAY,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,KAAK,KAAK,OAAO,EAAE,MAAM,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC;AAAA,CACxI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,WAAW,KAAK,OAAO,YAAY,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,OAAO,KAAK,OAAO,YAAY,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,SAASihB,GAAE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,QAAQ,KAAK,OAAO,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,IAAIjhB,EAAE,KAAK,OAAO,YAAY,CAAC,EAAEE,EAAEkb,GAAE,CAAC,EAAE,GAAGlb,IAAI,KAAK,OAAOF,EAAE,EAAEE,EAAE,IAAIL,EAAE,YAAY,EAAE,IAAI,OAAO,IAAIA,GAAG,WAAWohB,GAAE,CAAC,EAAE,KAAKphB,GAAG,IAAIG,EAAE,OAAOH,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAOG,CAAC,EAAE,CAACA,IAAI,EAAE,KAAK,OAAO,YAAYA,EAAE,KAAK,OAAO,YAAY,GAAG,IAAIE,EAAEkb,GAAE,CAAC,EAAE,GAAGlb,IAAI,KAAK,OAAO+gB,GAAE,CAAC,EAAE,EAAE/gB,EAAE,IAAIL,EAAE,aAAa,CAAC,UAAU,CAAC,IAAI,OAAO,IAAIA,GAAG,WAAWohB,GAAE,CAAC,CAAC,KAAKphB,GAAG,IAAIA,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,WAAW,GAAG,EAAE,OAAO,KAAK,OAAO,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,EAAE,QAAQ,EAAE,KAAKohB,GAAE,EAAE,IAAI,CAAC,CAAC,EAAM5f,GAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAMT,GAAE,MAAMF,EAAC,CAA+B,YAAYd,EAAE,CAA5C2b,EAAA,gBAAQA,EAAA,iBAASA,EAAA,qBAA4B,KAAK,QAAQ3b,GAAG0b,GAAE,KAAK,QAAQ,SAAS,KAAK,QAAQ,UAAU,IAAI5Z,GAAE,KAAK,SAAS,KAAK,QAAQ,SAAS,KAAK,SAAS,QAAQ,KAAK,QAAQ,KAAK,SAAS,OAAO,KAAK,KAAK,aAAa,IAAIL,EAAC,CAAC,OAAO,MAAMzB,EAAED,EAAE,CAAC,OAAO,IAAIe,GAAEf,CAAC,EAAE,MAAMC,CAAC,CAAC,CAAC,OAAO,YAAYA,EAAED,EAAE,CAAC,OAAO,IAAIe,GAAEf,CAAC,EAAE,YAAYC,CAAC,CAAC,CAAC,MAAMA,EAAE,SAAC,IAAID,EAAE,GAAG,QAAQM,EAAE,EAAEA,EAAEL,EAAE,OAAOK,IAAI,CAAC,IAAID,EAAEJ,EAAEK,CAAC,EAAE,IAAGc,GAAAD,EAAA,KAAK,QAAQ,aAAb,YAAAA,EAAyB,YAAzB,MAAAC,EAAqCf,EAAE,MAAM,CAAC,IAAIH,EAAEG,EAAEM,EAAE,KAAK,QAAQ,WAAW,UAAUT,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,IAAI,EAAEA,CAAC,EAAE,GAAGS,IAAI,IAAI,CAAC,CAAC,QAAQ,KAAK,UAAU,OAAO,QAAQ,aAAa,OAAO,OAAO,MAAM,YAAY,MAAM,EAAE,SAAST,EAAE,IAAI,EAAE,CAACF,GAAGW,GAAG,GAAG,QAAQ,CAAC,CAAC,IAAIJ,EAAEF,EAAE,OAAOE,EAAE,MAAM,IAAI,QAAQ,CAACP,GAAG,KAAK,SAAS,MAAMO,CAAC,EAAE,KAAK,CAAC,IAAI,KAAK,CAACP,GAAG,KAAK,SAAS,GAAGO,CAAC,EAAE,KAAK,CAAC,IAAI,UAAU,CAACP,GAAG,KAAK,SAAS,QAAQO,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAACP,GAAG,KAAK,SAAS,KAAKO,CAAC,EAAE,KAAK,CAAC,IAAI,QAAQ,CAACP,GAAG,KAAK,SAAS,MAAMO,CAAC,EAAE,KAAK,CAAC,IAAI,aAAa,CAACP,GAAG,KAAK,SAAS,WAAWO,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAACP,GAAG,KAAK,SAAS,KAAKO,CAAC,EAAE,KAAK,CAAC,IAAI,WAAW,CAACP,GAAG,KAAK,SAAS,SAASO,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAACP,GAAG,KAAK,SAAS,KAAKO,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAACP,GAAG,KAAK,SAAS,IAAIO,CAAC,EAAE,KAAK,CAAC,IAAI,YAAY,CAACP,GAAG,KAAK,SAAS,UAAUO,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAACP,GAAG,KAAK,SAAS,KAAKO,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAIL,EAAE,eAAeK,EAAE,KAAK,wBAAwB,GAAG,KAAK,QAAQ,OAAO,OAAO,QAAQ,MAAML,CAAC,EAAE,GAAG,MAAM,IAAI,MAAMA,CAAC,CAAC,CAAC,CAAC,CAAC,OAAOF,CAAC,CAAC,YAAYC,EAAED,EAAE,KAAK,SAAS,SAAC,IAAIM,EAAE,GAAG,QAAQD,EAAE,EAAEA,EAAEJ,EAAE,OAAOI,IAAI,CAAC,IAAIE,EAAEN,EAAEI,CAAC,EAAE,IAAGe,GAAAD,EAAA,KAAK,QAAQ,aAAb,YAAAA,EAAyB,YAAzB,MAAAC,EAAqCb,EAAE,MAAM,CAAC,IAAII,EAAE,KAAK,QAAQ,WAAW,UAAUJ,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,IAAI,EAAEA,CAAC,EAAE,GAAGI,IAAI,IAAI,CAAC,CAAC,SAAS,OAAO,OAAO,QAAQ,SAAS,KAAK,WAAW,KAAK,MAAM,MAAM,EAAE,SAASJ,EAAE,IAAI,EAAE,CAACD,GAAGK,GAAG,GAAG,QAAQ,CAAC,CAAC,IAAIT,EAAEK,EAAE,OAAOL,EAAE,KAAI,CAAE,IAAI,SAAS,CAACI,GAAGN,EAAE,KAAKE,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAACI,GAAGN,EAAE,KAAKE,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAACI,GAAGN,EAAE,KAAKE,CAAC,EAAE,KAAK,CAAC,IAAI,QAAQ,CAACI,GAAGN,EAAE,MAAME,CAAC,EAAE,KAAK,CAAC,IAAI,WAAW,CAACI,GAAGN,EAAE,SAASE,CAAC,EAAE,KAAK,CAAC,IAAI,SAAS,CAACI,GAAGN,EAAE,OAAOE,CAAC,EAAE,KAAK,CAAC,IAAI,KAAK,CAACI,GAAGN,EAAE,GAAGE,CAAC,EAAE,KAAK,CAAC,IAAI,WAAW,CAACI,GAAGN,EAAE,SAASE,CAAC,EAAE,KAAK,CAAC,IAAI,KAAK,CAACI,GAAGN,EAAE,GAAGE,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,CAACI,GAAGN,EAAE,IAAIE,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAACI,GAAGN,EAAE,KAAKE,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAIS,EAAE,eAAeT,EAAE,KAAK,wBAAwB,GAAG,KAAK,QAAQ,OAAO,OAAO,QAAQ,MAAMS,CAAC,EAAE,GAAG,MAAM,IAAI,MAAMA,CAAC,CAAC,CAAC,CAAC,CAAC,OAAOL,CAAC,CAAC,KAAME,IAAEW,GAAA,KAAK,CAAe,YAAY,EAAE,CAA5Bya,EAAA,gBAAQA,EAAA,cAAqB,KAAK,QAAQ,GAAGD,EAAC,CAA8L,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,CAAC,OAAO,CAAC,CAAC,iBAAiB,EAAE,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,OAAO,KAAK,MAAMha,GAAE,IAAIA,GAAE,SAAS,CAAC,eAAe,CAAC,OAAO,KAAK,MAAMV,GAAE,MAAMA,GAAE,WAAW,CAAC,EAA7Y2a,EAArDza,GAA4D,mBAAiB,IAAI,IAAI,CAAC,aAAa,cAAc,mBAAmB,cAAc,CAAC,GAAEya,EAArJza,GAA4J,+BAA6B,IAAI,IAAI,CAAC,aAAa,cAAc,kBAAkB,CAAC,GAAhPA,IAAwc2B,GAAE,KAAK,CAAqK,eAAe,EAAE,CAArL8Y,EAAA,gBAASxZ,GAAC,GAAGwZ,EAAA,eAAQ,KAAK,YAAWA,EAAA,aAAM,KAAK,cAAc,EAAE,GAAEA,EAAA,mBAAY,KAAK,cAAc,EAAE,GAAEA,EAAA,cAAO3a,IAAE2a,EAAA,gBAAS7Z,IAAE6Z,EAAA,oBAAala,IAAEka,EAAA,aAAMja,IAAEia,EAAA,iBAAUva,IAAEua,EAAA,aAAMpb,IAAoB,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,SAAC,IAAI,EAAE,GAAG,QAAQH,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,KAAKA,CAAC,CAAC,EAAEA,EAAE,MAAM,IAAI,QAAQ,CAAC,IAAIE,EAAEF,EAAE,QAAQH,KAAKK,EAAE,OAAO,EAAE,EAAE,OAAO,KAAK,WAAWL,EAAE,OAAO,CAAC,CAAC,EAAE,QAAQA,KAAKK,EAAE,KAAK,QAAQI,KAAKT,EAAE,EAAE,EAAE,OAAO,KAAK,WAAWS,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,OAAO,CAAC,IAAIJ,EAAEF,EAAE,EAAE,EAAE,OAAO,KAAK,WAAWE,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAIA,EAAEF,GAAEe,GAAAD,EAAA,KAAK,SAAS,aAAd,YAAAA,EAA0B,cAA1B,MAAAC,EAAwCb,EAAE,MAAM,KAAK,SAAS,WAAW,YAAYA,EAAE,IAAI,EAAE,QAAQL,GAAG,CAAC,IAAIS,EAAEJ,EAAEL,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,EAAE,OAAO,KAAK,WAAWS,EAAE,CAAC,CAAC,CAAC,CAAC,EAAEJ,EAAE,SAAS,EAAE,EAAE,OAAO,KAAK,WAAWA,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,SAAS,YAAY,CAAC,UAAU,GAAG,YAAY,EAAE,EAAE,OAAO,EAAE,QAAQ,GAAG,CAAC,IAAIF,EAAE,CAAC,GAAG,CAAC,EAAE,GAAGA,EAAE,MAAM,KAAK,SAAS,OAAOA,EAAE,OAAO,GAAG,EAAE,aAAa,EAAE,WAAW,QAAQE,GAAG,CAAC,GAAG,CAACA,EAAE,KAAK,MAAM,IAAI,MAAM,yBAAyB,EAAE,GAAG,aAAaA,EAAE,CAAC,IAAIL,EAAE,EAAE,UAAUK,EAAE,IAAI,EAAEL,EAAE,EAAE,UAAUK,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,IAAIJ,EAAEI,EAAE,SAAS,MAAM,KAAK,CAAC,EAAE,OAAOJ,IAAI,KAAKA,EAAED,EAAE,MAAM,KAAK,CAAC,GAAGC,CAAC,EAAE,EAAE,UAAUI,EAAE,IAAI,EAAEA,EAAE,QAAQ,CAAC,GAAG,cAAcA,EAAE,CAAC,GAAG,CAACA,EAAE,OAAOA,EAAE,QAAQ,SAASA,EAAE,QAAQ,SAAS,MAAM,IAAI,MAAM,6CAA6C,EAAE,IAAIL,EAAE,EAAEK,EAAE,KAAK,EAAEL,EAAEA,EAAE,QAAQK,EAAE,SAAS,EAAE,EAAEA,EAAE,KAAK,EAAE,CAACA,EAAE,SAAS,EAAEA,EAAE,QAAQA,EAAE,QAAQ,QAAQ,EAAE,WAAW,EAAE,WAAW,KAAKA,EAAE,KAAK,EAAE,EAAE,WAAW,CAACA,EAAE,KAAK,EAAEA,EAAE,QAAQ,WAAW,EAAE,YAAY,EAAE,YAAY,KAAKA,EAAE,KAAK,EAAE,EAAE,YAAY,CAACA,EAAE,KAAK,GAAG,CAAC,gBAAgBA,GAAGA,EAAE,cAAc,EAAE,YAAYA,EAAE,IAAI,EAAEA,EAAE,YAAY,CAAC,EAAEF,EAAE,WAAW,GAAG,EAAE,SAAS,CAAC,IAAIE,EAAE,KAAK,SAAS,UAAU,IAAIwB,GAAE,KAAK,QAAQ,EAAE,QAAQ7B,KAAK,EAAE,SAAS,CAAC,GAAG,EAAEA,KAAKK,GAAG,MAAM,IAAI,MAAM,aAAaL,CAAC,kBAAkB,EAAE,GAAG,CAAC,UAAU,QAAQ,EAAE,SAASA,CAAC,EAAE,SAAS,IAAI,EAAEA,EAAEC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAEI,EAAE,CAAC,EAAEA,EAAE,CAAC,EAAE,IAAIM,IAAI,CAAC,IAAIJ,EAAEN,EAAE,MAAMI,EAAEM,CAAC,EAAE,OAAOJ,IAAI,KAAKA,EAAE,EAAE,MAAMF,EAAEM,CAAC,GAAGJ,GAAG,EAAE,CAAC,CAACJ,EAAE,SAASE,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,IAAIA,EAAE,KAAK,SAAS,WAAW,IAAIc,GAAE,KAAK,QAAQ,EAAE,QAAQnB,KAAK,EAAE,UAAU,CAAC,GAAG,EAAEA,KAAKK,GAAG,MAAM,IAAI,MAAM,cAAcL,CAAC,kBAAkB,EAAE,GAAG,CAAC,UAAU,QAAQ,OAAO,EAAE,SAASA,CAAC,EAAE,SAAS,IAAI,EAAEA,EAAEC,EAAE,EAAE,UAAU,CAAC,EAAE,EAAEI,EAAE,CAAC,EAAEA,EAAE,CAAC,EAAE,IAAIM,IAAI,CAAC,IAAIJ,EAAEN,EAAE,MAAMI,EAAEM,CAAC,EAAE,OAAOJ,IAAI,KAAKA,EAAE,EAAE,MAAMF,EAAEM,CAAC,GAAGJ,CAAC,CAAC,CAACJ,EAAE,UAAUE,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,IAAIA,EAAE,KAAK,SAAS,OAAO,IAAIC,GAAE,QAAQN,KAAK,EAAE,MAAM,CAAC,GAAG,EAAEA,KAAKK,GAAG,MAAM,IAAI,MAAM,SAASL,CAAC,kBAAkB,EAAE,GAAG,CAAC,UAAU,OAAO,EAAE,SAASA,CAAC,EAAE,SAAS,IAAI,EAAEA,EAAEC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAEI,EAAE,CAAC,EAAEC,GAAE,iBAAiB,IAAIN,CAAC,EAAEK,EAAE,CAAC,EAAEM,GAAG,CAAC,GAAG,KAAK,SAAS,OAAOL,GAAE,6BAA6B,IAAIN,CAAC,EAAE,OAAO,SAAS,CAAC,IAAIuB,EAAE,MAAMtB,EAAE,KAAKI,EAAEM,CAAC,EAAE,OAAO,EAAE,KAAKN,EAAEkB,CAAC,CAAC,GAAC,EAAI,IAAIhB,EAAEN,EAAE,KAAKI,EAAEM,CAAC,EAAE,OAAO,EAAE,KAAKN,EAAEE,CAAC,CAAC,EAAEF,EAAE,CAAC,EAAE,IAAIM,IAAI,CAAC,GAAG,KAAK,SAAS,MAAM,OAAO,SAAS,CAAC,IAAIY,EAAE,MAAMtB,EAAE,MAAMI,EAAEM,CAAC,EAAE,OAAOY,IAAI,KAAKA,EAAE,MAAM,EAAE,MAAMlB,EAAEM,CAAC,GAAGY,CAAC,GAAC,EAAI,IAAIhB,EAAEN,EAAE,MAAMI,EAAEM,CAAC,EAAE,OAAOJ,IAAI,KAAKA,EAAE,EAAE,MAAMF,EAAEM,CAAC,GAAGJ,CAAC,CAAC,CAACJ,EAAE,MAAME,CAAC,CAAC,GAAG,EAAE,WAAW,CAAC,IAAIA,EAAE,KAAK,SAAS,WAAWL,EAAE,EAAE,WAAWG,EAAE,WAAW,SAAS,EAAE,CAAC,IAAIF,EAAE,GAAG,OAAOA,EAAE,KAAKD,EAAE,KAAK,KAAK,CAAC,CAAC,EAAEK,IAAIJ,EAAEA,EAAE,OAAOI,EAAE,KAAK,KAAK,CAAC,CAAC,GAAGJ,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,GAAG,KAAK,SAAS,GAAGE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC,GAAG,KAAK,SAAS,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,OAAOsB,GAAE,IAAI,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAOV,GAAE,MAAM,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC,cAAc,EAAE,CAAC,MAAM,CAACX,EAAED,IAAI,CAAC,IAAI,EAAE,CAAC,GAAGA,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,SAAS,GAAG,CAAC,EAAEM,EAAE,KAAK,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,SAAS,QAAQ,IAAI,EAAE,QAAQ,GAAG,OAAOA,EAAE,IAAI,MAAM,oIAAoI,CAAC,EAAE,GAAG,OAAOL,EAAE,KAAKA,IAAI,KAAK,OAAOK,EAAE,IAAI,MAAM,gDAAgD,CAAC,EAAE,GAAG,OAAOL,GAAG,SAAS,OAAOK,EAAE,IAAI,MAAM,wCAAwC,OAAO,UAAU,SAAS,KAAKL,CAAC,EAAE,mBAAmB,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,QAAQ,EAAE,EAAE,MAAM,MAAM,GAAG,EAAE,MAAM,OAAO,SAAS,CAAC,IAAIH,EAAE,EAAE,MAAM,MAAM,EAAE,MAAM,WAAWG,CAAC,EAAEA,EAAEO,EAAE,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,aAAY,EAAG,EAAEc,GAAE,IAAIA,GAAE,WAAWxB,EAAE,CAAC,EAAEM,EAAE,EAAE,MAAM,MAAM,EAAE,MAAM,iBAAiBI,CAAC,EAAEA,EAAE,EAAE,YAAY,MAAM,QAAQ,IAAI,KAAK,WAAWJ,EAAE,EAAE,UAAU,CAAC,EAAE,IAAIC,EAAE,MAAM,EAAE,MAAM,MAAM,EAAE,MAAM,gBAAgB,EAAEO,GAAE,MAAMA,GAAE,aAAaR,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,MAAM,EAAE,MAAM,YAAYC,CAAC,EAAEA,CAAC,KAAK,MAAMC,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQL,EAAE,EAAE,MAAM,WAAWA,CAAC,GAAG,IAAIM,GAAG,EAAE,MAAM,EAAE,MAAM,eAAe,EAAEe,GAAE,IAAIA,GAAE,WAAWrB,EAAE,CAAC,EAAE,EAAE,QAAQM,EAAE,EAAE,MAAM,iBAAiBA,CAAC,GAAG,EAAE,YAAY,KAAK,WAAWA,EAAE,EAAE,UAAU,EAAE,IAAIH,GAAG,EAAE,MAAM,EAAE,MAAM,cAAa,EAAG,EAAEQ,GAAE,MAAMA,GAAE,aAAaL,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQH,EAAE,EAAE,MAAM,YAAYA,CAAC,GAAGA,CAAC,OAAON,EAAE,CAAC,OAAOQ,EAAER,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,GAAG,CAAC,GAAG,EAAE,SAAS;AAAA,2DAC5iQ,EAAE,CAAC,IAAIE,EAAE,iCAAiCihB,GAAE,EAAE,QAAQ,GAAG,EAAE,EAAE,SAAS,OAAO,EAAE,QAAQ,QAAQjhB,CAAC,EAAEA,CAAC,CAAC,GAAG,EAAE,OAAO,QAAQ,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAMkB,GAAE,IAAIuB,GAAE,SAAShC,EAAEC,EAAEd,EAAE,CAAC,OAAOsB,GAAE,MAAMR,EAAEd,CAAC,CAAC,CAACa,EAAE,QAAQA,EAAE,WAAW,SAASC,EAAE,CAAC,OAAOQ,GAAE,WAAWR,CAAC,EAAED,EAAE,SAASS,GAAE,SAASmB,GAAE5B,EAAE,QAAQ,EAAEA,CAAC,EAAEA,EAAE,YAAYsB,GAAEtB,EAAE,SAAS6a,GAAE7a,EAAE,IAAI,YAAYC,EAAE,CAAC,OAAOQ,GAAE,IAAI,GAAGR,CAAC,EAAED,EAAE,SAASS,GAAE,SAASmB,GAAE5B,EAAE,QAAQ,EAAEA,CAAC,EAAEA,EAAE,WAAW,SAASC,EAAEd,EAAE,CAAC,OAAOsB,GAAE,WAAWR,EAAEd,CAAC,CAAC,EAAEa,EAAE,YAAYS,GAAE,YAAYT,EAAE,OAAOG,GAAEH,EAAE,OAAOG,GAAE,MAAMH,EAAE,SAASiB,GAAEjB,EAAE,aAAaY,GAAEZ,EAAE,MAAMa,GAAEb,EAAE,MAAMa,GAAE,IAAIb,EAAE,UAAUO,GAAEP,EAAE,MAAMN,GAAEM,EAAE,MAAMA,EAASA,EAAE,QAAWA,EAAE,WAAcA,EAAE,IAAOA,EAAE,WAAcA,EAAE,YAAoBG,GAAE,MAASU,GAAE,IClE1uB+vC,EAAO,WAAW,CAChB,IAAK,GACL,OAAQ,GACR,OAAQ,EACV,CAAC,EAED,MAAMC,GAAc,CAClB,IACA,IACA,aACA,KACA,OACA,MACA,KACA,KACA,KACA,KACA,KACA,KACA,IACA,KACA,KACA,IACA,MACA,SACA,QACA,QACA,KACA,KACA,QACA,KACA,IACF,EAEMC,GAAe,CAAC,QAAS,OAAQ,MAAO,SAAU,QAAS,OAAO,EAExE,IAAIC,GAAiB,GACrB,MAAMC,GAAsB,KACtBC,GAAuB,IACvBC,GAAuB,IACvBC,GAA2B,IAC3BC,OAAoB,IAE1B,SAASC,GAAkB/qC,EAA4B,CACrD,MAAMpD,EAASkuC,GAAc,IAAI9qC,CAAG,EACpC,OAAIpD,IAAW,OAAkB,MACjCkuC,GAAc,OAAO9qC,CAAG,EACxB8qC,GAAc,IAAI9qC,EAAKpD,CAAM,EACtBA,EACT,CAEA,SAASouC,GAAkBhrC,EAAahE,EAAe,CAErD,GADA8uC,GAAc,IAAI9qC,EAAKhE,CAAK,EACxB8uC,GAAc,MAAQF,GAAsB,OAChD,MAAMK,EAASH,GAAc,OAAO,OAAO,MACvCG,GAAQH,GAAc,OAAOG,CAAM,CACzC,CAEA,SAASC,IAAe,CAClBT,KACJA,GAAiB,GAEjB7L,GAAU,QAAQ,0BAA4BsF,GAAS,CACjD,EAAEA,aAAgB,oBAElB,CADSA,EAAK,aAAa,MAAM,IAErCA,EAAK,aAAa,MAAO,qBAAqB,EAC9CA,EAAK,aAAa,SAAU,QAAQ,EACtC,CAAC,EACH,CAEO,SAASiH,GAAwBC,EAA0B,CAChE,MAAMhvC,EAAQgvC,EAAS,OACvB,GAAI,CAAChvC,EAAO,MAAO,GAEnB,GADA8uC,GAAA,EACI9uC,EAAM,QAAUyuC,GAA0B,CAC5C,MAAMjuC,EAASmuC,GAAkB3uC,CAAK,EACtC,GAAIQ,IAAW,KAAM,OAAOA,CAC9B,CACA,MAAM2L,EAAYnG,GAAahG,EAAOsuC,EAAmB,EACnDrM,EAAS91B,EAAU,UACrB;;AAAA,eAAoBA,EAAU,KAAK,yBAAyBA,EAAU,KAAK,MAAM,KACjF,GACJ,GAAIA,EAAU,KAAK,OAASoiC,GAAsB,CAEhD,MAAMtiB,EAAO,2BADGgjB,GAAW,GAAG9iC,EAAU,IAAI,GAAG81B,CAAM,EAAE,CACR,SACzCiN,EAAY1M,GAAU,SAASvW,EAAM,CACzC,aAAckiB,GACd,aAAcC,EAAA,CACf,EACD,OAAIpuC,EAAM,QAAUyuC,IAClBG,GAAkB5uC,EAAOkvC,CAAS,EAE7BA,CACT,CACA,MAAMC,EAAWjB,EAAO,MAAM,GAAG/hC,EAAU,IAAI,GAAG81B,CAAM,EAAE,EACpDiN,EAAY1M,GAAU,SAAS2M,EAAU,CAC7C,aAAchB,GACd,aAAcC,EAAA,CACf,EACD,OAAIpuC,EAAM,QAAUyuC,IAClBG,GAAkB5uC,EAAOkvC,CAAS,EAE7BA,CACT,CAEA,SAASD,GAAWrvC,EAAuB,CACzC,OAAOA,EACJ,QAAQ,KAAM,OAAO,EACrB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,MAAM,EACpB,QAAQ,KAAM,QAAQ,EACtB,QAAQ,KAAM,OAAO,CAC1B,CClHA,MAAMwvC,GAAgB,KAChBC,GAAe,IACfC,GAAa,mBACbC,GAAe,SACfC,GAAc,cAOpB,eAAeC,GAAoB9rC,EAAgC,CACjE,GAAI,CAACA,EAAM,MAAO,GAElB,GAAI,CACF,aAAM,UAAU,UAAU,UAAUA,CAAI,EACjC,EACT,MAAQ,CAEN,GAAI,CACF,MAAM6sB,EAAK,SAAS,cAAc,UAAU,EAC5CA,EAAG,MAAQ7sB,EACX6sB,EAAG,MAAM,SAAW,QACpBA,EAAG,MAAM,QAAU,IACnB,SAAS,KAAK,YAAYA,CAAE,EAC5BA,EAAG,SACH,MAAMvF,EAAK,SAAS,YAAY,MAAM,EACtC,gBAAS,KAAK,YAAYuF,CAAE,EACrBvF,CACT,MAAQ,CACN,MAAO,EACT,CACF,CACF,CAEA,SAASykB,GAAeC,EAA2BjpC,EAAe,CAChEipC,EAAO,MAAQjpC,EACfipC,EAAO,aAAa,aAAcjpC,CAAK,CACzC,CAEA,SAASkpC,GAAiB/qC,EAA4C,CACpE,MAAMgrC,EAAYhrC,EAAQ,OAASyqC,GACnC,OAAOrjB;AAAAA;AAAAA;AAAAA;AAAAA,cAIK4jB,CAAS;AAAA,mBACJA,CAAS;AAAA,eACb,MAAOpzC,GAAa,CAC3B,MAAM8zB,EAAM9zB,EAAE,cAKd,GAJsB8zB,GAAA,MAAAA,EAAK,cACzB,wBAGE,CAACA,GAAOA,EAAI,QAAQ,UAAY,IAAK,OAEzCA,EAAI,QAAQ,QAAU,IACtBA,EAAI,aAAa,YAAa,MAAM,EACpCA,EAAI,SAAW,GAEf,MAAMuf,EAAS,MAAML,GAAoB5qC,EAAQ,MAAM,EACvD,GAAK0rB,EAAI,YAMT,IAJA,OAAOA,EAAI,QAAQ,QACnBA,EAAI,gBAAgB,WAAW,EAC/BA,EAAI,SAAW,GAEX,CAACuf,EAAQ,CACXvf,EAAI,QAAQ,MAAQ,IACpBmf,GAAenf,EAAKif,EAAW,EAE/B,OAAO,WAAW,IAAM,CACjBjf,EAAI,cACT,OAAOA,EAAI,QAAQ,MACnBmf,GAAenf,EAAKsf,CAAS,EAC/B,EAAGR,EAAY,EACf,MACF,CAEA9e,EAAI,QAAQ,OAAS,IACrBmf,GAAenf,EAAKgf,EAAY,EAEhC,OAAO,WAAW,IAAM,CACjBhf,EAAI,cACT,OAAOA,EAAI,QAAQ,OACnBmf,GAAenf,EAAKsf,CAAS,EAC/B,EAAGT,EAAa,EAClB,CAAC;AAAA;AAAA;AAAA,iDAG0CpjB,EAAM,IAAI;AAAA,kDACTA,EAAM,KAAK;AAAA;AAAA;AAAA,GAI7D,CAEO,SAAS+jB,GAA2Bf,EAAkC,CAC3E,OAAOY,GAAiB,CAAE,KAAM,IAAMZ,EAAU,MAAOM,GAAY,CACrE,CCzFO,SAASU,GAAiBnpC,EAA8B,CAC7D,MAAM7I,EAAI6I,EACJE,EAAUkpC,GAAiBjyC,EAAE,OAAO,EACpCkyC,EAAoB,GAE1B,UAAWlpC,KAAQD,EAAS,CAC1B,MAAMopC,EAAO,OAAOnpC,EAAK,MAAQ,EAAE,EAAE,eAEnC,CAAC,WAAY,YAAa,UAAW,UAAU,EAAE,SAASmpC,CAAI,GAC7D,OAAOnpC,EAAK,MAAS,UAAYA,EAAK,WAAa,OAEpDkpC,EAAM,KAAK,CACT,KAAM,OACN,KAAOlpC,EAAK,MAAmB,OAC/B,KAAMopC,GAAWppC,EAAK,WAAaA,EAAK,IAAI,EAC7C,CAEL,CAEA,UAAWA,KAAQD,EAAS,CAC1B,MAAMopC,EAAO,OAAOnpC,EAAK,MAAQ,EAAE,EAAE,cACrC,GAAImpC,IAAS,cAAgBA,IAAS,cAAe,SACrD,MAAMxsC,EAAO0sC,GAAgBrpC,CAAI,EAC3B/G,EAAO,OAAO+G,EAAK,MAAS,SAAWA,EAAK,KAAO,OACzDkpC,EAAM,KAAK,CAAE,KAAM,SAAU,KAAAjwC,EAAM,KAAA0D,EAAM,CAC3C,CAEA,GACEmF,GAAoBjC,CAAO,GAC3B,CAACqpC,EAAM,KAAMI,GAASA,EAAK,OAAS,QAAQ,EAC5C,CACA,MAAMrwC,EACH,OAAOjC,EAAE,UAAa,UAAYA,EAAE,UACpC,OAAOA,EAAE,WAAc,UAAYA,EAAE,WACtC,OACI2F,EAAOuD,GAAkBL,CAAO,GAAK,OAC3CqpC,EAAM,KAAK,CAAE,KAAM,SAAU,KAAAjwC,EAAM,KAAA0D,EAAM,CAC3C,CAEA,OAAOusC,CACT,CAqEA,SAASD,GAAiBlpC,EAAkD,CAC1E,OAAK,MAAM,QAAQA,CAAO,EACnBA,EAAQ,OAAO,OAAO,EADO,EAEtC,CAEA,SAASqpC,GAAWxwC,EAAyB,CAC3C,GAAI,OAAOA,GAAU,SAAU,OAAOA,EACtC,MAAME,EAAUF,EAAM,OAEtB,GADI,CAACE,GACD,CAACA,EAAQ,WAAW,GAAG,GAAK,CAACA,EAAQ,WAAW,GAAG,EAAG,OAAOF,EACjE,GAAI,CACF,OAAO,KAAK,MAAME,CAAO,CAC3B,MAAQ,CACN,OAAOF,CACT,CACF,CAEA,SAASywC,GAAgBrpC,EAAmD,CAC1E,GAAI,OAAOA,EAAK,MAAS,gBAAiBA,EAAK,KAC/C,GAAI,OAAOA,EAAK,SAAY,gBAAiBA,EAAK,OAEpD,CCjIA,MAAMupC,GAAgB,GAChBC,OAAoB,IAE1B,eAAeC,GAAgB5hC,EAAgC,CAC7D,MAAMrO,EAASgwC,GAAc,IAAI3hC,CAAG,EACpC,GAAIrO,EAAQ,OAAOA,EAEnB,GAAI,CACF,MAAMkwC,EAAM,IAAK,OAAO,cAAiB,OAAe,oBAElD16B,EAAM,MADA,MAAM,MAAMnH,CAAG,GACL,cAEhBhM,GADU,MAAM6tC,EAAI,gBAAgB16B,CAAG,GACzB,eAAe,CAAC,EAE9Byb,EAAO,KAAK,MAAM5uB,EAAI,OAAS0tC,EAAa,EAC5CI,EAAkB,GACxB,QAAS5zC,EAAI,EAAGA,EAAIwzC,GAAexzC,IAAK,CACtC,IAAIgJ,EAAM,EACV,MAAM6qC,EAAQ7zC,EAAI00B,EACZof,EAAM,KAAK,IAAID,EAAQnf,EAAM5uB,EAAI,MAAM,EAC7C,QAASxD,EAAIuxC,EAAOvxC,EAAIwxC,EAAKxxC,IAAK,CAChC,MAAMvB,EAAI,KAAK,IAAI+E,EAAIxD,CAAC,CAAC,EACrBvB,EAAIiI,IAAKA,EAAMjI,EACrB,CACA6yC,EAAM,KAAK5qC,CAAG,CAChB,CAEA,MAAM+qC,EAAO,KAAK,IAAI,GAAGH,EAAO,GAAI,EAC9BzxB,EAAayxB,EAAM,IAAK7yC,GAAM,KAAK,IAAIA,EAAIgzC,EAAM,GAAI,CAAC,EAC5D,OAAAN,GAAc,IAAI3hC,EAAKqQ,CAAU,EAC5BwxB,EAAI,QACFxxB,CACT,MAAQ,CAEN,MAAM7C,EAAO,MAAM,KAAKxN,CAAG,EAAE,OAAO,CAAC3R,EAAGD,KAAQC,GAAK,GAAKA,EAAID,EAAE,WAAW,CAAC,EAAK,EAAG,CAAC,EAC/E8zC,EAAiB,GACvB,QAASh0C,EAAI,EAAGA,EAAIwzC,GAAexzC,IAAK,CACtC,MAAMugB,EAAO,KAAK,KAAMjB,GAAQtf,EAAI,GAAK,KAAO,OAAS,OAAU,MAAM,EACzEg0C,EAAK,KAAK,IAAOzzB,EAAO,GAAI,CAC9B,CACA,OAAAkzB,GAAc,IAAI3hC,EAAKkiC,CAAI,EACpBA,CACT,CACF,CAaA,MAAMC,GAAS,CAAC,EAAG,IAAK,CAAC,EACnBC,OAAmB,IAEzB,SAASC,GAAiBriC,EAA0B,CAClD,IAAItF,EAAQ0nC,GAAa,IAAIpiC,CAAG,EAChC,GAAItF,EAAO,OAAOA,EAElB,MAAM4nC,EAAQ,IAAI,MAClB,OAAAA,EAAM,QAAU,WAChBA,EAAM,IAAMtiC,EAEZtF,EAAQ,CACN,MAAA4nC,EACA,QAAS,GACT,YAAa,EACb,SAAU,EACV,MAAO,EACP,SAAU,EAAC,EAGbF,GAAa,IAAIpiC,EAAKtF,CAAK,EAG3BknC,GAAgB5hC,CAAG,EAAE,KAAMiP,GAAM,CAC/BvU,EAAO,SAAWuU,EAClBszB,GAAcviC,CAAG,CACnB,CAAC,EAEMtF,CACT,CAIA,MAAM8nC,GAAS,6BAEf,SAASC,IAA+B,CACtC,MAAMxQ,EAAM,SAAS,gBAAgBuQ,GAAQ,KAAK,EAClDvQ,EAAI,aAAa,UAAW,WAAW,EACvCA,EAAI,aAAa,OAAQ,cAAc,EACvC,MAAMyQ,EAAO,SAAS,gBAAgBF,GAAQ,SAAS,EACvD,OAAAE,EAAK,aAAa,SAAU,gBAAgB,EAC5CzQ,EAAI,YAAYyQ,CAAI,EACbzQ,CACT,CAEA,SAAS0Q,IAAgC,CACvC,MAAM1Q,EAAM,SAAS,gBAAgBuQ,GAAQ,KAAK,EAClDvQ,EAAI,aAAa,UAAW,WAAW,EACvCA,EAAI,aAAa,OAAQ,cAAc,EACvC,MAAM2Q,EAAK,SAAS,gBAAgBJ,GAAQ,MAAM,EAClDI,EAAG,aAAa,IAAK,GAAG,EAAGA,EAAG,aAAa,IAAK,GAAG,EACnDA,EAAG,aAAa,QAAS,GAAG,EAAGA,EAAG,aAAa,SAAU,IAAI,EAAGA,EAAG,aAAa,KAAM,GAAG,EACzF,MAAMC,EAAK,SAAS,gBAAgBL,GAAQ,MAAM,EAClD,OAAAK,EAAG,aAAa,IAAK,IAAI,EAAGA,EAAG,aAAa,IAAK,GAAG,EACpDA,EAAG,aAAa,QAAS,GAAG,EAAGA,EAAG,aAAa,SAAU,IAAI,EAAGA,EAAG,aAAa,KAAM,GAAG,EACzF5Q,EAAI,OAAO2Q,EAAIC,CAAE,EACV5Q,CACT,CAIA,SAAS6Q,GAAc9iC,EAAiC,CACtD,OAAO,SAAS,cAAc,kBAAkB,IAAI,OAAOA,CAAG,CAAC,IAAI,CACrE,CAEA,SAASuiC,GAAcviC,EAAa,CAClC,MAAMnB,EAAYikC,GAAc9iC,CAAG,EACnC,GAAI,CAACnB,EAAW,OAChB,MAAMnE,EAAQ0nC,GAAa,IAAIpiC,CAAG,EAClC,GAAI,CAACtF,GAASA,EAAM,SAAS,SAAW,EAAG,OAE3C,MAAMqoC,EAAalkC,EAAU,cAAc,gBAAgB,EAC3D,GAAKkkC,EAGL,IAAIA,EAAW,SAAS,SAAW,EAAG,CACpC,MAAMC,EAAO,SAAS,yBACtB,UAAW30C,KAAKqM,EAAM,SAAU,CAC9B,MAAMuoC,EAAM,SAAS,cAAc,MAAM,EACzCA,EAAI,UAAY,WAChBA,EAAI,MAAM,OAAS,GAAG,KAAK,MAAM50C,EAAI,GAAG,CAAC,IACzC20C,EAAK,YAAYC,CAAG,CACtB,CACAF,EAAW,YAAYC,CAAI,CAC7B,CAEAE,GAAerkC,EAAWnE,CAAK,EACjC,CAEA,SAASwoC,GAAerkC,EAAwBnE,EAAoB,CAClE,MAAM+uB,EAAW/uB,EAAM,SAAW,EAAIA,EAAM,YAAcA,EAAM,SAAW,EACrEwnC,EAAOrjC,EAAU,iBAAiB,WAAW,EAC7CskC,EAAWjB,EAAK,OACtBA,EAAK,QAAQ,CAACe,EAAK/0C,IAAM,CACvB+0C,EAAI,UAAU,OAAO,mBAAoB/0C,EAAIi1C,EAAW1Z,CAAQ,CAClE,CAAC,EAED,MAAM2Z,EAASvkC,EAAU,cAAc,YAAY,EAC/CukC,IACFA,EAAO,YACL1oC,EAAM,SAAWA,EAAM,YAAc,EACjC2oC,GAAW3oC,EAAM,WAAW,EAC5B2oC,GAAW3oC,EAAM,QAAQ,EAEnC,CAEA,SAAS4oC,GAAezkC,EAAwB0kC,EAAkB,CAChE,MAAM7hB,EAAM7iB,EAAU,cAAc,YAAY,EAChD,GAAI,CAAC6iB,EAAK,OAEV,MAAM8hB,EAAS9hB,EAAI,cAAc,KAAK,EAChC+hB,EAASF,EAAUZ,GAAA,EAAmBF,GAAA,EACxCe,EACF9hB,EAAI,aAAa+hB,EAAQD,CAAM,EAE/B9hB,EAAI,YAAY+hB,CAAM,CAE1B,CAIA,SAASJ,GAAWK,EAAyB,CAC3C,GAAI,CAAC,SAASA,CAAO,GAAKA,EAAU,EAAG,MAAO,OAC9C,MAAMv0C,EAAI,KAAK,MAAMu0C,EAAU,EAAE,EAC3B71C,EAAI,KAAK,MAAM61C,EAAU,EAAE,EACjC,MAAO,GAAGv0C,CAAC,IAAItB,EAAE,WAAW,SAAS,EAAG,GAAG,CAAC,EAC9C,CAIA,MAAM81C,OAAgB,IAEtB,SAASC,GAAgB5jC,EAAa,CACpC,GAAI2jC,GAAU,IAAI3jC,CAAG,EAAG,OACxB2jC,GAAU,IAAI3jC,CAAG,EAEjB,MAAMtF,EAAQ0nC,GAAa,IAAIpiC,CAAG,EAClC,GAAI,CAACtF,EAAO,OACZ,KAAM,CAAE,MAAA4nC,GAAU5nC,EAElB4nC,EAAM,iBAAiB,iBAAkB,IAAM,CAC7C5nC,EAAM,SAAW4nC,EAAM,SACvB,MAAMzjC,EAAYikC,GAAc9iC,CAAG,EAC/BnB,GAAWqkC,GAAerkC,EAAWnE,CAAK,CAChD,CAAC,EAED4nC,EAAM,iBAAiB,aAAc,IAAM,CACzC5nC,EAAM,YAAc4nC,EAAM,YAC1B,MAAMzjC,EAAYikC,GAAc9iC,CAAG,EAC/BnB,GAAWqkC,GAAerkC,EAAWnE,CAAK,CAChD,CAAC,EAED4nC,EAAM,iBAAiB,QAAS,IAAM,CACpC5nC,EAAM,QAAU,GAChB4nC,EAAM,YAAc,EACpB5nC,EAAM,YAAc,EACpB,MAAMmE,EAAYikC,GAAc9iC,CAAG,EAC/BnB,IACFqkC,GAAerkC,EAAWnE,CAAK,EAC/B4oC,GAAezkC,EAAW,EAAK,EAEnC,CAAC,EAEDyjC,EAAM,iBAAiB,QAAS,IAAM,CACpC5nC,EAAM,QAAU,GAChB,MAAMmE,EAAYikC,GAAc9iC,CAAG,EAC/BnB,GAAWykC,GAAezkC,EAAW,EAAK,CAChD,CAAC,EAEDyjC,EAAM,iBAAiB,OAAQ,IAAM,CACnC5nC,EAAM,QAAU,GAChB,MAAMmE,EAAYikC,GAAc9iC,CAAG,EAC/BnB,GAAWykC,GAAezkC,EAAW,EAAI,CAC/C,CAAC,CACH,CAIO,SAASglC,GAAsB7jC,EAAa5O,EAAc,CAC/D,MAAMsJ,EAAQ2nC,GAAiBriC,CAAG,EAClC4jC,GAAgB5jC,CAAG,EAEnB,MAAM8jC,EAAcl2C,GAAa,CAC/BA,EAAE,kBACE8M,EAAM,QACRA,EAAM,MAAM,QAEPA,EAAM,MAAM,MAErB,EAEMqpC,EAAcn2C,GAAa,CAC/BA,EAAE,kBACF,MAAM0I,EAAM6rC,GAAO,QAAQznC,EAAM,KAAK,EAChCnG,EAAO4tC,IAAQ7rC,EAAM,GAAK6rC,GAAO,MAAM,EAC7CznC,EAAM,MAAQnG,EACdmG,EAAM,MAAM,aAAenG,EAC3B,MAAMmtB,EAAO9zB,EAAE,OAAuB,QAAQ,aAAa,EACvD8zB,IAAKA,EAAI,YAAc,GAAGntB,CAAI,IACpC,EAEMyvC,EAAiBp2C,GAAkB,CACvCA,EAAE,kBACF,MAAMmR,EAAUnR,EAAE,OAAuB,QAAQ,gBAAgB,EACjE,GAAI,CAACmR,EAAQ,OACb,MAAMqX,EAAOrX,EAAO,wBACdklC,EAAQ,KAAK,IAAI,EAAG,KAAK,IAAI,GAAIr2C,EAAE,QAAUwoB,EAAK,MAAQA,EAAK,KAAK,CAAC,EAC3E,GAAI1b,EAAM,SAAW,EAAG,CACtBA,EAAM,MAAM,YAAcupC,EAAQvpC,EAAM,SACxCA,EAAM,YAAcA,EAAM,MAAM,YAChC,MAAMmE,EAAYE,EAAO,QAAQ,MAAM,EACnCF,GAAWqkC,GAAerkC,EAAWnE,CAAK,CAChD,CACF,EAEMwpC,EACJxpC,EAAM,SAAWA,EAAM,YAAc,EACjC2oC,GAAW3oC,EAAM,WAAW,EAC5B2oC,GAAW3oC,EAAM,QAAQ,EAI/B,sBAAe,IAAM6nC,GAAcviC,CAAG,CAAC,EAEhCod;AAAAA,gCACuBpd,CAAG,WAAYpS,GAAaA,EAAE,iBAAiB;AAAA,yCACtCk2C,CAAU,eAAeppC,EAAM,QAAU,QAAU,MAAM;AAAA,UACxFA,EAAM,QAAUypC,GAAA,EAAcC,IAAU;AAAA;;AAAA;AAAA,4CAINJ,CAAa;;AAAA;AAAA,oCAGrBE,CAAO;AAAA,8CACGH,CAAU,IAAIrpC,EAAM,KAAK;AAAA,YAC3DtJ,EACEgsB,8BAAiCpd,CAAG,8CAA8C5O,CAAI,OACtF+sB,CAAO;AAAA;AAAA;AAAA;AAAA,GAKrB,CAIA,SAASimB,IAAW,CAClB,OAAOhnB,yFACT,CAEA,SAAS+mB,IAAY,CACnB,OAAO/mB,uJACT,CCxSA,SAASinB,GAAcrsC,EAAgC,OAErD,MAAME,EADIF,EACQ,QACZssC,EAAuB,GAE7B,GAAI,MAAM,QAAQpsC,CAAO,EACvB,UAAWqsC,KAASrsC,EAAS,CAC3B,GAAI,OAAOqsC,GAAU,UAAYA,IAAU,KAAM,SACjD,MAAM31C,EAAI21C,EAEV,GAAI31C,EAAE,OAAS,QAEb,KAAKE,EAAAF,EAAE,SAAF,YAAAE,EAAkD,QAAS,SAAU,CACxE,MAAM01C,EAAS51C,EAAE,OACXuP,EAAOqmC,EAAO,KACdC,EAAaD,EAAO,YAAyB,YAC7CxkC,EAAM7B,EAAK,WAAW,OAAO,EAC/BA,EACA,QAAQsmC,CAAS,WAAWtmC,CAAI,GACpCmmC,EAAO,KAAK,CAAE,IAAAtkC,EAAK,CAErB,SAAW,OAAOpR,EAAE,MAAS,UAAYA,EAAE,KAAM,CAC/C,MAAMuP,EAAOvP,EAAE,KACT81C,EAAY91C,EAAE,UAAwBA,EAAE,YAAyB,YACjEoR,EAAM7B,EAAK,WAAW,OAAO,EAC/BA,EACA,QAAQumC,CAAQ,WAAWvmC,CAAI,GACnCmmC,EAAO,KAAK,CAAE,IAAAtkC,EAAK,CACrB,MAAW,OAAOpR,EAAE,KAAQ,UAC1B01C,EAAO,KAAK,CAAE,IAAK11C,EAAE,IAAK,UAEnBA,EAAE,OAAS,YAAa,CAEjC,MAAM+1C,EAAW/1C,EAAE,UACf,OAAO+1C,GAAA,YAAAA,EAAU,MAAQ,UAC3BL,EAAO,KAAK,CAAE,IAAKK,EAAS,IAAK,CAErC,CACF,CAGF,OAAOL,CACT,CAEA,SAASM,GAAa5sC,EAA+B,CAEnD,MAAME,EADIF,EACQ,QACZ+f,EAAqB,GAE3B,GAAI,MAAM,QAAQ7f,CAAO,EACvB,UAAWqsC,KAASrsC,EAAS,CAC3B,GAAI,OAAOqsC,GAAU,UAAYA,IAAU,KAAM,SACjD,MAAM31C,EAAI21C,EAER31C,EAAE,OAAS,QACX,OAAOA,EAAE,KAAQ,UACjB,OAAOA,EAAE,MAAS,UAElBmpB,EAAM,KAAK,CACT,IAAKnpB,EAAE,IACP,KAAMA,EAAE,KACR,SAAWA,EAAE,UAAuB,2BACrC,CAEL,CAGF,OAAOmpB,CACT,CAEA,SAAS8sB,GAASH,EAA0B,CAC1C,OAAIA,IAAa,kBAA0B,KACvCA,EAAS,WAAW,QAAQ,EAAU,KACnC,IACT,CAEO,SAASI,GAA4BC,EAAgC,CAC1E,OAAO3nB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,GAWT,CAEO,SAAS4nB,GAAmBlwC,EAAc,CAC/C,OAAOsoB;AAAAA;AAAAA;AAAAA;AAAAA,YAIG6nB,GAAW/E,GAAwBprC,CAAI,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA,GAKrD,CAEO,SAASowC,GACdpwC,EACAqwC,EACAC,EACAL,EACA,CACA,OAAO3nB;AAAAA;AAAAA;AAAAA,UAGCioB,GACA,CACE,KAAM,YACN,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAAvwC,EAAM,EAChC,UAAWqwC,CAAA,EAEb,CAAE,YAAa,GAAO,cAAe,GAEvC,CAAC;AAAA;AAAA;AAAA,GAIT,CAEO,SAASG,GACdC,EACA5qC,EAMA,CACA,MAAM6qC,EAAiBzrC,GAAyBwrC,EAAM,IAAI,EACpDE,EACJD,IAAmB,OACf,OACAA,IAAmB,YACjB,YACA,QACF3rC,EAAY,IAAI,KAAK0rC,EAAM,SAAS,EAAE,eAAe,OAAW,CACpE,UAAW,SACX,UAAW,SACZ,EAIKjF,EAAWiF,EAAM,SAAS,IAAI,CAACptC,EAAMg5B,IACzCkU,GACEltC,EAAK,QACL,CACE,YACEotC,EAAM,aAAepU,IAAUoU,EAAM,SAAS,OAAS,EACzD,cAAe5qC,EAAK,cAGxB,GAEF,OAAI2lC,EAAS,MAAOtyC,GAAMA,IAAMmwB,CAAO,EAAUA,EAE1Cf;AAAAA,6BACoBqoB,CAAS;AAAA;AAAA,UAE5BnF,CAAQ;AAAA;AAAA,+CAE6BzmC,CAAS;AAAA;AAAA;AAAA;AAAA,GAKxD,CAEA,SAAS6rC,GAAoBpB,EAAsB,CACjD,OAAIA,EAAO,SAAW,EAAUnmB,EAEzBf;AAAAA;AAAAA,QAEDknB,EAAO,IACNqB,GAAQvoB;AAAAA;AAAAA,kBAECuoB,EAAI,GAAG;AAAA,kBACPA,EAAI,KAAO,gBAAgB;AAAA;AAAA,qBAExB,IAAM,OAAO,KAAKA,EAAI,IAAK,QAAQ,CAAC;AAAA;AAAA,UAGlD;AAAA;AAAA,GAGP,CAEA,SAASC,GAAmB7tB,EAAoB,CAC9C,OAAIA,EAAM,SAAW,EAAUoG,EAExBf;AAAAA;AAAAA,QAEDrF,EAAM,IAAKppB,GACXA,EAAE,WAAa,kBACXk3C,GAAiBl3C,CAAC,EAClBA,EAAE,SAAS,WAAW,QAAQ,EAC5Bk1C,GAAsBl1C,EAAE,IAAKA,EAAE,IAAI,EACnCm3C,GAAen3C,CAAC,EACvB;AAAA;AAAA,GAGP,CAEA,SAASo3C,GAAa/lC,EAAa5O,EAAc,CAC/C,MAAM40C,EAAU,SAAS,cAAc,KAAK,EAC5CA,EAAQ,UAAY,yBAEpB,MAAMpnB,EAAQ,SAAS,cAAc,KAAK,EAC1CA,EAAM,UAAY,iBAGlB,MAAMhnB,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,UAAY,yBAEnB,MAAM+O,EAAQ,SAAS,cAAc,MAAM,EAC3CA,EAAM,UAAY,wBAClBA,EAAM,YAAcvV,EAEpB,MAAM60C,EAAW,SAAS,cAAc,GAAG,EAC3CA,EAAS,UAAY,uBACrBA,EAAS,KAAOjmC,EAChBimC,EAAS,OAAS,SAClBA,EAAS,IAAM,sBACfA,EAAS,YAAc,kBAEvB,MAAMC,EAAW,SAAS,cAAc,QAAQ,EAChDA,EAAS,UAAY,wBACrBA,EAAS,aAAa,aAAc,OAAO,EAC3C,MAAMjU,EAAM,SAAS,gBAAgB,6BAA8B,KAAK,EACxEA,EAAI,aAAa,UAAW,WAAW,EACvC,MAAMkU,EAAQ,SAAS,gBAAgB,6BAA8B,MAAM,EAC3EA,EAAM,aAAa,KAAM,IAAI,EAAGA,EAAM,aAAa,KAAM,GAAG,EAC5DA,EAAM,aAAa,KAAM,GAAG,EAAGA,EAAM,aAAa,KAAM,IAAI,EAC5D,MAAMC,EAAQ,SAAS,gBAAgB,6BAA8B,MAAM,EAC3EA,EAAM,aAAa,KAAM,GAAG,EAAGA,EAAM,aAAa,KAAM,GAAG,EAC3DA,EAAM,aAAa,KAAM,IAAI,EAAGA,EAAM,aAAa,KAAM,IAAI,EAC7DnU,EAAI,OAAOkU,EAAOC,CAAK,EACvBF,EAAS,YAAYjU,CAAG,EAExBr6B,EAAO,OAAO+O,EAAOs/B,EAAUC,CAAQ,EAGvC,MAAMG,EAAQ,SAAS,cAAc,QAAQ,EAC7CA,EAAM,UAAY,wBAClBA,EAAM,IAAMrmC,EACZqmC,EAAM,MAAQj1C,EAEdwtB,EAAM,OAAOhnB,EAAQyuC,CAAK,EAC1BL,EAAQ,YAAYpnB,CAAK,EAEzBonB,EAAQ,iBAAiB,QAAUp4C,GAAM,CACnCA,EAAE,SAAWo4C,GAASA,EAAQ,QACpC,CAAC,EACDE,EAAS,iBAAiB,QAAS,IAAMF,EAAQ,QAAQ,EACzD,SAAS,KAAK,YAAYA,CAAO,CACnC,CAEA,SAASH,GAAiBl3C,EAAc,CACtC,OAAOyuB;AAAAA,2CACkC,IAAM2oB,GAAap3C,EAAE,IAAKA,EAAE,IAAI,CAAC;AAAA;AAAA,cAE9DA,EAAE,GAAG;AAAA;AAAA,gBAEHA,EAAE,IAAI;AAAA;AAAA;AAAA;AAAA,eAIPA,EAAE,GAAG;AAAA;AAAA;AAAA,iBAGFf,GAAaA,EAAE,iBAAiB;AAAA,SACzCe,EAAE,IAAI;AAAA;AAAA,GAGf,CAGA,SAASm3C,GAAen3C,EAAc,CACpC,OAAOyuB;AAAAA;AAAAA;AAAAA,aAGIzuB,EAAE,GAAG;AAAA;AAAA;AAAA;AAAA,2CAIyBk2C,GAASl2C,EAAE,QAAQ,CAAC;AAAA,2CACpBA,EAAE,IAAI;AAAA;AAAA,GAGjD,CAEA,SAAS02C,GACPrtC,EACA2C,EACAyqC,EACA,CACA,MAAMj2C,EAAI6I,EACJC,EAAO,OAAO9I,EAAE,MAAS,SAAWA,EAAE,KAAO,UAC7Cm3C,EACJrsC,GAAoBjC,CAAO,GAC3BC,EAAK,gBAAkB,cACvBA,EAAK,gBAAkB,eACvB,OAAO9I,EAAE,YAAe,UACxB,OAAOA,EAAE,cAAiB,SAGtBo3C,EADYpF,GAAiBnpC,CAAO,EACX,OAAS,EAClCssC,EAASD,GAAcrsC,CAAO,EAC9BwuC,EAAYlC,EAAO,OAAS,EAC5BvsB,EAAQ6sB,GAAa5sC,CAAO,EAC5ByuC,EAAW1uB,EAAM,OAAS,EAE1B2uB,EAAgBruC,GAAkBL,CAAO,EACzC2uC,EACJhsC,EAAK,eAAiB1C,IAAS,YAC3BU,GAAsBX,CAAO,EAC7B,KACA4uC,EAAeF,GAAA,MAAAA,EAAe,OAASA,EAAgB,KACvDG,EAAoBF,EACtB/tC,GAAwB+tC,CAAiB,EACzC,KACExG,EAAWyG,EACXE,GAAmB7uC,IAAS,aAAeA,IAAS,SAAW,GAAQkoC,GAAA,MAAAA,EAAU,QAEjF4G,EAAgB,CACpB,cACAD,EAAkB,WAAa,GAC/BnsC,EAAK,YAAc,YAAc,GACjC,WAEC,OAAO,OAAO,EACd,KAAK,GAAG,EAKX,MAFI,CAACwlC,IAAaoG,GAAgBD,IAE9B,CAACnG,GAAY,CAACqG,GAAa,CAACC,EAAiBtoB,EAE1Cf;AAAAA,kBACS2pB,CAAa;AAAA,QACvBD,EAAkB5F,GAA2Bf,CAAS,EAAIhiB,CAAO;AAAA,QACjEunB,GAAoBpB,CAAM,CAAC;AAAA,QAC3BsB,GAAmB7tB,CAAK,CAAC;AAAA,QACzB8uB,EACEzpB,+BAAkC6nB,GAChC/E,GAAwB2G,CAAiB,EAC1C,SACD1oB,CAAO;AAAA,QACTgiB,EACE/iB,2BAA8B6nB,GAAW/E,GAAwBC,CAAQ,CAAC,CAAC,SAC3EhiB,CAAO;AAAA;AAAA,GAGjB,CClWA,MAAMzjB,EAAuB,CAC3B,OAAQ,GACR,KAAM,MACN,UAAW,EACX,QAAS,EACT,cAAe,KACf,YAAa,GACb,OAAQ,KACR,QAAS,KACT,OAAQ,EACR,UAAW,EACb,EAEA,IAAIssC,EAA2C,KAG3CC,GAAkD,KAClDC,GAAc,GAElB,SAASnc,GAAe2Y,EAAyB,CAC/C,MAAMv0C,EAAI,KAAK,MAAMu0C,EAAU,EAAE,EAC3B71C,EAAI61C,EAAU,GACpB,MAAO,GAAGv0C,CAAC,IAAItB,EAAE,WAAW,SAAS,EAAG,GAAG,CAAC,EAC9C,CAEA,SAASs5C,IAAU,CAKjB,GAJIzsC,EAAM,UACR,cAAcA,EAAM,OAAO,EAC3BA,EAAM,QAAU,MAEdA,EAAM,OAAQ,CAChB,UAAW0sC,KAAS1sC,EAAM,OAAO,cAAmB,OACpDA,EAAM,OAAS,IACjB,CACIusC,KACF,aAAaA,EAAS,EACtBA,GAAY,MAEdI,GAAA,EACA3sC,EAAM,cAAgB,KACtBA,EAAM,YAAc,GACpBA,EAAM,OAAS,GACfA,EAAM,UAAY,GAClBwsC,GAAc,EAChB,CAEA,eAAeI,GAAexxC,EAAwC,OACpE,GAAI,CACF,GAAI,GAAChH,EAAA,UAAU,eAAV,MAAAA,EAAwB,cAC3B,eAAQ,KAAK,4DAA4D,EACzEq4C,GAAA,EACO,GAGT,MAAMI,EAAS,MAAM,UAAU,aAAa,aAAa,CAAE,MAAO,GAAM,EACxE7sC,EAAM,OAAS6sC,EAGf,MAAM7C,EAAW,cAAc,gBAAgB,wBAAwB,EACnE,yBACA,cAAc,gBAAgB,WAAW,EACvC,YACA,GAEA8C,EAAW9C,EACb,IAAI,cAAc6C,EAAQ,CAAE,SAAA7C,EAAU,EACtC,IAAI,cAAc6C,CAAM,EAE5B,OAAA7sC,EAAM,cAAgB8sC,EACtB9sC,EAAM,YAAc,GACpBA,EAAM,KAAO5E,EACb4E,EAAM,UAAY,KAAK,MACvBA,EAAM,QAAU,EAChBA,EAAM,OAAS,GACfA,EAAM,UAAY,GAElB8sC,EAAS,gBAAmB55C,GAAM,CAC5BA,EAAE,KAAK,KAAO,KAAS,YAAY,KAAKA,EAAE,IAAI,CACpD,EAEA45C,EAAS,OAAS,IAAM,CACtB,GAAI9sC,EAAM,UAAW,CACnBysC,GAAA,EACAH,GAAA,MAAAA,EAAW,kBACX,MACF,CAEA,MAAMjnC,EAAO,IAAI,KAAKrF,EAAM,YAAa,CAAE,KAAM8sC,EAAS,SAAU,EACpE,GAAIznC,EAAK,OAAS,EAAG,CACnBonC,GAAA,EACAH,GAAA,MAAAA,EAAW,kBACX,MACF,CAEA,MAAMS,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,CACpB,MAAMpsC,EAAUosC,EAAO,OACjBC,EAAMF,EAAS,SAAS,SAAS,KAAK,EAAI,MAAQ,OAClDG,EAA6B,CACjC,GAAIrtC,GAAA,EACJ,QAAAe,EACA,SAAUmsC,EAAS,UAAY,aAC/B,SAAU,cAAc,KAAK,KAAK,IAAIE,CAAG,IAE3CP,GAAA,EACAH,GAAA,MAAAA,EAAW,OAAOW,GAClBX,GAAA,MAAAA,EAAW,iBACb,EACAS,EAAO,QAAU,IAAM,CACrBN,GAAA,EACAH,GAAA,MAAAA,EAAW,iBACb,EACAS,EAAO,cAAc1nC,CAAI,CAC3B,EAEAynC,EAAS,MAAM,GAAG,EAElB9sC,EAAM,QAAU,YAAY,IAAM,CAChCA,EAAM,QAAU,KAAK,OAAO,KAAK,MAAQA,EAAM,WAAa,GAAI,EAChEssC,GAAA,MAAAA,EAAW,iBACb,EAAG,GAAI,EAEPA,GAAA,MAAAA,EAAW,kBACJ,EACT,OAAS/rC,EAAK,CACZ,eAAQ,KAAK,iCAAkCA,CAAG,EAClDksC,GAAA,EACO,EACT,CACF,CAEA,SAASS,IAAc,CACjB,CAACltC,EAAM,QAAU,CAACA,EAAM,gBAC5BA,EAAM,UAAY,GACdA,EAAM,cAAc,QAAU,aAChCA,EAAM,cAAc,OAExB,CAEA,SAASmtC,IAAkB,CACrB,CAACntC,EAAM,QAAU,CAACA,EAAM,gBAC5BA,EAAM,UAAY,GACdA,EAAM,cAAc,QAAU,YAChCA,EAAM,cAAc,QAEpBysC,GAAA,EACAH,GAAA,MAAAA,EAAW,mBAEf,CAOA,SAASc,IAAqB,CAC5B,SAAS,iBAAiB,YAAaC,EAAiB,CAC1D,CAEA,SAASV,IAAwB,CAC/B,SAAS,oBAAoB,YAAaU,EAAiB,CAC7D,CAEA,SAASA,GAAkB,EAAiB,CAC1C,GAAI,CAACb,IAAe,CAACxsC,EAAM,OAAQ,CACjC2sC,GAAA,EACA,MACF,CAKA,GAJAH,GAAc,GACdG,GAAA,EAGIJ,KACF,aAAaA,EAAS,EACtBA,GAAY,KACR,CAACvsC,EAAM,QAAQ,CACZ4sC,GAAe,KAAK,EACzB,MACF,CAIE5sC,EAAM,QAAUA,EAAM,OAAS,SAC7BA,EAAM,UACRmtC,GAAA,EAEAD,GAAA,GAIJ,EAAE,gBACJ,CAEA,SAASI,GAAiB,EAAiB,CACrCttC,EAAM,SACVwsC,GAAc,GACdxsC,EAAM,OAAS,EAAE,QAIjBotC,GAAA,EAGAb,GAAY,WAAW,SAAY,CACjC,GAAI,CAACC,GAAa,OACP,MAAMI,GAAe,MAAM,IAEpCJ,GAAc,GACdG,GAAA,EAEJ,EAAG,GAAG,EACR,CAEA,SAASY,GAAuB,EAAiB,CAC/C,GAAI,CAACvtC,EAAM,QAAUA,EAAM,OAAS,QAAU,CAACwsC,GAAa,OAC5D,MAAMgB,EAAKxtC,EAAM,OAAS,EAAE,QAExBwtC,EAAK,IACPxtC,EAAM,UAAY,GAClBssC,GAAA,MAAAA,EAAW,mBACFtsC,EAAM,WAAawtC,GAAM,KAClCxtC,EAAM,UAAY,GAClBssC,GAAA,MAAAA,EAAW,kBAEf,CAIO,SAASmB,IAAuB,CACrC,OAAOztC,EAAM,MACf,CAEO,SAAS0tC,GAAaC,EAA6B,CACxDrB,EAAYqB,CACd,CAGO,SAASC,GAAgBpb,EAAoC,CAClE,OAAO9P;AAAAA;AAAAA;AAAAA,kBAGS,CAAC8P,CAAS;AAAA,qBACP8a,EAAgB;AAAA;AAAA;AAAA;AAAA,QAI7B7qB,EAAM,GAAG;AAAA;AAAA,GAGjB,CAGO,SAASorB,IAAqD,CACnE,OAAK7tC,EAAM,OAEPA,EAAM,OAAS,MACV0iB;AAAAA,uDAC4C6qB,EAAsB;AAAA;AAAA;AAAA,mBAG1DJ,EAAe;AAAA;AAAA;AAAA;AAAA,YAItB1qB,EAAM,KAAK;AAAA;AAAA;AAAA;AAAA,sDAI+B4N,GAAerwB,EAAM,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA,mBAIhEktC,EAAW;AAAA;AAAA;AAAA;AAAA,YAIlBzqB,EAAM,IAAI;AAAA;AAAA;AAAA,MAObC;AAAAA,0DACiD6qB,EAAsB;AAAA;AAAA;AAAA,oDAG5Bld,GAAerwB,EAAM,OAAO,CAAC;AAAA,mDAC9BA,EAAM,UAAY,YAAc,EAAE;AAAA,YACzEA,EAAM,UAAY,oBAAsB,mBAAwB;AAAA;AAAA;AAAA;AAAA,IApChDyjB,CAyC5B,CCxTO,SAASqqB,GAAsBtpB,EAA6B,CACjE,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,yBAIgB8B,EAAM,OAAO;AAAA,YAC1B/B,EAAM,CAAC;AAAA;AAAA;AAAA;AAAA,UAIT+B,EAAM,MACJ9B;AAAAA,4CACgC8B,EAAM,KAAK;AAAA,+BACxBA,EAAM,aAAa;AAAA;AAAA;AAAA,cAItCA,EAAM,QACJ9B,kCAAqC6nB,GAAW/E,GAAwBhhB,EAAM,OAAO,CAAC,CAAC,SACvF9B,gDAAmD;AAAA;AAAA;AAAA,GAIjE,sMC5BO,IAAMqrB,GAAN,cAA+BC,EAAW,CAA1C,kCACuB,gBAAa,GACb,cAAW,GACX,cAAW,GAEvC,KAAQ,WAAa,GACrB,KAAQ,OAAS,EACjB,KAAQ,WAAa,EA8CrB,KAAQ,gBAAmB,GAAkB,CAC3C,KAAK,WAAa,GAClB,KAAK,OAAS,EAAE,QAChB,KAAK,WAAa,KAAK,WACvB,KAAK,UAAU,IAAI,UAAU,EAE7B,SAAS,iBAAiB,YAAa,KAAK,eAAe,EAC3D,SAAS,iBAAiB,UAAW,KAAK,aAAa,EAEvD,EAAE,gBACJ,EAEA,KAAQ,gBAAmB,GAAkB,CAC3C,GAAI,CAAC,KAAK,WAAY,OAEtB,MAAM7pC,EAAY,KAAK,cACvB,GAAI,CAACA,EAAW,OAEhB,MAAM8pC,EAAiB9pC,EAAU,wBAAwB,MAEnD+pC,GADS,EAAE,QAAU,KAAK,QACJD,EAE5B,IAAIE,EAAW,KAAK,WAAaD,EACjCC,EAAW,KAAK,IAAI,KAAK,SAAU,KAAK,IAAI,KAAK,SAAUA,CAAQ,CAAC,EAEpE,KAAK,cACH,IAAI,YAAY,SAAU,CACxB,OAAQ,CAAE,WAAYA,CAAA,EACtB,QAAS,GACT,SAAU,GACX,EAEL,EAEA,KAAQ,cAAgB,IAAM,CAC5B,KAAK,WAAa,GAClB,KAAK,UAAU,OAAO,UAAU,EAEhC,SAAS,oBAAoB,YAAa,KAAK,eAAe,EAC9D,SAAS,oBAAoB,UAAW,KAAK,aAAa,CAC5D,EAxDA,QAAS,CACP,OAAOzrB,GACT,CAEA,mBAAoB,CAClB,MAAM,oBACN,KAAK,iBAAiB,YAAa,KAAK,eAAe,CACzD,CAEA,sBAAuB,CACrB,MAAM,uBACN,KAAK,oBAAoB,YAAa,KAAK,eAAe,EAC1D,SAAS,oBAAoB,YAAa,KAAK,eAAe,EAC9D,SAAS,oBAAoB,UAAW,KAAK,aAAa,CAC5D,CA2CF,EA9FaqrB,GASJ,OAASK;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;;AAAAA;AAAAA;AAAAA;;AAAAA;AAAAA;AAAAA;AAAAA,IARYC,GAAA,CAA3BxX,GAAS,CAAE,KAAM,OAAQ,GADfkX,GACiB,0BACAM,GAAA,CAA3BxX,GAAS,CAAE,KAAM,OAAQ,GAFfkX,GAEiB,wBACAM,GAAA,CAA3BxX,GAAS,CAAE,KAAM,OAAQ,GAHfkX,GAGiB,wBAHjBA,GAANM,GAAA,CADNC,GAAc,mBAAmB,GACrBP,EAAA,ECRb,SAASQ,GAAsBC,EAAK,CAClC,GAAI,OAAOA,GAAQ,UAAY,CAACA,EAC9B,MAAM,IAAI,MAAM,qCAAuCA,CAAG,CAE9D,CAEA,SAASC,GAAcC,EAAQ,CAC7B,GAAI,OAAOA,GAAW,SACpB,MAAM,IAAI,MAAM,2BAA6BA,CAAM,CAEvD,CAEA,MAAMC,GAAqB,EACrBC,GAAqB,EACrBC,GAAc,QACdC,GAAiB,WACjBC,GAAkB,YAClBC,GAAe,SACfC,GAAe,SACfC,GAAgB,UAChBC,GAAc,QACdC,GAAc,QACdC,GAAc,QACdC,GAAwB,cACxBC,GAAW,OACXC,GAAU,MACVC,GAAyB,WACzBC,GAAgB,WAChBC,GAAiB,YACjBC,GAAqB,eACrBC,GAAqB,eAErBC,GAAsB,mFACtBC,GAAiB,KAGvB,SAASC,GAAQC,EAAKzb,EAAM,CAC1B,MAAM4B,EAAM,IAAI,IACVj2B,EAAM,GACZ,UAAW1C,KAAQwyC,EAAK,CACtB,MAAM51C,EAAMm6B,EAAK/2B,CAAI,EAChB24B,EAAI,IAAI/7B,CAAG,IACd+7B,EAAI,IAAI/7B,CAAG,EACX8F,EAAI,KAAK1C,CAAI,EAEjB,CACA,OAAO0C,CACT,CAEA,SAAS+vC,GAAWC,EAAQ,CAC1B,OAAOH,GAAOG,EAAQ37C,GAAKA,EAAE,OAAO,CACtC,CAEA,SAAS47C,GAAkBC,EAAI,CAC7B,SAASC,EAAmB55C,EAAM65C,EAASC,EAAS,CAClD,MAAMx5B,EAAQu5B,EACVF,EAAG,kBAAkB35C,EAAM,CAAE,QAAA65C,CAAO,CAAE,EACtCF,EAAG,kBAAkB35C,CAAI,EAC7B,GAAI85C,EACF,SAAW,CAACC,EAAW,CAACF,EAASG,CAAU,CAAC,IAAK,OAAO,QAAQF,CAAO,EACrEx5B,EAAM,YAAYy5B,EAAWF,EAAS,CAAE,WAAAG,CAAU,CAAE,EAGxD,OAAO15B,CACT,CAEAs5B,EAAkBxB,EAAc,EAChCwB,EAAkBzB,GAA2BK,GAAe,CAC1D,CAACD,EAAY,EAAG,CAACD,GAA+B,EAAI,EACpD,CAACM,EAAqB,EAAG,CAAC,CAACF,GAAaC,EAAW,CAAC,EACpD,CAACO,EAAkB,EAAG,CAACC,GAAqC,EAAI,CACpE,CAAG,EACDS,EAAkBvB,GAAiB,OAAW,CAC5C,CAACI,EAAW,EAAG,CAAC,EAAE,CACtB,CAAG,CACH,CAEA,MAAMwB,GAAwB,GACxBC,GAAgB,GAChBC,GAAmB,GAEzB,SAASC,GAAuBC,EAASC,EAAQC,EAAK,CAGpDA,EAAI,QAAU,IAAMD,EAAOC,EAAI,KAAK,EAEpCA,EAAI,UAAY,IAAMD,EAAO,IAAI,MAAM,aAAa,CAAC,EACrDC,EAAI,UAAY,IAAMF,EAAQE,EAAI,MAAM,CAC1C,CAEA,eAAeC,GAAgBC,EAAQ,CACrC,MAAMd,EAAK,MAAM,IAAI,QAAQ,CAACU,EAASC,IAAW,CAChD,MAAMC,EAAM,UAAU,KAAKE,EAAQxC,EAAkB,EACrDgC,GAAsBQ,CAAM,EAAIF,EAChCA,EAAI,gBAAkB/9C,GAAK,CAMrBA,EAAE,WAAa07C,IACjBwB,GAAiBa,EAAI,MAAM,CAE/B,EACAH,GAAsBC,EAASC,EAAQC,CAAG,CAC5C,CAAC,EAID,OAAAZ,EAAG,QAAU,IAAMe,GAAcD,CAAM,EAChCd,CACT,CAEA,SAASgB,GAAcF,EAAQ,CAC7B,OAAKP,GAAcO,CAAM,IACvBP,GAAcO,CAAM,EAAID,GAAeC,CAAM,GAExCP,GAAcO,CAAM,CAC7B,CAEA,SAASG,GAAWjB,EAAIkB,EAAWC,EAAqBxuB,EAAI,CAC1D,OAAO,IAAI,QAAQ,CAAC+tB,EAASC,IAAW,CAGtC,MAAMS,EAAMpB,EAAG,YAAYkB,EAAWC,EAAqB,CAAE,WAAY,UAAW,EAC9Ex6B,EAAQ,OAAOu6B,GAAc,SAC/BE,EAAI,YAAYF,CAAS,EACzBA,EAAU,IAAI76C,GAAQ+6C,EAAI,YAAY/6C,CAAI,CAAC,EAC/C,IAAIyJ,EACJ6iB,EAAGhM,EAAOy6B,EAAMj2C,GAAW,CACzB2E,EAAM3E,CACR,CAAC,EAEDi2C,EAAI,WAAa,IAAMV,EAAQ5wC,CAAG,EAElCsxC,EAAI,QAAU,IAAMT,EAAOS,EAAI,KAAK,CACtC,CAAC,CACH,CAEA,SAASL,GAAeD,EAAQ,CAE9B,MAAMF,EAAMN,GAAsBQ,CAAM,EAClCd,EAAKY,GAAOA,EAAI,OACtB,GAAIZ,EAAI,CACNA,EAAG,MAAK,EACR,MAAMqB,EAAYb,GAAiBM,CAAM,EAEzC,GAAIO,EACF,UAAWC,KAAYD,EACrBC,EAAQ,CAGd,CACA,OAAOhB,GAAsBQ,CAAM,EACnC,OAAOP,GAAcO,CAAM,EAC3B,OAAON,GAAiBM,CAAM,CAChC,CAEA,SAASS,GAAgBT,EAAQ,CAC/B,OAAO,IAAI,QAAQ,CAACJ,EAASC,IAAW,CAEtCI,GAAcD,CAAM,EACpB,MAAMF,EAAM,UAAU,eAAeE,CAAM,EAC3CL,GAAsBC,EAASC,EAAQC,CAAG,CAC5C,CAAC,CACH,CAKA,SAASY,GAAoBV,EAAQQ,EAAU,CAC7C,IAAID,EAAYb,GAAiBM,CAAM,EAClCO,IACHA,EAAYb,GAAiBM,CAAM,EAAI,IAEzCO,EAAU,KAAKC,CAAQ,CACzB,CAKA,MAAMG,GAAqB,IAAI,IAAI,CACjC,KAAM,KAAM,MAAO,MACnB,KAAM,KAAM,KAAM,KAClB,KAAM,KAAM,KAAM,KAClB,KAAM,KAAM,KAAM,KAClB,KAAM,MAAO,KAAM,KACnB,KAAM,KAAM,MAAO,KACnB,MAAO,KAAM,OAAQ,KACrB,IACF,CAAC,EAED,SAASC,GAAevD,EAAK,CAC3B,OAAOA,EACJ,MAAM,QAAQ,EACd,IAAIwD,GACC,CAACA,EAAK,MAAM,IAAI,GAAKF,GAAmB,IAAIE,CAAI,EAE3CA,EAAK,YAAW,EAGlBA,EACJ,QAAQ,UAAW,EAAE,EACrB,QAAQ,KAAM,GAAG,EACjB,YAAW,CACf,EAAE,OAAO,OAAO,CACrB,CAEA,MAAMC,GAAyB,EAO/B,SAASC,GAAiB1D,EAAK,CAC7B,OAAOA,EACJ,OAAO,OAAO,EACd,IAAIh6C,GAAKA,EAAE,YAAW,CAAE,EACxB,OAAOA,GAAKA,EAAE,QAAUy9C,EAAsB,CACnD,CAGA,SAASE,GAAoBC,EAAW,CAqCtC,OApCYA,EAAU,IAAI,CAAC,CAAE,WAAAC,EAAY,SAAAC,EAAU,MAAAzH,EAAO,MAAA0H,EAAO,WAAAC,EAAY,MAAAC,EAAO,KAAAC,EAAM,MAAAC,EAAO,QAAAC,CAAO,IAAO,CAC7G,MAAMC,EAAS,CAAC,GAAG,IAAI,IACrBX,GAAgB,CACd,IAAIM,GAAc,IAAI,IAAIT,EAAa,EAAE,KAAI,EAC7C,IAAIW,GAAQ,IAAI,IAAIX,EAAa,EAAE,KAAI,EACvC,GAAGA,GAAcM,CAAU,EAC3BC,CACR,CAAO,CACP,CAAK,EAAE,KAAI,EACDnyC,EAAM,CACV,WAAAkyC,EACA,MAAAxH,EACA,MAAA0H,EACA,KAAAG,EACA,OAAAG,EACA,QAASF,EACT,QAAAC,CACN,EAOI,GANIN,IACFnyC,EAAI,SAAWmyC,GAEbE,IACFryC,EAAI,WAAaqyC,GAEfC,EAAO,CACTtyC,EAAI,UAAY,GAChBA,EAAI,aAAe,GACnBA,EAAI,aAAe,GACnB,SAAW,CAAE,KAAA2yC,EAAM,MAAAH,EAAO,QAAAC,CAAO,IAAMH,EACrCtyC,EAAI,UAAU,KAAK2yC,CAAI,EACvB3yC,EAAI,aAAa,KAAKwyC,CAAK,EAC3BxyC,EAAI,aAAa,KAAKyyC,CAAO,CAEjC,CACA,OAAOzyC,CACT,CAAC,CAEH,CAIA,SAAS4yC,GAAW/7B,EAAOg8B,EAAQ34C,EAAK2oB,EAAI,CAC1ChM,EAAMg8B,CAAM,EAAE34C,CAAG,EAAE,UAAYnH,GAAM8vB,GAAMA,EAAG9vB,EAAE,OAAO,MAAM,CAC/D,CAEA,SAAS+/C,GAAQj8B,EAAO3c,EAAK2oB,EAAI,CAC/B+vB,GAAU/7B,EAAO,MAAO3c,EAAK2oB,CAAE,CACjC,CAEA,SAASkwB,GAAWl8B,EAAO3c,EAAK2oB,EAAI,CAClC+vB,GAAU/7B,EAAO,SAAU3c,EAAK2oB,CAAE,CACpC,CAEA,SAASmwB,GAAQ1B,EAAK,CAEhBA,EAAI,QACNA,EAAI,OAAM,CAEd,CAGA,SAAS2B,GAAOnmC,EAAOunB,EAAM,CAC3B,IAAI6e,EAAUpmC,EAAM,CAAC,EACrB,QAAS,EAAI,EAAG,EAAIA,EAAM,OAAQ,IAAK,CACrC,MAAMxP,EAAOwP,EAAM,CAAC,EAChBunB,EAAK6e,CAAO,EAAI7e,EAAK/2B,CAAI,IAC3B41C,EAAU51C,EAEd,CACA,OAAO41C,CACT,CAKA,SAASC,GAAmBC,EAAQC,EAAY,CAC9C,MAAMC,EAAgBL,GAAMG,EAAQ/+C,GAAKA,EAAE,MAAM,EAC3Ck/C,EAAU,GAChB,UAAWj2C,KAAQg2C,EAEZF,EAAO,KAAKtmC,GAASA,EAAM,UAAUzY,GAAKg/C,EAAWh/C,CAAC,IAAMg/C,EAAW/1C,CAAI,CAAC,IAAM,EAAE,GACvFi2C,EAAQ,KAAKj2C,CAAI,EAGrB,OAAOi2C,CACT,CAEA,eAAeC,GAAStD,EAAI,CAC1B,MAAO,CAAE,MAAMuD,GAAIvD,EAAIvB,GAAgBU,EAAO,CAChD,CAEA,eAAeqE,GAASxD,EAAI/qC,EAAKwuC,EAAM,CACrC,KAAM,CAACC,EAASC,CAAM,EAAI,MAAM,QAAQ,IAAI,CAACzE,GAAUC,EAAO,EAC3D,IAAIn1C,GAAOu5C,GAAIvD,EAAIvB,GAAgBz0C,CAAG,CAAC,CAAC,EAC3C,OAAQ05C,IAAYD,GAAQE,IAAW1uC,CACzC,CAEA,eAAe2uC,GAAmC5D,EAAI6D,EAAW,CAgB/D,OAAO5C,GAAUjB,EAAIxB,GAAaa,GAAe,CAACyE,EAAY1C,EAAKzuB,IAAO,CACxE,IAAI5c,EAEJ,MAAMguC,EAAmB,IAAM,CAC7BD,EAAW,OAAO/tC,GAAW,YAAY,WAAWA,EAAS,EAAI,EAAG,EAAU,EAAE,UAAYlT,GAAK,CAC/F,MAAMwgD,EAAUxgD,EAAE,OAAO,OACzB,UAAWsI,KAAUk4C,EAEnB,GADAttC,EAAU5K,EAAO,QACb04C,EAAU14C,CAAM,EAClB,OAAOwnB,EAAGxnB,CAAM,EAGpB,GAAIk4C,EAAQ,OAAS,GACnB,OAAO1wB,EAAE,EAEXoxB,EAAgB,CAClB,CACF,EACAA,EAAgB,CAClB,CAAC,CACH,CAEA,eAAeC,GAAUhE,EAAI+B,EAAW9sC,EAAKwuC,EAAM,CAwChD,CAtCC,MAAMQ,EAAkBnC,GAAmBC,CAAS,EACpD,MAAMd,GAAUjB,EAAI,CAACxB,GAAaC,EAAc,EAAGa,GAAgB,CAAC,CAACwE,EAAYI,CAAS,EAAG9C,IAAQ,CACnG,IAAIsC,EACAC,EACAQ,EAAO,EAEX,SAASC,GAAgB,CACnB,EAAED,IAAS,GACbE,EAAS,CAEb,CAEA,SAASA,GAAa,CACpB,GAAI,EAAAX,IAAYD,GAAQE,IAAW1uC,GAKnC,CAAA6uC,EAAW,MAAK,EAEhB,UAAW1wC,KAAQ6wC,EACjBH,EAAW,IAAI1wC,CAAI,EAErB8wC,EAAU,IAAIT,EAAMvE,EAAQ,EAC5BgF,EAAU,IAAIjvC,EAAKkqC,EAAO,EAC1B2D,GAAO1B,CAAG,EACZ,CAEAwB,GAAOsB,EAAWhF,GAAU/zC,GAAU,CACpCu4C,EAAUv4C,EACVi5C,EAAY,CACd,CAAC,EAEDxB,GAAOsB,EAAW/E,GAASh0C,GAAU,CACnCw4C,EAASx4C,EACTi5C,EAAY,CACd,CAAC,CACH,CAAC,EAGL,CAEA,eAAeE,GAAiBtE,EAAIxF,EAAO,CACzC,OAAOyG,GAAUjB,EAAIxB,GAAaa,GAAe,CAACyE,EAAY1C,EAAKzuB,IAAO,CACxE,MAAM4xB,EAAQ,YAAY,MAAM,CAAC/J,EAAO,CAAC,EAAG,CAACA,EAAQ,EAAG,CAAC,EAAG,GAAO,EAAI,EACvEqI,GAAUiB,EAAW,MAAM7E,EAAqB,EAAGsF,EAAO5xB,CAAE,CAC9D,CAAC,CACH,CAEA,eAAe6xB,GAAuBxE,EAAIjyB,EAAO,CAC/C,MAAMy0B,EAASX,GAAgBH,GAAc3zB,CAAK,CAAC,EAEnD,OAAKy0B,EAAO,OAILvB,GAAUjB,EAAIxB,GAAaa,GAAe,CAACyE,EAAY1C,EAAKzuB,IAAO,CAExE,MAAM8xB,EAAsB,GAEtBC,EAAY,IAAM,CAClBD,EAAoB,SAAWjC,EAAO,QACxCmC,EAAM,CAEV,EAEMA,EAAS,IAAM,CACnB,MAAMtB,EAAUJ,GAAkBwB,EAAqBtgD,GAAKA,EAAE,OAAO,EACrEwuB,EAAG0wB,EAAQ,KAAK,CAAC9/C,EAAGM,IAAMN,EAAE,MAAQM,EAAE,MAAQ,GAAK,CAAC,CAAC,CACvD,EAEA,QAASV,EAAI,EAAGA,EAAIq/C,EAAO,OAAQr/C,IAAK,CACtC,MAAMuW,EAAQ8oC,EAAOr/C,CAAC,EAChBohD,EAAQphD,IAAMq/C,EAAO,OAAS,EAChC,YAAY,MAAM9oC,EAAOA,EAAQ,IAAU,GAAO,EAAI,EACtD,YAAY,KAAKA,CAAK,EAC1BmpC,GAAUiB,EAAW,MAAMlF,EAAY,EAAG2F,EAAOp5C,GAAU,CACzDs5C,EAAoB,KAAKt5C,CAAM,EAC/Bu5C,EAAS,CACX,CAAC,CACH,CACF,CAAC,EA5BQ,EA6BX,CAIA,eAAeE,GAAqB5E,EAAI6E,EAAW,CACjD,MAAM/E,EAAS,MAAM0E,GAAsBxE,EAAI6E,CAAS,EAOxD,OAAK/E,EAAO,OAKLA,EAAO,OAAO37C,IACMA,EAAE,YAAc,IAAI,IAAIA,GAAKA,EAAE,aAAa,EAC9C,SAAS0gD,EAAU,YAAW,CAAE,CACxD,EAAE,CAAC,GAAK,KANC,MAAMjB,GAAkC5D,EAD9B77C,IAAOA,EAAE,YAAc,IAAI,SAAS0gD,EAAU,YAAW,CAAE,CAChB,GAAM,IAOvE,CAEA,eAAeC,GAAmB9E,EAAI+E,EAAS,CAC7C,OAAO9D,GAAUjB,EAAIxB,GAAaa,GAAe,CAACyE,EAAY1C,EAAKzuB,IACjEiwB,GAAOkB,EAAYiB,EAAS55C,GAAU,CACpC,GAAIA,EACF,OAAOwnB,EAAGxnB,CAAM,EAElBy3C,GAAOkB,EAAW,MAAMvE,EAAkB,EAAGwF,EAAS55C,GAAUwnB,EAAGxnB,GAAU,IAAI,CAAC,CACpF,CAAC,CACF,CACH,CAEA,SAASo4C,GAAKvD,EAAIkB,EAAWl3C,EAAK,CAChC,OAAOi3C,GAAUjB,EAAIkB,EAAW7B,GAAe,CAAC14B,EAAOy6B,EAAKzuB,IAC1DiwB,GAAOj8B,EAAO3c,EAAK2oB,CAAE,CACtB,CACH,CAEA,SAASoT,GAAKia,EAAIkB,EAAWl3C,EAAKhE,EAAO,CACvC,OAAOi7C,GAAUjB,EAAIkB,EAAW5B,GAAgB,CAAC34B,EAAOy6B,IAAQ,CAC9Dz6B,EAAM,IAAI3gB,EAAOgE,CAAG,EACpB84C,GAAO1B,CAAG,CACZ,CAAC,CACH,CAEA,SAAS4D,GAA6BhF,EAAI+E,EAAS,CACjD,OAAO9D,GAAUjB,EAAItB,GAAiBY,GAAgB,CAAC34B,EAAOy6B,IAC5DwB,GAAOj8B,EAAOo+B,EAAS55C,GAAU,CAC/Bwb,EAAM,KAAKxb,GAAU,GAAK,EAAG45C,CAAO,EACpCjC,GAAO1B,CAAG,CACZ,CAAC,CACF,CACH,CAEA,SAAS6D,GAAqBjF,EAAIkF,EAAkBr1C,EAAO,CACzD,OAAIA,IAAU,EACL,GAEFoxC,GAAUjB,EAAI,CAACtB,GAAiBF,EAAW,EAAGa,GAAe,CAAC,CAAC8F,EAAgBrB,CAAU,EAAG1C,EAAKzuB,IAAO,CAC7G,MAAM0wB,EAAU,GAChB8B,EAAe,MAAMrG,EAAW,EAAE,WAAW,OAAW,MAAM,EAAE,UAAYj8C,GAAK,CAC/E,MAAMuiD,EAASviD,EAAE,OAAO,OACxB,GAAI,CAACuiD,EACH,OAAOzyB,EAAG0wB,CAAO,EAGnB,SAASgC,EAAWl6C,EAAQ,CAE1B,GADAk4C,EAAQ,KAAKl4C,CAAM,EACfk4C,EAAQ,SAAWxzC,EACrB,OAAO8iB,EAAG0wB,CAAO,EAEnB+B,EAAO,SAAQ,CACjB,CAEA,MAAME,EAAgBF,EAAO,WACvBG,EAASL,EAAiB,OAAOI,CAAa,EACpD,GAAIC,EACF,OAAOF,EAAUE,CAAM,EAIzB3C,GAAOkB,EAAYwB,EAAehD,GAAS,CACzC,GAAIA,EACF,OAAO+C,EAAU/C,CAAK,EAGxB8C,EAAO,SAAQ,CACjB,CAAC,CACH,CACF,CAAC,CACH,CAKA,MAAMI,GAAc,GAEpB,SAASC,GAAM7F,EAAK8F,EAAc,CAChC,MAAMC,EAAM,IAAI,IAChB,UAAWv4C,KAAQwyC,EAAK,CACtB,MAAM4C,EAASkD,EAAat4C,CAAI,EAChC,UAAWsM,KAAS8oC,EAAQ,CAC1B,IAAIoD,EAAaD,EACjB,QAASxiD,EAAI,EAAGA,EAAIuW,EAAM,OAAQvW,IAAK,CACrC,MAAM0iD,EAAOnsC,EAAM,OAAOvW,CAAC,EAC3B,IAAI2iD,EAAUF,EAAW,IAAIC,CAAI,EAC5BC,IACHA,EAAU,IAAI,IACdF,EAAW,IAAIC,EAAMC,CAAO,GAE9BF,EAAaE,CACf,CACA,IAAIC,EAAeH,EAAW,IAAIJ,EAAW,EACxCO,IACHA,EAAe,GACfH,EAAW,IAAIJ,GAAaO,CAAY,GAE1CA,EAAa,KAAK34C,CAAI,CACxB,CACF,CAoCA,MAlCe,CAAC2gB,EAAOi4B,IAAU,CAC/B,IAAIJ,EAAaD,EACjB,QAASxiD,EAAI,EAAGA,EAAI4qB,EAAM,OAAQ5qB,IAAK,CACrC,MAAM0iD,EAAO93B,EAAM,OAAO5qB,CAAC,EACrB2iD,EAAUF,EAAW,IAAIC,CAAI,EACnC,GAAIC,EACFF,EAAaE,MAEb,OAAO,EAEX,CAEA,GAAIE,EAEF,OADgBJ,EAAW,IAAIJ,EAAW,GACxB,GAGpB,MAAMnC,EAAU,GAEV4C,EAAQ,CAACL,CAAU,EACzB,KAAOK,EAAM,QAAQ,CAEnB,MAAMC,EAAqB,CAAC,GADTD,EAAM,MAAK,EACY,QAAO,CAAE,EAAE,KAAK,CAAC1iD,EAAGM,IAAMN,EAAE,CAAC,EAAIM,EAAE,CAAC,EAAI,GAAK,CAAC,EACxF,SAAW,CAACmG,EAAKhE,CAAK,IAAKkgD,EACrBl8C,IAAQw7C,GACVnC,EAAQ,KAAK,GAAGr9C,CAAK,EAErBigD,EAAM,KAAKjgD,CAAK,CAGtB,CACA,OAAOq9C,CACT,CAGF,CAEA,MAAM8C,GAAiB,CACrB,OACA,KACF,EAEA,SAASC,GAAoBC,EAAc,CACzC,MAAMC,EAAUD,GAAgB,MAAM,QAAQA,CAAY,EACpDE,EAAoBD,GACxBD,EAAa,SACZ,CAACA,EAAa,CAAC,GAAKF,GAAe,KAAKn8C,GAAO,EAAEA,KAAOq8C,EAAa,CAAC,EAAE,GAC3E,GAAI,CAACC,GAAWC,EACd,MAAM,IAAI,MAAM,uCAAuC,CAE3D,CAEA,SAASrB,GAAkBmB,EAAc,CACvCD,GAAmBC,CAAY,EAE/B,MAAMG,EAAa,CAACjjD,EAAGM,IAAMN,EAAE,KAAK,YAAW,EAAKM,EAAE,KAAK,YAAW,EAAK,GAAK,EAK1E4iD,EAAMJ,EAAa,KAAKG,CAAU,EAgBlCE,EAAajB,GAAKY,EAXF/D,GAAS,CAC7B,MAAMvc,EAAM,IAAI,IAChB,GAAIuc,EAAM,WACR,UAAWuC,KAAavC,EAAM,WAC5B,UAAW5oC,KAASgoC,GAAcmD,CAAS,EACzC9e,EAAI,IAAIrsB,CAAK,EAInB,OAAOqsB,CACT,CACmD,EAC7C4gB,EAAqBxiD,GAAKuiD,EAAWviD,EAAG,EAAI,EAC5CyiD,EAAiBziD,GAAKuiD,EAAWviD,EAAG,EAAK,EAKzC0iD,EAAS94B,GAAS,CACtB,MAAMy0B,EAASd,GAAc3zB,CAAK,EAC5B02B,EAAsBjC,EAAO,IAAI,CAAC9oC,EAAOvW,KAC5CA,EAAIq/C,EAAO,OAAS,EAAImE,EAAqBC,GAAgBltC,CAAK,CACpE,EACD,OAAOupC,GAAkBwB,EAAqBtgD,GAAKA,EAAE,IAAI,EAAE,KAAKqiD,CAAU,CAC5E,EAKMM,EAAmB,IAAI,IACvBC,EAAc,IAAI,IACxB,UAAWC,KAAeX,EAAc,CACtCU,EAAY,IAAIC,EAAY,KAAK,YAAW,EAAIA,CAAW,EAC3D,UAAWnC,KAAcmC,EAAY,YAAc,GACjDF,EAAiB,IAAIjC,EAAU,YAAW,EAAImC,CAAW,CAE7D,CAKA,MAAO,CACL,IAAAP,EACA,OAAAI,EACA,YANkBhC,GAAaiC,EAAiB,IAAIjC,EAAU,aAAa,EAO3E,OANax+C,GAAQ0gD,EAAY,IAAI1gD,EAAK,aAAa,CAO3D,CACA,CAEA,MAAM4gD,GAAyB,OAAO,gBAAoB,IAI1D,SAASC,GAAY5E,EAAO,CAC1B,GAAI,CAACA,EACH,OAAOA,EAST,GAJI2E,KACF3E,EAAQ,gBAAgBA,CAAK,GAE/B,OAAOA,EAAM,OACTA,EAAM,UAAW,CACnB,MAAMzmC,EAAMymC,EAAM,UAAU,OAC5BA,EAAM,MAAQ,MAAMzmC,CAAG,EACvB,QAAS1Y,EAAI,EAAGA,EAAI0Y,EAAK1Y,IACvBm/C,EAAM,MAAMn/C,CAAC,EAAI,CACf,KAAMm/C,EAAM,UAAUn/C,CAAC,EACvB,QAASm/C,EAAM,aAAan/C,CAAC,EAC7B,QAASm/C,EAAM,aAAan/C,CAAC,CACrC,EAEI,OAAOm/C,EAAM,UACb,OAAOA,EAAM,aACb,OAAOA,EAAM,YACf,CACA,OAAOA,CACT,CAEA,SAAS6E,GAAU1D,EAAM,CAClBA,GACH,QAAQ,KAAK,yFAAyF,CAE1G,CAEA,MAAM2D,GAAe,CACnB,aACA,QACA,QACA,QACA,SACF,EAEA,SAASC,GAAiBtF,EAAW,CACnC,GAAI,CAACA,GACH,CAAC,MAAM,QAAQA,CAAS,GACxB,CAACA,EAAU,CAAC,GACX,OAAOA,EAAU,CAAC,GAAM,UACzBqF,GAAa,KAAKp9C,GAAQ,EAAEA,KAAO+3C,EAAU,CAAC,EAAG,EACjD,MAAM,IAAI,MAAM,mCAAmC,CAEvD,CAEA,SAASuF,GAAcC,EAAUC,EAAY,CAC3C,GAAI,KAAK,MAAMD,EAAS,OAAS,GAAG,IAAM,EACxC,MAAM,IAAI,MAAM,oBAAsBC,EAAa,MAAQD,EAAS,MAAM,CAE9E,CAEA,eAAeE,GAASD,EAAY,CAClC,MAAMD,EAAW,MAAM,MAAMC,EAAY,CAAE,OAAQ,OAAQ,EAC3DF,GAAaC,EAAUC,CAAU,EACjC,MAAM/D,EAAO8D,EAAS,QAAQ,IAAI,MAAM,EACxC,OAAAJ,GAAS1D,CAAI,EACNA,CACT,CAEA,eAAeiE,GAAgBF,EAAY,CACzC,MAAMD,EAAW,MAAM,MAAMC,CAAU,EACvCF,GAAaC,EAAUC,CAAU,EACjC,MAAM/D,EAAO8D,EAAS,QAAQ,IAAI,MAAM,EACxCJ,GAAS1D,CAAI,EACb,MAAM1B,EAAY,MAAMwF,EAAS,KAAI,EACrC,OAAAF,GAAgBtF,CAAS,EAClB,CAAC0B,EAAM1B,CAAS,CACzB,CAiBA,SAAS4F,GAA0Bz6B,EAAQ,CAKvC,QAJI/H,EAAS,GACT/V,EAAQ,IAAI,WAAW8d,CAAM,EAC7BvR,EAASvM,EAAM,WACfjM,EAAI,GACD,EAAEA,EAAIwY,GACTwJ,GAAU,OAAO,aAAa/V,EAAMjM,CAAC,CAAC,EAE1C,OAAOgiB,CACX,CAWA,SAASyiC,GAA0BziC,EAAQ,CAKvC,QAJIxJ,EAASwJ,EAAO,OAChB/I,EAAM,IAAI,YAAYT,CAAM,EAC5BikC,EAAM,IAAI,WAAWxjC,CAAG,EACxBjZ,EAAI,GACD,EAAEA,EAAIwY,GACTikC,EAAIz8C,CAAC,EAAIgiB,EAAO,WAAWhiB,CAAC,EAEhC,OAAOiZ,CACX,CAGA,eAAeyrC,GAAcvhB,EAAQ,CACnC,MAAMwhB,EAAW,KAAK,UAAUxhB,CAAM,EACtC,IAAIyhB,EAAWH,GAA0BE,CAAQ,EAGjD,MAAME,EAAY,MAAM,OAAO,OAAO,OAAO,QAASD,CAAQ,EACxDE,EAAeN,GAA0BK,CAAS,EAExD,OADY,KAAKC,CAAY,CAE/B,CAEA,eAAeC,GAAmBlI,EAAIwH,EAAY,CAEhD,IAAIzF,EACA0B,EAAO,MAAMgE,GAAQD,CAAU,EACnC,GAAI,CAAC/D,EAAM,CACT,MAAM0E,EAAc,MAAMT,GAAeF,CAAU,EACnD/D,EAAO0E,EAAY,CAAC,EACpBpG,EAAYoG,EAAY,CAAC,EACpB1E,IACHA,EAAO,MAAMoE,GAAa9F,CAAS,EAEvC,CACI,MAAMyB,GAAQxD,EAAIwH,EAAY/D,CAAI,IAC/B1B,IAEHA,GADoB,MAAM2F,GAAeF,CAAU,GAC3B,CAAC,GAE3B,MAAMxD,GAAShE,EAAI+B,EAAWyF,EAAY/D,CAAI,EAElD,CAEA,eAAe2E,GAAsBpI,EAAIwH,EAAY,CACnD,GAAI,CAAC/D,EAAM1B,CAAS,EAAI,MAAM2F,GAAeF,CAAU,EAClD/D,IAGHA,EAAO,MAAMoE,GAAa9F,CAAS,GAGrC,MAAMiC,GAAShE,EAAI+B,EAAWyF,EAAY/D,CAAI,CAChD,CAEA,eAAe4E,GAAiBrI,EAAIwH,EAAY,CAC9C,GAAI,CACF,MAAMU,GAAkBlI,EAAIwH,CAAU,CACxC,OAASt3C,EAAK,CAMZ,GAAIA,EAAI,OAAS,oBACf,MAAMA,CAEV,CACF,CAEA,MAAMo4C,EAAS,CACb,YAAa,CAAE,WAAAd,EAAa/H,GAAqB,OAAA8I,EAAS7I,GAAgB,YAAAsH,EAAc,EAAE,EAAK,GAAI,CACjG,KAAK,WAAaQ,EAClB,KAAK,OAASe,EACd,KAAK,QAAU,wBAAwB,KAAK,MAAM,GAClD,KAAK,IAAM,OACX,KAAK,YAAc,OACnB,KAAK,QAAUrD,GAAiB8B,CAAW,EAE3C,KAAK,OAAS,KAAK,OAAO,KAAK,IAAI,EACnC,KAAK,OAAS,KAAK,MAAK,CAC1B,CAEA,MAAM,OAAS,CACb,MAAMhH,EAAK,KAAK,IAAM,MAAMgB,GAAa,KAAK,OAAO,EAErDQ,GAAmB,KAAK,QAAS,KAAK,MAAM,EAC5C,MAAMgG,EAAa,KAAK,WACV,MAAMlE,GAAQtD,CAAE,EAG5B,MAAMoI,GAAqBpI,EAAIwH,CAAU,EAEzC,KAAK,YAAca,GAAgBrI,EAAIwH,CAAU,CAErD,CAEA,MAAM,OAAS,CACb,MAAMgB,EAAa,UACZ,KAAK,SACR,KAAK,OAAS,KAAK,MAAK,GAEnB,KAAK,QAEd,MAAMA,EAAU,EAIX,KAAK,KACR,MAAMA,EAAU,CAEpB,CAEA,MAAM,gBAAiBhO,EAAO,CAC5B,OAAA4D,GAAa5D,CAAK,EAClB,MAAM,KAAK,MAAK,EACTqF,GAAU,MAAMyE,GAAgB,KAAK,IAAK9J,CAAK,CAAC,EAAE,IAAI0M,EAAU,CACzE,CAEA,MAAM,sBAAuBn5B,EAAO,CAClCmwB,GAAqBnwB,CAAK,EAC1B,MAAM,KAAK,MAAK,EAChB,MAAM06B,EAAU,KAAK,QAAQ,OAAO16B,CAAK,EACnC26B,EAAU7I,GAAU,MAAM2E,GAAsB,KAAK,IAAKz2B,CAAK,CAAC,EAAE,IAAIm5B,EAAU,EACtF,MAAO,CACL,GAAGuB,EACH,GAAGC,CACT,CACE,CAEA,MAAM,oBAAqB7D,EAAW,CACpC3G,GAAqB2G,CAAS,EAC9B,MAAM,KAAK,MAAK,EAChB,MAAMU,EAAS,KAAK,QAAQ,YAAYV,CAAS,EACjD,OAAIU,GAGG2B,GAAW,MAAMtC,GAAoB,KAAK,IAAKC,CAAS,CAAC,CAClE,CAEA,MAAM,wBAAyBS,EAAe,CAC5CpH,GAAqBoH,CAAa,EAClC,MAAM,KAAK,MAAK,EAChB,MAAMC,EAAS,KAAK,QAAQ,OAAOD,CAAa,EAChD,OAAIC,GAGG2B,GAAW,MAAMpC,GAAkB,KAAK,IAAKQ,CAAa,CAAC,CACpE,CAEA,MAAM,sBAAwB,CAC5B,aAAM,KAAK,MAAK,EACR,MAAM/B,GAAI,KAAK,IAAK9E,GAAgBW,EAAsB,GAAM,CAC1E,CAEA,MAAM,qBAAsBuJ,EAAU,CACpC,OAAAvK,GAAauK,CAAQ,EACrB,MAAM,KAAK,MAAK,EACT5iB,GAAI,KAAK,IAAK0Y,GAAgBW,GAAwBuJ,CAAQ,CACvE,CAEA,MAAM,4BAA6BrD,EAAe,CAChD,OAAApH,GAAqBoH,CAAa,EAClC,MAAM,KAAK,MAAK,EACTN,GAA4B,KAAK,IAAKM,CAAa,CAC5D,CAEA,MAAM,oBAAqBz1C,EAAO,CAChC,OAAAuuC,GAAavuC,CAAK,EAClB,MAAM,KAAK,MAAK,GACR,MAAMo1C,GAAoB,KAAK,IAAK,KAAK,QAASp1C,CAAK,GAAG,IAAIq3C,EAAU,CAClF,CAEA,IAAI,YAAab,EAAc,CAC7B,KAAK,QAAUnB,GAAiBmB,CAAY,CAC9C,CAEA,IAAI,aAAe,CACjB,OAAO,KAAK,QAAQ,GACtB,CAEA,MAAM,WAAa,CACjB,MAAM,KAAK,QACX,GAAI,CACF,MAAM,KAAK,WACb,MAAc,CAA8C,CAC9D,CAGA,QAAU,CAKR,KAAK,IAAM,KAAK,OAAS,KAAK,YAAc,MAC9C,CAEA,MAAM,OAAS,CACb,MAAM,KAAK,UAAS,EACpB,MAAMtF,GAAc,KAAK,OAAO,CAClC,CAEA,MAAM,QAAU,CACd,MAAM,KAAK,UAAS,EACpB,MAAMQ,GAAe,KAAK,OAAO,CACnC,CACF,CCt+BA,MAAMqH,GAAY,CAChB,CAAC,GAAI,IAAK,QAAQ,EAClB,CAAC,EAAG,KAAM,iBAAiB,EAC3B,CAAC,EAAG,KAAM,aAAa,EACvB,CAAC,EAAG,KAAM,gBAAgB,EAC1B,CAAC,EAAG,KAAM,YAAY,EACtB,CAAC,EAAG,MAAO,eAAe,EAC1B,CAAC,EAAG,IAAK,YAAY,EACrB,CAAC,EAAG,KAAM,SAAS,EACnB,CAAC,EAAG,KAAM,SAAS,EACnB,CAAC,EAAG,KAAM,OAAO,CACnB,EAAE,IAAI,CAAC,CAAC75C,EAAIuzC,EAAOj8C,CAAI,KAAO,CAAE,GAAA0I,EAAI,MAAAuzC,EAAO,KAAAj8C,CAAI,EAAG,EAE5CwiD,GAASD,GAAU,MAAM,CAAC,EAE1BhH,GAAyB,EACzBkH,GAAiB,EAGjBC,GAAM,OAAO,qBAAwB,WAAa,oBAAsB,WAG9E,SAASC,GAAQ1G,EAAO,CACtB,OAAOA,EAAM,QAAQ,SAAS,GAAQ,CACxC,CAWA,MAAM2G,GAAuB,CAC3B,KAAM,GACN,KAAM,GACN,KAAM,KACN,KAAM,GACN,KAAM,KACN,KAAM,KACN,KAAM,GACN,KAAM,EACN,QAAS,EACT,KAAM,EACN,UAAW,EACX,KAAM,EACN,MAAO,GACP,KAAM,EACR,EAEMC,GAAiC,IACjCC,GAA0B,MAC1BC,GAAsB,EAMtBC,GAA2B,CAC/B,KACA,KACA,KACA,MACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,IACF,EAOMC,GAAc,0IAIdC,GAA2B,CAAChmD,EAAGM,IAAMN,EAAIM,EAAI,GAAKN,EAAIM,EAAI,EAAI,EAQ9D2lD,GAAiB,CAACz/C,EAAM5C,IAAU,CACtC,MAAMsiD,EAAS,SAAS,cAAc,QAAQ,EAC9CA,EAAO,MAAQA,EAAO,OAAS,EAE/B,MAAM3S,EAAM2S,EAAO,WAAW,KAAM,CAGlC,mBAAoB,EACxB,CAAG,EACD,OAAA3S,EAAI,aAAe,MACnBA,EAAI,KAAO,SAASwS,EAAW,GAC/BxS,EAAI,UAAY3vC,EAChB2vC,EAAI,MAAM,IAAM,GAAI,EACpBA,EAAI,SAAS/sC,EAAM,EAAG,CAAC,EAEhB+sC,EAAI,aAAa,EAAG,EAAG,EAAG,CAAC,EAAE,IACtC,EAEM4S,GAAkB,CAACC,EAAUC,IAAa,CAC9C,MAAMC,EAAc,CAAC,GAAGF,CAAQ,EAAE,KAAK,GAAG,EACpCG,EAAc,CAAC,GAAGF,CAAQ,EAAE,KAAK,GAAG,EAI1C,OAAOC,IAAgBC,GAAe,CAACD,EAAY,WAAW,QAAQ,CACxE,EAEA,SAASE,GAAyBhgD,EAAM,CAGtC,MAAM4/C,EAAWH,GAAez/C,EAAM,MAAM,EACtC6/C,EAAWJ,GAAez/C,EAAM,MAAM,EAC5C,OAAO4/C,GAAYC,GAAYF,GAAgBC,EAAUC,CAAQ,CACnE,CAKA,SAASI,IAA8B,CACrC,MAAMjvC,EAAU,OAAO,QAAQkuC,EAAoB,EACnD,GAAI,CAEF,SAAW,CAAC3G,EAAOC,CAAO,IAAKxnC,EAC7B,GAAIgvC,GAAwBzH,CAAK,EAC/B,OAAOC,CAGb,MAAY,CACZ,CAIA,OAAOxnC,EAAQ,CAAC,EAAE,CAAC,CACrB,CAGA,IAAIkvC,GACJ,MAAMC,GAA0B,KACzBD,KAIHA,GAAU,IAAI,QAAQvJ,GACpBqI,GAAI,IACFrI,EAAQsJ,GAA0B,CAAE,CACrC,CACF,GAEIC,IAIHE,GAAqB,IAAI,IAEzBC,GAAqB,IACrBC,GAAoB,SACpBC,GAAM,IACNC,GAAkB,OAClBC,GAA2B,MAKjC,SAASC,GAAetM,EAAKwK,EAAU,CACrC,GAAIA,IAAa,EACf,OAAOxK,EAET,MAAMuM,EAAWvM,EAAI,QAAQmM,EAAG,EAChC,OAAII,IAAa,GACRvM,EAAI,UAAU,EAAGuM,CAAQ,EAC9B,OAAO,cAAcH,GAAkB5B,EAAW,CAAC,EACnDxK,EAAI,UAAUuM,CAAQ,GAEtBvM,EAAI,SAASiM,EAAkB,IACjCjM,EAAMA,EAAI,UAAU,EAAGA,EAAI,OAAS,CAAC,GAEhCA,EAAMkM,GAAoB,OAAO,cAAcG,GAA2B7B,EAAW,CAAC,EAC/F,CAEA,SAASgC,GAAMp2C,EAAO,CACpBA,EAAM,eAAc,EACpBA,EAAM,gBAAe,CACvB,CAIA,SAASq2C,GAAsBC,EAAW1iD,EAAKy3C,EAAK,CAClD,OAAAz3C,GAAQ0iD,EAAY,GAAK,EACrB1iD,EAAM,EACRA,EAAMy3C,EAAI,OAAS,EACVz3C,GAAOy3C,EAAI,SACpBz3C,EAAM,GAEDA,CACT,CAGA,SAASw3C,GAAQC,EAAKzb,EAAM,CAC1B,MAAM4B,EAAM,IAAI,IACVj2B,EAAM,GACZ,UAAW1C,KAAQwyC,EAAK,CACtB,MAAM51C,EAAMm6B,EAAK/2B,CAAI,EAChB24B,EAAI,IAAI/7B,CAAG,IACd+7B,EAAI,IAAI/7B,CAAG,EACX8F,EAAI,KAAK1C,CAAI,EAEjB,CACA,OAAO0C,CACT,CAKA,SAASg7C,GAAsBhL,EAAQiL,EAAmB,CACxD,MAAMC,EAAmB5I,GAAS,CAChC,MAAMtyC,EAAM,GACZ,UAAWm7C,KAAQ7I,EAIb,OAAO6I,EAAK,MAAS,UAAYA,EAAK,SAAWF,IACnDj7C,EAAIm7C,EAAK,IAAI,EAAIA,EAAK,SAG1B,OAAOn7C,CACT,EAEA,OAAOgwC,EAAO,IAAI,CAAC,CAAE,QAAAiF,EAAS,MAAA3C,EAAO,WAAAD,EAAY,IAAAltC,EAAK,KAAA5O,EAAM,SAAA6kD,EAAU,WAAAlJ,CAAU,KAAQ,CACtF,QAAA+C,EACA,KAAA1+C,EACA,WAAA87C,EACA,IAAAltC,EACA,SAAAi2C,EACA,WAAAlJ,EACA,GAAI+C,GAAW1+C,EACf,MAAO+7C,GAAS4I,EAAiB5I,CAAK,CAC1C,EAAI,CACJ,CAGA,MAAM+I,GAAM,sBAMZ,IAAIC,GAA0B,OAAO,gBAAmB,WAExD,SAASC,GAAsBnd,EAAMod,EAAaC,EAAU,CAC1D,IAAIC,EACAJ,IACFI,EAAiB,IAAI,eAAeD,CAAQ,EAC5CC,EAAe,QAAQtd,CAAI,GAE3Bid,GAAII,CAAQ,EAIdD,EAAY,iBAAiB,QAAS,IAAM,CACtCE,GACFA,EAAe,WAAU,CAE7B,CAAC,CACH,CAGA,SAASC,GAAoBvd,EAAM,CAGjC,CACE,MAAMqW,EAAQ,SAAS,YAAW,EAClC,OAAAA,EAAM,WAAWrW,EAAK,UAAU,EACzBqW,EAAM,wBAAwB,KACvC,CACF,CAEA,IAAImH,GASJ,SAASC,GAAiBC,EAAkBC,EAAeC,EAAgB,CACzE,IAAIC,EAAe,GACfC,EAAa,GACjB,UAAW1J,KAASsJ,EAAkB,CACpC,MAAMK,EAAUH,EAAexJ,CAAK,EAGpC,GAAI,CAAC2J,EAIH,SAEF,MAAMC,EAAaT,GAAmBQ,CAAO,EAEzCC,IAAe,IACjBF,EAAa,IAEX,OAAON,GAAuB,MAChCA,GAAqBD,GAAmBI,CAAa,GAMvD,MAAMM,EAAYD,EAAa,IAAMR,GACrCvB,GAAmB,IAAI7H,EAAM,QAAS6J,CAAS,EAE1CA,IACHJ,EAAe,GAEnB,CAGA,OAAIC,GACF,QAAQ,KAAK;AAAA;AAAA;AAAA,gFAIjB,EAESD,CACT,CAIA,SAASK,GAAMxM,EAAK,CAClB,OAAOD,GAAOC,EAAKz7C,GAAKA,CAAC,CAC3B,CAOA,SAASkoD,GAA0BpmB,EAAS,CAEtCA,IACFA,EAAQ,UAAY,EAExB,CAEA,SAASqmB,GAAYC,EAAOviD,EAAKm6B,EAAM,CACrC,IAAIv9B,EAAS2lD,EAAM,IAAIviD,CAAG,EAC1B,OAAKpD,IACHA,EAASu9B,EAAI,EACbooB,EAAM,IAAIviD,EAAKpD,CAAM,GAEhBA,CACT,CAEA,SAAS4lD,GAAUxmD,EAAO,CACxB,MAAO,GAAKA,CACd,CAEA,SAASymD,GAAeC,EAAY,CAClC,MAAM5iB,EAAW,SAAS,cAAc,UAAU,EAClD,OAAAA,EAAS,UAAY4iB,EACd5iB,CACT,CAEA,MAAM6iB,GAAa,IAAI,QACjBC,GAAoB,IAAI,QAExBC,GAAgB,OAAO,UAAU,EAGjCC,GAAqB,oBAAqB,QAAQ,UACxD,SAASC,GAAiB5d,EAAY6d,EAAa,CAE7CF,GACF3d,EAAW,gBAAgB,GAAG6d,CAAW,GAEzC7d,EAAW,UAAY,GACvBA,EAAW,OAAO,GAAG6d,CAAW,EAEpC,CAEA,SAASC,GAAwB9d,EAAY6d,EAAa,CACxD,IAAIE,EAAW/d,EAAW,WACtBge,EAAmB,EAEvB,KAAOD,GAAU,CAGf,GAFiBF,EAAYG,CAAgB,IAE5BD,EACf,MAAO,GAETA,EAAWA,EAAS,YACpBC,GACF,CAEA,OAAOA,IAAqBH,EAAY,MAC1C,CAEA,SAASI,GAAeJ,EAAaK,EAAiB,CACpD,KAAM,CAAE,WAAAC,CAAU,EAAKD,EACvB,GAAI,CAAE,iBAAAE,CAAgB,EAAKF,EAEvBG,EAAgB,GAEhBD,EACFC,EAAgBP,GAAuBM,EAAkBP,CAAW,GAEpEQ,EAAgB,GAChBH,EAAgB,WAAa,OAC7BA,EAAgB,iBAAmBE,EAAmBD,EAAW,YAG/DE,GACFT,GAAgBQ,EAAkBP,CAAW,CAEjD,CAEA,SAAS90C,GAAOu1C,EAAaC,EAAkB,CAC7C,UAAWL,KAAmBK,EAAkB,CAC9C,KAAM,CACJ,WAAAJ,EACA,kBAAAK,EACA,QAAS,CACP,gBAAAC,EACA,cAAAC,EACA,kBAAAC,EACA,mBAAAC,CACR,CACA,EAAQV,EAEEW,EAAaP,EAAYG,CAAe,EAE9C,GAAID,IAAsBK,EAO1B,GAFAX,EAAgB,kBAAoBW,EAEhCH,EACF,GAAIG,IAAe,KAEjBV,EAAW,gBAAgBO,CAAa,MACnC,CAEL,MAAMI,EAAWH,EAAoBtB,GAASwB,CAAU,EAAID,EAC5DT,EAAW,aAAaO,EAAeI,CAAQ,CACjD,KACK,CACL,IAAIC,EACA,MAAM,QAAQF,CAAU,EAC1BZ,GAAcY,EAAYX,CAAe,EAChCW,aAAsB,SAC/BE,EAAUF,EACVV,EAAW,YAAYY,CAAO,GAI9BZ,EAAW,UAAYd,GAASwB,CAAU,EAExCE,IACFb,EAAgB,WAAaa,EAEjC,CACF,CACF,CAEA,SAASC,GAAO3L,EAAQ,CACtB,IAAIkK,EAAa,GAEb0B,EAAY,GACZC,EAAkB,GAClBC,EAAsB,GAE1B,MAAMC,EAAqB,IAAI,IACzBC,EAAiB,GAEvB,IAAIC,EAAiB,EACrB,QAAStrD,EAAI,EAAG0Y,EAAM2mC,EAAO,OAAQr/C,EAAI0Y,EAAK1Y,IAAK,CACjD,MAAMuW,EAAQ8oC,EAAOr/C,CAAC,EAGtB,GAFAupD,GAAchzC,EAAM,MAAM+0C,CAAc,EAEpCtrD,IAAM0Y,EAAM,EACd,MAGF,QAASpW,EAAI,EAAGA,EAAIiU,EAAM,OAAQjU,IAEhC,OADaiU,EAAM,OAAOjU,CAAC,EACf,CACV,IAAK,IAAK,CACSiU,EAAM,OAAOjU,EAAI,CAAC,IAClB,IAEf+oD,EAAe,IAAG,GAElBJ,EAAY,GACZI,EAAe,KAAK,EAAEF,CAAmB,GAE3C,KACF,CACA,IAAK,IAAK,CACRF,EAAY,GACZC,EAAkB,GAClB,KACF,CACA,IAAK,IAAK,CACRA,EAAkB,GAClB,KACF,CACR,CAGI,MAAMK,EAAeF,EAAeA,EAAe,OAAS,CAAC,EACvDG,EAAWrC,GAAWiC,EAAoBG,EAAc,IAAM,EAAE,EAEtE,IAAIb,EACAC,EACAC,EACJ,GAAIM,EAAiB,CAEnB,MAAMO,EAAoB,oBAAoB,KAAKl1C,CAAK,EACxDm0C,EAAgBe,EAAkB,CAAC,EACnCd,EAAoBc,EAAkB,CAAC,EACvC,MAAMC,EAAqB,gBAAgB,KAAKrM,EAAOr/C,EAAI,CAAC,CAAC,EAC7D4qD,EAAqBc,EAAmB,CAAC,EAGzCnC,EAAaA,EAAW,MAAM,EAAG,GAAKkC,EAAkB,CAAC,EAAE,MAAM,EACjEH,EAAiBI,EAAmB,CAAC,EAAE,MACzC,MACEJ,EAAiB,EAGnB,MAAM11C,EAAU,CACd,cAAA80C,EACA,kBAAAC,EACA,mBAAAC,EACA,gBAAiB5qD,CACvB,EAEIwrD,EAAS,KAAK51C,CAAO,EAEjB,CAACq1C,GAAa,CAACC,IAEjB3B,GAAc,IAElB,CAIA,MAAO,CACL,SAHeD,GAAcC,CAAU,EAIvC,mBAAA6B,CACJ,CACA,CAEA,SAASO,GAAeH,EAAU1oB,EAASynB,EAAkB,CAC3D,QAAS,EAAI,EAAG,EAAIiB,EAAS,OAAQ,IAAK,CACxC,MAAM51C,EAAU41C,EAAS,CAAC,EAEpBrB,EAAav0C,EAAQ,cACvBktB,EACAA,EAAQ,WAENonB,EAAkB,CACtB,QAAAt0C,EACA,WAAAu0C,EACA,iBAAkB,OAClB,kBAAmB,MACzB,EAEII,EAAiB,KAAKL,CAAe,CACvC,CACF,CAEA,SAAS0B,GAA0BC,EAAaT,EAAoB,CAClE,MAAMb,EAAmB,GAEzB,IAAIuB,EACJ,GAAIV,EAAmB,OAAS,IAAMU,EAAmBV,EAAmB,IAAI,CAAC,GAG/EO,GAAcG,EAAkBD,EAAatB,CAAgB,MACxD,CAEL,MAAMwB,EAAa,SAAS,iBAAiBF,EAAa,WAAW,YAAY,EAEjF,IAAI/oB,EAAU+oB,EACVN,EAAe,GACnB,EAAG,CACD,MAAMC,EAAWJ,EAAmB,IAAI,EAAEG,CAAY,EAClDC,GACFG,GAAcH,EAAU1oB,EAASynB,CAAgB,CAErD,OAAUznB,EAAUipB,EAAW,SAAQ,EACzC,CAEA,OAAOxB,CACT,CAEA,SAASyB,GAAW3M,EAAQ,CAE1B,KAAM,CAAE,SAAA1Y,EAAU,mBAAAykB,CAAkB,EAAKjC,GAAWK,GAAYnK,EAAQ,IAAM2L,GAAM3L,CAAM,CAAC,EAGrF4M,EAAMtlB,EAAS,UAAU,EAAI,EAAE,QAAQ,kBACvC4jB,EAAmBqB,GAAyBK,EAAKb,CAAkB,EAEzE,OAAO,SAA4Bd,EAAa,CAC9C,OAAAv1C,GAAMu1C,EAAaC,CAAgB,EAC5B0B,CACT,CACF,CAEA,SAASC,GAAiB1/C,EAAO,CAC/B,MAAM2/C,EAAehD,GAAWM,GAAmBj9C,EAAO,IAAM,IAAI,GAAK,EACzE,IAAI4/C,EAAsB1C,GAE1B,SAASx6B,EAAMmwB,KAAWiL,EAAa,CAGrC,MAAM+B,EAAwBlD,GAAWgD,EAAc9M,EAAQ,IAAM,IAAI,GAAK,EAG9E,OAF0B8J,GAAWkD,EAAuBD,EAAqB,IAAMJ,GAAU3M,CAAM,CAAC,EAE/EiL,CAAW,CACtC,CAEA,SAAS9H,EAAK/oC,EAAO6yC,EAAUC,EAAa,CAC1C,OAAO9yC,EAAM,IAAI,CAACxP,EAAMg5B,IAAU,CAChC,MAAMupB,EAAmBJ,EACzBA,EAAsBG,EAAYtiD,CAAI,EACtC,GAAI,CACF,OAAOqiD,EAASriD,EAAMg5B,CAAK,CAC7B,QAAC,CACCmpB,EAAsBI,CACxB,CACF,CAAC,CACH,CAEA,MAAO,CAAE,IAAAhK,EAAK,KAAAtzB,CAAI,CACpB,CAEA,SAASu9B,GAAQ97C,EAAWnE,EAAOkgD,EAASC,EAAQC,EAASnnC,EAAM0iC,EAAa0E,EAAeC,EAAa,CAC1G,KAAM,CAAE,cAAAC,EAAe,cAAAC,EAAe,gBAAAC,CAAe,EAAKP,EACpD,CAAE,KAAAx9B,EAAM,IAAAszB,GAAQ0J,GAAgB1/C,CAAK,EAE3C,SAAS0gD,EAAWvQ,EAAQwQ,EAAYv0C,EAAQ,CAC9C,OAAO4pC,EAAI7F,EAAQ,CAACwC,EAAOn/C,IAClBkvB,kBAAqBi+B,EAAa,SAAW,UAAU,oBAAoBA,EAAantD,IAAMwM,EAAM,iBAAmB,IAAI,iBAAiBugD,EAAc5N,EAAO3yC,EAAM,eAAe,CAAC,YAAYwgD,EAAc7N,CAAK,CAAC,YACpN,SACCgO,GAAcntD,IAAMwM,EAAM,iBAAmB,UAAY,KACzD2yC,EAAM,QAAU,GAAK,gBACtC,SAAuB,GAAGvmC,CAAM,IAAIumC,EAAM,EAAE,EAAE,YAAYA,EAAM,QAAU,KAAO,kCAAkC,KAAK,UAAUA,EAAM,GAAG,CAAC,GAAG,KACvIA,EAAM,QACF8N,EAAgB9N,EAAO3yC,EAAM,eAAe,EAC5C,EACZ,YAGO2yC,GAAS,GAAGvmC,CAAM,IAAIumC,EAAM,EAAE,EAAE,CACrC,CAkCA,MAAMiO,EA/BGl+B,+DAAkE1iB,EAAM,KAAK,WAAW,YAAYA,EAAM,aAAe,EAAE,uLAAuLA,EAAM,KAAK,WAAW,+EAA+E,CAAC,EAAEA,EAAM,YAAcA,EAAM,cAAc,OAAO,0HAA0HA,EAAM,mBAAqB,OAAOA,EAAM,kBAAkB,GAAK,IAAI,kIAAkIA,EAAM,KAAK,WAAW,0DAA0DA,EAAM,KAAK,iBAAiB,oDAAoDA,EAAM,qCAAuC,WAAa,EAAE,+CAA+CA,EAAM,uBAAyB,aAAe,EAAE,iBAAiBA,EAAM,mBAAmB,YAAYA,EAAM,mBAAmB,oFAAoFA,EAAM,sBAAsB,yEAAyEA,EAAM,oBAAsB,EAAE,kEAAkEA,EAAM,KAAK,mBAAmB,8FAA8FA,EAAM,uBAAyB,GAAK,mBAAmB,iCAAiCA,EAAM,uBAAyB,EAAI,2DAA2D,iCAAiCA,EAAM,KAAK,cAAc,qCAAqCA,EAAM,cAAc,kBAAkB,CAACA,EAAM,sBAAsB,yLACt4Dg2C,EAAIh2C,EAAM,UAAW,CAACg5C,EAAUxlD,IACzBkvB,sBAAyBlvB,CAAC,kBAAkBA,IAAMwM,EAAM,eAAiB,SAAW,EAAE,oBAAoBxM,IAAMwM,EAAM,cAAc,0BAA0BA,EAAM,KAAK,UAAUxM,CAAC,CAAC,iBAAiBwM,EAAM,KAAK,UAAUxM,CAAC,CAAC,KAAKwlD,CAAQ,SAC9OA,GAAYA,CAAQ,CAC3B,mFAA2Fh5C,EAAM,OAAO,MAAM,sBAAsBA,EAAM,KAAK,eAAe,+DAClJg2C,EAAIh2C,EAAM,OAAS6qC,GACVnoB,6DAAgEmoB,EAAM,EAAE,iBAAiB7qC,EAAM,KAAK,WAAW6qC,EAAM,IAAI,CAAC,oBAAoB,CAAC7qC,EAAM,YAAcA,EAAM,aAAa,KAAO6qC,EAAM,EAAE,YAAY7qC,EAAM,KAAK,WAAW6qC,EAAM,IAAI,CAAC,oBAAoBA,EAAM,EAAE,kCAAkCA,EAAM,KAAK,kBACjUA,GAASA,EAAM,EAAE,CAChC,4FAAkI7qC,EAAM,MAAQ,GAAK,GAAMA,EAAM,kBAAoB,GAAG,uCAAuCA,EAAM,QAAU,GAAK,MAAM,qCAAqCA,EAAM,SAAW,EAAE,yDAA0D,CAACA,EAAM,gBAAkBA,EAAM,QAAW,OAAS,EAAE,WAAWA,EAAM,WAAa,SAAW,UAAU,iBAAiBA,EAAM,WAAaA,EAAM,KAAK,mBAAqBA,EAAM,KAAK,WAAWA,EAAM,aAAa,IAAI,CAAC,SAASA,EAAM,WAAa,KAAO,OAAOA,EAAM,aAAa,EAAE,EAAE,0FACznBg2C,EAAIh2C,EAAM,4BAA6B,CAAC6gD,EAAmBrtD,IAClDkvB,6BAAgClvB,CAAC,qBAAqBwM,EAAM,4BAA4B,SAAW,GAAKA,EAAM,4BAA4B,CAAC,EAAE,WAAa,GAAK,OAAS,EAAE,wBAC/KA,EAAM,WACFA,EAAM,KAAK,mBAEX6gD,EAAkB,SACdA,EAAkB,SAElB7gD,EAAM,4BAA4B,OAAS,EACvCA,EAAM,KAAK,WAAW,OACtBA,EAAM,KAAK,WAAWA,EAAM,aAAa,IAAI,CAG3E,gCAAgDxM,IAAM,GAAK,CAACwM,EAAM,YAAcA,EAAM,aAAa,KAAO,GAAK,kBAAoB,EAAE,YAAY,eAAe,KAAK,KAAK6gD,EAAkB,OAAO,OAAS7gD,EAAM,UAAU,CAAC,EAAE,8CAA8CA,EAAM,WAAa,UAAY,MAAM,iCAAiCxM,CAAC,SAASwM,EAAM,WAAa,iBAAmB,IAAI,KACzX0gD,EAAUG,EAAkB,OAAQ7gD,EAAM,WAAyB,KAAK,CACtF,eACiB6gD,GAAqBA,EAAkB,QAAQ,CAChE,yDAAqE7gD,EAAM,QAAU,OAAS,EAAE,6BAA6BA,EAAM,KAAK,cAAc,kCAC1I0gD,EAAU1gD,EAAM,iBAAmC,GAAoB,KAAK,CACxF,4IAMQ8gD,EAA0B,CAAC5C,EAAe4B,IAAa,CAC3D,UAAWxpB,KAAWnyB,EAAU,iBAAiB,IAAI+5C,CAAa,GAAG,EACnE4B,EAASxpB,EAASA,EAAQ,aAAa4nB,CAAa,CAAC,CAEzD,EAEA,GAAIoC,EAAa,CACfn8C,EAAU,YAAYy8C,CAAO,EAK7B,UAAWG,IAAa,CAAC,QAAS,WAAY,QAAS,UAAW,OAAO,EACvED,EAAwB,WAAWC,CAAS,GAAI,CAACzqB,EAAS0qB,IAAiB,CACzE1qB,EAAQ,iBAAiByqB,EAAWZ,EAAOa,CAAY,CAAC,CAC1D,CAAC,EAIHF,EAAwB,WAAY,CAACxqB,EAAS2qB,IAAQ,CACpDhoC,EAAKgoC,CAAG,EAAI3qB,CACd,CAAC,EAGDqlB,EAAY,iBAAiB,QAAS,IAAM,CAC1Cx3C,EAAU,YAAYy8C,CAAO,CAC/B,CAAC,CACH,CAGAE,EAAwB,cAAe,CAACxqB,EAAS4qB,IAAW,CAC1D,IAAIC,EAAed,EAAc,IAAIa,CAAM,EACtCC,GACHd,EAAc,IAAIa,EAASC,EAAe,IAAI,OAAS,EAIpDA,EAAa,IAAI7qB,CAAO,IAC3B6qB,EAAa,IAAI7qB,CAAO,EACxB8pB,EAAQc,CAAM,EAAE5qB,CAAO,EAE3B,CAAC,CACH,CAGA,MAAM8qB,GAAK,OAAO,gBAAmB,WAAa,eAAiBtB,GAAY,QAAQ,QAAO,EAAG,KAAKA,CAAQ,EAE9G,SAASuB,GAAa1F,EAAa,CACjC,IAAI2F,EAAY,GACZC,EAEJ,MAAMC,EAAmB,IAAI,IACvBC,EAAiB,IAAI,IAE3B,IAAIC,EAEJ,MAAMC,EAAQ,IAAM,CAClB,GAAIL,EACF,OAEF,MAAMM,EAAiB,CAAC,GAAGH,CAAc,EACzCA,EAAe,MAAK,EACpB,GAAI,CACF,UAAWI,KAAYD,EACrBC,EAAQ,CAEZ,QAAC,CACCH,EAAS,GACLD,EAAe,OACjBC,EAAS,GACTN,GAAGO,CAAK,EAEZ,CACF,EAEM3hD,EAAQ,IAAI,MAAM,GAAI,CAC1B,IAAKqE,EAAQ9L,EAAM,CACjB,GAAIgpD,EAAiB,CACnB,IAAIO,EAAYN,EAAiB,IAAIjpD,CAAI,EACpCupD,IACHA,EAAY,IAAI,IAChBN,EAAiB,IAAIjpD,EAAMupD,CAAS,GAEtCA,EAAU,IAAIP,CAAe,CAC/B,CACA,OAAOl9C,EAAO9L,CAAI,CACpB,EACA,IAAK8L,EAAQ9L,EAAM+lD,EAAU,CAC3B,GAAIj6C,EAAO9L,CAAI,IAAM+lD,EAAU,CAC7Bj6C,EAAO9L,CAAI,EAAI+lD,EACf,MAAMwD,EAAYN,EAAiB,IAAIjpD,CAAI,EAC3C,GAAIupD,EAAW,CACb,UAAWD,KAAYC,EACrBL,EAAe,IAAII,CAAQ,EAExBH,IACHA,EAAS,GACTN,GAAGO,CAAK,EAEZ,CACF,CACA,MAAO,EACT,CACJ,CAAG,EAEKI,EAAgBjC,GAAa,CACjC,MAAMkC,EAAW,IAAM,CACrB,MAAMC,EAAcV,EACpBA,EAAkBS,EAClB,GAAI,CACF,OAAOlC,EAAQ,CACjB,QAAC,CACCyB,EAAkBU,CACpB,CACF,EACA,OAAOD,EAAQ,CACjB,EAGA,OAAArG,EAAY,iBAAiB,QAAS,IAAM,CAC1C2F,EAAY,EACd,CAAC,EAEM,CACL,MAAAthD,EACA,aAAA+hD,CACJ,CACA,CAGA,SAASG,GAA0BtyC,EAAMC,EAAOsyC,EAAc,CAC5D,GAAIvyC,EAAK,SAAWC,EAAM,OACxB,MAAO,GAET,QAAS,EAAI,EAAG,EAAID,EAAK,OAAQ,IAC/B,GAAI,CAACuyC,EAAavyC,EAAK,CAAC,EAAGC,EAAM,CAAC,CAAC,EACjC,MAAO,GAGX,MAAO,EACT,CAEA,MAAMuyC,GAA4B,IAAI,QAEtC,SAASC,GAA4B9jB,EAAMod,EAAahK,EAAU,CAEhE,CAEE,MAAMj6C,EAAO6mC,EAAK,QAAQ,WAAW,EAErC,IAAIsjB,EAAWO,GAA0B,IAAI1qD,CAAI,EAC5CmqD,IAIHA,EAAW,IAAI,qBAAqBlQ,EAAU,CAC5C,KAAAj6C,EAEA,WAAY,kBAEZ,UAAW,CACnB,CAAO,EAGD0qD,GAA0B,IAAI1qD,EAAMmqD,CAAQ,EAG5ClG,EAAY,iBAAiB,QAAS,IAAM,CAC1CkG,EAAS,WAAU,CACrB,CAAC,GAGHA,EAAS,QAAQtjB,CAAI,CACvB,CACF,CAKA,MAAM+jB,GAAc,GAEd,CAAE,OAAAC,EAAM,EAAK,OAEnB,SAASC,GAAYC,EAAYj+B,EAAO,CACtC,MAAMvL,EAAO,GACPypC,EAAkB,IAAI,gBACtB/G,EAAc+G,EAAgB,OAC9B,CAAE,MAAA1iD,EAAO,aAAA+hD,GAAiBV,GAAY1F,CAAW,EACjD0E,EAAgB,IAAI,IAG1BkC,GAAOviD,EAAO,CACZ,cAAe,OACf,KAAM,OACN,SAAU,OACV,YAAa,OACb,sBAAuB,OACvB,aAAc,MAClB,CAAG,EAGDuiD,GAAOviD,EAAOwkB,CAAK,EAGnB+9B,GAAOviD,EAAO,CACZ,YAAa,GACb,cAAe,GACf,4BAA6B,GAC7B,cAAe,GACf,WAAY,GACZ,WAAY,GACZ,iBAAkB,GAClB,QAAS,OACT,uBAAwB,GACxB,qCAAsC,GACtC,gBAAiB,EACjB,eAAgB,EAChB,mBAAoB,OACpB,YAAa,OACb,oBAAqB,GACrB,UAAW,GACX,iBAAkB,GAClB,sBAAuB,OACvB,WAAYy5C,GACZ,MAAO,GACP,kBAAmB,EACnB,OAAQP,GACR,eAAgB,GAChB,mBAAoB,MACxB,CAAG,EAKD6I,EAAa,IAAM,CACb/hD,EAAM,eAAiBA,EAAM,OAAOA,EAAM,iBAAiB,IAC7DA,EAAM,aAAeA,EAAM,OAAOA,EAAM,iBAAiB,EAE7D,CAAC,EAMD,MAAM2iD,EAAQvjD,GAAM,CAClBqjD,EAAW,eAAerjD,CAAE,EAAE,MAAK,CACrC,EAEM+8C,EAAiBxJ,GAAS8P,EAAW,eAAe,OAAO9P,EAAM,EAAE,EAAE,EAGrEiQ,EAAY,CAAClsD,EAAM6iB,IAAW,CAClCN,EAAK,YAAY,cAAc,IAAI,YAAYviB,EAAM,CACnD,OAAA6iB,EACA,QAAS,GACT,SAAU,EAChB,CAAK,CAAC,CACJ,EAMMspC,EAAqB,CAACjvD,EAAGM,IAAMN,EAAE,KAAOM,EAAE,GAE1C4uD,EAAqC,CAAClvD,EAAGM,IAAM,CACnD,KAAM,CAAE,SAAU6uD,EAAW,OAAQC,CAAO,EAAKpvD,EAC3C,CAAE,SAAUqvD,GAAW,OAAQC,CAAO,EAAKhvD,EAEjD,OAAI6uD,IAAcE,GACT,GAGFf,GAAyBc,EAASE,EAASL,CAAkB,CACtE,EAOMM,EAAuBC,GAAc,CACpClB,GAAyBliD,EAAM,cAAeojD,EAAWP,CAAkB,IAC9E7iD,EAAM,cAAgBojD,EAE1B,EAGMC,EAAoBC,GAAkB,CACtCtjD,EAAM,aAAesjD,IACvBtjD,EAAM,WAAasjD,EAEvB,EAGMC,EAAqCC,GAA4B,CAChEtB,GAAyBliD,EAAM,4BAA6BwjD,EAAyBV,CAAkC,IAC1H9iD,EAAM,4BAA8BwjD,EAExC,EAIM/C,EAAkB,CAAC9N,EAAO8Q,IAC7BA,GAAmB9Q,EAAM,OAASA,EAAM,MAAM8Q,CAAe,GAAM9Q,EAAM,QAetEuN,EAAU,CACd,cAboB,CAACvN,EAAO8Q,IAC5BhH,GAAK,CACF9J,EAAM,MAAQ8N,EAAgB9N,EAAO8Q,CAAe,EACrD9Q,EAAM,WACN,GAAIA,EAAM,YAAc2P,EAC9B,EAAM,OAAO,OAAO,CAAC,EAAE,KAAK,IAAI,EAQb,cALM3P,GACrBA,EAAM,aAAeA,EAAM,YAAc2P,IAAa,KAAK,IAAI,EAIjC,gBAAA7B,CAClC,EACQN,EAAS,CACb,sBAAAuD,EACA,aAAAC,GACA,WAAAC,GACA,aAAAC,GACA,gBAAAC,GACA,uBAAAC,GACA,0BAAAC,GACA,yBAAAC,GACA,uBAAAC,GACA,cAAAC,EACJ,EACQ/D,EAAU,CACd,wBAAAgE,EACA,qBAAAC,CACJ,EAEE,IAAI/D,EAAc,GAClByB,EAAa,IAAM,CACjB9B,GAAOwC,EAAYziD,EAAOkgD,EAASC,EAAQC,EAASnnC,EAAM0iC,EAAa0E,EAAeC,CAAW,EACjGA,EAAc,EAChB,CAAC,EAOItgD,EAAM,cACTu6C,GAAuB,EAAG,KAAKxvC,GAAS,CAGjCA,IACH/K,EAAM,QAAUA,EAAM,KAAK,wBAE/B,CAAC,EAOH+hD,EAAa,IAAM,CAEjB,eAAeuC,GAAyB,CACtC,IAAIC,EAAwB,GAC5B,MAAMC,EAAgB,WAAW,IAAM,CACrCD,EAAwB,GACxBvkD,EAAM,QAAUA,EAAM,KAAK,cAC7B,EAAGu5C,EAA8B,EACjC,GAAI,CACF,MAAMv5C,EAAM,SAAS,MAAK,EAC1BA,EAAM,eAAiB,EACzB,OAASO,EAAK,CACZ,QAAQ,MAAMA,CAAG,EACjBP,EAAM,QAAUA,EAAM,KAAK,mBAC7B,QAAC,CACC,aAAawkD,CAAa,EACtBD,IACFA,EAAwB,GACxBvkD,EAAM,QAAU,GAEpB,CACF,CAEIA,EAAM,UAERskD,EAAqB,CAEzB,CAAC,EAMDvC,EAAa,IAAM,CACjB/hD,EAAM,YAAc;AAAA,sBACFA,EAAM,OAAO,MAAM;AAAA,6BACZA,EAAM,WAAa,EAAI,CAAC;AAAA,yBAC5Bm5C,EAAc,GACrC,CAAC,EAMD4I,EAAa,IAAM,CACb/hD,EAAM,aAAeA,EAAM,UAC7BykD,GAEJ,CAAC,EAED1C,EAAa,IAAM,CACb/hD,EAAM,aAAeA,EAAM,YAAY,OACrCA,EAAM,SAAWi5C,KACnBj5C,EAAM,OAASi5C,IAERj5C,EAAM,SAAWk5C,KACtBl5C,EAAM,mBAGRA,EAAM,oBAERA,EAAM,OAASk5C,GAEnB,CAAC,EAMD6I,EAAa,IAAM,CACjB,eAAe2C,GAA2B,CACpC1kD,EAAM,iBACRA,EAAM,gBAAkB,MAAMA,EAAM,SAAS,qBAAoB,EAErE,CAEe0kD,EAAuB,CACxC,CAAC,EAED3C,EAAa,IAAM,CACjB/hD,EAAM,UAAY,MAAMm5C,EAAc,EAAE,KAAI,EAAG,IAAI,CAAC3kD,EAAGhB,IAAMsnD,GAAc96C,EAAM,cAAexM,CAAC,CAAC,CACpG,CAAC,EAEDuuD,EAAa,IAAM,CACjB/hD,EAAM,mBAAqBA,EAAM,UAAUA,EAAM,eAAe,CAClE,CAAC,EAED+hD,EAAa,IAAM,CACjB/hD,EAAM,oBAAsBA,EAAM,KAAK,cAAc,QAAQ,aAAcA,EAAM,KAAK,UAAUA,EAAM,eAAe,CAAC,CACxH,CAAC,EAMD+hD,EAAa,IAAM,CACjB,eAAe4C,GAA+B,CAC5C,KAAM,CAAE,SAAAC,CAAQ,EAAK5kD,EACf6kD,GAAQ,MAAM,QAAQ,IAAInL,GAAyB,IAAItE,GAC3DwP,EAAS,wBAAwBxP,CAAO,CACzC,CAAC,GAAG,OAAO,OAAO,EACnBp1C,EAAM,sBAAwB6kD,CAChC,CAEI7kD,EAAM,gBACO2kD,EAA2B,CAE9C,CAAC,EAED,SAASF,GAAqB,CAG5B,KAAM,CAAE,YAAApN,EAAa,SAAAuN,CAAQ,EAAK5kD,EAC5B8kD,EAAsBzN,GAAeiL,GACvCsC,EAAS,cAAgBE,IAG3BF,EAAS,YAAcE,EAE3B,CAEA/C,EAAa,IAAM,CACjB,eAAegD,GAAmB,CAChCN,IACA,KAAM,CAAE,SAAAG,EAAU,sBAAAI,EAAuB,WAAAC,CAAU,EAAKjlD,EAClDklD,GAAc,MAAMN,EAAS,oBAAoBK,CAAU,EAC3DE,EAAY,MAAMC,GAAgBpV,GAAO,CAC7C,GAAGkV,GACH,GAAGF,CACX,EAASxwD,IAAMA,GAAE,SAAWA,GAAE,IAAK,EAAE,MAAM,EAAGywD,CAAU,CAAC,EACnDjlD,EAAM,iBAAmBmlD,CAC3B,CAEInlD,EAAM,gBAAkBA,EAAM,uBACjB+kD,EAAe,CAElC,CAAC,EAaD,SAASX,EAAyB7lB,EAAM,CACtCmd,GAAqBnd,EAAMod,EAAa,IAAM,CAE5C,CAEE,MAAM0J,EAAQ,iBAAiBpsC,EAAK,WAAW,EACzCqsC,EAAgB,SAASD,EAAM,iBAAiB,eAAe,EAAG,EAAE,EACpEE,EAAWF,EAAM,iBAAiB,WAAW,IAAM,MAGzDrlD,EAAM,WAAaslD,EACnBtlD,EAAM,MAAQulD,CAChB,CACF,CAAC,CACH,CAIA,SAASlB,EAAsB9lB,EAAM,CACnC8jB,GAA2B9jB,EAAMod,EAAcvwC,GAAY,CACzD,SAAW,CAAE,OAAA/G,EAAQ,eAAAmhD,CAAc,IAAMp6C,EACvC/G,EAAO,UAAU,OAAO,WAAYmhD,CAAc,CAEtD,CAAC,CACH,CAOAzD,EAAa,IAAM,CACjB,eAAe0D,GAAgB,CAC7B,KAAM,CAAE,WAAAC,EAAY,aAAAC,EAAc,eAAAC,EAAgB,YAAAvO,EAAW,EAAKr3C,EAClE,GAAI,CAAC4lD,EACH5lD,EAAM,cAAgB,GACtBA,EAAM,WAAa,WACV0lD,EAAW,QAAUzT,GAAwB,CACtD,MAAMmR,EAAY,MAAMyC,GAAuBH,CAAU,EACrD1lD,EAAM,aAAe0lD,IACvBvC,EAAoBC,CAAS,EAC7BC,EAAiB,EAAI,EAEzB,KAAO,CACL,KAAM,CAAE,GAAIyC,CAAc,EAAKH,EAE/B,GAAIG,IAAmB,IAAOzO,IAAeA,GAAY,OAAS,CAChE,MAAM+L,GAAY,MAAM2C,GAAiBD,CAAc,EACnD9lD,EAAM,aAAa,KAAO8lD,IAC5B3C,EAAoBC,EAAS,EAC7BC,EAAiB,EAAK,EAE1B,CACF,CACF,CAEeoC,EAAY,CAC7B,CAAC,EAED,MAAMO,EAAsB,IAAM,CAChCxK,GAAI,IAAMkB,GAAyBzjC,EAAK,eAAe,CAAC,CAC1D,EAKA8oC,EAAa,IAAM,CACjB,KAAM,CAAE,cAAAkE,EAAe,aAAAC,CAAY,EAAKlmD,EAClCi8C,EAAmBgK,EACtB,OAAOtT,GAASA,EAAM,OAAO,EAC7B,OAAOA,GAAS0G,GAAO1G,CAAK,GAAK,CAAC6H,GAAmB,IAAI7H,EAAM,OAAO,CAAC,EAC1E,GAAI,CAACuT,GAAgBjK,EAAiB,OAEpCkH,EAAoB8C,CAAa,EACjCzK,GAAI,IAAM2K,EAAyBlK,CAAgB,CAAC,MAC/C,CACL,MAAMmH,EAAY8C,EAAeD,EAAgBA,EAAc,OAAOG,EAAc,EACpFjD,EAAoBC,CAAS,EAE7B4C,EAAmB,CACrB,CACF,CAAC,EAED,SAASG,EAA0BlK,EAAkB,CAC9BD,GAAgBC,EAAkBhjC,EAAK,cAAekjC,CAAc,EAGvF6J,EAAmB,EAInBhmD,EAAM,cAAgB,CAAC,GAAGA,EAAM,aAAa,CAEjD,CAEA,SAASomD,GAAgBzT,EAAO,CAC9B,MAAO,CAACA,EAAM,SAAW,CAAC0G,GAAO1G,CAAK,GAAK6H,GAAmB,IAAI7H,EAAM,OAAO,CACjF,CAEA,eAAe0T,GAAuBlW,EAAQ,CAC5C,MAAMiL,EAAoBp7C,EAAM,cAAgB,MAAMu6C,GAAuB,EAE7E,OAAOpK,EAAO,OAAO,CAAC,CAAE,QAAAyC,CAAO,IAAO,CAACA,GAAWA,GAAWwI,CAAiB,CAChF,CAEA,eAAegK,GAAiBjV,EAAQ,CACtC,OAAOgL,GAAqBhL,EAAQnwC,EAAM,cAAgB,MAAMu6C,GAAuB,CAAE,CAC3F,CAEA,eAAewL,GAAkBlb,EAAO,CAEtC,MAAM8H,EAAQ9H,IAAU,GAAK7qC,EAAM,YAAc,MAAMA,EAAM,SAAS,gBAAgB6qC,CAAK,EAC3F,OAAOua,GAAgB,MAAMiB,GAAsB1T,CAAK,CAAC,CAC3D,CAEA,eAAekT,GAAwBznC,EAAO,CAC5C,OAAOgnC,GAAgB,MAAMiB,GAAsB,MAAMrmD,EAAM,SAAS,sBAAsBoe,CAAK,CAAC,CAAC,CACvG,CAEA2jC,EAAa,IAAM,CACnB,CAAC,EAODA,EAAa,IAAM,CACjB,SAASuE,GAAwC,CAC/C,KAAM,CAAE,WAAA3F,EAAY,cAAAsF,CAAa,EAAKjmD,EACtC,GAAI2gD,EACF,MAAO,CACL,CACE,SAAU,GACV,OAAQsF,CACpB,CACA,EAEM,MAAMM,GAAoB,IAAI,IAC9B,UAAW5T,KAASsT,EAAe,CACjC,MAAM1K,GAAW5I,EAAM,UAAY,GACnC,IAAIxC,GAASoW,GAAkB,IAAIhL,EAAQ,EACtCpL,KACHA,GAAS,GACToW,GAAkB,IAAIhL,GAAUpL,EAAM,GAExCA,GAAO,KAAKwC,CAAK,CACnB,CACA,MAAO,CAAC,GAAG4T,GAAkB,QAAO,CAAE,EACnC,IAAI,CAAC,CAAChL,EAAUpL,EAAM,KAAO,CAAE,SAAAoL,EAAU,OAAApL,IAAS,EAClD,KAAK,CAACv8C,EAAGM,KAAM8L,EAAM,sBAAsBpM,EAAE,SAAUM,GAAE,QAAQ,CAAC,CACvE,CAEA,MAAMsvD,EAA0B8C,EAAoC,EACpE/C,EAAkCC,CAAuB,CAC3D,CAAC,EAMDzB,EAAa,IAAM,CACjB/hD,EAAM,mBAAqBA,EAAM,mBAAqB,IAAMA,EAAM,cAAcA,EAAM,gBAAgB,EAAE,EAC1G,CAAC,EAMD+hD,EAAa,IAAM,CACjB,KAAM,CAAE,cAAAyE,CAAa,EAAKxmD,EAC1Bo5C,GAAI,IAAM,CACRp5C,EAAM,YAAcwmD,GAAiB,IAAI,KAAI,EAC7CxmD,EAAM,iBAAmB,EAC3B,CAAC,CACH,CAAC,EAED,SAAS8jD,GAAiBl/C,EAAO,CAC/B,GAAI,CAAC5E,EAAM,YAAc,CAACA,EAAM,cAAc,OAC5C,OAGF,MAAMymD,EAAsBC,GAAa,CACvC1L,GAAKp2C,CAAK,EACV5E,EAAM,iBAAmBi7C,GAAqByL,EAAU1mD,EAAM,iBAAkBA,EAAM,aAAa,CACrG,EAEA,OAAQ4E,EAAM,IAAG,CACf,IAAK,YACH,OAAO6hD,EAAmB,EAAK,EACjC,IAAK,UACH,OAAOA,EAAmB,EAAI,EAChC,IAAK,QACH,GAAIzmD,EAAM,mBAAqB,GAE7BA,EAAM,iBAAmB,MAEzB,QAAAg7C,GAAKp2C,CAAK,EACH+hD,GAAW3mD,EAAM,cAAcA,EAAM,gBAAgB,EAAE,EAAE,CAE1E,CACE,CAMA,SAAS4jD,GAAYh/C,EAAO,CAC1B,KAAM,CAAE,OAAAP,CAAM,EAAKO,EACbgiD,EAAgBviD,EAAO,QAAQ,aAAa,EAElD,GAAI,CAACuiD,EACH,OAEF,MAAMC,EAAU,SAASD,EAAc,QAAQ,QAAS,EAAE,EAC1D3tC,EAAK,cAAc,MAAQ,GAC3BjZ,EAAM,cAAgB,GACtBA,EAAM,WAAa,GACnBA,EAAM,iBAAmB,GACzBA,EAAM,kBAAoBA,EAAM,OAAO,UAAUxL,IAAKA,GAAE,KAAOqyD,CAAO,CACxE,CAEA,SAAShD,GAAcj/C,EAAO,CAC5B,KAAM,CAAE,OAAAP,EAAQ,IAAAhK,CAAG,EAAKuK,EAElBkiD,EAAU7/B,IAAM,CAChBA,KACF+zB,GAAKp2C,CAAK,EACVqiB,GAAG,MAAK,EAEZ,EAEA,OAAQ5sB,EAAG,CACT,IAAK,YACH,OAAOysD,EAAQziD,EAAO,sBAAsB,EAC9C,IAAK,aACH,OAAOyiD,EAAQziD,EAAO,kBAAkB,EAC1C,IAAK,OACH,OAAOyiD,EAAQziD,EAAO,cAAc,iBAAiB,EACvD,IAAK,MACH,OAAOyiD,EAAQziD,EAAO,cAAc,gBAAgB,CAC5D,CACE,CAEA,eAAe0iD,GAAwBpR,EAAe,CACpD,MAAMhD,EAAQ,MAAM3yC,EAAM,SAAS,wBAAwB21C,CAAa,EAClEqR,EAAe,CAAC,GAAGhnD,EAAM,cAAe,GAAGA,EAAM,gBAAgB,EACpE,KAAKxL,IAAMA,GAAE,KAAOmhD,CAAc,EAC/BsR,EAAmBD,EAAa,SAAWvG,EAAgBuG,EAAchnD,EAAM,eAAe,EACpG,aAAMA,EAAM,SAAS,4BAA4B21C,CAAa,EACvD,CACL,MAAAhD,EACA,SAAU3yC,EAAM,gBAChB,GAAIinD,GAAoB,CAAE,QAASA,GACnC,GAAID,EAAa,MAAQ,CAAE,KAAMA,EAAa,IAAI,CACxD,CACE,CAKA,eAAeL,GAAYhR,EAAe,CACxC,MAAMuR,EAAmBH,GAAuBpR,CAAa,EAE7DiN,EAAU,mBAAoBsE,CAAgB,EAE9CtE,EAAU,cAAe,MAAMsE,CAAgB,CACjD,CAEA,SAASvD,GAAc/+C,EAAO,CAC5B,KAAM,CAAE,OAAAP,CAAM,EAAKO,EAEnB,GAAI,CAACP,EAAO,UAAU,SAAS,OAAO,EAEpC,OAEF22C,GAAKp2C,CAAK,EACV,MAAMxF,EAAKiF,EAAO,GAAG,UAAU,CAAC,EAEjBsiD,GAAWvnD,CAAE,CAC9B,CAMA,SAAS+nD,GAAgBnO,EAAU,CACjCh5C,EAAM,gBAAkBg5C,EACxBh5C,EAAM,uBAAyB,GAC/B2iD,EAAM,iBAAiB,EACvBC,EAAU,mBAAoB,CAAE,SAAA5J,EAAU,EAC3Bh5C,EAAM,SAAS,qBAAqBg5C,CAAQ,CAC7D,CAEA,SAAS+K,GAAwBn/C,EAAO,CACtC,KAAM,CAAE,OAAQ,CAAE,GAAAxF,CAAE,CAAE,EAAKwF,EACrBjJ,EAAQyD,GAAMA,EAAG,MAAM,gBAAgB,EAE7C,GAAI,CAACzD,EACH,OAEFq/C,GAAKp2C,CAAK,EACV,MAAMo0C,EAAW,SAASr9C,EAAM,CAAC,EAAG,EAAE,EACtCwrD,GAAenO,CAAQ,CACzB,CAEA,SAAS0K,EAAuB9+C,EAAO,CACrC5E,EAAM,uBAAyB,CAACA,EAAM,uBACtCA,EAAM,eAAiBA,EAAM,gBAEzBA,EAAM,yBACRg7C,GAAKp2C,CAAK,EACV42C,GAAI,IAAMmH,EAAM,eAAe,CAAC,EAEpC,CAKAZ,EAAa,IAAM,CACb/hD,EAAM,uBACRiZ,EAAK,iBAAiB,iBAAiB,gBAAiB,IAAM,CAC5DjZ,EAAM,qCAAuC,EAC/C,EAAG,CAAE,KAAM,GAAM,EAEjBA,EAAM,qCAAuC,EAEjD,CAAC,EAED,SAASikD,GAA0Br/C,EAAO,CAGxC,GAAI,CAAC5E,EAAM,uBACT,OAEF,MAAMonD,EAAuB,MAAMC,GAAgB,CACjDrM,GAAKp2C,CAAK,EACV5E,EAAM,eAAiBqnD,CACzB,EAEA,OAAQziD,EAAM,IAAG,CACf,IAAK,UACH,OAAOwiD,EAAqBnM,GAAqB,GAAMj7C,EAAM,eAAgBA,EAAM,SAAS,CAAC,EAC/F,IAAK,YACH,OAAOonD,EAAqBnM,GAAqB,GAAOj7C,EAAM,eAAgBA,EAAM,SAAS,CAAC,EAChG,IAAK,OACH,OAAOonD,EAAqB,CAAC,EAC/B,IAAK,MACH,OAAOA,EAAqBpnD,EAAM,UAAU,OAAS,CAAC,EACxD,IAAK,QAGH,OAAAg7C,GAAKp2C,CAAK,EACHuiD,GAAennD,EAAM,cAAc,EAC5C,IAAK,SACH,OAAAg7C,GAAKp2C,CAAK,EACV5E,EAAM,uBAAyB,GACxB2iD,EAAM,iBAAiB,CACtC,CACE,CAEA,SAASuB,GAAwBt/C,EAAO,CAGtC,GAAK5E,EAAM,wBAGH4E,EAAM,MACP,IAGH,OAAAo2C,GAAKp2C,CAAK,EACHuiD,GAAennD,EAAM,cAAc,CAEhD,CAEA,eAAegkD,GAA2Bp/C,EAAO,CAE/C,KAAM,CAAE,cAAA0iD,CAAa,EAAK1iD,GAGtB,CAAC0iD,GAAiBA,EAAc,KAAO,mBACzCtnD,EAAM,uBAAyB,GAEnC,CAEA,SAASmkD,GAAev/C,EAAO,CAC7B5E,EAAM,cAAgB4E,EAAM,OAAO,KACrC,CAEA,MAAO,CACL,KAAM2iD,EAAU,CACdhF,GAAOviD,EAAOunD,CAAQ,CACxB,EACA,UAAY,CACV7E,EAAgB,MAAK,CACvB,CACJ,CACA,CAEA,MAAM5S,GAAsB,mFACtBC,GAAiB,KAEvB,IAAIyX,GAAS,CACX,gBAAiB,aACjB,wBAAyB,6CACzB,eAAgB,YAChB,eAAgB,WAChB,oBAAqB,wBACrB,YAAa,eACb,kBAAmB,qFACnB,YAAa,SACb,mBAAoB,iBACpB,oBAAqB,iEACrB,cAAe,4CACf,eAAgB,aAChB,UAAW,CACT,UACA,QACA,eACA,SACA,cACA,MACJ,EACE,WAAY,CACV,OAAQ,SACR,kBAAmB,wBACnB,cAAe,kBACf,iBAAkB,qBAClB,aAAc,iBACd,gBAAiB,oBACjB,WAAY,aACZ,QAAS,UACT,QAAS,UACT,MAAO,OACX,CACA,EAEIC,GAAa,kyLAEjB,MAAMC,GAAQ,CACZ,cACA,wBACA,WACA,aACA,OACA,SACA,gBACA,cACF,EAGMC,GAAe,6BAA6BhO,EAAW,IAE7D,MAAMiO,WAAsB,WAAY,CACtC,YAAapjC,EAAO,CAClB,MAAK,EACL,KAAK,aAAa,CAAE,KAAM,MAAM,CAAE,EAClC,MAAM6gC,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,YAAcoC,GAAaE,GACjC,KAAK,WAAW,YAAYtC,CAAK,EACjC,KAAK,KAAO,CAEV,OAAQtV,GACR,WAAYD,GACZ,cAAe0J,GACf,sBAAuBI,GACvB,YAAa,KACb,KAAM4N,GACN,aAAc,KACd,GAAGhjC,CACT,EAEI,UAAWjsB,KAAQmvD,GACbnvD,IAAS,YAAc,OAAO,UAAU,eAAe,KAAK,KAAMA,CAAI,IACxE,KAAK,KAAKA,CAAI,EAAI,KAAKA,CAAI,EAC3B,OAAO,KAAKA,CAAI,GAGpB,KAAK,SAAQ,CACf,CAEA,mBAAqB,CACnBsvD,GAAuB,IAAI,EAGtB,KAAK,OACR,KAAK,KAAOrF,GAAW,KAAK,WAAY,KAAK,IAAI,EAErD,CAEA,sBAAwB,CACtBqF,GAAuB,IAAI,EAG3BzG,GAAG,IAAM,CAEP,GAAI,CAAC,KAAK,aAAe,KAAK,KAAM,CAClC,KAAK,KAAK,SAAQ,EAClB,KAAK,KAAO,OAEZ,KAAM,CAAE,SAAAwD,GAAa,KAAK,KAC1BA,EAAS,MAAK,EAEX,MAAMrkD,GAAO,QAAQ,MAAMA,CAAG,CAAC,CACpC,CACF,CAAC,CACH,CAEA,WAAW,oBAAsB,CAC/B,MAAO,CAAC,SAAU,cAAe,kBAAmB,eAAe,CACrE,CAEA,yBAA0BunD,EAAUC,EAAUzJ,EAAU,CACtD,KAAK,KAGHwJ,EAAS,QAAQ,YAAa,CAACtzD,EAAGwzD,IAAOA,EAAG,aAAa,EAEzDF,IAAa,gBAAkB,WAAWxJ,CAAQ,EAAIA,CAC5D,CACE,CAEA,KAAM/lD,EAAM+lD,EAAU,CACpB,KAAK,KAAK/lD,CAAI,EAAI+lD,EACd,KAAK,MACP,KAAK,KAAK,KAAK,CAAE,CAAC/lD,CAAI,EAAG+lD,CAAQ,CAAE,EAEjC,CAAC,SAAU,YAAY,EAAE,SAAS/lD,CAAI,GACxC,KAAK,SAAQ,CAEjB,CAEA,WAAa,CACX,KAAM,CAAE,OAAAqgD,EAAQ,WAAAf,EAAY,SAAA+M,CAAQ,EAAK,KAAK,MAE1C,CAACA,GAAYA,EAAS,SAAWhM,GAAUgM,EAAS,aAAe/M,IACrE,KAAK,KAAK,WAAY,IAAIc,GAAS,CAAE,OAAAC,EAAQ,WAAAf,CAAU,CAAE,CAAC,CAE9D,CAIA,UAAY,CACVuJ,GAAG,IACD,KAAK,UAAS,CACf,CACH,CACF,CAEA,MAAM6G,GAAc,GAEpB,UAAW1vD,KAAQmvD,GACjBO,GAAY1vD,CAAI,EAAI,CAClB,KAAO,CACL,OAAIA,IAAS,YAGX,KAAK,UAAS,EAET,KAAK,KAAKA,CAAI,CACvB,EACA,IAAKC,EAAK,CACR,GAAID,IAAS,WACX,MAAM,IAAI,MAAM,uBAAuB,EAEzC,KAAK,KAAKA,EAAMC,CAAG,CACrB,CACJ,EAGA,OAAO,iBAAiBovD,GAAc,UAAWK,EAAW,EAI5D,SAASJ,GAAwBvxB,EAAS,CAElCA,aAAmBsxB,IACvB,OAAO,eAAetxB,EAAS,eAAe,IAAIA,EAAQ,QAAQ,aAAa,EAAE,SAAS,CAE9F,CAGK,eAAe,IAAI,cAAc,GACpC,eAAe,OAAO,eAAgBsxB,EAAa,EC1vDrD,SAASM,GAASjhC,EAA+B,CAE/CA,EAAG,MAAM,OAAS,IAClB,MAAMkhC,EAAU,KAAK,IAAIlhC,EAAG,aAAc,EAAE,EAC5CA,EAAG,MAAM,OAAS,GAAGkhC,CAAO,KAC5BlhC,EAAG,MAAM,UAAYA,EAAG,aAAeA,EAAG,aAAe,OAAS,QACpE,CAGA,SAASmhC,GAAUnhC,EAA+B,CAChDA,EAAG,MAAM,OAAS,OAClBA,EAAG,MAAM,UAAY,QACvB,CAkEA,MAAM1jB,GAA+B,IAErC,SAAS8kD,GAA0B/+C,EAAsD,CACvF,OAAKA,EAGDA,EAAO,OACFoZ;AAAAA;AAAAA,UAEDD,EAAM,MAAM;AAAA;AAAA,MAMhBnZ,EAAO,aACO,KAAK,MAAQA,EAAO,YACtB/F,GACLmf;AAAAA;AAAAA,YAEDD,EAAM,KAAK;AAAA;AAAA,QAMdgB,EAvBaA,CAwBtB,CAEA,MAAM6kC,GAAuB,EAAI,KAAO,KAExC,SAASC,IAA+B,CACtC,MAAO,OAAO,KAAK,KAAK,IAAI,KAAK,SAAS,SAAS,EAAE,EAAE,MAAM,EAAG,CAAC,CAAC,EACpE,CAEA,SAASC,GAAoBvhC,EAAiB3pB,EAAiB,WAE7D,IAAImrD,GAAQr0D,EAAA6yB,EAAG,QAAQ,OAAO,IAAlB,YAAA7yB,EAAqB,cAAc,0BAC/C,GAAI,CAACq0D,EAAO,CACVA,EAAQ,SAAS,cAAc,KAAK,EACpCA,EAAM,UAAY,uCAClBA,EAAM,MAAM,QAAU,sDACtB,MAAMC,GAAUr0D,EAAA4yB,EAAG,QAAQ,OAAO,IAAlB,YAAA5yB,EAAqB,cAAc,kBACnDguB,EAAAqmC,GAAA,YAAAA,EAAS,gBAAT,MAAArmC,EAAwB,aAAaomC,EAAOC,EAC9C,CACAD,EAAM,YAAcnrD,EACpB,WAAW,IAAMmrD,GAAA,YAAAA,EAAO,SAAU,GAAI,CACxC,CAEA,MAAME,GAAkB,+EAExB,SAASC,GAAYtrC,EAAqB,CACxC,OAAOA,EAAK,KAAK,WAAW,QAAQ,GAClC,mCAAmC,KAAKA,EAAK,IAAI,CACrD,CAEA,SAASurC,GAAWvrC,EAAqB,CACvC,OAAOA,EAAK,KAAK,WAAW,OAAO,GACjCA,EAAK,OAAS,oBACdA,EAAK,OAAS,mBACdqrC,GAAgB,KAAKrrC,EAAK,IAAI,CAClC,CAEA,SAASwrC,GAAUxrC,EAAqB,CACtC,OAAOA,EAAK,OAAS,mBAAqB,UAAU,KAAKA,EAAK,IAAI,CACpE,CAEA,SAASyrC,GAAYzrC,EAAqB,CACxC,OAAOA,EAAK,KAAK,WAAW,QAAQ,GAClC,iCAAiC,KAAKA,EAAK,IAAI,CACnD,CAGA,SAAS0rC,GAAsB1rC,EAAYkH,EAAkB,CAC3D,GAAI,CAACA,EAAM,oBAAqB,OAChC,MAAMykC,EAAU,SAAS,cAAc,OAAO,EAE9C,GAAIL,GAAYtrC,CAAI,EAAG,CACrB,GAAIA,EAAK,KAAOgrC,GAAsB,CAChCW,GAAST,GAAoBS,EAAS,qBAAqB3rC,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EAC1H,MACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMmc,EAAyB,CAAE,GAAIX,KAAwB,QAASxb,EAAO,OAAkB,SAAUzvB,EAAK,OAC9GlpB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAIA,EAAM,aAAe,GAAK0kC,CAAM,EACnE,EACAnc,EAAO,cAAczvB,CAAI,CAC3B,SAAWurC,GAAWvrC,CAAI,EAAG,CAC3B,GAAIA,EAAK,KAAOgrC,GAAsB,CAChCW,GAAST,GAAoBS,EAAS,oBAAoB3rC,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EACzH,MACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMmc,EAAyB,CAAE,GAAIX,GAAA,EAAwB,QAAS,GAAI,SAAUjrC,EAAK,MAAQ,aAAc,SAAUA,EAAK,KAAM,YAAayvB,EAAO,SACxJ34C,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAIA,EAAM,aAAe,GAAK0kC,CAAM,EACnE,EACAnc,EAAO,WAAWzvB,CAAI,CACxB,SAAWwrC,GAAUxrC,CAAI,EAAG,CAC1B,GAAIA,EAAK,KAAOgrC,GAAsB,CAChCW,GAAST,GAAoBS,EAAS,mBAAmB3rC,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EACxH,MACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMmc,EAAyB,CAAE,GAAIX,GAAA,EAAwB,QAASxb,EAAO,OAAkB,SAAU,kBAAmB,SAAUzvB,EAAK,OAC3IlpB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAIA,EAAM,aAAe,GAAK0kC,CAAM,EACnE,EACAnc,EAAO,cAAczvB,CAAI,CAC3B,SAAWyrC,GAAYzrC,CAAI,EAAG,CAC5B,GAAIA,EAAK,KAAOgrC,GAAsB,CAChCW,GAAST,GAAoBS,EAAS,qBAAqB3rC,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EAC1H,MACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMmc,EAAyB,CAAE,GAAIX,GAAA,EAAwB,QAASxb,EAAO,OAAkB,SAAUzvB,EAAK,MAAQ,YAAa,SAAUA,EAAK,OAClJlpB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAIA,EAAM,aAAe,GAAK0kC,CAAM,EACnE,EACAnc,EAAO,cAAczvB,CAAI,CAC3B,MACM2rC,GAAST,GAAoBS,EAAS,0BAA0B3rC,EAAK,IAAI,8CAA8C,CAE/H,CAEA,SAAS6rC,GAAW,EAAc3kC,EAAkB,OAClD,EAAE,iBACF,EAAE,kBACF,MAAMngB,EAAU,EAAE,cAClBA,EAAO,UAAU,OAAO,gBAAgB,EAExC,MAAMgZ,GAAQjpB,EAAA,EAAE,eAAF,YAAAA,EAAgB,MAC9B,GAAI,GAACipB,GAASA,EAAM,SAAW,GAE/B,QAAS7pB,EAAI,EAAGA,EAAI6pB,EAAM,OAAQ7pB,IAAK,CACrC,MAAM8pB,EAAOD,EAAM7pB,CAAC,EAEpB,GAAIo1D,GAAYtrC,CAAI,EAAG,CACrB,GAAI,CAACkH,EAAM,oBAAqB,SAChC,GAAIlH,EAAK,KAAOgrC,GAAsB,CACpCE,GAAoBnkD,EAAQ,qBAAqBiZ,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EAC5G,QACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMpsC,EAAUosC,EAAO,OACjBqc,EAAgC,CACpC,GAAIb,GAAA,EACJ,QAAA5nD,EACA,SAAU2c,EAAK,MAEXzb,EAAU2iB,EAAM,aAAe,IACrCpwB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAG3iB,EAASunD,CAAa,EACxD,EACArc,EAAO,cAAczvB,CAAI,CAC3B,SAAWurC,GAAWvrC,CAAI,EAAG,CAC3B,GAAI,CAACkH,EAAM,oBAAqB,SAChC,GAAIlH,EAAK,KAAOgrC,GAAsB,CACpCE,GAAoBnkD,EAAQ,oBAAoBiZ,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EAC3G,QACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAM3yC,EAAO2yC,EAAO,OACdqc,EAAgC,CACpC,GAAIb,GAAA,EACJ,QAAS,GACT,SAAUjrC,EAAK,MAAQ,aACvB,SAAUA,EAAK,KACf,YAAaljB,CAAA,EAETyH,EAAU2iB,EAAM,aAAe,IACrCpwB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAG3iB,EAASunD,CAAa,EACxD,EACArc,EAAO,WAAWzvB,CAAI,CACxB,SAAWwrC,GAAUxrC,CAAI,EAAG,CAC1B,GAAI,CAACkH,EAAM,oBAAqB,SAChC,GAAIlH,EAAK,KAAOgrC,GAAsB,CACpCE,GAAoBnkD,EAAQ,mBAAmBiZ,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EAC1G,QACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMpsC,EAAUosC,EAAO,OACjBqc,EAAgC,CACpC,GAAIb,GAAA,EACJ,QAAA5nD,EACA,SAAU,kBACV,SAAU2c,EAAK,MAEXzb,EAAU2iB,EAAM,aAAe,IACrCpwB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAG3iB,EAASunD,CAAa,EACxD,EACArc,EAAO,cAAczvB,CAAI,CAC3B,SAAWyrC,GAAYzrC,CAAI,EAAG,CAC5B,GAAI,CAACkH,EAAM,oBAAqB,SAChC,GAAIlH,EAAK,KAAOgrC,GAAsB,CACpCE,GAAoBnkD,EAAQ,qBAAqBiZ,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EAC5G,QACF,CACA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMpsC,EAAUosC,EAAO,OACjBqc,EAAgC,CACpC,GAAIb,GAAA,EACJ,QAAA5nD,EACA,SAAU2c,EAAK,MAAQ,YACvB,SAAUA,EAAK,MAEXzb,EAAU2iB,EAAM,aAAe,IACrCpwB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAG3iB,EAASunD,CAAa,EACxD,EACArc,EAAO,cAAczvB,CAAI,CAC3B,MACEkrC,GAAoBnkD,EAAQ,0BAA0BiZ,EAAK,IAAI,8CAA8C,CAEjH,CACF,CAEA,SAAS+rC,GAAe,EAAc,CACpC,EAAE,iBACF,EAAE,kBACE,EAAE,eAAc,EAAE,aAAa,WAAa,QAC/C,EAAE,cAA8B,UAAU,IAAI,gBAAgB,CACjE,CAEA,SAASC,GAAgB,EAAc,CACrC,EAAE,iBACF,EAAE,kBACF,MAAMnlD,EAAY,EAAE,cAEdolD,EAAU,EAAE,eACd,CAACA,GAAW,CAACplD,EAAU,SAASolD,CAAO,IACzCplD,EAAU,UAAU,OAAO,gBAAgB,CAE/C,CAEA,SAASqlD,GACP,EACAhlC,EACA,WACA,MAAMilC,GAAQr1D,EAAA,EAAE,gBAAF,YAAAA,EAAiB,MAC/B,GAAI,CAACq1D,GAAS,CAACjlC,EAAM,oBAAqB,OAE1C,MAAMklC,EAAiC,GACvC,QAASl2D,EAAI,EAAGA,EAAIi2D,EAAM,OAAQj2D,IAAK,CACrC,MAAMiK,EAAOgsD,EAAMj2D,CAAC,GAChBiK,EAAK,KAAK,WAAW,QAAQ,GAAKA,EAAK,KAAK,WAAW,QAAQ,IACjEisD,EAAW,KAAKjsD,CAAI,CAExB,CAEA,GAAIisD,EAAW,SAAW,EAE1B,GAAE,iBAEF,UAAWjsD,KAAQisD,EAAY,CAC7B,MAAMpsC,EAAO7f,EAAK,YAClB,GAAI,CAAC6f,EAAM,SACX,MAAMngB,EAAQmgB,EAAK,KAAK,WAAW,QAAQ,EAAI,QAAU,QACzD,GAAIA,EAAK,KAAOgrC,GAAsB,CACpC,MAAMqB,IAAUtnC,GAAAhuB,EAAA,EAAE,SAAF,YAAAA,EAA0B,UAA1B,YAAAguB,EAAA,KAAAhuB,EAAoC,WAAY,SAAS,cAAc,OAAO,EAC1Fs1D,GAAQnB,GAAoBmB,EAAuB,GAAGxsD,CAAK,gBAAgBmgB,EAAK,KAAO,KAAO,MAAM,QAAQ,CAAC,CAAC,wBAAwB,EAC1I,QACF,CAEA,MAAMyvB,EAAS,IAAI,WACnBA,EAAO,OAAS,IAAM,OACpB,MAAMpsC,EAAUosC,EAAO,OACjB6c,EAAUtsC,EAAK,KAAK,WAAW,QAAQ,EACvC8rC,EAAgC,CACpC,GAAIb,GAAA,EACJ,QAAA5nD,EACA,SAAU2c,EAAK,KACf,SAAUssC,EAAWtsC,EAAK,MAAQ,YAAe,QAE7Czb,EAAU2iB,EAAM,aAAe,IACrCpwB,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B,CAAC,GAAG3iB,EAASunD,CAAa,EACxD,EACArc,EAAO,cAAczvB,CAAI,CAC3B,EACF,CAGA,SAASusC,GAAkB,EAAU,CACnC,MAAM7iC,EAAO,EAAE,cACT0hC,EAAU1hC,EAAI,QAAQ,eAAe,EACrC8iC,EAAQpB,GAAA,YAAAA,EAAS,cAAc,uBACrC,GAAI,CAACoB,EAAO,OAEZ,MAAMC,EAASD,EAAM,UAAU,OAAO,QAAQ,EAG9C,GAFA9iC,EAAI,UAAU,OAAO,SAAU+iC,CAAM,EAEjCA,EAAQ,CAEV,MAAMC,EAASC,GAAmB,CAC5BH,EAAM,SAASG,EAAG,MAAc,GAAKjjC,EAAI,SAASijC,EAAG,MAAc,IACvEH,EAAM,UAAU,OAAO,QAAQ,EAC/B9iC,EAAI,UAAU,OAAO,QAAQ,EAC7B,SAAS,oBAAoB,QAASgjC,EAAO,EAAI,EACnD,EAEA,sBAAsB,IAAM,SAAS,iBAAiB,QAASA,EAAO,EAAI,CAAC,CAC7E,CACF,CAGA,SAASE,GAAkB,EAAU1lC,EAAkB,CACrD,MAAMjL,EAAU,EAAkB,OAC5B67B,EAA8B77B,GAAA,YAAAA,EAAQ,QAC5C,GAAI,CAAC67B,EAAS,OAEd,MAAMsT,EAAW,EAAE,cAA8B,QAAQ,eAAe,EAClEyB,EAAKzB,GAAA,YAAAA,EAAS,cAAc,YAClC,GAAI,CAACyB,EAAI,OAGT,MAAM9iB,EAAQ8iB,EAAG,gBAAkB3lC,EAAM,MAAM,OACzC8iB,EAAM6iB,EAAG,cAAgB9iB,EACzB9W,EAAS/L,EAAM,MAAM,MAAM,EAAG6iB,CAAK,EACnC7W,EAAQhM,EAAM,MAAM,MAAM8iB,CAAG,EACnC9iB,EAAM,cAAc+L,EAAS6kB,EAAU5kB,CAAK,EAG5C,MAAMs5B,EAAQpB,GAAA,YAAAA,EAAS,cAAc,uBAC/B1hC,EAAM0hC,GAAA,YAAAA,EAAS,cAAc,wBACnCoB,GAAA,MAAAA,EAAO,UAAU,OAAO,UACxB9iC,GAAA,MAAAA,EAAK,UAAU,OAAO,UAGtB,sBAAsB,IAAM,CAC1BmjC,EAAG,QACH,MAAMC,EAAM/iB,EAAQ+N,EAAQ,OAC5B+U,EAAG,kBAAkBC,EAAKA,CAAG,CAC/B,CAAC,CACH,CAEA,SAASC,GAAwB7lC,EAAkB,CACjD,MAAM3jB,EAAc2jB,EAAM,aAAe,GACzC,OAAI3jB,EAAY,SAAW,EAAU4iB,EAE9Bf;AAAAA;AAAAA,QAED7hB,EAAY,IACXO,GAAA,OAAQ,OAAAA,EAAI,SACTshB;AAAAA;AAAAA,uDAE0CtuB,EAAAgN,EAAI,WAAJ,MAAAhN,EAAc,WAAW,UAAYquB,EAAM,KAAOA,EAAM,QAAQ;AAAA,4DAC1DrhB,EAAI,QAAQ,IAAIA,EAAI,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,2BAK7D,IAAM,OACb,MAAMvH,GAAQ2qB,EAAM,aAAe,IAAI,OACpC,GAAM,EAAE,KAAOpjB,EAAI,KAEtBhN,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B3qB,EAC9B,CAAC;AAAA;AAAA,oBAEC4oB,EAAM,CAAC;AAAA;AAAA;AAAA,cAIfC;AAAAA;AAAAA;AAAAA,oBAGQthB,EAAI,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAQR,IAAM,OACb,MAAMvH,GAAQ2qB,EAAM,aAAe,IAAI,OACpC,GAAM,EAAE,KAAOpjB,EAAI,KAEtBhN,EAAAowB,EAAM,sBAAN,MAAApwB,EAAA,KAAAowB,EAA4B3qB,EAC9B,CAAC;AAAA;AAAA,gBAEC4oB,EAAM,CAAC;AAAA;AAAA;AAAA,WAIhB;AAAA;AAAA,GAGP,CAEO,SAAS6nC,GAAW9lC,EAAkB,WAC3C,MAAM+lC,EAAa/lC,EAAM,UACnBmI,EAASnI,EAAM,SAAWA,EAAM,SAAW,KAC3CgmC,EAAW,GAAQhmC,EAAM,UAAYA,EAAM,SAC3CimC,GAAgBp2D,GAAAD,EAAAowB,EAAM,WAAN,YAAApwB,EAAgB,WAAhB,YAAAC,EAA0B,KAC7CuzB,GAAQA,EAAI,MAAQpD,EAAM,YAEvBkmC,GAAiBD,GAAA,YAAAA,EAAe,iBAAkB,MAClDE,EAAgBnmC,EAAM,cAAgBkmC,IAAmB,MAEvDlmC,EAAM,cACJA,EAAM,iBAAmBA,EAAM,mBAGzC,MAAM1jB,KAAkBuhB,EAAAmC,EAAM,cAAN,YAAAnC,EAAmB,SAAU,GAAK,EACpDuoC,EAAqBpmC,EAAM,UAC7B1jB,EACE,mBACA,aACF,cAGJ+pD,GAAkB,CAChB,OAAS5d,GAAe,CAClBzoB,EAAM,qBACRA,EAAM,oBAAoB,CAAC,GAAIA,EAAM,aAAe,GAAKyoB,CAAU,CAAC,EAGtE,sBAAsB,IAAMzoB,EAAM,QAAQ,CAC5C,EACA,gBAAiB,IAAM,QACrBpwB,EAAAowB,EAAM,gBAAN,MAAApwB,EAAA,KAAAowB,EACF,EACD,EAED,MAAMsmC,EAAYrd,GAAA,EACZsd,EAAU,CAACD,GAAa,CAACtmC,EAAM,MAAM,QAAU,CAAC1jB,GAAkB,CAAC6rB,EAEnEq+B,EAAaxmC,EAAM,YAAc,GACjCymC,EAAc,GAAQzmC,EAAM,aAAeA,EAAM,gBACjD0mC,EAASxoC;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,gBAKD8B,EAAM,YAAY;AAAA;AAAA,QAE1BA,EAAM,QACJ9B;AAAAA,cACI8B,EAAM,aACJ9B,0CAA6CD,EAAM,MAAM,kCACzDC,6DAAgE8B,EAAM,WAAW,+BAA+B;AAAA,kBAEtHf,CAAO;AAAA,QACTe,EAAM,QAAU9B,0CAA+Ce,CAAO;AAAA,QACtE0nC,GAAOC,GAAe5mC,CAAK,EAAI/mB,GAASA,EAAK,IAAMA,GAC/CA,EAAK,OAAS,UACT6sC,GAAmB7sC,EAAK,IAAI,EAGjCA,EAAK,OAAS,oBACT2sC,GAA6C,EAGlD3sC,EAAK,OAAS,SACT+sC,GACL/sC,EAAK,KACLA,EAAK,UACL+mB,EAAM,aAER,EAGE/mB,EAAK,OAAS,QACTmtC,GAAmBntC,EAAM,CAC9B,cAAe+mB,EAAM,cACrB,cAAAmmC,EACA,cAAenmC,EAAM,aAEvB,CAAC,EAGIf,CACR,CAAC;AAAA;AAAA,IAIN,OAAOf;AAAAA;AAAAA;AAAAA,cAGMxvB,GAAiBi2D,GAAWj2D,EAAGsxB,CAAK,CAAC;AAAA,kBAClC6kC,EAAc;AAAA,mBACbC,EAAe;AAAA;AAAA,QAE1B9kC,EAAM,eACJ9B,yBAA4B8B,EAAM,cAAc,SAChDf,CAAO;;AAAA,QAETe,EAAM,MACJ9B,gCAAmC8B,EAAM,KAAK,SAC9Cf,CAAO;;AAAA,QAET4kC,GAA0B7jC,EAAM,gBAAgB,CAAC;;AAAA,QAEjDA,EAAM,UACJ9B;AAAAA;AAAAA;AAAAA;AAAAA,uBAIa8B,EAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA,gBAI9B/B,EAAM,CAAC;AAAA;AAAA,YAGbgB,CAAO;;AAAA;AAAA,sCAGqBwnC,EAAc,6BAA+B,EAAE;AAAA;AAAA;AAAA;AAAA,yBAI5DA,EAAc,OAAOD,EAAa,GAAG,IAAM,UAAU;AAAA;AAAA,YAElEE,CAAM;AAAA,YACN1mC,EAAM,aAAe,GACnB9B;AAAAA;AAAAA;AAAAA;AAAAA,2BAIcxvB,GAAa,CACrB,MAAMm4D,EAAQn4D,EAAE,cAA8B,QAAQ,YAAY,EAC5DiR,EAAYknD,GAAA,YAAAA,EAAM,cAAc,gBAClClnD,GACFA,EAAU,SAAS,CAAE,IAAKA,EAAU,aAAc,SAAU,SAAU,CAE1E,CAAC;AAAA;AAAA;AAAA;AAAA,oBAICse,EAAM,WAAW;AAAA;AAAA,gBAGvBgB,CAAO;AAAA;;AAAA,UAGXwnC,EACEvoC;AAAAA;AAAAA,8BAEkBsoC,CAAU;AAAA,0BACb93D,GAAA,OACT,OAAAkB,EAAAowB,EAAM,qBAAN,YAAApwB,EAAA,KAAAowB,EAA2BtxB,EAAE,OAAO,YAAW;AAAA;AAAA;AAAA,kBAG/C46C,GAAsB,CACtB,QAAStpB,EAAM,gBAAkB,KACjC,MAAOA,EAAM,cAAgB,KAC7B,QAASA,EAAM,eACf,cAAe,IAAM,CACf,CAACA,EAAM,gBAAkB,CAACA,EAAM,eACpCA,EAAM,cAAc;AAAA,EAAWA,EAAM,cAAc;AAAA,OAAU,CAC/D,EACD,CAAC;AAAA;AAAA,cAGNf,CAAO;AAAA;;AAAA,QAGXe,EAAM,aAAeA,EAAM,YAAY,OAAS,EAC9C9B;AAAAA;AAAAA,gBAEM8B,EAAM,YAAY,IACjBpqB,GAASsoB;AAAAA;AAAAA;AAAAA;AAAAA,6BAIG,WAAM,OAAAtuB,EAAAowB,EAAM,oBAAN,YAAApwB,EAAA,KAAAowB,EAA0BpqB,GAAK;AAAA;AAAA,sBAE5CA,CAAI;AAAA;AAAA,kBAGX;AAAA;AAAA,YAGLqpB,CAAO;;AAAA;AAAA,UAGP4mC,GAAwB7lC,CAAK,CAAC;AAAA,UAC9BsmC,EACEjd,KACAnrB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,qBAKSmnC,EAAiB;AAAA;AAAA;AAAA;AAAA,cAIxBpnC,EAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKHvvB,GAAa,OACrB,MAAMuD,GAASrC,EAAAlB,EAAE,cACd,QAAQ,oBAAoB,IADhB,YAAAkB,EAEX,cAAgC,6BACpCqC,GAAA,MAAAA,EAAO,OACT,CAAC;AAAA;AAAA;AAAA;AAAA,cAICgsB,EAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAQNvvB,GAAa,CACtB,MAAMuD,EAAQvD,EAAE,OACVmqB,EAAQ5mB,EAAM,MACpB,GAAI,GAAC4mB,GAASA,EAAM,SAAW,GAAK,CAACmH,EAAM,qBAC3C,SAAShxB,EAAI,EAAGA,EAAI6pB,EAAM,OAAQ7pB,IAChCw1D,GAAsB3rC,EAAM7pB,CAAC,EAAGgxB,CAAK,EAEvC/tB,EAAM,MAAQ,GAChB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,uBAKU+tB,EAAM,KAAK;AAAA,0BACR,CAACA,EAAM,SAAS;AAAA,yBAChBtxB,GAAqB,CAC3BA,EAAE,MAAQ,UACVA,EAAE,aAAeA,EAAE,UAAY,KAC/BA,EAAE,UACDsxB,EAAM,YACXtxB,EAAE,iBACEq3D,IACF/lC,EAAM,SACN4jC,GAAUl1D,EAAE,MAA6B,IAE7C,CAAC;AAAA,uBACSA,GAAa,CACrB,MAAMi3D,EAAKj3D,EAAE,OACbsxB,EAAM,cAAc2lC,EAAG,KAAK,EAC5BjC,GAASiC,CAAE,CACb,CAAC;AAAA,uBACSj3D,GAAsBs2D,GAAYt2D,EAAGsxB,CAAK,CAAC;AAAA,4BACvComC,CAAkB;AAAA;AAAA;AAAA,YAGlCJ,EACE9nC;AAAAA;AAAAA;AAAAA,2BAGa8B,EAAM,OAAO;AAAA;AAAA;AAAA;AAAA,oBAIpB/B,EAAM,MAAM;AAAA;AAAA,gBAGlBgB,CAAO;AAAA,YACTsnC,EACEnd,GAAgBppB,EAAM,SAAS,EAC/B9B;AAAAA;AAAAA;AAAAA,wBAGU,CAAC8B,EAAM,SAAS;AAAA,qBAClBtxB,GAAa,OACrBsxB,EAAM,SACN,MAAM2lC,GAAM/1D,EAAAlB,EAAE,OAAuB,QAAQ,eAAe,IAAhD,YAAAkB,EAAmD,cAAc,YACzE+1D,MAAcA,CAAE,CACtB,CAAC;AAAA,0BACax9B,EAAS,QAAU,MAAM;AAAA,qBAC9BA,EAAS,gBAAkB,cAAc;AAAA;AAAA,cAEhDlK,EAAM,IAAI;AAAA,oBACJ;AAAA,eACL;AAAA;AAAA;AAAA,2BAGavvB,GAAag3D,GAAkBh3D,EAAGsxB,CAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,GAMpE,CAEA,SAAS8mC,GAAc7B,EAAmD,CACxE,OAAOA,EAAM,IAAKhsD,GAAS,CACzB,GAAIA,EAAK,OAAS,UAAW,OAAOA,EACpC,MAAMkY,EAAa9W,GAAiBpB,EAAK,OAAO,EAC1CF,EAAO8B,GAAyBsW,EAAW,IAAI,EAC/CxW,EAAYwW,EAAW,WAAa,KAAK,MAC/C,MAAO,CACL,KAAM,QACN,IAAK,SAASpY,CAAI,IAAIE,EAAK,GAAG,GAC9B,KAAAF,EACA,SAAU,CAAC,CAAE,QAASE,EAAK,QAAS,IAAKA,EAAK,IAAK,EACnD,UAAA0B,EACA,YAAa,GAEjB,CAAC,CACH,CAEA,SAASisD,GAAe5mC,EAAkD,OACxE,MAAMilC,EAAoB,GACpB8B,EAAU,MAAM,QAAQ/mC,EAAM,QAAQ,EAAIA,EAAM,SAAW,GAC3DgnC,EAAQ,MAAM,QAAQhnC,EAAM,YAAY,EAAIA,EAAM,aAAe,GACjEinC,EAAiBjnC,EAAM,cAAgBA,EAAM,eAAiB,MAAQA,EAAM,eAAiB,OACnG,QAAShxB,EAAI,EAAGA,EAAI+3D,EAAQ,OAAQ/3D,IAAK,CACvC,MAAMoL,EAAM2sD,EAAQ/3D,CAAC,EACfmiB,EAAa9W,GAAiBD,CAAG,EAEvC,GAAI,CAAC6sD,GAAkB91C,EAAW,KAAK,gBAAkB,aAAc,CAGrE,MAAMrc,EAAMsF,EAEN8sD,GADa,MAAM,QAAQpyD,EAAI,OAAO,EAAIA,EAAI,QAAU,IAC/B,OAC5BuwC,GAAmB,CAClB,MAAM52C,EAAK42C,EAAkC,KAC7C,OAAO52C,IAAM,SAAWA,IAAM,MAChC,GAEEy4D,EAAY,OAAS,GACvBjC,EAAM,KAAK,CACT,KAAM,UACN,IAAKkC,GAAW/sD,EAAKpL,CAAC,EACtB,QAAS,CACP,KAAM,YACN,QAASk4D,EACT,UAAW/1C,EAAW,UACxB,CACD,EAEH,QACF,CAEA8zC,EAAM,KAAK,CACT,KAAM,UACN,IAAKkC,GAAW/sD,EAAKpL,CAAC,EACtB,QAASoL,CAAA,CACV,CACH,CACA,GAAI6sD,EACF,QAASj4D,EAAI,EAAGA,EAAIg4D,EAAM,OAAQh4D,IAChCi2D,EAAM,KAAK,CACT,KAAM,UACN,IAAKkC,GAAWH,EAAMh4D,CAAC,EAAGA,EAAI+3D,EAAQ,MAAM,EAC5C,QAASC,EAAMh4D,CAAC,EACjB,EASL,GAJIgxB,EAAM,aACRilC,EAAM,KAAK,CAAE,KAAM,UAAW,IAAK,mBAAoB,KAAMjlC,EAAM,YAAa,EAG9EA,EAAM,SAAW,KAAM,CACzB,MAAMnqB,EAAM,UAAUmqB,EAAM,UAAU,IAAIA,EAAM,iBAAmB,MAAM,GACrEA,EAAM,OAAO,OAAO,OAAS,EAC/BilC,EAAM,KAAK,CACT,KAAM,SACN,IAAApvD,EACA,KAAMmqB,EAAM,OACZ,UAAWA,EAAM,iBAAmB,KAAK,KAAI,CAC9C,EAEDilC,EAAM,KAAK,CAAE,KAAM,oBAAqB,IAAApvD,EAAK,CAEjD,CAGA,UAAWuxD,KAAMpnC,EAAM,MAAO,CAC5B,MAAMtjB,IAAY9M,EAAAw3D,EAAG,cAAH,YAAAx3D,EAAgB,OAAQR,GAAMA,EAAE,UAAU,IAAKA,GAAMA,EAAE,YAAa,GAChFuN,EAAcD,EAAU,OAAS,EAClC0qD,EAAG,KAAO,GAAG1qD,EAAU,KAAK,IAAI,CAAC;;AAAA,EAAO0qD,EAAG,IAAI,GAAK1qD,EAAU,KAAK,IAAI,EACxE0qD,EAAG,KACPnC,EAAM,KAAK,CACT,KAAM,UACN,IAAK,SAASmC,EAAG,EAAE,GACnB,QAAS,CACP,KAAM,OACN,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAMzqD,EAAa,EAC7C,UAAWyqD,EAAG,UAChB,CACD,CACH,CAEA,OAAON,GAAc7B,CAAK,CAC5B,CAEA,SAASkC,GAAWruD,EAAkBm5B,EAAuB,CAC3D,MAAMhiC,EAAI6I,EACJsG,EAAa,OAAOnP,EAAE,YAAe,SAAWA,EAAE,WAAa,GACrE,GAAImP,EAAY,MAAO,QAAQA,CAAU,GACzC,MAAMxE,EAAK,OAAO3K,EAAE,IAAO,SAAWA,EAAE,GAAK,GAC7C,GAAI2K,EAAI,MAAO,OAAOA,CAAE,GACxB,MAAMysD,EAAY,OAAOp3D,EAAE,WAAc,SAAWA,EAAE,UAAY,GAClE,GAAIo3D,EAAW,MAAO,OAAOA,CAAS,GACtC,MAAM1sD,EAAY,OAAO1K,EAAE,WAAc,SAAWA,EAAE,UAAY,KAC5D8I,EAAO,OAAO9I,EAAE,MAAS,SAAWA,EAAE,KAAO,UACnD,OAAI0K,GAAa,KAAa,OAAO5B,CAAI,IAAI4B,CAAS,IAAIs3B,CAAK,GACxD,OAAOl5B,CAAI,IAAIk5B,CAAK,EAC7B,CCl4BA,SAASq1B,GAAgBtkC,EAAoB,CAC3C,GAAI,CAACA,EAAI,MAAO,GAChB,MAAMzzB,EAAI,IAAI,KAAKyzB,EAAK,GAAI,EAC5B,OAAOzzB,EAAE,mBAAmB,GAAI,CAAE,KAAM,UAAW,MAAO,QAAS,IAAK,UAAW,EACjF,IAAMA,EAAE,mBAAmB,GAAI,CAAE,KAAM,UAAW,OAAQ,UAAW,CACzE,CAEA,SAASg4D,GAAaC,EAAqB,CACzC,OAAOA,EAAI,QAAQ,qBAAsB,EAAE,EAAE,QAAQ,UAAW,EAAE,CACpE,CAEA,SAASC,GAAuBznC,EAAyC,CACvE,MAAMpG,EAAQoG,EAAM,YAAY,cAC1BlkB,EAAW8d,EACboG,EAAM,cAAc,OAAQ9wB,GAAMA,EAAE,KAAK,cAAc,SAAS0qB,CAAK,GAAK1qB,EAAE,IAAI,SAAS0qB,CAAK,CAAC,EAC/FoG,EAAM,cAEV,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBAOU8B,EAAM,WAAW;AAAA,mBAChBtxB,GAAasxB,EAAM,eAAgBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA,kDAEzCsxB,EAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,UAKvDA,EAAM,QACJ9B,gDACApiB,EAAS,SAAW,EAClBoiB,gCAAmC8B,EAAM,cAAc,SAAW,EAAI,uBAAyB,YAAY,SAC3GlkB,EAAS,IAAK5M,GAAMw4D,GAAsBx4D,EAAGA,EAAE,MAAQ8wB,EAAM,YAAa,IAAMA,EAAM,qBAAqB9wB,EAAE,GAAG,CAAC,CAAC,CAAC;AAAA;AAAA;AAAA,GAIjI,CAEA,SAASw4D,GAAsBC,EAA4B1iC,EAAmB2iC,EAAsC,CAClH,MAAMC,EAAkBF,EAAK,OAAS,SAAWA,EAAK,WAClDzpC,oCAAuCypC,EAAK,UAAU,KAAKA,EAAK,UAAU,UAC1E1oC,EAEJ,OAAOf;AAAAA,mCAC0B+G,EAAW,0BAA4B,EAAE,YAAY2iC,CAAQ;AAAA,mCAC7DD,EAAK,OAAS,QAAU,uBAAyB,EAAE,KAAKA,EAAK,OAAS,QAAU1pC,EAAM,MAAQA,EAAM,IAAI;AAAA;AAAA,sCAErG0pC,EAAK,IAAI;AAAA,qCACVJ,GAAaI,EAAK,GAAG,CAAC;AAAA;AAAA,QAEnDE,CAAe;AAAA;AAAA,GAGvB,CAEA,SAASC,GAAyB9nC,EAAyC,CACzE,MAAM2nC,EAAO3nC,EAAM,cAAc,KAAM9wB,GAAMA,EAAE,MAAQ8wB,EAAM,WAAW,EACxE,OAAK2nC,EAEEzpC;AAAAA;AAAAA,+CAEsC8B,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA,wCAInB2nC,EAAK,IAAI;AAAA,uCACVJ,GAAaI,EAAK,GAAG,CAAC;AAAA;AAAA;AAAA,IATzCzpC,GAapB,CAEA,SAAS6pC,GAAoB/nC,EAAyC,OACpE,MAAMgoC,EAAOhoC,EAAM,UACnB,MAAI,CAACgoC,GAAQ,GAACp4D,EAAAowB,EAAM,cAAN,MAAApwB,EAAmB,SAAS,UAAiBsuB,IAEpDA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBAMU8pC,EAAK,YAAc,SAAS;AAAA,oBAC1Bt5D,GAAasxB,EAAM,mBAAmBA,EAAM,YAAetxB,EAAE,OAA6B,KAAqC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAQ3Is5D,EAAK,aAAa,MAAM;AAAA,UACxBA,EAAK,KAAO9pC,OAAU8pC,EAAK,IAAI,GAAK/oC,CAAO;AAAA;AAAA;AAAA,GAIrD,CAEA,SAASgpC,GAAe9tD,EAA6C,CACnE,OAAIA,EAAS,SAAW,EACf+jB,+DAEFA;AAAAA,MACH/jB,EAAS,IAAKC,GAAQ8jB;AAAAA,8BACE9jB,EAAI,OAAS,gBAAkB,EAAE;AAAA,UACrD,CAACA,EAAI,QAAUA,EAAI,WAAa8jB,mCAAsC9jB,EAAI,UAAU,SAAW6kB,CAAO;AAAA,UACtG7kB,EAAI,OAAS8jB,mCAAsC9jB,EAAI,OAAO,IAAI,SAAW6kB,CAAO;AAAA,uCACvD7kB,EAAI,IAAI;AAAA,uCACRktD,GAAgBltD,EAAI,SAAS,CAAC;AAAA;AAAA,KAEhE,CAAC;AAAA,GAEN,CAEO,SAAS8tD,GAAkBloC,EAAyC,CACzE,OAAO9B;AAAAA,+BACsB8B,EAAM,YAAc,uBAAyB,EAAE;AAAA,QACtEynC,GAAuBznC,CAAK,CAAC;AAAA;AAAA,UAE3BA,EAAM,YACJ9B;AAAAA,gBACI4pC,GAAyB9nC,CAAK,CAAC;AAAA,gBAC/B+nC,GAAoB/nC,CAAK,CAAC;AAAA;AAAA,kBAExBA,EAAM,gBACJ9B,6DACA+pC,GAAejoC,EAAM,QAAQ,CAAC;AAAA;AAAA,cAGtC9B,0DAA6D;AAAA;AAAA;AAAA,GAIzE,CC/IA,MAAMiqC,GAAmBjqC,kWAoBlB,SAASkqC,GAAepoC,EAAsB,CACnD,GAAI,CAACA,EAAM,UACT,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAUT,MAAMpJ,EAAyBkL,EAAM,aAAe,OAE9CqoC,EAAYroC,EAAM,mBAAqBA,EAAM,oBAC/C9B;AAAAA;AAAAA,6BAEuB8B,EAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA,gBAItCmoC,EAAgB,OAC1BlpC,EAEEqpC,EAAStoC,EAAM,cACjB9B;AAAAA;AAAAA;AAAAA,mCAG6BpJ,IAAc,OAAS,SAAW,EAAE;AAAA,qBAClD,WAAM,OAAAllB,EAAAowB,EAAM,sBAAN,YAAApwB,EAAA,KAAAowB,EAA4B,QAAO;AAAA;AAAA;AAAA,mCAG3BlL,IAAc,WAAa,SAAW,EAAE;AAAA,qBACtD,WAAM,OAAAllB,EAAAowB,EAAM,sBAAN,YAAApwB,EAAA,KAAAowB,EAA4B,YAAW;AAAA;AAAA;AAAA,QAI5Df,EAEJ,OAAOf;AAAAA;AAAAA,QAEDO,GAAc,OAAQuB,EAAM,OAAO,CAAC;AAAA,QACpCqoC,CAAS;AAAA,QACTC,CAAM;AAAA;AAAA,UAEJxzC,IAAc,YAAckL,EAAM,cAChCkoC,GAAkBloC,EAAM,aAAa,EACrC8lC,GAAW9lC,CAAK,CAAC;AAAA;AAAA;AAAA,GAI7B,CCnBA,eAAsBuoC,GAAkB/sD,EAAyB,CAC/D,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,QAAU,GAChBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,yBAA0B,CAChE,UAAWA,EAAM,UAClB,EACDA,EAAM,cAAgBG,EAAI,aAC5B,OAASI,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,SACEP,EAAM,QAAU,EAClB,EACF,CAEA,eAAsBgtD,GAAmBhtD,EAAyBgsD,EAAa,CAC7E,GAAI,GAAChsD,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,YAAcgsD,EACpBhsD,EAAM,gBAAkB,GACxBA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMitD,EAAW,MAAMjtD,EAAM,OAAO,QAAQ,oBAAqB,CAC/D,IAAAgsD,EAAK,MAAO,IAAK,UAAWhsD,EAAM,UACnC,EACDA,EAAM,SAAWitD,EAAQ,QAC3B,OAAS1sD,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,CACA,GAAIyrD,EAAI,SAAS,OAAO,EACtB,GAAI,CACF,MAAMkB,EAAY,MAAMltD,EAAM,OAAO,QAAQ,qBAAsB,CACjE,IAAAgsD,EAAK,UAAWhsD,EAAM,UACvB,EACDA,EAAM,UAAYktD,CACpB,MAAQ,CAER,CAEFltD,EAAM,gBAAkB,GAC1B,CAEA,eAAsBmtD,GACpBntD,EACAgsD,EACAoB,EACA,CACA,GAAI,GAACptD,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,yBAA0B,CAAE,IAAAgsD,EAAK,WAAAoB,EAAY,UAAWptD,EAAM,UAAW,EAChGA,EAAM,YAAWA,EAAM,UAAU,WAAaotD,GAClD,MAAMjB,EAAOnsD,EAAM,cAAc,KAAMtM,GAAMA,EAAE,MAAQs4D,CAAG,EACtDG,MAAW,WAAaiB,EAC9B,OAAS7sD,EAAK,CACZP,EAAM,UAAY,OAAOO,CAAG,CAC9B,CACF,CCrGO,SAAS8sD,GAActxD,EAAoB,CAChD,OAAKA,EACE,GAAGD,GAASC,CAAE,CAAC,KAAKC,GAAUD,CAAE,CAAC,IADxB,KAElB,CAkBO,SAASuxD,GAAgB5lD,EAAc,CAC5C,MAAM1H,EAAQ0H,EAAI,OAAS,GACrB4B,EAAStJ,EAAM,YAAc,MAC7ButD,EAAOvtD,EAAM,YAAchE,GAAUgE,EAAM,WAAW,EAAI,QAChE,MAAO,GAAGsJ,CAAM,WAAWikD,CAAI,EACjC,CAEO,SAASC,GAAmB9lD,EAAc,CAC/C,MAAMvU,EAAIuU,EAAI,SACd,OAAIvU,EAAE,OAAS,KAAa,aAAa2I,GAAS3I,EAAE,IAAI,CAAC,GACrDA,EAAE,OAAS,QAAgB,SAASmJ,GAAiBnJ,EAAE,OAAO,CAAC,GAC5Ds6D,GAAat6D,EAAE,KAAMA,EAAE,EAAE,CAClC,CAMA,SAASs6D,GAAatmD,EAAcumD,EAAqB,CACvD,MAAM7yD,EAAQsM,EAAK,OAAO,MAAM,KAAK,EACrC,GAAItM,EAAM,SAAW,EAAG,OAAOsM,EAC/B,KAAM,CAACwmD,EAAQC,EAAMnO,EAAKoO,EAAOC,CAAG,EAAIjzD,EAElCkzD,EAAWL,EAAK,KAAKA,EAAG,QAAQ,QAAS,EAAE,EAAE,QAAQ,KAAM,GAAG,CAAC,IAAM,GAGrEM,EAAU,CAACr6D,EAAWc,IAChB,IAAI,KAAK,IAAM,EAAG,EAAGd,EAAGc,CAAC,EAC1B,mBAAmB,OAAW,CAAE,KAAM,UAAW,OAAQ,UAAW,EAIzE2H,EAAM,YAAY,KAAKuxD,CAAM,EAAI,SAASA,EAAQ,EAAE,EAAI,KAGxDM,EAAQC,GAAWN,CAAI,EAG7B,GAAIxxD,IAAQ,MAAQ,CAAC6xD,EAAO,MAAO,GAAG9mD,CAAI,GAAGumD,EAAK,KAAKA,CAAE,IAAM,EAAE,GAEjE,MAAMS,EAAWF,EAAM,IAAKt6D,GAAMq6D,EAAQr6D,EAAGyI,CAAG,CAAC,EAC3CgyD,EACJD,EAAS,QAAU,EACfA,EAAS,KAAK,KAAK,EACnB,GAAGA,EAAS,MAAM,EAAG,EAAE,EAAE,KAAK,IAAI,CAAC,MAAMA,EAASA,EAAS,OAAS,CAAC,CAAC,GAGtEE,EAAY,CAAC,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,KAAK,EAGlE,GAAI5O,IAAQ,KAAOoO,IAAU,IAAK,CAChC,GAAIC,IAAQ,IAAK,MAAO,YAAYM,CAAO,GAAGL,CAAQ,GACtD,GAAID,IAAQ,MAAO,MAAO,eAAeM,CAAO,GAAGL,CAAQ,GAC3D,GAAID,IAAQ,OAASA,IAAQ,YAAc,eAAeM,CAAO,GAAGL,CAAQ,GAC5E,MAAMO,EAAOJ,GAAWJ,CAAG,EAC3B,GAAIQ,EAEF,MAAO,GADUA,EAAK,IAAKv6D,GAAMs6D,EAAUt6D,EAAI,CAAC,GAAK,OAAOA,CAAC,CAAC,EAC3C,KAAK,IAAI,CAAC,OAAOq6D,CAAO,GAAGL,CAAQ,EAE1D,CAEA,MAAO,GAAG5mD,CAAI,GAAGumD,EAAK,KAAKA,CAAE,IAAM,EAAE,EACvC,CAGA,SAASQ,GAAWK,EAAgC,CAClD,GAAIA,IAAU,IAAK,OAAO,KAE1B,GAAI,eAAe,KAAKA,CAAK,EAC3B,OAAOA,EAAM,MAAM,GAAG,EAAE,IAAI,MAAM,EAGpC,GAAI,YAAY,KAAKA,CAAK,EAAG,CAC3B,KAAM,CAAClnB,EAAOC,CAAG,EAAIinB,EAAM,MAAM,GAAG,EAAE,IAAI,MAAM,EAChD,GAAIlnB,EAAQC,EAAK,OAAO,KACxB,MAAM9rC,EAAmB,GACzB,QAAShI,EAAI6zC,EAAO7zC,GAAK8zC,EAAK9zC,IAAKgI,EAAO,KAAKhI,CAAC,EAChD,OAAOgI,CACT,CACA,OAAO,IACT,CAEO,SAASgzD,GAAkB9mD,EAAc+mD,EAAW,GAAM,CAC/D,MAAM36D,EAAI4T,EAAI,QACd,OAAI5T,EAAE,OAAS,cAEN,SADM26D,GAAY36D,EAAE,KAAK,OAAS,GAAK,GAAGA,EAAE,KAAK,MAAM,EAAG,EAAE,CAAC,IAAWA,EAAE,IAC7D,GAGf,YADK26D,GAAY36D,EAAE,QAAQ,OAAS,GAAK,GAAGA,EAAE,QAAQ,MAAM,EAAG,EAAE,CAAC,IAAWA,EAAE,OAChE,EACxB,CAEO,SAAS46D,GAAyBhnD,EAA6B,CACpE,MAAM5T,EAAI4T,EAAI,QACd,GAAI5T,EAAE,OAAS,YAAa,OAAO,KAEnC,MAAMqU,EAAWrU,EAA8B,SAAWA,EAAE,SACtDgqB,EAAKhqB,EAAE,GACb,GAAI,CAACgqB,GAAM,CAAC3V,EAAS,OAAO,KAC5B,MAAMtN,EAAkB,GACxB,GAAIijB,EAAI,CAGN,MAAM6wC,EADa7wC,EAAG,MAAM,GAAG,EAAE,IAAK3qB,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,EAC1C,IAAK,GAAO,EAAE,gBAAkB,SAAW,aAAe,CAAE,EACtF0H,EAAM,KAAK8zD,EAAO,KAAK,IAAI,CAAC,CAC9B,CACA,OAAIxmD,GAAWA,IAAY,UAAc,KAAK,OAAOA,CAAO,EAAE,EACvDtN,EAAM,KAAK,GAAG,GAAK,IAC5B,CC9FA,IAAI6pB,GAA2D,KAI/D,SAASkqC,GAAoBpqC,EAA4B,OACvD,MAAMlpB,EAAU,CAAC,OAAQ,GAAGkpB,EAAM,SAAS,OAAO,OAAO,CAAC,EACpD3iB,GAAUzN,EAAAowB,EAAM,KAAK,UAAX,YAAApwB,EAAoB,OAChCyN,GAAW,CAACvG,EAAQ,SAASuG,CAAO,GACtCvG,EAAQ,KAAKuG,CAAO,EAEtB,MAAMgtD,MAAW,IACjB,OAAOvzD,EAAQ,OAAQjF,GACjBw4D,EAAK,IAAIx4D,CAAK,EAAU,IAC5Bw4D,EAAK,IAAIx4D,CAAK,EACP,GACR,CACH,CAEA,SAASy4D,GAAoBtqC,EAAkBrc,EAAyB,SACtE,GAAIA,IAAY,OAAQ,MAAO,OAC/B,MAAM0C,GAAOzW,EAAAowB,EAAM,cAAN,YAAApwB,EAAmB,KAAMoO,GAAUA,EAAM,KAAO2F,GAC7D,OAAI0C,GAAA,MAAAA,EAAM,MAAcA,EAAK,QACtBxW,EAAAmwB,EAAM,gBAAN,YAAAnwB,EAAsB8T,KAAYA,CAC3C,CAGA,SAAS4mD,GAAiBjxC,EAAoB,CAE5C,OADcA,EAAG,MAAM,GAAG,EAAE,IAAK3qB,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,EAClD,IAAKW,GAAOA,EAAE,gBAAkB,SAAW,aAAeA,CAAE,EAAE,KAAK,IAAI,CACtF,CAGA,SAASk7D,GAAWl0D,EAA0B,CAC5C,OAAKA,GAAgB,SAEvB,CAIA,MAAMm0D,GAAWvsC,yEACXwsC,GAAYxsC,sHACZysC,GAAYzsC,qJACZqQ,GAAQrQ,+EACR0sC,GAAU1sC,6FACV2sC,GAAW3sC,2EACX4sC,GAAW5sC,4KAIV,SAAS6sC,GAAW/qC,EAAkB,CAC3C,MAAMgrC,EAAYhrC,EAAM,YACpBA,EAAM,KAAK,KAAM1uB,GAAMA,EAAE,KAAO0uB,EAAM,WAAW,GAAK,KACtD,KAEEirC,EAAgBjrC,EAAM,mBAAqB,CAAC,CAACA,EAAM,UAEzD,OAAO9B;AAAAA,MACHgtC,GAAgBlrC,CAAK,CAAC;AAAA,MACtBmrC,GAAgBnrC,CAAK,CAAC;AAAA,MACtBirC,EAAgBG,GAAqBprC,CAAK,EAAIf,CAAO;AAAA,MACrD+rC,EAAYK,GAAkBL,EAAWhrC,CAAK,EAAIf,CAAO;AAAA,MACzDe,EAAM,cAAgBsrC,GAAetrC,CAAK,EAAIf,CAAO;AAAA,GAE3D,CAIA,SAASisC,GAAgBlrC,EAAkB,CACzC,MAAMrxB,EAAIqxB,EAAM,OACV5c,GAAUzU,GAAA,YAAAA,EAAG,UAAW,GACxB48D,EAAWvrC,EAAM,KAAK,OACtBwrC,EAAW78D,GAAA,YAAAA,EAAG,aAEpB,OAAOuvB;AAAAA;AAAAA;AAAAA,iCAGwB9a,EAAU,KAAO,EAAE;AAAA,gBACpCA,EAAU,SAAW,UAAU;AAAA;AAAA,gBAE/BmoD,CAAQ,SAASA,IAAa,EAAI,IAAM,EAAE;AAAA,UAChDC,EACEttC;AAAAA;AAAAA,4BAEgB1mB,GAAUg0D,CAAQ,CAAC;AAAA,cAEnCvsC,CAAO;AAAA;AAAA;AAAA,sBAGGe,EAAM,OAAO;AAAA,mBAChBA,EAAM,SAAS;AAAA;AAAA;AAAA,YAGtBA,EAAM,QAAU,cAAqB,SAAS;AAAA;AAAA,UAEhDA,EAAM,MAAQ9B,wBAA2B8B,EAAM,KAAK,UAAYf,CAAO;AAAA;AAAA,mDAE9Be,EAAM,mBAAmB;AAAA,UAClE6qC,EAAQ;AAAA;AAAA;AAAA,GAIlB,CAIA,SAASM,GAAgBnrC,EAAkB,CACzC,OAAIA,EAAM,KAAK,SAAW,EACjB9B,+FAGFA;AAAAA;AAAAA,QAED8B,EAAM,KAAK,IAAK9c,GAAQuoD,GAAgBvoD,EAAK8c,CAAK,CAAC,CAAC;AAAA;AAAA,GAG5D,CAEA,SAASyrC,GAAgBvoD,EAAc8c,EAAkB,CACvD,OAAO9B;AAAAA;AAAAA,0BAEiBhb,EAAI,QAAU,GAAK,UAAU;AAAA,eACxC,IAAM8c,EAAM,aAAa9c,CAAG,CAAC;AAAA;AAAA;AAAA,wCAGJA,EAAI,MAAQ,UAAU;AAAA,4BAClCA,EAAI,QAAU,UAAY,EAAE;AAAA,YAC5CA,EAAI,QAAU,KAAO,KAAK;AAAA;AAAA;AAAA,0CAGI8lD,GAAmB9lD,CAAG,CAAC;AAAA,QACzDA,EAAI,QACFgb,mCAAsCssC,GAAWtnD,EAAI,OAAO,CAAC,SAC7D+b,CAAO;AAAA,QACTirC,GAAyBhnD,CAAG,EAC1Bgb,yEAA4EgsC,GAAyBhnD,CAAG,CAAC,SACzG+b,CAAO;AAAA;AAAA;AAAA,yDAGwC6pC,GAAgB5lD,CAAG,CAAC;AAAA;AAAA,kDAE1BxU,GAAaA,EAAE,iBAAiB;AAAA;AAAA;AAAA,qBAG9DwU,EAAI,QAAU,QAAU,QAAQ;AAAA,wBAC7B8c,EAAM,IAAI;AAAA,qBACb,IAAMA,EAAM,SAAS9c,EAAK,CAACA,EAAI,OAAO,CAAC;AAAA;AAAA,cAE9CA,EAAI,QAAUwnD,GAAYD,EAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,wBAKxBzqC,EAAM,IAAI;AAAA,qBACb,IAAMA,EAAM,MAAM9c,CAAG,CAAC;AAAA;AAAA,cAE7B0nD,EAAO;AAAA;AAAA,YAET5qC,EAAM,kBAAoB9c,EAAI,GAC5Bgb;AAAAA;AAAAA,4BAEc8B,EAAM,IAAI;AAAA,yBACb,IAAM,CACTE,iBAAiCA,EAAkB,EACvDA,GAAqB,KACrBF,EAAM,SAAS9c,CAAG,CACpB,CAAC;AAAA,yCAEHgb;AAAAA;AAAAA;AAAAA,4BAGc8B,EAAM,IAAI;AAAA,yBACb,IAAM,CACbA,EAAM,YAAY9c,EAAI,EAAE,EACpBgd,iBAAiCA,EAAkB,EACvDA,GAAqB,WAAW,IAAM,CACpCF,EAAM,YAAY,EAAE,EACpBE,GAAqB,IACvB,EAAG,GAAI,CACT,CAAC;AAAA,iBACAyqC,EAAS,WAChB;AAAA;AAAA;AAAA;AAAA,GAKV,CAIA,SAASS,GAAqBprC,EAAkB,CAC9C,MAAM0rC,EAAS,CAAC,CAAC1rC,EAAM,UACjB2rC,EAAiBvB,GAAoBpqC,CAAK,EAC1C4rC,EAAU,IAAM,CAIlB5rC,EAAM,sBAIV,EAEA,OAAO9B;AAAAA,8CACqC0tC,CAAO;AAAA,wCACZl9D,GAAaA,EAAE,iBAAiB;AAAA;AAAA,4CAE7Bg9D,EAAS,aAAe,WAAW;AAAA,sDACzBE,CAAO;AAAA,cAC/Cr9B,EAAK;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,uBAQIvO,EAAM,KAAK,IAAI;AAAA,uBACdtxB,GACRsxB,EAAM,aAAa,CAAE,KAAOtxB,EAAE,OAA4B,MAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAO3DsxB,EAAM,KAAK,WAAW;AAAA,uBACrBtxB,GACRsxB,EAAM,aAAa,CAAE,YAActxB,EAAE,OAA4B,MAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAOlEsxB,EAAM,KAAK,OAAO;AAAA,wBAChBtxB,GACTsxB,EAAM,aAAa,CAAE,QAAUtxB,EAAE,OAA6B,MAAO,CAAC;AAAA;AAAA;AAAA,gBAGtEsxB,EAAM,SAAS,IACdplB,GAAOsjB,kBAAqBtjB,CAAE,IAAIA,CAAE,YACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAOUolB,EAAM,KAAK,OAAO;AAAA,wBAClBtxB,GACTsxB,EAAM,aAAa,CAAE,QAAUtxB,EAAE,OAA4B,QAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAMhEsxB,EAAM,KAAK,YAAY;AAAA,wBACrBtxB,GACTsxB,EAAM,aAAa,CACjB,aAAetxB,EAAE,OAA6B,MAC/C,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,UASRm9D,GAAqB7rC,CAAK,CAAC;;AAAA;AAAA;AAAA;AAAA;AAAA,uBAMdA,EAAM,KAAK,aAAa;AAAA,wBACtBtxB,GAAa,CACtB,MAAMmR,EAAUnR,EAAE,OAA6B,MAC/CsxB,EAAM,aAAa,CACjB,cAAengB,EACf,YAAaA,IAAW,WAAa,YAAc,cACpD,CACH,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBASQmgB,EAAM,KAAK,QAAQ;AAAA,wBACjBtxB,GACTsxB,EAAM,aAAa,CACjB,SAAWtxB,EAAE,OAA6B,MAC3C,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBASKsxB,EAAM,KAAK,WAAW;AAAA,wBACpBtxB,GAAa,CACtB,MAAM0zC,EAAQ1zC,EAAE,OAA6B,MAC7CsxB,EAAM,aAAa,CACjB,YAAaoiB,EACb,cAAeA,IAAS,YAAc,WAAa,OACpD,CACH,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA,kBASGpiB,EAAM,KAAK,cAAgB,cAAgB,mBAAqB,iBAAiB;AAAA;AAAA,qBAE9EA,EAAM,KAAK,WAAW;AAAA,qBACrBtxB,GACRsxB,EAAM,aAAa,CACjB,YAActxB,EAAE,OAA+B,MAChD,CAAC;AAAA;AAAA,2BAEWsxB,EAAM,KAAK,cAAgB,cACtC,yCACA,2BAAgC;AAAA;AAAA;;AAAA,UAItCA,EAAM,KAAK,cAAgB,YACzB9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,+BAMmB8B,EAAM,KAAK,OAAO;AAAA,8BAClBtxB,GACTsxB,EAAM,aAAa,CACjB,QAAUtxB,EAAE,OAA4B,QACzC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAMKsxB,EAAM,KAAK,SAAW,MAAM;AAAA,8BAC1BtxB,GACTsxB,EAAM,aAAa,CACjB,QAAUtxB,EAAE,OAA6B,MAC1C,CAAC;AAAA;AAAA,sBAEFi9D,EAAe,IACdhoD,GACCua,kBAAqBva,CAAO;AAAA,4BACxB2mD,GAAoBtqC,EAAOrc,CAAO,CAAC;AAAA,mCAE1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAOUqc,EAAM,KAAK,QAAQ;AAAA,8BACnBtxB,GACTsxB,EAAM,aAAa,CACjB,SAAWtxB,EAAE,OAA4B,QAC1C,CAAC;AAAA;AAAA;AAAA;AAAA,gBAIRo9D,GAAqB9rC,CAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,6BAKdA,EAAM,KAAK,cAAc;AAAA,6BACxBtxB,GACRsxB,EAAM,aAAa,CACjB,eAAiBtxB,EAAE,OAA4B,MAChD,CAAC;AAAA;AAAA;AAAA,kBAGNsxB,EAAM,KAAK,gBAAkB,WAC3B9B;AAAAA;AAAAA;AAAAA;AAAAA,mCAIe8B,EAAM,KAAK,gBAAgB;AAAA,mCAC1BtxB,GACRsxB,EAAM,aAAa,CACjB,iBAAmBtxB,EAAE,OAA4B,MAClD,CAAC;AAAA;AAAA;AAAA,sBAIVuwB,CAAO;AAAA;AAAA,cAGfA,CAAO;;AAAA;AAAA,uCAGoB2sC,CAAO;AAAA,YAClCF,EACExtC,0CAA6C8B,EAAM,IAAI,WAAWA,EAAM,UAAU;AAAA,kBAC9EA,EAAM,KAAO,UAAiB,cAAc;AAAA,yBAEhD9B,0CAA6C8B,EAAM,IAAI,WAAWA,EAAM,KAAK;AAAA,kBACzEA,EAAM,KAAO,YAAmB,cAAc;AAAA,wBACxC;AAAA;AAAA;AAAA;AAAA,GAKxB,CAIA,SAAS8rC,GAAqB9rC,EAAkB,CAC9C,MAAM+rC,EAAa/rC,EAAM,KAAK,WAE9B,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBAMU,IAAM,CACb8B,EAAM,aAAa,CAAE,WAAY,CAAC,GAAG+rC,EAAY,EAAE,EAAG,CACxD,CAAC;AAAA;AAAA,YAEClB,EAAQ;AAAA;AAAA;AAAA,QAGZkB,EAAW,SAAW,GAAK,CAAC/rC,EAAM,KAAK,SACrC9B,+HACAe,CAAO;AAAA,QACT8sC,EAAW,IACX,CAACC,EAAW/5B,IAAU/T;AAAAA;AAAAA;AAAAA;AAAAA,uBAIP8tC,CAAS;AAAA,uBACRt9D,GAAa,CACrB,MAAMkjB,EAAU,CAAC,GAAGm6C,CAAU,EAC9Bn6C,EAAQqgB,CAAK,EAAKvjC,EAAE,OAA4B,MAChDsxB,EAAM,aAAa,CAAE,WAAYpO,CAAA,CAAS,CAC5C,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAMQ,IAAM,CACb,MAAMA,EAAUm6C,EAAW,OAAO,CAAC/7D,EAAGhB,IAAMA,IAAMijC,CAAK,EACvDjS,EAAM,aAAa,CAAE,WAAYpO,CAAA,CAAS,CAC5C,CAAC;AAAA;AAAA,gBAEC2c,EAAK;AAAA;AAAA;AAAA,UAId;AAAA;AAAA,GAGP,CAIA,SAASs9B,GAAqB7rC,EAAkB,CAC9C,MAAMxe,EAAOwe,EAAM,KACnB,OAAIxe,EAAK,eAAiB,KACjB0c;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBAKQ1c,EAAK,UAAU;AAAA,mBACd9S,GACRsxB,EAAM,aAAa,CACjB,WAAatxB,EAAE,OAA4B,MAC5C,CAAC;AAAA;AAAA;AAAA,MAKR8S,EAAK,eAAiB,QACjB0c;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,qBAKU1c,EAAK,WAAW;AAAA,qBACf9S,GACRsxB,EAAM,aAAa,CACjB,YAActxB,EAAE,OAA4B,MAC7C,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAMK8S,EAAK,SAAS;AAAA,sBACZ9S,GACTsxB,EAAM,aAAa,CACjB,UAAYtxB,EAAE,OAA6B,MAC5C,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUPwvB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBAKU1c,EAAK,QAAQ;AAAA,mBACZ9S,GACRsxB,EAAM,aAAa,CAAE,SAAWtxB,EAAE,OAA4B,MAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAO/D8S,EAAK,MAAM;AAAA,mBACV9S,GACRsxB,EAAM,aAAa,CAAE,OAAStxB,EAAE,OAA4B,MAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,GAMhF,CAIA,SAAS28D,GAAkBnoD,EAAc8c,EAAkB,OACzD,OAAO9B;AAAAA,8CACqC8B,EAAM,aAAa;AAAA,wCACxBtxB,GAAaA,EAAE,iBAAiB;AAAA;AAAA,4CAE7BwU,EAAI,MAAQ,gBAAgB;AAAA,sDAClB8c,EAAM,aAAa;AAAA,cAC3DuO,EAAK;AAAA;AAAA;;AAAA,UAITrrB,EAAI,YACFgb,4EAA+Ehb,EAAI,WAAW,SAC9F+b,CAAO;;AAAA;AAAA;AAAA;AAAA,wBAKKe,EAAM,IAAI;AAAA,qBACb,IAAMA,EAAM,OAAO9c,CAAG,CAAC;AAAA;AAAA,cAE9B4nD,EAAQ;AAAA;AAAA;AAAA;AAAA,wBAIE9qC,EAAM,IAAI;AAAA,qBACb,IAAMA,EAAM,SAAS9c,EAAK,CAACA,EAAI,OAAO,CAAC;AAAA;AAAA,cAE9CA,EAAI,QAAU,UAAY,QAAQ;AAAA;AAAA;AAAA;AAAA,wBAIxB8c,EAAM,IAAI;AAAA,qBACb,IAAMA,EAAM,MAAM9c,CAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAMnB8c,EAAM,IAAI;AAAA,qBACb,IAAM,CACTA,EAAM,kBAAoB9c,EAAI,IAC5Bgd,iBAAiCA,EAAkB,EACvDA,GAAqB,KACrBF,EAAM,SAAS9c,CAAG,EAClB8c,EAAM,kBAENA,EAAM,YAAY9c,EAAI,EAAE,EACpBgd,iBAAiCA,EAAkB,EACvDA,GAAqB,WAAW,IAAM,CACpCF,EAAM,YAAY,EAAE,EACpBE,GAAqB,IACvB,EAAG,GAAI,EAEX,CAAC;AAAA;AAAA,cAECF,EAAM,kBAAoB9c,EAAI,GAAK,kBAAoB,QAAQ;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,kCAQ3CA,EAAI,QAAU,UAAY,EAAE;AAAA,kBAC5CA,EAAI,QAAU,UAAY,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+CAMP8lD,GAAmB9lD,CAAG,CAAC;AAAA;AAAA,YAE1DA,EAAI,QACFgb;AAAAA;AAAAA;AAAAA,0DAG4Chb,EAAI,OAAO;AAAA;AAAA,gBAGvD+b,CAAO;AAAA;AAAA;AAAA;AAAA,gBAIL/b,EAAI,gBAAkB,OAAS,SAAW,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAMpDA,EAAI,WAAa,MAAQ,aAAe,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,wJAK2E8mD,GAAkB9mD,EAAK,EAAK,CAAC;AAAA;AAAA,YAEzKA,EAAI,QAAQ,OAAS,aAAeA,EAAI,QAAQ,GAC9Cgb;AAAAA;AAAAA;AAAAA,0DAG4CqsC,GAAiBrnD,EAAI,QAAQ,EAAE,CAAC;AAAA;AAAA,gBAG5E+b,CAAO;AAAA,YACT/b,EAAI,QAAQ,OAAS,cAAiBA,EAAI,QAAoC,SAAWA,EAAI,QAAQ,UACnGgb;AAAAA;AAAAA;AAAAA,qDAGwChb,EAAI,QAAoC,SAAWA,EAAI,QAAQ,QAAQ;AAAA;AAAA,gBAG/G+b,CAAO;AAAA,YACT/b,EAAI,QAAQ,OAAS,YACnBgb;AAAAA;AAAAA;AAAAA,qDAGuChb,EAAI,QAAQ,QAAU,MAAQ,IAAI;AAAA;AAAA,gBAGzE+b,CAAO;AAAA;;AAAA;AAAA;AAAA;AAAA,+CAM0B6pC,GAAgB5lD,CAAG,CAAC;AAAA;AAAA,aAEvDtT,EAAAsT,EAAI,QAAJ,MAAAtT,EAAW,YACTsuB;AAAAA;AAAAA;AAAAA,qDAGuC2qC,GAAc3lD,EAAI,MAAM,WAAW,CAAC;AAAA;AAAA,gBAG3E+b,CAAO;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,YAOTe,EAAM,KAAK,SAAW,EACpB9B,2EACAA;AAAAA;AAAAA,oBAEM,CAAC,GAAG8B,EAAM,IAAI,EAAE,KAAK,CAAC5wB,EAAGM,IAAMA,EAAE,GAAKN,EAAE,EAAE,EAAE,IAAK4O,GAAUiuD,GAAUjuD,CAAK,CAAC,CAAC;AAAA;AAAA,eAEjF;AAAA;;AAAA;AAAA;AAAA,GAMf,CAIA,SAASstD,GAAetrC,EAAkB,CACxC,MAAMhpB,EAASgpB,EAAM,UACfksC,EAAU,CAACl1D,EACXm1D,GAAcn1D,GAAA,YAAAA,EAAQ,UAAW,KAAO,aAAcA,GAAA,YAAAA,EAAQ,UAAW,QAAU,SAAUA,GAAA,YAAAA,EAAQ,UAAW,UAAY,WAAYA,GAAA,YAAAA,EAAQ,SAAU,GAEhK,OAAOknB;AAAAA,8CACqC8B,EAAM,eAAe;AAAA,kEACAtxB,GAAaA,EAAE,iBAAiB;AAAA;AAAA,4CAEvDsxB,EAAM,eAAe;AAAA,sDACXA,EAAM,eAAe;AAAA,cAC7DuO,EAAK;AAAA;AAAA;;AAAA,UAIT29B,EACEhuC;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,cAQAA;AAAAA;AAAAA;AAAAA;AAAAA,kCAIsBlnB,EAAO,SAAW,KAAO,UAAYA,EAAO,SAAW,SAAWA,EAAO,SAAW,UAAY,YAAc,EAAE;AAAA;AAAA;AAAA,sBAG5Hm1D,CAAW;AAAA;AAAA,oBAEbn1D,EAAO,YAAc,KACnBknB,iDAAoDpmB,GAAiBd,EAAO,UAAU,CAAC,UACvFioB,CAAO;AAAA;AAAA,kBAEXjoB,EAAO,YAAcA,EAAO,QAC1BknB;AAAAA,sJACkIlnB,EAAO,YAAcA,EAAO,OAAO;AAAA,sBAErKioB,CAAO;AAAA,kBACTjoB,EAAO,MACLknB;AAAAA;AAAAA;AAAAA,8GAG0FlnB,EAAO,KAAK;AAAA;AAAA,sBAGtGioB,CAAO;AAAA,kBACT,CAACjoB,EAAO,YAAc,CAACA,EAAO,SAAW,CAACA,EAAO,MAC/CknB,mFACAe,CAAO;AAAA;AAAA;AAAA,qDAG0Be,EAAM,eAAe;AAAA;AAAA,aAE7D;AAAA;AAAA;AAAA,GAIb,CAIA,SAASosC,GAAetnD,EAAwB,CAC9C,MAAMnW,EAAImW,EAAO,cACjB,OAAInW,IAAM,MAAQA,IAAM,UAAkB,eACtCA,IAAM,SAAWA,IAAM,QAAUA,IAAM,UAAYA,IAAM,UAAkB,iBACxE,MACT,CAEA,SAASs9D,GAAUjuD,EAAwB,CACzC,OAAOkgB;AAAAA;AAAAA;AAAAA,sBAGakuC,GAAepuD,EAAM,MAAM,CAAC;AAAA,YACtCA,EAAM,MAAM;AAAA;AAAA,uDAE+BxG,GAAUwG,EAAM,EAAE,CAAC;AAAA,uDACnBlG,GAAiBkG,EAAM,UAAU,CAAC;AAAA;AAAA,QAEjFA,EAAM,QACJkgB,gDAAmDlgB,EAAM,OAAO,SAChEihB,CAAO;AAAA,QACTjhB,EAAM,MACJkgB;AAAAA;AAAAA;AAAAA,oGAG0FlgB,EAAM,KAAK;AAAA;AAAA,YAGrGihB,CAAO;AAAA;AAAA,GAGjB,CC/xBO,SAASotC,GAAarsC,EAAoB,OAC/C,MAAMssC,IAAS18D,EAAAowB,EAAM,SAAN,YAAApwB,EAAc,SAAU,GACjC28D,EAASvsC,EAAM,OAAO,OAAO,cAC7BwsC,EAAaxsC,EAAM,WACnBysC,EAAczsC,EAAM,YACpBlkB,EAAWwwD,EAAO,OAAQI,GAAU,OAIxC,OAHIF,IAAe,aAAe,CAACE,EAAM,WACrCF,IAAe,SAAWE,EAAM,WAAaA,EAAM,cACnDF,IAAe,YAAc,CAACE,EAAM,aACpCD,IAAgB,OAAS,GAAC78D,EAAA88D,EAAM,SAAN,MAAA98D,EAAc,SAAS68D,IAAqB,GACtEF,EACK,CAACG,EAAM,KAAMA,EAAM,WAAW,EAClC,KAAK,GAAG,EACR,cACA,SAASH,CAAM,EAEb,EACT,CAAC,EAEKI,EAAW,CAACh0D,EAAe9G,IAA2BqsB;AAAAA;AAAAA,oBAE1CsuC,IAAe36D,EAAQ,UAAY,EAAE;AAAA,0DAEjD26D,IAAe36D,EAAQ,yBAA2B,yCACpD,YAAY26D,IAAe36D,EAAQ,OAAS,aAAa;AAAA,eAChD,IAAMmuB,EAAM,mBAAmBnuB,CAAK,CAAC;AAAA,OAC7C8G,CAAK;AAAA,IAGJi0D,EAAY,CAACj0D,EAAe9G,IAA4BqsB;AAAAA;AAAAA,oBAE5CuuC,IAAgB56D,EAAQ,UAAY,EAAE;AAAA,0DAElD46D,IAAgB56D,EAAQ,yBAA2B,yCACrD,YAAY46D,IAAgB56D,EAAQ,OAAS,aAAa;AAAA,eACjD,IAAMmuB,EAAM,oBAAoBnuB,CAAK,CAAC;AAAA,OAC9C8G,CAAK;AAAA,IAGV,OAAOulB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,+CAQsC8B,EAAM,SAAS;AAAA,0CACpBA,EAAM,OAAO,WAAWA,EAAM,SAAS;AAAA,cACnEA,EAAM,QAAU,WAAa,SAAS;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,qBAS/BA,EAAM,MAAM;AAAA,qBACXtxB,GACRsxB,EAAM,eAAgBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,YAK5Di+D,EAAS,MAAO,KAAK,CAAC;AAAA,YACtBA,EAAS,YAAa,WAAW,CAAC;AAAA,YAClCA,EAAS,OAAQ,MAAM,CAAC;AAAA,YACxBA,EAAS,WAAY,UAAU,CAAC;AAAA;AAAA;AAAA,YAGhCC,EAAU,aAAc,KAAK,CAAC;AAAA,YAC9BA,EAAU,QAAS,OAAO,CAAC;AAAA,YAC3BA,EAAU,SAAU,QAAQ,CAAC;AAAA;AAAA,6BAEZ9wD,EAAS,MAAM;AAAA;;AAAA,QAGpCkkB,EAAM,MACJ9B,0DAA6D8B,EAAM,KAAK,SACxEf,CAAO;;AAAA,QAETnjB,EAAS,SAAW,EAClBoiB,uEACAA;AAAAA;AAAAA,gBAEMpiB,EAAS,IAAK4wD,GAAUG,GAAYH,EAAO1sC,CAAK,CAAC,CAAC;AAAA;AAAA,WAEvD;AAAA;;AAAA,MAGLA,EAAM,OAASqrC,GAAkBrrC,CAAK,EAAIf,CAAO;AAAA,MACjDe,EAAM,SAAW8sC,GAAe9sC,CAAK,EAAIf,CAAO;AAAA,GAEtD,CAEA,SAAS4tC,GAAYH,EAAyB1sC,EAAoB,CAChE,MAAMkK,EAAOlK,EAAM,UAAY0sC,EAAM,SAC/B94C,EAASoM,EAAM,MAAM0sC,EAAM,QAAQ,GAAK,GACxC5zD,EAAUknB,EAAM,SAAS0sC,EAAM,QAAQ,GAAK,KAC5CK,EACJL,EAAM,QAAQ,OAAS,GAAKA,EAAM,QAAQ,KAAK,OAAS,EACpDM,EAAU,CACd,GAAGN,EAAM,QAAQ,KAAK,IAAKh9D,GAAM,OAAOA,CAAC,EAAE,EAC3C,GAAGg9D,EAAM,QAAQ,IAAI,IAAKh+D,GAAM,OAAOA,CAAC,EAAE,EAC1C,GAAGg+D,EAAM,QAAQ,OAAO,IAAKx9D,GAAM,UAAUA,CAAC,EAAE,EAChD,GAAGw9D,EAAM,QAAQ,GAAG,IAAK99D,GAAM,MAAMA,CAAC,EAAE,GAEpCq+D,EAAoB,GAC1B,OAAIP,EAAM,UAAUO,EAAQ,KAAK,UAAU,EACvCP,EAAM,oBAAoBO,EAAQ,KAAK,sBAAsB,EAC1D/uC;AAAAA,6DACoD,IAAM8B,EAAM,aAAa0sC,EAAM,IAAI,CAAC;AAAA;AAAA;AAAA,YAGrFA,EAAM,MAAQ,GAAGA,EAAM,KAAK,IAAM,EAAE,GAAGA,EAAM,IAAI;AAAA;AAAA,gCAE7B30D,GAAU20D,EAAM,YAAa,GAAG,CAAC;AAAA;AAAA,8BAEnCA,EAAM,UAAY,UAAY,EAAE;AAAA,cAChDA,EAAM,YAAc,WAAaA,EAAM,UAAY,YAAc,MAAM;AAAA;AAAA,YAEzEA,EAAM,aAAeA,EAAM,mBACzBxuC,sHAAyHwuC,EAAM,kBAAkB,UACjJztC,CAAO;AAAA,YACTytC,EAAM,SAAWxuC,gDAAqDe,CAAO;AAAA,YAC5EytC,EAAM,UAYLztC,EAXAf;AAAAA,8BACgBwuC,EAAM,aAAe,UAAY,EAAE;AAAA;AAAA,wBAEzCA,EAAM,aACV,0EACA,sEAAsE;AAAA,yBAChEh+D,GAAa,CACrBA,EAAE,kBACFsxB,EAAM,qBAAqB0sC,EAAM,KAAM,CAACA,EAAM,YAAY,CAC5D,CAAC;AAAA,iBACAA,EAAM,aAAe,gBAAkB,WAAW,SAC9C;AAAA,YACTQ,GAAsBR,EAAO1sC,CAAK,CAAC;AAAA;AAAA,UAErCgtC,EAAQ,OAAS,EACf9uC;AAAAA;AAAAA,2BAEe8uC,EAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,cAGjC/tC,CAAO;AAAA,UACTguC,EAAQ,OAAS,EACf/uC;AAAAA;AAAAA,0BAEc+uC,EAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,cAGhChuC,CAAO;AAAA;AAAA,sCAEoBvwB,GAAaA,EAAE,iBAAiB;AAAA;AAAA,YAE3Dg+D,EAAM,UACJztC,EACAf;AAAAA;AAAAA,4BAEcgM,CAAI;AAAA,yBACP,IAAMlK,EAAM,SAAS0sC,EAAM,SAAUA,EAAM,QAAQ,CAAC;AAAA;AAAA,kBAE3DA,EAAM,SAAW,SAAW,SAAS;AAAA,wBAC/B;AAAA,YACXA,EAAM,UAQLztC,EAPAf;AAAAA;AAAAA,4BAEcgM,CAAI;AAAA,yBACP,IAAMlK,EAAM,YAAY0sC,EAAM,IAAI,CAAC;AAAA;AAAA;AAAA,wBAIvC;AAAA,YACRA,EAAM,UAYLztC,EAXAf;AAAAA;AAAAA,4BAEcgM,CAAI;AAAA,yBACP,IAAM,CACT,QAAQ,iBAAiBwiC,EAAM,IAAI,IAAI,GACzC1sC,EAAM,SAAS0sC,EAAM,IAAI,CAE7B,CAAC;AAAA;AAAA;AAAA,wBAII;AAAA,YACTK,EACE7uC;AAAAA;AAAAA,4BAEcgM,CAAI;AAAA,yBACP,IACPlK,EAAM,UAAU0sC,EAAM,SAAUA,EAAM,KAAMA,EAAM,QAAQ,CAAC,EAAE,EAAE,CAAC;AAAA;AAAA,kBAEhExiC,EAAO,cAAgBwiC,EAAM,QAAQ,CAAC,EAAE,KAAK;AAAA,yBAEjDztC,CAAO;AAAA;AAAA,UAEXnmB,EACEolB;AAAAA;AAAAA,+CAGIplB,EAAQ,OAAS,QACb,+BACA,+BACN;AAAA;AAAA,gBAEEA,EAAQ,OAAO;AAAA,oBAEnBmmB,CAAO;AAAA,UACTytC,EAAM,WACJxuC;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,2BAKetK,CAAM;AAAA,2BACLllB,GACRsxB,EAAM,OAAO0sC,EAAM,SAAWh+D,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAM1Dw7B,CAAI;AAAA,yBACP,IAAMlK,EAAM,UAAU0sC,EAAM,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,cAKlDztC,CAAO;AAAA;AAAA;AAAA,GAInB,CAEA,SAASiuC,GAAsBR,EAAyB1sC,EAAoB,CAC1E,MAAM1K,EAASo3C,EAAM,QAAU,CAAC,QAAS,QAAQ,EAC3CS,EAAST,EAAM,aACfU,EAAW93C,EAAO,SAAS,OAAO,EAClC+3C,EAAY/3C,EAAO,SAAS,QAAQ,EAEpCg4C,EAAS,CAACzjC,EAAe0jC,IAAqB,CAClD,MAAMl4D,EAAOk4D,EACT,CAAC,GAAGj4C,EAAQuU,CAAK,EACjBvU,EAAO,OAAQlmB,GAAMA,IAAMy6B,CAAK,EAChCx0B,EAAK,SAAW,GACpB2qB,EAAM,eAAe0sC,EAAM,SAAUr3D,CAAI,CAC3C,EAEA,OAAO6oB;AAAAA;AAAAA,gJAEuIivC,EAAS,GAAM,CAAC;AAAA,eAChJz+D,GAAaA,EAAE,iBAAiB;AAAA;AAAA,mFAEmCy+D,EAAS,UAAY,SAAS;AAAA;AAAA;AAAA,qBAG5FC,CAAQ;AAAA,sBACPD,CAAM;AAAA,oBACPz+D,GAAa4+D,EAAO,QAAU5+D,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,mFAKNy+D,EAAS,UAAY,SAAS;AAAA;AAAA;AAAA,qBAG5FE,CAAS;AAAA,sBACRF,CAAM;AAAA,oBACPz+D,GAAa4+D,EAAO,SAAW5+D,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAO1F,CAIA,SAAS28D,GAAkBrrC,EAAoB,WAC7C,MAAMjL,EAASiL,EAAM,OACfwtC,EAAO,CAAC,WAAY,GAAGz4C,EAAO,WAAW,IAAKjmB,GAAMA,EAAE,IAAI,CAAC,EAC3DgmB,EAAYkL,EAAM,WAAa,WAC/BytC,EACJ34C,IAAc,WACVC,EAAO,UACPnlB,EAAAmlB,EAAO,WAAW,KAAMjmB,GAAMA,EAAE,OAASgmB,CAAS,IAAlD,YAAAllB,EAAqD,UAAW,GAEhE89D,EAAsBh/D,GAAa,CAClCA,EAAE,OAAuB,UAAU,SAAS,qBAAqB,GACpEsxB,EAAM,eAEV,EAGM2tC,GAAa9vC,GAAAhuB,EAAAmwB,EAAM,SAAN,YAAAnwB,EAAc,SAAd,YAAAguB,EAAsB,KAAMlvB,GAAMA,EAAE,OAASomB,EAAO,MACjE64C,EAAcD,EAAa,CAACA,EAAW,UAAY,GAEzD,OAAOzvC;AAAAA,8CACqCwvC,CAAkB;AAAA,yEACUh/D,GAAaA,EAAE,iBAAiB;AAAA;AAAA,4CAE9DqmB,EAAO,IAAI;AAAA;AAAA,cAEzC64C,EACE1vC,+BAAkC,IAAM8B,EAAM,aAAalL,CAAS,CAAC,iBACrEmK,CAAO;AAAA,wDACiCe,EAAM,aAAa;AAAA;AAAA;AAAA,UAGjEwtC,EAAK,OAAS,EACZtvC;AAAAA;AAAAA,kBAEMsvC,EAAK,IACJt5C,GAAQgK;AAAAA;AAAAA,oCAEShK,IAAQY,EAAY,UAAY,EAAE;AAAA,0EAE9CZ,IAAQY,EAAY,yBAA2B,yCACjD,YAAYZ,IAAQY,EAAY,OAAS,aAAa;AAAA,+BAC7C,IAAMkL,EAAM,YAAY9L,CAAG,CAAC;AAAA;AAAA,wBAEnCA,CAAG;AAAA;AAAA,oBAGV;AAAA;AAAA,cAGL+K,CAAO;AAAA,8OAC2NwuC,CAAa;AAAA;AAAA;AAAA,GAI3P,CAIA,SAASX,GAAe9sC,EAAoB,CAC1C,MAAM6tC,EAAY7tC,EAAM,OAAO,OAAS,EAClCkK,EAAOlK,EAAM,UAAY,UACzB8tC,EAAa9tC,EAAM,QAAQ,KAAK,SAAW,GAC3C+tC,EAAc/tC,EAAM,aAAe,YAEnC0tC,EAAsBh/D,GAAa,CAClCA,EAAE,OAAuB,UAAU,SAAS,qBAAqB,GACpEsxB,EAAM,YAEV,EAEMvY,EAAQqmD,EACVC,EACE,eAAe/tC,EAAM,QAAQ,IAAI,GACjC,eAAeA,EAAM,QAAQ,IAAI,GACnC,eAEJ,OAAO9B;AAAAA,8CACqCwvC,CAAkB;AAAA,yEACUh/D,GAAaA,EAAE,iBAAiB;AAAA;AAAA,4CAE9D+Y,CAAK;AAAA,sDACKuY,EAAM,UAAU;AAAA;;AAAA,UAG5D8tC,EACEE,GAAgBhuC,EAAOkK,CAAI,EAC3B2jC,EACEI,GAAiBjuC,EAAOkK,CAAI,EAC5BhM;AAAAA;AAAAA;AAAAA;AAAAA,eAIC;AAAA;AAAA;AAAA,GAIf,CAEA,SAAS8vC,GAAgBhuC,EAAoBkK,EAAe,CAC1D,MAAM1oB,EAAOwe,EAAM,QAEbkuC,EADcluC,EAAM,aAAe,YACT,aAAe,aACzCmuC,EAAU3sD,EAAK,WAAW,OAAS,EACnCsT,EAAYkL,EAAM,SAAW,WAC7BouC,EAAY5sD,EAAK,WAAW,KAAM1S,GAAMA,EAAE,OAASgmB,CAAS,EAE5Du5C,EAAWn6C,GAAgBgK;AAAAA;AAAAA,oBAEfhK,IAAQY,EAAY,UAAY,EAAE;AAAA,0DAE9CZ,IAAQY,EAAY,yBAA2B,yCACjD,YAAYZ,IAAQY,EAAY,OAAS,aAAa;AAAA,eAC7C,IAAMkL,EAAM,UAAU9L,CAAG,CAAC;AAAA,OAClCA,CAAG;AAAA,IAGR,OAAOgK;AAAAA;AAAAA;AAAAA;AAAAA,iBAIQ1c,EAAK,IAAI;AAAA,iBACR9S,GAAasxB,EAAM,gBAAgB,OAAStxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA,MAI5Fy/D,EACEjwC;AAAAA;AAAAA,cAEMmwC,EAAQ,UAAU,CAAC;AAAA,cACnB7sD,EAAK,WAAW,IAAK1S,GAAMu/D,EAAQv/D,EAAE,IAAI,CAAC,CAAC;AAAA;AAAA,UAGjDmwB,CAAO;AAAA,MACTmvC,EACElwC;AAAAA;AAAAA,oBAEYkwC,EAAU,IAAI;AAAA;AAAA,uBAEXA,EAAU,OAAO;AAAA,uBAChB1/D,GAAasxB,EAAM,YAAYouC,EAAU,KAAO1/D,EAAE,OAA+B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA,UAKvGwvB;AAAAA;AAAAA;AAAAA;AAAAA,uBAIe1c,EAAK,YAAY;AAAA,uBAChB9S,GAAasxB,EAAM,gBAAgB,eAAiBtxB,EAAE,OAA+B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,SAK1G;AAAA;AAAA,mCAE0BsxB,EAAM,UAAU;AAAA;AAAA;AAAA,oBAG/BkK,GAAQ,CAAC1oB,EAAK,KAAK,QAAU,CAACA,EAAK,aAAa,MAAM;AAAA,iBACzDwe,EAAM,SAAS;AAAA;AAAA,UAEtBkK,EAAO,UAAYgkC,CAAS;AAAA;AAAA;AAAA,GAItC,CAEA,SAASD,GAAiBjuC,EAAoBkK,EAAe,CAC3D,OAAOhM;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,QAKD8B,EAAM,OAAO,IACZ1L,GAAU,SACT,MAAMg6C,IAAmBz+D,GAAAD,EAAAowB,EAAM,SAAN,YAAApwB,EAAc,SAAd,YAAAC,EAAsB,KAAMlB,GAAMA,EAAE,OAAS2lB,EAAM,QAAS,GACrF,OAAO4J;AAAAA;AAAAA;AAAAA,wCAGuB5J,EAAM,IAAI;AAAA;AAAA,kBAEhCA,EAAM,WAAW,OAAS,EACxB,cAAcA,EAAM,WAAW,MAAM,aAAaA,EAAM,WAAW,OAAS,EAAI,IAAM,EAAE,GACxF,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,8BAOA4V,CAAI;AAAA,2BACP,IAAMlK,EAAM,cAAc1L,CAAK,CAAC;AAAA;AAAA;AAAA;AAAA,kBAIzCg6C,EACEpwC,2FACAA;AAAAA;AAAAA,kCAEcgM,CAAI;AAAA,+BACP,IAAMlK,EAAM,eAAe1L,CAAK,CAAC;AAAA;AAAA,wBAExC4V,EAAO,cAAgB,SAAS;AAAA,8BAC1B;AAAA;AAAA;AAAA,8BAGAA,CAAI;AAAA,2BACP,IAAMlK,EAAM,cAAc1L,EAAM,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAOvD,EACF;AAAA;AAAA,GAGP,CCriBA,MAAMi6C,GAA0B,CAC9B,OACA,YACA,YACA,cACA,WACA,OACF,EAwBMC,GAA8C,CAClD,KAAM,OACN,UAAW,YACX,KAAM,OACN,UAAW,OACX,YAAa,SACb,SAAU,WACV,MAAO,QACP,OAAQ,QACV,EAKA,SAASC,GAAmBC,EAAsB11D,EAAkC,CAClF,OAAI01D,IAAS,OAAe,YACxBA,IAAS,eAAiB,OAAO11D,GAAY,UAAYA,EAAQ,WAAW,SAAS,EAAU,QAC5F01D,CACT,CAEA,SAASvqB,GAAWtyC,EAAgB,CAClC,GAAI,CAACA,EAAO,MAAO,GACnB,MAAM88D,EAAO,IAAI,KAAK98D,CAAK,EAC3B,OAAI,OAAO,MAAM88D,EAAK,SAAS,EAAU98D,EAClC88D,EAAK,eAAe,OAAW,CACpC,IAAK,UACL,MAAO,QACP,KAAM,UACN,OAAQ,UACR,OAAQ,UACT,CACH,CAEA,SAASC,GAAmB/4D,EAAqB,CAI/C,OADcA,EAAI,MAAM,GAAG,EACd,MAAM,CAAC,EAAE,KAAK,GAAG,GAAKA,CACrC,CAEA,SAASg5D,GAAc7wD,EAA+B8wD,EAAgB,CACpE,OAAKA,EACY,CAAC9wD,EAAM,QAASA,EAAM,QAASA,EAAM,WAAYA,EAAM,UAAWA,EAAM,SAAUA,EAAM,UAAU,EAChH,OAAO,OAAO,EACd,KAAK,GAAG,EACR,cACa,SAAS8wD,CAAM,EALX,EAMtB,CAGA,SAASC,GAAS/wD,EAA+Bi0B,EAAuB,CACtE,MAAO,GAAGj0B,EAAM,SAAS,IAAIA,EAAM,SAAS,IAAIi0B,CAAK,EACvD,CAEA,MAAM+8B,GAAyB,IAE/B,SAASC,GACPjxD,EACAkxD,EACS,CACT,MAAMC,EAAUV,GAAmBzwD,EAAM,KAAMA,EAAM,OAAO,EAC5D,OAAOkxD,EAAYC,CAAO,GAAK,EACjC,CAEO,SAASC,GAAkBpvC,EAAyB,CACzD,MAAM8uC,EAAS9uC,EAAM,WAAW,OAAO,cACjClkB,EAAWkkB,EAAM,QAAQ,OAAQhiB,GACjC,CAACixD,GAAiBjxD,EAAOgiB,EAAM,WAAW,GAC1CA,EAAM,OAAO,OAAS,GAAK,EAAEA,EAAM,aAAahiB,EAAM,OAAO,GAAK,IAAc,GAC7E6wD,GAAc7wD,EAAO8wD,CAAM,CACnC,EAED,OAAO5wC;AAAAA;AAAAA,sEAE6D8B,EAAM,aAAa;AAAA,yCAChDA,EAAM,cAAgB,WAAa,EAAE,KAAK/B,EAAM,WAAW;AAAA;AAAA;AAAA,QAG5F+B,EAAM,cAAgB9B;AAAAA;AAAAA,YAElBqwC,GAAM,IACLG,GAASxwC;AAAAA,oDAC8BwwC,CAAI;AAAA;AAAA;AAAA,6BAG3B1uC,EAAM,YAAY0uC,CAAI,CAAC;AAAA,4BACvBhgE,GACTsxB,EAAM,aAAa0uC,EAAOhgE,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA,wBAE5D8/D,GAAYE,CAAI,CAAC;AAAA;AAAA,cAG9B;AAAA,YACC1uC,EAAM,OAAO,IACZ6J,GAAU3L;AAAAA;AAAAA;AAAAA;AAAAA,6BAIM8B,EAAM,aAAa6J,CAAK,GAAK,EAAI;AAAA,4BACjCn7B,GACTsxB,EAAM,cAAc6J,EAAQn7B,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA,wBAE9Dm7B,CAAK;AAAA;AAAA,cAGlB;AAAA;AAAA;AAAA;AAAA,yBAIc7J,EAAM,UAAU;AAAA,wBAChBtxB,GACTsxB,EAAM,mBAAoBtxB,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKtEuwB,CAAO;;AAAA,QAETe,EAAM,MACJ9B,0DAA6D8B,EAAM,KAAK,SACxEf,CAAO;;AAAA,kEAEiDe,EAAM,QAAQ;AAAA,UACtElkB,EAAS,SAAW,EAClBoiB,2EACApiB,EAAS,IAAI,CAACkC,EAAO5G,IAAQ,CAC3B,MAAM+3D,EAAUV,GAAmBzwD,EAAM,KAAMA,EAAM,OAAO,EACtDpD,EAAKm0D,GAAS/wD,EAAO5G,CAAG,EACxB03B,EAAW9O,EAAM,YAAY,IAAIplB,CAAE,EACnCy0D,EAASrxD,EAAM,QAAQ,OAASgxD,GAChCh2D,EAAU81B,GAAY,CAACugC,EACzBrxD,EAAM,QACNA,EAAM,QAAQ,MAAM,EAAGgxD,EAAsB,EAAI,IAErD,OAAO9wC;AAAAA,oDAC+BixC,CAAO;AAAA;AAAA,kDAEThrB,GAAWnmC,EAAM,SAAS,CAAC;AAAA,oDACzBmxD,CAAO,KAAKX,GAAYW,CAAO,CAAC;AAAA,uDAC7BnxD,EAAM,OAAO;AAAA,uDACb4wD,GAAmB5wD,EAAM,UAAU,CAAC;AAAA,sBACrEA,EAAM,SACJkgB,oCAAuClgB,EAAM,QAAQ,UACrDihB,CAAO;AAAA,sBACTjhB,EAAM,WACJkgB,uCAA0ClgB,EAAM,WAAW,MAAM,EAAG,EAAE,CAAC,UACvEihB,CAAO;AAAA,sBACTjhB,EAAM,MACJkgB,qCAAwClgB,EAAM,KAAK,UACnDihB,CAAO;AAAA;AAAA,kDAEmBjmB,CAAO;AAAA,oBACrCq2D,EACEnxC;AAAAA;AAAAA,iCAEW,IAAM8B,EAAM,eAAeplB,CAAE,CAAC;AAAA,yBACtCk0B,EAAW,WAAa,QAAQ,YACnC7P,CAAO;AAAA;AAAA,eAGjB,CAAC,CAAC;AAAA;AAAA;AAAA,GAId,CCnMA,MAAMjZ,GAAqB,CAAC,QAAS,QAAS,OAAQ,OAAQ,QAAS,OAAO,EAkC9E,SAASm+B,GAAWtyC,EAAuB,CACzC,GAAI,CAACA,EAAO,MAAO,GACnB,MAAM88D,EAAO,IAAI,KAAK98D,CAAK,EAC3B,OAAI,OAAO,MAAM88D,EAAK,SAAS,EAAU98D,EAClC88D,EAAK,oBACd,CAEA,SAASE,GAAc7wD,EAAiB8wD,EAAgB,CACtD,OAAKA,EACY,CAAC9wD,EAAM,QAASA,EAAM,UAAWA,EAAM,GAAG,EACxD,OAAO,OAAO,EACd,KAAK,GAAG,EACR,cACa,SAAS8wD,CAAM,EALX,EAMtB,CAEO,SAASQ,GAAWtvC,EAAkB,CAG3C,MAAMuvC,EAAY,CAACvvC,EAAM,SAAWA,EAAM,aAAe,UAEzD,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,kCAIyBqxC,EAAY,SAAW,EAAE;AAAA,qBACtC,IAAMvvC,EAAM,eAAe,SAAS,CAAC;AAAA;AAAA;AAAA,YAG9CA,EAAM,QAAU9B;AAAAA,kCACOqxC,EAAuB,GAAX,QAAa;AAAA,qBACvC,IAAMvvC,EAAM,eAAe,QAAQ,CAAC;AAAA;AAAA;AAAA,YAG3Cf,CAAO;AAAA;;AAAA,UAGXswC,EAAYrxC;AAAAA;AAAAA;AAAAA,qBAGD8B,EAAM,iBAAiB,UAAU;AAAA,qBAChCtxB,GACRsxB,EAAM,iBAAiB,mBAAoBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA,UAGjFwvB;AAAAA;AAAAA;AAAAA,qBAGS8B,EAAM,UAAU;AAAA,qBACftxB,GACRsxB,EAAM,mBAAoBtxB,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA,SAGnE;;AAAA;AAAA,YAGG6gE,EAAYrxC;AAAAA,mDAC2B8B,EAAM,iBAAiB,OAAO,WAAWA,EAAM,iBAAiB,SAAS;AAAA,gBAC5GA,EAAM,iBAAiB,QAAU,WAAkB,SAAS;AAAA;AAAA;AAAA;AAAA,0BAIlDA,EAAM,iBAAiB,QAAQ,SAAW,CAAC;AAAA,uBAC9C,IAAM,CACb,MAAMwvC,EAAKxvC,EAAM,iBACX8uC,EAASU,EAAG,WAAW,OAAO,cAS9B71D,EARW61D,EAAG,QAAQ,OAAQxxD,GAAU,CAC5C,MAAMyxD,EAAczxD,EAAM,OAAS,OAAS,YAAcA,EAAM,KAEhE,MADI,CAACwxD,EAAG,YAAYC,CAAW,GAC3BD,EAAG,OAAO,OAAS,GAAK,EAAEA,EAAG,aAAaxxD,EAAM,OAAO,GAAK,IAAc,GACzE8wD,EACE,CAAC9wD,EAAM,QAASA,EAAM,QAASA,EAAM,WAAYA,EAAM,UAAWA,EAAM,SAAUA,EAAM,UAAU,EACtG,OAAO,OAAO,EAAE,KAAK,GAAG,EAAE,cAAc,SAAS8wD,CAAM,EAFtC,EAGtB,CAAC,EACsB,IAAKpgE,GAC1B,GAAGA,EAAE,SAAS,KAAMA,EAAE,IAAI,KAAMA,EAAE,OAAO,IAAKA,EAAE,UAAU,IAAKA,EAAE,UAAY,EAAE,IAAKA,EAAE,OAAO,EAAE,EACjG8gE,EAAG,SAAS71D,EAAOm1D,EAAS,WAAa,SAAS,CACpD,CAAC;AAAA;AAAA;AAAA;AAAA,YAID5wC;AAAAA,mDACqC8B,EAAM,OAAO,WAAWA,EAAM,SAAS;AAAA,gBAC1EA,EAAM,QAAU,WAAkB,SAAS;AAAA;AAAA;AAAA;AAAA,0BAIjCA,EAAM,QAAQ,SAAW,CAAC;AAAA,uBAC7B,IAAM,CACb,MAAM8uC,EAAS9uC,EAAM,WAAW,OAAO,cACjC0vC,EAAgB1pD,GAAO,KAAMO,GAAU,CAACyZ,EAAM,aAAazZ,CAAK,CAAC,EACjEzK,EAAWkkB,EAAM,QAAQ,OAAQhiB,GACjCA,EAAM,OAAS,CAACgiB,EAAM,aAAahiB,EAAM,KAAK,EAAU,GACrD6wD,GAAc7wD,EAAO8wD,CAAM,CACnC,EACKa,EAAcb,GAAUY,EAAgB,WAAa,UAC3D1vC,EAAM,SAASlkB,EAAS,IAAKkC,GAAUA,EAAM,GAAG,EAAG2xD,CAAW,CAChE,CAAC;AAAA;AAAA;AAAA;AAAA,WAIJ;AAAA;AAAA;;AAAA,QAIHJ,EACEH,GAAkBpvC,EAAM,gBAAgB,EACxC4vC,GAAiB5vC,CAAK,CAAC;AAAA;AAAA,GAGjC,CAEA,SAAS4vC,GAAiB5vC,EAAkB,CAC1C,MAAM8uC,EAAS9uC,EAAM,WAAW,OAAO,cACjBha,GAAO,KAAMO,GAAU,CAACyZ,EAAM,aAAazZ,CAAK,CAAC,EACvE,MAAMzK,EAAWkkB,EAAM,QAAQ,OAAQhiB,GACjCA,EAAM,OAAS,CAACgiB,EAAM,aAAahiB,EAAM,KAAK,EAAU,GACrD6wD,GAAc7wD,EAAO8wD,CAAM,CACnC,EAEKe,EAAQ7vC,EAAM,eACd8vC,EAAc9vC,EAAM,eAAiB6vC,EAAM,OAAS,EAAIA,EAAM,CAAC,EAAI,MACnEpsC,EAAeqsC,EAAcD,EAAM,QAAQC,CAAW,EAAI,EAC1DC,EAAWtsC,EAAe,GAAKzD,EAAM,cAAgB,KACrDgwC,EAAWvsC,GAAgB,GAAKA,EAAeosC,EAAM,OAAS,EAEpE,OAAO3xC;AAAAA,MACH2xC,EAAM,OAAS,EAAI3xC;AAAAA;AAAAA,+CAEsB,CAAC8xC,CAAQ;AAAA,mBACrC,IAAM,CACb,MAAMC,EAAUxsC,EAAe,EAC3BwsC,EAAUJ,EAAM,UAAc,aAAaA,EAAMI,CAAO,CAAC,CAC/D,CAAC,IAAIhyC,EAAM,WAAW;AAAA,wCACQ6xC,GAAe,OAAO;AAAA,+CACf,CAACC,CAAQ;AAAA,mBACrC,IAAM,CACTtsC,GAAgB,EAClBzD,EAAM,aAAa,IAAI,EAEvBA,EAAM,aAAa6vC,EAAMpsC,EAAe,CAAC,CAAC,CAE9C,CAAC,UAAUxF,EAAM,YAAY;AAAA,UAC7B+B,EAAM,cAAgB,KAAO9B;AAAAA,8CACO,IAAM8B,EAAM,aAAa,IAAI,CAAC;AAAA;AAAA;AAAA,UAGhEf,CAAO;AAAA;AAAA,MAEXA,CAAO;;AAAA,0CAE2Be,EAAM,aAAa;AAAA,uCACtBA,EAAM,cAAgB,WAAa,EAAE,KAAK/B,EAAM,WAAW;AAAA;AAAA;AAAA,MAG5F+B,EAAM,cAAgB9B;AAAAA;AAAAA,UAElBlY,GAAO,IACNO,GAAU2X;AAAAA,0CACqB3X,CAAK;AAAA;AAAA;AAAA,2BAGpByZ,EAAM,aAAazZ,CAAK,CAAC;AAAA,0BACzB7X,GACTsxB,EAAM,cAAczZ,EAAQ7X,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA,sBAE9D6X,CAAK;AAAA;AAAA,YAGlB;AAAA;AAAA;AAAA;AAAA,uBAIcyZ,EAAM,UAAU;AAAA,sBAChBtxB,GACTsxB,EAAM,mBAAoBtxB,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MAKtEuwB,CAAO;;AAAA,MAETe,EAAM,KACJ9B,uDAA0D8B,EAAM,IAAI,SACpEf,CAAO;AAAA,MACTe,EAAM,UACJ9B;AAAAA;AAAAA,gBAGAe,CAAO;AAAA,MACTe,EAAM,MACJ9B,0DAA6D8B,EAAM,KAAK,SACxEf,CAAO;;AAAA,gEAEiDe,EAAM,QAAQ;AAAA,QACtElkB,EAAS,SAAW,EAClBoiB,mEACA,CAAC,GAAGpiB,CAAQ,EAAE,UAAU,IACrBkC,GAAUkgB;AAAAA;AAAAA;AAAAA,gDAGyBimB,GAAWnmC,EAAM,IAAI,CAAC;AAAA,2CAC3BA,EAAM,OAAS,EAAE,KAAKA,EAAM,OAAS,EAAE;AAAA,qDAC7BA,EAAM,WAAa,EAAE;AAAA;AAAA,gDAE1BA,EAAM,SAAWA,EAAM,GAAG;AAAA;AAAA,cAG/D;AAAA;AAAA,GAGX,CCxOA,MAAMkyD,GAA+C,CACnD,CAAE,IAAK,SAAU,MAAO,UACxB,CAAE,IAAK,UAAW,MAAO,WACzB,CAAE,IAAK,YAAa,MAAO,aAC3B,CAAE,IAAK,WAAY,MAAO,YAC1B,CAAE,IAAK,SAAU,MAAO,UACxB,CAAE,IAAK,WAAY,MAAO,YAC1B,CAAE,IAAK,SAAU,MAAO,SAC1B,EAIM3hC,GAAQrQ,+EACR2sC,GAAW3sC,2EAIV,SAASiyC,GAAmBnwC,EAA0B,CAC3D,OAAO9B;AAAAA,MACHkyC,GAAoBpwC,CAAK,CAAC;AAAA,MAC1BqwC,GAAwBrwC,CAAK,CAAC;AAAA,MAC9BswC,GAAqBtwC,CAAK,CAAC;AAAA,MAC3BuwC,GAAkBvwC,CAAK,CAAC;AAAA,MACxBwwC,GAAiBxwC,CAAK,CAAC;AAAA,GAE7B,CAIA,SAASowC,GAAoBpwC,EAA0B,CACrD,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,mBAIU8B,EAAM,KAAK,OAAO;AAAA,kBAClBtxB,GACTsxB,EAAM,aAAa,CAAE,QAAUtxB,EAAE,OAA4B,QAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAUjF,CAIA,SAAS2hE,GAAwBrwC,EAA0B,CACzD,MAAMywC,EAAezwC,EAAM,KAAK,QAChC,OAAO9B;AAAAA;AAAAA;AAAAA,iCAGwBuyC,EAAe,GAAK,qCAAqC;AAAA;AAAA;AAAA;AAAA,mBAIvEzwC,EAAM,KAAK,kBAAkB;AAAA,oBAC5B,CAACywC,CAAY;AAAA,kBACd/hE,GACTsxB,EAAM,aAAa,CAAE,mBAAqBtxB,EAAE,OAA4B,QAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,YAKhF+hE,EACE,gIACA,6BAA6B;AAAA;AAAA;AAAA;AAAA,GAK3C,CAIA,SAASH,GAAqBtwC,EAA0B,CACtD,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,UAICgyC,GAAW,IAAKQ,GAAQC,GAAaD,EAAK1wC,CAAK,CAAC,CAAC;AAAA;AAAA;AAAA,GAI3D,CAEA,SAAS2wC,GAAaD,EAAqC1wC,EAA0B,CACnF,MAAM4wC,EAAW5wC,EAAM,KAAK,KAAK0wC,EAAI,GAAG,EACxC,GAAI,CAACE,EAAU,OAAO3xC,EACtB,MAAM4xC,EAAWD,EAAS,OAE1B,OAAO1yC;AAAAA;AAAAA,kCAEyBwyC,EAAI,KAAK;AAAA,yCACFG,EAAW,uCAAyC,EAAE;AAAA;AAAA;AAAA,mBAG5ED,EAAS,KAAK;AAAA,mBACbliE,GACRsxB,EAAM,YAAY0wC,EAAI,IAAK,QAAUhiE,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,mBAKlEkiE,EAAS,GAAG;AAAA,mBACXliE,GACRsxB,EAAM,YAAY0wC,EAAI,IAAK,MAAQhiE,EAAE,OAA4B,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAM9DmiE,CAAQ;AAAA,oBACRniE,GACTsxB,EAAM,YAAY0wC,EAAI,IAAK,SAAWhiE,EAAE,OAA4B,OAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,GAMxF,CAIA,IAAIoiE,GAAiB,GAErB,SAASP,GAAkBvwC,EAA0B,CACnD,MAAM6vC,EAAQ7vC,EAAM,KAAK,YAEzB,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,UAIC2xC,EAAM,SAAW,EACf3xC,wEACA2xC,EAAM,IACHlB,GAASzwC;AAAAA;AAAAA,oBAEJywC,CAAI;AAAA;AAAA;AAAA;AAAA,6BAIK,IAAM3uC,EAAM,mBAAmB2uC,CAAI,CAAC;AAAA;AAAA,sBAE3CpgC,EAAK;AAAA;AAAA;AAAA,gBAId;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAOQ7/B,GAAa,CAAEoiE,GAAkBpiE,EAAE,OAA4B,KAAO,CAAC;AAAA;AAAA;AAAA;AAAA,mBAIzE,IAAM,CACb,GAAIoiE,GAAgB,CAClB9wC,EAAM,gBAAgB8wC,EAAc,EACpC,MAAMruC,EAAK,SAAS,eAAe,oBAAoB,EACnDA,MAAO,MAAQ,IACnBquC,GAAiB,EACnB,CACF,CAAC;AAAA;AAAA,YAECjG,EAAQ;AAAA;AAAA;AAAA;AAAA,GAKpB,CAIA,SAAS2F,GAAiBxwC,EAA0B,CAClD,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA,oBAIW8B,EAAM,IAAI;AAAA,iBACbA,EAAM,MAAM;AAAA;AAAA,UAEnBA,EAAM,KAAO,UAAiB,MAAM;AAAA;AAAA;AAAA,GAI9C,CC1LA,MAAM+wC,GAA6C,CACjD,CAAE,GAAI,OAAQ,MAAO,UACrB,CAAE,GAAI,SAAU,MAAO,UACvB,CAAE,GAAI,gBAAiB,MAAO,iBAC9B,CAAE,GAAI,OAAQ,MAAO,OACvB,EAEA,SAASC,GAAiBhxC,EAA0B,CAClD,OAAQA,EAAM,WACZ,IAAK,OACH,OAAO+qC,GAAW/qC,EAAM,SAAS,EACnC,IAAK,SACH,OAAOqsC,GAAarsC,EAAM,WAAW,EACvC,IAAK,gBACH,OAAOmwC,GAAmBnwC,EAAM,iBAAiB,EACnD,IAAK,OACH,OAAOsvC,GAAWtvC,EAAM,SAAS,EACnC,QACE,OAAO+qC,GAAW/qC,EAAM,SAAS,EAEvC,CAEO,SAASixC,GAAmBjxC,EAA0B,CAC3D,OAAKA,EAAM,UAWJ9B;AAAAA;AAAAA,QAEDO,GAAc,WAAYuB,EAAM,OAAO,CAAC;AAAA;AAAA;AAAA,YAGpC+wC,GAAK,IACJ78C,GAAQgK;AAAAA;AAAAA,gCAEW8B,EAAM,YAAc9L,EAAI,GAAK,SAAW,EAAE;AAAA,yBACjD,IAAM8L,EAAM,YAAY9L,EAAI,EAAE,CAAC;AAAA;AAAA,kBAEtCA,EAAI,KAAK;AAAA;AAAA,cAGhB;AAAA;AAAA,UAED88C,GAAiBhxC,CAAK,CAAC;AAAA;AAAA;AAAA,IA1BtB9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,KA8BX,CCzCO,SAASgzC,GAAmB11D,EAA0B,CAC3D,GAAI,CAACA,EAAM,KAAM,OAAOyjB,EAExB,MAAMkyC,EAAQz+D,GAAA,EACR0+D,EAAc51D,EAAM,YACpB61D,EAAe71D,EAAM,gBAAkB,IAAQ,CAAC41D,EAChDE,EAAa91D,EAAM,gBAAkB,GAE3C,IAAI+1D,EAAkB/1D,EAAM,SAAS,OAAS,EAAIA,EAAM,SAAS,CAAC,EAAE,GAAK,GAEzE,MAAMg2D,EAAuB9iE,GAAa,OACxC6iE,EAAmB7iE,EAAE,OAA6B,MAElD,MAAMkwB,GAAQhvB,EAAAlB,EAAE,OAAuB,QAAQ,aAAa,IAA9C,YAAAkB,EAAiD,cAAc,qBACzEgvB,IAAOA,EAAqB,MAAM,QAAU2yC,IAAoB,aAAe,GAAK,OAC1F,EAEM9kC,EAAmBC,GAAiCh+B,GAAa,CACrE,MAAMuD,EAAQvD,EAAE,OAChBuD,EAAM,MAAQA,EAAM,MAAM,QAAQ,MAAO,EAAE,EAAE,MAAM,EAAG,CAAC,EACvDy6B,EAAOz6B,EAAM,KAAK,CACpB,EAEM+6B,EAAuBt+B,GAAa,CACxC,MAAM8zB,EAAO9zB,EAAE,cACTu+B,EAAUzK,EAAI,QAAQ,oBAAoB,EAC1CvwB,EAAQg7B,GAAA,YAAAA,EAAS,cAAc,SACrC,GAAI,CAACh7B,EAAO,OACZ,MAAMk1B,EAAUl1B,EAAM,OAAS,OAC/BA,EAAM,KAAOk1B,EAAU,WAAa,OACpC3E,EAAI,UAAU,OAAO,SAAU,CAAC2E,CAAO,CACzC,EAGMsqC,EAAkB,CAACL,GAAe51D,EAAM,SAAS,OAAS,EAC5D0iB;AAAAA;AAAAA;AAAAA,oBAGcszC,CAAmB;AAAA,sBACjBh2D,EAAM,MAAQ81D,CAAU;AAAA;AAAA,YAElC91D,EAAM,SAAS,IACf,CAACk2D,EAAK1iE,IAAMkvB;AAAAA,8BACMwzC,EAAI,EAAE,cAAc1iE,IAAM,CAAC;AAAA,kBACvC0iE,EAAI,WAAW;AAAA;AAAA,cAGtB;AAAA;AAAA,QAGLzyC,EAGJ,GAAIoyC,EAAc,CAChB,IAAI/kC,EAAS,GACTC,EAAS,GACTC,EAAa,GAEjB,MAAMmlC,EAAyBjjE,GAAa,OAC1CA,EAAE,iBACE,CAAA4iE,IACA,CAAChlC,GAAU,CAACC,GAAU,CAACC,GACvBD,IAAWC,GACV+kC,KACL3hE,EAAA4L,EAAM,cAAN,MAAA5L,EAAA,KAAA4L,EAAoB+1D,EAAiBjlC,EAAQC,IAC/C,EAEA,OAAOrO;AAAAA;AAAAA;AAAAA,yCAG8BizC,EAAM,OAAO,UAAUA,EAAM,IAAI;AAAA;AAAA;AAAA,6CAG7BQ,CAAqB;AAAA,cACpDF,CAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAUDH,CAAU;AAAA,yBACb7kC,EAAiB18B,GAAM,CAAEu8B,EAASv8B,CAAG,CAAC,CAAC;AAAA;AAAA;AAAA,sEAGMi9B,CAAmB;AAAA,6CAC5C/O,EAAM,GAAG;AAAA,6CACTA,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAY7BqzC,CAAU;AAAA,yBACb7kC,EAAiB18B,GAAM,CAAEw8B,EAASx8B,CAAG,CAAC,CAAC;AAAA;AAAA,sEAEMi9B,CAAmB;AAAA,6CAC5C/O,EAAM,GAAG;AAAA,6CACTA,EAAM,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAY7BqzC,CAAU;AAAA,yBACb7kC,EAAiB18B,GAAM,CAAEy8B,EAAaz8B,CAAG,CAAC,CAAC;AAAA;AAAA,sEAEEi9B,CAAmB;AAAA,6CAC5C/O,EAAM,GAAG;AAAA,6CACTA,EAAM,MAAM;AAAA;AAAA;AAAA,cAG3CziB,EAAM,eACJ0iB,2BAA8B1iB,EAAM,cAAc,OAClDyjB,CAAO;AAAA,cACTzjB,EAAM,iBACJ0iB,6BAAgC1iB,EAAM,gBAAgB,OACtDyjB,CAAO;AAAA;AAAA;AAAA;AAAA,0BAIGqyC,CAAU;AAAA,eACrBA,EAAapzC,uCAA4C,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAM5DxvB,GAAa,OAAEA,EAAE,kBAAkBkB,EAAA4L,EAAM,wBAAN,MAAA5L,EAAA,KAAA4L,EAAiC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,KAM3F,CAGA,IAAIo2D,EAAW,GACXC,EAAe,GAEnB,MAAMjlC,EAAgBl+B,GAAa,CAEjC,GADAA,EAAE,iBACE,CAAA8M,EAAM,KACV,GAAI41D,EAAa,CAEf,GADI,CAACQ,GAAY,CAACC,GACdD,IAAaC,EAAc,OAC/Br2D,EAAM,SAASo2D,CAAQ,CACzB,KAAO,CACL,GAAI,CAACA,GAAY,CAACL,EAAiB,OACnC/1D,EAAM,SAAS+1D,EAAiBK,CAAQ,CAC1C,CACF,EAEA,OAAO1zC;AAAAA;AAAAA;AAAAA,uCAG8BizC,EAAM,OAAO,UAAUA,EAAM,IAAI;AAAA,kCACtCA,EAAM,IAAI;AAAA;AAAA,YAEhCC,EACE,mCACA,4BAA4B;AAAA;AAAA,2CAECxkC,CAAY;AAAA,YAC3C6kC,CAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BASEL,EAAc,yBAA2B,KAAK;AAAA,0BACjD51D,EAAM,IAAI;AAAA,uBACbixB,EAAiB,GAAM,CAAEmlC,EAAW,CAAG,CAAC,CAAC;AAAA;AAAA;AAAA,oEAGI5kC,CAAmB;AAAA,2CAC5C/O,EAAM,GAAG;AAAA,2CACTA,EAAM,MAAM;AAAA;AAAA;AAAA,YAG3CmzC,EACElzC;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,gCAUkB1iB,EAAM,IAAI;AAAA,6BACbixB,EAAiB,GAAM,CAAEolC,EAAe,CAAG,CAAC,CAAC;AAAA;AAAA,0EAEA7kC,CAAmB;AAAA,iDAC5C/O,EAAM,GAAG;AAAA,iDACTA,EAAM,MAAM;AAAA;AAAA;AAAA,gBAI/CgB,CAAO;AAAA,YACTzjB,EAAM,MACJ0iB,2BAA8B1iB,EAAM,KAAK,OACzCyjB,CAAO;AAAA;AAAA;AAAA;AAAA,wBAIGzjB,EAAM,IAAI;AAAA;AAAA,cAEpBA,EAAM,KACJ0iB,uCACAkzC,EACE,UACA,QAAQ;AAAA;AAAA;AAAA,UAGhBA,EACElzC,8HACA1iB,EAAM,SAAS,KAAMpM,GAAMA,EAAE,KAAO,YAAY,EAC9C8uB,mEAAsEqzC,IAAoB,aAAe,kBAAoB,EAAE;AAAA;AAAA;AAAA;AAAA,2BAIjH7iE,GAAa,OAAEA,EAAE,kBAAkBkB,EAAA4L,EAAM,wBAAN,MAAA5L,EAAA,KAAA4L,EAAiC,CAAC;AAAA;AAAA,oBAGnFyjB,CAAO;AAAA;AAAA;AAAA,GAIrB,CCrRO,SAAS6yC,GAAqB9xC,EAA4B,CAC/D,GAAI,CAACA,EAAM,UACT,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAWT,MAAM6zC,EAAuB,CAC3B,GAAG/xC,EACH,SAAU,KACV,UAAW,GACX,aAAc,GACd,cAAe,KACf,WAAY,GACZ,kBAAmB,IAAM,CAAC,EAC1B,mBAAoB,IAAM,CAAC,EAC3B,aAAc,IAAM,CAAC,GAGjB9tB,EAAO8tB,EAAM,eAAiB,YAEpC,OAAO9B;AAAAA;AAAAA;AAAAA,iDAGwChsB,CAAI;AAAA;AAAA;AAAA,UAG3C4zD,GAAWiM,CAAS,CAAC;AAAA;AAAA;AAAA,GAI/B,CCnCA,eAAsBC,GAAWx2D,EAAoB,CACnD,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,cACV,CAAAA,EAAM,cAAgB,GACtBA,EAAM,YAAc,KACpB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,cAAe,EAAE,EACrDG,MAAW,WAAaA,EAC9B,OAASI,EAAK,CACZP,EAAM,YAAc,OAAOO,CAAG,CAChC,SACEP,EAAM,cAAgB,EACxB,EACF,CCGA,eAAsBy2D,GAAez2D,EAAuC,CAC1E,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,kBACV,CAAAA,EAAM,kBAAoB,GAC1BA,EAAM,gBAAkB,KACxB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,kBAAmB,EAAE,EAG7DA,EAAM,WAAaG,EAAI,UACzB,OAASI,EAAK,CACZP,EAAM,gBAAkB,OAAOO,CAAG,CACpC,SACEP,EAAM,kBAAoB,EAC5B,EACF,CAEA,eAAsB02D,GACpB12D,EACAiC,EAKe,SAEf,GADI,CAACjC,EAAM,QAAU,CAACA,EAAM,WACxBA,EAAM,gBAAiB,OAE3B,MAAMtJ,EAAOuL,EAAO,KAAK,OACzB,GAAI,CAACvL,EAAM,CACTsJ,EAAM,gBAAkB,4BACxB,MACF,CAEAA,EAAM,gBAAkB,GACxBA,EAAM,gBAAkB,KACxB,GAAI,CAEF,MAAM8I,EAAa,MAAM9I,EAAM,OAAO,QAAQ,aAAc,EAAE,EAC9DA,EAAM,eAAiB8I,EACvB,MAAMlC,EAAWkC,EAAU,KAC3B,GAAI,CAAClC,EAAU,CACb5G,EAAM,gBAAkB,yCACxB,MACF,CAEA,MAAM8b,EAAqC,CACzC,KAAAplB,EACA,SAAAkQ,EACA,oBAAqBlQ,CAAA,GAEnBtC,EAAA6N,EAAO,gBAAP,MAAA7N,EAAsB,SACxB0nB,EAAU,aAAe7Z,EAAO,cAAc,QAGhD,MAAM9B,EAAO,MAAMH,EAAM,OAAO,QAAQ,oBAAqB8b,CAAS,EAKtE9b,EAAM,gBAAkB,GACxBA,EAAM,iBAAmB,GACzBA,EAAM,iBAAmB,GAGzB,MAAMy2D,GAAez2D,CAAK,GAG1B3L,EAAA4N,EAAO,YAAP,MAAA5N,EAAA,KAAA4N,EAAmB9B,EACrB,OAASI,EAAK,CACZP,EAAM,gBAAkB,OAAOO,CAAG,CACpC,SACEP,EAAM,gBAAkB,EAC1B,CACF,CAEA,eAAsB22D,GACpB32D,EACAtJ,EACe,CACf,GAAI,GAACsJ,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,gBAEV,CAAAA,EAAM,gBAAkB,GACxBA,EAAM,gBAAkB,KACxB,GAAI,CAEF,MAAM8I,EAAa,MAAM9I,EAAM,OAAO,QAAQ,aAAc,EAAE,EAC9DA,EAAM,eAAiB8I,EACvB,MAAMlC,EAAWkC,EAAU,KAC3B,GAAI,CAAClC,EAAU,CACb5G,EAAM,gBAAkB,yCACxB,MACF,CAEA,MAAMA,EAAM,OAAO,QAAQ,oBAAqB,CAAE,KAAAtJ,EAAM,SAAAkQ,EAAU,EAElE5G,EAAM,uBAAyB,KAG/B,MAAMy2D,GAAez2D,CAAK,CAC5B,OAASO,EAAK,CACZP,EAAM,gBAAkB,OAAOO,CAAG,CACpC,SACEP,EAAM,gBAAkB,EAC1B,EACF,CAEA,eAAsB42D,GACpB52D,EACAtJ,EACAmgE,EACe,CACf,GAAI,GAAC72D,EAAM,QAAU,CAACA,EAAM,WAE5B,CAAAA,EAAM,gBAAkB,KACxB,GAAI,CACF,MAAM8I,EAAa,MAAM9I,EAAM,OAAO,QAAQ,aAAc,EAAE,EAC9DA,EAAM,eAAiB8I,EACvB,MAAMlC,EAAWkC,EAAU,KAC3B,GAAI,CAAClC,EAAU,CACb5G,EAAM,gBAAkB,yCACxB,MACF,CAEA,MAAMA,EAAM,OAAO,QAAQ,oBAAqB,CAAE,KAAAtJ,EAAM,YAAAmgE,EAAa,SAAAjwD,EAAU,EAG/E,MAAM6vD,GAAez2D,CAAK,CAC5B,OAASO,EAAK,CACZP,EAAM,gBAAkB,OAAOO,CAAG,CACpC,EACF,gLC/Jau2D,GAAqB,CAChC,WAAY,aACZ,WAAY,wBACZ,SAAU,WACV,QAAS,UACT,IAAK,MACL,eAAgB,iBAChB,UAAW,mBACX,QAAS,iBACT,YAAa,qBACb,UAAW,YACX,KAAM,OACN,YAAa,cACb,MAAO,mBACP,YAAa,aACf,EAKaC,GAAuBD,GAGvBE,GAAuB,CAClC,QAAS,UACT,IAAK,MACL,GAAI,KACJ,QAAS,UACT,KAAM,OACN,MAAO,QACP,KAAM,MACR,EAe8B,IAAI,IAAqB,OAAO,OAAOF,EAAkB,CAAC,EACxD,IAAI,IAAuB,OAAO,OAAOE,EAAoB,CAAC,ECnCvF,SAASC,GAAuBh1D,EAAyC,CAC9E,MAAM2wC,EAAU3wC,EAAO,UAAYA,EAAO,MAAQ,KAAO,MACnD2U,EAAS3U,EAAO,OAAO,KAAK,GAAG,EAC/B8H,EAAQ9H,EAAO,OAAS,GACxBpK,EAAO,CACX+6C,EACA3wC,EAAO,SACPA,EAAO,SACPA,EAAO,WACPA,EAAO,KACP2U,EACA,OAAO3U,EAAO,UAAU,EACxB8H,CAAA,EAEF,OAAI6oC,IAAY,MACd/6C,EAAK,KAAKoK,EAAO,OAAS,EAAE,EAEvBpK,EAAK,KAAK,GAAG,CACtB,CCqCA,MAAMq/D,GAA4B,KAE3B,MAAMC,EAAqB,CAUhC,YAAoBl3D,EAAmC,CAAnC,UAAAA,EATpB,KAAQ,GAAuB,KAC/B,KAAQ,YAAc,IACtB,KAAQ,OAAS,GACjB,KAAQ,QAAyB,KACjC,KAAQ,aAA8B,KACtC,KAAQ,YAAc,GACtB,KAAQ,aAA8B,KACtC,KAAQ,UAAY,GAEoC,CAExD,OAAQ,CACN,KAAK,OAAS,GACd,KAAK,SACP,CAEA,MAAO,OACL,KAAK,OAAS,IACd7L,EAAA,KAAK,KAAL,MAAAA,EAAS,QACT,KAAK,GAAK,KACV,KAAK,aAAa,IAAI,MAAM,wBAAwB,CAAC,CACvD,CAEA,IAAI,WAAY,OACd,QAAOA,EAAA,KAAK,KAAL,YAAAA,EAAS,cAAe,UAAU,IAC3C,CAEQ,SAAU,CACZ,KAAK,SACT,KAAK,GAAK,IAAI,UAAU,KAAK,KAAK,GAAG,EACrC,KAAK,GAAG,OAAS,IAAM,KAAK,eAC5B,KAAK,GAAG,UAAa61D,GAAO,KAAK,cAAc,OAAOA,EAAG,MAAQ,EAAE,CAAC,EACpE,KAAK,GAAG,QAAWA,GAAO,SACxB,MAAMmN,EAAS,OAAOnN,EAAG,QAAU,EAAE,EACrC,KAAK,GAAK,KACV,KAAK,aAAa,IAAI,MAAM,mBAAmBA,EAAG,IAAI,MAAMmN,CAAM,EAAE,CAAC,GACrE/iE,GAAAD,EAAA,KAAK,MAAK,UAAV,MAAAC,EAAA,KAAAD,EAAoB,CAAE,KAAM61D,EAAG,KAAM,OAAAmN,IACrC,KAAK,mBACP,EACA,KAAK,GAAG,QAAU,IAAM,CAExB,EACF,CAEQ,mBAAoB,CAC1B,GAAI,KAAK,OAAQ,OACjB,MAAMC,EAAQ,KAAK,UACnB,KAAK,UAAY,KAAK,IAAI,KAAK,UAAY,IAAK,IAAM,EACtD,OAAO,WAAW,IAAM,KAAK,UAAWA,CAAK,CAC/C,CAEQ,aAAa92D,EAAY,CAC/B,SAAW,EAAGzM,CAAC,IAAK,KAAK,QAASA,EAAE,OAAOyM,CAAG,EAC9C,KAAK,QAAQ,OACf,CAEA,MAAc,aAAc,OAC1B,GAAI,KAAK,YAAa,OACtB,KAAK,YAAc,GACf,KAAK,eAAiB,OACxB,OAAO,aAAa,KAAK,YAAY,EACrC,KAAK,aAAe,MAGtB,MAAMhD,EAAO,KAAK,KAAK,MAAQ,WACzBqZ,EAAS,KAAK,KAAK,QAAU,CAAC,iBAAkB,qBAAsB,kBAAkB,EAMxF0gD,EAAkB,EALG/5D,IAAS,aAKW,OAAO,OAAW,KAAe,CAAC,CAAC,OAAO,OAEzF,IAAIg6D,EAAgF,KAChFC,EAAsB,GACtBC,EAAY,KAAK,KAAK,MAE1B,GAAIH,EAAiB,CACnBC,EAAiB,MAAMrhD,GAAA,EACvB,MAAMwhD,GAActjE,EAAA6iB,GAAoB,CACtC,SAAUsgD,EAAe,SACzB,KAAAh6D,CAAA,CACD,IAHmB,YAAAnJ,EAGhB,MACJqjE,EAAYC,GAAe,KAAK,KAAK,MACrCF,EAAsB,GAAQE,GAAe,KAAK,KAAK,MACzD,CACA,MAAMC,EACJF,GAAa,KAAK,KAAK,SACnB,CACE,MAAOA,EACP,SAAU,KAAK,KAAK,UAEtB,OAEN,IAAIG,EAUJ,GAAIN,GAAmBC,EAAgB,CACrC,MAAMM,EAAa,KAAK,MAClBC,EAAQ,KAAK,cAAgB,OAC7Bl2D,EAAUq1D,GAAuB,CACrC,SAAUM,EAAe,SACzB,SAAU,KAAK,KAAK,YAAcR,GAAqB,WACvD,WAAY,KAAK,KAAK,MAAQC,GAAqB,QACnD,KAAAz5D,EACA,OAAAqZ,EACA,WAAAihD,EACA,MAAOJ,GAAa,KACpB,MAAAK,CAAA,CACD,EACKC,EAAY,MAAMxhD,GAAkBghD,EAAe,WAAY31D,CAAO,EAC5Eg2D,EAAS,CACP,GAAIL,EAAe,SACnB,UAAWA,EAAe,UAC1B,UAAAQ,EACA,SAAUF,EACV,MAAAC,CAAA,CAEJ,CACA,MAAM71D,EAAS,CACb,YAAa,EACb,YAAa,EACb,OAAQ,CACN,GAAI,KAAK,KAAK,YAAc80D,GAAqB,WACjD,QAAS,KAAK,KAAK,eAAiB,MACpC,SAAU,KAAK,KAAK,UAAY,UAAU,UAAY,MACtD,KAAM,KAAK,KAAK,MAAQC,GAAqB,QAC7C,WAAY,KAAK,KAAK,YAExB,KAAAz5D,EACA,OAAAqZ,EACA,OAAAghD,EACA,KAAM,GACN,KAAAD,EACA,UAAW,UAAU,UACrB,OAAQ,UAAU,UAGf,KAAK,QAAwB,UAAW11D,CAAM,EAChD,KAAM+1D,GAAU,YACX5jE,EAAA4jE,GAAA,YAAAA,EAAO,OAAP,MAAA5jE,EAAa,aAAemjE,GAC9BrgD,GAAqB,CACnB,SAAUqgD,EAAe,SACzB,KAAMS,EAAM,KAAK,MAAQz6D,EACzB,MAAOy6D,EAAM,KAAK,YAClB,OAAQA,EAAM,KAAK,QAAU,EAAC,CAC/B,EAEH,KAAK,UAAY,KACjB31C,GAAAhuB,EAAA,KAAK,MAAK,UAAV,MAAAguB,EAAA,KAAAhuB,EAAoB2jE,EACtB,CAAC,EACA,MAAM,IAAM,OACPR,GAAuBD,GACzBngD,GAAqB,CAAE,SAAUmgD,EAAe,SAAU,KAAAh6D,EAAM,GAElEnJ,EAAA,KAAK,KAAL,MAAAA,EAAS,MAAM8iE,GAA2B,iBAC5C,CAAC,CACL,CAEQ,cAAc59D,EAAa,iBACjC,IAAIkI,EACJ,GAAI,CACFA,EAAS,KAAK,MAAMlI,CAAG,CACzB,MAAQ,CACN,MACF,CAEA,MAAMqyC,EAAQnqC,EACd,GAAImqC,EAAM,OAAS,QAAS,CAC1B,MAAMssB,EAAMz2D,EACZ,GAAIy2D,EAAI,QAAU,oBAAqB,CACrC,MAAMr2D,EAAUq2D,EAAI,QACdH,EAAQl2D,GAAW,OAAOA,EAAQ,OAAU,SAAWA,EAAQ,MAAQ,KACzEk2D,IACF,KAAK,aAAeA,EACf,KAAK,eAEZ,MACF,CACA,MAAMI,EAAM,OAAOD,EAAI,KAAQ,SAAWA,EAAI,IAAM,KAChDC,IAAQ,OACN,KAAK,UAAY,MAAQA,EAAM,KAAK,QAAU,KAChD7jE,GAAAD,EAAA,KAAK,MAAK,QAAV,MAAAC,EAAA,KAAAD,EAAkB,CAAE,SAAU,KAAK,QAAU,EAAG,SAAU8jE,KAE5D,KAAK,QAAUA,GAEjB,GAAI,EACFzsD,GAAA4W,EAAA,KAAK,MAAK,UAAV,MAAA5W,EAAA,KAAA4W,EAAoB41C,EACtB,OAAS13D,EAAK,CACZ,QAAQ,MAAM,iCAAkCA,CAAG,CACrD,CACA,MACF,CAEA,GAAIorC,EAAM,OAAS,MAAO,CACxB,MAAMxrC,EAAMqB,EACN22D,EAAU,KAAK,QAAQ,IAAIh4D,EAAI,EAAE,EACvC,GAAI,CAACg4D,EAAS,OAEd,GADA,KAAK,QAAQ,OAAOh4D,EAAI,EAAE,EACtBA,EAAI,GAAIg4D,EAAQ,QAAQh4D,EAAI,OAAO,MAClC,CACH,MAAMI,EAAM,IAAI,QAAM4hC,EAAAhiC,EAAI,QAAJ,YAAAgiC,EAAW,UAAW,gBAAgB,EAI5D5hC,EAAI,QAAUJ,EAAI,QAClBI,EAAI,SAAU63D,EAAAj4D,EAAI,QAAJ,YAAAi4D,EAAW,QACzBD,EAAQ,OAAO53D,CAAG,CACpB,CACA,MACF,CACF,CAEA,QAAqByyC,EAAgB/wC,EAA8B,CACjE,GAAI,CAAC,KAAK,IAAM,KAAK,GAAG,aAAe,UAAU,KAC/C,OAAO,QAAQ,OAAO,IAAI,MAAM,uBAAuB,CAAC,EAE1D,MAAM7C,EAAKQ,GAAA,EACL+rC,EAAQ,CAAE,KAAM,MAAO,GAAAvsC,EAAI,OAAA4zC,EAAQ,OAAA/wC,CAAA,EACnCnO,EAAI,IAAI,QAAW,CAACi9C,EAASC,IAAW,CAC5C,KAAK,QAAQ,IAAI5xC,EAAI,CAAE,QAAU7K,GAAMw8C,EAAQx8C,CAAM,EAAG,OAAAy8C,CAAA,CAAQ,CAClE,CAAC,EACD,YAAK,GAAG,KAAK,KAAK,UAAUrF,CAAK,CAAC,EAC3B73C,CACT,CAEQ,cAAe,CACrB,KAAK,aAAe,KACpB,KAAK,YAAc,GACf,KAAK,eAAiB,MAAM,OAAO,aAAa,KAAK,YAAY,EACrE,KAAK,aAAe,OAAO,WAAW,IAAM,CACrC,KAAK,aACZ,EAAG,GAAG,CACR,CACF,CC9RA,SAASukE,GAAShiE,EAAkD,CAClE,OAAO,OAAOA,GAAU,UAAYA,IAAU,IAChD,CAEO,SAASiiE,GAA2B12D,EAA8C,CACvF,GAAI,CAACy2D,GAASz2D,CAAO,EAAG,OAAO,KAC/B,MAAMxC,EAAK,OAAOwC,EAAQ,IAAO,SAAWA,EAAQ,GAAG,OAAS,GAC1D22D,EAAU32D,EAAQ,QACxB,GAAI,CAACxC,GAAM,CAACi5D,GAASE,CAAO,EAAG,OAAO,KACtC,MAAMC,EAAU,OAAOD,EAAQ,SAAY,SAAWA,EAAQ,QAAQ,OAAS,GAC/E,GAAI,CAACC,EAAS,OAAO,KACrB,MAAMC,EAAc,OAAO72D,EAAQ,aAAgB,SAAWA,EAAQ,YAAc,EAC9E82D,EAAc,OAAO92D,EAAQ,aAAgB,SAAWA,EAAQ,YAAc,EACpF,MAAI,CAAC62D,GAAe,CAACC,EAAoB,KAClC,CACL,GAAAt5D,EACA,QAAS,CACP,QAAAo5D,EACA,IAAK,OAAOD,EAAQ,KAAQ,SAAWA,EAAQ,IAAM,KACrD,KAAM,OAAOA,EAAQ,MAAS,SAAWA,EAAQ,KAAO,KACxD,SAAU,OAAOA,EAAQ,UAAa,SAAWA,EAAQ,SAAW,KACpE,IAAK,OAAOA,EAAQ,KAAQ,SAAWA,EAAQ,IAAM,KACrD,QAAS,OAAOA,EAAQ,SAAY,SAAWA,EAAQ,QAAU,KACjE,aAAc,OAAOA,EAAQ,cAAiB,SAAWA,EAAQ,aAAe,KAChF,WAAY,OAAOA,EAAQ,YAAe,SAAWA,EAAQ,WAAa,MAE5E,YAAAE,EACA,YAAAC,CAAA,CAEJ,CAEO,SAASC,GAA0B/2D,EAA+C,CACvF,GAAI,CAACy2D,GAASz2D,CAAO,EAAG,OAAO,KAC/B,MAAMxC,EAAK,OAAOwC,EAAQ,IAAO,SAAWA,EAAQ,GAAG,OAAS,GAChE,OAAKxC,EACE,CACL,GAAAA,EACA,SAAU,OAAOwC,EAAQ,UAAa,SAAWA,EAAQ,SAAW,KACpE,WAAY,OAAOA,EAAQ,YAAe,SAAWA,EAAQ,WAAa,KAC1E,GAAI,OAAOA,EAAQ,IAAO,SAAWA,EAAQ,GAAK,MALpC,IAOlB,CAEO,SAASg3D,GAAuBtiB,EAAqD,CAC1F,MAAM32C,EAAM,KAAK,MACjB,OAAO22C,EAAM,OAAQ9zC,GAAUA,EAAM,YAAc7C,CAAG,CACxD,CAEO,SAASk5D,GACdviB,EACA9zC,EACuB,CACvB,MAAM3I,EAAO++D,GAAuBtiB,CAAK,EAAE,OAAQ74C,GAASA,EAAK,KAAO+E,EAAM,EAAE,EAChF,OAAA3I,EAAK,KAAK2I,CAAK,EACR3I,CACT,CAEO,SAASi/D,GAAmBxiB,EAA8Bl3C,EAAmC,CAClG,OAAOw5D,GAAuBtiB,CAAK,EAAE,OAAQ9zC,GAAUA,EAAM,KAAOpD,CAAE,CACxE,CChFO,MAAM25D,EAAsB,CAA5B,cACL,KAAQ,OAAmC,KAC3C,KAAQ,IAAuC,KAC/C,KAAQ,IAAM,IAAI,MAClB,KAAQ,aAA8B,KACtC,KAAQ,MAAuB,KAC/B,KAAQ,YAAc,KACtB,KAAQ,aAAe,IACvB,KAAQ,gBAAkB,EAC1B,KAAiB,kBAAoB,GAErC,OAAOjf,EAAiC,CACtC,KAAK,OAASA,EACd,KAAK,IAAMA,EAAO,WAAW,IAAI,CACnC,CAEA,QAAe,CACT,KAAK,OAAS,OAChB,qBAAqB,KAAK,KAAK,EAC/B,KAAK,MAAQ,MAEf,KAAK,OAAS,KACd,KAAK,IAAM,KACX,KAAK,aAAe,IACtB,CAEA,YACEkf,EACAC,EACM,CASN,GARIA,GAAA,MAAAA,EAAU,cAAa,KAAK,YAAcA,EAAS,aACnDA,GAAA,MAAAA,EAAU,eAAc,KAAK,aAAeA,EAAS,cAEzD,KAAK,aAAeD,EAKhB,CAAC,KAAK,OAAQ,CAChB,MAAM/xC,EAAK,SAAS,eAAe,2BAA2B,EAC1DA,GAAI,KAAK,OAAOA,CAAE,CACxB,CAEI,KAAK,OAAS,OAChB,KAAK,MAAQ,sBAAsB,IAAM,KAAK,aAAa,EAE/D,CAEQ,aAAoB,CAC1B,KAAK,MAAQ,KACb,MAAMxjB,EAAO,KAAK,aACd,CAACA,GAAQ,CAAC,KAAK,QAAU,CAAC,KAAK,MACnC,KAAK,aAAe,KAEpB,KAAK,IAAI,OAAS,IAAM,CAClB,CAAC,KAAK,QAAU,CAAC,KAAK,OAGxB,KAAK,OAAO,QAAU,KAAK,IAAI,OAC/B,KAAK,OAAO,SAAW,KAAK,IAAI,UAEhC,KAAK,OAAO,MAAQ,KAAK,IAAI,MAC7B,KAAK,OAAO,OAAS,KAAK,IAAI,QAEhC,KAAK,IAAI,UAAU,KAAK,IAAK,EAAG,CAAC,EACnC,EACA,KAAK,IAAI,IAAM,0BAA0BA,CAAI,GAC/C,CAKA,qBACEy1D,EACAC,EAC0B,CAC1B,GAAI,CAAC,KAAK,OAAQ,MAAO,CAAE,EAAGD,EAAS,EAAGC,CAAA,EAE1C,MAAMz9C,EAAO,KAAK,OAAO,wBAEnB09C,EAAS,KAAK,OAAO,MAAQ19C,EAAK,MAClC29C,EAAS,KAAK,OAAO,OAAS39C,EAAK,OAGnC49C,EAAiB,KAAK,YAAc,KAAK,OAAO,MAChDC,EAAiB,KAAK,aAAe,KAAK,OAAO,OAEvD,MAAO,CACL,EAAG,KAAK,MAAML,EAAUE,EAASE,CAAc,EAC/C,EAAG,KAAK,MAAMH,EAAUE,EAASE,CAAc,EAEnD,CAKA,yBAAmC,CACjC,MAAM55D,EAAM,YAAY,MACxB,OAAIA,EAAM,KAAK,gBAAkB,KAAK,kBAC7B,IAET,KAAK,gBAAkBA,EAChB,GACT,CAEA,qBAAyD,CACvD,MAAO,CAAE,MAAO,KAAK,YAAa,OAAQ,KAAK,aACjD,CACF,CC9FA,IAAI65D,GAA+C,KAE5C,SAASC,IAA2C,CACzD,OAAKD,KACHA,GAAiB,IAAIT,IAEhBS,EACT,CAEA,SAAS3hD,GAAgBtX,EAAsB,CAC7C,OAAIA,aAAe,MAAcA,EAAI,QAC9B,OAAOA,CAAG,CACnB,CAEA,eAAsBm5D,GAAgB15D,EAA2B,CAC/D,GAAI,CAACA,EAAM,OAAQ,CACjB,QAAQ,MAAM,sCAAsC,EACpDA,EAAM,aAAe,2BACrB,MACF,CACA,GAAI,CAACA,EAAM,UAAW,CACpB,QAAQ,MAAM,4DAA4D,EAC1EA,EAAM,aAAe,2BACrB,MACF,CACA,QAAQ,IAAI,4CAA4C,EACxDA,EAAM,eAAiB,GACvBA,EAAM,aAAe,KACrB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,2BAA4B,CAClE,QAAS,GACT,SAAU,KACV,UAAW,IACZ,EACD,QAAQ,IAAI,sCAAuCG,CAAG,EAClDA,GAAA,MAAAA,EAAK,GACPH,EAAM,wBAA0B,IAEhC,QAAQ,KAAK,2DAA4DG,CAAG,EAC5EH,EAAM,aAAe,8CAEzB,OAASO,EAAK,CACZ,QAAQ,MAAM,mCAAoCA,CAAG,EACrDP,EAAM,aAAe6X,GAAgBtX,CAAG,CAC1C,SACEP,EAAM,eAAiB,EACzB,CACF,CAEA,eAAsB25D,GAAe35D,EAA2B,CAC9D,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAC5B,CAAAA,EAAM,eAAiB,GACvBA,EAAM,kBAAoB,GAC1B,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,0BAA2B,EAAE,EACxDA,EAAM,wBAA0B,GAChCA,EAAM,uBAAyB,KAC/BA,EAAM,0BAA4B,IACpC,OAASO,EAAK,CACZP,EAAM,aAAe6X,GAAgBtX,CAAG,CAC1C,SACEP,EAAM,eAAiB,EACzB,EACF,CAEA,eAAsB45D,GACpB55D,EACAkhD,EACAtsD,EACAN,EACA8xC,EACA,CACA,GAAI,GAACpmC,EAAM,QAAU,CAACA,EAAM,WAAa,CAACA,EAAM,kBAChD,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,2BAA4B,CACrD,KAAM,QACN,OAAAkhD,EACA,EAAAtsD,EACA,EAAAN,EACA,OAAQ8xC,GAAU,OAClB,WAAY8a,IAAW,eAAiB,EAAI,EAC7C,CACH,MAAQ,CAER,CACF,CAEA,eAAsB2Y,GACpB75D,EACAkhD,EACA7mD,EACA4F,EACA,CACA,GAAI,GAACD,EAAM,QAAU,CAACA,EAAM,WAAa,CAACA,EAAM,kBAChD,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,2BAA4B,CACrD,KAAM,MACN,OAAAkhD,EACA,IAAA7mD,EACA,GAAI4F,GAAA,MAAAA,EAAM,KAAO,CAAE,KAAMA,EAAK,MAAS,GACvC,GAAIA,GAAA,MAAAA,EAAM,KAAO,CAAE,KAAMA,EAAK,MAAS,GACvC,GAAIA,GAAA,MAAAA,EAAM,UAAY,CAAE,UAAWA,EAAK,WAAc,EAAC,CACxD,CACH,MAAQ,CAER,CACF,CAEA,eAAsB65D,GAAgB95D,EAA2B,CAC/D,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAC5B,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,2BAA4B,EAAE,EACzDA,EAAM,sBAAwB,GAC9BA,EAAM,qBAAuB,KAC7BA,EAAM,iBAAmB,IAC3B,OAASO,EAAK,CACZP,EAAM,aAAe6X,GAAgBtX,CAAG,CAC1C,CACF,CAEO,SAASw5D,GAAgB/5D,EAA2B,CACzDA,EAAM,iBAAmB,CAACA,EAAM,gBAClC,CAEO,SAASg6D,GAAiBh6D,EAA2B,CAC1DA,EAAM,kBAAoB,CAACA,EAAM,kBAEhBy5D,GAAA,EACR,QACX,CAKO,SAASQ,GACdj6D,EACA4B,EACA,CACA,GAAI,EAACA,GAAA,MAAAA,EAAS,MAAM,OACpB5B,EAAM,uBAAyB4B,EAAQ,KACvC5B,EAAM,0BAA4B4B,EAAQ,UAAY,KAGrC63D,GAAA,EACR,YAAY73D,EAAQ,KAAMA,EAAQ,QAAQ,CACrD,CAKO,SAASs4D,GACdl6D,EACA4B,EACA,CACKA,IACL5B,EAAM,sBAAwB,GAC9BA,EAAM,qBAAuB4B,EAAQ,QAAU,kBAC/C5B,EAAM,iBAAmB4B,EAAQ,IAAM,KACzC,CAKO,SAASu4D,GAAsBn6D,EAA2B,CAC/DA,EAAM,sBAAwB,GAC9BA,EAAM,qBAAuB,KAC7BA,EAAM,iBAAmB,IAC3B,CC1KA,eAAsBo6D,GACpBp6D,EACAC,EACA,CACA,GAAI,CAACD,EAAM,QAAU,CAACA,EAAM,UAAW,OACvC,MAAM9F,EAAyC8F,EAAM,WAAW,OAC1DiC,EAAS/H,EAAa,CAAE,WAAAA,CAAA,EAAe,GAC7C,GAAI,CACF,MAAMiG,EAAO,MAAMH,EAAM,OAAO,QAAQ,qBAAsBiC,CAAM,EAGpE,GAAI,CAAC9B,EAAK,OACV,MAAMwV,EAAanf,GAA2B2J,CAAG,EACjDH,EAAM,cAAgB2V,EAAW,KACjC3V,EAAM,gBAAkB2V,EAAW,OACnC3V,EAAM,iBAAmB2V,EAAW,SAAW,IACjD,MAAQ,CAER,CACF,CCKA,eAAsB0kD,GACpBC,EAC2B,CAE3B,OADe,MAAMA,EAAO,QAAyC,cAAc,GACrE,WAAa,EAC7B,CAEA,eAAsBC,GACpBD,EACAE,EACApiD,EACe,CACf,MAAMkiD,EAAO,QAAQ,cAAe,CAAE,SAAAE,EAAU,OAAApiD,EAAQ,CAC1D,CAEA,eAAsBqiD,GACpBH,EACAE,EACe,CACf,MAAMF,EAAO,QAAQ,iBAAkB,CAAE,SAAAE,EAAU,CACrD,CAEA,eAAsBE,GACpBJ,EACAE,EACAG,EACe,CACf,MAAML,EAAO,QAAQ,kBAAmB,CAAE,SAAAE,EAAU,SAAAG,EAAU,CAChE,CCCA,MAAMC,GAAqB,4BAE3B,eAAsBliB,GAAgB14C,EAAmC,SACvE,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,eAEV,CAAAA,EAAM,eAAiB,GACvBA,EAAM,cAAgB,MACtB5L,EAAA4L,EAAM,gBAAN,MAAA5L,EAAA,KAAA4L,GAEA,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,gBAAiB,EAAE,EAC3DA,EAAM,eAAiBG,EAAI,QAC3BH,EAAM,cAAgBG,EAAI,OAC1BH,EAAM,gBAAkBG,EAAI,gBAC5BH,EAAM,cAAgBG,EAAI,gBACtB,IAAIA,EAAI,MAAM,aACd,YACN,OAASI,EAAK,CACZP,EAAM,cAAgB,iBAAiB,OAAOO,CAAG,CAAC,GAClDP,EAAM,gBAAkB,IAC1B,SACEA,EAAM,eAAiB,IACvB3L,EAAA2L,EAAM,gBAAN,MAAA3L,EAAA,KAAA2L,EACF,EACF,CAEA,eAAsB66D,GAAU76D,EAAmC,aACjE,GAAI,GAACA,EAAM,QAAUA,EAAM,eAE3B,CAAAA,EAAM,cAAgB,GACtBA,EAAM,cAAgB,qBACtBA,EAAM,oBAAsB,GAC5BA,EAAM,iBAAmB,MACzB5L,EAAA4L,EAAM,gBAAN,MAAA5L,EAAA,KAAA4L,GAGA,GAAI,CACF,aAAa,QAAQ46D,GAAoB,OAAO,KAAK,KAAK,CAAC,EAC3D,aAAa,WAAWE,EAAW,CACrC,MAAQ,CAAwC,CAEhD,GAAI,CACF,MAAM36D,EAAO,MAAMH,EAAM,OAAO,QAAQ,aAAc,CACpD,eAAgB,IAChB,KAAM,yBACP,EAED,GAAIG,EAAI,IAAMA,EAAI,OAAO,SAAW,KAClCH,EAAM,cAAgB,mCACtB3L,EAAA2L,EAAM,gBAAN,MAAA3L,EAAA,KAAA2L,WAGSG,EAAI,IAAMA,EAAI,OAAO,SAAW,UACzC46D,GAAA,EACA/6D,EAAM,cAAgBG,EAAI,OAAO,QAAU,iBAC3CH,EAAM,cAAgB,IACtBqiB,EAAAriB,EAAM,gBAAN,MAAAqiB,EAAA,KAAAriB,OAEA,OAAA+6D,GAAA,EACM,IAAI,MAAM56D,EAAI,OAAO,QAAU,eAAe,CAExD,OAASI,EAAK,CACZw6D,GAAA,EACA/6D,EAAM,cAAgB,kBAAkB,OAAOO,CAAG,CAAC,GACnDP,EAAM,cAAgB,GACtBA,EAAM,oBAAsB,IAC5ByL,EAAAzL,EAAM,gBAAN,MAAAyL,EAAA,KAAAzL,EACF,EACF,CAGO,SAASg7D,GACdh7D,EACA4B,EACM,WACN,MAAM8B,EAAQ9B,EAAQ,MAEtB,GAAI8B,IAAU,aAAc,CAC1B,MAAMhN,EAAOkL,EAAQ,KACf60B,EAAQ70B,EAAQ,MAChBvB,EAAQuB,EAAQ,MACtB5B,EAAM,cAAgB,aAAatJ,CAAI,KAAK+/B,EAAQ,CAAC,IAAIp2B,CAAK,IAG9D,MAAM8W,EAAWnX,EAAM,oBAAoB,KAAM7M,GAAMA,EAAE,QAAUsjC,CAAK,EACpEtf,GACFA,EAAS,OAAS,UAClBA,EAAS,KAAOzgB,GAEhBsJ,EAAM,oBAAsB,CAC1B,GAAGA,EAAM,oBACT,CAAE,KAAAtJ,EAAM,MAAA+/B,EAAO,MAAAp2B,EAAO,OAAQ,UAAU,GAG5CjM,EAAA4L,EAAM,gBAAN,MAAA5L,EAAA,KAAA4L,EACF,SAAW0D,IAAU,YAAa,CAChC,MAAMhN,EAAOkL,EAAQ,KACf60B,EAAQ70B,EAAQ,MAChBvB,EAAQuB,EAAQ,MAChB8f,EAAK9f,EAAQ,GACbq5D,EAAar5D,EAAQ,WAErBuV,EAAWnX,EAAM,oBAAoB,KAAM7M,GAAMA,EAAE,QAAUsjC,CAAK,EACpEtf,GACFA,EAAS,OAASuK,EAAK,OAAS,SAChCvK,EAAS,WAAa8jD,GAEtBj7D,EAAM,oBAAsB,CAC1B,GAAGA,EAAM,oBACT,CAAE,KAAAtJ,EAAM,MAAA+/B,EAAO,MAAAp2B,EAAO,OAAQqhB,EAAK,OAAS,SAAU,WAAAu5C,CAAA,CAAW,EAGrE,MAAMC,EAAc,CAACx5C,GAAM9f,EAAQ,MAAQ,KAAMA,EAAQ,MAAiB,MAAM,EAAG,GAAG,CAAC,GAAK,GAC5F5B,EAAM,cAAgB0hB,EAClB,aAAahrB,CAAI,UAAU+/B,EAAQ,CAAC,IAAIp2B,CAAK,IAC7C,uBAAuB3J,CAAI,GAAGwkE,CAAW,IAC7C7mE,EAAA2L,EAAM,gBAAN,MAAA3L,EAAA,KAAA2L,EACF,SAAW0D,IAAU,WAAY,CAE/B,GADe9B,EAAQ,SACR,KACb5B,EAAM,cAAgB,8CACjB,CACL,MAAMo3D,EAASx1D,EAAQ,OACvB5B,EAAM,cAAgBo3D,EAAS,kBAAkBA,CAAM,GAAK,gBAC5Dp3D,EAAM,cAAgB,GACtB+6D,GAAA,CACF,EACA14C,EAAAriB,EAAM,gBAAN,MAAAqiB,EAAA,KAAAriB,EACF,CACF,CAQA,eAAsBm7D,GAAsBn7D,EAAmC,aAC7E,GAAI,CAACA,EAAM,QAAU,CAACA,EAAM,UAAW,OAEvC,MAAMo7D,EAAiBC,GAAA,EACvBN,GAAA,EAEA,GAAI,CACF,MAAM56D,EAAO,MAAMH,EAAM,OAAO,QAC9B,oBACA,EAAC,EAEH,GAAI,CAACG,EAAI,IAAM,CAACA,EAAI,OAAQ,OAK5B,MAAMm7D,EAAY,EAAI,IAChBC,EAAW,KAAK,MAAQp7D,EAAI,OAAO,GAAKm7D,EAI9C,GAHI,CAACF,GAAkB,CAACG,GAGpBC,GAAkBr7D,EAAI,OAAO,EAAE,EAAG,OAEtCH,EAAM,iBAAmBG,EAAI,OAE7B,MAAMs7D,GAAgBrnE,EAAA+L,EAAI,OAAO,QAAX,YAAA/L,EAA8C,QAKpE,GAJI+L,EAAI,OAAO,SAAW,MAAQs7D,IAChCz7D,EAAM,eAAiBy7D,GAEzBz7D,EAAM,gBAAkB,GACpBG,EAAI,OAAO,SAAW,KAAM,CAC9B,MAAMowB,GAASl8B,EAAA8L,EAAI,OAAO,SAAX,YAAA9L,EAAmB,QAC5Bm8B,EAAQirC,GAAgBt7D,EAAI,OAAO,eACzCH,EAAM,cAAgBuwB,EAClB,aAAaA,CAAM,OAAOC,CAAK,GAC/B,eAAeA,CAAK,EAC1B,KAAO,CACL,MAAM4mC,EAASj3D,EAAI,OAAO,UAAUkiB,EAAAliB,EAAI,OAAO,aAAX,YAAAkiB,EAAuB,OAAQ,gBACnEriB,EAAM,cAAgB,kBAAkBo3D,CAAM,EAChD,CACF,MAAQ,CAER,SACEp3D,EAAM,cAAgB,GACtBA,EAAM,oBAAsB,IAC5ByL,EAAAzL,EAAM,gBAAN,MAAAyL,EAAA,KAAAzL,EACF,CACF,CAEA,MAAM86D,GAAc,8BAEb,SAASY,GAAoB17D,EAA0B,OAC5DA,EAAM,iBAAmB,KACzBA,EAAM,cAAgB,KACtB,GAAI,CACF,aAAa,QAAQ86D,GAAa,OAAO,KAAK,KAAK,CAAC,CACtD,MAAQ,CAAe,EACvB1mE,EAAA4L,EAAM,gBAAN,MAAA5L,EAAA,KAAA4L,EACF,CAEA,SAASq7D,IAA2B,CAClC,GAAI,CACF,MAAM7zC,EAAK,aAAa,QAAQozC,EAAkB,EAClD,OAAKpzC,EAEO,KAAK,MAAQ,OAAOA,CAAE,EACxB,GAAK,KACb,aAAa,WAAWozC,EAAkB,EACnC,IAEF,GAPS,EAQlB,MAAQ,CACN,MAAO,EACT,CACF,CAEA,SAASG,IAA2B,CAClC,GAAI,CACF,aAAa,WAAWH,EAAkB,CAC5C,MAAQ,CAAe,CACzB,CAEA,SAASY,GAAkBG,EAA2B,CACpD,GAAI,CACF,MAAMC,EAAc,aAAa,QAAQd,EAAW,EACpD,OAAKc,EAEE,OAAOA,CAAW,GAAKD,EAFL,EAG3B,MAAQ,CACN,MAAO,EACT,CACF,CCjSA,MAAME,GAAY,sBAEX,SAASC,GACdC,EACM,CACN,MAAM5kD,EAAW,SAAS,eAAe0kD,EAAS,EAClD,GAAI,CAACE,EAAc,CACjB5kD,GAAA,MAAAA,EAAU,SACV,MACF,CACIA,KAAmB,SAEvB,MAAM6kD,EAAS,SAAS,cAAc,KAAK,EAC3CA,EAAO,GAAKH,GACZ,OAAO,OAAOG,EAAO,MAAO,CAC1B,WAAY,2BACZ,OAAQ,oCACR,aAAc,MACd,QAAS,YACT,OAAQ,aACR,QAAS,OACT,WAAY,SACZ,eAAgB,gBAChB,IAAK,OACL,MAAO,2BACP,SAAU,OACX,EAED,MAAMp9D,EAAM,SAAS,cAAc,MAAM,EACzCA,EAAI,YAAcm9D,EAAa,QAC/BC,EAAO,YAAYp9D,CAAG,EAEtB,MAAMq9D,EAAU,SAAS,cAAc,QAAQ,EAC/CA,EAAQ,aAAa,aAAc,SAAS,EAC5CA,EAAQ,YAAc,IACtB,OAAO,OAAOA,EAAQ,MAAO,CAC3B,WAAY,OACZ,OAAQ,OACR,MAAO,2BACP,OAAQ,UACR,SAAU,OACV,QAAS,QACV,EACDA,EAAQ,iBAAiB,QAAS,IAAMD,EAAO,QAAQ,EACvDA,EAAO,YAAYC,CAAO,GAEb,SAAS,cAAc,MAAM,GAAK,SAAS,MACnD,QAAQD,CAAM,CACrB,CCqCA,SAASE,GACP7lE,EACA8lE,EACQ,WACR,MAAM7iE,GAAOjD,GAAS,IAAI,OACpB+lE,GAAiBhoE,EAAA+nE,EAAS,iBAAT,YAAA/nE,EAAyB,OAChD,GAAI,CAACgoE,EAAgB,OAAO9iE,EAC5B,GAAI,CAACA,EAAK,OAAO8iE,EACjB,MAAMC,IAAUhoE,EAAA8nE,EAAS,UAAT,YAAA9nE,EAAkB,SAAU,OACtCioE,GAAiBj6C,EAAA85C,EAAS,iBAAT,YAAA95C,EAAyB,OAOhD,OALE/oB,IAAQ,QACRA,IAAQ+iE,GACPC,IACEhjE,IAAQ,SAASgjE,CAAc,SAC9BhjE,IAAQ,SAASgjE,CAAc,IAAID,CAAO,IAC/BD,EAAiB9iE,CACpC,CAEA,SAASijE,GAAqBx5D,EAAmBo5D,EAAoC,CACnF,GAAI,EAACA,GAAA,MAAAA,EAAU,gBAAgB,OAC/B,MAAMK,EAAqBN,GAA+Bn5D,EAAK,WAAYo5D,CAAQ,EAC7EM,EAA6BP,GACjCn5D,EAAK,SAAS,WACdo5D,CAAA,EAEIO,EAA+BR,GACnCn5D,EAAK,SAAS,qBACdo5D,CAAA,EAEIQ,EAAiBH,GAAsBC,GAA8B15D,EAAK,WAC1E65D,EAAe,CACnB,GAAG75D,EAAK,SACR,WAAY05D,GAA8BE,EAC1C,qBAAsBD,GAAgCC,CAAA,EAElDE,EACJD,EAAa,aAAe75D,EAAK,SAAS,YAC1C65D,EAAa,uBAAyB75D,EAAK,SAAS,qBAClD45D,IAAmB55D,EAAK,aAC1BA,EAAK,WAAa45D,GAEhBE,GACF19C,GAAcpc,EAAwD65D,CAAY,CAEtF,CAEO,SAASE,GAAe/5D,EAAmB,OAChDA,EAAK,UAAY,KACjBA,EAAK,MAAQ,KACbA,EAAK,UAAY,GACjBA,EAAK,kBAAoB,GACzBA,EAAK,kBAAoB,KAKzB,IAAIg6D,EAAkC,KAEtC,MAAMC,EAAW,EAAQj6D,EAAK,WAKxBk6D,EAAmBl6D,EAAK,OAASA,EAAK,WAAaA,EAAK,aACzDA,EAAK,UAAYA,EAAK,YAAcA,EAAK,cAAgBA,EAAK,aAC7Dm6D,EAAaF,EAAW,cAAgBC,EAAmB,WAAa,yBAE9E7oE,EAAA2O,EAAK,SAAL,MAAA3O,EAAa,OACb2O,EAAK,OAAS,IAAIo0D,GAAqB,CACrC,IAAKp0D,EAAK,SAAS,WACnB,MAAOi6D,EAAW,OAAaj6D,EAAK,SAAS,MAAM,OAASA,EAAK,SAAS,MAAQ,OAClF,SAAUi6D,EAAW,OAAaj6D,EAAK,SAAS,OAASA,EAAK,SAAW,OACzE,WAAAm6D,EACA,KAAM,UACN,KAAMF,EAAW,SAAW,OAC5B,OAAQA,EAAW,GAAK,OACxB,QAAUhF,GAAU,SAClB,MAAMmF,IAAkB/oE,EAAA4jE,EAAM,SAAN,YAAA5jE,EAAc,UAAW,KACjD,GAAI2oE,IAAqB,MAAQI,IAAoB,MAAQA,IAAoBJ,EAAkB,CAGjG,OAAO,SAAS,SAChB,MACF,CAUA,GATIA,IAAqB,OACvBA,EAAmBI,GAGrBp6D,EAAK,UAAY,GACjBA,EAAK,UAAY,KACjBA,EAAK,MAAQi1D,EAGTgF,EAAU,CACZI,GAAcr6D,EAAMi1D,CAAK,EACpBoC,GAAsBr3D,CAAgC,KAE1C1O,EAAA0O,EAAK,mBAAL,YAAA1O,EAAuB,OAAQ,eAC/B,aACVgpE,GAAwBt6D,CAAI,EAEnC,MACF,CAIIujB,OACFC,GAAA,EACCxjB,EAAkC,cAAgB,IAErDq6D,GAAcr6D,EAAMi1D,CAAK,EAEnBj1D,EAAkC,oBACnCo4D,GAAsBp4D,CAAgC,EAAE,KAAK,IAAM,CACjE21C,GAAgB31C,CAAgC,CACvD,CAAC,EACIq3D,GAAsBr3D,CAAgC,EACtDyzD,GAAWzzD,CAAgC,GAE5CA,EAAK,UAAYA,EAAK,QACnBu6D,GAAiBv6D,CAAI,EAEvBuU,GAAUvU,EAAkC,CAAE,MAAO,GAAM,EAC3DsU,GAAYtU,EAAkC,CAAE,MAAO,GAAM,EAC7D0zD,GAAe1zD,CAAgC,EAAE,KAAK,IAAM,CAC9DA,EAAkC,wBACrC,CAAC,EAEAA,EAAkC,sBAG/BA,EAAK,OAASA,EAAK,WAChBsD,GAAWtD,CAAgC,EAE9CA,EAAK,QACFs3D,GAAoBt3D,CAAgC,EAEpDw6D,GAAoBx6D,CAAgC,EAEpDy6D,GAAez6D,CAAgC,EAE/C06D,GAAkB16D,CAAgC,GAEpDid,GAAiBjd,CAAyD,CACjF,EACA,QAAS,CAAC,CAAE,KAAA26D,EAAM,OAAAtG,KAAa,CAC7Br0D,EAAK,UAAY,GAEb26D,IAAS,OACX36D,EAAK,UAAY,iBAAiB26D,CAAI,MAAMtG,GAAU,WAAW,GAErE,EACA,QAAUa,GAAQ0F,GAAmB56D,EAAMk1D,CAAG,EAC9C,MAAO,CAAC,CAAE,SAAA2F,EAAU,SAAAC,KAAe,CAIjC,QAAQ,KAAK,qCAAqCD,CAAQ,SAASC,CAAQ,EAAE,EACxE79C,GAAiBjd,CAAyD,CACjF,EACD,EACDA,EAAK,OAAO,OACd,CAEO,SAAS46D,GAAmB56D,EAAmBk1D,EAAwB,CAC5E,GAAI,CACF6F,GAAyB/6D,EAAMk1D,CAAG,CACpC,OAAS13D,EAAK,CACZ,QAAQ,MAAM,sCAAuC03D,EAAI,MAAO13D,CAAG,CACrE,CACF,CAEA,SAASu9D,GAAyB/6D,EAAmBk1D,EAAwB,OAS3E,GARAl1D,EAAK,eAAiB,CACpB,CAAE,GAAI,KAAK,MAAO,MAAOk1D,EAAI,MAAO,QAASA,EAAI,SACjD,GAAGl1D,EAAK,gBACR,MAAM,EAAG,GAAG,EACVA,EAAK,MAAQ,UACfA,EAAK,SAAWA,EAAK,gBAGnBk1D,EAAI,QAAU,QAAS,CACzB,GAAIl1D,EAAK,WAAY,OACrBY,GACEZ,EACAk1D,EAAI,SAEN,MACF,CAEA,GAAIA,EAAI,QAAU,OAAQ,CACxB,MAAMr2D,EAAUq2D,EAAI,QAChBr2D,GAAA,MAAAA,EAAS,YACXyd,GACEtc,EACAnB,EAAQ,YAGZ,MAAM5B,EAAQ2B,GAAgBoB,EAAkCnB,CAAO,EAOvE,IANI5B,IAAU,SAAWA,IAAU,SAAWA,IAAU,aACtDsD,GAAgBP,CAAwD,EACnEof,GACHpf,CAAA,GAGA/C,IAAU,QAAS,CAErB,MAAMif,EAAMlc,EACNkf,EAAc,KAAK,OAAK7tB,EAAA6qB,EAAI,eAAJ,YAAA7qB,EAAkB,SAAU,GAAK,GAAI0L,EAAc,EAC5EC,GAAgBkf,EAAK,CAAE,MAAOgD,EAAa,CAClD,CACA,MACF,CAEA,GAAIg2C,EAAI,QAAU,cAAe,CAC/B,MAAMr2D,EAAUq2D,EAAI,SAElBr2D,GAAA,YAAAA,EAAS,cAAemB,EAAK,YAC7B,MAAM,QAAQnB,EAAQ,WAAW,GACjCA,EAAQ,YAAY,OAAS,IAE5BmB,EAAkC,gBAAkBnB,EAAQ,aAE/D,MACF,CAEA,GAAIq2D,EAAI,QAAU,WAAY,CAC5B,MAAMr2D,EAAUq2D,EAAI,QAChBr2D,GAAA,MAAAA,EAAS,UAAY,MAAM,QAAQA,EAAQ,QAAQ,IACrDmB,EAAK,gBAAkBnB,EAAQ,SAC/BmB,EAAK,cAAgB,KACrBA,EAAK,eAAiB,MAExB,MACF,CAEA,GAAIk1D,EAAI,QAAU,OAAQ,CACxB,MAAMr2D,EAAUq2D,EAAI,QAChBr2D,GAASmG,GAAmBhF,EAAMnB,CAAO,EACzCmB,EAAK,MAAQ,QACTA,EAAkC,UAE5C,CAMA,IAJIk1D,EAAI,QAAU,yBAA2BA,EAAI,QAAU,yBACpD5gD,GAAYtU,EAAkC,CAAE,MAAO,GAAM,EAGhEk1D,EAAI,QAAU,0BAA2B,CAC3C,MAAMz1D,EAAQ81D,GAA2BL,EAAI,OAAO,EACpD,GAAIz1D,EAAO,CACTO,EAAK,kBAAoB81D,GAAgB91D,EAAK,kBAAmBP,CAAK,EACtEO,EAAK,kBAAoB,KACzB,MAAMs0D,EAAQ,KAAK,IAAI,EAAG70D,EAAM,YAAc,KAAK,MAAQ,GAAG,EAC9D,OAAO,WAAW,IAAM,CACtBO,EAAK,kBAAoB+1D,GAAmB/1D,EAAK,kBAAmBP,EAAM,EAAE,CAC9E,EAAG60D,CAAK,CACV,CACA,MACF,CAEA,GAAIY,EAAI,QAAU,2BAA4B,CAC5CgC,GACEl3D,EACAk1D,EAAI,SAEN,MACF,CAEA,GAAIA,EAAI,QAAU,kBAAmB,CACnCiC,GACEn3D,EACAk1D,EAAI,SAGDl1D,EAAK,cACR,OAAO,SAAS,KAAO,YAEzB,MACF,CAEA,GAAIk1D,EAAI,QAAU,2BAA4B,CAC5CkC,GAAsBp3D,CAAgC,EACtD,MACF,CAEA,GAAIk1D,EAAI,QAAU,yBAA0B,CAC1C,MAAMr3C,EAAW+3C,GAA0BV,EAAI,OAAO,EAClDr3C,IACF7d,EAAK,kBAAoB+1D,GAAmB/1D,EAAK,kBAAmB6d,EAAS,EAAE,GAEjF,MACF,CAEA,GAAIq3C,EAAI,QAAU,kBAAmB,CACnC+C,GACEj4D,EACAk1D,EAAI,SAEN,MACF,CAEA,GAAIA,EAAI,QAAU,eAAgB,CAChC,MAAMr2D,EAAUq2D,EAAI,SAGhBr2D,GAAA,YAAAA,EAAS,YAAa,kBACxBk6D,GAAyBl6D,CAAO,EAElC,MACF,CACF,CAEO,SAASw7D,GAAcr6D,EAAmBi1D,EAAuB,CACtE,MAAMvxD,EAAWuxD,EAAM,SAOnBvxD,GAAA,MAAAA,EAAU,UAAY,MAAM,QAAQA,EAAS,QAAQ,IACvD1D,EAAK,gBAAkB0D,EAAS,UAE9BA,GAAA,MAAAA,EAAU,SACZ1D,EAAK,YAAc0D,EAAS,QAE1BA,GAAA,MAAAA,EAAU,iBACZ81D,GAAqBx5D,EAAM0D,EAAS,eAAe,CAEvD,CAEA,eAAe62D,GAAiBv6D,EAAmB,CACjD,GAAI,GAACA,EAAK,QAAU,CAACA,EAAK,WAC1B,GAAI,CACF,MAAM5C,EAAO,MAAM4C,EAAK,OAAO,QAAQ,cAAe,EAAE,EAGpD,MAAM,QAAQ5C,GAAA,YAAAA,EAAK,MAAM,IAC3B4C,EAAK,iBAAmB5C,EAAI,OAEhC,MAAQ,CAER,CACF,CAEA,eAAek6D,GAAoBt3D,EAAqB,CACtD,GAAI,GAACA,EAAK,QAAU,CAACA,EAAK,WAC1B,GAAI,CACFA,EAAK,gBAAkB,MAAMg7D,GAAqBh7D,EAAK,MAAM,CAC/D,MAAQ,CAER,CACF,CAEA,eAAew6D,GAAoBx6D,EAAqB,CACtD,GAAI,GAACA,EAAK,QAAU,CAACA,EAAK,WAC1B,GAAI,CACFA,EAAK,gBAAkB,MAAMA,EAAK,OAAO,QAAQ,kBAAkB,EACnEA,EAAK,sBAAwB,KAC7BA,EAAK,oBAAsB,IAC7B,MAAQ,CAER,CACF,CAEA,eAAey6D,GAAez6D,EAAqB,CACjD,GAAI,GAACA,EAAK,QAAU,CAACA,EAAK,WAC1B,GAAI,CACF,MAAMuG,EAAS,MAAMvG,EAAK,OAAO,QAA6C,aAAa,EAK3F,GAJAA,EAAK,WAAauG,EAIdA,GAAA,MAAAA,EAAQ,WAAaA,EAAO,QAAU,KACxC,GAAI,CACF,KAAM,CAAC00D,EAAYC,CAAW,EAAI,MAAM,QAAQ,IAAI,CAClDl7D,EAAK,OAAQ,QAAkG,WAAW,EAC1HA,EAAK,OAAQ,QAA6C,aAAa,EACxE,EAID,GAFAA,EAAK,WAAak7D,EAEdA,EAAY,QAAU,MAAQD,EAAW,SAAU,CACrD,MAAME,EAASF,EAAW,SAAS,KAAMzqE,GAAMA,EAAE,MAAM,EACnD2qE,IACFn7D,EAAK,WAAa,CAAE,GAAGk7D,EAAa,OAAQC,EAAO,QAEvD,CACF,MAAQ,CAER,CAEJ,MAAQ,CAER,CACF,CAEA,eAAeT,GAAkB16D,EAAqB,CACpD,GAAI,GAACA,EAAK,QAAU,CAACA,EAAK,WAC1B,GAAI,CACF,MAAMvH,EAAS,MAAMuH,EAAK,OAAO,QAA4C,gBAAgB,EAC7FA,EAAK,YAAcvH,EAAO,KAC1BuH,EAAK,gBAAkBvH,EAAO,SAC9BuH,EAAK,iBAAmB,OAAOvH,EAAO,IAAI,EAC1CuH,EAAK,qBAAuBvH,EAAO,QACrC,MAAQ,CAER,CACF,CAIA,MAAM2iE,GAAqB,uBAE3B,SAASC,GAA0BC,EAAU,GAAY,OACvD,MAAMlnD,EAAW,SAAS,OACvB,MAAM,GAAG,EACT,IAAKzjB,GAAMA,EAAE,MAAM,EACnB,KAAMA,GAAMA,EAAE,WAAW,GAAGyqE,EAAkB,GAAG,CAAC,EACrD,GAAIhnD,EAAU,OAAOA,EAAS,MAAM,GAAG,EAAE,CAAC,EAE1C,MAAM/X,EAAK,UAAQhL,EAAA,OAAO,aAAP,YAAAA,EAAA,eAAyB,KAAK,SAAS,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,GACzEkqE,EAAU,IAAI,KAAK,KAAK,MAAQD,EAAU,KAAQ,EAAE,cAC1D,gBAAS,OAAS,GAAGF,EAAkB,IAAI/+D,CAAE,qBAAqBk/D,CAAO,iBAClEl/D,CACT,CAEA,eAAei+D,GAAwBt6D,EAAmB,WACxD,GAAI,CAACA,EAAK,QAAU,CAACA,EAAK,UAAW,OACrC,MAAMw7D,EAAWH,IAA0BhqE,EAAA2O,EAAK,mBAAL,YAAA3O,EAAuB,aAAa,EAC/E,GAAI,CACF,MAAMqT,GAAYpT,EAAA0O,EAAK,mBAAL,YAAA1O,EAAuB,UACnC8L,EAAO,MAAM4C,EAAK,OAAO,QAAQ,iBAAkB,CAAE,SAAAw7D,EAAU,UAAA92D,EAAW,EAGhF,GAAItH,GAAA,MAAAA,EAAK,WAAY,CACnB4C,EAAK,qBAAuB5C,EAAI,WAChC4C,EAAK,WAAa5C,EAAI,WACtB4C,EAAK,wBAA0B,GAC/BA,EAAK,mBAAqB,QAE1B,MAAMy7D,IAASn8C,EAAAtf,EAAK,mBAAL,YAAAsf,EAAuB,YAAa,GAClDtf,EAAkC,YAAczI,GAAUkkE,EAAQr+D,EAAI,UAAU,EAC5EJ,GAAgBgD,CAAgC,CACvD,CACF,OAASxC,EAAK,CACZ,QAAQ,MAAM,qDAAsDA,CAAG,EACvEwC,EAAK,UAAY,8BACnB,CACF,CC3gBA,IAAI07D,GAAU,GACVC,GAA0B,KAC1BC,GAAW,GACXC,GAAW,GACXC,GAAU,GAEVC,GAAqB,GAErBC,GAAuC,QAEvCC,GAA+C,GAGnD,SAASC,GAAe3lE,EAAqB,CAC3C,OAAOA,EAAI,QAAQ,YAAa,EAAE,CACpC,CAEA,SAAS4lE,IAAgB,CACvBT,GAAU,GACVC,GAAW,KACXC,GAAW,GACXC,GAAW,GACXC,GAAU,GACVC,GAAqB,GACrBC,GAAoB,QACpBC,GAAsB,EACxB,CAEA,eAAeG,GAAsB36C,EAAwB,CAC3D,GAAI,CAACA,EAAM,QAAU,CAACA,EAAM,UAAW,OACvC,MAAM+5C,EAAWH,GAA0B55C,EAAM,aAAa,EAC9D,GAAI,CACF,MAAMrkB,EAAO,MAAMqkB,EAAM,OAAO,QAAQ,iBAAkB,CAAE,SAAA+5C,EAAU,UAAW/5C,EAAM,UAAW,EAG9FrkB,GAAA,MAAAA,EAAK,YACPqkB,EAAM,gBAAgBrkB,EAAI,UAAU,CAExC,OAASI,EAAK,CACZm+D,GAAWn+D,aAAe,MAAQA,EAAI,QAAU,0BAChDikB,EAAM,eACR,CACF,CAEA,eAAe46C,GAAW56C,EAAwB,CAChD,GAAI,CAACA,EAAM,QAAUi6C,GAAS,OAC9B,MAAMY,EAAQJ,GAAeN,EAAQ,EACrC,GAAI,CAACU,EAAO,CACVX,GAAW,iCACXl6C,EAAM,gBACN,MACF,CACAi6C,GAAU,GACVC,GAAW,KACXl6C,EAAM,gBACN,GAAI,CACF,MAAMrkB,EAAO,MAAMqkB,EAAM,OAAO,QAAQ,qBAAsB,CAC5D,MAAA66C,EACA,KAAMR,GAAQ,QAAU,OACxB,UAAWr6C,EAAM,UACjB,QAASw6C,IAAuB,OACjC,EACG7+D,GAAA,MAAAA,EAAK,IACP2+D,GAAqB3+D,EAAI,SAAW,GACpC4+D,GAAoB,QACpBv6C,EAAM,iBAAiB,KAAK,GAE5Bk6C,IAAWv+D,GAAA,YAAAA,EAAK,QAAS,kCAE7B,OAASI,EAAK,CACZm+D,GAAWn+D,aAAe,MAAQA,EAAI,QAAU,kCAClD,SACEk+D,GAAU,GACVj6C,EAAM,eACR,CACF,CAEA,eAAe86C,GAAgB96C,EAAwB,CACrD,GAAI,CAACA,EAAM,QAAUi6C,GAAS,OAC9B,MAAMc,EAAQX,GAAS,OAAO,cAC9B,GAAI,CAACW,GAAS,CAACA,EAAM,SAAS,GAAG,EAAG,CAClCb,GAAW,qCACXl6C,EAAM,gBACN,MACF,CACAi6C,GAAU,GACVC,GAAW,KACXl6C,EAAM,gBACN,GAAI,CACF,MAAMrkB,EAAO,MAAMqkB,EAAM,OAAO,QAAQ,qBAAsB,CAC5D,WAAY+6C,EACZ,UAAW/6C,EAAM,UAClB,EACGrkB,GAAA,MAAAA,EAAK,IACP2+D,GAAqB3+D,EAAI,SAAW,QACpC4+D,GAAoB,QACpBv6C,EAAM,iBAAiB,KAAK,GAE5Bk6C,IAAWv+D,GAAA,YAAAA,EAAK,QAAS,kCAE7B,OAASI,EAAK,CACZm+D,GAAWn+D,aAAe,MAAQA,EAAI,QAAU,kCAClD,SACEk+D,GAAU,GACVj6C,EAAM,eACR,CACF,CAEA,eAAeg7C,GAAUh7C,EAAwBk5C,EAAc,CAC7D,GAAI,GAACl5C,EAAM,QAAUi6C,IACrB,IAAI,CAACf,EAAK,OAAQ,CAChBgB,GAAW,qCACXl6C,EAAM,gBACN,MACF,CACAi6C,GAAU,GACVC,GAAW,KACXl6C,EAAM,gBACN,GAAI,CACF,MAAMi7C,EAAaV,KAAsB,QAAUH,GAAS,OAAO,cAAgBK,GAAeN,EAAQ,EACpGx+D,EAAO,MAAMqkB,EAAM,OAAO,QAAQ,oBAAqB,CAC3D,WAAAi7C,EACA,KAAM/B,EAAK,OACX,UAAWl5C,EAAM,UAClB,EACGrkB,GAAA,MAAAA,EAAK,IAAMA,EAAI,YACjB++D,GAAA,EACA16C,EAAM,gBAAgBrkB,EAAI,UAAU,GAEpCu+D,IAAWv+D,GAAA,YAAAA,EAAK,QAAS,2BAE7B,OAASI,EAAK,CACZm+D,GAAWn+D,aAAe,MAAQA,EAAI,QAAU,qBAClD,SACEk+D,GAAU,GACVj6C,EAAM,eACR,EACF,CAEA,SAASk7C,GAAaC,EAAyB,CAG7C,OAAOl8C,CACT,CAEA,SAASm8C,GAAgBp7C,EAAwB,CAC/C,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBAMUm8C,EAAO;AAAA,mBACN3rE,GAAa,CAAE2rE,GAAW3rE,EAAE,OAA4B,KAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAQjEyrE,EAAQ;AAAA,mBACPzrE,GAAa,CAAEyrE,GAAYzrE,EAAE,OAA4B,KAAO,CAAC;AAAA,qBAC/DA,GAAqB,CAC3BA,EAAE,MAAQ,UAAWA,EAAE,iBAAuBksE,GAAW56C,CAAK,EACpE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKHk6C,GAAWh8C,oCAAuCg8C,EAAQ,SAAWj7C,CAAO;AAAA;AAAA;AAAA,oBAGhEg7C,EAAO;AAAA,iBACV,KAAWW,GAAW56C,CAAK,EAAC;AAAA;AAAA,UAEnCi6C,GAAU,aAAe,wBAAwB;AAAA;AAAA;AAAA,GAI3D,CAEA,SAASoB,GAAgBr7C,EAAwB,CAC/C,OAAO9B;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,mBAMUm8C,EAAO;AAAA,mBACN3rE,GAAa,CAAE2rE,GAAW3rE,EAAE,OAA4B,KAAO,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAQjE0rE,EAAQ;AAAA,mBACP1rE,GAAa,CAAE0rE,GAAY1rE,EAAE,OAA4B,KAAO,CAAC;AAAA,qBAC/DA,GAAqB,CAC3BA,EAAE,MAAQ,UAAWA,EAAE,iBAAuBosE,GAAgB96C,CAAK,EACzE,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKHk6C,GAAWh8C,oCAAuCg8C,EAAQ,SAAWj7C,CAAO;AAAA;AAAA;AAAA,oBAGhEg7C,EAAO;AAAA,iBACV,KAAWa,GAAgB96C,CAAK,EAAC;AAAA;AAAA,UAExCi6C,GAAU,aAAe,wBAAwB;AAAA;AAAA;AAAA,GAI3D,CAEA,SAASqB,GAAct7C,EAAwB,CAC7C,IAAIu7C,EAAU,GACd,MAAMC,EAAajB,KAAsB,QACnCkB,EAAeD,EAAa,QAAUlB,KAAuB,MAAQ,MAAQ,WAC7EoB,EAAoBF,EAAapB,GAAWD,GAC5CwB,EAA8BH,EAAa,QAAU,QAC3D,OAAOt9C;AAAAA;AAAAA;AAAAA,iDAGwCw9C,CAAiB,iBAAiBD,CAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAQ3E/sE,GAAa,CAAE6sE,EAAW7sE,EAAE,OAA4B,KAAO,CAAC;AAAA,qBAC9DA,GAAqB,CAC3BA,EAAE,MAAQ,UAAWA,EAAE,iBAAuBssE,GAAUh7C,EAAOu7C,CAAO,EAC5E,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAKHrB,GAAWh8C,oCAAuCg8C,EAAQ,SAAWj7C,CAAO;AAAA;AAAA;AAAA,oBAGhEg7C,EAAO;AAAA,iBACV,KAAWe,GAAUh7C,EAAOu7C,CAAO,EAAC;AAAA;AAAA,UAE3CtB,GAAU,eAAiB,QAAQ;AAAA;AAAA;AAAA;AAAA,iBAI5B,IAAM,CAAEC,GAAW,KAAMl6C,EAAM,iBAAiB27C,CAAQ,CAAG,CAAC;AAAA;AAAA,UAEnEH,EAAa,wBAA0B,wBAAwB;AAAA;AAAA;AAAA,GAIzE,CAEO,SAASI,GAAiB57C,EAAwB,CACvD,KAAM,CAAE,SAAA67C,EAAU,SAAAC,CAAA,EAAa97C,EACzB+7C,EAAe,CAAC/7C,EAAM,aAAeA,EAAM,YAAY,OAAS,EAItE,GAAI67C,IAAa,YACf,OAAO39C;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAWT,GAAI29C,IAAa,WAAY,CAC3B,MAAMG,EAAUh8C,EAAM,eAAiB,CAAC,WAAY,KAAK,EACnDi8C,EAAWD,EAAQ,SAAS,UAAU,GAAKA,EAAQ,SAAS,KAAK,GAAKA,EAAQ,SAAS,OAAO,EAC9FrzC,EAAWqzC,EAAQ,SAAS,OAAO,EAEzC,MAAI,CAACD,GAAgB,CAACpzC,EACbzK;AAAAA;AAAAA;AAAAA,cAGCg9C,GAAkB,CAAC;AAAA,uDACsBl7C,EAAM,aAAa;AAAA;AAAA;AAAA;AAAA,QAOlE87C,IAAa,MACR59C;AAAAA;AAAAA;AAAAA,cAGCg9C,GAAkB,CAAC;AAAA,uDACsBl7C,EAAM,aAAa;AAAA,cAC5Ds7C,GAAct7C,CAAK,CAAC;AAAA;AAAA;AAAA,QAM1B87C,IAAa,QACR59C;AAAAA;AAAAA;AAAAA,cAGCg9C,GAAkB,CAAC;AAAA,uDACsBl7C,EAAM,aAAa;AAAA;AAAA,cAE5Dq7C,GAAgBr7C,CAAK,CAAC;AAAA,cACtBi8C,EAAW/9C;AAAAA;AAAAA,yBAEA,IAAM,CAAEw8C,GAAA,EAAiB16C,EAAM,iBAAiB,OAAO,CAAG,CAAC;AAAA;AAAA;AAAA,cAGpEf,CAAO;AAAA;AAAA;AAAA,QAMf68C,IAAa,QACR59C;AAAAA;AAAAA;AAAAA,cAGCg9C,GAAkB,CAAC;AAAA,uDACsBl7C,EAAM,aAAa;AAAA;AAAA,cAE5Do7C,GAAgBp7C,CAAK,CAAC;AAAA,cACtB2I,EAAWzK;AAAAA;AAAAA,yBAEA,IAAM,CAAEw8C,GAAA,EAAiB16C,EAAM,iBAAiB,OAAO,CAAG,CAAC;AAAA;AAAA;AAAA,cAGpEf,CAAO;AAAA;AAAA;AAAA,QAQfg9C,GAAYtzC,EACPzK;AAAAA;AAAAA;AAAAA,cAGCg9C,GAAkB,CAAC;AAAA,uDACsBl7C,EAAM,aAAa;AAAA;AAAA,cAE5Do7C,GAAgBp7C,CAAK,CAAC;AAAA;AAAA,uBAEb,IAAM,CAAE06C,GAAA,EAAiB16C,EAAM,iBAAiB,OAAO,CAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,QAO1E2I,EACKzK;AAAAA;AAAAA;AAAAA,cAGCg9C,GAAkB,CAAC;AAAA,uDACsBl7C,EAAM,aAAa;AAAA;AAAA,cAE5Dq7C,GAAgBr7C,CAAK,CAAC;AAAA;AAAA;AAAA,QAMzB9B;AAAAA;AAAAA;AAAAA,YAGCg9C,GAAkB,CAAC;AAAA,qDACsBl7C,EAAM,aAAa;AAAA;AAAA,YAE5Do7C,GAAgBp7C,CAAK,CAAC;AAAA;AAAA;AAAA,KAIhC,CAGA,MAAMg8C,EAAUh8C,EAAM,eAAiB,CAAC,WAAY,KAAK,EACnDyI,EAAcuzC,EAAQ,SAAS,UAAU,IAAM,CAACh8C,EAAM,aAAeA,EAAM,YAAY,SAAS,UAAU,GAC1G0I,EAASszC,EAAQ,SAAS,KAAK,EAC/BrzC,EAAWqzC,EAAQ,SAAS,OAAO,EAEnCE,EADWzzC,GAAeC,GAAUszC,EAAQ,SAAS,OAAO,GAC9BrzC,EAEpC,GAAImzC,IAAa,SAAWA,IAAa,SAAWA,IAAa,MAAO,CACtE,MAAMK,EAAiBL,IAAa,SAAYA,IAAa,OAASvB,KAAsB,QAEtFlsC,EAAW8tC,EACb,0EACA,kDAHgBA,EAAiB,QAAU3B,KAAwB,MAAQ,MAAQ,UAGtB,IACjE,OAAOt8C;AAAAA;AAAAA;AAAAA,YAGCg9C,GAAkB,CAAC;AAAA,qDACsBl7C,EAAM,aAAa;AAAA,6CAC3BqO,CAAQ;AAAA,YACzCytC,IAAa,MACXR,GAAct7C,CAAK,EACnB87C,IAAa,QACXT,GAAgBr7C,CAAK,EACrBo7C,GAAgBp7C,CAAK,CAAC;AAAA,YAC1B87C,IAAa,MAAQ59C;AAAAA;AAAAA,uBAEV,IAAM,CAAEw8C,GAAA,EAAiB16C,EAAM,iBAAiB,MAAM,CAAG,CAAC;AAAA;AAAA;AAAA,YAGnEf,CAAO;AAAA;AAAA;AAAA,KAInB,CAGA,OAAOf;AAAAA;AAAAA;AAAAA,UAGCg9C,GAAkB,CAAC;AAAA,mDACsBl7C,EAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,qBAKjD,KAAW26C,GAAsB36C,CAAK,EAAC;AAAA;AAAA;AAAA;AAAA,YAIhDyI,EACEvK;AAAAA;AAAAA;AAAAA,2BAGa,IAAM,CAAEw8C,GAAA,EAAiBF,GAAsB,WAAYx6C,EAAM,iBAAiB,OAAO,CAAG,CAAC;AAAA;AAAA;AAAA;AAAA,gBAK1Gf,CAAO;AAAA,YACTyJ,EACExK;AAAAA;AAAAA;AAAAA,2BAGa,IAAM,CAAEw8C,GAAA,EAAiBF,GAAsB,MAAOx6C,EAAM,iBAAiB,OAAO,CAAG,CAAC;AAAA;AAAA;AAAA;AAAA,gBAKrGf,CAAO;AAAA,YACT0J,EACEzK;AAAAA;AAAAA;AAAAA,2BAGa,IAAM,CAAEw8C,GAAA,EAAiB16C,EAAM,iBAAiB,OAAO,CAAG,CAAC;AAAA;AAAA;AAAA;AAAA,gBAKxEf,CAAO;AAAA;AAAA,UAEXi9C,EACEh+C;AAAAA;AAAAA;AAAAA;AAAAA,cAKAe,CAAO;AAAA;AAAA;AAAA,GAInB,CC3dO,SAASm9C,IAAiD,CAC/D,MAAO,CACL,QAAS,GACT,mBAAoB,GACpB,KAAM,CACJ,OAAQ,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,IAChD,QAAS,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,IACjD,UAAW,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,IACnD,SAAU,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,IAClD,OAAQ,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,IAChD,SAAU,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,IAClD,OAAQ,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,GAAK,EAEvD,YAAa,EAAC,CAElB,CAgBA,MAAMC,GAAW,CAAC,SAAU,UAAW,YAAa,WAAY,SAAU,WAAY,QAAQ,EAM9F,eAAsBC,GAAiB9gE,EAA0B,CAC/D,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,oBACV,CAAAA,EAAM,oBAAsB,GAC5BA,EAAM,kBAAoB,KAC1B,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,4BAA6B,EAAE,EAEvE,GAAIG,EAAI,aAAc,CACpB,MAAM4gE,EAAK5gE,EAAI,aACTmuD,EAAsC,GAC5C,UAAW4G,KAAO2L,GAAU,CAC1B,MAAMG,EAAQD,EAAG,SAAS7L,CAAG,EACzB8L,GAAU,KACZ1S,EAAK4G,CAAG,EAAI,CAAE,MAAO,QAAS,IAAK,QAAS,OAAQ,IAEpD5G,EAAK4G,CAAG,EAAI,CAAE,MAAO8L,EAAM,MAAO,IAAKA,EAAM,IAAK,OAAQ,GAE9D,CACAhhE,EAAM,iBAAmB,CACvB,QAAS+gE,EAAG,QACZ,mBAAoB5gE,EAAI,mBACxB,KAAAmuD,EACA,YAAa,CAAC,GAAIyS,EAAG,aAAe,EAAG,EAAE,MAAK,CAElD,KAAO,CACL,MAAM/6D,EAAO46D,GAAA,EACb56D,EAAK,mBAAqB7F,EAAI,mBAC9BH,EAAM,iBAAmBgG,CAC3B,CACF,OAASzF,EAAK,CACZP,EAAM,kBAAoB,OAAOO,CAAG,CACtC,SACEP,EAAM,oBAAsB,EAC9B,EACF,CAIA,eAAsBihE,GAAiBjhE,EAA0B,CAC/D,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,WAAaA,EAAM,kBAC/C,CAAAA,EAAM,iBAAmB,GACzBA,EAAM,kBAAoB,KAC1B,GAAI,CACF,MAAMgG,EAAOhG,EAAM,iBACbwH,EAAkE,GACxE,UAAW0tD,KAAO2L,GAAU,CAC1B,MAAM9sE,EAAIiS,EAAK,KAAKkvD,CAAG,EACvB1tD,EAAS0tD,CAAG,EAAInhE,GAAA,MAAAA,EAAG,OAAS,KAAO,CAAE,MAAOA,EAAE,MAAO,IAAKA,EAAE,IAC9D,CAEA,MAAMmtE,EAAW,KAAK,iBAAiB,kBAAkB,SACnDC,EAAe,CACnB,QAASn7D,EAAK,QACd,SAAAk7D,EACA,SAAA15D,EACA,YAAaxB,EAAK,YAAY,OAAS,EAAI,CAAC,GAAGA,EAAK,WAAW,EAAE,OAAS,QAGtES,EAAY,MAAMzG,EAAM,OAAO,QAAQ,aAAc,EAAE,EAC7D,MAAMA,EAAM,OAAO,QAAQ,eAAgB,CACzC,IAAK,KAAK,UAAU,CAClB,SAAU,CAAE,aAAAmhE,EAAc,mBAAoBn7D,EAAK,mBAAmB,CACvE,EACD,SAAUS,EAAS,KACnB,KAAM,wBACP,EAGD,MAAMq6D,GAAiB9gE,CAAK,CAC9B,OAASO,EAAK,CACZP,EAAM,kBAAoB,OAAOO,CAAG,CACtC,SACEP,EAAM,iBAAmB,EAC3B,EACF,wKCvGA,SAASohE,GAAmBr4D,EAAwCs4D,EAAgB,QAA4B,OAC9G,GAAI,CAACt4D,EAAQ,MAAO,GACpB,MAAMi2C,EAAWj2C,EAAO,SACxB,GAAI,CAAC,MAAM,QAAQi2C,CAAQ,QAAU,GAErC,MAAM5zC,EAA6B,GACnC,UAAWhC,KAAW41C,EAAU,CAG9B,GAFI,CAAC51C,GAAW,OAAOA,GAAY,UAE/BA,EAAQ,UAAYi4D,GAAiBj4D,EAAQ,UAAY,aAAc,SAC3E,MAAMzN,EAAQyN,EAAQ,MAGtB,GAFI,CAACzN,GAAS,OAAOA,GAAU,WACdA,EAAM,SAAW,IAAI,gBACtB,WAAY,SAC5B,MAAM2lE,EAAO3lE,EAAM,KAEnB,GADI,CAAC2lE,GAAQ,OAAOA,GAAS,UACzBA,EAAK,OAAS,KAAM,SACxB,MAAMliE,EAAKkiE,EAAK,IAAM,GAClBliE,GACFgM,EAAQ,KAAK,CACX,MAAOhM,EACP,SAAQhL,EAAAgV,EAAQ,OAAR,YAAAhV,EAAc,UAAW,GAClC,CAEL,CAEA,OAAAgX,EAAQ,KAAK,CAACxX,EAAGM,IACXN,EAAE,QAAU,CAACM,EAAE,OAAe,GAC9B,CAACN,EAAE,QAAUM,EAAE,OAAe,EAC3B,CACR,EACMkX,CACT,CAMA,SAASm2D,GACPC,EACAC,EACAJ,EAAgB,QAChB55D,EACgB,CAChB,MAAMi6D,EAAgBtiE,GAAeA,IAAOiiE,GAAiBjiE,IAAO,aAG9DuiE,MAAsB,IACtBC,MAA2B,IACjC,UAAWx4D,KAAWo4D,EAAkB,CAEtC,GADI,CAACp4D,GAAW,OAAOA,GAAY,UAC/B,CAACs4D,EAAat4D,EAAQ,OAAO,EAAG,SACpC,MAAMzN,EAAQyN,EAAQ,MAGtB,GAFI,CAACzN,GAAS,OAAOA,GAAU,WACdA,EAAM,SAAW,IAAI,gBACtB,WAAY,SAC5B,MAAM2lE,EAAO3lE,EAAM,KAEnB,GADI,CAAC2lE,GAAQ,OAAOA,GAAS,UACzBA,EAAK,OAAS,KAAM,SACxB,MAAMliE,EAAKkiE,EAAK,IAAM,GAClBliE,IACEgK,EAAQ,MAAMu4D,EAAgB,IAAIviE,EAAIgK,EAAQ,IAAI,EAClDzN,EAAM,WAAWimE,EAAqB,IAAIxiE,EAAIzD,EAAM,SAAS,EAErE,CAGA,MAAM2E,EAAWkhE,EAAiB,OAAQp4D,GAAY,CAEpD,GADI,CAACA,GAAW,OAAOA,GAAY,UAC/B,CAACs4D,EAAat4D,EAAQ,OAAO,EAAG,MAAO,GAC3C,MAAMzN,EAAQyN,EAAQ,MAGtB,GAFI,CAACzN,GAAS,OAAOA,GAAU,WACdA,EAAM,SAAW,IAAI,gBACtB,WAAY,MAAO,GACnC,MAAM2lE,EAAO3lE,EAAM,KACnB,MAAI,CAAC2lE,GAAQ,OAAOA,GAAS,SAAiB,GACvCA,EAAK,OAAS,IACvB,CAAC,EAGKO,EAA8BJ,EAAO,IAAKj/D,GAAU,CAExD,MAAMs/D,EAAoBr6D,GAAam6D,EAAqB,IAAIp/D,EAAM,KAAK,EACrEu/D,EAAkC,CACtC,QAAS,WACT,KAAM,CAAE,KAAM,KAAM,GAAIv/D,EAAM,MAAM,EAElCs/D,MAA4B,UAAYA,GAC5C,MAAM14D,EAAwB,CAAE,QAASi4D,EAAe,MAAOU,CAAA,EAEzDC,EAAeL,EAAgB,IAAIn/D,EAAM,KAAK,EACpD,OAAIw/D,EACF54D,EAAQ,KAAO44D,EACNx/D,EAAM,SACf4G,EAAQ,KAAO,CAAE,OAAQ,KAEpBA,CACT,CAAC,EAED,MAAO,CAAC,GAAG9I,EAAU,GAAGuhE,CAAW,CACrC,CAEA,eAAsBI,GAAWjiE,EAAoBkiE,EAAuB,CAC1E,GAAI,CAACliE,EAAM,QAAU,CAACA,EAAM,UAAW,OACvC,GAAI,CAACkiE,EAAc,CAEjBliE,EAAM,YAAc,GACpB,MACF,CACA,GAAIA,EAAM,cAAe,OACzBA,EAAM,cAAgB,GACtBA,EAAM,YAAc,KACpB,MAAMlF,EAAUonE,EAChB,GAAI,CACF,MAAM/hE,EAAO,MAAMH,EAAM,OAAO,QAAQ,aAAc,EAAE,EACxDA,EAAM,eAAiBG,EACvB,MAAM4I,EAAS5I,EAAI,OACnBH,EAAM,WAAa8F,GAAkBiD,GAAU,EAAE,EACjD/I,EAAM,YAAcohE,GAAmBr4D,EAAQjO,CAAO,EACtDkF,EAAM,gBAAkB,EAC1B,OAASO,EAAK,CACZP,EAAM,YAAc,OAAOO,CAAG,CAChC,SACEP,EAAM,cAAgB,EACxB,CACF,CAEA,eAAsBmiE,GAASniE,EAAoBq/D,EAAe6C,EAAuBz6D,EAAoB,SAC3G,GAAI,CAACzH,EAAM,QAAU,CAACA,EAAM,UAAW,OACvC,GAAI,CAACkiE,EAAc,CACjBliE,EAAM,YAAc,wBACpB,MACF,CACA,GAAIA,EAAM,aAAc,OACxB,MAAMlF,EAAUonE,EAGhB,IAAIvsD,EAAa0pD,EAAM,QAAQ,cAAe,EAAE,EAChD,GAAI,CAAC1pD,EAAY,CACf3V,EAAM,YAAc,2BACpB,MACF,CAMA,GAJK2V,EAAW,WAAW,GAAG,IAC5BA,EAAa,IAAMA,GAGjB,CAAC,oBAAoB,KAAKA,CAAU,EAAG,CACzC3V,EAAM,YAAc,yEACpB,MACF,CAGA,GAAIA,EAAM,YAAY,KAAMwC,GAAUA,EAAM,QAAUmT,CAAU,EAAG,CACjE3V,EAAM,YAAc,8BACpB,MACF,CAEAA,EAAM,aAAe,GACrBA,EAAM,YAAc,KACpB,GAAI,CACF,MAAM+I,EAASjD,GACb9F,EAAM,cAAc5L,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,SAAU,EAAC,EAEjDotE,EAAoBz4D,EAAO,UAA+B,GAC1Dq5D,EAA+B,CAAC,GAAGpiE,EAAM,YAAa,CAAE,MAAO2V,EAAY,EAC3E0sD,EAAkBd,GAAwBC,EAAkBY,EAAWtnE,EAAS2M,CAAS,EAC/FxB,GAAa8C,EAAQ,CAAC,UAAU,EAAGs5D,CAAe,EAElD,MAAMz7D,GAAWvS,EAAA2L,EAAM,iBAAN,YAAA3L,EAAsB,KACvC,GAAI,CAACuS,EAAU,CACb5G,EAAM,YAAc,yCACpB,MACF,CACA,MAAM1G,EAAMyM,GAAoBgD,CAAM,EACtC,MAAM/I,EAAM,OAAO,QAAQ,aAAc,CAAE,IAAA1G,EAAK,SAAAsN,EAAU,EAG1D,MAAMq7D,GAAWjiE,EAAOkiE,CAAY,CACtC,OAAS3hE,EAAK,CACZP,EAAM,YAAc,OAAOO,CAAG,CAChC,SACEP,EAAM,aAAe,EACvB,CACF,CAEA,eAAsBsiE,GAAYtiE,EAAoBq/D,EAAe6C,EAAuBz6D,EAAoB,SAC9G,GAAI,CAACzH,EAAM,QAAU,CAACA,EAAM,UAAW,OACvC,GAAI,CAACkiE,EAAc,CACjBliE,EAAM,YAAc,wBACpB,MACF,CACA,GAAIA,EAAM,aAAc,OACxB,MAAMlF,EAAUonE,EAGV1/D,EAAQxC,EAAM,YAAY,KAAM9M,GAAMA,EAAE,QAAUmsE,CAAK,EAC7D,GAAI78D,GAAA,MAAAA,EAAO,OAAQ,CACjBxC,EAAM,YAAc,yDACpB,MACF,CAEAA,EAAM,aAAe,GACrBA,EAAM,YAAc,KACpB,GAAI,CACF,MAAM+I,EAASjD,GACb9F,EAAM,cAAc5L,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,SAAU,EAAC,EAEjDotE,EAAoBz4D,EAAO,UAA+B,GAC1Dq5D,EAAYpiE,EAAM,YAAY,OAAQ9M,GAAMA,EAAE,QAAUmsE,CAAK,EAC7DgD,EAAkBd,GAAwBC,EAAkBY,EAAWtnE,EAAS2M,CAAS,EAC/FxB,GAAa8C,EAAQ,CAAC,UAAU,EAAGs5D,CAAe,EAElD,MAAMz7D,GAAWvS,EAAA2L,EAAM,iBAAN,YAAA3L,EAAsB,KACvC,GAAI,CAACuS,EAAU,CACb5G,EAAM,YAAc,yCACpB,MACF,CACA,MAAM1G,EAAMyM,GAAoBgD,CAAM,EACtC,MAAM/I,EAAM,OAAO,QAAQ,aAAc,CAAE,IAAA1G,EAAK,SAAAsN,EAAU,EAG1D,MAAMq7D,GAAWjiE,EAAOkiE,CAAY,CACtC,OAAS3hE,EAAK,CACZP,EAAM,YAAc,OAAOO,CAAG,CAChC,SACEP,EAAM,aAAe,EACvB,CACF,8IChPA,eAAsBuiE,GAAaviE,EAAsBxG,EAAoB,CAC3E,GAAI,GAACwG,EAAM,QAAU,CAACA,EAAM,WAC5B,IAAI,CAACxG,EAAW,CAEdwG,EAAM,gBAAkB,GACxB,MACF,CACA,GAAI,CAAAA,EAAM,gBACV,CAAAA,EAAM,gBAAkB,GACxBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMoe,EAAQpe,EAAM,oBAAoB,OAClCG,EAAMie,EACP,MAAMpe,EAAM,OAAO,QAAQ,iBAAkB,CAAE,MAAAoe,EAAO,UAAA5kB,EAAW,EACjE,MAAMwG,EAAM,OAAO,QAAQ,eAAgB,CAAE,UAAAxG,EAAW,EAC7DwG,EAAM,gBAAkBG,EAAI,SAAW,EACzC,OAASI,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,gBAAkB,EAC1B,GACF,CAEA,eAAsBwiE,GAAWxiE,EAAsBq/D,EAAe3oE,EAAc8C,EAAoB,CAEtG,GADI,CAACwG,EAAM,QAAU,CAACA,EAAM,WACxBA,EAAM,eAAgB,OAE1B,IAAIyiE,EAAkBpD,EAAM,QAAQ,cAAe,EAAE,EACrD,MAAMqD,EAAchsE,EAAK,OACzB,GAAI,CAAC+rE,EAAiB,CACpBziE,EAAM,cAAgB,2BACtB,MACF,CACA,GAAI,CAAC0iE,EAAa,CAChB1iE,EAAM,cAAgB,mBACtB,MACF,CAIA,GAHKyiE,EAAgB,WAAW,GAAG,IACjCA,EAAkB,IAAMA,GAEtB,CAAC,oBAAoB,KAAKA,CAAe,EAAG,CAC9CziE,EAAM,cAAgB,yEACtB,MACF,CAEAA,EAAM,eAAiB,GACvBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,cAAe,CACxC,GAAIyiE,EACJ,KAAMC,EACN,OAAQ,GACR,UAAAlpE,CAAA,CACD,EACDwG,EAAM,oBAAsB,GAC5BA,EAAM,iBAAmB,GACzBA,EAAM,gBAAkB,GACxB,MAAMuiE,GAAaviE,EAAOxG,CAAS,CACrC,OAAS+G,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,eAAiB,EACzB,CACF,CAEA,eAAsB2iE,GAAc3iE,EAAsBZ,EAAY5F,EAAoB,CACxF,GAAI,GAACwG,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,eACV,CAAAA,EAAM,eAAiB,GACvBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,iBAAkB,CAAE,GAAAZ,EAAI,EAC/CY,EAAM,oBAAsBZ,IAAIY,EAAM,kBAAoB,MAC9D,MAAMuiE,GAAaviE,EAAOxG,CAAS,CACrC,OAAS+G,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,eAAiB,EACzB,EACF,CAEA,eAAsB4iE,GACpB5iE,EACAZ,EACA/E,EACAhE,EACAmD,EACA,CACA,GAAI,GAACwG,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,eACV,CAAAA,EAAM,eAAiB,GACvBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,mBAAoB,CAAE,GAAAZ,EAAI,IAAA/E,EAAK,MAAAhE,EAAO,EACjE,MAAMksE,GAAaviE,EAAOxG,CAAS,CACrC,OAAS+G,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,eAAiB,EACzB,EACF,CAEA,eAAsB6iE,GAAmB7iE,EAAsBZ,EAAY/E,EAAab,EAAoB,CAC1G,GAAI,GAACwG,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,eACV,CAAAA,EAAM,eAAiB,GACvBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,sBAAuB,CAAE,GAAAZ,EAAI,IAAA/E,EAAK,EAC7D,MAAMkoE,GAAaviE,EAAOxG,CAAS,CACrC,OAAS+G,EAAK,CACZP,EAAM,cAAgB,OAAOO,CAAG,CAClC,SACEP,EAAM,eAAiB,EACzB,EACF,6LCfA,IAAI8iE,GAA6D,KAC7DC,GAAyD,KACzDC,GAAuD,KAE3D,MAAMC,GAA2C,CAC/C,CAAC,EAAG,+BAA+B,EACnC,CAAC,EAAG,mBAAmB,EACvB,CAAC,GAAI,mCAAmC,EACxC,CAAC,GAAI,iCAAiC,EACtC,CAAC,GAAI,iBAAiB,CACxB,EAEA,SAASC,IAAuB,CAC1BJ,KAAuB,cAAcA,EAAmB,EAAGA,GAAsB,MACjFC,KAAmB,cAAcA,EAAe,EAAGA,GAAkB,MACrEC,KAAkB,aAAaA,EAAc,EAAGA,GAAiB,KACvE,CAEA,SAASG,GAAuBnjE,EAAoD,CAClF,GAAIA,EAAM,WAAW,SAAW,EAChC,MAAO,CACL,WAAYA,EAAM,WAClB,kBAAmBA,EAAM,kBACzB,kBAAoBtJ,GAAiBsJ,EAAM,sBAAsBtJ,CAAI,EACrE,QAASsJ,EAAM,YAAY,QAC3B,SAAUA,EAAM,YAAY,OAC5B,SAAU,IAAMA,EAAM,eACtB,WAAYA,EAAM,aAAa,OAC/B,aAAc,IAAM,CAAEA,EAAM,eAAiB,EAAM,EACnD,iBAAkB,IAAMA,EAAM,sBAAqB,CAEvD,CAGA,SAASojE,GAA4BpjE,EAAoD,CACvF,GAAIA,EAAM,WAAW,SAAW,EAChC,MAAO,CACL,WAAYA,EAAM,WAClB,kBAAmBA,EAAM,kBACzB,kBAAoBtJ,GAAiBsJ,EAAM,sBAAsBtJ,CAAI,EACrE,aAAc,IAAM,CAAEsJ,EAAM,gBAAkB,EAAM,EACpD,QAASA,EAAM,YAAY,QAC3B,SAAUA,EAAM,YAAY,OAC5B,SAAU,IAAMA,EAAM,eACtB,WAAYA,EAAM,aAAa,OAC/B,aAAc,IAAM,CAAEA,EAAM,eAAiB,EAAM,EACnD,iBAAkB,IAAMA,EAAM,sBAAqB,CAEvD,CAEA,SAASqjE,GAAoBrjE,EAAyC,CACpE,MAAMnH,EAAKyqE,GAAyBtjE,CAAK,EACzC,GAAI,CAACnH,EAAI,OACT,MAAM0qE,EAAa1qE,EAAG,OAAO,KAAMjF,GAAMA,EAAE,GAAG,SAAS,QAAQ,GAAKA,EAAE,KAAO,OAAO,EACpF,OAAO2vE,GAAA,YAAAA,EAAY,EACrB,CAEA,SAASC,GAAyBxjE,EAAyC,CACzE,MAAMnH,EAAKyqE,GAAyBtjE,CAAK,EACzC,OAAOnH,GAAA,YAAAA,EAAI,oBAAqB,MAClC,CAEA,SAAS4qE,GAAoBzjE,EAAyC,OACpE,MAAMnH,EAAKyqE,GAAyBtjE,CAAK,EACzC,GAAI,CAACnH,EAAI,OAGT,MAAM0qE,EAAa1qE,EAAG,OAAO,KAAMjF,GAAMA,EAAE,GAAG,SAAS,QAAQ,GAAKA,EAAE,KAAO,OAAO,EACpF,OAAO2vE,GAAA,YAAAA,EAAY,OAAMnvE,EAAAyE,EAAG,OAAO,CAAC,IAAX,YAAAzE,EAAc,GACzC,CAEA,SAASsvE,GAAqB1jE,EAAyC,CACrE,OAAOA,EAAM,mBAAqB,MACpC,CAEA,SAASsjE,GAAyBtjE,EAA2C,CAC3E,OAAKA,EAAM,kBACJA,EAAM,WAAW,KAAMnH,GAAOA,EAAG,OAASmH,EAAM,iBAAiB,GAAK,KADxC,IAEvC,CAEA,MAAM2jE,GAAiB,UACjBC,GAAiB,gBAEvB,SAASC,GAA0B7jE,EAAyC,SAC1E,MAAM8jE,IAAO1vE,EAAA4L,EAAM,aAAN,YAAA5L,EAAkB,SAAU,GACnCoN,EAAS5G,GAAqBoF,EAAM,UAAU,EAC9ClF,GACJ0G,GAAA,YAAAA,EAAQ,YACRnN,EAAA2L,EAAM,aAAN,YAAA3L,EAAkB,YAClB,OACIg6B,EAAQy1C,EAAK,KAAMthE,GAAUA,EAAM,KAAO1H,CAAO,EACjDub,EAAWgY,GAAA,YAAAA,EAAO,SAClB3T,GAAYrE,GAAA,YAAAA,EAAU,aAAaA,GAAA,YAAAA,EAAU,QACnD,GAAKqE,EACL,OAAIipD,GAAe,KAAKjpD,CAAS,GAAKkpD,GAAe,KAAKlpD,CAAS,EAAUA,EACtErE,GAAA,YAAAA,EAAU,SACnB,CAGA,SAAS0tD,GACPt9D,EAC6F,OAC7F,GAAI,CAACA,EAAU,OAAO,KACtB,MAAMyC,GAAW9U,EAAAqS,EAAS,kBAAT,YAAArS,EAA0B,SAC3C,GAAI,CAAC8U,GAAYA,EAAS,SAAW,EAAG,OAAO,KAC/C,MAAMnP,EAAUmP,EAAS,CAAC,EAC1B,MAAO,CACL,QAASnP,EAAQ,SAAW,GAC5B,UAAWA,EAAQ,WAAa,GAChC,OAAQA,EAAQ,QAAU,GAC1B,UAAWA,EAAQ,UAEvB,CAGA,SAASiqE,GAAsBv9D,EAQ7B,OACA,GAAI,CAACA,EAAU,MAAO,CAAE,WAAY,GAAO,QAAS,GAAO,UAAW,GAAO,UAAW,KAAM,aAAc,GAAO,SAAU,KAAM,QAAS,MAC5I,MAAMyC,GAAW9U,EAAAqS,EAAS,kBAAT,YAAArS,EAA0B,SAC3C,GAAI,CAAC8U,GAAYA,EAAS,SAAW,EACnC,MAAO,CAAE,WAAY,GAAO,QAAS,GAAO,UAAW,GAAO,UAAW,KAAM,aAAc,GAAO,SAAU,KAAM,QAAS,MAE/H,MAAMnP,EAAUmP,EAAS,CAAC,EACpBwnD,EAAU32D,EAAQ,SAAW,GAI7B0O,EAAQ1O,EAAQ,MAChBy4B,EAAY/pB,GAAS,KAAQA,EAAM,KAAO,GAAQioD,EACxD,MAAO,CACL,WAAY32D,EAAQ,YAAc,GAClC,QAAA22D,EACA,UAAAl+B,EACA,UAAWz4B,EAAQ,WAAa,KAChC,aAAcA,EAAQ,OAAS,aAAe,EAASA,EAAoC,aAC3F,SAAUA,EAAQ,UAAY,KAC9B,QAASA,EAAQ,SAAW,KAEhC,CAOA,SAASkqE,GAA8BjkE,EAAoC,OACzE,MAAM+I,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OACrC,GAAI,CAAC2U,EAAQ,OAAO,KACpB,MAAMi2C,EAAWj2C,EAAO,SAKxB,GAAI,CAAC,MAAM,QAAQi2C,CAAQ,EAAG,OAAO,KACrC,MAAMklB,EAAcllB,EAAS,KAC1B9qD,GAAA,SAAM,QAAAE,EAAAF,EAAE,QAAF,YAAAE,EAAS,WAAY,cAAcC,EAAAH,EAAE,OAAF,YAAAG,EAAQ,iBAEpD,GAAI,CAAC6vE,EAAa,OAAO,KACzB,MAAMppE,EAAUopE,EAAY,QAE5B,UAAWrrE,KAAMmH,EAAM,WACrB,GAAInH,EAAG,OAAO,KAAMjF,GAAMA,EAAE,KAAOkH,CAAO,EAAG,OAAOjC,EAAG,KAGzD,GAAIiC,IAAY,SAAWA,IAAY,SAAU,CAC/C,MAAMqpE,EAAYnkE,EAAM,WAAW,KAAMnH,GAAOA,EAAG,SAAS,EAC5D,OAAOsrE,GAAA,YAAAA,EAAW,OAAQ,IAC5B,CACA,MAAM/3D,EAAStR,EAAQ,QAAQ,mBAAoB,EAAE,EACrD,GAAIsR,IAAWtR,EAAS,CACtB,MAAMjC,EAAKmH,EAAM,WAAW,KAAMnH,GAAOA,EAAG,OAASuT,CAAM,EAC3D,OAAOvT,GAAA,YAAAA,EAAI,OAAQ,IACrB,CACA,OAAO,IACT,CAOA,SAASurE,GAAmBpkE,EAAuC,CAIjE,MAAMqkE,EAA0B,OAAO,OAAO,IAAI,EAClD,cAAO,iBAAiBA,EAAO,CAC7B,OAAkB,CAAE,IAAK,IAAMrkE,EAAM,OAAkB,IAAK,IAAM,CAAC,GACnE,UAAkB,CAAE,IAAK,IAAMA,EAAM,UAAkB,IAAK,IAAM,CAAC,GACnE,cAAkB,CAAE,IAAK,IAAMA,EAAM,gBAAkB,IAAMzL,GAAM,CAAEyL,EAAM,gBAAkBzL,CAAG,GAChG,YAAkB,CAAE,IAAK,IAAMyL,EAAM,cAAkB,IAAMzL,GAAM,CAAEyL,EAAM,cAAgBzL,CAAG,GAC9F,SAAkB,CAAE,IAAK,IAAMyL,EAAM,WAAkB,IAAMzL,GAAM,CAAEyL,EAAM,WAAazL,CAAG,GAC3F,UAAkB,CAAE,IAAK,IAAMyL,EAAM,YAAkB,IAAMzL,GAAM,CAAEyL,EAAM,YAAczL,CAAG,GAC5F,QAAkB,CAAE,IAAK,IAAMyL,EAAM,UAAkB,IAAMzL,GAAM,CAAEyL,EAAM,UAAYzL,CAAG,GAC1F,gBAAkB,CAAE,IAAK,IAAMyL,EAAM,kBAAmB,IAAMzL,GAAM,CAAEyL,EAAM,kBAAoBzL,CAAG,GACnG,YAAkB,CAAE,IAAK,IAAMyL,EAAM,cAAkB,IAAMzL,GAAM,CAAEyL,EAAM,cAAgBzL,CAAG,GAC9F,aAAkB,CAAE,IAAK,IAAMyL,EAAM,eAAkB,IAAMzL,GAAM,CAAEyL,EAAM,eAAiBzL,CAAG,GAC/F,QAAkB,CAAE,IAAK,IAAMyL,EAAM,UAAkB,IAAMzL,GAAM,CAAEyL,EAAM,UAAYzL,CAAG,GAC1F,UAAkB,CAAE,IAAK,IAAMyL,EAAM,YAAkB,IAAMzL,GAAM,CAAEyL,EAAM,YAAczL,CAAG,GAC5F,UAAkB,CAAE,IAAK,IAAMivE,GAAyBxjE,CAAK,EAAG,IAAK,IAAM,CAAC,EAAE,CAC/E,EACMqkE,CACT,CAEA,SAASC,IAAuC,CAC9C,sBAAsB,IAAM,CAC1B,MAAMr9C,EAAK,SAAS,cAAc,cAAc,EAC5CA,IAAIA,EAAG,UAAYA,EAAG,aAC5B,CAAC,CACH,CAEA,SAASs9C,GAAmBvkE,EAAuC,CACjE,MAAO,CACL,OAAQA,EAAM,OACd,UAAWA,EAAM,UACjB,cAAeA,EAAM,iBAAmB,GACxC,YAAaA,EAAM,eAAiB,KACpC,SAAUA,EAAM,YAAc,GAC9B,UAAWA,EAAM,aAAe,KAChC,QAASA,EAAM,WAAa,GAC5B,gBAAiBA,EAAM,mBAAqB,GAC5C,YAAaA,EAAM,eAAiB,GACpC,aAAcA,EAAM,gBAAkB,GACtC,QAASA,EAAM,WAAa,GAC5B,UAAWA,EAAM,aAAe,KAChC,UAAWwjE,GAAyBxjE,CAAK,EACzC,qBAAuBgsD,GAAQ,CAC7B,MAAMwY,EAAUJ,GAAmBpkE,CAAK,EACnCgtD,GAAmBwX,EAASxY,CAAG,EAAE,KAAK,IAAM,CAC/ChsD,EAAM,gBACNskE,GAAA,CACF,CAAC,CACH,EACA,OAAQ,IAAM,CACZtkE,EAAM,cAAgB,KACtBA,EAAM,WAAa,GACnBA,EAAM,YAAc,KACpBA,EAAM,eACR,EACA,eAAiBoe,GAAU,CACzBpe,EAAM,cAAgBoe,EACtBpe,EAAM,eACR,EACA,mBAAoB,CAACgsD,EAAKoB,IAAe,CACvC,MAAMoX,EAAUJ,GAAmBpkE,CAAK,EACnCmtD,GAAmBqX,EAASxY,EAAKoB,CAAU,EAAE,KAAK,IAAMptD,EAAM,eAAe,CACpF,EACA,UAAW,IAAM,CACf,MAAMwkE,EAAUJ,GAAmBpkE,CAAK,EACnC+sD,GAAkByX,CAAO,EAAE,KAAK,IAAMxkE,EAAM,eAAe,CAClE,EACA,cAAe,IAAMA,EAAM,eAAc,CAE7C,CAEO,SAASykE,GAAUzkE,EAAqB,yBAI7C,GAAIA,EAAM,sBAAwB,CAACA,EAAM,WACvC,OAAO0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,MAoBT,GAAI1iB,EAAM,WAAY,CACpB,GAAI,CAACA,EAAM,UACT,OAAO0iB;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA;AAAAA,QAST,GAAI,CAAC1iB,EAAM,wBACT,OAAOogE,GAAiB,CACtB,SAAWpgE,EAAM,iBAAiB,MAAQ,YAC1C,SAAUA,EAAM,mBAChB,UAAWA,EAAM,UACjB,OAAQA,EAAM,OACd,cAAeA,EAAM,cACrB,gBAAiBA,EAAM,gBACvB,UAAWA,EAAM,iBAAiB,UAClC,cAAeA,EAAM,iBAAiB,cACtC,YAAaA,EAAM,iBAAiB,YACpC,cAAeA,EAAM,iBAAiB,cACtC,gBAAkB9F,GAAuB,OACvC8F,EAAM,qBAAuB9F,EAC7B8F,EAAM,WAAa9F,EACnB8F,EAAM,wBAA0B,GAChCA,EAAM,mBAAqB,QAE3B,MAAMw+D,IAASpqE,EAAA4L,EAAM,mBAAN,YAAA5L,EAAwB,YAAa,GACpD4L,EAAM,YAAc1F,GAAUkkE,EAAQtkE,CAAU,8CAC3C,kFAA6B,KAAK,CAAC,CAAE,gBAAA6F,KAAsB,CAC9DA,EAAgBC,CAAiD,CACnE,CAAC,CACH,EACA,iBAAmBkoB,GAAuD,CACxEloB,EAAM,mBAAqBkoB,CAC7B,EACA,cAAe,IAAM,CAAEloB,EAAM,eAAiB,EAC/C,EAGH,MAAM0kE,GAAYtwE,EAAA4L,EAAM,mBAAN,YAAA5L,EAA8D,SAC1EuwE,EAAe3kE,EAAM,aACrB4kE,EAAgB,CAAC5kE,EAAM,aAAe0kE,EACxC,CAAC,CAAE,KAAM,YAAa,QAAS,CAAC,CAAE,KAAM,OAAQ,KAAMA,EAAU,EAAG,UAAW,GAAK,GAAI,MAAM,QAAQC,CAAY,EAAIA,EAAe,EAAG,EACvIA,EAEJ,OAAOrO,GAAqB,CAC1B,UAAWt2D,EAAM,UACjB,WAAYA,EAAM,WAClB,QAASA,EAAM,YACf,QAASA,EAAM,YACf,SAAU4kE,EACV,aAAc5kE,EAAM,iBACpB,OAAQA,EAAM,WACd,gBAAkBA,EAA4D,oBAC9E,YAAcA,EAAwD,gBACtE,mBAAoBA,EAAM,eAAiB6jE,GAA0B7jE,CAAK,GAAK,KAC/E,MAAOA,EAAM,YACb,MAAOA,EAAM,UACb,QAASA,EAAM,UACf,SAAU,EAAQA,EAAM,UACxB,eAAgBA,EAAM,UAAY,KAAO,gBACzC,MAAOA,EAAM,UACb,cAAeA,EAAM,cACrB,gBAAiBA,EAAM,gBACvB,YAAcA,EAAmD,gBACjE,kBAAoB5F,GAAiB,CACnC4F,EAAM,YAAc5F,EACnB4F,EAAmD,gBAAkB,GAChEA,EAA6D,gBACrE,EACA,UAAW,KACRA,EAAqD,kBACtDugB,GAAA,gCAAAskD,CAAA,QAAO,+BAA2B,uBAAAA,CAAA,2BAAE,KAAK,CAAC,CAAE,gBAAA9kE,KAAsB,CAChEA,EAAgBC,CAAiD,CACnE,CAAC,GAEH,cAAgBnG,GAAS,OACvBmG,EAAM,YAAcnG,EACpB,MAAM2kE,IAASpqE,EAAA4L,EAAM,mBAAN,YAAA5L,EAAwB,YAAa,GACpDsG,GAAkB8jE,EAAQx+D,EAAM,WAAYnG,CAAI,CAClD,EACA,cAAe,IAAMmG,EAAM,gBAC3B,YAAaA,EAAM,gBACnB,oBAAsBnG,GAAUmG,EAAM,gBAAkBnG,EACxD,OAAQ,IAAOmG,EAA6D,iBAC5E,QAAS,KAAYA,EAA8D,mBACnF,cAAgBZ,GAAQY,EAAmE,oBAAoBZ,CAAE,EACjH,aAAewF,GAAW5E,EAA8D,iBAAiB4E,CAAK,EAC9G,WAAY5E,EAAM,mBAClB,QAAUA,EAAqD,mBAC/D,aAAeA,EAAmD,iBAClE,YAAa,KAAYA,EAAkE,sBAAoB,CAChH,CACH,CAIA,GAAIA,EAAM,WAAaA,EAAM,YAAY,QAAS,CAChD,KAAM,CAAE,YAAA8kE,GAAgB9kE,EAGxB,GAAI8kE,EAAY,SAAW,CAACA,EAAY,cACtC,OAAOpP,GAAmB,CACxB,KAAM,GACN,YAAa,GACb,SAAUoP,EAAY,SACtB,MAAOA,EAAY,MACnB,KAAMA,EAAY,KAClB,SAAU,CAACC,EAAsB56D,IAAiB,CAC5CA,GAAO,MAAMnK,EAAM,gBAAgB+kE,EAAc56D,CAAG,CAC1D,EACA,cAAenK,EAAM,mBACrB,sBAAuB,IAAMA,EAAM,sBACnC,cAAeA,EAAM,cACrB,eAAgBA,EAAM,eACtB,iBAAkBA,EAAM,iBACxB,YAAa,CAACjG,EAAS+2B,EAAQC,IAAW/wB,EAAM,gBAAgBjG,EAAS+2B,EAAQC,CAAM,EACxF,EAKH,GAAI,CAAC+zC,EAAY,cAAgB,CAACA,EAAY,eAAiB9kE,EAAM,MACnE,OAAO01D,GAAmB,CACxB,KAAM,GACN,YAAa,GACb,SAAU,GACV,MAAOoP,EAAY,MACnB,KAAMA,EAAY,KAClB,SAAW36D,GAAgBnK,EAAM,mBAAmBmK,CAAG,EACxD,EAIH,GAAI,CAAC26D,EAAY,cAAgB,CAACA,EAAY,eAAiB,CAAC9kE,EAAM,MACpE,cAAO,SAAS,KAAO,SAChByjB,CAEX,CAGA,GAAIzjB,EAAM,MAAO,CACf,MAAMmyB,EAAwB4xC,GAAsB/jE,EAAM,gBAAgB,EACpEglE,IAAmB3iD,GAAAhuB,EAAA2L,EAAM,mBAAN,YAAA3L,EAAwB,kBAAxB,YAAAguB,EAAyC,WAAY,GACxE4iD,EAAOjB,GAAsBhkE,EAAM,gBAAgB,EACnDklE,EAAyBjB,GAA8BjkE,CAAK,EAC5DmlE,EAAyB,SAAY,CACzCnlE,EAAM,gBAAkB,MAAMA,EAAM,OAAQ,QAAmD,kBAAkB,EACjHA,EAAM,sBAAwB,KAC9BA,EAAM,oBAAsB,IAC9B,EACMolE,EAAyB,IAAM,CACnC,MAAMC,EAAY,KAAK,MACvBrlE,EAAM,yBAA2B,EACjCA,EAAM,wBAA0BijE,GAAqB,CAAC,EAAE,CAAC,EACzDjjE,EAAM,wBAA0B,GAChCA,EAAM,eAAiB,KACvBkjE,GAAA,EACAJ,GAAsB,YAAY,IAAM,CACtC,MAAMt5B,GAAW,KAAK,MAAQ67B,GAAa,IAErCt2C,EAAW,KAAK,IAAI,GAAI,IAAM,EAAI,KAAK,IAAI,CAACya,EAAU,EAAE,EAAE,EAChExpC,EAAM,yBAA2B,KAAK,MAAM+uB,CAAQ,EAEpD,IAAInwB,EAAMqkE,GAAqB,CAAC,EAAE,CAAC,EACnC,SAAW,CAACqC,EAAWlrE,CAAI,IAAK6oE,GAC1Bz5B,GAAW87B,IAAW1mE,EAAMxE,GAElC4F,EAAM,wBAA0BpB,CAClC,EAAG,GAAG,CACR,EACA,OAAO2zB,GAAY,CACjB,UAAWvyB,EAAM,UACjB,iBAAgBmiC,GAAA12B,EAAAzL,EAAM,QAAN,YAAAyL,EAAa,SAAb,YAAA02B,EAAqB,WAAY,KACjD,cAAeniC,EAAM,cACrB,YAAaA,EAAM,UAEnB,WAAYA,EAAM,WAClB,YAAaA,EAAM,YACnB,aAAcA,EAAM,aACpB,eAAgBA,EAAM,eACtB,YAAaA,EAAM,YACnB,gBAAiBA,EAAM,gBACvB,iBAAkBA,EAAM,iBACxB,mBAAqB3F,GAAgB2F,EAAM,uBAAuB3F,CAAG,EACrE,kBAAmB,IAAM2F,EAAM,wBAC/B,gBAAiB,SAAY,CAAE,MAAMA,EAAM,sBAAuBA,EAAM,qBAAuB,EAAO,EACtG,qBAAsBA,EAAM,qBAC5B,uBAAwB,IAAM,CAAEA,EAAM,qBAAuB,EAAM,EACnE,sBAAuB,IAAM,CAAEA,EAAM,qBAAuB,EAAO,EAEnE,cAAeA,EAAM,cACrB,SAAUA,EAAM,SAChB,YAAaA,EAAM,YACnB,QAASA,EAAM,QACf,cAAeA,EAAM,cACrB,cAAeA,EAAM,cACrB,iBAAkBA,EAAM,iBACxB,oBAAqBA,EAAM,oBAC3B,sBAAuBA,EAAM,sBAC7B,qBAAsBA,EAAM,qBAC5B,sBAAuBA,EAAM,sBAC7B,sBAAuB,IAAMA,EAAM,4BACnC,uBAAwB,IAAMA,EAAM,6BACpC,0BAA4BzL,GAAc,CAAEyL,EAAM,sBAAwBzL,CAAG,EAC7E,qBAAsB,IAAMyL,EAAM,2BAElC,aAAcA,EAAM,aACpB,qBAAsBA,EAAM,qBAC5B,uBAAwBA,EAAM,uBAC9B,uBAAwBA,EAAM,uBAE9B,sBAAAmyB,EAEA,iBAAA6yC,EACA,0BAA2BhlE,EAAM,0BACjC,sBAAuBA,EAAM,sBAE7B,eAAgBA,EAAM,eACtB,qBAAsBA,EAAM,qBAC5B,qBAAsBA,EAAM,qBAC5B,mBAAoBA,EAAM,mBAE1B,gBAAiBA,EAAM,gBACvB,eAAgBA,EAAM,eACtB,cAAeA,EAAM,cACrB,eAAgBA,EAAM,eACtB,cAAeA,EAAM,cACrB,cAAeA,EAAM,cACrB,oBAAqBA,EAAM,oBAC3B,iBAAkBA,EAAM,iBACxB,cAAe,IAAMA,EAAM,oBAC3B,YAAa,IAAMA,EAAM,kBACzB,sBAAuB,IAAMA,EAAM,4BAEnC,iBAAkBA,EAAM,iBACxB,cAAeA,EAAM,cACrB,cAAeA,EAAM,cACrB,eAAgBA,EAAM,eACtB,qBAAsBA,EAAM,qBAC5B,mBAAoB,IAAMA,EAAM,yBAChC,kBAAmB,IAAMA,EAAM,wBAC/B,6BAA+B5F,GAAiB4F,EAAM,iCAAiC5F,CAAI,EAC3F,eAAgB,IAAM4F,EAAM,qBAC5B,mBAAoB,IAAMA,EAAM,yBAEhC,YAAa,IAAMA,EAAM,kBACzB,iBAAmB09D,GAAiB19D,EAAM,qBAAqB09D,CAAI,EACnE,iBAAmBA,GAAiB19D,EAAM,qBAAqB09D,CAAI,EACnE,iBAAkB,MAAOj2D,GAAuB,CAC9C,MAAMzH,EAAM,oBAAoB,GAAMyH,CAAS,EAE3CzH,EAAM,yBACR,MAAMA,EAAM,mBAAmByH,CAAS,EAExC,MAAMe,EAAaxI,EAAO,EAAI,EAC9BA,EAAM,gBAEV,EACA,iBAAkB,MAAOyH,GAAuB,CAC9C,MAAMzH,EAAM,qBAAqByH,CAAS,CAC5C,EACA,gBAAiB,MAAOA,GAAuB,CAE7C,MAAMzH,EAAM,qBAAqByH,CAAS,EAC1C,MAAMzH,EAAM,oBAAoB,GAAMyH,CAAS,EAE3CzH,EAAM,yBACR,MAAMA,EAAM,mBAAmByH,CAAS,EAExC,MAAMe,EAAaxI,EAAO,EAAI,EAC9BA,EAAM,gBAEV,EACA,gBAAiB,SAAY,CAC3B,MAAMwI,EAAaxI,EAAO,EAAI,EAC9B,MAAMA,EAAM,0BACd,EACA,uBAAwB,IAAMA,EAAM,2BACpC,wBAAyB,IAAMwI,EAAaxI,EAAO,EAAI,EACvD,eAAgB,IAAM,CAEpBA,EAAM,uBAAyB,KAC/BA,EAAM,qBAAuB,KAC7BA,EAAM,uBAAyB,KAC/BA,EAAM,0BAA4B,KAClCA,EAAM,gBACNwI,EAAaxI,EAAO,EAAI,CAC1B,EACA,iBAAkB,IAAMA,EAAM,uBAC9B,wBAA0ByH,GAAczH,EAAM,4BAA4ByH,CAAS,EAEnF,WAAYzH,EAAM,WAClB,kBAAmBA,EAAM,kBACzB,gBAAiBA,EAAM,gBACvB,gBAAiBA,EAAM,gBACvB,iBAAkBA,EAAM,iBACxB,iBAAkBA,EAAM,iBACxB,gBAAiBA,EAAM,gBACvB,uBAAwBA,EAAM,uBAC9B,gBAAiBA,EAAM,gBACvB,qBAAuBmK,GAAgB,CAAEnK,EAAM,gBAAkBmK,CAAK,EACtE,kBAAmB,MAAOzT,EAAM6uE,IAAkB,CAChD,MAAMp7D,EAAMnK,EAAM,gBAClB,MAAMA,EAAM,sBAAsBtJ,EAAM6uE,CAAa,EAEjDp7D,EAAI,MAAM,WAAW,IACvB,MAAME,GAAcrK,EAAOtJ,EAAMyT,CAAG,EACpCnK,EAAM,gBAAkB,GAE5B,EACA,kBAAoBtJ,GAASsJ,EAAM,sBAAsBtJ,CAAI,EAC7D,qBAAuB8uE,GAAW,CAAExlE,EAAM,gBAAkBwlE,CAAQ,EACpE,sBAAwB9uE,GAAS,CAAEsJ,EAAM,iBAAmBtJ,CAAM,EAClE,sBAAwBwP,GAAS,CAAElG,EAAM,iBAAmBkG,CAAM,EAClE,4BAA8BxP,GAAS,CAAEsJ,EAAM,uBAAyBtJ,CAAM,EAE9E,kBAAmBsJ,EAAM,kBACzB,oBAAqBA,EAAM,oBAC3B,uBAAwB,IAAMA,EAAM,6BACpC,wBAAyB,IAAMA,EAAM,8BACrC,kBAAmB,CAACtJ,EAAcmgE,IAAwB72D,EAAM,sBAAsBtJ,EAAMmgE,CAAW,EAEvG,kBAAmB,IAAM,CACvB,MAAMh+D,EAAKyqE,GAAyBtjE,CAAK,EACnCZ,EAAKvG,GAAA,YAAAA,EAAI,kBACT4sE,EAAOrmE,EAAK4lE,EAAiB,KAAMpxE,GAAMA,EAAE,YAAcwL,CAAE,EAAI4lE,EAAiB,CAAC,EACvF,OAAOS,GAAA,YAAAA,EAAM,WAAY,IAC3B,KACA,mBAAoB,SAAY,OAC9B,MAAM5sE,EAAKyqE,GAAyBtjE,CAAK,EACnCZ,EAAKvG,GAAA,YAAAA,EAAI,kBACTkB,EAAUqF,EAAK4lE,EAAiB,KAAMpxE,GAAMA,EAAE,YAAcwL,CAAE,EAAI4lE,EAAiB,CAAC,EAC1F,GAAI,CAACjrE,EAAS,OAEd,MAAM2rE,EADY3rE,EAAQ,UAAY,MAAQA,EAAQ,WAAa,WACrC,WAAa,OAErC4rE,EAAeD,IAAc,OAC/B,CAAE,SAAUA,EAAW,UAAW,CAAC,GAAG,GACtC,CAAE,SAAUA,CAAA,EAChB,GAAI,CACF,MAAMj/D,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACfm/D,GAAMxxE,EAAA2pC,GAAA,YAAAA,EAAK,WAAL,YAAA3pC,EAA2C,SAGjDmU,KAFSq9D,GAAA,YAAAA,EAAI,WAAY,IAEX7rE,EAAQ,SAAS,EACjC,CAAE,SAAU,CAAE,SAAU,CAAE,SAAU,CAAE,CAACA,EAAQ,SAAS,EAAG4rE,CAAA,EAAe,CAAE,EAC5E,CAAE,SAAU,CAAE,SAAUA,EAAa,EACzC,MAAM3lE,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAUuI,EAAK,EACzB,SAAU9B,EAAS,KACnB,KAAM,wBAAwBi/D,CAAS,GACvC,YAAa,GACd,EAED,MAAMl9D,EAAaxI,EAAO,EAAK,CACjC,OAASO,EAAK,CACZ,QAAQ,MAAM,oBAAqBA,CAAG,CACxC,CACF,EAEA,qBAAsB,IAAM,SAC1B,MAAMwI,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BwxE,GAAMvxE,EAAA0U,GAAA,YAAAA,EAAQ,WAAR,YAAA1U,EAA8C,SACpDwE,EAAKyqE,GAAyBtjE,CAAK,EACnCyH,EAAY5O,GAAA,YAAAA,EAAI,kBAChBgtE,GAASD,GAAA,YAAAA,EAAI,WAAY,GACzBE,EAAUr+D,EAAYo+D,EAAMp+D,CAAS,EAAI,OAE/C,OADgBq+D,GAAA,YAAAA,EAAS,eAAeF,GAAA,YAAAA,EAAI,cAAe,WAE7D,KACA,6BAA8B,IAAM,SAClC,MAAM78D,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BwxE,GAAMvxE,EAAA0U,GAAA,YAAAA,EAAQ,WAAR,YAAA1U,EAA8C,SACpDwE,EAAKyqE,GAAyBtjE,CAAK,EACnCyH,EAAY5O,GAAA,YAAAA,EAAI,kBAChBgtE,GAASD,GAAA,YAAAA,EAAI,WAAY,GACzBE,EAAUr+D,EAAYo+D,EAAMp+D,CAAS,EAAI,OAEzCs+D,IADUD,GAAA,YAAAA,EAAS,UAAUF,GAAA,YAAAA,EAAI,SAAU,IACzB,GAAG,EAC3B,OAAOG,GAAA,YAAAA,EAAU,kBAAmB,EACtC,KACA,sBAAuB,SAAY,OACjC,MAAMltE,EAAKyqE,GAAyBtjE,CAAK,EACnCyH,EAAY5O,GAAA,YAAAA,EAAI,kBACtB,GAAI,CACF,MAAM4N,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACfm/D,IAAOxxE,EAAA2pC,GAAA,YAAAA,EAAK,WAAL,YAAA3pC,EAA2C,WAAY,GAC9DyxE,EAASD,EAAG,UAAY,GACxBE,EAAUr+D,EAAYo+D,EAAMp+D,CAAS,EAAI,OACzCu+D,GAAiBF,GAAA,YAAAA,EAAS,cAAeF,EAAG,aAAe,YAC3DK,EAAWD,IAAkB,YAAcA,IAAkB,YAC7DN,EAAYO,EAAW,OAAS,WAEhCC,GAAcD,EAAW,CAAE,IAAK,IAAO,OACvCN,GAAwC,CAAE,YAAaD,CAAA,EACzDQ,QAA0B,OAASA,IACvC,MAAM39D,GAAQu9D,EACV,CAAE,SAAU,CAAE,SAAU,CAAE,SAAU,CAAE,CAACr+D,CAAU,EAAGk+D,EAAA,CAAa,IACjE,CAAE,SAAU,CAAE,SAAUA,GAAa,EACzC,MAAM3lE,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAUuI,EAAK,EACzB,SAAU9B,EAAS,KACnB,KAAM,qBAAqBi/D,CAAS,GACpC,YAAa,GACd,EACD1lE,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,uBAAwBA,CAAG,CAC3C,CACF,EACA,6BAA8B,MAAO4lE,GAA4B,OAC/D,MAAMttE,EAAKyqE,GAAyBtjE,CAAK,EACnCyH,EAAY5O,GAAA,YAAAA,EAAI,kBACtB,GAAI,CACF,MAAM4N,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OAEfo/D,KADOzxE,EAAA2pC,GAAA,YAAAA,EAAK,WAAL,YAAA3pC,EAA2C,WAAY,IAClD,UAAY,GACxB0xE,EAAUr+D,EAAYo+D,EAAMp+D,CAAS,EAAI,OACzC2+D,EAAc,CAAE,IAAK,CAAE,eAAAD,EAAe,EACtC59D,EAAQu9D,EACV,CAAE,SAAU,CAAE,SAAU,CAAE,SAAU,CAAE,CAACr+D,CAAU,EAAG,CAAE,OAAQ2+D,EAAY,CAAE,EAAI,EAChF,CAAE,SAAU,CAAE,SAAU,CAAE,OAAQA,CAAA,EAAc,EACpD,MAAMpmE,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAUuI,CAAK,EACzB,SAAU9B,EAAS,KACnB,KAAM,4BAA4B0/D,EAAiB,iBAAmB,QAAQ,GAC9E,YAAa,GACd,EACDnmE,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,+BAAgCA,CAAG,CACnD,CACF,EAEA,qBAAsBP,EAAM,sBAAwB,GACpD,uBAAwB,IAAM,CAAEA,EAAM,qBAAuB,EAAM,EACnE,wBAAyB,IAAM,CAAEA,EAAM,qBAAuB,EAAO,EAErE,mBAAoBilE,EAAK,WACzB,gBAAiBA,EAAK,QACtB,kBAAmBA,EAAK,UACxB,kBAAmBA,EAAK,UACxB,qBAAsBA,EAAK,aAC3B,gBAAiBA,EAAK,QACtB,iBAAkBjlE,EAAM,iBACxB,sBAAuBA,EAAM,sBAC7B,uBAAAklE,EACA,iBAAkB,IAAM,CAAEllE,EAAM,sBAAwB,EAAM,EAC9D,wBAAyB,SAAY,CACnCA,EAAM,iBAAmB,GACzB,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+I,EAAStC,EAAS,OAClB+6D,GAAoBz4D,GAAA,YAAAA,EAAQ,WAAY,GAOxClQ,EAAKyqE,GAAyBtjE,CAAK,EACnCujE,EAAa1qE,GAAA,YAAAA,EAAI,OAAO,KAAMjF,GAAMA,EAAE,GAAG,SAAS,QAAQ,GAAKA,EAAE,KAAO,SACxEsuE,GAAeqB,GAAA,YAAAA,EAAY,KAAM,QAGjC8C,EAAsB7E,EAAiB,OAC1CttE,GAAA,OAAM,QAAAE,EAAAF,EAAE,QAAF,YAAAE,EAAS,WAAY,aAKxBkyE,EAAmB,CACvB,CACE,QAASpE,EACT,MAAO,CAAE,QAAS,WAAY,KAAM,CAAE,KAAM,KAAM,GAAI,WAAW,EACjE,KAAM,CAAE,cAAe,GAAK,CAC9B,EAGIG,EAAkB,CAAC,GAAGgE,EAAqB,GAAGC,CAAgB,EAEpE,MAAMtmE,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAClB,SAAU,CACR,SAAU,CACR,aAAc,GACd,SAAU,WACV,UAAW,CAAC,GAAG,EACjB,EAEF,SAAUqiE,CAAA,CACX,EACD,SAAU57D,EAAS,KACnB,KAAM,qCAAsC5N,GAAA,YAAAA,EAAI,OAAQ,WACzD,EACDmH,EAAM,sBAAwB,GAE9B,WAAW,IAAM,CACV,QAAQ,IAAI,CAACwI,EAAaxI,EAAO,EAAI,EAAGqG,GAAWrG,CAAK,CAAC,CAAC,EAAE,KAAK,IAAM,CAC1EA,EAAM,iBAAmB,EAC3B,CAAC,CACH,EAAG,GAAI,CACT,MAAQ,CACNA,EAAM,iBAAmB,EAC3B,CACF,EACA,uBAAwB,IAAM,CAAEA,EAAM,sBAAwB,EAAO,EACrE,gBAAiB,SAAY,CAC3BA,EAAM,iBAAmB,GACzBA,EAAM,gBACN,GAAI,CACF,MAAMwI,EAAaxI,EAAO,EAAI,CAChC,SACEA,EAAM,iBAAmB,EAC3B,CACF,EACA,qBAAsB,SAAY,CAChCA,EAAM,iBAAmB,GACzB,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+I,EAAStC,EAAS,OAOlB4/D,IANoBt9D,GAAA,YAAAA,EAAQ,WAAY,IAMD,OAC1C7U,GAAA,OAAM,QAAAE,EAAAF,EAAE,QAAF,YAAAE,EAAS,WAAY,aAE9B,MAAM4L,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAClB,SAAU,CACR,SAAU,CACR,aAAc,GACd,SAAU,WACZ,EAEF,SAAUqmE,CAAA,CACX,EACD,SAAU5/D,EAAS,KACnB,KAAM,sBACP,EACDzG,EAAM,sBAAwB,GAC9B,WAAW,IAAM,CACV,QAAQ,IAAI,CAACwI,EAAaxI,EAAO,EAAI,EAAGqG,GAAWrG,CAAK,CAAC,CAAC,EAAE,KAAK,IAAM,CAC1EA,EAAM,iBAAmB,EAC3B,CAAC,CACH,EAAG,GAAI,CACT,MAAQ,CACNA,EAAM,iBAAmB,EAC3B,CACF,EACA,mBAAoB,SAAY,CAE9BA,EAAM,iBAAmB,GACzB,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+I,EAAStC,EAAS,OAClB+6D,GAAoBz4D,GAAA,YAAAA,EAAQ,WAAY,GAKxClQ,EAAKyqE,GAAyBtjE,CAAK,EACnCujE,EAAa1qE,GAAA,YAAAA,EAAI,OAAO,KAAMjF,GAAMA,EAAE,GAAG,SAAS,QAAQ,GAAKA,EAAE,KAAO,SACxEsuE,GAAeqB,GAAA,YAAAA,EAAY,KAAM,QACjC8C,EAAsB7E,EAAiB,OAC1CttE,GAAA,OAAM,QAAAE,EAAAF,EAAE,QAAF,YAAAE,EAAS,WAAY,aAExBkyE,EAAmB,CACvB,CACE,QAASpE,EACT,MAAO,CAAE,QAAS,WAAY,KAAM,CAAE,KAAM,KAAM,GAAI,WAAW,EACjE,KAAM,CAAE,cAAe,GAAK,CAC9B,EAEF,MAAMliE,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAClB,SAAU,CACR,SAAU,CACR,aAAc,GACd,SAAU,WACV,UAAW,CAAC,GAAG,EACjB,EAEF,SAAU,CAAC,GAAGqmE,EAAqB,GAAGC,CAAgB,EACvD,EACD,SAAU7/D,EAAS,KACnB,KAAM,0BAA2B5N,GAAA,YAAAA,EAAI,OAAQ,WAC9C,EACDmH,EAAM,sBAAwB,GAC9B,WAAW,IAAM,CACV,QAAQ,IAAI,CAACwI,EAAaxI,EAAO,EAAI,EAAGqG,GAAWrG,CAAK,CAAC,CAAC,EAAE,KAAK,IAAM,CAC1EA,EAAM,iBAAmB,EAC3B,CAAC,CACH,EAAG,GAAI,CACT,MAAQ,CACNA,EAAM,iBAAmB,EAC3B,CACF,EAEA,cAAeA,EAAM,cACrB,gBAAkBZ,GAAe,aAE/B,GADAY,EAAM,cAAgBZ,EAClBA,IAAO,gBAAiB,CAC1B,MAAMkG,IAAMlR,EAAA4L,EAAM,kBAAN,YAAA5L,EAAuB,eAAeC,EAAA2L,EAAM,kBAAN,MAAA3L,EAAuB,SAAW,WAAW2L,EAAM,gBAAgB,QAAQ,GAAK,MAC9HsF,GAAO,CAACtF,EAAM,uBAChBA,EAAM,OAAQ,QAA6B,cAAe,CAAE,IAAAsF,EAAK,EAAE,KAAMnF,GAAQ,CAC/EH,EAAM,uBAAwBG,GAAA,YAAAA,EAAK,UAAW,IAChD,CAAC,EAAE,MAAM,IAAM,CAAC,CAAC,CAErB,SAAWf,IAAO,cAAe,CAC/B,MAAMmnE,IAAUlkD,EAAAriB,EAAM,kBAAN,YAAAqiB,EAAuB,cAAa5W,EAAAzL,EAAM,kBAAN,YAAAyL,EAAuB,aAAc,KACnFhE,EAAYzH,EAAM,mBAAqB,KAC7C,GAAIumE,GAAW9+D,EAAW,CACxB,MAAM++D,EAAU,GAAGD,CAAO,gBAAgB,mBAAmB9+D,CAAS,CAAC,GAClEzH,EAAM,qBACTA,EAAM,OAAQ,QAA6B,cAAe,CAAE,IAAKwmE,EAAS,EAAE,KAAMrmE,GAAQ,CACxFH,EAAM,qBAAsBG,GAAA,YAAAA,EAAK,UAAW,IAC9C,CAAC,EAAE,MAAM,IAAM,CAAC,CAAC,CAErB,CACF,CACF,EACA,iBAAkB,IAAM,CAAEH,EAAM,cAAgB,IAAM,EACtD,sBAAuBA,EAAM,uBAAyB,KACtD,oBAAqBA,EAAM,qBAAuB,KAClD,mBAAoB,IAAM,SACxB,MAAMumE,IAAUnyE,EAAA4L,EAAM,kBAAN,YAAA5L,EAAuB,cAAaC,EAAA2L,EAAM,kBAAN,YAAA3L,EAAuB,aAAc,KACnFoT,EAAYzH,EAAM,mBAAqB,KAC7C,MAAI,CAACumE,GAAW,CAAC9+D,EAAkB,KAC5B,GAAG8+D,CAAO,gBAAgB,mBAAmB9+D,CAAS,CAAC,EAChE,KAEA,SAAUzH,EAAM,YAAY,OAC5B,gBAAiBA,EAAM,gBACvB,gBAAiBA,EAAM,gBACvB,WAAYA,EAAM,WAClB,YAAaA,EAAM,YACnB,cAAeA,EAAM,cACrB,qBAAsBA,EAAM,qBAC5B,kBAAmB,IAAM,CAAEA,EAAM,gBAAkB,GAAMA,EAAM,YAAc,KAAMA,EAAM,cAAgB,KAAMA,EAAM,qBAAuB,IAAM,EAClJ,mBAAoB,IAAM,CAAEA,EAAM,gBAAkB,GAAOA,EAAM,YAAc,KAAMA,EAAM,cAAgB,KAAMA,EAAM,qBAAuB,IAAM,EACpJ,aAAc,MAAOw6D,EAAkBpiD,IAAmB,CACxDpY,EAAM,qBAAuBw6D,EAC7Bx6D,EAAM,WAAa,GACnBA,EAAM,YAAc,KACpBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMu6D,GAAWv6D,EAAM,OAASw6D,EAAUpiD,CAAM,EAChD,MAAMquD,EAAa,GAAGjM,CAAQ,aAC9Bx6D,EAAM,cAAgBymE,EACtBzmE,EAAM,qBAAuB,KAC7B,GAAI,CAAEA,EAAM,gBAAkB,MAAM0mE,GAAY1mE,EAAM,MAAO,CAAG,MAAQ,CAAe,CACnFw6D,IAAa,aACf,MAAMx6D,EAAM,wBAEd,WAAW,IAAM,CAAMA,EAAM,gBAAkBymE,IAAYzmE,EAAM,cAAgB,KAAM,EAAG,IAAI,CAChG,OAASO,EAAK,CACZP,EAAM,YAAcO,aAAe,MAAQA,EAAI,QAAU,qBACzDP,EAAM,qBAAuB,IAC/B,SACEA,EAAM,WAAa,EACrB,CACF,EACA,eAAgB,MAAOw6D,GAAqB,CAC1Cx6D,EAAM,qBAAuBw6D,EAC7Bx6D,EAAM,WAAa,GACnBA,EAAM,YAAc,KACpBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAMy6D,GAAaz6D,EAAM,OAASw6D,CAAQ,EAC1C,MAAMiM,EAAa,GAAGjM,CAAQ,eAC9Bx6D,EAAM,cAAgBymE,EACtBzmE,EAAM,qBAAuB,KAC7B,GAAI,CAAEA,EAAM,gBAAkB,MAAM0mE,GAAY1mE,EAAM,MAAO,CAAG,MAAQ,CAAe,CACvF,WAAW,IAAM,CAAMA,EAAM,gBAAkBymE,IAAYzmE,EAAM,cAAgB,KAAM,EAAG,IAAI,CAChG,OAASO,EAAK,CACZP,EAAM,YAAcO,aAAe,MAAQA,EAAI,QAAU,uBACzDP,EAAM,qBAAuB,IAC/B,SACEA,EAAM,WAAa,EACrB,CACF,EACA,gBAAiB,MAAOw6D,EAAkBG,IAAsB,CAC9D36D,EAAM,qBAAuBw6D,EAC7Bx6D,EAAM,WAAa,GACnBA,EAAM,YAAc,KACpBA,EAAM,cAAgB,KACtB,GAAI,CACF,MAAM06D,GAAc16D,EAAM,OAASw6D,EAAUG,CAAQ,EACrD,MAAM8L,EAAa,GAAGjM,CAAQ,IAAIG,EAAW,WAAa,SAAS,GACnE36D,EAAM,cAAgBymE,EACtBzmE,EAAM,qBAAuB,KAC7B,GAAI,CAAEA,EAAM,gBAAkB,MAAM0mE,GAAY1mE,EAAM,MAAO,CAAG,MAAQ,CAAe,CACvF,WAAW,IAAM,CAAMA,EAAM,gBAAkBymE,IAAYzmE,EAAM,cAAgB,KAAM,EAAG,IAAI,CAChG,OAASO,EAAK,CACZP,EAAM,YAAcO,aAAe,MAAQA,EAAI,QAAU,aAAao6D,EAAW,UAAY,QAAQ,OACrG36D,EAAM,qBAAuB,IAC/B,SACEA,EAAM,WAAa,EACrB,CACF,EAEA,eAAgBA,EAAM,eACtB,gBAAiBA,EAAM,gBACvB,eAAgBA,EAAM,eACtB,gBAAiBA,EAAM,gBACvB,mBAAoB,IAAM,CAAEA,EAAM,eAAiB,CAACA,EAAM,eAAgBA,EAAM,gBAAkB,IAAM,EACxG,mBAAqB3F,GAAgB,CAAE2F,EAAM,gBAAkB3F,CAAK,EACpE,mBAAoB,SAAY,CAC9B,MAAMA,EAAM2F,EAAM,gBAAgB,OAClC,GAAK3F,EACL,CAAA2F,EAAM,eAAiB,GACvBA,EAAM,gBAAkB,KACxB,GAAI,CACF,MAAMu6D,GAAWv6D,EAAM,OAAS,YAAa3F,CAAG,EAChD,MAAM2F,EAAM,wBACZA,EAAM,eAAiB,GACvBA,EAAM,gBAAkB,EAC1B,OAASO,EAAK,CACZP,EAAM,gBAAkBO,aAAe,MAAQA,EAAI,QAAU,wBAC/D,SACEP,EAAM,eAAiB,EACzB,EACF,EAEA,eAAgB,IAAM,OACpB,MAAMnH,EAAKmH,EAAM,qBAAqB5L,EAAA4L,EAAM,WAAW,CAAC,IAAlB,YAAA5L,EAAqB,MAC3D,OAAOyE,EAAKmH,EAAM,YAAY,SAAS,KAAMpM,GAAMA,EAAE,KAAOiF,CAAE,EAAI,EACpE,KACA,oBAAqBmH,EAAM,oBAC3B,eAAgBA,EAAM,eACtB,gBAAiBA,EAAM,gBACvB,kBAAmBA,EAAM,kBACzB,sBAAuB,IAAM,CAAEA,EAAM,oBAAsB,GAAMA,EAAM,gBAAkB,KAAMA,EAAM,kBAAoB,IAAM,EAC/H,uBAAwB,IAAM,CAAEA,EAAM,oBAAsB,GAAOA,EAAM,gBAAkB,KAAMA,EAAM,kBAAoB,IAAM,EACjI,iBAAkB,CAAC8wB,EAAuBC,IAAmB,OAC3D,MAAMl4B,EAAKmH,EAAM,qBAAqB5L,EAAA4L,EAAM,WAAW,CAAC,IAAlB,YAAA5L,EAAqB,MACvDyE,GAAImH,EAAM,qBAAqBnH,EAAIi4B,EAAQC,CAAM,CACvD,EAEA,oBAAqB/wB,EAAM,mBAAqB,KAChD,uBAAwBA,EAAM,uBAC9B,yBAA0B,IAAM,CAAEA,EAAM,uBAAyB,EAAM,EACvE,0BAA2B,IAAM,CAAEA,EAAM,uBAAyB,EAAO,EACzE,0BAA2BA,EAAM,0BACjC,4BAA6B,IAAM,CAAEA,EAAM,0BAA4B,EAAM,EAC7E,6BAA8B,IAAM,CAAEA,EAAM,0BAA4B,EAAO,EAC/E,mBAAoB,IAAM,OACxB,MAAM+I,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BuyE,EAAK59D,GAAA,YAAAA,EAAQ,WACnB,OAAO49D,GAAA,YAAAA,EAAI,WAAY,EACzB,KACA,oBAAqB,IAAM,SACzB,MAAM59D,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BuyE,EAAK59D,GAAA,YAAAA,EAAQ,WACblQ,EAAKmH,EAAM,mBAAqB,GAChC4mE,EAAkBD,GAAA,YAAAA,EAAI,gBACtBvrE,IAAQ/G,EAAAuyE,GAAA,YAAAA,EAAkB/tE,KAAlB,YAAAxE,EAAuB,QAAQsyE,GAAA,YAAAA,EAAI,MACjD,OAAQvrE,IAAS,YAAcA,IAAS,SAAYA,EAAO,WAC7D,KACA,oBAAqB,IAAM,OACzB,MAAM2N,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BuyE,EAAK59D,GAAA,YAAAA,EAAQ,WACb89D,EAAYF,GAAA,YAAAA,EAAI,UAChB9tE,EAAKmH,EAAM,mBAAqB,GACtC,OAAQnH,IAAMguE,GAAA,YAAAA,EAAYhuE,MAAQ,EACpC,KACA,uBAAwBmH,EAAM,uBAC9B,2BAA4B,SAAY,OACtC,GAAIA,EAAM,uBAAwB,OAClC,MAAMnH,EAAKmH,EAAM,mBAAqB,GACtC,GAAKnH,EACL,CAAAmH,EAAM,uBAAyB,GAC/B,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACfogE,GAAazyE,EAAA2pC,GAAA,YAAAA,EAAK,aAAL,YAAA3pC,EAA6C,UAEhE,GADgByyE,GAAA,YAAAA,EAAYhuE,GACf,CAEX,MAAM0P,EAAQ,CAAE,WAAY,CAAE,UAAW,CAAE,CAAC1P,CAAE,EAAG,MAAO,EACxD,MAAMmH,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAUuI,CAAK,EACzB,SAAU9B,EAAS,KACnB,KAAM,oCAAoC5N,CAAE,IAC5C,YAAa,GACd,CACH,KAAO,CAEL,MAAM2C,EAAS,MAAMwE,EAAM,OAAQ,QAAQ,2BAA4B,CAAE,UAAWnH,EAAI,EACxF,GAAI2C,GAAA,MAAAA,EAAQ,IAAMA,EAAO,SAAU,CACjC,MAAMsrE,EAAgB,MAAM9mE,EAAM,OAAQ,QAAwB,YAAY,EAC9E,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,UAAW,CAAE,CAACnH,CAAE,EAAG2C,EAAO,SAAS,EAAK,EAC5E,SAAUsrE,EAAc,KACxB,KAAM,mCAAmCjuE,CAAE,IAC3C,YAAa,GACd,CACH,CACF,CACAmH,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,sCAAuCA,CAAG,CAC1D,SACEP,EAAM,uBAAyB,EACjC,EACF,EACA,yBAA0B,MAAO5F,GAAiB,CAChD,MAAMvB,EAAKmH,EAAM,mBAAqB,GACtC,GAAKnH,EACL,GAAI,CACF,MAAM4N,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACzE,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,UAAW,CAAE,CAACnH,CAAE,EAAGuB,CAAA,CAAK,EAAK,EACjE,SAAUqM,EAAS,KACnB,KAAM,sCAAsC5N,CAAE,IAC9C,YAAa,GACd,EACDmH,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,oCAAqCA,CAAG,CACxD,CACF,EACA,+BAAgC,SAAY,CAC1C,GAAIP,EAAM,uBAAwB,OAClC,MAAMnH,EAAKmH,EAAM,mBAAqB,GACtC,GAAKnH,EACL,CAAAmH,EAAM,uBAAyB,GAC/B,GAAI,CACF,MAAMxE,EAAS,MAAMwE,EAAM,OAAQ,QAAQ,2BAA4B,CAAE,UAAWnH,EAAI,EACxF,GAAI2C,GAAA,MAAAA,EAAQ,IAAMA,EAAO,SAAU,CACjC,MAAMiL,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACzE,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,UAAW,CAAE,CAACnH,CAAE,EAAG2C,EAAO,SAAS,EAAK,EAC5E,SAAUiL,EAAS,KACnB,KAAM,qCAAqC5N,CAAE,IAC7C,YAAa,GACd,EACDmH,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,CACF,OAASO,EAAK,CACZ,QAAQ,MAAM,4CAA6CA,CAAG,CAChE,SACEP,EAAM,uBAAyB,EACjC,EACF,EACA,eAAgBA,EAAM,qBACtB,mBAAoB,SAAY,OAC9B,GAAI,CAAAA,EAAM,qBACV,CAAAA,EAAM,qBAAuB,GAC7B,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACf5E,IAAWzN,EAAA2pC,GAAA,YAAAA,EAAK,aAAL,YAAA3pC,EAA6C,WAAY,GAC1E,MAAM4L,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,QAAS,CAAC6B,CAAA,EAAW,EACzD,SAAU4E,EAAS,KACnB,KAAM,iBAAkB5E,EAAsB,WAAZ,SAAsB,GACxD,YAAa,GACd,EACD7B,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,EAC/EA,EAAM,oBAAsB,IAC9B,OAASO,EAAK,CACZ,QAAQ,MAAM,6BAA8BA,CAAG,CACjD,SACEP,EAAM,qBAAuB,EAC/B,EACF,EACA,2BAA4B,MAAO5E,GAA8C,CAC/E,GAAI4E,EAAM,qBAAsB,OAChC,MAAMnH,EAAKmH,EAAM,mBAAqB,GACtC,GAAKnH,EACL,CAAAmH,EAAM,qBAAuB,GAC7B,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACzE,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,gBAAiB,CAAE,CAACnH,CAAE,EAAG,CAAE,KAAMuC,EAAK,CAAE,EAAK,EACjF,SAAUqL,EAAS,KACnB,KAAM,sBAAsBrL,CAAI,GAChC,YAAa,GACd,EACD4E,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,uCAAwCA,CAAG,CAC3D,SACEP,EAAM,qBAAuB,EAC/B,EACF,EAEA,qBAAsB,IAAM,SAC1B,MAAM+I,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BmrE,GAASlrE,EAAA0U,GAAA,YAAAA,EAAQ,aAAR,YAAA1U,EAA4D,MAC3E,OAAQkrE,GAAA,YAAAA,EAAO,OAAmB,EACpC,KACA,oBAAqBv/D,EAAM,oBAC3B,yBAA0B,IAAM,SAC9B,MAAM+I,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BuyE,EAAK59D,GAAA,YAAAA,EAAQ,WACblQ,EAAKmH,EAAM,mBAAqB,GAChC4mE,EAAkBD,GAAA,YAAAA,EAAI,gBACtBnG,IAAWnsE,EAAAuyE,GAAA,YAAAA,EAAkB/tE,KAAlB,YAAAxE,EAAuB,iBAAiBsyE,GAAA,YAAAA,EAAI,eAC7D,OAAO,MAAM,QAAQnG,CAAO,EAAIA,EAAU,CAAC,WAAY,KAAK,CAC9D,KACA,sBAAuB,MAAOuG,EAAkB/5C,IAA4B,CAC1E,GAAIhtB,EAAM,oBAAqB,OAC/B,MAAMnH,EAAKmH,EAAM,mBAAqB,GACtC,GAAKnH,EACL,CAAAmH,EAAM,oBAAsB,GAC5B,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACzE,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAClB,WAAY,CACV,MAAO,CACL,KAAM+mE,GAAY,QAEpB,gBAAiB,CAAE,CAACluE,CAAE,EAAG,CAAE,cAAAm0B,EAAc,CAAE,CAC7C,CACD,EACD,SAAUvmB,EAAS,KACnB,KAAM,qDACN,YAAa,GACd,EACDzG,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,kCAAmCA,CAAG,CACtD,SACEP,EAAM,oBAAsB,EAC9B,EACF,EAEA,kBAAmB,IAAM,OACvB,MAAMnH,EAAKmH,EAAM,kBACjB,OAAKnH,IAEEzE,EADQ+C,GAAA,EACD0B,CAAE,IAAT,YAAAzE,EAAY,cAAe,GAFlB,EAGlB,KACA,sBAAuB,IAAM,OAC3B,MAAMyE,EAAKmH,EAAM,kBACjB,OAAKnH,IAEEzE,EADQ+C,GAAA,EACD0B,CAAE,IAAT,YAAAzE,EAAY,kBAAmB,GAFtB,EAGlB,KACA,cAAe,IAAM,OACnB,MAAMyE,EAAKmH,EAAM,kBACjB,OAAKnH,EAEE,IAAQzE,EADA+C,GAAA,EACO0B,CAAE,IAAT,MAAAzE,EAAY,SAFX,EAGlB,KAEA,kBAAoB4L,EAAoD,kBACxE,qBAAsB,IAAM,SAC1B,MAAMnH,EAAKyqE,GAAyBtjE,CAAK,EACzC,GAAI,CAACnH,EAAI,MAAO,GAChB,MAAMkQ,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/B4yE,GAAc3yE,EAAA0U,GAAA,YAAAA,EAAQ,SAAR,YAAA1U,EAA4C,KAGhE,OAAOwE,EAAG,OAAO,IAAKjF,GAAM,OAC1B,MAAMqzE,EAAW,MAAM,QAAQD,CAAU,EAAIA,EAAW,KAAMtzE,IAAMA,GAAE,KAAOE,EAAE,EAAE,EAAI,OAC/EszE,EAAWD,GAAA,YAAAA,EAAU,MACrBhhD,EAAQ,OAAOihD,GAAa,SAAWA,GAAYA,GAAA,YAAAA,EAAmC,UAAW,KACjG14C,EAAU56B,EAAE,GAAG,SAAS,QAAQ,GAAKA,EAAE,KAAO,QACpD,MAAO,CACL,GAAIA,EAAE,GACN,MAAO46B,EAAU,QAAU,SAC3B,OAAOvI,GAAA,YAAAA,EAAO,SAAU,KACxB,gBAAe7xB,EAAA6yE,GAAA,YAAAA,EAAU,gBAAV,YAAA7yE,EAAyB,SAAU,KAEtD,CAAC,CACH,KACA,0BAA4B4L,EAAsH,kBAAoB,GACtK,gBAAiB,IAAM,WACrB,MAAM+I,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/B+yE,GAAc9kD,GAAAhuB,EAAA0U,GAAA,YAAAA,EAAQ,SAAR,YAAA1U,EAA4C,WAA5C,YAAAguB,EAAkF,aACtG,OAAQ,OAAO8kD,GAAA,YAAAA,EAAW,WAAa,UAAYA,EAAU,SAAYA,EAAU,SAAW,OAChG,KACA,gBAAiB,IAAM,WACrB,MAAMp+D,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/B+yE,GAAc9kD,GAAAhuB,EAAA0U,GAAA,YAAAA,EAAQ,SAAR,YAAA1U,EAA4C,WAA5C,YAAAguB,EAAkF,aACtG,OAAQ,OAAO8kD,GAAA,YAAAA,EAAW,WAAa,UAAYA,EAAU,SAAYA,EAAU,SAAW,MAChG,KACA,sBAAuB,IAAM,CAC1BnnE,EAAoD,kBACnD,CAAEA,EAAoD,iBAC1D,EACA,mBAAoB,MAAOlF,EAAiBssE,IAAqB,CAC/D,GAAI,CACF,MAAM3gE,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACfqT,GAAUikB,GAAA,YAAAA,EAAK,SAAU,GACzB+lC,EAAQ,MAAM,QAAQhqD,EAAO,IAAI,EAAI,CAAC,GAAGA,EAAO,IAAI,EAAI,GAExDle,EAAMkoE,EAAK,UAAWlwE,GAAMA,EAAE,KAAOkH,CAAO,EAClD,GAAIssE,EACExrE,GAAO,EACTkoE,EAAKloE,CAAG,EAAI,CAAE,GAAGkoE,EAAKloE,CAAG,EAAG,MAAOwrE,CAAA,EAEnCtD,EAAK,KAAK,CAAE,GAAIhpE,EAAS,MAAOssE,EAAU,UAGxCxrE,GAAO,EAAG,CACZ,KAAM,CAAE,MAAOpH,EAAG,GAAGuG,CAAA,EAAS+oE,EAAKloE,CAAG,EAClC,OAAO,KAAKb,CAAI,EAAE,QAAU,EAAG+oE,EAAK,OAAOloE,EAAK,CAAC,EAChDkoE,EAAKloE,CAAG,EAAIb,CACnB,CAGF,MAAMwN,EAAQu7D,EAAK,OAAS,EAAI,CAAE,OAAQ,CAAE,KAAAA,CAAA,CAAK,EAAM,CAAE,OAAQ,CAAE,KAAM,KAAK,EAC9E,MAAM9jE,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAUuI,CAAK,EACzB,SAAU9B,EAAS,KACnB,KAAM,SAAS3L,CAAO,YAAYssE,GAAY,SAAS,GACvD,YAAa,GACd,EACDpnE,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,6BAA8BA,CAAG,CACjD,CACF,EACA,sBAAuB,MAAOzF,EAAiBiQ,IAAkB,CAC/D,GAAI,CACF,MAAMtE,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACfqT,GAAUikB,GAAA,YAAAA,EAAK,SAAU,GACzB+lC,EAAQ,MAAM,QAAQhqD,EAAO,IAAI,EAAI,CAAC,GAAGA,EAAO,IAAI,EAAI,GAExDle,EAAMkoE,EAAK,UAAWlwE,GAAMA,EAAE,KAAOkH,CAAO,EAC5CusE,EAAiBt8D,IAAU,MAAQ,OAAYA,EACrD,GAAIs8D,EACEzrE,GAAO,EACTkoE,EAAKloE,CAAG,EAAI,CAAE,GAAGkoE,EAAKloE,CAAG,EAAG,cAAeyrE,CAAA,EAE3CvD,EAAK,KAAK,CAAE,GAAIhpE,EAAS,cAAeusE,EAAgB,UAGtDzrE,GAAO,EAAG,CACZ,KAAM,CAAE,cAAepH,EAAG,GAAGuG,CAAA,EAAS+oE,EAAKloE,CAAG,EAC1C,OAAO,KAAKb,CAAI,EAAE,QAAU,EAAG+oE,EAAK,OAAOloE,EAAK,CAAC,EAChDkoE,EAAKloE,CAAG,EAAIb,CACnB,CAGF,MAAMwN,EAAQu7D,EAAK,OAAS,EAAI,CAAE,OAAQ,CAAE,KAAAA,CAAA,CAAK,EAAM,CAAE,OAAQ,CAAE,KAAM,KAAK,EAC9E,MAAM9jE,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAUuI,CAAK,EACzB,SAAU9B,EAAS,KACnB,KAAM,SAAS3L,CAAO,eAAeusE,GAAkB,SAAS,GAChE,YAAa,GACd,EACDrnE,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,gCAAiCA,CAAG,CACpD,CACF,EACA,uBAAwB,MAAOi6D,GAAqB,CAClD,GAAI,CACF,MAAM/zD,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACzE,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,OAAQ,CAAE,SAAU,CAAE,aAAc,CAAE,SAAAw6D,CAAA,CAAS,CAAE,EAAK,EAC5E,SAAU/zD,EAAS,KACnB,KAAM,4BAA4B+zD,CAAQ,GAC1C,YAAa,GACd,EACDx6D,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,iCAAkCA,CAAG,CACrD,CACF,EACA,uBAAwB,MAAO5D,GAAqB,CAClD,GAAI,CACF,MAAM8J,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACzE,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,OAAQ,CAAE,SAAU,CAAE,aAAc,CAAE,SAAArD,CAAA,CAAS,CAAE,EAAK,EAC5E,SAAU8J,EAAS,KACnB,KAAM,4BAA4B9J,CAAQ,GAC1C,YAAa,GACd,EACDqD,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,CACjF,OAASO,EAAK,CACZ,QAAQ,MAAM,iCAAkCA,CAAG,CACrD,CACF,EACA,aAAcP,EAAM,aACpB,iBAAkBA,EAAM,iBACxB,iBAAkB,IAAM,CACtBA,EAAM,iBAAmB,CAACA,EAAM,gBAClC,EACA,yBAA0B,MAAOxI,GAAkB,OACjD,MAAMqB,EAAKmH,EAAM,kBACjB,GAAI,GAACnH,GAAMmH,EAAM,cACjB,CAAAA,EAAM,aAAe,GACrB,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACf0Q,IAAa/iB,EAAA2pC,GAAA,YAAAA,EAAK,aAAL,YAAA3pC,EAA8CyE,KAAmC,GAC9FyuE,EAAiBnwD,EAAS,OAAqC,GACrE,MAAMnX,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,CAACnH,CAAE,EAAG,CAAE,GAAGse,EAAU,MAAO,CAAE,GAAGmwD,EAAe,YAAa9vE,CAAA,CAAM,CAAE,EAAK,EAC9G,SAAUiP,EAAS,KACnB,KAAM,kBAAkBjP,CAAK,GAC7B,YAAa,GACd,EACDwI,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,EAE/E,MAAMunE,EAASpwE,GAAA,EACVowE,EAAO1uE,CAAE,IAAG0uE,EAAO1uE,CAAE,EAAI,IAC9B0uE,EAAO1uE,CAAE,EAAE,YAAcrB,EACzBiB,GAAoBI,CAAE,CACxB,OAAS0H,EAAK,CACZ,QAAQ,MAAM,8BAA+BA,CAAG,CAClD,SACEP,EAAM,aAAe,EACvB,EACF,EACA,6BAA8B,MAAOxI,GAAkB,OACrD,MAAMqB,EAAKmH,EAAM,kBACjB,GAAI,GAACnH,GAAMmH,EAAM,cACjB,CAAAA,EAAM,aAAe,GACrB,GAAI,CACF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACf0Q,IAAa/iB,EAAA2pC,GAAA,YAAAA,EAAK,aAAL,YAAA3pC,EAA8CyE,KAAmC,GAC9FyuE,EAAiBnwD,EAAS,OAAqC,GACrE,MAAMnX,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,CAACnH,CAAE,EAAG,CAAE,GAAGse,EAAU,MAAO,CAAE,GAAGmwD,EAAe,gBAAiB9vE,CAAA,CAAM,CAAE,EAAK,EAClH,SAAUiP,EAAS,KACnB,KAAM,sBAAsBjP,CAAK,GACjC,YAAa,GACd,EACDwI,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,EAC/E,MAAMunE,EAASpwE,GAAA,EACVowE,EAAO1uE,CAAE,IAAG0uE,EAAO1uE,CAAE,EAAI,IAC9B0uE,EAAO1uE,CAAE,EAAE,gBAAkBrB,EAC7BiB,GAAoBI,CAAE,CACxB,OAAS0H,EAAK,CACZ,QAAQ,MAAM,kCAAmCA,CAAG,CACtD,SACEP,EAAM,aAAe,EACvB,EACF,EACA,kBAAmB,MAAOsd,GAAe,CACvC,MAAMzkB,EAAKmH,EAAM,kBACjB,GAAI,GAACnH,GAAMmH,EAAM,cACjB,CAAAA,EAAM,aAAe,GACrB,GAAI,CACF,MAAMud,EAAS,MAAMD,EAAK,cACpB7d,EAAQ,IAAI,WAAW8d,CAAM,EACnC,IAAI/H,EAAS,GACb,QAAShiB,EAAI,EAAGA,EAAIiM,EAAM,OAAQjM,IAAKgiB,GAAU,OAAO,aAAa/V,EAAMjM,CAAC,CAAC,EAC7E,MAAMgqB,EAAS,KAAKhI,CAAM,EAC1B,MAAMxV,EAAM,OAAQ,QAAQ,mBAAoB,CAC9C,UAAWnH,EACX,KAAM2kB,EACN,SAAUF,EAAK,KAChB,EAED,MAAMiqD,EAASpwE,GAAA,EACVowE,EAAO1uE,CAAE,IAAG0uE,EAAO1uE,CAAE,EAAI,IAC9B0uE,EAAO1uE,CAAE,EAAE,QAAU,eAAe,mBAAmBA,CAAE,CAAC,EAC5D,OAAS0H,EAAK,CACZ,QAAQ,MAAM,4BAA6BA,CAAG,CAChD,SACEP,EAAM,aAAe,EACvB,EACF,EACA,kBAAmB,SAAY,CAC7B,MAAMnH,EAAKmH,EAAM,kBACjB,GAAI,GAACnH,GAAMmH,EAAM,cACjB,CAAAA,EAAM,aAAe,GACrB,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,mBAAoB,CAAE,UAAWnH,EAAI,EACjE,MAAM0uE,EAASpwE,GAAA,EACXowE,EAAO1uE,CAAE,GAAG,OAAO0uE,EAAO1uE,CAAE,EAAE,OACpC,OAAS0H,EAAK,CACZ,QAAQ,MAAM,4BAA6BA,CAAG,CAChD,SACEP,EAAM,aAAe,EACvB,EACF,EACA,aAAc,SAAY,OACxB,MAAMnH,EAAKmH,EAAM,kBACjB,GAAI,GAACnH,GAAMmH,EAAM,cACjB,CAAAA,EAAM,aAAe,GACrB,GAAI,CAEF,MAAMyG,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACnE+9B,EAAMt3B,EAAS,OACf0Q,IAAa/iB,EAAA2pC,GAAA,YAAAA,EAAK,aAAL,YAAA3pC,EAA8CyE,KAAmC,GAC9F,CAAE,MAAO2uE,EAAU,GAAGzsE,GAASoc,EACrC,MAAMnX,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAU,CAAE,WAAY,CAAE,CAACnH,CAAE,EAAG,CAAE,GAAGkC,EAAM,MAAO,KAAK,EAAK,EACtE,SAAU0L,EAAS,KACnB,KAAM,0BACN,YAAa,GACd,EACDzG,EAAM,eAAiB,MAAMA,EAAM,OAAQ,QAAwB,YAAY,EAE/E,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,mBAAoB,CAAE,UAAWnH,EAAI,CACnE,MAAQ,CAA0B,CAElC,MAAM0uE,EAASpwE,GAAA,EACf,OAAOowE,EAAO1uE,CAAE,EAChBJ,GAAoBI,CAAE,CACxB,OAAS0H,EAAK,CACZ,QAAQ,MAAM,sBAAuBA,CAAG,CAC1C,SACEP,EAAM,aAAe,EACvB,EACF,EAEA,gBAAiBA,EAAM,gBACvB,cAAeA,EAAM,cACrB,iBAAkBA,EAAM,iBACxB,eAAgBA,EAAM,eACtB,wBAAyBA,EAAM,wBAC/B,yBAA0BA,EAAM,yBAChC,wBAAyBA,EAAM,wBAC/B,yBAA0BA,EAAM,yBAChC,wBAAyBA,EAAM,wBAC/B,wBAAyBA,EAAM,wBAC/B,kBAAmB,SAAY,CAC7B,GAAI,CAAAA,EAAM,cACV,CAAAA,EAAM,cAAgB,GACtBA,EAAM,iBAAmB,KACzBolE,EAAA,EACA,GAAI,CACF,MAAM5pE,EAAS,MAAMwE,EAAM,OAAQ,QAAyD,kBAAkB,EAC1GxE,EAAO,SAELsnE,KAAuB,cAAcA,EAAmB,EAAGA,GAAsB,MACrF9iE,EAAM,yBAA2B,IACjCA,EAAM,wBAA0B,gCAChCA,EAAM,iBAAmBxE,EAAO,QAEhCunE,GAAkB,YAAY,SAAY,CACxC,GAAI,CACF,MAAMz5D,EAAS,MAAMtJ,EAAM,OAAQ,QAAmD,kBAAkB,EACxGA,EAAM,gBAAkBsJ,EACxBtJ,EAAM,sBAAwB,KAC9BA,EAAM,oBAAsB,KACxBsJ,EAAO,WACT45D,GAAA,EAEAljE,EAAM,iBAAmB,KACzBA,EAAM,wBAA0B,GAChCA,EAAM,wBAA0B,aAChC,WAAW,IAAM,CACfA,EAAM,wBAA0B,GAChCA,EAAM,yBAA2B,EACjCA,EAAM,wBAA0B,GAChCA,EAAM,cAAgB,EACxB,EAAG,IAAI,EAEX,MAAQ,CAER,CACF,EAAG,GAAI,EAEPgjE,GAAiB,WAAW,IAAM,CAChCE,GAAA,EACIljE,EAAM,gBACRA,EAAM,yBAA2B,EACjCA,EAAM,wBAA0B,GAChCA,EAAM,cAAgB,GAE1B,EAAG,GAAO,GACDxE,EAAO,iBAChB0nE,GAAA,EACAljE,EAAM,gBAAkB,MAAMA,EAAM,OAAQ,QAAmD,kBAAkB,EACjHA,EAAM,sBAAwB,KAC9BA,EAAM,oBAAsB,KAC5BA,EAAM,yBAA2B,EACjCA,EAAM,wBAA0B,GAChCA,EAAM,cAAgB,KAEtBkjE,GAAA,EACAljE,EAAM,yBAA2B,EACjCA,EAAM,wBAA0B,GAChCA,EAAM,cAAgB,GAE1B,OAASO,EAAK,CACZ,QAAQ,MAAM,2BAA4BA,CAAG,EAC7C2iE,GAAA,EACAljE,EAAM,eAAkBO,EAAc,SAAW,iCACjDP,EAAM,yBAA2B,EACjCA,EAAM,wBAA0B,GAChCA,EAAM,cAAgB,EACxB,EACF,EACA,wBAAyB,IAAM,CAC7BA,EAAM,eAAiB,IACzB,EACA,uBAAwB,SAAY,OAClC,GAAI,CAAAA,EAAM,cACV,CAAAA,EAAM,cAAgB,GACtBA,EAAM,eAAiB,KACvBA,EAAM,wBAA0B,KAChC,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,wBAAwB,EACpD,MAAMmlE,EAAA,CACR,OAAS5kE,EAAK,CACZ,QAAQ,MAAM,iCAAkCA,CAAG,EACnD,MAAMknE,EAASlnE,GACXnM,EAAAqzE,EAAO,UAAP,MAAArzE,EAAgB,YAClB4L,EAAM,wBAA0BynE,EAAO,QAAQ,WAEjDznE,EAAM,eAAiBynE,EAAO,SAAW,gCAC3C,SACEznE,EAAM,cAAgB,EACxB,EACF,EACA,wBAAyB,SAAY,CACnC,GAAI,CAAAA,EAAM,cACV,CAAAA,EAAM,cAAgB,GACtB,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,yBAAyB,EACrD,MAAMmlE,EAAA,CACR,OAAS5kE,EAAK,CACZ,QAAQ,MAAM,kCAAmCA,CAAG,CACtD,SACEP,EAAM,cAAgB,EACxB,EACF,EACA,wBAAyB,SAAY,OACnC,GAAI,CAAAA,EAAM,cACV,CAAAA,EAAM,cAAgB,GACtBA,EAAM,eAAiB,KACvBA,EAAM,yBAA2B,KACjC,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,yBAAyB,EACrD,MAAMmlE,EAAA,CACR,OAAS5kE,EAAK,CACZ,QAAQ,MAAM,kCAAmCA,CAAG,EACpD,MAAMknE,EAASlnE,GACXnM,EAAAqzE,EAAO,UAAP,MAAArzE,EAAgB,YAClB4L,EAAM,yBAA2BynE,EAAO,QAAQ,WAElDznE,EAAM,eAAiBynE,EAAO,SAAW,yBAC3C,SACEznE,EAAM,cAAgB,EACxB,EACF,EACA,yBAA0B,SAAY,CACpC,GAAI,CAAAA,EAAM,cACV,CAAAA,EAAM,cAAgB,GACtB,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,0BAA0B,EACtD,MAAMmlE,EAAA,CACR,OAAS5kE,EAAK,CACZ,QAAQ,MAAM,mCAAoCA,CAAG,CACvD,SACEP,EAAM,cAAgB,EACxB,EACF,EACA,gCAAiC,IAAM,CACrCA,EAAM,wBAA0B,CAACA,EAAM,uBACzC,EAEA,cAAeA,EAAM,cACrB,kBAAmB,IAAM,CACvBA,EAAM,cAAgB,CAACA,EAAM,cAExBA,EAAM,gBACTA,EAAM,aAAe,GACrBA,EAAM,iBAAmB,KACzBA,EAAM,aAAe,GACrBA,EAAM,UAAY,KAEtB,EACA,WAAYA,EAAM,WAClB,aAAcA,EAAM,aACpB,SAAUA,EAAM,SAChB,UAAWA,EAAM,UACjB,aAAcA,EAAM,aACpB,iBAAkBA,EAAM,iBACxB,WAAY,SAAY,OACtB,GAAI,CAAAA,EAAM,SACV,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CAEF,KAAM,CAACg+D,EAAY0J,CAAY,EAAI,MAAM,QAAQ,IAAI,CACnD1nE,EAAM,OAAQ,QAA8D,WAAW,EACvFA,EAAM,OAAQ,QAA8C,aAAa,EAC1E,EAGD,GAFAA,EAAM,aAAeg+D,EAAW,SAE5B0J,EAAa,WAAaA,EAAa,QAAU,QAAQtzE,EAAA4pE,EAAW,WAAX,MAAA5pE,EAAqB,QAAQ,CACxF,MAAMuH,EAAQqiE,EAAW,SAAS,KAAMzqE,GAAMA,EAAE,MAAM,GACjDyqE,EAAW,SAAS,KAAMzqE,GAAMA,EAAE,OAASm0E,EAAa,IAAI,EAC7D/rE,IAAO+rE,EAAa,OAAS/rE,EAAM,OACzC,CACAqE,EAAM,WAAa0nE,CACrB,OAASnnE,EAAK,CACZ,QAAQ,MAAM,oBAAqBA,CAAG,EACtCP,EAAM,UAAaO,EAAc,SAAW,yBAC9C,SACEP,EAAM,SAAW,EACnB,EACF,EACA,cAAe,SAAY,OACzB,GAAIA,EAAM,UAAY,CAACA,EAAM,iBAAkB,OAC/C,MAAM2nE,EAAiB3nE,EAAM,iBAC7BA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMxE,EAAS,MAAMwE,EAAM,OAAQ,QAAiE,eAAgB,CAClH,KAAM2nE,EACN,SAAU3nE,EAAM,aACjB,EACDA,EAAM,aAAe,GACrBA,EAAM,iBAAmB,KACzBA,EAAM,aAAe,GAErBA,EAAM,WAAa,CACjB,UAAW,GACX,UAAWxE,EAAO,UAClB,KAAMA,EAAO,KACb,OAAQ,KACR,GAAIA,EAAO,GACX,UAAWA,EAAO,KAClB,YAAa,IAEfwE,EAAM,SAAW,GAEjB,GAAI,CACF,KAAM,CAACg+D,EAAY10D,CAAM,EAAI,MAAM,QAAQ,IAAI,CAC7CtJ,EAAM,OAAQ,QAA8D,WAAW,EACvFA,EAAM,OAAQ,QAA8C,aAAa,EAC1E,EACD,GAAIsJ,EAAO,WAAaA,EAAO,QAAU,QAAQlV,EAAA4pE,EAAW,WAAX,MAAA5pE,EAAqB,QAAQ,CAC5E,MAAMuH,EAAQqiE,EAAW,SAAS,KAAMzqE,GAAMA,EAAE,MAAM,GACjDyqE,EAAW,SAAS,KAAMzqE,GAAMA,EAAE,OAAS+V,EAAO,IAAI,EACvD3N,IAAO2N,EAAO,OAAS3N,EAAM,OACnC,CACAqE,EAAM,WAAasJ,CACrB,MAAQ,CAAqB,CAC/B,OAAS/I,EAAK,CACZ,QAAQ,MAAM,uBAAwBA,CAAG,EACzCP,EAAM,UAAaO,EAAc,SAAW,oBAC5CP,EAAM,SAAW,EACnB,CACF,EACA,iBAAkB,SAAY,CAC5B,GAAI,CAAAA,EAAM,SACV,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,iBAAiB,EAC7CA,EAAM,aAAe,GACrBA,EAAM,iBAAmB,KACzBA,EAAM,aAAe,GACrB,MAAMsJ,EAAS,MAAMtJ,EAAM,OAAQ,QAA8C,aAAa,EAC9FA,EAAM,WAAasJ,CACrB,OAAS/I,EAAK,CACZ,QAAQ,MAAM,0BAA2BA,CAAG,EAC5CP,EAAM,UAAaO,EAAc,SAAW,sBAC9C,SACEP,EAAM,SAAW,EACnB,EACF,EACA,aAAc,SAAY,CACxB,GAAI,CAAAA,EAAM,SACV,CAAAA,EAAM,SAAW,GACjBA,EAAM,UAAY,KAClB,GAAI,CACF,MAAMA,EAAM,OAAQ,QAAQ,aAAa,EACzCA,EAAM,aAAe,GACrBA,EAAM,iBAAmB,KACzBA,EAAM,aAAe,GACrB,MAAMsJ,EAAS,MAAMtJ,EAAM,OAAQ,QAA8C,aAAa,EAC9FA,EAAM,WAAasJ,CACrB,OAAS/I,EAAK,CACZ,QAAQ,MAAM,sBAAuBA,CAAG,EACxCP,EAAM,UAAaO,EAAc,SAAW,0BAC9C,SACEP,EAAM,SAAW,EACnB,EACF,EACA,cAAe,IAAM,CACnBA,EAAM,aAAe,GACrBA,EAAM,iBAAmB,KACzBA,EAAM,aAAe,GACrBA,EAAM,UAAY,IACpB,EACA,iBAAmB4nE,GAAwB,CACzC5nE,EAAM,iBAAmB4nE,EACzB5nE,EAAM,aAAe,GACrBA,EAAM,UAAY,IACpB,EACA,qBAAuB4f,GAAqB,CAC1C5f,EAAM,aAAe4f,CACvB,EAEA,YAAa5f,EAAM,YACnB,gBAAiBA,EAAM,gBACvB,iBAAkBA,EAAM,iBACxB,qBAAsBA,EAAM,qBAC5B,iBAAkBA,EAAM,iBACxB,YAAaA,EAAM,YACnB,aAAcA,EAAM,aACpB,eAAgBA,EAAM,eACtB,qBAAsB,IAAM,CAC1BA,EAAM,iBAAmB,CAACA,EAAM,iBAE5BA,EAAM,mBACRA,EAAM,iBAAmB,OAAOA,EAAM,aAAe,EAAE,EACvDA,EAAM,qBAAuBA,EAAM,gBACnCA,EAAM,aAAe,KACrBA,EAAM,eAAiB,KAE3B,EACA,oBAAsB6nE,GAAiB,CACrC7nE,EAAM,iBAAmB6nE,EACzB7nE,EAAM,aAAe,KACrBA,EAAM,eAAiB,IACzB,EACA,wBAA0B8nE,GAAqB,CAC7C9nE,EAAM,qBAAuB8nE,EAC7B9nE,EAAM,aAAe,KACrBA,EAAM,eAAiB,IACzB,EACA,cAAe,SAAY,CACzB,GAAIA,EAAM,YAAa,OACvBA,EAAM,YAAc,GACpBA,EAAM,aAAe,KACrBA,EAAM,eAAiB,KAEvB,MAAM+nE,EAAU/nE,EAAM,iBAAiB,OACjCgoE,EAAU,OAAO,SAASD,EAAS,EAAE,EACrCE,EAAcjoE,EAAM,qBAAqB,OAG/C,GAAI,CAAC+nE,GAAW,CAAC,OAAO,SAASC,CAAO,GAAKA,EAAU,MAAQA,EAAU,MAAO,CAC9EhoE,EAAM,aAAe,+CACrBA,EAAM,YAAc,GACpB,MACF,CAEA,MAAMgwB,EAAcg4C,IAAYhoE,EAAM,YAChCiwB,EAAkBg4C,IAAgBjoE,EAAM,gBAE9C,GAAI,CAACgwB,GAAe,CAACC,EAAiB,CACpCjwB,EAAM,YAAc,GACpB,MACF,CAEA,GAAI,CAEEiwB,GACF,MAAMjwB,EAAM,OAAQ,QAAQ,sBAAuB,CAAE,SAAUioE,EAAa,EAI9E,MAAM1/D,EAAiC,GACnCynB,IACFznB,EAAM,QAAU,CAAE,KAAMy/D,CAAA,GAEtB/3C,IACF1nB,EAAM,UAAY,CAAE,gBAAiB0/D,CAAA,GAIvC,MAAMxhE,EAAW,MAAMzG,EAAM,OAAQ,QAAwB,YAAY,EACzE,MAAMA,EAAM,OAAQ,QAAQ,eAAgB,CAC1C,IAAK,KAAK,UAAUuI,CAAK,EACzB,SAAU9B,EAAS,KACnB,KAAM,CACJupB,EAAc,UAAUg4C,CAAO,GAAK,KACpC/3C,EAAkB,cAAcg4C,CAAW,GAAK,MAChD,OAAO,OAAO,EAAE,KAAK,IAAI,EAC3B,eAAgB,IACjB,EAGDjoE,EAAM,eAAiB,yBAEvB,MAAMkoE,EAAkB,OAAO,SAAS,SAClCC,EAAUl4C,EAAkB,GAAGg4C,CAAW,SAAW,OAAO,SAAS,SACrEG,EAAUp4C,EAAcg4C,EAAUhoE,EAAM,YACxCqoE,EAAS,GAAGH,CAAe,KAAKC,CAAO,IAAIC,CAAO,SAGxD,WAAW,IAAM,CACf,OAAO,SAAS,KAAOC,CACzB,EAAG,IAAI,CACT,OAAS9nE,EAAK,CACZ,QAAQ,MAAM,uBAAwBA,CAAG,EACzCP,EAAM,aAAgBO,EAAc,SAAW,kCAC/CP,EAAM,YAAc,EACtB,CACF,EAEA,QAASojE,GAA4BpjE,CAAK,EAC3C,CACH,CAGA,GAAIA,EAAM,UAAW,CACnB,MAAMsoE,EAAe7E,GAAoBzjE,CAAK,EAC9C,OAAO4lB,GAAY,CACjB,UAAW5lB,EAAM,UACjB,QAASmjE,GAAuBnjE,CAAK,EACrC,QAASA,EAAM,aACf,KAAMA,EAAM,UACZ,KAAMA,EAAM,UACZ,MAAOA,EAAM,WACb,aAAcA,EAAM,kBACpB,cAAeA,EAAM,mBACrB,eAAgBA,EAAM,oBACtB,eAAgBA,EAAM,oBACtB,cAAeA,EAAM,mBACrB,YAAaA,EAAM,iBACnB,aAAcA,EAAM,kBACpB,WAAYA,EAAM,gBAClB,QAASA,EAAM,aACf,WAAYA,EAAM,gBAClB,YAAaA,EAAM,iBACnB,aAAcA,EAAM,kBACpB,UAAW,IAAM,CAAOmc,GAAanc,EAAOsoE,CAAY,EAAQvqD,GAAiB/d,EAAOsoE,CAAY,CAAG,EACvG,UAAW,IAAMtqD,GAAche,EAAOsoE,CAAY,EAClD,aAAepiE,GAAS,CAAElG,EAAM,uBAAyB,KAAMoc,GAAWpc,EAAOkG,EAAMoiE,CAAY,CAAG,EACtG,mBAAqBpiE,GAASqW,GAAiBvc,EAAOkG,EAAMoiE,CAAY,EACxE,YAAcpiE,GAASgY,GAAgBle,EAAOkG,CAAI,EAClD,SAAU,CAACkX,EAASC,IAAUF,GAAYnd,EAAOod,EAASC,EAAOirD,CAAY,EAC7E,YAAa,CAAC5qD,EAAWhnB,IAAS+mB,GAAazd,EAAO0d,EAAWhnB,EAAM4xE,CAAY,EACnF,WAAapiE,GAAS2W,GAAa7c,EAAOkG,EAAMoiE,CAAY,EAC5D,eAAgB,IAAM7rD,GAAkBzc,EAAOsoE,CAAY,EAC3D,SAAWpiE,GAAS,CAAElG,EAAM,uBAAyB,KAAM4d,GAAW5d,EAAOkG,EAAMoiE,CAAY,CAAG,EAClG,kBAAmBtoE,EAAM,uBACzB,YAAckG,GAAS,CAAElG,EAAM,uBAAyBkG,GAAQ,IAAM,EACtE,YAAa,CAACmW,EAAUU,IAAcD,GAAc9c,EAAOqc,EAAUU,EAAWurD,CAAY,EAC5F,YAAatoE,EAAM,iBACnB,cAAeA,EAAM,mBACrB,cAAeA,EAAM,mBACrB,cAAeA,EAAM,mBACrB,SAAUA,EAAM,mBAAqB,GACrC,SAAWoe,GAAU,CACnB,MAAMmqD,EAAcvoE,EAAM,oBAAsBsoE,EAChDnqD,GAAane,EAAOoe,EAAOmqD,CAAW,CACxC,EACA,oBAAsBztE,GAAY,CAChCkF,EAAM,mBAAqBlF,CAC7B,EACA,cAAe,IAAM,CACnBujB,GAAYre,CAAK,CACnB,EACA,oBAAsBoe,GAAU,CAC9Bpe,EAAM,iBAAmBoe,CAC3B,EACD,CACH,CAGA,GAAIpe,EAAM,YACR,OAAOukB,GAAoB,CACzB,UAAWvkB,EAAM,UACjB,OAAQA,EAAM,wBACd,QAASA,EAAM,eACf,MAAOA,EAAM,aACb,UAAWA,EAAM,iBACjB,WAAYA,EAAM,kBAClB,eAAgBA,EAAM,sBACtB,cAAeA,EAAM,qBACrB,QAAS,IAAMwoE,GAAuBxoE,CAAK,EAC3C,OAAQ,IAAMyoE,GAAsBzoE,CAAK,EACzC,cAAe,IAAM+5D,GAAgB/5D,CAAK,EAC1C,mBAAoB,IAAMg6D,GAAiBh6D,CAAK,EAChD,kBAAmB,IAAM85D,GAAgB95D,CAAK,EAC9C,kBAAoB9M,GAAkB,CAEpC,MAAMwoB,EADSxoB,EAAE,OACG,wBAEdw1E,EADWjP,GAAA,EACO,qBAAqBvmE,EAAE,QAAUwoB,EAAK,KAAMxoB,EAAE,QAAUwoB,EAAK,GAAG,EACxFk+C,GAAe55D,EAAO,eAAgB0oE,EAAO,EAAGA,EAAO,EACrDx1E,EAAE,SAAW,EAAI,QAAUA,EAAE,SAAW,EAAI,SAAW,OAC3D,EACA,gBAAkBA,GAAkB,CAElC,MAAMwoB,EADSxoB,EAAE,OACG,wBAEdw1E,EADWjP,GAAA,EACO,qBAAqBvmE,EAAE,QAAUwoB,EAAK,KAAMxoB,EAAE,QAAUwoB,EAAK,GAAG,EACxFk+C,GAAe55D,EAAO,gBAAiB0oE,EAAO,EAAGA,EAAO,CAAC,CAC3D,EACA,kBAAoBx1E,GAAkB,CACpC,MAAMy1E,EAAWlP,GAAA,EACjB,GAAIkP,EAAS,0BAA2B,OAExC,MAAMjtD,EADSxoB,EAAE,OACG,wBACdw1E,EAASC,EAAS,qBAAqBz1E,EAAE,QAAUwoB,EAAK,KAAMxoB,EAAE,QAAUwoB,EAAK,GAAG,EACxFk+C,GAAe55D,EAAO,aAAc0oE,EAAO,EAAGA,EAAO,CAAC,CACxD,EACA,gBAAkBx1E,GAAqB,CACrC,IAAI01E,EAAY,EACZ11E,EAAE,SAAQ01E,GAAa,GACvB11E,EAAE,UAAS01E,GAAa,GACxB11E,EAAE,UAAS01E,GAAa,GACxB11E,EAAE,WAAU01E,GAAa,GAC7B/O,GAAa75D,EAAO,UAAW9M,EAAE,IAAK,CAAE,KAAMA,EAAE,KAAM,UAAW01E,GAAa,OAAW,EACrF11E,EAAE,IAAI,SAAW,GAAG2mE,GAAa75D,EAAO,OAAQ9M,EAAE,IAAK,CAAE,KAAMA,EAAE,IAAK,CAC5E,EACA,cAAgBA,GAAqB,CACnC2mE,GAAa75D,EAAO,QAAS9M,EAAE,IAAK,CAAE,KAAMA,EAAE,KAAM,CACtD,EACD,EAIH,GAAI8M,EAAM,WAAY,CACpB,MAAMkiE,EAAemB,GAAoBrjE,CAAK,EACxC6oE,EAAcrF,GAAyBxjE,CAAK,EAClD,OAAO8yB,GAAiB,CACtB,UAAW9yB,EAAM,UACjB,QAASmjE,GAAuBnjE,CAAK,EACrC,QAASA,EAAM,cACf,OAAQA,EAAM,aACd,OAAQA,EAAM,YACd,MAAOA,EAAM,YACb,SAAUA,EAAM,eAChB,UAAW,IAAMiiE,GAAWjiE,EAAOkiE,CAAY,EAC/C,MAAQ7C,GAAU,CACX8C,GAASniE,EAAOq/D,EAAO6C,EAAc2G,CAAW,EAAE,KAAK,IAAM,CAC3D7oE,EAAM,cAAaA,EAAM,eAAiB,GACjD,CAAC,CACH,EACA,SAAWq/D,GAAUiD,GAAYtiE,EAAOq/D,EAAO6C,EAAc2G,CAAW,EACxE,iBAAmBxyE,GAAU2J,EAAM,2BAA2B3J,CAAK,EACpE,CACH,CAGA,GAAI2J,EAAM,aAAc,CACtB,MAAM8oE,EAASpF,GAAqB1jE,CAAK,EACzC,OAAOyzB,GAAmB,CACxB,UAAWzzB,EAAM,UACjB,QAASmjE,GAAuBnjE,CAAK,EACrC,QAASA,EAAM,gBACf,OAAQA,EAAM,eACd,QAASA,EAAM,gBACf,MAAOA,EAAM,cACb,YAAaA,EAAM,oBACnB,UAAWA,EAAM,kBACjB,YAAaA,EAAM,oBACnB,eAAgBA,EAAM,iBACtB,cAAeA,EAAM,gBACrB,gBAAiBA,EAAM,wBACvB,cAAeA,EAAM,sBACrB,YAAaA,EAAM,oBACnB,cAAeA,EAAM,sBACrB,SAAWoe,GAAWpe,EAAM,oBAAsBoe,EAClD,eAAgB,IAAMmkD,GAAaviE,EAAO8oE,CAAM,EAChD,MAAO,CAACzJ,EAAO3oE,IAAS8rE,GAAWxiE,EAAOq/D,EAAO3oE,EAAMoyE,CAAM,EAC7D,SAAW1pE,GAAOujE,GAAc3iE,EAAOZ,EAAI0pE,CAAM,EACjD,WAAY,CAAC1pE,EAAI/E,EAAKhE,IAAUusE,GAAgB5iE,EAAOZ,EAAI/E,EAAKhE,EAAOyyE,CAAM,EAC7E,cAAe,CAAC1pE,EAAI/E,IAAQwoE,GAAmB7iE,EAAOZ,EAAI/E,EAAKyuE,CAAM,EACrE,eAAiB1pE,GAAO,CACtBY,EAAM,kBAAoBA,EAAM,oBAAsBZ,EAAK,KAAOA,CACpE,EACA,cAAe,IAAOY,EAAM,oBAAsB,GAClD,gBAAiB,IAAM,CACrBA,EAAM,oBAAsB,GAC5BA,EAAM,iBAAmB,GACzBA,EAAM,gBAAkB,EAC1B,EACA,uBAAyB3J,GAAU2J,EAAM,6BAA6B3J,CAAK,EAC3E,sBAAwBA,GAAU2J,EAAM,4BAA4B3J,CAAK,EACzE,UAAW,IAAMksE,GAAaviE,EAAO8oE,CAAM,EAC3C,oBAAsB1pE,GAAQY,EAAM,wBAA0BZ,EAC9D,qBAAsB,IAAOY,EAAM,wBAA0B,KAC7D,eAAiBZ,GAAO,CACtBY,EAAM,sBAAwBZ,EAC9BY,EAAM,oBAAsB,GAC5BA,EAAM,sBAAwB,EAChC,EACA,gBAAiB,IAAM,CACrBA,EAAM,sBAAwB,KAC9BA,EAAM,oBAAsB,GAC5BA,EAAM,sBAAwB,EAChC,EACA,oBAAsB3J,GAAW2J,EAAM,oBAAsB3J,EAC7D,sBAAwBA,GAAW2J,EAAM,sBAAwB3J,EACjE,iBAAkB,IAAM,CACtB,MAAM+I,EAAKY,EAAM,sBACX3F,EAAM2F,EAAM,oBAAoB,OAClC,CAACZ,GAAM,CAAC/E,IACZuoE,GAAgB5iE,EAAOZ,EAAI/E,EAAK2F,EAAM,sBAAuB8oE,CAAM,EACnE9oE,EAAM,sBAAwB,KAC9BA,EAAM,oBAAsB,GAC5BA,EAAM,sBAAwB,GAChC,EACD,CACH,CAGA,GAAIA,EAAM,SAAU,CAClB,MAAM+oE,EAAqB/oE,EAAM,UAAY,KAAO,6BAC9CgpE,EAAqBnF,GAA0B7jE,CAAK,EACpDipE,EAAgBjpE,EAAM,eAAiBgpE,GAAsB,KAC7DE,GAAgB,IAAM,OAC1B,MAAMngE,GAAS3U,EAAA4L,EAAM,iBAAN,YAAA5L,EAAsB,OAC/BuyE,EAAK59D,GAAA,YAAAA,EAAQ,WACnB,OAAO49D,GAAA,YAAAA,EAAI,WAAY,EACzB,KACA,OAAO/Z,GAAe,CACpB,UAAW5sD,EAAM,UACjB,QAASmjE,GAAuBnjE,CAAK,EACrC,kBAAmBkpE,EACnB,oBAAqBlpE,EAAM,mBAAqB,OAChD,YAAaA,EAAM,aAAe,OAClC,oBAAsB0Y,GAAqB,CAEzC,GADA1Y,EAAM,YAAc0Y,EAChBA,IAAQ,YAAc,CAAC1Y,EAAM,WAAaA,EAAM,gBAAgB,SAAW,EAAG,CAChF,MAAMwkE,EAAUJ,GAAmBpkE,CAAK,EACnC+sD,GAAkByX,CAAO,EAAE,KAAK,IAAMxkE,EAAM,eAAe,CAClE,CACF,EACA,cAAeukE,GAAmBvkE,CAAK,EACvC,WAAYA,EAAM,WAClB,mBAAqBnG,GAAS,CAE5B,MAAMhB,EAAKmH,EAAM,mBAAqB,GACtCrF,GAAA,EACAR,GAAUtB,EAAImH,EAAM,WAAYA,EAAM,WAAW,EACjDA,EAAM,WAAanG,EACnBmG,EAAM,YAAc1F,GAAUzB,EAAIgB,CAAI,EACtCmG,EAAM,gBAAkB,GACxBA,EAAM,WAAa,KAClBA,EAAwD,gBAAkB,KAC1EA,EAAmD,gBAAkB,GACrEA,EAA4D,oBAAsB,KACnFA,EAAM,UAAY,KAClBA,EAAM,UAAY,GACjBA,EAAqD,kBACrDA,EAAqD,kBACtDA,EAAM,cAAc,CAClB,GAAGA,EAAM,SACT,WAAYnG,EACZ,qBAAsBA,CAAA,CACvB,EACImG,EAAM,wBACND,GAAgBC,CAAK,EACrBkiB,GAAkBliB,CAAK,CAC9B,EACA,aAAcA,EAAM,SAAS,kBAAoB,GACjD,aAAeA,EAAyD,iBACxE,YAAcA,EAAmD,gBACjE,kBAAoB5F,GAAiB,CACnC4F,EAAM,YAAc5F,EACnB4F,EAAmD,gBAAkB,GAChEA,EAA6D,gBACrE,EACA,QAASA,EAAM,YACf,QAASA,EAAM,YACf,iBAAmBA,EAAmD,iBACtE,mBAAoBipE,EACpB,SAAUjpE,EAAM,aAChB,aAAcA,EAAM,iBACpB,OAAQA,EAAM,WACd,gBAAkBA,EAA4D,oBAC9E,YAAcA,EAAwD,gBACtE,MAAOA,EAAM,YACb,MAAOA,EAAM,UACb,QAASA,EAAM,UACf,eAAgB+oE,EAChB,MAAO/oE,EAAM,UACb,SAAUA,EAAM,eAChB,UAAW,GACX,UAAW,IAAM,CACdA,EAAqD,kBACtD,MAAMmpE,EAAM,KAAK,IAAInpE,EAAM,aAAa,OAAS,GAAIF,EAAc,EACnE,OAAO,QAAQ,IAAI,CAACC,GAAgBC,EAAO,CAAE,MAAOmpE,EAAK,EAAGjnD,GAAkBliB,CAAK,CAAC,CAAC,CACvF,EACA,kBAAmB,IAAM,CAAC,EAC1B,aAAe4E,GAAW5E,EAA8D,iBAAiB4E,CAAK,EAC9G,WAAY5E,EAAM,mBAClB,QAAUA,EAAqD,mBAC/D,aAAeA,EAAmD,iBAClE,YAAa,KAAYA,EAAkE,uBAC3F,cAAgBnG,GAAS,CACvBmG,EAAM,YAAcnG,EACpBa,GAAkBsF,EAAM,mBAAqB,GAAIA,EAAM,WAAYnG,CAAI,CACzE,EACA,cAAe,IAAMmG,EAAM,gBAC3B,YAAaA,EAAM,gBACnB,oBAAsBnG,GAAUmG,EAAM,gBAAkBnG,EACxD,OAAQ,IAAOmG,EAA6D,iBAC5E,SAAU,EAAQA,EAAM,UACxB,QAAS,KAAYA,EAA8D,mBACnF,cAAgBZ,GAAQY,EAAmE,oBAAoBZ,CAAE,EACjH,aAAc,IACXY,EAA4G,eAAe,OAAQ,CAAE,aAAc,GAAM,EAC5J,YAAcA,EAA8C,YAC5D,eAAiBA,EAAuD,eACxE,aAAeA,EAAqD,aACpE,WAAaA,EAA4C,WACzD,cAAgBxC,GAAqBwC,EAAgE,kBAAkBxC,CAAO,EAC9H,eAAgB,IAAOwC,EAAwD,qBAC/E,mBAAqBupC,GAAmBvpC,EAAqE,uBAAuBupC,CAAK,EACzI,cAAevpC,EAAM,cACrB,gBAAiBA,EAAM,gBACxB,CACH,CAGA,OAAIA,EAAM,aACDy1D,GAAmB,CACxB,UAAWz1D,EAAM,UACjB,QAASmjE,GAAuBnjE,CAAK,EACrC,UAAWA,EAAM,YACjB,YAAc0Y,GAAQ,CACnB1Y,EAA6C,YAAc0Y,EAExDA,IAAQ,QAAa1Y,EAAM,WAC3B0Y,IAAQ,UAAeX,GAAW/X,EAAO,CAAE,cAAe,GAAM,EAChE0Y,IAAQ,iBAAsBooD,GAAiB9gE,CAAK,EACpD0Y,IAAQ,SACM1Y,EAA4C,aAC7C,UACR6b,GAAgB7b,EAA2D,CAAE,MAAO,GAAM,EAE1FmL,GAASnL,EAAO,CAAE,MAAO,GAAM,EAG1C,EACA,UAAW,CACT,QAASA,EAAM,YACf,OAAQA,EAAM,WACd,KAAMA,EAAM,SACZ,MAAOA,EAAM,UACb,KAAMA,EAAM,SACZ,KAAMA,EAAM,SACZ,UAAUopE,GAAAhR,EAAAp4D,EAAM,mBAAN,YAAAo4D,EAAwB,cAAxB,MAAAgR,EAAqC,OAC3CppE,EAAM,iBAAiB,YAAY,IAAKwC,GAAUA,EAAM,EAAE,IAC1D6mE,EAAArpE,EAAM,mBAAN,YAAAqpE,EAAwB,eAAgB,GAC5C,gBAAeC,EAAAtpE,EAAM,mBAAN,YAAAspE,EAAwB,gBAAiB,GACxD,cAAaC,EAAAvpE,EAAM,mBAAN,YAAAupE,EAAwB,cAAe,GACpD,UAAW,IAAM,OACf,MAAM1wE,EAAKyqE,GAAyBtjE,CAAK,EACzC,QAAO5L,EAAAyE,GAAA,YAAAA,EAAI,SAAJ,YAAAzE,EAAY,IAAKR,GAAMA,EAAE,MAAO,EACzC,KACA,UAAWoM,EAAM,cACjB,KAAMA,EAAM,SACZ,kBAAmBA,EAAM,kBACzB,oBAAqB,IAAM,CAAEA,EAAM,kBAAoB,EAAM,EAC7D,qBAAsB,IAAM,CAAEA,EAAM,kBAAoB,GAAOA,EAAM,cAAgB,IAAM,EAC3F,YAAaA,EAAM,gBACnB,UAAWA,EAAM,cACjB,aAAe0H,GAAQ,CAAE1H,EAAM,gBAAkB0H,EAAI,GAAII,GAAa9H,EAAO0H,EAAI,EAAE,CAAG,EACtF,cAAe,IAAM,CAAE1H,EAAM,gBAAkB,IAAM,EACrD,OAAS0H,GAAQ,CACf1H,EAAM,SAAWiI,GAAmBP,CAAG,EACvC1H,EAAM,cAAgB0H,EAAI,GAC1B1H,EAAM,gBAAkB,IAC1B,EACA,WAAY,IAAM,CAChB,MAAMsI,EAAQtI,EAAM,cACfsI,GACAD,GAAcrI,EAAOsI,CAAK,EAAE,KAAK,IAAM,CAC1CtI,EAAM,cAAgB,IACxB,CAAC,CACH,EACA,aAAeuI,GAAWvI,EAAM,SAAW,CAAE,GAAGA,EAAM,SAAU,GAAGuI,CAAA,EACnE,UAAW,IAAMvI,EAAM,WACvB,MAAO,IAAM,CAAOuH,GAAWvH,CAAK,EAAE,KAAK,IAAM,CAAEA,EAAM,kBAAoB,EAAO,CAAC,CAAG,EACxF,SAAU,CAAC0H,EAAKE,IAAYD,GAAc3H,EAAO0H,EAAKE,CAAO,EAC7D,MAAQF,GAAQG,GAAW7H,EAAO0H,CAAG,EACrC,SAAWA,GAAQ,CAAE1H,EAAM,oBAAsB,KAAMgI,GAAchI,EAAO0H,CAAG,CAAG,EAClF,gBAAiB1H,EAAM,oBACvB,YAAcsI,GAAU,CAAEtI,EAAM,oBAAsBsI,GAAS,IAAM,EACrE,WAAaA,GAAUR,GAAa9H,EAAOsI,CAAK,EAChD,cAAetI,EAAM,kBACrB,gBAAiBA,EAAM,oBACvB,UAAWA,EAAM,cACjB,gBAAiB,IAAM,CAAEA,EAAM,kBAAoB,KAAMA,EAAM,oBAAsB,GAAIA,EAAM,cAAgB,IAAM,GAEvH,YAAa,CACX,QAASA,EAAM,cACf,OAAQA,EAAM,aACd,MAAOA,EAAM,YACb,OAAQA,EAAM,aACd,WAAYA,EAAM,iBAClB,MAAOA,EAAM,WACb,SAAUA,EAAM,cAChB,QAASA,EAAM,cACf,OAAQA,EAAM,YACd,UAAWA,EAAM,eACjB,SAAUA,EAAM,cAChB,QAASA,EAAM,aACf,WAAYA,EAAM,mBAClB,QAASA,EAAM,aACf,OAAQA,EAAM,YACd,eAAiBnG,GAAUmG,EAAM,aAAenG,EAChD,mBAAqBA,GAAUmG,EAAM,iBAAmBnG,EACxD,UAAW,IAAMke,GAAW/X,EAAO,CAAE,cAAe,GAAM,EAC1D,SAAU,CAAC3F,EAAKuN,IAAYsQ,GAAmBlY,EAAO3F,EAAKuN,CAAO,EAClE,OAAQ,CAACvN,EAAKhE,IAAU2hB,GAAgBhY,EAAO3F,EAAKhE,CAAK,EACzD,UAAYgE,GAAQ8d,GAAgBnY,EAAO3F,CAAG,EAC9C,UAAW,CAAC4d,EAAUvhB,EAAM4hB,IAC1BD,GAAarY,EAAOiY,EAAUvhB,EAAM4hB,CAAS,EAC/C,aAAe5hB,GAAS6hB,GAAgBvY,EAAOtJ,CAAI,EACnD,cAAe,IAAM8hB,GAAiBxY,CAAK,EAC3C,YAAc0Y,GAAQD,GAAkBzY,EAAO0Y,CAAG,EAClD,UAAW,IAAMC,GAAkB3Y,CAAK,EACxC,WAAY,IAAM4Y,GAAmB5Y,CAAK,EAC1C,cAAgB8Y,GAAUD,GAAY7Y,EAAO8Y,CAAK,EAClD,eAAiBA,GAAUC,GAAa/Y,EAAO8Y,CAAK,EACpD,cAAgBpiB,GAASyiB,GAAYnZ,EAAOtJ,CAAI,EAChD,UAAW,IAAMsiB,GAAahZ,CAAK,EACnC,gBAAiB,CAACuuD,EAAOl4D,IAAU,CACjC2J,EAAM,aAAe,CAAE,GAAGA,EAAM,aAAc,CAACuuD,CAAK,EAAGl4D,CAAA,CACzD,EACA,qBAAsB,CAACK,EAAMkjB,IAAiBD,GAAmB3Z,EAAOtJ,EAAMkjB,CAAY,EAC1F,SAAWljB,GAASqjB,GAAY/Z,EAAOtJ,CAAI,EAC3C,YAAcA,GAAS0iB,GAAUpZ,EAAOtJ,CAAI,EAC5C,aAAe4iB,GAAcD,GAAgBrZ,EAAOsZ,CAAS,EAC7D,YAAa,CAACG,EAASjc,IAAYgc,GAAoBxZ,EAAOyZ,EAASjc,CAAO,EAC9E,UAAYkb,GAAQgB,GAAW1Z,EAAO0Y,CAAG,EACzC,YAAa1Y,EAAM,kBACnB,oBAAsBnG,GAAUmG,EAAM,kBAAoBnG,EAC1D,eAAgB,CAACoe,EAAU6B,IAAWD,GAAkB7Z,EAAOiY,EAAU6B,CAAM,GAEjF,UAAW,CACT,WAAa9Z,EAA0D,WACvE,QAASA,EAAM,YAAY,QAAU,CAACA,EAAM,YAAY,QACxD,eAAiB0Y,GAAQ,CACtB1Y,EAA0D,WAAa0Y,EACpEA,IAAQ,UACLmD,GAAgB7b,EAA2D,CAAE,MAAO,GAAM,EAE1FmL,GAASnL,EAAO,CAAE,MAAO,GAAM,CAExC,EACA,iBAAkB,CAChB,QAAUA,EAAqD,mBAC/D,MAAQA,EAAyD,iBACjE,QAAUA,EAAsE,mBAChF,OAASA,EAAqD,kBAC9D,WAAaA,EAAuD,sBACpE,YAAcA,EAAiF,uBAC/F,aAAeA,EAA0E,wBACzF,WAAaA,EAAwD,sBACrE,cAAgBA,EAA2D,yBAC3E,YAAcA,EAA6D,uBAC3E,mBAAqBnG,GAAWmG,EAAuD,sBAAwBnG,EAC/G,aAAc,CAACq5D,EAAMtrD,IAAY,CAC/B,MAAMzU,EAAI6M,EACV7M,EAAE,uBAAyB,CAAE,GAAGA,EAAE,uBAAwB,CAAC+/D,CAAI,EAAGtrD,CAAA,CACpE,EACA,cAAe,CAACymB,EAAOzmB,IAAY,CACjC,MAAMzU,EAAI6M,EACV7M,EAAE,wBAA0B,CAAE,GAAGA,EAAE,wBAAyB,CAACk7B,CAAK,EAAGzmB,CAAA,CACvE,EACA,mBAAqB/N,GAAWmG,EAAwD,sBAAwBnG,EAChH,cAAe,IAAM,CACnB,MAAM1G,EAAI6M,EACV7M,EAAE,yBAA2B,CAACA,EAAE,wBAClC,EACA,eAAiBiM,GAAO,CACtB,MAAMjM,EAAI6M,EACJnG,EAAO,IAAI,IAAI1G,EAAE,sBAAsB,EACzC0G,EAAK,IAAIuF,CAAE,EAAGvF,EAAK,OAAOuF,CAAE,EAAQvF,EAAK,IAAIuF,CAAE,EACnDjM,EAAE,uBAAyB0G,EAC3B1G,EAAE,eACJ,EACA,UAAW,KAAW0oB,GAAgB7b,EAA2D,CAAE,MAAO,GAAM,GAChH,SAAU,CAAC7B,EAAOhB,IAAW6C,EAA8E,kBAAkB7B,EAAOhB,CAAK,EACzI,SAAWyH,GAAW5E,EAAqE,wBAAwB4E,CAAK,GAE1H,QAAS5E,EAAM,YACf,MAAOA,EAAM,UACb,KAAMA,EAAM,SACZ,QAASA,EAAM,YACf,WAAYA,EAAM,eAClB,aAAcA,EAAM,iBACpB,WAAYA,EAAM,eAClB,cAAgBA,EAAoD,kBACpE,UAAWA,EAAM,cACjB,aAAcA,EAAM,SACpB,eAAgBA,EAAM,mBACtB,aAAemzD,GAAwB,CACrCnzD,EAAM,SAAWmzD,EACZhoD,GAASnL,EAAO,CAAE,MAAO,GAAM,CACtC,EACA,mBAAqBnG,GAAUmG,EAAM,eAAiBnG,EACtD,cAAe,CAACkR,EAAOnD,IAAY,CACjC5H,EAAM,iBAAmB,CAAE,GAAGA,EAAM,iBAAkB,CAAC+K,CAAK,EAAGnD,CAAA,CACjE,EACA,mBAAqB/N,GAAUmG,EAAM,eAAiBnG,EACtD,cAAe,IAAM,CACnB,MAAM1G,EAAI6M,EACV7M,EAAE,kBAAoB,CAACA,EAAE,iBAC3B,EACA,UAAW,IAAMgY,GAASnL,EAAO,CAAE,MAAO,GAAM,EAChD,SAAU,CAAC7B,EAAOhB,IAAW6C,EAA8E,kBAAkB7B,EAAOhB,CAAK,EACzI,SAAWyH,GAAW5E,EAA8D,iBAAiB4E,CAAK,GAE5G,kBAAmB,CACjB,QAAU5E,EAAsD,oBAChE,MAAQA,EAA0D,kBAClE,KAAOA,EAAmD,iBAC1D,KAAOA,EAAuG,iBAC9G,aAAeuI,GAAU,CACvB,MAAMpV,EAAI6M,EACV7M,EAAE,iBAAmB,CAAE,GAAGA,EAAE,iBAAkB,GAAGoV,CAAA,CACnD,EACA,YAAa,CAAC2sD,EAAK3G,EAAOl4D,IAAU,CAClC,MAAMlD,EAAI6M,EACJsuD,EAAO,CAAE,GAAGn7D,EAAE,iBAAiB,MACrCm7D,EAAK4G,CAAG,EAAI,CAAE,GAAG5G,EAAK4G,CAAG,EAAG,CAAC3G,CAAK,EAAGl4D,CAAA,EACrClD,EAAE,iBAAmB,CAAE,GAAGA,EAAE,iBAAkB,KAAAm7D,CAAA,CAChD,EACA,gBAAkB6E,GAAS,CACzB,MAAMhgE,EAAI6M,EACL7M,EAAE,iBAAiB,YAAY,SAASggE,CAAI,IAC/ChgE,EAAE,iBAAmB,CACnB,GAAGA,EAAE,iBACL,YAAa,CAAC,GAAGA,EAAE,iBAAiB,YAAaggE,CAAI,EAAE,MAAK,EAGlE,EACA,mBAAqBA,GAAS,CAC5B,MAAMhgE,EAAI6M,EACV7M,EAAE,iBAAmB,CACnB,GAAGA,EAAE,iBACL,YAAaA,EAAE,iBAAiB,YAAY,OAAQY,GAAMA,IAAMo/D,CAAI,EAExE,EACA,OAAQ,KAAW8N,GAAiBjhE,CAA0D,GAChG,CACD,GAIH,OAAO,SAAS,QAAQ,OAAO,EACxB0iB,IACT,CC3/EA,SAASopC,GAAgBtkC,EAAoB,CAC3C,MAAMzzB,EAAI,IAAI,KAAKyzB,CAAE,EACf2rC,EAAOp/D,EAAE,mBAAmB,QAAS,CAAE,IAAK,UAAW,MAAO,QAAS,EACvE+W,EAAO/W,EAAE,mBAAmB,QAAS,CAAE,KAAM,UAAW,OAAQ,UAAW,EACjF,MAAO,GAAGo/D,CAAI,IAAIroD,CAAI,EACxB,CAEA,SAAS0+D,GAAYtjE,EAAsB,CACzC,OAAIA,EAAK,WAAW,gBAAgB,EAAU,SAC1CA,EAAK,WAAW,gBAAgB,EAAU,SACvC,OACT,CAEO,SAASujE,GACdr+D,EACAs+D,EACAtZ,EACA,CAOA,OAAO1tC;AAAAA,8CANqBxvB,GAAa,CAClCA,EAAE,OAAuB,UAAU,SAAS,qBAAqB,GACpEk9D,EAAA,CAEJ,CAG8D;AAAA;AAAA;AAAA;AAAA,qDAIXA,CAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAMlDhlD,EAAQ,SAAW,EACjBsX,0DACAA;AAAAA;AAAAA,gBAEItX,EAAQ,IAAK5I,GAAUkgB;AAAAA;AAAAA;AAAAA,0EAGmC8mD,GAAYhnE,EAAM,IAAI,CAAC,KAAKgnE,GAAYhnE,EAAM,IAAI,CAAC;AAAA,qEACxDA,EAAM,IAAI;AAAA;AAAA;AAAA,sBAGzDspD,GAAgBtpD,EAAM,SAAS,CAAC;AAAA,sDACAA,EAAM,OAAO;AAAA;AAAA;AAAA,eAGpD,CAAC;AAAA;AAAA,oEAEoDknE,CAAO;AAAA;AAAA;AAAA,WAGhE;AAAA;AAAA;AAAA,GAIX,CC3DO,MAAMC,GAAuD,CAClE,MAAO,GACP,MAAO,GACP,KAAM,GACN,KAAM,GACN,MAAO,GACP,MAAO,EACT,EAEaC,GAAmC,CAC9C,KAAM,GACN,YAAa,GACb,QAAS,GACT,QAAS,GACT,aAAc,QACd,WAAY,GACZ,YAAa,KACb,UAAW,UACX,SAAU,YACV,OAAQ,GACR,cAAe,OACf,SAAU,iBACV,YAAa,cACb,YAAa,GACb,QAAS,GACT,QAAS,OACT,WAAY,GACZ,SAAU,GACV,eAAgB,GAChB,iBAAkB,EACpB,ECgEO,SAASC,GAAgB9mE,EAAqB,CACnDA,EAAK,SAAW0d,GAAA,EAGhB,MAAMk1C,EAAQz+D,GAAA,EACdK,GAAsBo+D,EAAM,WAAW,EACvCr9D,GAA0Bq9D,EAAM,eAAe,EAC/C,MAAMmU,EAAc,SAAS,cAA+B,kBAAkB,EAU9E,GATIA,IAAaA,EAAY,KAAOnU,EAAM,SAG1C,OAAO,SAAS,EAAG,CAAC,EAGpB72C,GAAkB/b,CAA0D,EAGxEA,EAAK,WAAY,CACnB,MAAMg7B,EAAM,OAAO,kCACb0nC,GAAO1nC,GAAA,YAAAA,EAAK,YAAa,GACzBrnC,EAAO+uE,EAAOA,EAAK,OAAO,CAAC,EAAE,cAAgBA,EAAK,MAAM,CAAC,EAAI,YACnE,SAAS,MAAQ,aAAa/uE,CAAI,GAClComE,GAAe/5D,CAAuD,EACtE,MACF,CAGA,GAAIA,EAAK,MAAO,CACd,SAAS,MAAQ,GAAG4yD,EAAM,IAAI,SAC9BmH,GAAe/5D,CAAuD,EACtE,MACF,CAGA,GAAIA,EAAK,UAAW,CAClB,SAAS,MAAQ,GAAG4yD,EAAM,IAAI,SAC9B32C,GAAyBjc,CAAiE,EAC1F+5D,GAAe/5D,CAAuD,EACtE,MACF,CAGA,GAAIA,EAAK,YAAa,CACpB,SAAS,MAAQ,GAAG4yD,EAAM,IAAI,WAC9BmH,GAAe/5D,CAAuD,EACtE,MACF,CAGA,GAAIA,EAAK,WAAY,CACnB,SAAS,MAAQ,GAAG4yD,EAAM,IAAI,UAC9BmH,GAAe/5D,CAAuD,EACtE,MACF,CAGA,GAAIA,EAAK,aAAc,CACrB,SAAS,MAAQ,GAAG4yD,EAAM,IAAI,YAC9BmH,GAAe/5D,CAAuD,EACtE,MACF,CAGA,GAAIA,EAAK,SAAU,CACjB,SAAS,MAAQ,GAAG4yD,EAAM,IAAI,QAC9BmH,GAAe/5D,CAAuD,EACtE,MACF,CAGA,GAAIA,EAAK,aAAc,CACrB,SAAS,MAAQ,GAAG4yD,EAAM,IAAI,YAC9BmH,GAAe/5D,CAAuD,EAEtE2b,GAAwB3b,CAAgE,EACxFyb,GAAiBzb,CAAyD,EAC1E,MACF,CAEAge,GACEhe,EACA,IAEF4d,GACE5d,CAAA,EAEF8d,GACE9d,CAAA,EAEF,OAAO,iBAAiB,WAAYA,EAAK,eAAe,EACxDuc,GACEvc,CAAA,EAEF+5D,GAAe/5D,CAAuD,EACtEub,GAAkBvb,CAA0D,EACxEA,EAAK,MAAQ,SACCA,EAA4C,aAC7C,UACb2b,GAAwB3b,CAAgE,EAExFyb,GAAiBzb,CAAyD,GAG1EA,EAAK,MAAQ,SACf6b,GAAkB7b,CAA0D,CAEhF,CAEO,SAASgnE,GAAmBhnE,EAAqB,CACtD2C,GAAc3C,CAAsD,CACtE,CAEO,SAASinE,GAAmBjnE,EAAqB,OACtD,OAAO,oBAAoB,WAAYA,EAAK,eAAe,EAC3Dwb,GAAiBxb,CAAyD,EAC1E0b,GAAgB1b,CAAwD,EACxE4b,GAAuB5b,CAA+D,EACtF8b,GAAiB9b,CAAyD,EAC1Egc,GAAiBhc,CAAyD,EAC1Emc,GAAwBnc,CAAgE,EACxF+d,GACE/d,CAAA,GAEF3O,EAAA2O,EAAK,iBAAL,MAAA3O,EAAqB,aACrB2O,EAAK,eAAiB,IACxB,CAEO,SAASknE,GACdlnE,EACA8oB,EACA,CAEA,GAAI,CAAA9oB,EAAK,WA2CT,IAxCIA,EAAK,WAAaA,EAAK,WACH8oB,EAAQ,IAAI,WAAW,GAAKA,EAAQ,IAAI,WAAW,IAAM,IAC1D9oB,EAAK,iBACxBA,EAAK,kBAKLA,EAAK,YAAcA,EAAK,WACJ8oB,EAAQ,IAAI,WAAW,GAAKA,EAAQ,IAAI,WAAW,IAAM,IAC1D9oB,EAAK,kBACxBA,EAAK,mBAKLA,EAAK,cAAgBA,EAAK,WACN8oB,EAAQ,IAAI,WAAW,GAAKA,EAAQ,IAAI,WAAW,IAAM,IAC1D9oB,EAAK,oBACxBA,EAAK,qBAKLA,EAAK,UAAYA,EAAK,WACF8oB,EAAQ,IAAI,WAAW,GAAKA,EAAQ,IAAI,WAAW,IAAM,IAC1D9oB,EAAK,gBACxBA,EAAK,iBAKLA,EAAK,cAAgBA,EAAK,WACN8oB,EAAQ,IAAI,WAAW,GAAKA,EAAQ,IAAI,WAAW,IAAM,IAC1D9oB,EAAK,oBACxBA,EAAK,qBAKLA,EAAK,OAASA,EAAK,UAAW,CAChC,MAAMmnE,EAAgBr+C,EAAQ,IAAI,WAAW,GAAKA,EAAQ,IAAI,WAAW,IAAM,GAG3Eq+C,GAAiBnnE,EAAK,0BAA4BA,EAAK,eAAiB,MAAQ,CAACA,EAAK,aACxFA,EAAK,2BAIHmnE,GAAiBnnE,EAAK,mBACxBA,EAAK,oBAIP,MAAMonE,EAAkBt+C,EAAQ,IAAI,WAAW,GAAK9oB,EAAK,YAAc,OACjEqnE,EAAmBv+C,EAAQ,IAAI,WAAW,GAAK9oB,EAAK,YAAc,SACpEmnE,GAAiBC,GAAmBC,IAClCrnE,EAAK,uBAAyBA,EAAK,gBAAkB,MAAQ,CAACA,EAAK,UACrEA,EAAK,wBAKLA,EAAK,YAAc,SACG8oB,EAAQ,IAAI,WAAW,GAGxB9oB,EAAK,QAAU,CAACA,EAAK,kBAC1CA,EAAK,gBAAkB,GACvBA,EAAK,OAAO,QAAQ,kBAAmB,CAAE,MAAO,GAAM,UAAW,IAAM,EACpE,KAAM5C,GAAQ,CACb4C,EAAK,iBAAmB5C,EACxB4C,EAAK,gBAAkB,EACzB,CAAC,EACA,MAAM,IAAM,CACXA,EAAK,gBAAkB,EACzB,CAAC,GAKH8oB,EAAQ,IAAI,wBAAwB,GAAK9oB,EAAK,yBAA2B,IACvEA,EAAK,QAAU,CAACA,EAAK,kBACvBA,EAAK,gBAAkB,GACvBA,EAAK,OAAO,QAAQ,kBAAmB,CAAE,MAAO,GAAM,UAAW,IAAM,EACpE,KAAM5C,GAAQ,CACb4C,EAAK,iBAAmB5C,EACxB4C,EAAK,gBAAkB,EACzB,CAAC,EACA,MAAM,IAAM,CACXA,EAAK,gBAAkB,EACzB,CAAC,EAGT,CAEA,GACEA,EAAK,MAAQ,QACb,CAACA,EAAK,eACL8oB,EAAQ,IAAI,cAAc,GACzBA,EAAQ,IAAI,kBAAkB,GAC9BA,EAAQ,IAAI,YAAY,GACxBA,EAAQ,IAAI,aAAa,GACzBA,EAAQ,IAAI,KAAK,GACnB,CACA,MAAMw+C,EAAcx+C,EAAQ,IAAI,KAAK,EAC/By+C,EACJz+C,EAAQ,IAAI,aAAa,GACzBA,EAAQ,IAAI,aAAa,IAAM,IAC/B9oB,EAAK,cAAgB,GACvBiB,GACEjB,EACAsnE,GAAeC,GAAgB,CAACvnE,EAAK,oBAEzC,CAGEA,EAAK,MAAQ,QACb,CAACA,EAAK,eACL8oB,EAAQ,IAAI,aAAa,GAAKA,EAAQ,IAAI,gBAAgB,GAAKA,EAAQ,IAAI,KAAK,IAE7E9oB,EAAK,gBAAkBA,EAAK,cAC9B2B,GACE3B,EACA8oB,EAAQ,IAAI,KAAK,GAAKA,EAAQ,IAAI,gBAAgB,IAMtDA,EAAQ,IAAI,oBAAoB,GAAKA,EAAQ,IAAI,uBAAuB,IAEpE9oB,EAAK,uBAAyBA,EAAK,cACrC2B,GACE3B,EACA8oB,EAAQ,IAAI,uBAAuB,GAI3C,CCtFO,SAAS0+C,GACdC,EACuB,CACvB,MAAMC,EAA2B,CAC/B,MAAMD,GAAA,YAAAA,EAAS,OAAQ,GACvB,aAAaA,GAAA,YAAAA,EAAS,cAAe,GACrC,OAAOA,GAAA,YAAAA,EAAS,QAAS,GACzB,SAASA,GAAA,YAAAA,EAAS,UAAW,GAC7B,QAAQA,GAAA,YAAAA,EAAS,SAAU,GAC3B,SAASA,GAAA,YAAAA,EAAS,UAAW,GAC7B,OAAOA,GAAA,YAAAA,EAAS,QAAS,GACzB,OAAOA,GAAA,YAAAA,EAAS,QAAS,IAG3B,MAAO,CACL,OAAAC,EACA,SAAU,CAAE,GAAGA,CAAA,EACf,OAAQ,GACR,UAAW,GACX,MAAO,KACP,QAAS,KACT,YAAa,GACb,aAAc,GACZD,GAAA,MAAAA,EAAS,QAAUA,GAAA,MAAAA,EAAS,SAAWA,GAAA,MAAAA,EAAS,OAASA,GAAA,MAAAA,EAAS,MACpE,CAEJ,CC1SA,eAAsBE,GAAoB3nE,EAAqBM,EAAgBoE,EAAoB,CACjG,MAAMiB,GAAmB3F,EAAMM,EAAOoE,CAAS,EAC/C,MAAMe,EAAazF,EAAM,EAAI,CAC/B,CAEA,eAAsB4nE,GAAmB5nE,EAAqB0E,EAAoB,CAChF,MAAMkB,GAAkB5F,EAAM0E,CAAS,EACvC,MAAMe,EAAazF,EAAM,EAAI,CAC/B,CAEA,eAAsB6nE,GAAqB7nE,EAAqB0E,EAAoB,CAClF,MAAMmB,GAAe7F,EAAM0E,CAAS,EACpC,MAAMe,EAAazF,EAAM,EAAI,CAC/B,CAEA,eAAsB8nE,GAAyB9nE,EAAqBrM,EAAc,CAChF,MAAMmS,GAAmB9F,EAAMrM,CAAI,CACrC,CAEA,eAAsBo0E,GAA4B/nE,EAAqB0E,EAAmB,CACxF,MAAM0B,GAAsBpG,EAAM0E,CAAS,CAC7C,CAEA,eAAsBsjE,GAAwBhoE,EAAqB,CACjE,MAAM4D,GAAW5D,CAAI,EACrB,MAAMsD,GAAWtD,CAAI,EACrB,MAAMyF,EAAazF,EAAM,EAAI,CAC/B,CAEA,eAAsBioE,GAA0BjoE,EAAqB,CACnE,MAAMsD,GAAWtD,CAAI,EACrB,MAAMyF,EAAazF,EAAM,EAAI,CAC/B,CAEA,SAASkoE,GAAsBC,EAA0C,CACvE,GAAI,CAAC,MAAM,QAAQA,CAAO,QAAU,GACpC,MAAMC,EAAiC,GACvC,UAAW3oE,KAAS0oE,EAAS,CAC3B,GAAI,OAAO1oE,GAAU,SAAU,SAC/B,KAAM,CAAC4oE,EAAU,GAAGrwE,CAAI,EAAIyH,EAAM,MAAM,GAAG,EAC3C,GAAI,CAAC4oE,GAAYrwE,EAAK,SAAW,EAAG,SACpC,MAAMwzD,EAAQ6c,EAAS,OACjB9tE,EAAUvC,EAAK,KAAK,GAAG,EAAE,OAC3BwzD,GAASjxD,IAAS6tE,EAAO5c,CAAK,EAAIjxD,EACxC,CACA,OAAO6tE,CACT,CAEA,SAASE,GAAsBtoE,EAA6B,WAE1D,QAAOsf,KADUhuB,GAAAD,EAAA2O,EAAK,mBAAL,YAAA3O,EAAuB,kBAAvB,YAAAC,EAAwC,QAAS,IAClD,CAAC,IAAV,YAAAguB,EAAa,YAAatf,EAAK,uBAAyB,SACjE,CAEA,SAASuoE,GAAqB7jE,EAAmBixB,EAAS,GAAY,CACpE,MAAO,uBAAuB,mBAAmBjxB,CAAS,CAAC,WAAWixB,CAAM,EAC9E,CAEO,SAAS6yC,GACdxoE,EACA0E,EACA+iE,EACA,CACAznE,EAAK,sBAAwB0E,EAC7B1E,EAAK,sBAAwBwnE,GAA4BC,GAAW,MAAS,CAC/E,CAEO,SAASgB,GAAyBzoE,EAAqB,CAC5DA,EAAK,sBAAwB,KAC7BA,EAAK,sBAAwB,IAC/B,CAEO,SAAS0oE,GACd1oE,EACAwrD,EACAl4D,EACA,CACA,MAAM2J,EAAQ+C,EAAK,sBACd/C,IACL+C,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,OAAQ,CACN,GAAGA,EAAM,OACT,CAACuuD,CAAK,EAAGl4D,CAAA,EAEX,YAAa,CACX,GAAG2J,EAAM,YACT,CAACuuD,CAAK,EAAG,GACX,EAEJ,CAEO,SAASmd,GAAiC3oE,EAAqB,CACpE,MAAM/C,EAAQ+C,EAAK,sBACd/C,IACL+C,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,aAAc,CAACA,EAAM,cAEzB,CAEA,eAAsB2rE,GAAuB5oE,EAAqB,CAChE,MAAM/C,EAAQ+C,EAAK,sBACnB,GAAI,CAAC/C,GAASA,EAAM,OAAQ,OAC5B,MAAMyH,EAAY4jE,GAAsBtoE,CAAI,EAE5CA,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,OAAQ,GACR,MAAO,KACP,QAAS,KACT,YAAa,EAAC,EAGhB,GAAI,CACF,MAAM43C,EAAW,MAAM,MAAM0zB,GAAqB7jE,CAAS,EAAG,CAC5D,OAAQ,MACR,QAAS,CACP,eAAgB,oBAElB,KAAM,KAAK,UAAUzH,EAAM,MAAM,EAClC,EACKyD,EAAQ,MAAMm0C,EAAS,OAAO,MAAM,IAAM,IAAI,EAIpD,GAAI,CAACA,EAAS,KAAMn0C,GAAA,YAAAA,EAAM,MAAO,IAAS,CAACA,EAAM,CAC/C,MAAMmoE,GAAenoE,GAAA,YAAAA,EAAM,QAAS,0BAA0Bm0C,EAAS,MAAM,IAC7E70C,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,OAAQ,GACR,MAAO4rE,EACP,QAAS,KACT,YAAaX,GAAsBxnE,GAAA,YAAAA,EAAM,OAAO,GAElD,MACF,CAEA,GAAI,CAACA,EAAK,UAAW,CACnBV,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,OAAQ,GACR,MAAO,wCACP,QAAS,MAEX,MACF,CAEA+C,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,OAAQ,GACR,MAAO,KACP,QAAS,+BACT,YAAa,GACb,SAAU,CAAE,GAAGA,EAAM,OAAO,EAE9B,MAAMwI,EAAazF,EAAM,EAAI,CAC/B,OAASxC,EAAK,CACZwC,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,OAAQ,GACR,MAAO,0BAA0B,OAAOO,CAAG,CAAC,GAC5C,QAAS,KAEb,CACF,CAEA,eAAsBsrE,GAAyB9oE,EAAqB,CAClE,MAAM/C,EAAQ+C,EAAK,sBACnB,GAAI,CAAC/C,GAASA,EAAM,UAAW,OAC/B,MAAMyH,EAAY4jE,GAAsBtoE,CAAI,EAE5CA,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,UAAW,GACX,MAAO,KACP,QAAS,MAGX,GAAI,CACF,MAAM43C,EAAW,MAAM,MAAM0zB,GAAqB7jE,EAAW,SAAS,EAAG,CACvE,OAAQ,OACR,QAAS,CACP,eAAgB,oBAElB,KAAM,KAAK,UAAU,CAAE,UAAW,GAAM,EACzC,EACKhE,EAAQ,MAAMm0C,EAAS,OAAO,MAAM,IAAM,IAAI,EAIpD,GAAI,CAACA,EAAS,KAAMn0C,GAAA,YAAAA,EAAM,MAAO,IAAS,CAACA,EAAM,CAC/C,MAAMmoE,GAAenoE,GAAA,YAAAA,EAAM,QAAS,0BAA0Bm0C,EAAS,MAAM,IAC7E70C,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,UAAW,GACX,MAAO4rE,EACP,QAAS,MAEX,MACF,CAEA,MAAME,EAASroE,EAAK,QAAUA,EAAK,UAAY,KACzCsoE,EAAaD,EAAS,CAAE,GAAG9rE,EAAM,OAAQ,GAAG8rE,GAAW9rE,EAAM,OAC7DgsE,EAAe,GACnBD,EAAW,QAAUA,EAAW,SAAWA,EAAW,OAASA,EAAW,OAG5EhpE,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,UAAW,GACX,OAAQ+rE,EACR,MAAO,KACP,QAAStoE,EAAK,MACV,oDACA,wCACJ,aAAAuoE,CAAA,EAGEvoE,EAAK,OACP,MAAM+E,EAAazF,EAAM,EAAI,CAEjC,OAASxC,EAAK,CACZwC,EAAK,sBAAwB,CAC3B,GAAG/C,EACH,UAAW,GACX,MAAO,0BAA0B,OAAOO,CAAG,CAAC,GAC5C,QAAS,KAEb,CACF,CCtLA,eAAsB0rE,GAAmBjsE,EAA+C,CACtF,GAAI,CAACA,EAAM,OAAQ,OACnB,MAAM+J,EAAQ/J,EAAM,sBAAsB,OAC1C,GAAK+J,EAEL,CAAA/J,EAAM,qBAAuB,GAC7BA,EAAM,sBAAwB,KAE9B,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,0BAA2B,CACjE,aAAc+J,CAAA,CACf,EAED/J,EAAM,cAAgBG,EAAI,UAC1BH,EAAM,cAAgBG,EAAI,WAAa,KACvCH,EAAM,YAAcG,EAAI,SAAW,KACnCH,EAAM,iBAAmB+J,EACzB/J,EAAM,sBAAwB,GAC9BA,EAAM,oBAAsB,EAC9B,OAASO,EAAK,CACZP,EAAM,sBAAwBO,aAAe,MAAQA,EAAI,QAAU,wBACrE,SACEP,EAAM,qBAAuB,EAC/B,EACF,CAKA,eAAsBksE,GAAgBlsE,EAAiC,CACrE,GAAKA,EAAM,OAEX,CAAAA,EAAM,SAAW,GACjBA,EAAM,YAAc,KAEpB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,cAAe,EAAE,EAEzDA,EAAM,cAAgBG,EAAI,UAC1BH,EAAM,cAAgBG,EAAI,WAAa,KACvCH,EAAM,YAAcG,EAAI,SAAW,KACnCH,EAAM,iBAAmBG,EAAI,cAAgB,IAI/C,OAASI,EAAK,CACZP,EAAM,cAAgB,GACtBA,EAAM,YAAcO,aAAe,MAAQA,EAAI,QAAU,6BAC3D,SACEP,EAAM,SAAW,EACnB,EACF,CAKA,eAAsBmsE,GAAUnsE,EAAiC,CAC/D,GAAKA,EAAM,OAEX,CAAAA,EAAM,SAAW,GACjBA,EAAM,YAAc,KACpBA,EAAM,QAAU,KAChBA,EAAM,cAAgB,KAEtB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,mBAAoB,CAC1D,SAAU,YACX,EAEDA,EAAM,QAAUG,EAAI,QACpBH,EAAM,YAAcG,EAAI,SAAW,sCACrC,OAASI,EAAK,CACZP,EAAM,cAAgB,GACtBA,EAAM,YAAcO,aAAe,MAAQA,EAAI,QAAU,2BAC3D,SACEP,EAAM,SAAW,EACnB,EACF,CAKA,eAAsBosE,GAAepsE,EAAkB09D,EAA6B,CAClF,GAAK19D,EAAM,OAEX,CAAAA,EAAM,SAAW,GACjBA,EAAM,YAAc,oBAEpB,GAAI,CAEF,MAAMA,EAAM,OAAO,QAAQ,kBAAmB,CAAE,KAAA09D,EAAM,EAGtD,MAAMv9D,EAAO,MAAMH,EAAM,OAAO,QAAQ,kBAAmB,CACzD,UAAW,IACZ,EAEGG,EAAI,WACNH,EAAM,cAAgB,GACtBA,EAAM,YAAcG,EAAI,SAAW,uBACnCH,EAAM,QAAU,KAChBA,EAAM,cAAgB,IAGtBA,EAAM,YAAcG,EAAI,SAAW,oCAEvC,OAASI,EAAK,CACZP,EAAM,cAAgB,GACtBA,EAAM,YAAcO,aAAe,MAAQA,EAAI,QAAU,qBAC3D,SACEP,EAAM,SAAW,EACnB,EACF,CAKO,SAASqsE,GAAoBrsE,EAAkB09D,EAAoB,CACxE19D,EAAM,cAAgB09D,CACxB,CC5IA,eAAsB4O,GAAmBtsE,EAAoC,CAC3E,GAAKA,EAAM,OAEX,CAAAA,EAAM,YAAc,GACpBA,EAAM,eAAiB,KAEvB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,iBAAkB,EAAE,EAE5DA,EAAM,gBAAkBG,EAAI,UAAY,KACxCH,EAAM,iBAAmBG,EAAI,KAAO,KAEhCA,EAAI,UACNH,EAAM,aAAe,GACrBA,EAAM,YAAcG,EAAI,MAAQ,KAChCH,EAAM,UAAY,UAElBA,EAAM,aAAe,KACrBA,EAAM,UAAY,UAEtB,OAASO,EAAK,CAEZ,MAAM3B,EAAM2B,aAAe,MAAQA,EAAI,QAAU,OAAOA,CAAG,EACvD3B,EAAI,SAAS,gBAAgB,GAC/BoB,EAAM,aAAe,GACrBA,EAAM,UAAY,UAElBA,EAAM,aAAe,KACrBA,EAAM,eAAiBpB,EACvBoB,EAAM,UAAY,UAEtB,SACEA,EAAM,YAAc,EACtB,EACF,CAKA,eAAsBusE,GAAgBvsE,EAAoC,CACxE,GAAKA,EAAM,QACNA,EAAM,WAAW,OAEtB,CAAAA,EAAM,YAAc,GACpBA,EAAM,eAAiB,KACvBA,EAAM,aAAe,KAErB,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,mBAAoB,CAC1D,IAAKA,EAAM,WAAW,MAAK,CAC5B,EAEGG,EAAI,OACNH,EAAM,aAAe,GACrBA,EAAM,eAAiBG,EAAI,SAAW,oBACtCH,EAAM,YAAcG,EAAI,MAAQ,KAEhC,WAAW,IAAM,CACfH,EAAM,UAAY,OACpB,EAAG,IAAI,IAEPA,EAAM,aAAe,GACrBA,EAAM,eAAiBG,EAAI,SAAW,sBAE1C,OAASI,EAAK,CACZP,EAAM,aAAe,GACrBA,EAAM,eAAiBO,aAAe,MAAQA,EAAI,QAAU,mBAC9D,SACEP,EAAM,YAAc,EACtB,EACF,CAKA,eAAsBwsE,GAAcxsE,EAAoC,CACtE,GAAKA,EAAM,OAEX,CAAAA,EAAM,YAAc,GACpB,GAAI,CACF,MAAMA,EAAM,OAAO,QAAQ,iBAAkB,EAAE,EAC/CA,EAAM,aAAe,KACrBA,EAAM,WAAa,GACnBA,EAAM,YAAc,KACpBA,EAAM,eAAiB,KACvBA,EAAM,UAAY,SACpB,OAASO,EAAK,CACZP,EAAM,eAAiBO,aAAe,MAAQA,EAAI,QAAU,0BAC9D,SACEP,EAAM,YAAc,EACtB,EACF,CAKO,SAASysE,GAAiBzsE,EAAqB3F,EAAmB,CACvE2F,EAAM,WAAa3F,CACrB,CC9GA,eAAsBqyE,GAAkB1sE,EAAoC,SAC1E,GAAI,GAACA,EAAM,QAAU,CAACA,EAAM,YACxB,CAAAA,EAAM,qBAEV,CAAAA,EAAM,qBAAuB,IAC7B5L,EAAA4L,EAAM,gBAAN,MAAA5L,EAAA,KAAA4L,GAEA,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,SAAU,CAChD,MAAO,GACR,EAEDA,EAAM,eAAiBG,EAAI,KAAO,GAClCH,EAAM,qBAAuBG,EAAI,GAC7B,UAAUA,EAAI,WAAa,KAAKA,EAAI,UAAU,MAAQ,EAAE,GACxD,WACN,OAASI,EAAK,CACZP,EAAM,eAAiB,GACvBA,EAAM,qBAAuB,UAAU,OAAOO,CAAG,CAAC,EACpD,SACEP,EAAM,qBAAuB,IAC7B3L,EAAA2L,EAAM,gBAAN,MAAA3L,EAAA,KAAA2L,EACF,EACF,CAEA,eAAsB2sE,GAAe3sE,EAAoC,WACvE,GAAI,GAACA,EAAM,QAAUA,EAAM,oBAE3B,CAAAA,EAAM,mBAAqB,GAC3BA,EAAM,qBAAuB,iBAC7B5L,EAAA4L,EAAM,gBAAN,MAAA5L,EAAA,KAAA4L,GAEA,GAAI,CACF,MAAMG,EAAO,MAAMH,EAAM,OAAO,QAAQ,kBAAmB,CACzD,OAAQ,iCACR,QAAS,IACV,EAED,GAAIG,EAAI,MAAM9L,EAAA8L,EAAI,UAAJ,MAAA9L,EAAa,IACzB2L,EAAM,qBAAuB,gBAG7B,WAAW,IAAM,CACf,OAAO,SAAS,QAClB,EAAG,GAAI,MAEP,OAAM,IAAI,MAAM,uBAAuB,CAE3C,OAASO,EAAK,CACZP,EAAM,qBAAuB,mBAAmB,OAAOO,CAAG,CAAC,GAC3DP,EAAM,mBAAqB,IAC3BqiB,EAAAriB,EAAM,gBAAN,MAAAqiB,EAAA,KAAAriB,EACF,EACF,qMC0DA,MAAM4sE,GAA4Bh2E,GAAA,EAElC,SAASi2E,IAAiC,CACxC,GAAI,CAAC,OAAO,SAAS,OAAQ,MAAO,GAEpC,MAAMvzE,EADS,IAAI,gBAAgB,OAAO,SAAS,MAAM,EACtC,IAAI,YAAY,EACnC,GAAI,CAACA,EAAK,MAAO,GACjB,MAAMqc,EAAarc,EAAI,OAAO,cAC9B,OAAOqc,IAAe,KAAOA,IAAe,QAAUA,IAAe,OAASA,IAAe,IAC/F,CAEA,SAASm3D,IAA4B,CAEnC,MAAMvyD,EAAW,OAAO,SAAS,SACjC,GAAIA,IAAa,UAAYA,EAAS,SAAS,QAAQ,EACrD,MAAO,GAGT,GAAI,CAAC,OAAO,SAAS,OAAQ,MAAO,GAEpC,MAAMjhB,EADS,IAAI,gBAAgB,OAAO,SAAS,MAAM,EACtC,IAAI,OAAO,EAC9B,GAAI,CAACA,EAAK,MAAO,GACjB,MAAMqc,EAAarc,EAAI,OAAO,cAC9B,OAAOqc,IAAe,KAAOA,IAAe,QAAUA,IAAe,OAASA,IAAe,IAC/F,CAEA,SAASo3D,IAAgC,CACvC,MAAMxyD,EAAW,OAAO,SAAS,SACjC,OAAOA,IAAa,UAAYA,EAAS,SAAS,QAAQ,CAC5D,CAEA,SAASyyD,IAAkC,CACzC,MAAMzyD,EAAW,OAAO,SAAS,SACjC,OAAOA,IAAa,YAAcA,EAAS,SAAS,UAAU,CAChE,CAEA,SAAS0yD,IAAiC,CACxC,MAAM1yD,EAAW,OAAO,SAAS,SACjC,OAAOA,IAAa,WAAaA,EAAS,SAAS,SAAS,CAC9D,CAEA,SAAS2yD,IAAmC,CAC1C,MAAM3yD,EAAW,OAAO,SAAS,SACjC,OAAOA,IAAa,aAAeA,EAAS,SAAS,WAAW,CAClE,CAEA,SAAS4yD,IAA+B,CACtC,MAAM5yD,EAAW,OAAO,SAAS,SACjC,OAAOA,IAAa,SAAWA,EAAS,SAAS,OAAO,CAC1D,CAEA,SAAS6yD,IAAmC,CAC1C,MAAM7yD,EAAW,OAAO,SAAS,SACjC,OAAOA,IAAa,aAAeA,EAAS,SAAS,WAAW,CAClE,CAGO,IAAM8yD,EAAN,cAA4Br/B,EAAW,CAAvC,kCACI,cAAuBr0C,GAAA,EACvB,cAAW,GACX,SAAW,OACX,gBAAakzE,GAAA,EACb,WAAQC,GAAA,EACR,eAAYC,GAAA,EACZ,iBAAcC,GAAA,EACd,gBAAaC,GAAA,EACb,kBAAeC,GAAA,EACf,cAAWC,GAAA,EACX,kBAAeC,GAAA,EACf,iBAA4D,OAE5D,gBAAa,EAAQ,OAAO,2BAC5B,sBAAmB,OAAO,mCAAqC,GAC/D,0BAAsC,KACtC,6BAA0B,GAC1B,wBAAmE,OACnE,eAAY,GACZ,iBAA2BxjE,GAC3B,WAAmB,KAAK,SAAS,OAAS,SAC1C,mBAA+B,OAC/B,WAA+B,KAC/B,eAA2B,KAC3B,cAA4B,GACrC,KAAQ,eAAkC,GAC1C,KAAQ,oBAAqC,KAC7C,KAAQ,kBAAmC,KAElC,mBAAgBgjE,GAA0B,KAC1C,qBAAkBA,GAA0B,OAC5C,sBAAmBA,GAA0B,SAAW,KAExD,gBAAa,KAAK,SAAS,WAC3B,iBAAc,GACd,iBAAc,GACd,iBAAc,GACd,kBAA0B,GAC1B,sBAAmB,EACnB,wBAAqB,GACrB,sBAAmB,GACnB,sBAA8B,GAC9B,gBAA4B,KAC5B,qBAAiC,KACjC,qBAA4B,GAC5B,yBAAqC,KACrC,eAA2B,KAC3B,sBAAwE,KACxE,mBAA+B,KAC/B,sBAA+F,GAC/F,sBAAkC,KAClC,eAA6B,GAC7B,qBAAoC,GAEpC,iBAAc,GACd,oBAAgC,KAChC,kBAA8B,KAC9B,gBAAa,KAAK,SAAS,WAE3B,kBAAe,GACf,WAAwC,GACxC,oBAAiB,GACjB,kBAA8B,KAC9B,iBAAwC,KACxC,0BAAuB,GACvB,yBAAsB,GACtB,wBAAqB,GACrB,2BAAsD,KACtD,uBAA8C,KAC9C,gCAA4C,KAC5C,yBAA0C,UAC1C,+BAA2C,KAC3C,uBAA2C,GAC3C,sBAAmB,GACnB,uBAAmC,KAEnC,mBAAgB,GAChB,eAAY;AAAA;AAAA,EACZ,uBAAoB,GACpB,iBAA8B,KAC9B,kBAA0B,GAC1B,kBAAe,GACf,oBAAiB,GACjB,mBAAgB,GAChB,qBAAkB,KAAK,SAAS,qBAChC,oBAAwC,KACxC,kBAA+B,KAC/B,yBAAqC,KACrC,yBAAsB,GACtB,mBAA+B,GAC/B,gBAA6C,KAC7C,wBAAqD,KACrD,qBAAkB,GAClB,oBAAiC,OACjC,uBAAoB,GACpB,yBAAqC,KACrC,4BAAwC,KAExC,qBAAkB,GAClB,sBAAkD,KAClD,mBAA+B,KAC/B,yBAAqC,KACrC,0BAAsC,KACtC,4BAAwC,KACxC,4BAAyC,KACzC,kBAAe,GACf,+BAA2C,KAC3C,yBAAqC,KACrC,2BAAwB,GACxB,4BAAyB,GACzB,0BAAsC,KACtC,2BAAwB,GACxB,0BAAuB,GACvB,0BAAuB,GACvB,4BAAyB,GACzB,yBAAsB,GACtB,4BAAyB,GACzB,+BAA4B,GAE5B,kBAAe,GACf,uBAAoB,GACpB,sBAAmB,GAEnB,qBAAmD,KACnD,mBAAgB,GAChB,sBAAkC,KAClC,oBAAgC,KAChC,6BAAyC,KACzC,8BAA0C,KAC1C,6BAA0B,GAC1B,8BAA2B,EAC3B,6BAA0B,GAC1B,6BAA0B,GAE1B,gBAAyC,KACzC,kBAA6C,GAC7C,cAAW,GACX,eAA2B,KAC3B,kBAAe,GACf,sBAAkC,KAElC,iBAA2C,KAC3C,qBAAkB,GAClB,sBAAmB,GACnB,0BAAuB,GACvB,sBAAmB,GACnB,iBAAc,GACd,kBAA8B,KAC9B,oBAAgC,KAEhC,mBAAgB,GAEhB,gBAAa,GACb,iBAAc,GACd,kBAA+B,KAC/B,oBAAgC,KAChC,iBAA6B,KAC7B,qBAAiC,KACjC,sBAAkC,KAClC,0BAAuB,GAEvB,mBAAgC,KAChC,cAAW,GACX,iBAA6B,KAC7B,aAAyB,KACzB,mBAAgB,GAChB,mBAA+B,KAC/B,sBAAkC,KAClC,yBAAsB,GACtB,2BAAwB,GACxB,0BAAuB,GACvB,2BAAuC,KACvC,eAA0C,UAE1C,oBAAiC,KACjC,0BAAuB,GACvB,0BAAsC,KACtC,wBAAqB,GAErB,qBAAkC,KAClC,oBAAgC,KAChC,mBAA+B,KAC/B,oBAAiB,GAEjB,mBAA+B,KAC/B,yBAA4C,GAC5C,sBAA4C,KAE5C,sBAAmB,GACnB,mBAAgB,GAChB,mBAAgB,GAChB,oBAAgC,KAChC,0BAAuB,GACvB,2BAAsD,KACtD,2BAAuC,KAEvC,qBAAkB,GAClB,qBAAmC,GACnC,mBAA+B,KAC/B,oBAAgC,KAEhC,mBAAgB,GAChB,gBAAsC,KACtC,iBAA6B,KAE7B,qBAAkB,GAClB,oBAA4C,KAC5C,mBAA+B,KAE/B,iBAAc,GACd,cAAsB,GACtB,gBAAgC,KAChC,eAA2B,KAC3B,cAA0B,CAAE,GAAGhD,EAAA,EAC/B,mBAA+B,KAC/B,cAA8B,GAC9B,cAAW,GACX,uBAAoB,GACpB,qBAAiC,KACjC,mBAA+B,KAC/B,yBAAqC,KACrC,uBAAmC,KACnC,yBAAsB,GACtB,mBAAkG,KAIlG,yBAAsB,GACtB,uBAAmC,KACnC,sBAAmB,GACnB,sBAAmB0D,GAAA,EAEnB,6BAA0B,GAC1B,4BAAwC,KACxC,+BAAoF,KACpF,2BAAwB,GACxB,0BAAsC,KACtC,sBAAkC,KAClC,sBAAmB,GACnB,uBAAoB,GACpB,oBAAiB,GACjB,kBAA8B,KAE9B,kBAAe,GACf,eAAgE,GAChE,eAAY,GACZ,gBAA4B,KAC5B,uBAAmC,KACnC,4BAAsC,IACtC,yBAAqC,KACrC,yBAAsB,GACtB,wBAAqB,GACrB,sBAAkC,KAClC,2BAAqC,IACrC,qBAAkB,IAClB,4BAAwC,KACxC,kBAAmE,KACnE,qBAAkB,GAClB,sBAAmB,GACnB,uBAA2J,KAE3J,0BAAuB,GAChC,KAAQ,mBAAoC,KACnC,sBAAmB,GACnB,wBAAkF,KAClF,wBAAqB,GACrB,wBAAoC,KAE7C,0BAA2C,OAGlC,kBAA6B,GAC7B,kBAAe,GACf,oBAAiB,GAEjB,mBAAgB,GAChB,kBAAyC,KACzC,iBAA6B,KAC7B,kBAAe,GACf,sBAAiD,MACjD,uBAAgD,MAChD,gBAAqC,GACrC,mBAA+B,KAC/B,mBAA8C,GAC9C,iBAAqE,KACrE,oBAAiB,GACjB,mBAAgB,GAChB,kBAA4D,CAAE,KAAM,GAAI,aAAc,GAAI,WAAY,EAAC,EACvG,wBAAqE,QACrE,kBAAe,WACf,iBAA2D,GAE3D,mBAAgB,GAChB,iBAAiC,GACjC,iBAA6B,KAC7B,kBAAe,GACf,oBAAiB,GAEjB,qBAAkB,GAClB,oBAAiB,GACjB,qBAAyE,GACzE,mBAA+B,KAC/B,yBAAsB,GACtB,uBAAmC,KACnC,yBAAsB,GACtB,sBAAmB,GACnB,qBAAkB,GAClB,6BAAyC,KACzC,2BAAuC,KACvC,yBAAsB,GACtB,2BAAwB,GAIxB,2BAAwB,GACxB,sBAAmB,GAEnB,iBAAmC,OACnC,qBAA2E,GAC3E,mBAA+B,KAC/B,gBAAiE,GACjE,iBAAyE,KACzE,eAAY,GACZ,uBAAoB,GACpB,mBAAgB,GAChB,oBAAiB,GACjB,eAAY,GACZ,iBAA6B,KAE7B,mBAA+B,KAC/B,2BAAuC,KACvC,yBAAqC,KAErC,gBAAiE,GACjE,uBAAoB,GACpB,qBAAiC,KACjC,uBAAmC,KACnC,qBAAkB,GAClB,sBAAmB,GACnB,sBAAmB,GACnB,qBAAkB,GAClB,yBAAsB,GACtB,oBAAiB,GACjB,qBAAiC,KACjC,uBAAmC,KAEnC,qBAAoE,GACpE,qBAAkB,GAClB,gBAAa,GACb,iBAA6B,KAC7B,mBAA+B,KAC/B,0BAAsC,KACtC,oBAAiB,GACjB,qBAAkB,GAClB,oBAAiB,GACjB,qBAAiC,KACjC,iBAA2C,KAC3C,mBAAgB,GAChB,oBAAgC,KAChC,wBAAqB,GACrB,mBAAgB,GAChB,oBAAgC,KAChC,sBAAkC,KAClC,qBAAkB,GAClB,4BAAwC,KACxC,uBAAoB,GACpB,yBAAsB,GAEtB,kBAAe,GACf,iBAAoC,KACpC,iBAAqC,KACrC,iBAAyB,GACzB,oBAAiC,KACjC,qBAAkB,GAClB,qBAAkB,KAClB,qBAAiC,KACjC,oBAAgC,KAEhC,iBAAc,GACd,eAA2B,KAC3B,cAA0B,KAC1B,iBAA0B,GAC1B,oBAAiB,GACjB,sBAA8C,CACrD,GAAG3D,EAAA,EAEI,oBAAiB,GACjB,mBAAgB,GAChB,gBAA4B,KAC5B,qBAAiC,KACjC,eAAY,IACZ,kBAAe,KACf,kBAAe,GACf,cAA0B,KAC1B,wBAA+B,GAE/B,gBAAmC,UACnC,uBAAoB,GACpB,wBAAqB,GACrB,sBAAkC,KAClC,wBAA+C,GAC/C,2BAAwB,GACxB,4BAA0D,CACjE,KAAM,GACN,UAAW,GACX,KAAM,GACN,UAAW,GACX,YAAa,GACb,SAAU,GACV,MAAO,GACP,OAAQ,IAED,6BAAmD,GACnD,uBAA8B,GAC9B,2BAAwB,GACxB,8BAA2B,GACpC,gCAA0C,IACjC,wBAA6C,GAC7C,4BAAwC,KACxC,yBAAsB,GAE/B,YAAsC,KACtC,KAAQ,gBAAiC,KACzC,KAAQ,kBAAmC,KAC3C,KAAQ,oBAAsB,GACrB,wBAAqB,GAC9B,iBAAmC,IAAM,KAAK,sBAC9C,KAAQ,kBAAmC,KAC3C,KAAQ,iBAAkC,KAC1C,KAAQ,wBAAyC,KACjD,KAAQ,kBAAmC,KAC3C,KAAQ,kBAAmC,KAC3C,KAAQ,gBAAiC,KACzC,KAAQ,mBAAqB,IAC7B,KAAQ,gBAA4B,GACpC,cAAW,GACX,KAAQ,gBAAkB,IACxB4D,GACE,MAEJ,KAAQ,WAAoC,KAC5C,KAAQ,kBAAmE,KAC3E,KAAQ,eAAwC,KAMhD,KAAQ,qBAAuB,IAAM,OACnC5yE,GAAA,EACA,MAAM9B,EAAK,KAAK,qBAAsBzE,EAAA,KAAkE,mBAAlE,YAAAA,EAAoF,YAAa,GACnIyE,GAAIsB,GAAUtB,EAAI,KAAK,WAAY,KAAK,WAAW,CACzD,EARA,kBAAmB,CACjB,OAAO,IACT,CAQA,mBAAoB,CAClB,MAAM,oBACNgxE,GAAgB,IAAwD,EACxE,OAAO,iBAAiB,eAAgB,KAAK,oBAAoB,CACnE,CAEU,cAAe,CACvBE,GAAmB,IAA2D,CAChF,CAEA,sBAAuB,CACrB,OAAO,oBAAoB,eAAgB,KAAK,oBAAoB,EACpE,KAAK,oBACLC,GAAmB,IAA2D,EAC9E,MAAM,sBACR,CAGA,oBAAqB,CACnB,GAAI,KAAK,oBAAsB,KAAM,OACrC,MAAMwD,EAAO,SAAY,CACvB,GAAI,GAAC,KAAK,QAAU,CAAC,KAAK,WAC1B,IAAI,CACF,MAAMrtE,EAAO,MAAM,KAAK,OAAO,QAAQ,gBAAiB,EAAE,EAK1D,IADcA,GAAA,YAAAA,EAAK,kBACL,cACZ,KAAK,qBAAuB,OACvB,CAED,KAAK,uBACP,KAAK,qBAAuB,IAE9B,KAAK,oBACL,MACF,CACF,MAAQ,CAEN,KAAK,qBAAuB,GAC5B,KAAK,oBACL,MACF,CAEA,KAAK,mBAAqB,OAAO,WAAWqtE,EAAM,GAAI,EACxD,EACKA,EAAA,CACP,CAEA,mBAAoB,CACd,KAAK,oBAAsB,OAC7B,OAAO,aAAa,KAAK,kBAAkB,EAC3C,KAAK,mBAAqB,KAE9B,CAEU,QAAQ3hD,EAAoC,CACpDo+C,GACE,KACAp+C,CAAA,CAEJ,CAEA,SAAU,CACR4hD,GACE,KAEJ,CAEA,iBAAiB7oE,EAAc,CAC7B8oE,GACE,KACA9oE,CAAA,CAEJ,CAEA,iBAAiBA,EAAc,CAC7B+oE,GACE,KACA/oE,CAAA,CAEJ,CAEA,wBAAwBA,EAAc,CACpCgpE,GACE,KACAhpE,CAAA,CAEJ,CAEA,WAAWzG,EAAiBhB,EAAe,CACzC0wE,GAAmB1vE,EAAOhB,CAAK,CACjC,CAEA,kBAAkBgB,EAAiBhB,EAAe,CAChD2wE,GAA0B3vE,EAAOhB,CAAK,CACxC,CAEA,iBAAkB,CAChB4wE,GACE,KAEJ,CAEA,iBAAkB,CAChBC,GACE,KAEJ,CAEA,MAAM,uBAAwB,CAC5B,MAAMC,GAA8B,IAAI,CAC1C,CAEA,cAAcp0E,EAAkB,CAC9Bq0E,GACE,KACAr0E,CAAA,CAEJ,CAEA,OAAOA,EAAW,CAChBs0E,GAAe,KAAyDt0E,CAAI,CAC9E,CAEA,SAASA,EAAiBshB,EAAkD,CAC1EizD,GACE,KACAv0E,EACAshB,CAAA,CAEJ,CAEA,MAAM,cAAe,CACnB,MAAMkzD,GACJ,KAEJ,CAEA,MAAM,UAAW,OACf,MAAMC,EAAS,KAAK,2BACpB,KAAK,oBAAoBl6E,EAAAk6E,GAAA,YAAAA,EAAQ,SAAR,YAAAl6E,EAAgB,IAAKR,GAAMA,EAAE,MAAO,OAC7D,KAAK,UAAY,KAAK,mBAAqB,OAC3C,KAAK,SAAW,CACd,GAAG,KAAK,SACR,UAAW,KAAK,mBAAqB,QAEvC,MAAM26E,GACJ,KAEJ,CAEA,MAAM,iBAAkB,CACtB,MAAMC,GACJ,KAEJ,CAEA,oBAAoBpvE,EAAY,CAC9BqvE,GACE,KACArvE,CAAA,CAEJ,CAEA,MAAM,eACJ0iB,EACA7hB,EACA,CACA,MAAMyuE,GACJ,KACA5sD,EACA7hB,CAAA,CAEJ,CAEA,MAAM,oBAAoBoD,EAAgBoE,EAAoB,CAC5D,MAAMknE,GAA4B,KAAMtrE,EAAOoE,CAAS,CAC1D,CAEA,MAAM,mBAAmBA,EAAoB,CAC3C,MAAMmnE,GAA2B,KAAMnnE,CAAS,CAClD,CAEA,MAAM,qBAAqBA,EAAoB,CAC7C,MAAMonE,GAA6B,KAAMpnE,CAAS,CACpD,CAEA,MAAM,yBAAyB/Q,EAAc,CAC3C,MAAMo4E,GAAiC,KAAMp4E,CAAI,CACnD,CAEA,MAAM,4BAA4B+Q,EAAmB,CACnD,MAAMsnE,GAAoC,KAAMtnE,CAAS,CAC3D,CAGA,MAAM,mBAAoB,CACxB,MAAMunE,GAA0B,IAAI,CACtC,CAEA,MAAM,gBAAgBj1E,EAAiBoQ,EAAa,CAClD,MAAM8kE,GAAkB,KAAMl1E,EAASoQ,CAAG,EAEtC,KAAK,YAAY,eAAiB,KAAK,YAAY,WACrD,KAAK,sBAAsB,KAAK,YAAY,SAAS,CAEzD,CAEA,MAAM,mBAAmBA,EAAa,CACpC,MAAM+kE,GAAqB,KAAM/kE,CAAG,CACtC,CAEA,MAAM,cAAe,CACnB,MAAMglE,GAAe,IAAI,CAC3B,CAEA,qBAAsB,CACpB,KAAK,mBAAqB,CAAC,KAAK,mBAChC,KAAK,eAAiB,KACtB,KAAK,iBAAmB,IAC1B,CAEA,MAAM,gBAAgBp1E,EAAiB+2B,EAAgBC,EAAgB,CACrE,GAAK,KAAK,OACV,MAAK,cAAgB,GACrB,KAAK,eAAiB,KACtB,KAAK,iBAAmB,KACxB,GAAI,CAEF,MAAMq+C,EAAgB,MAAM,KAAK,OAAO,QAAQ,gBAAiB,CAAE,QAAAr1E,EAAS,IAAK+2B,EAAQ,EAIzF,GAAI,CAACs+C,EAAa,GAAI,CACpB,KAAK,eAAiBA,EAAa,SAAW,wBAC9C,KAAK,cAAgB,GACrB,MACF,CAEIr1E,IAAY,aACd,MAAM,KAAK,OAAO,QAAQ,sBAAuB,CAAE,IAAKg3B,EAAQ,EAEhE,MAAM,KAAK,OAAO,QAAQ,uBAAwB,CAAE,UAAWh3B,EAAS,IAAKg3B,EAAQ,EAEvF,KAAK,iBAAmB,2BACxB,KAAK,cAAgB,GAErB,WAAW,IAAM,CACf,KAAK,mBAAqB,GAC1B,KAAK,iBAAmB,IAC1B,EAAG,GAAI,CACT,MAAQ,CACN,KAAK,eAAiB,uBACtB,KAAK,cAAgB,EACvB,EACF,CAEA,MAAM,qBAAqBv3B,EAAmBs3B,EAAuBC,EAAgB,CACnF,GAAK,KAAK,OACV,MAAK,eAAiB,GACtB,KAAK,gBAAkB,KACvB,KAAK,kBAAoB,KACzB,GAAI,CAEF,GAAID,IAAW,KAAM,CACnB,MAAMs+C,EAAgB,MAAM,KAAK,OAAO,QAAQ,gBAAiB,CAAE,QAAS51E,EAAW,IAAKs3B,CAAA,CAAQ,EAGpG,GAAI,CAACs+C,EAAa,GAAI,CACpB,KAAK,gBAAkBA,EAAa,SAAW,wBAC/C,KAAK,eAAiB,GACtB,MACF,CACF,CAEA,MAAM,KAAK,OAAO,QAAQ,uBAAwB,CAAE,UAAA51E,EAAW,IAAKu3B,EAAQ,EAC5E,KAAK,kBAAoB,YACzB,KAAK,eAAiB,GAEtB,MAAMi+C,GAA0B,IAAI,EAEpC,WAAW,IAAM,CACf,KAAK,oBAAsB,GAC3B,KAAK,kBAAoB,KACzB,KAAK,gBAAkB,IACzB,EAAG,IAAI,CACT,MAAQ,CACN,KAAK,gBAAkB,qBACvB,KAAK,eAAiB,EACxB,EACF,CAGA,MAAM,0BAA2B,CAC/B,MAAMK,GAA2B,IAAI,CACvC,CAEA,MAAM,uBAAwB,CAC5B,MAAMC,GAAwB,IAAI,CACpC,CAEA,MAAM,qBAAsB,CAC1B,MAAMC,GAAsB,IAAI,CAClC,CAEA,uBAAuBl1E,EAAa,CAClCm1E,GAAyB,KAAMn1E,CAAG,CACpC,CAGA,MAAM,uBAAwB,CAC5B,MAAMo1E,GAAwB,IAAI,CACpC,CAEA,MAAM,iBAAkB,CACtB,MAAMC,GAAkB,IAAI,CAC9B,CAEA,MAAM,qBAAqBhS,EAAc,CACvC,MAAMiS,GAAuB,KAAMjS,CAAI,CACzC,CAEA,qBAAqBA,EAAc,CACjCkS,GAA4B,KAAMlS,CAAI,CACxC,CAEA,2BAA4B,CAC1B,KAAK,oBAAsB,EAC7B,CAEA,4BAA6B,CAC3B,KAAK,oBAAsB,GAC3B,KAAK,QAAU,KACf,KAAK,sBAAwB,GAC7B,KAAK,sBAAwB,IAC/B,CAEA,MAAM,0BAA2B,CAC/B,MAAMmS,GAA2B,IAAI,CACvC,CAGA,MAAM,0BAA2B,CAC/B,MAAMC,GAA0B,IAAI,CACtC,CAEA,MAAM,sBAAuB,CAC3B,MAAMC,GAAuB,IAAI,CACnC,CAGA,MAAM,mBAAoB,CACxB,MAAMC,GAAwB,IAAI,CACpC,CAEA,MAAM,iBAAkB,CACtB,MAAMC,GAAkB,IAAI,CAC9B,CAEA,2BAA4B,CAC1BC,GAA4B,IAAI,CAClC,CAGA,wBAAyB,CACvB,KAAK,iBAAmB,GACxB,KAAK,qBAAuB,EAC9B,CAEA,uBAAwB,CACtB,KAAK,iBAAmB,GACxB,KAAK,qBAAuB,GAC5B,KAAK,eAAiB,IACxB,CAEA,iCAAiC91E,EAAc,CAC7C,KAAK,qBAAuBA,CAC9B,CAEA,MAAM,oBAAqB,CACzB,KAAM,CAAE,aAAAgsB,CAAA,EAAiB,MAAA7F,GAAA,6BAAA6F,CAAA,QAAM,2BAAA+pD,EAAA,EAAmC,oBAAA/pD,CAAA,2BAClE,MAAMA,EAAa,IAAI,CACzB,CAEA,wBAAyB,CACvB7F,GAAA,mCAAAgG,CAAA,uCAAmC,0BAAAA,EAAA,0BAAE,KAAK,CAAC,CAAE,mBAAAA,KAAyB,CACpEA,EAAA,CACF,CAAC,EACD,KAAK,cAAgB,GACrB,KAAK,iBAAmB,GACxB,KAAK,qBAAuB,EAC9B,CAGA,MAAM,kBAAmB,CACvB,MAAM6pD,GAAyB,IAAI,CACrC,CAEA,MAAM,YAAa,CACjB,MAAMC,GAAmB,IAAI,EAC7B,KAAK,eAAiB,EACxB,CAGA,iBAAkB,OAChB,MAAM/B,EAAS,KAAK,2BACpB,KAAK,oBAAoBl6E,EAAAk6E,GAAA,YAAAA,EAAQ,SAAR,YAAAl6E,EAAgB,IAAKR,GAAMA,EAAE,MAAO,OAC7D,MAAM00E,EAAe,KAAK,sBAC1B,KAAK,qBAAuBA,EACvBgI,GAAqB,KAAMhI,CAAY,EACvCiI,GAAyB,KAAMjI,CAAY,CAClD,CAGA,kBAAmB,CACjB,MAAMpG,EAAe,KAAK,sBAC1B3hD,GAAA,2BAAA0hD,CAAA,QAAK,2BAAAuO,EAAA,EAA6B,kBAAAvO,EAAA,0BAAE,KAAK,CAAC,CAAE,WAAAA,KAAiB,CAC3DA,EAAW,KAAMC,CAAY,CAC/B,CAAC,CACH,CAEQ,qBAA0C,CAChD,MAAMrpE,EAAK,KAAK,2BAChB,GAAI,CAACA,EAAI,OACT,MAAM0qE,EAAa1qE,EAAG,OAAO,KAAMjF,GAAMA,EAAE,GAAG,SAAS,QAAQ,GAAKA,EAAE,KAAO,OAAO,EACpF,OAAO2vE,GAAA,YAAAA,EAAY,EACrB,CAEQ,qBAA0C,OAChD,MAAM1qE,EAAK,KAAK,2BAChB,GAAI,CAACA,EAAI,OAGT,MAAM0qE,EAAa1qE,EAAG,OAAO,KAAMjF,GAAMA,EAAE,GAAG,SAAS,QAAQ,GAAKA,EAAE,KAAO,OAAO,EACpF,OAAO2vE,GAAA,YAAAA,EAAY,OAAMnvE,EAAAyE,EAAG,OAAO,CAAC,IAAX,YAAAzE,EAAc,GACzC,CAKA,gBAAiB,CACf,MAAM8tE,EAAe,KAAK,sBAC1B,GAAIA,EAAc,CAChB,MAAMuO,EAAgB,SAASvO,CAAY,QACvCuO,IAAkB,KAAK,aACzB,KAAK,WAAaA,EAClB,KAAK,aAAe,GACpB,KAAK,WAAa,KAClB,KAAK,gBAAkB,KACvB,KAAK,UAAY,KACjB,KAAK,gBAAkB,GAEvB,KAAK,kBACL,KAAK,cAAc,CACjB,GAAG,KAAK,SACR,WAAYA,EACZ,qBAAsBA,CAAA,CACvB,EACI,KAAK,wBAEd,CACAlwD,GAAA,gCAAAxgB,CAAA,QAAK,2BAAA2wE,EAAA,EAA2B,uBAAA3wE,EAAA,0BAAE,KAAK,CAAC,CAAE,gBAAAA,KAAsB,CACzDA,EAAgB,IAAI,EAAE,KAAK,IAAM,CAGpC4wE,GACE,KACA,GAEJ,CAAC,CACH,CAAC,CACH,CAGA,MAAM,qBAAsB,CAC1B,GAAI,KAAK,kBAAoB,CAAC,KAAK,mBAAoB,OACvD,MAAMC,EAAgB/rE,GACpB,MAEI,CAAE,qBAAArE,CAAA,EAAyB,MAAA+f,GAAA,qCAAA/f,CAAA,QAAM,2BAAAkwE,EAAA,EAA2B,4BAAAlwE,CAAA,2BACnD,MAAMA,EAAqB,IAAI,GAChCowE,IAEZ,MAAM,KAAK,eACXA,EAAA,EAEJ,CAGA,oBAAqB,OACnB,MAAMtC,EAAS,KAAK,2BACpB,KAAK,oBAAoBl6E,EAAAk6E,GAAA,YAAAA,EAAQ,SAAR,YAAAl6E,EAAgB,IAAKR,GAAMA,EAAE,MAAO,OAE7D,KAAK,mBAAqB,GAC1B,KAAK,mBAAqB,GAC1B,KAAK,kBAAoB,GAKrB,KAAK,cAAgB,QAAU,KAAK,mBAAwB,KAAK,WACjE,KAAK,cAAgB,iBACvB2sB,GAAA,iCAAAugD,CAAA,QAAK,2BAAAK,EAAA,EAAoC,wBAAAL,EAAA,0BAAE,KAAK,CAAC,CAAE,iBAAAA,KAAuB,CACxEA,EAAiB,IAAyD,CAC5E,CAAC,EAEC,KAAK,cAAgB,SACnB,KAAK,aAAe,UACtBvgD,GAAA,gCAAA1E,CAAA,QAAK,2BAAA2E,EAAA,EAAmC,uBAAA3E,EAAA,0BAAE,KAAK,CAAC,CAAE,gBAAAA,KAAsB,CACtEA,EAAgB,KAA0D,CAAE,MAAO,GAAM,CAC3F,CAAC,EAED0E,GAAA,yBAAApV,CAAA,QAAK,2BAAA0lE,EAAA,EAA2B,gBAAA1lE,EAAA,0BAAE,KAAK,CAAC,CAAE,SAAAA,KAAe,CACvDA,EAAS,KAAM,CAAE,MAAO,GAAM,CAChC,CAAC,GAGD,KAAK,cAAgB,UACvBoV,GAAA,2BAAAxI,CAAA,QAAK,2BAAA+4C,EAAA,EAA6B,kBAAA/4C,EAAA,0BAAE,KAAK,CAAC,CAAE,WAAAA,KAAiB,CAC3DA,EAAW,KAAM,CAAE,cAAe,GAAM,CAC1C,CAAC,CAEL,CAEA,MAAM,yBAA0B,CAC9B,MAAM+4D,GAAgC,IAAI,CAC5C,CAEA,MAAM,2BAA4B,CAChC,MAAMC,GAAkC,IAAI,CAC9C,CAEA,uBAAuBtpE,EAAmB+iE,EAA8B,CACtEwG,GAA+B,KAAMvpE,EAAW+iE,CAAO,CACzD,CAEA,0BAA2B,CACzByG,GAAiC,IAAI,CACvC,CAEA,8BAA8B1iB,EAA2Bl4D,EAAe,CACtE66E,GAAsC,KAAM3iB,EAAOl4D,CAAK,CAC1D,CAEA,MAAM,wBAAyB,CAC7B,MAAM86E,GAA+B,IAAI,CAC3C,CAEA,MAAM,0BAA2B,CAC/B,MAAMC,GAAiC,IAAI,CAC7C,CAEA,kCAAmC,CACjCC,GAAyC,IAAI,CAC/C,CAEA,MAAM,2BAA2BC,EAAkD,CACjF,MAAMpT,EAAS,KAAK,kBAAkB,CAAC,EACvC,GAAI,GAACA,GAAU,CAAC,KAAK,QAAU,KAAK,kBACpC,MAAK,iBAAmB,GACxB,KAAK,kBAAoB,KACzB,GAAI,CACF,MAAM,KAAK,OAAO,QAAQ,wBAAyB,CACjD,GAAIA,EAAO,GACX,SAAAoT,CAAA,CACD,EACD,KAAK,kBAAoB,KAAK,kBAAkB,OAAQ9uE,GAAUA,EAAM,KAAO07D,EAAO,EAAE,CAC1F,OAAS39D,EAAK,CACZ,KAAK,kBAAoB,yBAAyB,OAAOA,CAAG,CAAC,EAC/D,SACE,KAAK,iBAAmB,EAC1B,EACF,CAGA,kBAAkB/C,EAAiB,CAC7B,KAAK,mBAAqB,OAC5B,OAAO,aAAa,KAAK,iBAAiB,EAC1C,KAAK,kBAAoB,MAE3B,KAAK,eAAiBA,EACtB,KAAK,aAAe,KACpB,KAAK,YAAc,EACrB,CAEA,oBAAqB,CACnB,KAAK,YAAc,GAEf,KAAK,mBAAqB,MAC5B,OAAO,aAAa,KAAK,iBAAiB,EAE5C,KAAK,kBAAoB,OAAO,WAAW,IAAM,CAC3C,KAAK,cACT,KAAK,eAAiB,KACtB,KAAK,aAAe,KACpB,KAAK,kBAAoB,KAC3B,EAAG,GAAG,CACR,CAEA,uBAAuB+rC,EAAe,CACpC,MAAM4E,EAAW,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK5E,CAAK,CAAC,EACnD,KAAK,WAAa4E,EAClB,KAAK,cAAc,CAAE,GAAG,KAAK,SAAU,WAAYA,EAAU,CAC/D,CAGA,2BAA2B93C,EAAe,CACxC,KAAK,eAAiBA,EAElB,KAAK,cAAa,KAAK,YAAc,KAC3C,CAGA,oBAAqB,CACnB,MAAMmD,EAAY,KAAK,mBAAqB,OAC5C+mB,GAAA,6BAAAgiD,CAAA,QAAK,2BAAAgP,EAAA,EAA+B,oBAAAhP,EAAA,0BAAE,KAAK,CAAC,CAAE,aAAAA,KAAmB,CAC/DA,EAAa,KAAM/oE,CAAS,CAC9B,CAAC,CACH,CAEA,6BAA6BnD,EAAe,CAC1C,KAAK,iBAAmBA,EACpB,KAAK,gBAAe,KAAK,cAAgB,KAC/C,CAEA,4BAA4BA,EAAe,CACzC,KAAK,gBAAkBA,EACnB,KAAK,gBAAe,KAAK,cAAgB,KAC/C,CAGA,MAAM,sBAAuB,CAC3B,KAAM,CAAE,eAAAogE,CAAA,EAAmB,MAAAl2C,GAAA,+BAAAk2C,CAAA,QAAM,2BAAAtyC,EAAA,EAAiC,sBAAAsyC,CAAA,2BAClE,MAAMA,EAAe,IAAI,CAC3B,CAEA,MAAM,sBAAsB//D,EAAc6uE,EAAwB,CAChE,KAAM,CAAE,gBAAA7O,CAAA,EAAoB,MAAAn2C,GAAA,gCAAAm2C,CAAA,QAAM,2BAAAvyC,EAAA,EAAiC,uBAAAuyC,CAAA,2BAC7D,CAAE,aAAAluD,CAAA,EAAiB,MAAA+X,GAAA,6BAAA/X,CAAA,QAAM,2BAAAQ,EAAA,EAA+B,oBAAAR,CAAA,2BAC9D,MAAMkuD,EAAgB,KAAM,CAC1B,KAAAhgE,EACA,cAAA6uE,EACA,UAAYplE,GAAQ,CAClB,GAAI,CAACA,EAAI,kBAAmB,OAC5B,MAAMsH,EAAYtH,EAAI,kBAEtB,KAAK,sBAAsBzJ,CAAI,EAG/B,WAAW,SAAY,CACrB,GAAI,CACF,MAAM8R,EAAa,KAAM,EAAI,EAC7B,MAAM,KAAK,oBAAoB,GAAMf,CAAS,EAC1C,KAAK,yBACP,MAAM,KAAK,mBAAmBA,CAAS,EACvC,MAAMe,EAAa,KAAM,EAAI,EAC7B,MAAM,KAAK,uBAEf,MAAQ,CAER,CACA,KAAK,eACP,EAAG,GAAI,CACT,EACD,CACH,CAEA,MAAM,sBAAsB9R,EAAc,CACxC,KAAM,CAAE,gBAAAigE,CAAA,EAAoB,MAAAp2C,GAAA,gCAAAo2C,CAAA,QAAM,2BAAAxyC,EAAA,EAAiC,uBAAAwyC,CAAA,2BACnE,MAAMA,EAAgB,KAAMjgE,CAAI,CAClC,CAEA,4BAA6B,CAC3B,MAAMmC,EAAK,KAAK,2BAChB,KAAK,qBAAsBA,GAAA,YAAAA,EAAI,eAAeA,GAAA,YAAAA,EAAI,OAAQ,GAC1D,KAAK,kBAAoB,EAC3B,CAEA,6BAA8B,CAC5B,KAAK,kBAAoB,GACzB,KAAK,oBAAsB,EAC7B,CAEA,MAAM,sBAAsBnC,EAAcmgE,EAAqB,CAC7D,KAAM,CAAE,gBAAAD,CAAA,EAAoB,MAAAr2C,GAAA,gCAAAq2C,CAAA,QAAM,2BAAAzyC,EAAA,EAAiC,uBAAAyyC,CAAA,2BACnE,MAAMA,EAAgB,KAAMlgE,EAAMmgE,CAAW,EAC7C,KAAK,kBAAoB,GACzB,KAAK,oBAAsB,EAC7B,CAEA,sBAAsBngE,EAAc,CAElCiE,GAAA,EACI,KAAK,mBACPR,GAAU,KAAK,kBAAmB,KAAK,WAAY,KAAK,WAAW,EAErE,KAAK,kBAAoBzD,EACzB,KAAK,oBAAsB,KAC3B,aAAa,QAAQ,gCAAiCA,CAAI,EAE1D+B,GAAoB/B,CAAI,EAExBgD,GAAmBhD,CAAI,EACvB,KAAK,SAAWiD,GAAA,EAEhB,KAAK,YAAcW,GAAU5D,EAAM,KAAK,SAAS,UAAU,EAC3D,KAAK,gBAAkB,GACvB,KAAK,WAAa,KAClB,KAAK,gBAAkB,KACvB,KAAK,gBAAkB,GACvB,KAAK,oBAAsB,KAC3B,KAAK,UAAY,KACjB,KAAK,UAAY,GACjB,KAAK,UAAY,KAEjB,KAAK,gBAAkB,GACvB,KAAK,cAAgB,KACrB,KAAK,WAAa,GAClB,KAAK,YAAc,KACnB,KAAK,YAAc,KACnB,KAAK,cAAgB,GACrB,KAAK,eAAiB,GACtB,KAAK,uBACP,CAEA,0BAAoF,CAClF,OAAK,KAAK,kBACH,KAAK,WAAW,KAAMmC,GAAOA,EAAG,OAAS,KAAK,iBAAiB,GAAK,KADvC,IAEtC,CAEQ,uBAAwB,CAEzB,KAAK,mBAEN,KAAK,WAAY,KAAK,mBACjB,KAAK,aAAc,KAAK,qBACxB,KAAK,UAAW,KAAK,kBACrB,KAAK,UACZ,KAAK,iBAED,KAAK,cAAgB,YAAc,CAAC,KAAK,WAAa,KAAK,gBAAgB,SAAW,GACnF,KAAK,+BAEH,KAAK,cAAc,KAAK,oBACrC,CAEA,MAAc,6BAA8B,CAC1C,GAAI,GAAC,KAAK,QAAU,CAAC,KAAK,WAC1B,MAAK,UAAY,GACjB,KAAK,YAAc,KACnB,GAAI,CACF,MAAMA,EAAK,KAAK,2BACV4O,EAAY5O,GAAA,YAAAA,EAAI,kBAChBsH,EAAO,MAAM,KAAK,OAAO,QAAQ,yBAA0B,CAC/D,UAAAsH,CAAA,CACD,EACD,KAAK,gBAAkBtH,EAAI,aAC7B,OAASI,EAAK,CACZ,KAAK,YAAc,OAAOA,CAAG,CAC/B,SACE,KAAK,UAAY,EACnB,EACF,CAGA,wBAAyB,CACvB,GAAI,KAAK,WAAW,SAAW,EAAG,CAIhC,KAAK,wBACL,MACF,CACA,MAAM+V,EAAS,aAAa,QAAQ,+BAA+B,EAC7D3a,EAAQ2a,EAAS,KAAK,WAAW,KAAMzd,GAAOA,EAAG,OAASyd,CAAM,EAAI,KAC1E,GAAI3a,EACF,KAAK,kBAAoBA,EAAM,SAC1B,CAEL,MAAMwoE,EAAY,KAAK,WAAW,KAAMtrE,GAAOA,EAAG,SAAS,GAAK,KAAK,WAAW,CAAC,EACjF,KAAK,kBAAoBsrE,EAAU,KACnC,aAAa,QAAQ,gCAAiCA,EAAU,IAAI,CACtE,CAEA1rE,GAAoB,KAAK,iBAAiB,EAE1CiB,GAAmB,KAAK,iBAAiB,EACzC,KAAK,SAAWC,GAAA,EAEhB,KAAK,YAAcW,GAAU,KAAK,kBAAmB,KAAK,SAAS,UAAU,EAE7E,KAAK,uBACP,CAEA,QAAS,CACP,OAAOooB,IAAO+hD,GAAU,IAAI,CAAC,GAAG,KAAK,eAAiBgF,GAAiB,KAAK,aAAc,IAAM,KAAK,aAAc,IAAM,CAAE,KAAK,eAAiB,EAAO,CAAC,EAAIhmD,CAAO,EACtK,CACF,EAruCW4qB,EAAA,CAARruC,EAAA,CAAM,EADIqtE,EACF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAFIqtE,EAEF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAHIqtE,EAGF,mBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAJIqtE,EAIF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EALIqtE,EAKF,qBACAh/B,EAAA,CAARruC,EAAA,CAAM,EANIqtE,EAMF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAPIqtE,EAOF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EARIqtE,EAQF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EATIqtE,EASF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAVIqtE,EAUF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAXIqtE,EAWF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAZIqtE,EAYF,2BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAdIqtE,EAcF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAfIqtE,EAeF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhBIqtE,EAgBF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjBIqtE,EAiBF,uCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlBIqtE,EAkBF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnBIqtE,EAmBF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EApBIqtE,EAoBF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArBIqtE,EAqBF,qBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtBIqtE,EAsBF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvBIqtE,EAuBF,qBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxBIqtE,EAwBF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzBIqtE,EAyBF,wBAKAh/B,EAAA,CAARruC,EAAA,CAAM,EA9BIqtE,EA8BF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/BIqtE,EA+BF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhCIqtE,EAgCF,gCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAlCIqtE,EAkCF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnCIqtE,EAmCF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApCIqtE,EAoCF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArCIqtE,EAqCF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtCIqtE,EAsCF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvCIqtE,EAuCF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxCIqtE,EAwCF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzCIqtE,EAyCF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1CIqtE,EA0CF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3CIqtE,EA2CF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5CIqtE,EA4CF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7CIqtE,EA6CF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9CIqtE,EA8CF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/CIqtE,EA+CF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhDIqtE,EAgDF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjDIqtE,EAiDF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlDIqtE,EAkDF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnDIqtE,EAmDF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EApDIqtE,EAoDF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EArDIqtE,EAqDF,+BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAvDIqtE,EAuDF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxDIqtE,EAwDF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzDIqtE,EAyDF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1DIqtE,EA0DF,0BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA5DIqtE,EA4DF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7DIqtE,EA6DF,qBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9DIqtE,EA8DF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/DIqtE,EA+DF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhEIqtE,EAgEF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjEIqtE,EAiEF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlEIqtE,EAkEF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnEIqtE,EAmEF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EApEIqtE,EAoEF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArEIqtE,EAqEF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtEIqtE,EAsEF,0CACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvEIqtE,EAuEF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxEIqtE,EAwEF,yCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzEIqtE,EAyEF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1EIqtE,EA0EF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3EIqtE,EA2EF,iCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA7EIqtE,EA6EF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9EIqtE,EA8EF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/EIqtE,EA+EF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhFIqtE,EAgFF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjFIqtE,EAiFF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlFIqtE,EAkFF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnFIqtE,EAmFF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApFIqtE,EAoFF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArFIqtE,EAqFF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtFIqtE,EAsFF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvFIqtE,EAuFF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxFIqtE,EAwFF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzFIqtE,EAyFF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1FIqtE,EA0FF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3FIqtE,EA2FF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5FIqtE,EA4FF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7FIqtE,EA6FF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9FIqtE,EA8FF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/FIqtE,EA+FF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhGIqtE,EAgGF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjGIqtE,EAiGF,sCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAnGIqtE,EAmGF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApGIqtE,EAoGF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArGIqtE,EAqGF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtGIqtE,EAsGF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvGIqtE,EAuGF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxGIqtE,EAwGF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzGIqtE,EAyGF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1GIqtE,EA0GF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3GIqtE,EA2GF,yCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5GIqtE,EA4GF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7GIqtE,EA6GF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9GIqtE,EA8GF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/GIqtE,EA+GF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhHIqtE,EAgHF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjHIqtE,EAiHF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlHIqtE,EAkHF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnHIqtE,EAmHF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EApHIqtE,EAoHF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArHIqtE,EAqHF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtHIqtE,EAsHF,yCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAxHIqtE,EAwHF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzHIqtE,EAyHF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1HIqtE,EA0HF,gCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA5HIqtE,EA4HF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7HIqtE,EA6HF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9HIqtE,EA8HF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/HIqtE,EA+HF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhIIqtE,EAgIF,uCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjIIqtE,EAiIF,wCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlIIqtE,EAkIF,uCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnIIqtE,EAmIF,wCACAh/B,EAAA,CAARruC,EAAA,CAAM,EApIIqtE,EAoIF,uCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArIIqtE,EAqIF,uCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAvIIqtE,EAuIF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxIIqtE,EAwIF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzIIqtE,EAyIF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1IIqtE,EA0IF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3IIqtE,EA2IF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5IIqtE,EA4IF,gCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA9IIqtE,EA8IF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/IIqtE,EA+IF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhJIqtE,EAgJF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjJIqtE,EAiJF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlJIqtE,EAkJF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnJIqtE,EAmJF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApJIqtE,EAoJF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArJIqtE,EAqJF,8BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAvJIqtE,EAuJF,6BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAzJIqtE,EAyJF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1JIqtE,EA0JF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3JIqtE,EA2JF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5JIqtE,EA4JF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7JIqtE,EA6JF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9JIqtE,EA8JF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/JIqtE,EA+JF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhKIqtE,EAgKF,oCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAlKIqtE,EAkKF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnKIqtE,EAmKF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EApKIqtE,EAoKF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArKIqtE,EAqKF,uBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtKIqtE,EAsKF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvKIqtE,EAuKF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxKIqtE,EAwKF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzKIqtE,EAyKF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1KIqtE,EA0KF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3KIqtE,EA2KF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5KIqtE,EA4KF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7KIqtE,EA6KF,yBAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA/KIqtE,EA+KF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhLIqtE,EAgLF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjLIqtE,EAiLF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlLIqtE,EAkLF,kCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EApLIqtE,EAoLF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArLIqtE,EAqLF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtLIqtE,EAsLF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvLIqtE,EAuLF,8BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAzLIqtE,EAyLF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1LIqtE,EA0LF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3LIqtE,EA2LF,gCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA7LIqtE,EA6LF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9LIqtE,EA8LF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/LIqtE,EA+LF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhMIqtE,EAgMF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjMIqtE,EAiMF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlMIqtE,EAkMF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnMIqtE,EAmMF,qCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EArMIqtE,EAqMF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtMIqtE,EAsMF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvMIqtE,EAuMF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxMIqtE,EAwMF,8BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA1MIqtE,EA0MF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3MIqtE,EA2MF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5MIqtE,EA4MF,2BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA9MIqtE,EA8MF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/MIqtE,EA+MF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhNIqtE,EAgNF,6BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAlNIqtE,EAkNF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnNIqtE,EAmNF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EApNIqtE,EAoNF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArNIqtE,EAqNF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtNIqtE,EAsNF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvNIqtE,EAuNF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxNIqtE,EAwNF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzNIqtE,EAyNF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1NIqtE,EA0NF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3NIqtE,EA2NF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5NIqtE,EA4NF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7NIqtE,EA6NF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9NIqtE,EA8NF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/NIqtE,EA+NF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhOIqtE,EAgOF,6BAIAh/B,EAAA,CAARruC,EAAA,CAAM,EApOIqtE,EAoOF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArOIqtE,EAqOF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtOIqtE,EAsOF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvOIqtE,EAuOF,gCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAzOIqtE,EAyOF,uCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1OIqtE,EA0OF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3OIqtE,EA2OF,yCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5OIqtE,EA4OF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7OIqtE,EA6OF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9OIqtE,EA8OF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/OIqtE,EA+OF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhPIqtE,EAgPF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjPIqtE,EAiPF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlPIqtE,EAkPF,4BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EApPIqtE,EAoPF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArPIqtE,EAqPF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtPIqtE,EAsPF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvPIqtE,EAuPF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxPIqtE,EAwPF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzPIqtE,EAyPF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1PIqtE,EA0PF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3PIqtE,EA2PF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5PIqtE,EA4PF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7PIqtE,EA6PF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9PIqtE,EA8PF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/PIqtE,EA+PF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhQIqtE,EAgQF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjQIqtE,EAiQF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlQIqtE,EAkQF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnQIqtE,EAmQF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EApQIqtE,EAoQF,iCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAtQIqtE,EAsQF,oCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAxQIqtE,EAwQF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzQIqtE,EAyQF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1QIqtE,EA0QF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3QIqtE,EA2QF,kCAKAh/B,EAAA,CAARruC,EAAA,CAAM,EAhRIqtE,EAgRF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjRIqtE,EAiRF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlRIqtE,EAkRF,8BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EApRIqtE,EAoRF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArRIqtE,EAqRF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtRIqtE,EAsRF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvRIqtE,EAuRF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxRIqtE,EAwRF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzRIqtE,EAyRF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1RIqtE,EA0RF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3RIqtE,EA2RF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5RIqtE,EA4RF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7RIqtE,EA6RF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9RIqtE,EA8RF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/RIqtE,EA+RF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhSIqtE,EAgSF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjSIqtE,EAiSF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlSIqtE,EAkSF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnSIqtE,EAmSF,2BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EArSIqtE,EAqSF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtSIqtE,EAsSF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvSIqtE,EAuSF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxSIqtE,EAwSF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzSIqtE,EAySF,8BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA3SIqtE,EA2SF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5SIqtE,EA4SF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7SIqtE,EA6SF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9SIqtE,EA8SF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/SIqtE,EA+SF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhTIqtE,EAgTF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjTIqtE,EAiTF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlTIqtE,EAkTF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnTIqtE,EAmTF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApTIqtE,EAoTF,uCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArTIqtE,EAqTF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtTIqtE,EAsTF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvTIqtE,EAuTF,qCAIAh/B,EAAA,CAARruC,EAAA,CAAM,EA3TIqtE,EA2TF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5TIqtE,EA4TF,gCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA9TIqtE,EA8TF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/TIqtE,EA+TF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhUIqtE,EAgUF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjUIqtE,EAiUF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlUIqtE,EAkUF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnUIqtE,EAmUF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EApUIqtE,EAoUF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArUIqtE,EAqUF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtUIqtE,EAsUF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvUIqtE,EAuUF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxUIqtE,EAwUF,2BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA1UIqtE,EA0UF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3UIqtE,EA2UF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5UIqtE,EA4UF,mCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA9UIqtE,EA8UF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/UIqtE,EA+UF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhVIqtE,EAgVF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjVIqtE,EAiVF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlVIqtE,EAkVF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnVIqtE,EAmVF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EApVIqtE,EAoVF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EArVIqtE,EAqVF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtVIqtE,EAsVF,mCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvVIqtE,EAuVF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxVIqtE,EAwVF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzVIqtE,EAyVF,iCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA3VIqtE,EA2VF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5VIqtE,EA4VF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7VIqtE,EA6VF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9VIqtE,EA8VF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/VIqtE,EA+VF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhWIqtE,EAgWF,oCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjWIqtE,EAiWF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlWIqtE,EAkWF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnWIqtE,EAmWF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApWIqtE,EAoWF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArWIqtE,EAqWF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtWIqtE,EAsWF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvWIqtE,EAuWF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxWIqtE,EAwWF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzWIqtE,EAyWF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1WIqtE,EA0WF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3WIqtE,EA2WF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5WIqtE,EA4WF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7WIqtE,EA6WF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9WIqtE,EA8WF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/WIqtE,EA+WF,mCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAjXIqtE,EAiXF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlXIqtE,EAkXF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnXIqtE,EAmXF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApXIqtE,EAoXF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArXIqtE,EAqXF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtXIqtE,EAsXF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvXIqtE,EAuXF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxXIqtE,EAwXF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzXIqtE,EAyXF,8BAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA3XIqtE,EA2XF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA5XIqtE,EA4XF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA7XIqtE,EA6XF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9XIqtE,EA8XF,2BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/XIqtE,EA+XF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhYIqtE,EAgYF,gCAGAh/B,EAAA,CAARruC,EAAA,CAAM,EAnYIqtE,EAmYF,8BACAh/B,EAAA,CAARruC,EAAA,CAAM,EApYIqtE,EAoYF,6BACAh/B,EAAA,CAARruC,EAAA,CAAM,EArYIqtE,EAqYF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAtYIqtE,EAsYF,+BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAvYIqtE,EAuYF,yBACAh/B,EAAA,CAARruC,EAAA,CAAM,EAxYIqtE,EAwYF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EAzYIqtE,EAyYF,4BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA1YIqtE,EA0YF,wBACAh/B,EAAA,CAARruC,EAAA,CAAM,EA3YIqtE,EA2YF,kCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EA7YIqtE,EA6YF,0BACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9YIqtE,EA8YF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/YIqtE,EA+YF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhZIqtE,EAgZF,gCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAjZIqtE,EAiZF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAlZIqtE,EAkZF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnZIqtE,EAmZF,sCAUAh/B,EAAA,CAARruC,EAAA,CAAM,EA7ZIqtE,EA6ZF,uCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA9ZIqtE,EA8ZF,iCACAh/B,EAAA,CAARruC,EAAA,CAAM,EA/ZIqtE,EA+ZF,qCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAhaIqtE,EAgaF,wCAEAh/B,EAAA,CAARruC,EAAA,CAAM,EAlaIqtE,EAkaF,kCACAh/B,EAAA,CAARruC,EAAA,CAAM,EAnaIqtE,EAmaF,sCACAh/B,EAAA,CAARruC,EAAA,CAAM,EApaIqtE,EAoaF,mCAMAh/B,EAAA,CAARruC,EAAA,CAAM,EA1aIqtE,EA0aF,kCA1aEA,EAANh/B,EAAA,CADNC,GAAc,gBAAgB,GAClB++B,CAAA","names":["t","e","s","o","n$3","r","n","i","S","c","h","a","l","p","d","u","f","b","y$2","_a","_b","y","v","_","m","g","$","x","E","A","C","P","V","N","S$1","I","L","z","H","M","R","k","Z","I$2","Z$1","j","B","D","MAX_ASSISTANT_NAME","MAX_ASSISTANT_AVATAR","DEFAULT_ASSISTANT_NAME","coerceIdentityValue","value","maxLength","trimmed","normalizeAssistantIdentity","input","name","avatar","resolveInjectedAssistantIdentity","DEFAULT_BRAND_NAME","DEFAULT_BRAND_ICON_URL","DEFAULT_ACCENT_COLOR","DEFAULT_BACKGROUND_COLOR","cached","resolveBrand","getWorkspaceBrands","hexToRgb","hex","relativeLuminance","applyBrandAccentColor","color","rgb","root","fg","blendHex","base","tint","opacity","bm","tm","blend","bi","ti","BASE_TOKENS","applyBrandBackgroundColor","prop","val","applyWorkspaceBrand","workspaceName","deviceBrand","wsBrands","ws","accent","bg","GLOBAL_KEY","ACCOUNT_PREFIX","defaultGatewayUrl","GLOBAL_DEFAULTS","ACCOUNT_DEFAULTS","loadGlobal","raw","loadAccount","workspace","activeWorkspace","setActiveWorkspace","loadSettings","saveSettings","next","global","account","DRAFT_PREFIX","draftKey","sessionKey","saveDraft","text","key","loadDraft","clearDraft","_draftTimer","_pendingDraft","scheduleDraftSave","flushDraftSave","parseAgentSessionKey","parts","agentId","rest","QUICK_TAG_RE","FINAL_TAG_RE","THINKING_TAG_RE","applyTrim","mode","stripReasoningTagsFromText","options","cleaned","result","lastIndex","inThinking","match","idx","isClose","formatMs","ms","formatAgo","diff","ahead","sec","min","hr","formatDurationMs","clampText","max","truncateText","toNumber","fallback","stripThinkingTags","ENVELOPE_PREFIX","ENVELOPE_CHANNELS","textCache","thinkingCache","looksLikeEnvelopeHeader","header","label","stripEnvelope","extractText","message","role","content","item","joined","extractTextCached","obj","extractThinking","rawText","extractRawText","extracted","extractThinkingCached","formatReasoningMarkdown","lines","line","HEARTBEAT_PROMPT_PATTERN","HEARTBEAT_RESPONSE_PATTERN","SILENT_REPLY_PATTERN","INTERNAL_PROMPT_PATTERN","isHeartbeatMessage","filterHeartbeatMessages","messages","msg","normalizeMessage","hasToolId","contentRaw","contentItems","hasToolContent","hasToolName","timestamp","id","normalizeRoleForGrouping","lower","isToolResultMessage","uuidFromBytes","bytes","weakRandomBytes","now","generateUUID","cryptoLike","CHAT_PAGE_SIZE","loadChatHistory","state","opts","limit","res","rawMessages","total","filtered","err","loadOlderChatHistory","currentCount","dataUrlToBase64","dataUrl","sendChatMessage","attachments","hasAttachments","imageAtts","fileAtts","contentBlocks","fileNames","displayText","att","runId","allAtts","apiAttachments","parsed","error","abortChatRun","handleChatEvent","payload","current","trimmedCurrent","trimmedExisting","loadSessions","params","activeMinutes","TOOL_STREAM_LIMIT","TOOL_STREAM_THROTTLE_MS","TOOL_OUTPUT_CHAR_LIMIT","extractToolOutputText","record","entry","part","formatToolOutput","contentText","truncated","buildToolStreamMessage","trimToolStream","host","overflow","removed","syncToolStreamMessages","flushToolStreamSync","scheduleToolStreamSync","force","resetToolStream","COMPACTION_TOAST_DURATION_MS","handleCompactionEvent","data","phase","handleAgentEvent","toolCallId","args","output","scrollGen","scheduleChatScroll","gen","pickScrollTarget","container","overflowY","target","distanceFromBottom","retryDelay","latest","latestDistanceFromBottom","scheduleLogsScroll","handleChatScroll","event","captureScrollForPrepend","prevScrollHeight","prevScrollTop","delta","handleLogsScroll","handleSessionLogsScroll","resetChatScroll","exportLogs","blob","url","anchor","stamp","exportSessionLogs","observeTopbar","topbar","update","height","cloneConfigObject","serializeConfigForm","form","setPathValue","path","nextKey","lastKey","loadConfig","applyConfigSnapshot","loadConfigSchema","applyConfigSchema","snapshot","rawFromSnapshot","saveConfig","baseHash","loadCronStatus","loadCronJobs","listParams","buildCronSchedule","amount","unit","expr","buildCronPayload","toParts","timeoutSeconds","addCronJob","schedule","accountId","job","toggleCronJob","enabled","runCronJob","loadCronRuns","handleCronRunEvent","removeCronJob","cronJobToFormState","pad","channel","rawTo","updateCronJob","jobId","patch","loadChannels","probe","startWhatsAppLogin","waitWhatsAppLogin","logoutWhatsApp","addWhatsAppAccount","configRes","config","channels","whatsapp","accounts","removeWhatsAppAccount","binding","loadDebug","status","health","models","heartbeat","modelPayload","ACCESS_SESSION_KEY","DEFAULT_ACCESS_STATE","getStoredSessionToken","storeSessionToken","token","clearSessionToken","checkAccessStatus","verifyPin","pin","setMasterPin","setAccountPin","logout","LOG_BUFFER_LIMIT","LEVELS","parseMaybeJsonString","normalizeLevel","lowered","parseLogLine","meta","time","level","contextCandidate","contextObj","subsystem","loadLogs","entries","shouldReset","ed25519_CURVE","Gx","Gy","_d","L2","captureTrace","isBig","isStr","isBytes","abytes","length","title","len","needsLen","prefix","ofLen","got","u8n","u8fr","buf","padh","bytesToHex","_ch","ch","hexToBytes","hl","al","array","ai","hi","n1","n2","cr","subtle","concatBytes","arrs","sum","randomBytes","big","assertRange","modN","invert","num","md","q","callHash","fn","hashes","apoint","Point","B256","_Point","X","Y","T","__publicField","zip215","normed","lastByte","bytesToNumLE","y2","isValid","uvRatio","isXOdd","isLastByteOdd","X2","Y2","Z2","Z4","aX2","left","right","XY","ZT","other","X1","Y1","Z1","X1Z2","X2Z1","Y1Z2","Y2Z1","x1y1","G","F","X3","Y3","T3","Z3","T1","T2","safe","wNAF","scalar","iz","numTo32bLE","pow2","power","pow_2_252_3","b2","b4","b5","b10","b20","b40","b80","b160","b240","b250","RM1","v3","v7","pow","vx2","root1","root2","useRoot1","useRoot2","noRoot","modL_LE","hash","sha512a","sha512s","hash2extK","hashed","head","point","pointBytes","getExtendedPublicKeyAsync","secretKey","getExtendedPublicKey","getPublicKeyAsync","hashFinishA","_sign","rBytes","signAsync","randomSecretKey","seed","utils","W","scalarBits","pwindows","pwindowSize","precompute","points","w","Gpows","ctneg","cnd","comp","pow_2_w","maxNum","mask","shiftBy","wbits","off","offF","offP","isEven","isNeg","STORAGE_KEY","base64UrlEncode","binary","byte","base64UrlDecode","normalized","padded","out","fingerprintPublicKey","publicKey","generateIdentity","privateKey","loadOrCreateDeviceIdentity","derivedId","updated","identity","stored","signDevicePayload","privateKeyBase64Url","sig","normalizeRole","normalizeScopes","scopes","scope","readStore","writeStore","store","loadDeviceAuthToken","storeDeviceAuthToken","existing","clearDeviceAuthToken","loadDevices","loadNodes","resolveExecApprovalsRpc","loadExecApprovals","rpc","applyExecApprovalsSnapshot","loadPresence","setSkillMessage","getErrorMessage","emptyAddForm","loadSkills","updateSkillEdit","skillKey","updateSkillEnabled","saveSkillApiKey","apiKey","installSkill","installId","viewSkillDetail","closeSkillDetail","setSkillDetailTab","tab","openAddSkillModal","closeAddSkillModal","importDraft","draft","installDraft","saveNewSkill","refs","skillName","deleteDraft","editSkill","editDetailSkill","activeTab","detail","updateFormReference","refName","setEditTab","toggleAlwaysActive","alwaysActive","updateSkillAgents","agents","deleteSkill","TAB_PATHS","PATH_TO_TAB","normalizeBasePath","basePath","normalizePath","pathForTab","tabFromPath","pathname","inferBasePathFromPathname","segments","candidate","getSystemTheme","resolveTheme","clamp01","hasReducedMotionPreference","cleanupThemeTransition","startThemeTransition","nextTheme","applyTheme","context","currentTheme","documentReference","document_","prefersReducedMotion","xPercent","yPercent","rect","transition","SESSION_LOG_BUFFER_LIMIT","loadSessionLogs","rpcParams","loadAuditEntries","clearAudit","messageTimer","setSuccessMessage","loadFileTree","selectFile","filePath","previewFile","toggleSelectFile","remaining","bulkDownloadFiles","paths","successCount","errorMsg","downloadFile","moveFileToDir","targetDir","fileName","dest","moveFile","uploadFiles","dirPath","files","file","buffer","base64","createFolder","parentDir","folderName","deleteFile","from","to","loadMemoryStatus","reindexMemory","chunks","toggleDirectory","searchMemory","query","clearSearch","startNodesPolling","stopNodesPolling","startLogsPolling","stopLogsPolling","startSessionLogsPolling","stopSessionLogsPolling","startDebugPolling","stopDebugPolling","startAuditPolling","stopAuditPolling","startMemoryStatusPolling","app","stopMemoryStatusPolling","applySettings","applyResolvedTheme","setLastActiveSessionKey","applySettingsFromUrl","tokenRaw","passwordRaw","sessionRaw","gatewayUrlRaw","shouldCleanUrl","password","session","gatewayUrl","setTab","refreshActiveTab","syncUrlWithTab","setTheme","loadOverview","loadChannelsTab","loadCron","refreshChat","__vitePreload","sessionLogs","inferBasePath","configured","syncThemeWithSettings","resolved","attachThemeListener","detachThemeListener","syncTabWithLocation","replace","setTabFromRoute","onPopState","targetPath","currentPath","isChatBusy","isChatStopCommand","handleAbortChat","enqueueChatMessage","sendChatMessageNow","ok","flushChatQueue","removeQueuedMessage","handleSendChat","messageOverride","previousDraft","attachmentsToSend","reloadLimit","refreshChatAvatar","flushChatQueueForEvent","resolveAgentIdForSession","_c","buildAvatarMetaUrl","encoded","avatarUrl","icons","html","lockIcon","bellIcon","powerIcon","burgerListenerBound","ensureBurgerOutsideClickListener","cb","renderPageNav","currentPage","wsProps","link","href","links","selectorEl","renderWorkspaceSelector","nothing","logoutEl","restartEl","renderRestartButton","auditCount","auditEl","closeBurger","onRestart","confirmOpen","modal","workspaces","selectedWorkspace","onWorkspaceSelect","select","renderBrowserViewer","props","INTERNAL_DRAG_MIME","pendingDeleteTimer","formatSize","handleDirDrop","internalPath","mdFiles","renderTreeEntry","depth","isDir","isExpanded","isSelected","isCurrent","indent","child","renderBulkActions","count","renderPreview","renderSearchBar","renderSearchResults","renderFiles","uploadTarget","completed","indexed","filePart","model","friendly","UNINSTALL_DONE_KEY","runUninstall","markUninstallDone","checkUninstallDone","clearUninstallDone","renderStatusLight","renderInfoButton","renderInfoModal","rows","headerContent","addr","mins","expiryText","btn","el","maskedKey","getSelectedWorkspace","resolveWorkspaceWhatsApp","formatChannelError","imsgOwned","resolveIMessageState","ts","AUTH_MODE_LABELS","hasAny","akConfigured","row","renderStepIndicator","currentStep","steps","stepOrder","currentIndex","step","stepIndex","isActive","isCompleted","renderLicenseStep","licenseKey","licenseBusy","licenseValid","licenseMessage","licenseDeviceId","onLicenseKeyChange","onLicenseActivate","renderAuthStep","authConnected","authBusy","authMessage","authUrl","authCodeInput","authExpiresIn","onStartAuth","onSubmitAuthCode","onAuthCodeChange","accountMap","selected","renderDashboardHeader","businessName","handleSave","renderGatewayStatusRow","renderClaudeStatusRow","isConnected","renderLicenseStatusRow","boom","renderWhatsAppStatusRow","isLinked","hasAccount","waStatus","waStatusText","isBaileys","isActiveQr","renderWhatsAppSettingsModal","closeModal","infoStyle","labelStyle","valueStyle","selectedWs","ownerWs","thisWsOwns","anotherWsOwns","renderIMessageStatusRow","statusText","renderIMessageActionModal","renderApiKeysSection","renderApiKeysModal","providers","storedKeys","providerId","toggleVisibility","visible","handleInput","changed","saveBtn","eyeBtn","primary","advanced","renderProviderRow","isSaving","justSaved","justRemoved","justDisabled","justEnabled","renderUpdateRow","statusLight","versionText","isBusy","renderPublicChatRow","renderPublicChatSettingsModal","hasGreeting","showVerify","verifyMethods","hasWhatsApp","hasSms","hasEmail","waAccount","whatsAppConnected","renderWidgetSnippetModal","publicUrl","serverUrl","snippet","handleCopy","prev","handleDownload","AGENT_CURATED_MODELS","AGENT_THINKING_LEVELS","AGENT_DEFAULT_MODEL_KEY","renderAgentSettingsRow","summary","renderAgentSettingsModal","catalog","available","agent","currentModelKey","currentThinking","isAdmin","renderBrandingRow","busy","renderBrandingModal","logoUrl","renderTailscaleConnectModal","success","progress","renderRemoteAccessRow","serveEnableUrl","enableUrl","confirmOrError","renderSignalBars","signal","activeBars","renderWifiRow","hasSaved","renderWifiModal","networks","isSaved","net","needsPassword","renderNetworkRow","renderNetworkModal","portChanged","hostnameChanged","hasChanges","renderUpdateModal","showProgress","formatDuration","isSuccess","before","after","durationText","rem","renderAccountPinRow","hasPin","renderAccountPinModal","oldPin","newPin","confirmPin","pinInputHandler","setter","showValidationError","handleSubmit","renderAddAccountForm","workspaceSaving","submitForm","togglePinVisibility","wrapper","renderRemoveAccountSection","renderUninstallSection","confirmed","renderSupportLink","renderWhatsAppStep","whatsappBusy","whatsappLoginMessage","whatsappLoginQrDataUrl","whatsappLoginConnected","whatsappChannelStatus","isReallyConnected","allGood","renderClaudeAuthModal","renderSetup","connected","isUpdating","stepContent","pageNav","renderPhoneEntry","subtitle","renderAdminsPage","iconX","fieldCount","renderDeleteConfirmModal","renderAddFieldModal","canSubmit","renderFieldEditor","renderRecord","expanded","fields","fieldLabel","renderContactsPage","handleSearchSubmit","handleAddSubmit","deleteRecord","addFieldRecord","i$1","setPrototypeOf","isFrozen","getPrototypeOf","getOwnPropertyDescriptor","freeze","seal","create","apply","construct","func","thisArg","_len","_key","Func","_len2","_key2","arrayForEach","unapply","arrayLastIndexOf","arrayPop","arrayPush","arraySplice","stringToLowerCase","stringToString","stringMatch","stringReplace","stringIndexOf","stringTrim","objectHasOwnProperty","regExpTest","typeErrorCreate","unconstruct","_len3","_key3","_len4","_key4","addToSet","set","transformCaseFunc","element","lcElement","cleanArray","index","clone","object","newObject","property","lookupGetter","desc","fallbackValue","html$1","svg$1","svgFilters","svgDisallowed","mathMl$1","mathMlDisallowed","svg","mathMl","xml","MUSTACHE_EXPR","ERB_EXPR","TMPLIT_EXPR","DATA_ATTR","ARIA_ATTR","IS_ALLOWED_URI","IS_SCRIPT_OR_DATA","ATTR_WHITESPACE","DOCTYPE_NAME","CUSTOM_ELEMENT","EXPRESSIONS","NODE_TYPE","getGlobal","_createTrustedTypesPolicy","trustedTypes","purifyHostElement","suffix","ATTR_NAME","policyName","scriptUrl","_createHooksMap","createDOMPurify","window","DOMPurify","document","originalDocument","currentScript","DocumentFragment","HTMLTemplateElement","Node","Element","NodeFilter","NamedNodeMap","HTMLFormElement","DOMParser","ElementPrototype","cloneNode","remove","getNextSibling","getChildNodes","getParentNode","template","trustedTypesPolicy","emptyHTML","implementation","createNodeIterator","createDocumentFragment","getElementsByTagName","importNode","hooks","IS_ALLOWED_URI$1","ALLOWED_TAGS","DEFAULT_ALLOWED_TAGS","ALLOWED_ATTR","DEFAULT_ALLOWED_ATTR","CUSTOM_ELEMENT_HANDLING","FORBID_TAGS","FORBID_ATTR","EXTRA_ELEMENT_HANDLING","ALLOW_ARIA_ATTR","ALLOW_DATA_ATTR","ALLOW_UNKNOWN_PROTOCOLS","ALLOW_SELF_CLOSE_IN_ATTR","SAFE_FOR_TEMPLATES","SAFE_FOR_XML","WHOLE_DOCUMENT","SET_CONFIG","FORCE_BODY","RETURN_DOM","RETURN_DOM_FRAGMENT","RETURN_TRUSTED_TYPE","SANITIZE_DOM","SANITIZE_NAMED_PROPS","SANITIZE_NAMED_PROPS_PREFIX","KEEP_CONTENT","IN_PLACE","USE_PROFILES","FORBID_CONTENTS","DEFAULT_FORBID_CONTENTS","DATA_URI_TAGS","DEFAULT_DATA_URI_TAGS","URI_SAFE_ATTRIBUTES","DEFAULT_URI_SAFE_ATTRIBUTES","MATHML_NAMESPACE","SVG_NAMESPACE","HTML_NAMESPACE","NAMESPACE","IS_EMPTY_INPUT","ALLOWED_NAMESPACES","DEFAULT_ALLOWED_NAMESPACES","MATHML_TEXT_INTEGRATION_POINTS","HTML_INTEGRATION_POINTS","COMMON_SVG_AND_HTML_ELEMENTS","PARSER_MEDIA_TYPE","SUPPORTED_PARSER_MEDIA_TYPES","DEFAULT_PARSER_MEDIA_TYPE","CONFIG","formElement","isRegexOrFunction","testValue","_parseConfig","cfg","ALL_SVG_TAGS","ALL_MATHML_TAGS","_checkValidNamespace","parent","tagName","parentTagName","_forceRemove","node","_removeAttribute","_initDocument","dirty","doc","leadingWhitespace","matches","dirtyPayload","body","_createNodeIterator","_isClobbered","_isNode","_executeHooks","currentNode","hook","_sanitizeElements","_isBasicCustomElement","parentNode","childNodes","childCount","childClone","_isValidAttribute","lcTag","lcName","_sanitizeAttributes","attributes","hookEvent","attr","namespaceURI","attrValue","initValue","_sanitizeShadowDOM","fragment","shadowNode","shadowIterator","importedNode","returnNode","nodeIterator","serializedHTML","tag","entryPoint","hookFunction","purify","me","xe","be","Re","Te","re","se","Oe","Q","we","ye","Pe","Se","ie","$e","U","te","_e","Le","Me","ze","oe","Ae","K","ae","Ce","le","Ie","Ee","Be","ue","qe","ve","pe","De","He","Ze","Ge","Ne","Qe","Fe","je","ce","he","Ue","ne","Ke","We","Xe","ke","J","de","ge","Je","O","ee","fe","marked","allowedTags","allowedAttrs","hooksInstalled","MARKDOWN_CHAR_LIMIT","MARKDOWN_PARSE_LIMIT","MARKDOWN_CACHE_LIMIT","MARKDOWN_CACHE_MAX_CHARS","markdownCache","getCachedMarkdown","setCachedMarkdown","oldest","installHooks","toSanitizedMarkdownHtml","markdown","escapeHtml","sanitized","rendered","COPIED_FOR_MS","ERROR_FOR_MS","COPY_LABEL","COPIED_LABEL","ERROR_LABEL","copyTextToClipboard","setButtonLabel","button","createCopyButton","idleLabel","copied","renderCopyAsMarkdownButton","extractToolCards","normalizeContent","cards","kind","coerceArgs","extractToolText","card","WAVEFORM_BARS","waveformCache","extractWaveform","ctx","peaks","start","end","peak","bars","SPEEDS","playerStates","getOrCreateState","audio","paintWaveform","SVG_NS","createPlaySvg","poly","createPauseSvg","r1","r2","findContainer","waveformEl","frag","bar","updateProgress","barCount","timeEl","formatTime","updatePlayIcon","playing","oldSvg","newSvg","seconds","wiredUrls","wireAudioEvents","renderVoiceNotePlayer","togglePlay","cycleSpeed","seekFromClick","ratio","elapsed","pauseIcon","playIcon","extractImages","images","block","source","mediaType","mimeType","imageUrl","extractFiles","fileIcon","renderReadingIndicatorGroup","_assistant","renderInterimGroup","unsafeHTML","renderStreamingGroup","startedAt","onOpenSidebar","renderGroupedMessage","renderMessageGroup","group","normalizedRole","roleClass","renderMessageImages","img","renderMessageFiles","renderPdfPreview","renderFileCard","openPdfModal","overlay","openLink","closeBtn","line1","line2","frame","isToolResult","hasToolCards","hasImages","hasFiles","extractedText","extractedThinking","markdownBase","reasoningMarkdown","canCopyMarkdown","bubbleClasses","callbacks","holdTimer","pointerDown","cleanup","track","removeGlobalPointerUp","startRecording","stream","recorder","reader","ext","attachment","stopAndSend","cancelRecording","addGlobalPointerUp","onGlobalPointerUp","onMicPointerDown","onRecordingPointerMove","dx","isRecording","setCallbacks","cbs","renderMicButton","renderRecordingUI","renderMarkdownSidebar","ResizableDivider","LitElement","containerWidth","deltaRatio","newRatio","css","__decorateClass","customElement","assertNonEmptyString","str","assertNumber","number","DB_VERSION_CURRENT","DB_VERSION_INITIAL","STORE_EMOJI","STORE_KEYVALUE","STORE_FAVORITES","FIELD_TOKENS","INDEX_TOKENS","FIELD_UNICODE","INDEX_COUNT","FIELD_GROUP","FIELD_ORDER","INDEX_GROUP_AND_ORDER","KEY_ETAG","KEY_URL","KEY_PREFERRED_SKINTONE","MODE_READONLY","MODE_READWRITE","INDEX_SKIN_UNICODE","FIELD_SKIN_UNICODE","DEFAULT_DATA_SOURCE","DEFAULT_LOCALE","uniqBy","arr","uniqEmoji","emojis","initialMigration","db","createObjectStore","keyPath","indexes","indexName","multiEntry","openIndexedDBRequests","databaseCache","onCloseListeners","handleOpenOrDeleteReq","resolve","reject","req","createDatabase","dbName","closeDatabase","openDatabase","dbPromise","storeName","readOnlyOrReadWrite","txn","listeners","listener","deleteDatabase","addOnCloseListener","irregularEmoticons","extractTokens","word","MIN_SEARCH_TEXT_LENGTH","normalizeTokens","transformEmojiData","emojiData","annotation","emoticon","order","shortcodes","skins","tags","emoji","version","tokens","tone","callStore","method","getIDB","getAllIDB","commit","minBy","minItem","findCommonMembers","arrays","uniqByFunc","shortestArray","results","isEmpty","get","hasData","eTag","oldETag","oldUrl","doFullDatabaseScanForSingleResult","predicate","emojiStore","processNextBatch","loadData","transformedData","metaStore","todo","checkFetched","onFetched","getEmojiByGroup","range","getEmojiBySearchQuery","intermediateResults","checkDone","onDone","getEmojiByShortcode","shortcode","getEmojiByUnicode","unicode","incrementFavoriteEmojiCount","getTopFavoriteEmoji","customEmojiIndex","favoritesStore","cursor","addResult","unicodeOrName","custom","CODA_MARKER","trie","itemToTokens","map","currentMap","char","nextMap","valuesAtCoda","exact","queue","entriesSortedByKey","requiredKeys$1","assertCustomEmojis","customEmojis","isArray","firstItemIsFaulty","sortByName","all","searchTrie","searchByExactMatch","searchByPrefix","search","shortcodeToEmoji","nameToEmoji","customEmoji","isFirefoxContentScript","cleanEmoji","warnETag","requiredKeys","assertEmojiData","assertStatus","response","dataSource","getETag","getETagAndData","arrayBufferToBinaryString","binaryStringToArrayBuffer","jsonChecksum","inString","inBuffer","outBuffer","outBinString","doCheckForUpdates","eTagAndData","loadDataForFirstTime","checkForUpdates","Database","locale","checkReady","customs","natives","skinTone","allGroups","groups","NUM_SKIN_TONES","rIC","hasZwj","versionsAndTestEmoji","TIMEOUT_BEFORE_LOADING_MESSAGE","DEFAULT_SKIN_TONE_EMOJI","DEFAULT_NUM_COLUMNS","MOST_COMMONLY_USED_EMOJI","FONT_FAMILY","DEFAULT_CATEGORY_SORTING","getTextFeature","canvas","compareFeatures","feature1","feature2","feature1Str","feature2Str","testColorEmojiSupported","determineEmojiSupportLevel","promise","detectEmojiSupportLevel","supportedZwjEmojis","VARIATION_SELECTOR","SKINTONE_MODIFIER","ZWJ","LIGHT_SKIN_TONE","LIGHT_SKIN_TONE_MODIFIER","applySkinTone","zwjIndex","halt","incrementOrDecrement","decrement","summarizeEmojisForUI","emojiSupportLevel","toSimpleSkinsMap","skin","category","rAF","resizeObserverSupported","resizeObserverAction","abortSignal","onUpdate","resizeObserver","calculateTextWidth","baselineEmojiWidth","checkZwjSupport","zwjEmojisToCheck","baselineEmoji","emojiToDomNode","allSupported","shouldWarn","domNode","emojiWidth","supported","uniq","resetScrollTopIfPossible","getFromMap","cache","toString","parseTemplate","htmlString","parseCache","domInstancesCache","unkeyedSymbol","hasReplaceChildren","replaceChildren","newChildren","doChildrenNeedRerender","oldChild","oldChildrenCount","patchChildren","instanceBinding","targetNode","targetParentNode","needsRerender","expressions","instanceBindings","currentExpression","expressionIndex","attributeName","attributeValuePre","attributeValuePost","expression","newValue","newNode","parse","withinTag","withinAttribute","elementIndexCounter","elementsToBindings","elementIndexes","skipTokenChars","elementIndex","bindings","attributePreMatch","attributePostMatch","applyBindings","traverseAndSetupBindings","rootElement","topLevelBindings","treeWalker","parseHtml","dom","createFramework","domInstances","domInstanceCacheKey","domInstancesForTokens","callback","keyFunction","originalCacheKey","render","helpers","events","actions","actionContext","firstRender","labelWithSkin","titleForEmoji","unicodeWithSkin","emojiList","searchMode","rootDom","emojiWithCategory","forElementWithAttribute","eventName","listenerName","ref","action","boundActions","qM","createState","destroyed","currentObserver","propsToObservers","dirtyObservers","queued","flush","observersToRun","observer","observers","createEffect","runnable","oldObserver","arraysAreEqualByFunction","areEqualFunc","intersectionObserverCache","intersectionObserverAction","EMPTY_ARRAY","assign","createRoot","shadowRoot","abortController","focus","fireEvent","compareEmojiArrays","compareCurrentEmojisWithCategories","aCategory","aEmojis","bCategory","bEmojis","updateCurrentEmojis","newEmojis","updateSearchMode","newSearchMode","updateCurrentEmojisWithCategories","newEmojisWithCategories","currentSkinTone","onClickSkinToneButton","onEmojiClick","onNavClick","onNavKeydown","onSearchKeydown","onSkinToneOptionsClick","onSkinToneOptionsFocusOut","onSkinToneOptionsKeydown","onSkinToneOptionsKeyup","onSearchInput","calculateEmojiGridStyle","updateOnIntersection","handleDatabaseLoading","showingLoadingMessage","timeoutHandle","updateCustomEmoji","updatePreferredSkinTone","updateDefaultFavoriteEmojis","database","favs","databaseCustomEmoji","updateFavorites","defaultFavoriteEmojis","numColumns","dbFavorites","favorites","summarizeEmojis","style","newNumColumns","newIsRtl","isIntersecting","updateEmojis","searchText","currentGroup","databaseLoaded","getEmojisBySearchQuery","currentGroupId","getEmojisByGroup","resetScrollTopInRaf","currentEmojis","emojiVersion","checkZwjSupportAndUpdate","isZwjSupported","filterEmojisByVersion","calculateCurrentEmojisWithCategories","categoriesToEmoji","rawSearchText","goToNextOrPrevious","previous","clickEmoji","closestTarget","groupId","doFocus","getDetailForClickEvent","emojiSummary","skinTonedUnicode","promiseForDetail","changeSkinTone","changeActiveSkinTone","nextSkinTone","relatedTarget","newState","enI18n","baseStyles","PROPS","EXTRA_STYLES","PickerElement","rescueElementPrototype","attrName","oldValue","up","definitions","autoGrow","desired","resetGrow","renderCompactionIndicator","MAX_ATTACHMENT_BYTES","generateAttachmentId","showAttachmentError","toast","compose","TEXT_EXTENSIONS","isImageFile","isTextFile","isPdfFile","isVideoFile","processAttachmentFile","errorEl","newAtt","handleDrop","newAttachment","handleDragOver","handleDragLeave","related","handlePaste","items","mediaItems","chatEl","isVideo","toggleEmojiPicker","popup","isOpen","close","ev","handleEmojiSelect","ta","pos","renderAttachmentPreview","renderChat","canCompose","canAbort","activeSession","reasoningLevel","showReasoning","composePlaceholder","setVoiceCallbacks","recording","showMic","splitRatio","sidebarOpen","thread","repeat","buildChatItems","main","groupMessages","history","tools","showToolDetail","mediaBlocks","messageKey","qi","messageId","formatTimestamp","jidToDisplay","jid","renderConversationList","renderConversationRow","conv","onSelect","activationBadge","renderConversationHeader","renderGroupSettings","info","renderMessages","renderWhatsAppTab","externalLinkIcon","renderChatPage","publicBtn","tabBar","loadConversations","selectConversation","msgsRes","groupRes","setGroupActivation","activation","formatNextRun","formatCronState","last","formatCronSchedule","humanizeCron","tz","minute","hour","month","dow","tzSuffix","fmtTime","hours","parseField","timeList","timeStr","DOW_NAMES","days","field","formatCronPayload","truncate","formatCronDeliveryTarget","labels","buildChannelOptions","seen","resolveChannelLabel","formatRecipients","agentLabel","iconPlay","iconPause","iconTrash","iconZap","iconPlus","iconEdit","renderCron","detailJob","formModalOpen","renderStatusBar","renderEventGrid","renderEventFormModal","renderDetailModal","renderRunModal","jobCount","nextWake","renderEventCard","isEdit","channelOptions","onClose","renderScheduleFields","renderRecipientsList","recipients","recipient","renderRun","running","statusLabel","runStatusClass","renderSkills","skills","filter","typeFilter","agentFilter","skill","typeChip","agentChip","renderSkill","renderAddModal","canInstall","missing","reasons","renderAgentCheckboxes","locked","hasAdmin","hasPublic","toggle","checked","tabs","activeContent","handleOverlayClick","skillEntry","isUserSkill","hasDrafts","formActive","isInstalled","renderSkillForm","renderDraftsList","saveLabel","hasRefs","activeRef","tabChip","alreadyInstalled","TYPES","TYPE_LABELS","resolveDisplayType","type","date","formatSessionLabel","matchesFilter","needle","entryKey","CONTENT_PREVIEW_LENGTH","passesTypeFilter","typeFilters","display","renderSessionLogs","isLong","renderLogs","isSession","sp","displayType","levelFiltered","exportLabel","renderSystemLogs","dates","currentDate","hasNewer","hasOlder","nextIdx","DAY_LABELS","renderOpeningHours","renderEnabledToggle","renderPublicAgentToggle","renderWeeklySchedule","renderClosedDates","renderSaveButton","hoursEnabled","day","renderDayRow","dayState","isClosed","_newClosedDate","TABS","renderTabContent","renderAdvancedPage","renderLoginOverlay","brand","isFirstTime","isChangeMode","changeBusy","selectedAccount","handleAccountChange","accountSelector","acc","handleChangePinSubmit","pinValue","confirmValue","renderPublicChatPage","chatProps","loadAgents","loadWorkspaces","createWorkspace","removeWorkspace","renameWorkspace","displayName","GATEWAY_CLIENT_IDS","GATEWAY_CLIENT_NAMES","GATEWAY_CLIENT_MODES","buildDeviceAuthPayload","CONNECT_FAILED_CLOSE_CODE","GatewayBrowserClient","reason","delay","isSecureContext","deviceIdentity","canFallbackToShared","authToken","storedToken","auth","device","signedAtMs","nonce","signature","hello","evt","seq","pending","_f","isRecord","parseExecApprovalRequested","request","command","createdAtMs","expiresAtMs","parseExecApprovalResolved","pruneExecApprovalQueue","addExecApproval","removeExecApproval","BrowserCanvasRenderer","base64Data","metadata","canvasX","canvasY","scaleX","scaleY","viewportScaleX","viewportScaleY","canvasRenderer","getCanvasRenderer","startScreencast","stopScreencast","sendMouseInput","sendKeyInput","completeHandoff","toggleInputMode","toggleFullscreen","handleScreencastFrame","handleHandoffEvent","handleHandoffResolved","loadAssistantIdentity","loadApiKeyProviders","client","saveApiKey","provider","removeApiKey","disableApiKey","disabled","UPDATE_PENDING_KEY","runUpdate","DISMISS_KEY","clearUpdatePending","handleUpdateProgress","durationMs","errorDetail","fetchLastUpdateResult","hadPendingFlag","isUpdatePending","RECENT_MS","isRecent","isDismissedResult","afterVersion","dismissUpdateResult","resultTs","dismissedAt","BANNER_ID","renderNotificationBanner","notification","banner","dismiss","normalizeSessionKeyForDefaults","defaults","mainSessionKey","mainKey","defaultAgentId","applySessionDefaults","resolvedSessionKey","resolvedSettingsSessionKey","resolvedLastActiveSessionKey","nextSessionKey","nextSettings","shouldUpdateSettings","connectGateway","connectedVersion","isPublic","isStandalonePage","clientName","incomingVersion","applySnapshot","resolveAnonymousSession","loadModelCatalog","loadTailscaleStatus","loadWifiStatus","loadNetworkStatus","code","handleGatewayEvent","expected","received","handleGatewayEventUnsafe","fetchApiKeyProviders","scanResult","freshStatus","active","PUBLIC_COOKIE_NAME","getOrCreatePublicCookieId","ttlDays","expires","cookieId","acctId","otpBusy","otpError","otpPhone","otpEmail","otpName","otpDeliveryChannel","otpIdentifierType","otpPreferredChannel","normalizePhone","resetOtpState","startAnonymousSession","requestOtp","phone","requestEmailOtp","email","verifyOtp","identifier","renderAvatar","_props","renderPhoneForm","renderEmailForm","renderOtpForm","otpCode","isEmailOtp","channelLabel","displayIdentifier","backStep","renderPublicAuth","authMode","authStep","otpAvailable","methods","hasPhone","verifyAvailable","isEmailContext","defaultOpeningHoursForm","DAY_KEYS","loadOpeningHours","oh","sched","saveOpeningHours","timezone","openingHours","extractAdminPhones","targetAgentId","peer","buildBindingsWithAdmins","existingBindings","phones","isAdminAgent","existingMetaMap","existingAccountIdMap","newBindings","resolvedAccountId","matchObj","existingMeta","loadAdmins","adminAgentId","addAdmin","newPhones","updatedBindings","removeAdmin","loadContacts","addContact","normalizedPhone","trimmedName","deleteContact","setContactField","deleteContactField","_tsProgressInterval","_tsPollInterval","_tsPollTimeout","TS_PROGRESS_MESSAGES","clearTailscaleTimers","buildWorkspaceNavProps","buildSetupWorkspaceNavProps","resolveAdminAgentId","getSelectedWorkspaceInfo","adminAgent","resolveWhatsAppAccountId","resolveFilesAgentId","resolveWorkspaceName","AVATAR_DATA_RE","AVATAR_HTTP_RE","resolveAssistantAvatarUrl","list","extractWhatsAppStatus","extractIMessageStatus","resolveIMessageOwnerWorkspace","imsgBinding","defaultWs","buildWhatsAppState","proxy","scrollWhatsAppMessagesToBottom","buildWhatsAppProps","waState","renderApp","greeting","realMessages","chatMessages","loadChatHistory2","accessState","accountOrPin","whatsappAccounts","imsg","imessageOwnerWorkspace","refreshTailscaleStatus","startTailscaleProgress","startTime","threshold","workspacePath","adding","acct","newPolicy","policyFields","wa","accts","acctCfg","wildcard","currentPolicy","enabling","groupsPatch","requireMention","groupsField","nonImessageBindings","imessageBindings","baseUrl","fullUrl","successMsg","loadApiKeys","pc","accountSettings","greetings","freshSnapshot","fromAddr","agentsList","cfgEntry","modelRaw","memSearch","modelRef","effectiveLevel","existingBrand","brands","_removed","rpcErr","statusResult","connectingSsid","ssid","port","hostname","portStr","portNum","newHostname","currentProtocol","newHost","newPort","newUrl","filesAgentId","searchAgent","startBrowserScreencast","stopBrowserScreencast","coords","renderer","modifiers","waAccountId","wsName","chatDisabledReason","assistantAvatarUrl","chatAvatarUrl","publicChatOn","lim","_g","_h","_i","_j","folderLabel","renderAuditModal","onClear","DEFAULT_LOG_LEVEL_FILTERS","DEFAULT_CRON_FORM","handleConnected","faviconLink","handleFirstUpdated","handleDisconnected","handleUpdated","justConnected","justEnteredAuth","justEnteredSetup","forcedByTab","forcedByLoad","createNostrProfileFormState","profile","values","handleWhatsAppStart","handleWhatsAppWait","handleWhatsAppLogout","handleAddWhatsAppAccount","handleRemoveWhatsAppAccount","handleChannelConfigSave","handleChannelConfigReload","parseValidationErrors","details","errors","rawField","resolveNostrAccountId","buildNostrProfileUrl","handleNostrProfileEdit","handleNostrProfileCancel","handleNostrProfileFieldChange","handleNostrProfileToggleAdvanced","handleNostrProfileSave","errorMessage","handleNostrProfileImport","merged","nextValues","showAdvanced","importRefreshToken","checkAuthStatus","startAuth","submitAuthCode","updateAuthCodeInput","checkLicenseStatus","activateLicense","removeLicense","updateLicenseKey","loadGatewayHealth","restartGateway","injectedAssistantIdentity","resolveOnboardingMode","resolveSetupMode","resolveFilesPageMode","resolveBrowserPageMode","resolveAdminsPageMode","resolveContactsPageMode","resolveChatPageMode","resolveAdvancedPageMode","TaskmasterApp","defaultOpeningHoursFormFn","onPopStateInternal","poll","connectGatewayInternal","handleChatScrollInternal","handleLogsScrollInternal","handleSessionLogsScrollInternal","exportLogsInternal","exportSessionLogsInternal","resetToolStreamInternal","resetChatScrollInternal","loadAssistantIdentityInternal","applySettingsInternal","setTabInternal","setThemeInternal","loadOverviewInternal","wsInfo","loadCronInternal","handleAbortChatInternal","removeQueuedMessageInternal","handleSendChatInternal","handleWhatsAppStartInternal","handleWhatsAppWaitInternal","handleWhatsAppLogoutInternal","handleAddWhatsAppAccountInternal","handleRemoveWhatsAppAccountInternal","checkAccessStatusInternal","verifyPinInternal","setMasterPinInternal","logoutInternal","verifyResult","checkLicenseStatusInternal","activateLicenseInternal","removeLicenseInternal","updateLicenseKeyInternal","checkAuthStatusInternal","startAuthInternal","submitAuthCodeInternal","updateAuthCodeInputInternal","importRefreshTokenInternal","loadGatewayHealthInternal","restartGatewayInternal","checkForUpdatesInternal","runUpdateInternal","dismissUpdateResultInternal","uninstall","loadAuditEntriesInternal","clearAuditInternal","loadFileTreeInternal","loadMemoryStatusInternal","admins","newSessionKey","chat","scheduleChatScrollInternal","restoreScroll","logs","handleChannelConfigSaveInternal","handleChannelConfigReloadInternal","handleNostrProfileEditInternal","handleNostrProfileCancelInternal","handleNostrProfileFieldChangeInternal","handleNostrProfileSaveInternal","handleNostrProfileImportInternal","handleNostrProfileToggleAdvancedInternal","decision","contacts"],"ignoreList":[0,1,2,3,4,5,6,27,52,53,54,55,56,57,66,67],"sources":["../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/css-tag.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/reactive-element.js","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/lit-html.js","../../../node_modules/.pnpm/lit-element@4.2.2/node_modules/lit-element/lit-element.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/decorators/custom-element.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/decorators/property.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/decorators/state.js","../../../ui/src/ui/assistant-identity.ts","../../../ui/src/ui/brand.ts","../../../ui/src/ui/storage.ts","../../../src/sessions/session-key-utils.ts","../../../src/shared/text/reasoning-tags.ts","../../../ui/src/ui/format.ts","../../../ui/src/ui/chat/message-extract.ts","../../../ui/src/ui/chat/message-normalizer.ts","../../../ui/src/ui/uuid.ts","../../../ui/src/ui/controllers/chat.ts","../../../ui/src/ui/controllers/sessions.ts","../../../ui/src/ui/app-tool-stream.ts","../../../ui/src/ui/app-scroll.ts","../../../ui/src/ui/controllers/config/form-utils.ts","../../../ui/src/ui/controllers/config.ts","../../../ui/src/ui/controllers/cron.ts","../../../ui/src/ui/controllers/channels.ts","../../../ui/src/ui/controllers/debug.ts","../../../ui/src/ui/controllers/access.ts","../../../ui/src/ui/controllers/logs.ts","../../../node_modules/.pnpm/@noble+ed25519@3.0.0/node_modules/@noble/ed25519/index.js","../../../ui/src/ui/device-identity.ts","../../../ui/src/ui/device-auth.ts","../../../ui/src/ui/controllers/devices.ts","../../../ui/src/ui/controllers/nodes.ts","../../../ui/src/ui/controllers/exec-approvals.ts","../../../ui/src/ui/controllers/presence.ts","../../../ui/src/ui/controllers/skills.ts","../../../ui/src/ui/navigation.ts","../../../ui/src/ui/theme.ts","../../../ui/src/ui/theme-transition.ts","../../../ui/src/ui/controllers/session-logs.ts","../../../ui/src/ui/controllers/audit.ts","../../../ui/src/ui/controllers/files.ts","../../../ui/src/ui/app-polling.ts","../../../ui/src/ui/app-settings.ts","../../../ui/src/ui/app-chat.ts","../../../ui/src/ui/icons.ts","../../../ui/src/ui/views/page-nav.ts","../../../ui/src/ui/views/browser-viewer.ts","../../../ui/src/ui/views/files.ts","../../../ui/src/ui/controllers/uninstall.ts","../../../ui/src/ui/views/setup.ts","../../../ui/src/ui/views/admins.ts","../../../ui/src/ui/views/contacts.ts","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directive.js","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directive-helpers.js","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directives/repeat.js","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directives/unsafe-html.js","../../../node_modules/.pnpm/dompurify@3.3.1/node_modules/dompurify/dist/purify.es.mjs","../../../node_modules/.pnpm/marked@17.0.1/node_modules/marked/lib/marked.esm.js","../../../ui/src/ui/markdown.ts","../../../ui/src/ui/chat/copy-as-markdown.ts","../../../ui/src/ui/chat/tool-cards.ts","../../../ui/src/ui/chat/voice-note-player.ts","../../../ui/src/ui/chat/grouped-render.ts","../../../ui/src/ui/chat/voice-recorder.ts","../../../ui/src/ui/views/markdown-sidebar.ts","../../../ui/src/ui/components/resizable-divider.ts","../../../node_modules/.pnpm/emoji-picker-element@1.29.0/node_modules/emoji-picker-element/database.js","../../../node_modules/.pnpm/emoji-picker-element@1.29.0/node_modules/emoji-picker-element/picker.js","../../../ui/src/ui/views/chat.ts","../../../ui/src/ui/views/whatsapp-tab.ts","../../../ui/src/ui/views/chat-page.ts","../../../ui/src/ui/controllers/whatsapp.ts","../../../ui/src/ui/presenter.ts","../../../ui/src/ui/views/cron.ts","../../../ui/src/ui/views/skills.ts","../../../ui/src/ui/views/session-logs.ts","../../../ui/src/ui/views/logs.ts","../../../ui/src/ui/views/opening-hours.ts","../../../ui/src/ui/views/advanced.ts","../../../ui/src/ui/views/login.ts","../../../ui/src/ui/views/public-chat-page.ts","../../../ui/src/ui/controllers/agents.ts","../../../ui/src/ui/controllers/workspaces.ts","../../../src/gateway/protocol/client-info.ts","../../../src/gateway/device-auth.ts","../../../ui/src/ui/gateway.ts","../../../ui/src/ui/controllers/exec-approval.ts","../../../ui/src/ui/browser-canvas.ts","../../../ui/src/ui/controllers/browser-viewer.ts","../../../ui/src/ui/controllers/assistant-identity.ts","../../../ui/src/ui/controllers/apikeys.ts","../../../ui/src/ui/controllers/update.ts","../../../ui/src/ui/views/notification-banner.ts","../../../ui/src/ui/app-gateway.ts","../../../ui/src/ui/views/public-auth.ts","../../../ui/src/ui/controllers/opening-hours.ts","../../../ui/src/ui/controllers/admins.ts","../../../ui/src/ui/controllers/contacts.ts","../../../ui/src/ui/app-render.ts","../../../ui/src/ui/views/audit-modal.ts","../../../ui/src/ui/app-defaults.ts","../../../ui/src/ui/app-lifecycle.ts","../../../ui/src/ui/views/channels.nostr-profile-form.ts","../../../ui/src/ui/app-channels.ts","../../../ui/src/ui/controllers/auth.ts","../../../ui/src/ui/controllers/license.ts","../../../ui/src/ui/controllers/gateway.ts","../../../ui/src/ui/app.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&\"adoptedStyleSheets\"in Document.prototype&&\"replace\"in CSSStyleSheet.prototype,s=Symbol(),o=new WeakMap;class n{constructor(t,e,o){if(this._$cssResult$=!0,o!==s)throw Error(\"CSSResult is not constructable. Use `unsafeCSS` or `css` instead.\");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const s=this.t;if(e&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o.set(s,t))}return t}toString(){return this.cssText}}const r=t=>new n(\"string\"==typeof t?t:t+\"\",void 0,s),i=(t,...e)=>{const o=1===t.length?t[0]:e.reduce((e,s,o)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if(\"number\"==typeof t)return t;throw Error(\"Value passed to 'css' function must be a 'css' function result: \"+t+\". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.\")})(s)+t[o+1],t[0]);return new n(o,t,s)},S=(s,o)=>{if(e)s.adoptedStyleSheets=o.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of o){const o=document.createElement(\"style\"),n=t.litNonce;void 0!==n&&o.setAttribute(\"nonce\",n),o.textContent=e.cssText,s.appendChild(o)}},c=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e=\"\";for(const s of t.cssRules)e+=s.cssText;return r(e)})(t):t;export{n as CSSResult,S as adoptStyles,i as css,c as getCompatibleStyle,e as supportsAdoptingStyleSheets,r as unsafeCSS};\n//# sourceMappingURL=css-tag.js.map\n","import{getCompatibleStyle as t,adoptStyles as s}from\"./css-tag.js\";export{CSSResult,css,supportsAdoptingStyleSheets,unsafeCSS}from\"./css-tag.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const{is:i,defineProperty:e,getOwnPropertyDescriptor:h,getOwnPropertyNames:r,getOwnPropertySymbols:o,getPrototypeOf:n}=Object,a=globalThis,c=a.trustedTypes,l=c?c.emptyScript:\"\",p=a.reactiveElementPolyfillSupport,d=(t,s)=>t,u={toAttribute(t,s){switch(s){case Boolean:t=t?l:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,s){let i=t;switch(s){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},f=(t,s)=>!i(t,s),b={attribute:!0,type:String,converter:u,reflect:!1,useDefault:!1,hasChanged:f};Symbol.metadata??=Symbol(\"metadata\"),a.litPropertyMetadata??=new WeakMap;class y extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=b){if(s.state&&(s.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=!0),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),h=this.getPropertyDescriptor(t,i,s);void 0!==h&&e(this.prototype,t,h)}}static getPropertyDescriptor(t,s,i){const{get:e,set:r}=h(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t}};return{get:e,set(s){const h=e?.call(this);r?.call(this,s),this.requestUpdate(t,h,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(d(\"elementProperties\")))return;const t=n(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(d(\"finalized\")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(d(\"properties\"))){const t=this.properties,s=[...r(t),...o(t)];for(const i of s)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(t(s))}else void 0!==s&&i.push(t(s));return i}static _$Eu(t,s){const i=s.attribute;return!1===i?void 0:\"string\"==typeof i?i:\"string\"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return s(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,s,i){this._$AK(t,i)}_$ET(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&!0===i.reflect){const h=(void 0!==i.converter?.toAttribute?i.converter:u).toAttribute(s,i.type);this._$Em=t,null==h?this.removeAttribute(e):this.setAttribute(e,h),this._$Em=null}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),h=\"function\"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u;this._$Em=e;const r=h.fromAttribute(s,t.type);this[e]=r??this._$Ej?.get(e)??r,this._$Em=null}}requestUpdate(t,s,i,e=!1,h){if(void 0!==t){const r=this.constructor;if(!1===e&&(h=this[t]),i??=r.getPropertyOptions(t),!((i.hasChanged??f)(h,s)||i.useDefault&&i.reflect&&h===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,s,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,s,{useDefault:i,reflect:e,wrapped:h},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??s??this[t]),!0!==h||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),!0===e&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,s]of this._$Ep)this[t]=s;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[s,i]of t){const{wrapped:t}=i,e=this[s];!0!==t||this._$AL.has(s)||void 0===e||this.C(s,void 0,i,e)}}let t=!1;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(s)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(s)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}}y.elementStyles=[],y.shadowRootOptions={mode:\"open\"},y[d(\"elementProperties\")]=new Map,y[d(\"finalized\")]=new Map,p?.({ReactiveElement:y}),(a.reactiveElementVersions??=[]).push(\"2.1.2\");export{y as ReactiveElement,s as adoptStyles,u as defaultConverter,t as getCompatibleStyle,f as notEqual};\n//# sourceMappingURL=reactive-element.js.map\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=globalThis,i=t=>t,s=t.trustedTypes,e=s?s.createPolicy(\"lit-html\",{createHTML:t=>t}):void 0,h=\"$lit$\",o=`lit$${Math.random().toFixed(9).slice(2)}$`,n=\"?\"+o,r=`<${n}>`,l=document,c=()=>l.createComment(\"\"),a=t=>null===t||\"object\"!=typeof t&&\"function\"!=typeof t,u=Array.isArray,d=t=>u(t)||\"function\"==typeof t?.[Symbol.iterator],f=\"[ \\t\\n\\f\\r]\",v=/<(?:(!--|\\/[^a-zA-Z])|(\\/?[a-zA-Z][^>\\s]*)|(\\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${f}(?:([^\\\\s\"'>=/]+)(${f}*=${f}*(?:[^ \\t\\n\\f\\r\"'\\`<>=]|(\"|')|))|$)`,\"g\"),g=/'/g,$=/\"/g,y=/^(?:script|style|textarea|title)$/i,x=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),b=x(1),w=x(2),T=x(3),E=Symbol.for(\"lit-noChange\"),A=Symbol.for(\"lit-nothing\"),C=new WeakMap,P=l.createTreeWalker(l,129);function V(t,i){if(!u(t)||!t.hasOwnProperty(\"raw\"))throw Error(\"invalid template strings array\");return void 0!==e?e.createHTML(i):i}const N=(t,i)=>{const s=t.length-1,e=[];let n,l=2===i?\"<svg>\":3===i?\"<math>\":\"\",c=v;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,f=0;for(;f<s.length&&(c.lastIndex=f,u=c.exec(s),null!==u);)f=c.lastIndex,c===v?\"!--\"===u[1]?c=_:void 0!==u[1]?c=m:void 0!==u[2]?(y.test(u[2])&&(n=RegExp(\"</\"+u[2],\"g\")),c=p):void 0!==u[3]&&(c=p):c===p?\">\"===u[0]?(c=n??v,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?p:'\"'===u[3]?$:g):c===$||c===g?c=p:c===_||c===m?c=v:(c=p,n=void 0);const x=c===p&&t[i+1].startsWith(\"/>\")?\" \":\"\";l+=c===v?s+r:d>=0?(e.push(a),s.slice(0,d)+h+s.slice(d)+o+x):s+o+(-2===d?i:x)}return[V(t,l+(t[s]||\"<?>\")+(2===i?\"</svg>\":3===i?\"</math>\":\"\")),e]};class S{constructor({strings:t,_$litType$:i},e){let r;this.parts=[];let l=0,a=0;const u=t.length-1,d=this.parts,[f,v]=N(t,i);if(this.el=S.createElement(f,e),P.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(r=P.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(h)){const i=v[a++],s=r.getAttribute(t).split(o),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:l,name:e[2],strings:s,ctor:\".\"===e[1]?I:\"?\"===e[1]?L:\"@\"===e[1]?z:H}),r.removeAttribute(t)}else t.startsWith(o)&&(d.push({type:6,index:l}),r.removeAttribute(t));if(y.test(r.tagName)){const t=r.textContent.split(o),i=t.length-1;if(i>0){r.textContent=s?s.emptyScript:\"\";for(let s=0;s<i;s++)r.append(t[s],c()),P.nextNode(),d.push({type:2,index:++l});r.append(t[i],c())}}}else if(8===r.nodeType)if(r.data===n)d.push({type:2,index:l});else{let t=-1;for(;-1!==(t=r.data.indexOf(o,t+1));)d.push({type:7,index:l}),t+=o.length-1}l++}}static createElement(t,i){const s=l.createElement(\"template\");return s.innerHTML=t,s}}function M(t,i,s=t,e){if(i===E)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=a(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(!1),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=M(t,h._$AS(t,i.values),h,e)),i}class R{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??l).importNode(i,!0);P.currentNode=e;let h=P.nextNode(),o=0,n=0,r=s[0];for(;void 0!==r;){if(o===r.index){let i;2===r.type?i=new k(h,h.nextSibling,this,t):1===r.type?i=new r.ctor(h,r.name,r.strings,this,t):6===r.type&&(i=new Z(h,this,t)),this._$AV.push(i),r=s[++n]}o!==r?.index&&(h=P.nextNode(),o++)}return P.currentNode=l,e}p(t){let i=0;for(const s of this._$AV)void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++}}class k{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=A,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=M(this,t,i),a(t)?t===A||null==t||\"\"===t?(this._$AH!==A&&this._$AR(),this._$AH=A):t!==this._$AH&&t!==E&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):d(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==A&&a(this._$AH)?this._$AA.nextSibling.data=t:this.T(l.createTextNode(t)),this._$AH=t}$(t){const{values:i,_$litType$:s}=t,e=\"number\"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=S.createElement(V(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else{const t=new R(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t}}_$AC(t){let i=C.get(t.strings);return void 0===i&&C.set(t.strings,i=new S(t)),i}k(t){u(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new k(this.O(c()),this.O(c()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e)}_$AR(t=this._$AA.nextSibling,s){for(this._$AP?.(!1,!0,s);t!==this._$AB;){const s=i(t).nextSibling;i(t).remove(),t=s}}setConnected(t){void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t))}}class H{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=A,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||\"\"!==s[0]||\"\"!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A}_$AI(t,i=this,s,e){const h=this.strings;let o=!1;if(void 0===h)t=M(this,t,i,0),o=!a(t)||t!==this._$AH&&t!==E,o&&(this._$AH=t);else{const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=M(this,e[s+n],i,n),r===E&&(r=this._$AH[n]),o||=!a(r)||r!==this._$AH[n],r===A?t=A:t!==A&&(t+=(r??\"\")+h[n+1]),this._$AH[n]=r}o&&!e&&this.j(t)}j(t){t===A?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??\"\")}}class I extends H{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===A?void 0:t}}class L extends H{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==A)}}class z extends H{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5}_$AI(t,i=this){if((t=M(this,t,i,0)??A)===E)return;const s=this._$AH,e=t===A&&s!==A||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==A&&(s===A||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){\"function\"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}}class Z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){M(this,t)}}const j={M:h,P:o,A:n,C:1,L:N,R,D:d,V:M,I:k,H,N:L,U:z,B:I,F:Z},B=t.litHtmlPolyfillSupport;B?.(S,k),(t.litHtmlVersions??=[]).push(\"3.3.2\");const D=(t,i,s)=>{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new k(i.insertBefore(c(),t),t,void 0,s??{})}return h._$AI(t),h};export{j as _$LH,b as html,T as mathml,E as noChange,A as nothing,D as render,w as svg};\n//# sourceMappingURL=lit-html.js.map\n","import{ReactiveElement as t}from\"@lit/reactive-element\";export*from\"@lit/reactive-element\";import{render as e,noChange as r}from\"lit-html\";export*from\"lit-html\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const s=globalThis;class i extends t{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const r=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=e(r,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return r}}i._$litElement$=!0,i[\"finalized\"]=!0,s.litElementHydrateSupport?.({LitElement:i});const o=s.litElementPolyfillSupport;o?.({LitElement:i});const n={_$AK:(t,e,r)=>{t._$AK(e,r)},_$AL:t=>t._$AL};(s.litElementVersions??=[]).push(\"4.2.2\");export{i as LitElement,n as _$LE};\n//# sourceMappingURL=lit-element.js.map\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=t=>(e,o)=>{void 0!==o?o.addInitializer(()=>{customElements.define(t,e)}):customElements.define(t,e)};export{t as customElement};\n//# sourceMappingURL=custom-element.js.map\n","import{notEqual as t,defaultConverter as e}from\"../reactive-element.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const o={attribute:!0,type:String,converter:e,reflect:!1,hasChanged:t},r=(t=o,e,r)=>{const{kind:n,metadata:i}=r;let s=globalThis.litPropertyMetadata.get(i);if(void 0===s&&globalThis.litPropertyMetadata.set(i,s=new Map),\"setter\"===n&&((t=Object.create(t)).wrapped=!0),s.set(r.name,t),\"accessor\"===n){const{name:o}=r;return{set(r){const n=e.get.call(this);e.set.call(this,r),this.requestUpdate(o,n,t,!0,r)},init(e){return void 0!==e&&this.C(o,void 0,t,e),e}}}if(\"setter\"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t,!0,r)}}throw Error(\"Unsupported decorator location: \"+n)};function n(t){return(e,o)=>\"object\"==typeof o?r(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)}export{n as property,r as standardProperty};\n//# sourceMappingURL=property.js.map\n","import{property as t}from\"./property.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */function r(r){return t({...r,state:!0,attribute:!1})}export{r as state};\n//# sourceMappingURL=state.js.map\n","const MAX_ASSISTANT_NAME = 50;\nconst MAX_ASSISTANT_AVATAR = 200;\n\nexport const DEFAULT_ASSISTANT_NAME = \"Assistant\";\nexport const DEFAULT_ASSISTANT_AVATAR = \"A\";\n\nexport type AssistantIdentity = {\n agentId?: string | null;\n name: string;\n avatar: string | null;\n};\n\ndeclare global {\n interface Window {\n __TASKMASTER_ASSISTANT_NAME__?: string;\n __TASKMASTER_ASSISTANT_AVATAR__?: string;\n }\n}\n\nfunction coerceIdentityValue(value: string | undefined, maxLength: number): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n if (trimmed.length <= maxLength) return trimmed;\n return trimmed.slice(0, maxLength);\n}\n\nexport function normalizeAssistantIdentity(\n input?: Partial<AssistantIdentity> | null,\n): AssistantIdentity {\n const name =\n coerceIdentityValue(input?.name, MAX_ASSISTANT_NAME) ?? DEFAULT_ASSISTANT_NAME;\n const avatar = coerceIdentityValue(input?.avatar ?? undefined, MAX_ASSISTANT_AVATAR) ?? null;\n const agentId =\n typeof input?.agentId === \"string\" && input.agentId.trim()\n ? input.agentId.trim()\n : null;\n return { agentId, name, avatar };\n}\n\nexport function resolveInjectedAssistantIdentity(): AssistantIdentity {\n if (typeof window === \"undefined\") {\n return normalizeAssistantIdentity({});\n }\n return normalizeAssistantIdentity({\n name: window.__TASKMASTER_ASSISTANT_NAME__,\n avatar: window.__TASKMASTER_ASSISTANT_AVATAR__,\n });\n}\n","/**\n * Per-device and per-workspace product branding.\n *\n * Reads window globals injected by the gateway (control-ui.ts) and exposes\n * the resolved brand identity + helpers to apply accent/background colours\n * as CSS custom properties on :root.\n *\n * Workspace brands are injected as a map (`__TASKMASTER_WORKSPACE_BRANDS__`)\n * so the control panel can re-theme when the user switches accounts.\n */\n\n/** Per-workspace brand entry injected by the server. */\nexport type WorkspaceBrandEntry = {\n accentColor?: string;\n backgroundColor?: string;\n logoUrl?: string;\n};\n\ndeclare global {\n interface Window {\n __TASKMASTER_BRAND_NAME__?: string;\n __TASKMASTER_BRAND_ICON_URL__?: string;\n __TASKMASTER_ACCENT_COLOR__?: string;\n __TASKMASTER_BACKGROUND_COLOR__?: string;\n __TASKMASTER_WORKSPACE_BRANDS__?: Record<string, WorkspaceBrandEntry>;\n }\n}\n\nexport type BrandIdentity = {\n name: string;\n iconUrl: string;\n accentColor: string;\n backgroundColor: string;\n};\n\nconst DEFAULT_BRAND_NAME = \"Taskmaster\";\nconst DEFAULT_BRAND_ICON_URL = \"/taskmaster-icon.png\";\nconst DEFAULT_ACCENT_COLOR = \"#00d4ff\";\nconst DEFAULT_BACKGROUND_COLOR = \"\";\n\nlet cached: BrandIdentity | null = null;\n\n/** Read device-level brand identity from injected window globals (cached after first call). */\nexport function resolveBrand(): BrandIdentity {\n if (cached) return cached;\n cached = {\n name: window.__TASKMASTER_BRAND_NAME__ || DEFAULT_BRAND_NAME,\n iconUrl: window.__TASKMASTER_BRAND_ICON_URL__ || DEFAULT_BRAND_ICON_URL,\n accentColor: window.__TASKMASTER_ACCENT_COLOR__ || DEFAULT_ACCENT_COLOR,\n backgroundColor: window.__TASKMASTER_BACKGROUND_COLOR__ || DEFAULT_BACKGROUND_COLOR,\n };\n return cached;\n}\n\n/** Get workspace brands map (may be empty if none configured). */\nexport function getWorkspaceBrands(): Record<string, WorkspaceBrandEntry> {\n return window.__TASKMASTER_WORKSPACE_BRANDS__ ?? {};\n}\n\n/**\n * Hex to rgb triplet (e.g. \"#f59e0b\" to \"245, 158, 11\").\n * Returns null on invalid input.\n */\nfunction hexToRgb(hex: string): string | null {\n const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex);\n if (!m) return null;\n return `${parseInt(m[1], 16)}, ${parseInt(m[2], 16)}, ${parseInt(m[3], 16)}`;\n}\n\n/** Relative luminance (WCAG). Returns 0–1; > 0.5 means the colour is \"light\". */\nfunction relativeLuminance(hex: string): number {\n const m = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(hex);\n if (!m) return 0;\n const [r, g, b] = [m[1], m[2], m[3]].map((c) => {\n const v = parseInt(c, 16) / 255;\n return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n });\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/**\n * Apply brand accent colour as CSS custom properties on :root.\n * Overrides the default cyan (#00d4ff) with the configured colour.\n */\nexport function applyBrandAccentColor(color: string): void {\n const rgb = hexToRgb(color);\n if (!rgb) return;\n\n const root = document.documentElement;\n root.style.setProperty(\"--accent\", color);\n root.style.setProperty(\"--accent-hover\", color);\n root.style.setProperty(\"--accent-muted\", color);\n root.style.setProperty(\"--primary\", color);\n root.style.setProperty(\"--ring\", color);\n root.style.setProperty(\"--accent-subtle\", `rgba(${rgb}, 0.15)`);\n root.style.setProperty(\"--accent-glow\", `rgba(${rgb}, 0.25)`);\n root.style.setProperty(\"--tasker-orange\", color);\n root.style.setProperty(\"--tasker-orange-hover\", color);\n root.style.setProperty(\"--tasker-orange-glow\", `rgba(${rgb}, 0.25)`);\n\n // Pick button text colour for contrast: dark text on light accents, white on dark\n const fg = relativeLuminance(color) > 0.4 ? \"#111111\" : \"#ffffff\";\n root.style.setProperty(\"--accent-foreground\", fg);\n root.style.setProperty(\"--primary-foreground\", fg);\n}\n\n/**\n * Blend a tint colour into a base hex at a given opacity (0–1).\n * Returns a new hex colour.\n */\nfunction blendHex(base: string, tint: string, opacity: number): string {\n const bm = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(base);\n const tm = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(tint);\n if (!bm || !tm) return base;\n const blend = (bi: number, ti: number) =>\n Math.round(parseInt(bm[bi], 16) * (1 - opacity) + parseInt(tm[ti], 16) * opacity);\n const r = blend(1, 1);\n const g = blend(2, 2);\n const b = blend(3, 3);\n return `#${r.toString(16).padStart(2, \"0\")}${g.toString(16).padStart(2, \"0\")}${b.toString(16).padStart(2, \"0\")}`;\n}\n\n// Base dark-theme tokens (must match base.css :root)\nconst BASE_TOKENS = {\n \"--bg\": \"#12141a\",\n \"--bg-muted\": \"#262a35\",\n \"--card\": \"#181b22\",\n \"--secondary\": \"#1e2028\",\n};\n\n/**\n * Apply background tint colour as CSS custom properties on :root.\n * Blends the tint into core colour tokens so every surface picks it up.\n */\nexport function applyBrandBackgroundColor(color: string): void {\n const root = document.documentElement;\n if (!color) {\n // Restore original tokens\n for (const [prop, val] of Object.entries(BASE_TOKENS)) {\n root.style.setProperty(prop, val);\n }\n root.style.removeProperty(\"--brand-bg\");\n root.style.removeProperty(\"--brand-bg-subtle\");\n root.style.removeProperty(\"--brand-bg-card\");\n return;\n }\n\n const rgb = hexToRgb(color);\n if (!rgb) return;\n\n // Blend tint into every base token at varying strengths\n root.style.setProperty(\"--bg\", blendHex(BASE_TOKENS[\"--bg\"], color, 0.08));\n root.style.setProperty(\"--bg-muted\", blendHex(BASE_TOKENS[\"--bg-muted\"], color, 0.10));\n root.style.setProperty(\"--card\", blendHex(BASE_TOKENS[\"--card\"], color, 0.12));\n root.style.setProperty(\"--secondary\", blendHex(BASE_TOKENS[\"--secondary\"], color, 0.10));\n\n // Keep the overlay vars for surfaces that still use them (setup-page, setup-card, etc.)\n root.style.setProperty(\"--brand-bg\", color);\n root.style.setProperty(\"--brand-bg-subtle\", `rgba(${rgb}, 0.08)`);\n root.style.setProperty(\"--brand-bg-card\", `rgba(${rgb}, 0.12)`);\n}\n\n/**\n * Apply a full workspace brand (accent + background + logo).\n * Called when the user switches workspaces in the control panel.\n * Falls back to device-level defaults when the workspace has no brand config.\n */\nexport function applyWorkspaceBrand(workspaceName: string | null): void {\n const deviceBrand = resolveBrand();\n const wsBrands = getWorkspaceBrands();\n const ws = workspaceName ? wsBrands[workspaceName] : undefined;\n\n // Accent colour: workspace level then device level then default\n const accent = ws?.accentColor ?? deviceBrand.accentColor;\n applyBrandAccentColor(accent);\n\n // Background colour: workspace level then device level then none\n const bg = ws?.backgroundColor ?? deviceBrand.backgroundColor;\n applyBrandBackgroundColor(bg);\n}\n","const GLOBAL_KEY = \"taskmaster.control.settings.v1\";\nconst ACCOUNT_PREFIX = \"taskmaster.account.settings.\";\n\nimport type { ThemeMode } from \"./theme\";\n\n/** Browser-level settings (shared across all accounts). */\nexport type GlobalSettings = {\n gatewayUrl: string;\n token: string;\n theme: ThemeMode;\n navCollapsed: boolean;\n navGroupsCollapsed: Record<string, boolean>;\n};\n\n/** Per-account settings (scoped to a workspace). */\nexport type AccountSettings = {\n sessionKey: string;\n lastActiveSessionKey: string;\n chatFocusMode: boolean;\n chatShowThinking: boolean;\n splitRatio: number;\n};\n\n/** Combined settings (what the rest of the app sees). */\nexport type UiSettings = GlobalSettings & AccountSettings;\n\nfunction defaultGatewayUrl(): string {\n const proto = location.protocol === \"https:\" ? \"wss\" : \"ws\";\n return `${proto}://${location.host}`;\n}\n\nconst GLOBAL_DEFAULTS: GlobalSettings = {\n gatewayUrl: defaultGatewayUrl(),\n token: \"\",\n theme: \"system\",\n navCollapsed: false,\n navGroupsCollapsed: {},\n};\n\nconst ACCOUNT_DEFAULTS: AccountSettings = {\n sessionKey: \"main\",\n lastActiveSessionKey: \"main\",\n chatFocusMode: false,\n chatShowThinking: false,\n splitRatio: 0.6,\n};\n\nfunction loadGlobal(): GlobalSettings {\n try {\n const raw = localStorage.getItem(GLOBAL_KEY);\n if (!raw) return { ...GLOBAL_DEFAULTS, gatewayUrl: defaultGatewayUrl() };\n const p = JSON.parse(raw) as Partial<GlobalSettings>;\n return {\n gatewayUrl:\n typeof p.gatewayUrl === \"string\" && p.gatewayUrl.trim()\n ? p.gatewayUrl.trim()\n : defaultGatewayUrl(),\n token: typeof p.token === \"string\" ? p.token : GLOBAL_DEFAULTS.token,\n theme:\n p.theme === \"light\" || p.theme === \"dark\" || p.theme === \"system\"\n ? p.theme\n : GLOBAL_DEFAULTS.theme,\n navCollapsed:\n typeof p.navCollapsed === \"boolean\"\n ? p.navCollapsed\n : GLOBAL_DEFAULTS.navCollapsed,\n navGroupsCollapsed:\n typeof p.navGroupsCollapsed === \"object\" && p.navGroupsCollapsed !== null\n ? p.navGroupsCollapsed\n : GLOBAL_DEFAULTS.navGroupsCollapsed,\n };\n } catch {\n return { ...GLOBAL_DEFAULTS, gatewayUrl: defaultGatewayUrl() };\n }\n}\n\nfunction loadAccount(workspace: string | null): AccountSettings {\n if (!workspace) return { ...ACCOUNT_DEFAULTS };\n try {\n const raw = localStorage.getItem(ACCOUNT_PREFIX + workspace);\n if (!raw) return { ...ACCOUNT_DEFAULTS };\n const p = JSON.parse(raw) as Partial<AccountSettings>;\n return {\n sessionKey:\n typeof p.sessionKey === \"string\" && p.sessionKey.trim()\n ? p.sessionKey.trim()\n : ACCOUNT_DEFAULTS.sessionKey,\n lastActiveSessionKey:\n typeof p.lastActiveSessionKey === \"string\" && p.lastActiveSessionKey.trim()\n ? p.lastActiveSessionKey.trim()\n : (typeof p.sessionKey === \"string\" && p.sessionKey.trim()) ||\n ACCOUNT_DEFAULTS.lastActiveSessionKey,\n chatFocusMode:\n typeof p.chatFocusMode === \"boolean\"\n ? p.chatFocusMode\n : ACCOUNT_DEFAULTS.chatFocusMode,\n chatShowThinking:\n typeof p.chatShowThinking === \"boolean\"\n ? p.chatShowThinking\n : ACCOUNT_DEFAULTS.chatShowThinking,\n splitRatio:\n typeof p.splitRatio === \"number\" && p.splitRatio >= 0.4 && p.splitRatio <= 0.7\n ? p.splitRatio\n : ACCOUNT_DEFAULTS.splitRatio,\n };\n } catch {\n return { ...ACCOUNT_DEFAULTS };\n }\n}\n\n/** Current workspace for per-account storage. Set via setActiveWorkspace(). */\nlet activeWorkspace: string | null = null;\n\n/** Update the workspace used for per-account settings. Call on account switch. */\nexport function setActiveWorkspace(workspace: string | null) {\n activeWorkspace = workspace;\n}\n\n/** Load combined settings (global + per-account for active workspace). */\nexport function loadSettings(): UiSettings {\n return { ...loadGlobal(), ...loadAccount(activeWorkspace) };\n}\n\n/** Save combined settings (routes fields to the correct store). */\nexport function saveSettings(next: UiSettings) {\n const global: GlobalSettings = {\n gatewayUrl: next.gatewayUrl,\n token: next.token,\n theme: next.theme,\n navCollapsed: next.navCollapsed,\n navGroupsCollapsed: next.navGroupsCollapsed,\n };\n localStorage.setItem(GLOBAL_KEY, JSON.stringify(global));\n\n if (activeWorkspace) {\n const account: AccountSettings = {\n sessionKey: next.sessionKey,\n lastActiveSessionKey: next.lastActiveSessionKey,\n chatFocusMode: next.chatFocusMode,\n chatShowThinking: next.chatShowThinking,\n splitRatio: next.splitRatio,\n };\n localStorage.setItem(ACCOUNT_PREFIX + activeWorkspace, JSON.stringify(account));\n }\n}\n\n// ---- Draft persistence (per workspace + session) ----\n\nconst DRAFT_PREFIX = \"taskmaster.draft.\";\n\nfunction draftKey(workspace: string, sessionKey: string): string {\n return DRAFT_PREFIX + workspace + \".\" + sessionKey;\n}\n\n/** Save draft text to localStorage. Removes the entry if text is empty. */\nexport function saveDraft(workspace: string, sessionKey: string, text: string) {\n try {\n const key = draftKey(workspace, sessionKey);\n if (!text) {\n localStorage.removeItem(key);\n } else {\n localStorage.setItem(key, text);\n }\n } catch {\n // localStorage full or unavailable — ignore\n }\n}\n\n/** Load draft text from localStorage. Returns empty string if none stored. */\nexport function loadDraft(workspace: string, sessionKey: string): string {\n try {\n return localStorage.getItem(draftKey(workspace, sessionKey)) ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n/** Remove stored draft for a given scope. */\nexport function clearDraft(workspace: string, sessionKey: string) {\n try {\n localStorage.removeItem(draftKey(workspace, sessionKey));\n } catch {\n // ignore\n }\n}\n\nlet _draftTimer: ReturnType<typeof setTimeout> | null = null;\nlet _pendingDraft: { workspace: string; sessionKey: string; text: string } | null = null;\n\n/** Debounced draft save (300 ms). Batches rapid keystrokes into a single write. */\nexport function scheduleDraftSave(workspace: string, sessionKey: string, text: string) {\n _pendingDraft = { workspace, sessionKey, text };\n if (_draftTimer != null) clearTimeout(_draftTimer);\n _draftTimer = setTimeout(() => {\n if (_pendingDraft) saveDraft(_pendingDraft.workspace, _pendingDraft.sessionKey, _pendingDraft.text);\n _pendingDraft = null;\n _draftTimer = null;\n }, 300);\n}\n\n/** Flush any pending debounced draft save immediately. Call on beforeunload or context switch. */\nexport function flushDraftSave() {\n if (_draftTimer != null) clearTimeout(_draftTimer);\n _draftTimer = null;\n if (_pendingDraft) {\n saveDraft(_pendingDraft.workspace, _pendingDraft.sessionKey, _pendingDraft.text);\n _pendingDraft = null;\n }\n}\n\n// ---- Migration: move legacy v1 settings into the new split format ----\n(function migrateLegacy() {\n try {\n const raw = localStorage.getItem(GLOBAL_KEY);\n if (!raw) return;\n const p = JSON.parse(raw) as Record<string, unknown>;\n // If the old key has account-level fields, it's legacy format\n if (!(\"sessionKey\" in p)) return;\n // Save global portion under the global key (stripping account fields)\n const global: GlobalSettings = {\n gatewayUrl: typeof p.gatewayUrl === \"string\" ? p.gatewayUrl : defaultGatewayUrl(),\n token: typeof p.token === \"string\" ? p.token : \"\",\n theme: (p.theme === \"light\" || p.theme === \"dark\" || p.theme === \"system\") ? p.theme : \"system\",\n navCollapsed: typeof p.navCollapsed === \"boolean\" ? p.navCollapsed : false,\n navGroupsCollapsed:\n typeof p.navGroupsCollapsed === \"object\" && p.navGroupsCollapsed !== null\n ? (p.navGroupsCollapsed as Record<string, boolean>)\n : {},\n };\n localStorage.setItem(GLOBAL_KEY, JSON.stringify(global));\n // Don't migrate account settings — they'll use fresh defaults per account\n } catch {\n // ignore\n }\n})();\n","export type ParsedAgentSessionKey = {\n agentId: string;\n rest: string;\n};\n\nexport function parseAgentSessionKey(\n sessionKey: string | undefined | null,\n): ParsedAgentSessionKey | null {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return null;\n const parts = raw.split(\":\").filter(Boolean);\n if (parts.length < 3) return null;\n if (parts[0] !== \"agent\") return null;\n const agentId = parts[1]?.trim();\n const rest = parts.slice(2).join(\":\");\n if (!agentId || !rest) return null;\n return { agentId, rest };\n}\n\nexport function isSubagentSessionKey(sessionKey: string | undefined | null): boolean {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return false;\n if (raw.toLowerCase().startsWith(\"subagent:\")) return true;\n const parsed = parseAgentSessionKey(raw);\n return Boolean((parsed?.rest ?? \"\").toLowerCase().startsWith(\"subagent:\"));\n}\n\nexport function isAcpSessionKey(sessionKey: string | undefined | null): boolean {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return false;\n const normalized = raw.toLowerCase();\n if (normalized.startsWith(\"acp:\")) return true;\n const parsed = parseAgentSessionKey(raw);\n return Boolean((parsed?.rest ?? \"\").toLowerCase().startsWith(\"acp:\"));\n}\n\nconst THREAD_SESSION_MARKERS = [\":thread:\", \":topic:\"];\n\nexport function resolveThreadParentSessionKey(\n sessionKey: string | undefined | null,\n): string | null {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return null;\n const normalized = raw.toLowerCase();\n let idx = -1;\n for (const marker of THREAD_SESSION_MARKERS) {\n const candidate = normalized.lastIndexOf(marker);\n if (candidate > idx) idx = candidate;\n }\n if (idx <= 0) return null;\n const parent = raw.slice(0, idx).trim();\n return parent ? parent : null;\n}\n","export type ReasoningTagMode = \"strict\" | \"preserve\";\nexport type ReasoningTagTrim = \"none\" | \"start\" | \"both\";\n\nconst QUICK_TAG_RE = /<\\s*\\/?\\s*(?:think(?:ing)?|thought|antthinking|final)\\b/i;\nconst FINAL_TAG_RE = /<\\s*\\/?\\s*final\\b[^>]*>/gi;\nconst THINKING_TAG_RE = /<\\s*(\\/?)\\s*(?:think(?:ing)?|thought|antthinking)\\b[^>]*>/gi;\n\nfunction applyTrim(value: string, mode: ReasoningTagTrim): string {\n if (mode === \"none\") return value;\n if (mode === \"start\") return value.trimStart();\n return value.trim();\n}\n\nexport function stripReasoningTagsFromText(\n text: string,\n options?: {\n mode?: ReasoningTagMode;\n trim?: ReasoningTagTrim;\n },\n): string {\n if (!text) return text;\n if (!QUICK_TAG_RE.test(text)) return text;\n\n const mode = options?.mode ?? \"strict\";\n const trimMode = options?.trim ?? \"both\";\n\n let cleaned = text;\n if (FINAL_TAG_RE.test(cleaned)) {\n FINAL_TAG_RE.lastIndex = 0;\n cleaned = cleaned.replace(FINAL_TAG_RE, \"\");\n } else {\n FINAL_TAG_RE.lastIndex = 0;\n }\n\n THINKING_TAG_RE.lastIndex = 0;\n let result = \"\";\n let lastIndex = 0;\n let inThinking = false;\n\n for (const match of cleaned.matchAll(THINKING_TAG_RE)) {\n const idx = match.index ?? 0;\n const isClose = match[1] === \"/\";\n\n if (!inThinking) {\n result += cleaned.slice(lastIndex, idx);\n if (!isClose) {\n inThinking = true;\n }\n } else if (isClose) {\n inThinking = false;\n }\n\n lastIndex = idx + match[0].length;\n }\n\n if (!inThinking || mode === \"preserve\") {\n result += cleaned.slice(lastIndex);\n }\n\n return applyTrim(result, trimMode);\n}\n","import { stripReasoningTagsFromText } from \"../../../src/shared/text/reasoning-tags.js\";\n\nexport function formatMs(ms?: number | null): string {\n if (!ms && ms !== 0) return \"n/a\";\n return new Date(ms).toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"medium\",\n });\n}\n\nexport function formatAgo(ms?: number | null): string {\n if (!ms && ms !== 0) return \"n/a\";\n const diff = Date.now() - ms;\n if (diff < 0) {\n // Future timestamp — show \"in Xh\", \"in Xm\", etc.\n const ahead = -diff;\n const sec = Math.round(ahead / 1000);\n if (sec < 60) return `in ${sec}s`;\n const min = Math.round(sec / 60);\n if (min < 60) return `in ${min}m`;\n const hr = Math.round(min / 60);\n if (hr < 48) return `in ${hr}h`;\n const day = Math.round(hr / 24);\n return `in ${day}d`;\n }\n const sec = Math.round(diff / 1000);\n if (sec < 60) return `${sec}s ago`;\n const min = Math.round(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.round(min / 60);\n if (hr < 48) return `${hr}h ago`;\n const day = Math.round(hr / 24);\n return `${day}d ago`;\n}\n\nexport function formatDurationMs(ms?: number | null): string {\n if (!ms && ms !== 0) return \"n/a\";\n if (ms < 1000) return `${ms}ms`;\n const sec = Math.round(ms / 1000);\n if (sec < 60) return `${sec}s`;\n const min = Math.round(sec / 60);\n if (min < 60) return `${min}m`;\n const hr = Math.round(min / 60);\n if (hr < 48) return `${hr}h`;\n const day = Math.round(hr / 24);\n return `${day}d`;\n}\n\nexport function formatList(values?: Array<string | null | undefined>): string {\n if (!values || values.length === 0) return \"none\";\n return values.filter((v): v is string => Boolean(v && v.trim())).join(\", \");\n}\n\nexport function clampText(value: string, max = 120): string {\n if (value.length <= max) return value;\n return `${value.slice(0, Math.max(0, max - 1))}…`;\n}\n\nexport function truncateText(value: string, max: number): {\n text: string;\n truncated: boolean;\n total: number;\n} {\n if (value.length <= max) {\n return { text: value, truncated: false, total: value.length };\n }\n return {\n text: value.slice(0, Math.max(0, max)),\n truncated: true,\n total: value.length,\n };\n}\n\nexport function toNumber(value: string, fallback: number): number {\n const n = Number(value);\n return Number.isFinite(n) ? n : fallback;\n}\n\nexport function parseList(input: string): string[] {\n return input\n .split(/[,\\n]/)\n .map((v) => v.trim())\n .filter((v) => v.length > 0);\n}\n\nexport function stripThinkingTags(value: string): string {\n return stripReasoningTagsFromText(value, { mode: \"preserve\", trim: \"start\" });\n}\n","import { stripThinkingTags } from \"../format\";\n\nconst ENVELOPE_PREFIX = /^\\[([^\\]]+)\\]\\s*/;\nconst ENVELOPE_CHANNELS = [\n \"WebChat\",\n \"WhatsApp\",\n \"Telegram\",\n \"Signal\",\n \"Slack\",\n \"Discord\",\n \"iMessage\",\n \"Teams\",\n \"Matrix\",\n \"Zalo\",\n \"Zalo Personal\",\n \"BlueBubbles\",\n];\n\nconst textCache = new WeakMap<object, string | null>();\nconst thinkingCache = new WeakMap<object, string | null>();\n\nfunction looksLikeEnvelopeHeader(header: string): boolean {\n if (/\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}Z\\b/.test(header)) return true;\n if (/\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}\\b/.test(header)) return true;\n return ENVELOPE_CHANNELS.some((label) => header.startsWith(`${label} `));\n}\n\nexport function stripEnvelope(text: string): string {\n const match = text.match(ENVELOPE_PREFIX);\n if (!match) return text;\n const header = match[1] ?? \"\";\n if (!looksLikeEnvelopeHeader(header)) return text;\n return text.slice(match[0].length);\n}\n\nexport function extractText(message: unknown): string | null {\n const m = message as Record<string, unknown>;\n const role = typeof m.role === \"string\" ? m.role : \"\";\n const content = m.content;\n if (typeof content === \"string\") {\n const processed = role === \"assistant\" ? stripThinkingTags(content) : stripEnvelope(content);\n return processed;\n }\n if (Array.isArray(content)) {\n const parts = content\n .map((p) => {\n const item = p as Record<string, unknown>;\n if (item.type === \"text\" && typeof item.text === \"string\") return item.text;\n return null;\n })\n .filter((v): v is string => typeof v === \"string\");\n if (parts.length > 0) {\n const joined = parts.join(\"\\n\");\n const processed = role === \"assistant\" ? stripThinkingTags(joined) : stripEnvelope(joined);\n return processed;\n }\n }\n if (typeof m.text === \"string\") {\n const processed = role === \"assistant\" ? stripThinkingTags(m.text) : stripEnvelope(m.text);\n return processed;\n }\n return null;\n}\n\nexport function extractTextCached(message: unknown): string | null {\n if (!message || typeof message !== \"object\") return extractText(message);\n const obj = message as object;\n if (textCache.has(obj)) return textCache.get(obj) ?? null;\n const value = extractText(message);\n textCache.set(obj, value);\n return value;\n}\n\nexport function extractThinking(message: unknown): string | null {\n const m = message as Record<string, unknown>;\n const content = m.content;\n const parts: string[] = [];\n if (Array.isArray(content)) {\n for (const p of content) {\n const item = p as Record<string, unknown>;\n if (item.type === \"thinking\" && typeof item.thinking === \"string\") {\n const cleaned = item.thinking.trim();\n if (cleaned) parts.push(cleaned);\n }\n }\n }\n if (parts.length > 0) return parts.join(\"\\n\");\n\n // Back-compat: older logs may still have <think> tags inside text blocks.\n const rawText = extractRawText(message);\n if (!rawText) return null;\n const matches = [\n ...rawText.matchAll(\n /<\\s*think(?:ing)?\\s*>([\\s\\S]*?)<\\s*\\/\\s*think(?:ing)?\\s*>/gi,\n ),\n ];\n const extracted = matches\n .map((m) => (m[1] ?? \"\").trim())\n .filter(Boolean);\n return extracted.length > 0 ? extracted.join(\"\\n\") : null;\n}\n\nexport function extractThinkingCached(message: unknown): string | null {\n if (!message || typeof message !== \"object\") return extractThinking(message);\n const obj = message as object;\n if (thinkingCache.has(obj)) return thinkingCache.get(obj) ?? null;\n const value = extractThinking(message);\n thinkingCache.set(obj, value);\n return value;\n}\n\nexport function extractRawText(message: unknown): string | null {\n const m = message as Record<string, unknown>;\n const content = m.content;\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const parts = content\n .map((p) => {\n const item = p as Record<string, unknown>;\n if (item.type === \"text\" && typeof item.text === \"string\") return item.text;\n return null;\n })\n .filter((v): v is string => typeof v === \"string\");\n if (parts.length > 0) return parts.join(\"\\n\");\n }\n if (typeof m.text === \"string\") return m.text;\n return null;\n}\n\nexport function formatReasoningMarkdown(text: string): string {\n const trimmed = text.trim();\n if (!trimmed) return \"\";\n const lines = trimmed\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => `_${line}_`);\n return lines.length ? [\"_Reasoning:_\", ...lines].join(\"\\n\") : \"\";\n}\n","/**\n * Message normalization utilities for chat rendering.\n */\n\nimport type {\n NormalizedMessage,\n MessageContentItem,\n} from \"../types/chat-types\";\n\n// Heartbeat detection patterns\nconst HEARTBEAT_PROMPT_PATTERN = /Read HEARTBEAT\\.md if it exists|reply HEARTBEAT_OK/i;\nconst HEARTBEAT_RESPONSE_PATTERN = /^[\\s*`_]*HEARTBEAT_OK[\\s*`_]*$/i;\n\n// Silent reply token — agent outputs this to indicate no reply needed\nconst SILENT_REPLY_PATTERN = /^[\\s*`_]*NO_REPLY[\\s*`_]*$/i;\n\n// Internal system prompt patterns (should never be shown to users)\nconst INTERNAL_PROMPT_PATTERN = /^A new session was started via \\/new or \\/reset\\./;\n\n/**\n * Check if a message is a heartbeat prompt or response.\n * These are internal system messages that shouldn't be shown to users.\n */\nexport function isHeartbeatMessage(message: unknown): boolean {\n const m = message as Record<string, unknown>;\n const role = typeof m.role === \"string\" ? m.role : \"\";\n\n // Extract text content\n let text = \"\";\n if (typeof m.content === \"string\") {\n text = m.content;\n } else if (Array.isArray(m.content)) {\n text = m.content\n .filter((item: unknown) => typeof item === \"object\" && item !== null)\n .map((item: Record<string, unknown>) => item.text ?? \"\")\n .join(\" \");\n } else if (typeof m.text === \"string\") {\n text = m.text;\n }\n\n const trimmed = text.trim();\n if (!trimmed) return false;\n\n // Check for heartbeat prompt (user role)\n if (role === \"user\" && HEARTBEAT_PROMPT_PATTERN.test(trimmed)) {\n return true;\n }\n\n // Check for heartbeat response (assistant role)\n if (role === \"assistant\" && HEARTBEAT_RESPONSE_PATTERN.test(trimmed)) {\n return true;\n }\n\n // Check for internal system prompts leaked as user messages (e.g. /new greeting)\n if (role === \"user\" && INTERNAL_PROMPT_PATTERN.test(trimmed)) {\n return true;\n }\n\n // Check for silent reply token (assistant NO_REPLY)\n if (role === \"assistant\" && SILENT_REPLY_PATTERN.test(trimmed)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Filter out heartbeat messages from an array of messages.\n */\nexport function filterHeartbeatMessages<T>(messages: T[]): T[] {\n return messages.filter((msg) => !isHeartbeatMessage(msg));\n}\n\n/**\n * Normalize a raw message object into a consistent structure.\n */\nexport function normalizeMessage(message: unknown): NormalizedMessage {\n const m = message as Record<string, unknown>;\n let role = typeof m.role === \"string\" ? m.role : \"unknown\";\n\n // Detect tool messages by common gateway shapes.\n // Some tool events come through as assistant role with tool_* items in the content array.\n const hasToolId =\n typeof m.toolCallId === \"string\" || typeof m.tool_call_id === \"string\";\n\n const contentRaw = m.content;\n const contentItems = Array.isArray(contentRaw) ? contentRaw : null;\n const hasToolContent =\n Array.isArray(contentItems) &&\n contentItems.some((item) => {\n const x = item as Record<string, unknown>;\n const t = String(x.type ?? \"\").toLowerCase();\n return t === \"toolresult\" || t === \"tool_result\";\n });\n\n const hasToolName =\n typeof (m as Record<string, unknown>).toolName === \"string\" ||\n typeof (m as Record<string, unknown>).tool_name === \"string\";\n\n if (hasToolId || hasToolContent || hasToolName) {\n role = \"toolResult\";\n }\n\n // Extract content\n let content: MessageContentItem[] = [];\n\n if (typeof m.content === \"string\") {\n content = [{ type: \"text\", text: m.content }];\n } else if (Array.isArray(m.content)) {\n content = m.content.map((item: Record<string, unknown>) => ({\n type: (item.type as MessageContentItem[\"type\"]) || \"text\",\n text: item.text as string | undefined,\n name: item.name as string | undefined,\n args: item.args || item.arguments,\n }));\n } else if (typeof m.text === \"string\") {\n content = [{ type: \"text\", text: m.text }];\n }\n\n const timestamp = typeof m.timestamp === \"number\" ? m.timestamp : Date.now();\n const id = typeof m.id === \"string\" ? m.id : undefined;\n\n return { role, content, timestamp, id };\n}\n\n/**\n * Normalize role for grouping purposes.\n */\nexport function normalizeRoleForGrouping(role: string): string {\n const lower = role.toLowerCase();\n // Preserve original casing when it's already a core role.\n if (role === \"user\" || role === \"User\") return role;\n if (role === \"assistant\") return \"assistant\";\n if (role === \"system\") return \"system\";\n // Keep tool-related roles distinct so the UI can style/toggle them.\n if (\n lower === \"toolresult\" ||\n lower === \"tool_result\" ||\n lower === \"tool\" ||\n lower === \"function\"\n ) {\n return \"tool\";\n }\n return role;\n}\n\n/**\n * Check if a message is a tool result message based on its role.\n */\nexport function isToolResultMessage(message: unknown): boolean {\n const m = message as Record<string, unknown>;\n const role = typeof m.role === \"string\" ? m.role.toLowerCase() : \"\";\n return role === \"toolresult\" || role === \"tool_result\";\n}\n","export type CryptoLike = {\n randomUUID?: (() => string) | undefined;\n getRandomValues?: ((array: Uint8Array) => Uint8Array) | undefined;\n};\n\nfunction uuidFromBytes(bytes: Uint8Array): string {\n bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 1\n\n let hex = \"\";\n for (let i = 0; i < bytes.length; i++) {\n hex += bytes[i]!.toString(16).padStart(2, \"0\");\n }\n\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(\n 16,\n 20,\n )}-${hex.slice(20)}`;\n}\n\nfunction weakRandomBytes(): Uint8Array {\n const bytes = new Uint8Array(16);\n const now = Date.now();\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n bytes[0] ^= now & 0xff;\n bytes[1] ^= (now >>> 8) & 0xff;\n bytes[2] ^= (now >>> 16) & 0xff;\n bytes[3] ^= (now >>> 24) & 0xff;\n return bytes;\n}\n\nexport function generateUUID(cryptoLike: CryptoLike | null = globalThis.crypto): string {\n if (cryptoLike && typeof cryptoLike.randomUUID === \"function\") return cryptoLike.randomUUID();\n\n if (cryptoLike && typeof cryptoLike.getRandomValues === \"function\") {\n const bytes = new Uint8Array(16);\n cryptoLike.getRandomValues(bytes);\n return uuidFromBytes(bytes);\n }\n\n return uuidFromBytes(weakRandomBytes());\n}\n","import { extractText } from \"../chat/message-extract\";\nimport { filterHeartbeatMessages } from \"../chat/message-normalizer\";\nimport type { GatewayBrowserClient } from \"../gateway\";\nimport { generateUUID } from \"../uuid\";\nimport type { ChatAttachment } from \"../ui-types\";\n\n/** Number of messages to fetch on initial load and per scroll-up batch. */\nexport const CHAT_PAGE_SIZE = 50;\n\nexport type ChatState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n sessionKey: string;\n chatLoading: boolean;\n chatMessages: unknown[];\n chatHistoryTotal: number;\n chatHistoryHasMore: boolean;\n chatLoadingOlder: boolean;\n chatVerboseLevel: string | null;\n chatSending: boolean;\n chatMessage: string;\n chatAttachments: ChatAttachment[];\n chatRunId: string | null;\n chatStream: string | null;\n chatStreamStartedAt: number | null;\n chatInterimText: string | null;\n chatSuggestions: string[];\n lastError: string | null;\n};\n\nexport type ChatEventPayload = {\n runId: string;\n sessionKey: string;\n state: \"delta\" | \"final\" | \"aborted\" | \"error\" | \"block\" | \"working\";\n message?: unknown;\n errorMessage?: string;\n};\n\ntype ChatHistoryResponse = {\n messages?: unknown[];\n totalMessages?: number;\n thinkingLevel?: string | null;\n modelProvider?: string | null;\n model?: string | null;\n verboseLevel?: string | null;\n fillerEnabled?: boolean | null;\n};\n\n/**\n * Load the most recent chat messages. On initial load, fetches CHAT_PAGE_SIZE.\n * After a \"final\" event (new response), fetches enough to cover all currently\n * loaded messages plus some headroom for the new ones.\n */\nexport async function loadChatHistory(state: ChatState, opts?: { limit?: number }) {\n if (!state.client || !state.connected) return;\n state.chatLoading = true;\n state.lastError = null;\n const limit = opts?.limit ?? CHAT_PAGE_SIZE;\n try {\n const res = (await state.client.request(\"chat.history\", {\n sessionKey: state.sessionKey,\n limit,\n })) as ChatHistoryResponse;\n const rawMessages = Array.isArray(res.messages) ? res.messages : [];\n const total = typeof res.totalMessages === \"number\" ? res.totalMessages : rawMessages.length;\n // Filter out heartbeat messages (internal system messages)\n const filtered = filterHeartbeatMessages(rawMessages);\n state.chatMessages = filtered;\n state.chatHistoryTotal = total;\n state.chatHistoryHasMore = total > rawMessages.length;\n state.chatVerboseLevel = typeof res.verboseLevel === \"string\" ? res.verboseLevel : null;\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.chatLoading = false;\n }\n}\n\n/**\n * Load older messages when the user scrolls to the top of the chat thread.\n * Prepends older messages to the existing chatMessages array.\n */\nexport async function loadOlderChatHistory(state: ChatState): Promise<boolean> {\n if (!state.client || !state.connected) return false;\n if (state.chatLoadingOlder || !state.chatHistoryHasMore) return false;\n state.chatLoadingOlder = true;\n try {\n const currentCount = state.chatMessages.length;\n const res = (await state.client.request(\"chat.history\", {\n sessionKey: state.sessionKey,\n limit: CHAT_PAGE_SIZE,\n offset: currentCount,\n })) as ChatHistoryResponse;\n const rawMessages = Array.isArray(res.messages) ? res.messages : [];\n const total = typeof res.totalMessages === \"number\" ? res.totalMessages : 0;\n if (rawMessages.length === 0) {\n state.chatHistoryHasMore = false;\n return false;\n }\n const filtered = filterHeartbeatMessages(rawMessages);\n state.chatMessages = [...filtered, ...state.chatMessages];\n state.chatHistoryTotal = total;\n state.chatHistoryHasMore = total > currentCount + rawMessages.length;\n return true;\n } catch (err) {\n state.lastError = String(err);\n return false;\n } finally {\n state.chatLoadingOlder = false;\n }\n}\n\nfunction dataUrlToBase64(dataUrl: string): { content: string; mimeType: string } | null {\n // MIME type may include parameters (e.g. audio/webm;codecs=opus), so match\n // everything before the \";base64,\" marker rather than stopping at the first \";\".\n const match = /^data:(.+?);base64,(.+)$/.exec(dataUrl);\n if (!match) return null;\n return { mimeType: match[1], content: match[2] };\n}\n\nexport async function sendChatMessage(\n state: ChatState,\n message: string,\n attachments?: ChatAttachment[],\n): Promise<boolean> {\n state.chatSuggestions = [];\n if (!state.client || !state.connected) return false;\n const msg = message.trim();\n const hasAttachments = attachments && attachments.length > 0;\n if (!msg && !hasAttachments) return false;\n\n const now = Date.now();\n\n // Split: images (no fileName) vs file attachments (have fileName)\n const imageAtts = (attachments ?? []).filter((a) => !a.fileName);\n const fileAtts = (attachments ?? []).filter((a) => a.fileName);\n\n // Build user message content blocks for local chat history display\n const contentBlocks: Array<{ type: string; text?: string; source?: unknown }> = [];\n const fileNames = fileAtts.map((f) => f.fileName).filter(Boolean);\n if (fileNames.length > 0) {\n const displayText = msg ? `${fileNames.join(\", \")}\\n\\n${msg}` : fileNames.join(\", \");\n contentBlocks.push({ type: \"text\", text: displayText });\n } else if (msg) {\n contentBlocks.push({ type: \"text\", text: msg });\n }\n for (const att of imageAtts) {\n contentBlocks.push({\n type: \"image\",\n source: { type: \"base64\", media_type: att.mimeType, data: att.dataUrl },\n });\n }\n\n state.chatMessages = [\n ...state.chatMessages,\n {\n role: \"user\",\n content: contentBlocks,\n timestamp: now,\n },\n ];\n\n state.chatSending = true;\n state.lastError = null;\n const runId = generateUUID();\n state.chatRunId = runId;\n state.chatStream = \"\";\n state.chatStreamStartedAt = now;\n\n // Build API attachments: images + all file attachments (text + binary)\n const allAtts = [...imageAtts, ...fileAtts];\n const apiAttachments = allAtts.length > 0\n ? allAtts\n .map((att) => {\n // Text file: base64-encode the text content\n if (att.textContent) {\n return {\n type: \"document\" as const,\n mimeType: att.mimeType || \"text/plain\",\n fileName: att.fileName,\n content: btoa(unescape(encodeURIComponent(att.textContent))),\n };\n }\n // Binary file (images, PDFs): parse data URL\n const parsed = dataUrlToBase64(att.dataUrl);\n if (!parsed) return null;\n return {\n type: att.fileName ? (\"document\" as const) : (\"image\" as const),\n mimeType: parsed.mimeType,\n fileName: att.fileName,\n content: parsed.content,\n };\n })\n .filter((a): a is NonNullable<typeof a> => a !== null)\n : undefined;\n\n try {\n await state.client.request(\"chat.send\", {\n sessionKey: state.sessionKey,\n message: msg,\n deliver: false,\n idempotencyKey: runId,\n attachments: apiAttachments,\n });\n return true;\n } catch (err) {\n const error = String(err);\n state.chatRunId = null;\n state.chatStream = null;\n state.chatStreamStartedAt = null;\n state.lastError = error;\n state.chatMessages = [\n ...state.chatMessages,\n {\n role: \"assistant\",\n content: [{ type: \"text\", text: \"Error: \" + error }],\n timestamp: Date.now(),\n },\n ];\n return false;\n } finally {\n state.chatSending = false;\n }\n}\n\nexport async function abortChatRun(state: ChatState): Promise<boolean> {\n if (!state.client || !state.connected) return false;\n const runId = state.chatRunId;\n try {\n await state.client.request(\n \"chat.abort\",\n runId\n ? { sessionKey: state.sessionKey, runId }\n : { sessionKey: state.sessionKey },\n );\n return true;\n } catch (err) {\n state.lastError = String(err);\n return false;\n }\n}\n\nexport function handleChatEvent(\n state: ChatState,\n payload?: ChatEventPayload,\n) {\n if (!payload) return null;\n if (payload.sessionKey !== state.sessionKey) return null;\n\n // Final from another run (e.g. sub-agent announce): refresh history to show new message.\n if (\n payload.runId &&\n state.chatRunId &&\n payload.runId !== state.chatRunId\n ) {\n if (payload.state === \"final\") return \"final\";\n return null;\n }\n\n if (payload.state === \"working\") {\n // Tool call started — preserve any streamed text as interim \"thinking\"\n // and reset the stream so the UI shows the bouncing-dots indicator.\n // Prefer the server's buffered text (authoritative, complete) over\n // chatStream which may be stale due to the 150ms delta throttle.\n const serverText = payload.message ? extractText(payload.message)?.trim() : undefined;\n const current = serverText || state.chatStream?.trim();\n if (current) {\n if (!state.chatInterimText) {\n state.chatInterimText = current;\n } else {\n const trimmedCurrent = current.trim();\n const trimmedExisting = state.chatInterimText.trim();\n if (trimmedCurrent === trimmedExisting) {\n // Exact duplicate — skip.\n } else if (trimmedExisting.endsWith(trimmedCurrent)) {\n // Existing text already contains this at the end — skip.\n } else if (trimmedCurrent.startsWith(trimmedExisting)) {\n // Incoming is a superset (server sent full buffer with new text appended).\n state.chatInterimText = current;\n } else {\n // Genuinely new content — append.\n state.chatInterimText = `${state.chatInterimText}\\n\\n${current}`;\n }\n }\n }\n state.chatStream = \"\";\n return \"working\";\n } else if (payload.state === \"block\") {\n // Filler / block reply — add as an inline assistant message\n const text = extractText(payload.message);\n if (typeof text === \"string\" && text.trim()) {\n state.chatMessages = [\n ...state.chatMessages,\n {\n role: \"assistant\",\n content: [{ type: \"text\", text: text.trim() }],\n timestamp: Date.now(),\n filler: true,\n },\n ];\n }\n return \"block\";\n } else if (payload.state === \"delta\") {\n state.chatSuggestions = [];\n const next = extractText(payload.message);\n if (typeof next === \"string\") {\n // Suppress \"NO_REPLY\" silent token from streaming display\n if (next.trim() === \"NO_REPLY\") return null;\n const current = state.chatStream ?? \"\";\n if (!current || next.length >= current.length) {\n state.chatStream = next;\n }\n }\n } else if (payload.state === \"final\") {\n state.chatStream = null;\n state.chatRunId = null;\n state.chatStreamStartedAt = null;\n state.chatInterimText = null;\n } else if (payload.state === \"aborted\") {\n state.chatStream = null;\n state.chatRunId = null;\n state.chatStreamStartedAt = null;\n state.chatInterimText = null;\n } else if (payload.state === \"error\") {\n state.chatStream = null;\n state.chatRunId = null;\n state.chatStreamStartedAt = null;\n state.chatInterimText = null;\n state.lastError = payload.errorMessage ?? \"chat error\";\n }\n return payload.state;\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { toNumber } from \"../format\";\nimport type { SessionsListResult } from \"../types\";\n\nexport type SessionsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n sessionsLoading: boolean;\n sessionsResult: SessionsListResult | null;\n sessionsError: string | null;\n sessionsFilterActive?: string;\n sessionsFilterLimit?: string;\n sessionsIncludeGlobal?: boolean;\n sessionsIncludeUnknown?: boolean;\n};\n\nexport async function loadSessions(state: SessionsState) {\n if (!state.client || !state.connected) return;\n if (state.sessionsLoading) return;\n state.sessionsLoading = true;\n state.sessionsError = null;\n try {\n const params: Record<string, unknown> = {\n includeGlobal: state.sessionsIncludeGlobal ?? true,\n includeUnknown: state.sessionsIncludeUnknown ?? false,\n };\n const activeMinutes = toNumber(state.sessionsFilterActive ?? \"\", 0);\n const limit = toNumber(state.sessionsFilterLimit ?? \"\", 0);\n if (activeMinutes > 0) params.activeMinutes = activeMinutes;\n if (limit > 0) params.limit = limit;\n const res = (await state.client.request(\"sessions.list\", params)) as\n | SessionsListResult\n | undefined;\n if (res) state.sessionsResult = res;\n } catch (err) {\n state.sessionsError = String(err);\n } finally {\n state.sessionsLoading = false;\n }\n}\n\nexport async function patchSession(\n state: SessionsState,\n key: string,\n patch: {\n label?: string | null;\n thinkingLevel?: string | null;\n verboseLevel?: string | null;\n reasoningLevel?: string | null;\n model?: string | null;\n fillerEnabled?: boolean | null;\n },\n) {\n if (!state.client || !state.connected) return;\n const params: Record<string, unknown> = { key };\n if (\"label\" in patch) params.label = patch.label;\n if (\"thinkingLevel\" in patch) params.thinkingLevel = patch.thinkingLevel;\n if (\"verboseLevel\" in patch) params.verboseLevel = patch.verboseLevel;\n if (\"reasoningLevel\" in patch) params.reasoningLevel = patch.reasoningLevel;\n if (\"model\" in patch) params.model = patch.model;\n if (\"fillerEnabled\" in patch) params.fillerEnabled = patch.fillerEnabled;\n try {\n await state.client.request(\"sessions.patch\", params);\n await loadSessions(state);\n } catch (err) {\n state.sessionsError = String(err);\n }\n}\n\nexport async function deleteSession(state: SessionsState, key: string) {\n if (!state.client || !state.connected) return;\n if (state.sessionsLoading) return;\n const confirmed = window.confirm(\n `Delete session \"${key}\"?\\n\\nDeletes the session entry and archives its transcript.`,\n );\n if (!confirmed) return;\n state.sessionsLoading = true;\n state.sessionsError = null;\n try {\n await state.client.request(\"sessions.delete\", { key, deleteTranscript: true });\n await loadSessions(state);\n } catch (err) {\n state.sessionsError = String(err);\n } finally {\n state.sessionsLoading = false;\n }\n}\n","import { truncateText } from \"./format\";\n\nconst TOOL_STREAM_LIMIT = 50;\nconst TOOL_STREAM_THROTTLE_MS = 80;\nconst TOOL_OUTPUT_CHAR_LIMIT = 120_000;\n\nexport type AgentEventPayload = {\n runId: string;\n seq: number;\n stream: string;\n ts: number;\n sessionKey?: string;\n data: Record<string, unknown>;\n};\n\nexport type ToolStreamEntry = {\n toolCallId: string;\n runId: string;\n sessionKey?: string;\n name: string;\n args?: unknown;\n output?: string;\n startedAt: number;\n updatedAt: number;\n message: Record<string, unknown>;\n};\n\ntype ToolStreamHost = {\n sessionKey: string;\n chatRunId: string | null;\n toolStreamById: Map<string, ToolStreamEntry>;\n toolStreamOrder: string[];\n chatToolMessages: Record<string, unknown>[];\n toolStreamSyncTimer: number | null;\n};\n\nfunction extractToolOutputText(value: unknown): string | null {\n if (!value || typeof value !== \"object\") return null;\n const record = value as Record<string, unknown>;\n if (typeof record.text === \"string\") return record.text;\n const content = record.content;\n if (!Array.isArray(content)) return null;\n const parts = content\n .map((item) => {\n if (!item || typeof item !== \"object\") return null;\n const entry = item as Record<string, unknown>;\n if (entry.type === \"text\" && typeof entry.text === \"string\") return entry.text;\n return null;\n })\n .filter((part): part is string => Boolean(part));\n if (parts.length === 0) return null;\n return parts.join(\"\\n\");\n}\n\nfunction formatToolOutput(value: unknown): string | null {\n if (value === null || value === undefined) return null;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n const contentText = extractToolOutputText(value);\n let text: string;\n if (typeof value === \"string\") {\n text = value;\n } else if (contentText) {\n text = contentText;\n } else {\n try {\n text = JSON.stringify(value, null, 2);\n } catch {\n text = String(value);\n }\n }\n const truncated = truncateText(text, TOOL_OUTPUT_CHAR_LIMIT);\n if (!truncated.truncated) return truncated.text;\n return `${truncated.text}\\n\\n… truncated (${truncated.total} chars, showing first ${truncated.text.length}).`;\n}\n\nfunction buildToolStreamMessage(entry: ToolStreamEntry): Record<string, unknown> {\n const content: Array<Record<string, unknown>> = [];\n content.push({\n type: \"toolcall\",\n name: entry.name,\n arguments: entry.args ?? {},\n });\n if (entry.output) {\n content.push({\n type: \"toolresult\",\n name: entry.name,\n text: entry.output,\n });\n }\n return {\n role: \"assistant\",\n toolCallId: entry.toolCallId,\n runId: entry.runId,\n content,\n timestamp: entry.startedAt,\n };\n}\n\nfunction trimToolStream(host: ToolStreamHost) {\n if (host.toolStreamOrder.length <= TOOL_STREAM_LIMIT) return;\n const overflow = host.toolStreamOrder.length - TOOL_STREAM_LIMIT;\n const removed = host.toolStreamOrder.splice(0, overflow);\n for (const id of removed) host.toolStreamById.delete(id);\n}\n\nfunction syncToolStreamMessages(host: ToolStreamHost) {\n host.chatToolMessages = host.toolStreamOrder\n .map((id) => host.toolStreamById.get(id)?.message)\n .filter((msg): msg is Record<string, unknown> => Boolean(msg));\n}\n\nexport function flushToolStreamSync(host: ToolStreamHost) {\n if (host.toolStreamSyncTimer != null) {\n clearTimeout(host.toolStreamSyncTimer);\n host.toolStreamSyncTimer = null;\n }\n syncToolStreamMessages(host);\n}\n\nexport function scheduleToolStreamSync(host: ToolStreamHost, force = false) {\n if (force) {\n flushToolStreamSync(host);\n return;\n }\n if (host.toolStreamSyncTimer != null) return;\n host.toolStreamSyncTimer = window.setTimeout(\n () => flushToolStreamSync(host),\n TOOL_STREAM_THROTTLE_MS,\n );\n}\n\nexport function resetToolStream(host: ToolStreamHost) {\n host.toolStreamById.clear();\n host.toolStreamOrder = [];\n host.chatToolMessages = [];\n flushToolStreamSync(host);\n}\n\nexport type CompactionStatus = {\n active: boolean;\n startedAt: number | null;\n completedAt: number | null;\n};\n\ntype CompactionHost = ToolStreamHost & {\n compactionStatus?: CompactionStatus | null;\n compactionClearTimer?: number | null;\n};\n\nconst COMPACTION_TOAST_DURATION_MS = 5000;\n\nexport function handleCompactionEvent(host: CompactionHost, payload: AgentEventPayload) {\n const data = payload.data ?? {};\n const phase = typeof data.phase === \"string\" ? data.phase : \"\";\n\n // Clear any existing timer\n if (host.compactionClearTimer != null) {\n window.clearTimeout(host.compactionClearTimer);\n host.compactionClearTimer = null;\n }\n\n if (phase === \"start\") {\n host.compactionStatus = {\n active: true,\n startedAt: Date.now(),\n completedAt: null,\n };\n } else if (phase === \"end\") {\n host.compactionStatus = {\n active: false,\n startedAt: host.compactionStatus?.startedAt ?? null,\n completedAt: Date.now(),\n };\n // Auto-clear the toast after duration\n host.compactionClearTimer = window.setTimeout(() => {\n host.compactionStatus = null;\n host.compactionClearTimer = null;\n }, COMPACTION_TOAST_DURATION_MS);\n }\n}\n\nexport function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPayload) {\n if (!payload) return;\n\n // Handle compaction events\n if (payload.stream === \"compaction\") {\n handleCompactionEvent(host as CompactionHost, payload);\n return;\n }\n\n if (payload.stream !== \"tool\") return;\n const sessionKey =\n typeof payload.sessionKey === \"string\" ? payload.sessionKey : undefined;\n if (sessionKey && sessionKey !== host.sessionKey) return;\n // Fallback: only accept session-less events for the active run.\n if (!sessionKey && host.chatRunId && payload.runId !== host.chatRunId) return;\n if (host.chatRunId && payload.runId !== host.chatRunId) return;\n if (!host.chatRunId) return;\n\n const data = payload.data ?? {};\n const toolCallId = typeof data.toolCallId === \"string\" ? data.toolCallId : \"\";\n if (!toolCallId) return;\n const name = typeof data.name === \"string\" ? data.name : \"tool\";\n const phase = typeof data.phase === \"string\" ? data.phase : \"\";\n const args = phase === \"start\" ? data.args : undefined;\n const output =\n phase === \"update\"\n ? formatToolOutput(data.partialResult)\n : phase === \"result\"\n ? formatToolOutput(data.result)\n : undefined;\n\n const now = Date.now();\n let entry = host.toolStreamById.get(toolCallId);\n if (!entry) {\n entry = {\n toolCallId,\n runId: payload.runId,\n sessionKey,\n name,\n args,\n output,\n startedAt: typeof payload.ts === \"number\" ? payload.ts : now,\n updatedAt: now,\n message: {},\n };\n host.toolStreamById.set(toolCallId, entry);\n host.toolStreamOrder.push(toolCallId);\n } else {\n entry.name = name;\n if (args !== undefined) entry.args = args;\n if (output !== undefined) entry.output = output;\n entry.updatedAt = now;\n }\n\n entry.message = buildToolStreamMessage(entry);\n trimToolStream(host);\n scheduleToolStreamSync(host, phase === \"result\");\n}\n","type ScrollHost = {\n updateComplete: Promise<unknown>;\n querySelector: (selectors: string) => Element | null;\n style: CSSStyleDeclaration;\n chatScrollFrame: number | null;\n chatScrollTimeout: number | null;\n chatHasAutoScrolled: boolean;\n chatUserNearBottom: boolean;\n logsScrollFrame: number | null;\n logsAtBottom: boolean;\n topbarObserver: ResizeObserver | null;\n onLoadOlder?: (() => void) | null;\n};\n\n// Generation counter: incremented on every scheduleChatScroll call so that\n// stale updateComplete.then(rAF(...)) callbacks from earlier calls bail out\n// instead of firing orphaned scrolls that can't be cancelled via chatScrollFrame.\nlet scrollGen = 0;\n\nexport function scheduleChatScroll(host: ScrollHost, force = false) {\n if (host.chatScrollFrame) cancelAnimationFrame(host.chatScrollFrame);\n if (host.chatScrollTimeout != null) {\n clearTimeout(host.chatScrollTimeout);\n host.chatScrollTimeout = null;\n }\n const gen = ++scrollGen;\n const pickScrollTarget = () => {\n const container = host.querySelector(\".chat-thread\") as HTMLElement | null;\n if (container) {\n const overflowY = getComputedStyle(container).overflowY;\n const canScroll =\n overflowY === \"auto\" ||\n overflowY === \"scroll\" ||\n container.scrollHeight - container.clientHeight > 1;\n if (canScroll) return container;\n }\n return (document.scrollingElement ?? document.documentElement) as HTMLElement | null;\n };\n // Wait for Lit render to complete, then scroll\n void host.updateComplete.then(() => {\n if (gen !== scrollGen) return;\n host.chatScrollFrame = requestAnimationFrame(() => {\n host.chatScrollFrame = null;\n if (gen !== scrollGen) return;\n const target = pickScrollTarget();\n if (!target) return;\n const distanceFromBottom =\n target.scrollHeight - target.scrollTop - target.clientHeight;\n const shouldStick = force || host.chatUserNearBottom || distanceFromBottom < 200;\n if (!shouldStick) return;\n if (force) host.chatHasAutoScrolled = true;\n target.scrollTop = target.scrollHeight;\n host.chatUserNearBottom = true;\n const retryDelay = force ? 150 : 120;\n host.chatScrollTimeout = window.setTimeout(() => {\n host.chatScrollTimeout = null;\n if (gen !== scrollGen) return;\n const latest = pickScrollTarget();\n if (!latest) return;\n const latestDistanceFromBottom =\n latest.scrollHeight - latest.scrollTop - latest.clientHeight;\n const shouldStickRetry =\n force || host.chatUserNearBottom || latestDistanceFromBottom < 200;\n if (!shouldStickRetry) return;\n latest.scrollTop = latest.scrollHeight;\n host.chatUserNearBottom = true;\n }, retryDelay);\n });\n });\n}\n\nexport function scheduleLogsScroll(host: ScrollHost, force = false) {\n if (host.logsScrollFrame) cancelAnimationFrame(host.logsScrollFrame);\n void host.updateComplete.then(() => {\n host.logsScrollFrame = requestAnimationFrame(() => {\n host.logsScrollFrame = null;\n const container = host.querySelector(\".log-stream\") as HTMLElement | null;\n if (!container) return;\n // Logs are newest-first, so \"auto-follow\" means staying at the top\n const shouldStick = force || container.scrollTop < 80;\n if (!shouldStick) return;\n container.scrollTop = 0;\n });\n });\n}\n\nexport function handleChatScroll(host: ScrollHost, event: Event) {\n const container = event.currentTarget as HTMLElement | null;\n if (!container) return;\n const distanceFromBottom =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n host.chatUserNearBottom = distanceFromBottom < 200;\n\n // Trigger lazy loading when scrolled near the top\n if (container.scrollTop < 100 && host.onLoadOlder) {\n host.onLoadOlder();\n }\n}\n\n/**\n * Preserve scroll position after older messages are prepended.\n * Call before the DOM update to capture scrollHeight, then call the returned\n * function after the update to restore the visual scroll position.\n */\nexport function captureScrollForPrepend(host: ScrollHost): (() => void) | null {\n const container = host.querySelector(\".chat-thread\") as HTMLElement | null;\n if (!container) return null;\n const prevScrollHeight = container.scrollHeight;\n const prevScrollTop = container.scrollTop;\n return () => {\n const delta = container.scrollHeight - prevScrollHeight;\n container.scrollTop = prevScrollTop + delta;\n };\n}\n\nexport function handleLogsScroll(host: ScrollHost, event: Event) {\n const container = event.currentTarget as HTMLElement | null;\n if (!container) return;\n // Logs are newest-first, so \"at top\" means following latest entries\n host.logsAtBottom = container.scrollTop < 80;\n}\n\nexport function handleSessionLogsScroll(host: ScrollHost, event: Event) {\n const container = event.currentTarget as HTMLElement | null;\n if (!container) return;\n host.logsAtBottom = container.scrollTop < 80;\n}\n\nexport function resetChatScroll(host: ScrollHost) {\n host.chatHasAutoScrolled = false;\n host.chatUserNearBottom = true;\n}\n\nexport function exportLogs(lines: string[], label: string) {\n if (lines.length === 0) return;\n const blob = new Blob([`${lines.join(\"\\n\")}\\n`], { type: \"text/plain\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n const stamp = new Date().toISOString().slice(0, 19).replace(/[:T]/g, \"-\");\n anchor.href = url;\n anchor.download = `taskmaster-logs-${label}-${stamp}.log`;\n anchor.click();\n URL.revokeObjectURL(url);\n}\n\nexport function exportSessionLogs(lines: string[], label: string) {\n if (lines.length === 0) return;\n const blob = new Blob([`${lines.join(\"\\n\")}\\n`], { type: \"text/plain\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n const stamp = new Date().toISOString().slice(0, 19).replace(/[:T]/g, \"-\");\n anchor.href = url;\n anchor.download = `taskmaster-session-logs-${label}-${stamp}.log`;\n anchor.click();\n URL.revokeObjectURL(url);\n}\n\nexport function observeTopbar(host: ScrollHost) {\n if (typeof ResizeObserver === \"undefined\") return;\n const topbar = host.querySelector(\".topbar\");\n if (!topbar) return;\n const update = () => {\n const { height } = topbar.getBoundingClientRect();\n host.style.setProperty(\"--topbar-height\", `${height}px`);\n };\n update();\n host.topbarObserver = new ResizeObserver(() => update());\n host.topbarObserver.observe(topbar);\n}\n","export function cloneConfigObject<T>(value: T): T {\n if (typeof structuredClone === \"function\") {\n return structuredClone(value);\n }\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nexport function serializeConfigForm(form: Record<string, unknown>): string {\n return `${JSON.stringify(form, null, 2).trimEnd()}\\n`;\n}\n\nexport function setPathValue(\n obj: Record<string, unknown> | unknown[],\n path: Array<string | number>,\n value: unknown,\n) {\n if (path.length === 0) return;\n let current: Record<string, unknown> | unknown[] = obj;\n for (let i = 0; i < path.length - 1; i += 1) {\n const key = path[i];\n const nextKey = path[i + 1];\n if (typeof key === \"number\") {\n if (!Array.isArray(current)) return;\n if (current[key] == null) {\n current[key] =\n typeof nextKey === \"number\" ? [] : ({} as Record<string, unknown>);\n }\n current = current[key] as Record<string, unknown> | unknown[];\n } else {\n if (typeof current !== \"object\" || current == null) return;\n const record = current as Record<string, unknown>;\n if (record[key] == null) {\n record[key] =\n typeof nextKey === \"number\" ? [] : ({} as Record<string, unknown>);\n }\n current = record[key] as Record<string, unknown> | unknown[];\n }\n }\n const lastKey = path[path.length - 1];\n if (typeof lastKey === \"number\") {\n if (Array.isArray(current)) current[lastKey] = value;\n return;\n }\n if (typeof current === \"object\" && current != null) {\n (current as Record<string, unknown>)[lastKey] = value;\n }\n}\n\nexport function removePathValue(\n obj: Record<string, unknown> | unknown[],\n path: Array<string | number>,\n) {\n if (path.length === 0) return;\n let current: Record<string, unknown> | unknown[] = obj;\n for (let i = 0; i < path.length - 1; i += 1) {\n const key = path[i];\n if (typeof key === \"number\") {\n if (!Array.isArray(current)) return;\n current = current[key] as Record<string, unknown> | unknown[];\n } else {\n if (typeof current !== \"object\" || current == null) return;\n current = (current as Record<string, unknown>)[key] as\n | Record<string, unknown>\n | unknown[];\n }\n if (current == null) return;\n }\n const lastKey = path[path.length - 1];\n if (typeof lastKey === \"number\") {\n if (Array.isArray(current)) current.splice(lastKey, 1);\n return;\n }\n if (typeof current === \"object\" && current != null) {\n delete (current as Record<string, unknown>)[lastKey];\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type {\n ConfigSchemaResponse,\n ConfigSnapshot,\n ConfigUiHints,\n} from \"../types\";\nimport {\n cloneConfigObject,\n removePathValue,\n serializeConfigForm,\n setPathValue,\n} from \"./config/form-utils\";\n\nexport type ConfigState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n applySessionKey: string;\n configLoading: boolean;\n configRaw: string;\n configRawOriginal: string;\n configValid: boolean | null;\n configIssues: unknown[];\n configSaving: boolean;\n configApplying: boolean;\n updateRunning: boolean;\n configSnapshot: ConfigSnapshot | null;\n configSchema: unknown | null;\n configSchemaVersion: string | null;\n configSchemaLoading: boolean;\n configUiHints: ConfigUiHints;\n configForm: Record<string, unknown> | null;\n configFormOriginal: Record<string, unknown> | null;\n configFormDirty: boolean;\n configFormMode: \"form\" | \"raw\";\n configSearchQuery: string;\n configActiveSection: string | null;\n configActiveSubsection: string | null;\n lastError: string | null;\n};\n\nexport async function loadConfig(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.configLoading = true;\n state.lastError = null;\n try {\n const res = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n applyConfigSnapshot(state, res);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configLoading = false;\n }\n}\n\nexport async function loadConfigSchema(state: ConfigState) {\n if (!state.client || !state.connected) return;\n if (state.configSchemaLoading) return;\n state.configSchemaLoading = true;\n try {\n const res = (await state.client.request(\n \"config.schema\",\n {},\n )) as ConfigSchemaResponse;\n applyConfigSchema(state, res);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configSchemaLoading = false;\n }\n}\n\nexport function applyConfigSchema(\n state: ConfigState,\n res: ConfigSchemaResponse,\n) {\n state.configSchema = res.schema ?? null;\n state.configUiHints = res.uiHints ?? {};\n state.configSchemaVersion = res.version ?? null;\n}\n\nexport function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot) {\n state.configSnapshot = snapshot;\n const rawFromSnapshot =\n typeof snapshot.raw === \"string\"\n ? snapshot.raw\n : snapshot.config && typeof snapshot.config === \"object\"\n ? serializeConfigForm(snapshot.config as Record<string, unknown>)\n : state.configRaw;\n if (!state.configFormDirty || state.configFormMode === \"raw\") {\n state.configRaw = rawFromSnapshot;\n } else if (state.configForm) {\n state.configRaw = serializeConfigForm(state.configForm);\n } else {\n state.configRaw = rawFromSnapshot;\n }\n state.configValid = typeof snapshot.valid === \"boolean\" ? snapshot.valid : null;\n state.configIssues = Array.isArray(snapshot.issues) ? snapshot.issues : [];\n\n if (!state.configFormDirty) {\n state.configForm = cloneConfigObject(snapshot.config ?? {});\n state.configFormOriginal = cloneConfigObject(snapshot.config ?? {});\n state.configRawOriginal = rawFromSnapshot;\n }\n}\n\nexport async function saveConfig(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.configSaving = true;\n state.lastError = null;\n try {\n const raw =\n state.configFormMode === \"form\" && state.configForm\n ? serializeConfigForm(state.configForm)\n : state.configRaw;\n const baseHash = state.configSnapshot?.hash;\n if (!baseHash) {\n state.lastError = \"Config hash missing; reload and retry.\";\n return;\n }\n await state.client.request(\"config.set\", { raw, baseHash });\n state.configFormDirty = false;\n await loadConfig(state);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configSaving = false;\n }\n}\n\nexport async function applyConfig(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.configApplying = true;\n state.lastError = null;\n try {\n const raw =\n state.configFormMode === \"form\" && state.configForm\n ? serializeConfigForm(state.configForm)\n : state.configRaw;\n const baseHash = state.configSnapshot?.hash;\n if (!baseHash) {\n state.lastError = \"Config hash missing; reload and retry.\";\n return;\n }\n await state.client.request(\"config.apply\", {\n raw,\n baseHash,\n sessionKey: state.applySessionKey,\n });\n state.configFormDirty = false;\n await loadConfig(state);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configApplying = false;\n }\n}\n\nexport async function runUpdate(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.updateRunning = true;\n state.lastError = null;\n try {\n await state.client.request(\"update.run\", {\n sessionKey: state.applySessionKey,\n });\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.updateRunning = false;\n }\n}\n\nexport function updateConfigFormValue(\n state: ConfigState,\n path: Array<string | number>,\n value: unknown,\n) {\n const base = cloneConfigObject(\n state.configForm ?? state.configSnapshot?.config ?? {},\n );\n setPathValue(base, path, value);\n state.configForm = base;\n state.configFormDirty = true;\n if (state.configFormMode === \"form\") {\n state.configRaw = serializeConfigForm(base);\n }\n}\n\nexport function removeConfigFormValue(\n state: ConfigState,\n path: Array<string | number>,\n) {\n const base = cloneConfigObject(\n state.configForm ?? state.configSnapshot?.config ?? {},\n );\n removePathValue(base, path);\n state.configForm = base;\n state.configFormDirty = true;\n if (state.configFormMode === \"form\") {\n state.configRaw = serializeConfigForm(base);\n }\n}\n","import { toNumber } from \"../format\";\nimport type { GatewayBrowserClient } from \"../gateway\";\nimport type { CronJob, CronRunLogEntry, CronStatus } from \"../types\";\nimport type { CronFormState } from \"../ui-types\";\n\nexport type CronRunResult = {\n status: string;\n durationMs?: number;\n summary?: string;\n outputText?: string;\n error?: string;\n};\n\nexport type CronState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n cronLoading: boolean;\n cronJobs: CronJob[];\n cronStatus: CronStatus | null;\n cronError: string | null;\n cronForm: CronFormState;\n cronRunsJobId: string | null;\n cronRuns: CronRunLogEntry[];\n cronBusy: boolean;\n workspaceAgentIds?: string[];\n accountId?: string;\n cronRunModalJobId: string | null;\n cronRunModalJobName: string;\n cronRunResult: CronRunResult | null;\n};\n\nexport async function loadCronStatus(state: CronState) {\n if (!state.client || !state.connected) return;\n try {\n const res = (await state.client.request(\"cron.status\", {})) as CronStatus;\n state.cronStatus = res;\n } catch (err) {\n state.cronError = String(err);\n }\n}\n\nexport async function loadCronJobs(state: CronState) {\n if (!state.client || !state.connected) return;\n if (state.cronLoading) return;\n state.cronLoading = true;\n state.cronError = null;\n try {\n const listParams: Record<string, unknown> = { includeDisabled: true };\n if (Array.isArray(state.workspaceAgentIds) && state.workspaceAgentIds.length > 0) {\n listParams.agentIds = state.workspaceAgentIds;\n }\n if (state.accountId) {\n listParams.accountId = state.accountId;\n }\n const res = (await state.client.request(\"cron.list\", listParams)) as { jobs?: CronJob[] };\n state.cronJobs = Array.isArray(res.jobs) ? res.jobs : [];\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronLoading = false;\n }\n}\n\nexport function buildCronSchedule(form: CronFormState) {\n if (form.scheduleKind === \"at\") {\n const ms = Date.parse(form.scheduleAt);\n if (!Number.isFinite(ms)) throw new Error(\"Invalid run time.\");\n return { kind: \"at\" as const, atMs: ms };\n }\n if (form.scheduleKind === \"every\") {\n const amount = toNumber(form.everyAmount, 0);\n if (amount <= 0) throw new Error(\"Invalid interval amount.\");\n const unit = form.everyUnit;\n const mult = unit === \"minutes\" ? 60_000 : unit === \"hours\" ? 3_600_000 : 86_400_000;\n return { kind: \"every\" as const, everyMs: amount * mult };\n }\n const expr = form.cronExpr.trim();\n if (!expr) throw new Error(\"Cron expression required.\");\n return { kind: \"cron\" as const, expr, tz: form.cronTz.trim() || undefined };\n}\n\nexport function buildCronPayload(form: CronFormState) {\n if (form.payloadKind === \"systemEvent\") {\n const text = form.payloadText.trim();\n if (!text) throw new Error(\"System event text required.\");\n return { kind: \"systemEvent\" as const, text };\n }\n const message = form.payloadText.trim();\n if (!message) throw new Error(\"Agent message required.\");\n const payload: {\n kind: \"agentTurn\";\n message: string;\n deliver?: boolean;\n channel?: string;\n to?: string;\n timeoutSeconds?: number;\n } = { kind: \"agentTurn\", message };\n if (form.deliver) payload.deliver = true;\n if (form.channel) payload.channel = form.channel;\n // Combine recipients + admins token into comma-separated `to` field.\n const toParts: string[] = [];\n if (form.toAdmins) toParts.push(\"admins\");\n for (const r of form.recipients) {\n const trimmed = r.trim();\n if (trimmed) toParts.push(trimmed);\n }\n if (toParts.length > 0) payload.to = toParts.join(\",\");\n const timeoutSeconds = toNumber(form.timeoutSeconds, 0);\n if (timeoutSeconds > 0) payload.timeoutSeconds = timeoutSeconds;\n return payload;\n}\n\nexport async function addCronJob(state: CronState) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n const schedule = buildCronSchedule(state.cronForm);\n const payload = buildCronPayload(state.cronForm);\n const agentId = state.cronForm.agentId.trim();\n const accountId = state.cronForm.accountId?.trim();\n const job = {\n name: state.cronForm.name.trim(),\n description: state.cronForm.description.trim() || undefined,\n agentId: agentId || undefined,\n accountId: accountId || undefined,\n enabled: state.cronForm.enabled,\n schedule,\n sessionTarget: state.cronForm.sessionTarget,\n wakeMode: state.cronForm.wakeMode,\n payload,\n isolation:\n state.cronForm.postToMainPrefix.trim() &&\n state.cronForm.sessionTarget === \"isolated\"\n ? { postToMainPrefix: state.cronForm.postToMainPrefix.trim() }\n : undefined,\n };\n if (!job.name) throw new Error(\"Name required.\");\n await state.client.request(\"cron.add\", job);\n state.cronForm = {\n ...state.cronForm,\n name: \"\",\n description: \"\",\n payloadText: \"\",\n };\n await loadCronJobs(state);\n await loadCronStatus(state);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\nexport async function toggleCronJob(\n state: CronState,\n job: CronJob,\n enabled: boolean,\n) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n await state.client.request(\"cron.update\", { id: job.id, patch: { enabled } });\n await loadCronJobs(state);\n await loadCronStatus(state);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\nexport async function runCronJob(state: CronState, job: CronJob) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n // Show the run modal immediately so the user sees feedback.\n state.cronRunModalJobId = job.id;\n state.cronRunModalJobName = job.name || \"Untitled\";\n state.cronRunResult = null;\n try {\n await state.client.request(\"cron.run\", { id: job.id, mode: \"force\" });\n await loadCronRuns(state, job.id);\n } catch (err) {\n state.cronError = String(err);\n state.cronRunResult = { status: \"error\", error: String(err) };\n } finally {\n state.cronBusy = false;\n }\n}\n\n/** Handle incoming cron events — updates the run modal when the running job finishes. */\nexport function handleCronRunEvent(\n state: CronState,\n payload: { jobId?: string; action?: string; status?: string; durationMs?: number; summary?: string; outputText?: string; error?: string },\n) {\n if (\n state.cronRunModalJobId &&\n payload.jobId === state.cronRunModalJobId &&\n payload.action === \"finished\"\n ) {\n state.cronRunResult = {\n status: payload.status ?? \"unknown\",\n durationMs: payload.durationMs,\n summary: payload.summary,\n outputText: payload.outputText,\n error: payload.error,\n };\n }\n}\n\nexport function closeCronRunModal(state: CronState) {\n state.cronRunModalJobId = null;\n state.cronRunModalJobName = \"\";\n state.cronRunResult = null;\n}\n\nexport async function removeCronJob(state: CronState, job: CronJob) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n await state.client.request(\"cron.remove\", { id: job.id });\n if (state.cronRunsJobId === job.id) {\n state.cronRunsJobId = null;\n state.cronRuns = [];\n }\n await loadCronJobs(state);\n await loadCronStatus(state);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\n/**\n * Convert a CronJob back to CronFormState for editing.\n * Reverse-maps schedule (everyMs → amount+unit), payload (message → payloadText), etc.\n */\nexport function cronJobToFormState(job: CronJob): CronFormState {\n const form: CronFormState = {\n name: job.name || \"\",\n description: job.description || \"\",\n agentId: job.agentId || \"\",\n enabled: job.enabled,\n scheduleKind: job.schedule.kind,\n scheduleAt: \"\",\n everyAmount: \"30\",\n everyUnit: \"minutes\",\n cronExpr: \"\",\n cronTz: \"\",\n sessionTarget: job.sessionTarget || \"main\",\n wakeMode: job.wakeMode || \"next-heartbeat\",\n payloadKind: job.payload.kind,\n payloadText: \"\",\n deliver: false,\n channel: \"last\",\n recipients: [],\n toAdmins: false,\n timeoutSeconds: \"\",\n postToMainPrefix: \"\",\n };\n\n // Schedule\n if (job.schedule.kind === \"at\") {\n const d = new Date(job.schedule.atMs);\n // datetime-local expects \"YYYY-MM-DDTHH:MM\"\n const pad = (n: number) => String(n).padStart(2, \"0\");\n form.scheduleAt = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n } else if (job.schedule.kind === \"every\") {\n const ms = job.schedule.everyMs;\n if (ms % 86_400_000 === 0) {\n form.everyAmount = String(ms / 86_400_000);\n form.everyUnit = \"days\";\n } else if (ms % 3_600_000 === 0) {\n form.everyAmount = String(ms / 3_600_000);\n form.everyUnit = \"hours\";\n } else {\n form.everyAmount = String(ms / 60_000);\n form.everyUnit = \"minutes\";\n }\n } else if (job.schedule.kind === \"cron\") {\n form.cronExpr = job.schedule.expr;\n form.cronTz = job.schedule.tz || \"\";\n }\n\n // Payload\n if (job.payload.kind === \"systemEvent\") {\n form.payloadText = job.payload.text;\n } else if (job.payload.kind === \"agentTurn\") {\n form.payloadText = job.payload.message;\n form.deliver = job.payload.deliver ?? false;\n form.timeoutSeconds = job.payload.timeoutSeconds ? String(job.payload.timeoutSeconds) : \"\";\n // channel can be on payload directly or via legacy 'provider' field\n const channel = (job.payload as Record<string, unknown>).channel ?? job.payload.provider;\n form.channel = (channel as string) || \"last\";\n // Parse comma-separated `to` into recipients + toAdmins\n const rawTo = job.payload.to || \"\";\n if (rawTo) {\n const parts = rawTo.split(\",\").map((s) => s.trim()).filter(Boolean);\n form.toAdmins = parts.some((p) => p.toLowerCase() === \"admins\");\n form.recipients = parts.filter((p) => p.toLowerCase() !== \"admins\");\n }\n }\n\n // Isolation\n if (job.isolation?.postToMainPrefix) {\n form.postToMainPrefix = job.isolation.postToMainPrefix;\n }\n\n return form;\n}\n\nexport async function updateCronJob(state: CronState, jobId: string) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n const schedule = buildCronSchedule(state.cronForm);\n const payload = buildCronPayload(state.cronForm);\n const patch: Record<string, unknown> = {\n name: state.cronForm.name.trim(),\n description: state.cronForm.description.trim() || undefined,\n agentId: state.cronForm.agentId.trim() || undefined,\n enabled: state.cronForm.enabled,\n schedule,\n sessionTarget: state.cronForm.sessionTarget,\n wakeMode: state.cronForm.wakeMode,\n payload,\n };\n if (state.cronForm.postToMainPrefix.trim() && state.cronForm.sessionTarget === \"isolated\") {\n patch.isolation = { postToMainPrefix: state.cronForm.postToMainPrefix.trim() };\n } else {\n patch.isolation = undefined;\n }\n if (!patch.name) throw new Error(\"Name required.\");\n await state.client.request(\"cron.update\", { id: jobId, patch });\n await loadCronJobs(state);\n await loadCronStatus(state);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\nexport async function loadCronRuns(state: CronState, jobId: string) {\n if (!state.client || !state.connected) return;\n try {\n const res = (await state.client.request(\"cron.runs\", {\n id: jobId,\n limit: 50,\n })) as { entries?: CronRunLogEntry[] };\n state.cronRunsJobId = jobId;\n state.cronRuns = Array.isArray(res.entries) ? res.entries : [];\n } catch (err) {\n state.cronError = String(err);\n }\n}\n","import type { ChannelsStatusSnapshot, ConfigSnapshot } from \"../types\";\nimport type { ChannelsState } from \"./channels.types\";\nimport { cloneConfigObject, serializeConfigForm } from \"./config/form-utils\";\n\nexport type { ChannelsState };\n\nexport async function loadChannels(state: ChannelsState, probe: boolean) {\n if (!state.client || !state.connected) return;\n if (state.channelsLoading) return;\n state.channelsLoading = true;\n state.channelsError = null;\n try {\n const res = (await state.client.request(\"channels.status\", {\n probe,\n timeoutMs: 8000,\n })) as ChannelsStatusSnapshot;\n state.channelsSnapshot = res;\n state.channelsLastSuccess = Date.now();\n } catch (err) {\n state.channelsError = String(err);\n } finally {\n state.channelsLoading = false;\n }\n}\n\nexport async function startWhatsAppLogin(state: ChannelsState, force: boolean, accountId?: string) {\n if (!state.client || !state.connected || state.whatsappBusy) {\n return;\n }\n state.whatsappBusy = true;\n state.whatsappActiveQrAccountId = accountId ?? null;\n try {\n const res = (await state.client.request(\"web.login.start\", {\n force,\n timeoutMs: 30000,\n accountId,\n })) as { message?: string; qrDataUrl?: string };\n state.whatsappLoginMessage = res.message ?? null;\n state.whatsappLoginQrDataUrl = res.qrDataUrl ?? null;\n state.whatsappLoginConnected = null;\n } catch (err) {\n state.whatsappLoginMessage = String(err);\n state.whatsappLoginQrDataUrl = null;\n state.whatsappLoginConnected = null;\n } finally {\n state.whatsappBusy = false;\n }\n}\n\nexport async function waitWhatsAppLogin(state: ChannelsState, accountId?: string) {\n if (!state.client || !state.connected || state.whatsappBusy) return;\n state.whatsappBusy = true;\n try {\n const res = (await state.client.request(\"web.login.wait\", {\n timeoutMs: 120000,\n accountId,\n })) as { connected?: boolean; message?: string; selfPhone?: string };\n state.whatsappLoginMessage = res.message ?? null;\n state.whatsappLoginConnected = res.connected ?? null;\n if (res.connected) {\n state.whatsappLoginQrDataUrl = null;\n state.whatsappActiveQrAccountId = null;\n state.whatsappPairedPhone = res.selfPhone ?? null;\n }\n } catch (err) {\n state.whatsappLoginMessage = String(err);\n state.whatsappLoginConnected = null;\n } finally {\n state.whatsappBusy = false;\n }\n}\n\nexport async function logoutWhatsApp(state: ChannelsState, accountId?: string) {\n if (!state.client || !state.connected || state.whatsappBusy) return;\n state.whatsappBusy = true;\n try {\n await state.client.request(\"channels.logout\", { channel: \"whatsapp\", accountId });\n state.whatsappLoginMessage = \"Logged out.\";\n state.whatsappLoginQrDataUrl = null;\n state.whatsappLoginConnected = null;\n state.whatsappActiveQrAccountId = null;\n } catch (err) {\n state.whatsappLoginMessage = String(err);\n } finally {\n state.whatsappBusy = false;\n }\n}\n\n/**\n * Add a new WhatsApp Baileys account to config.\n * Follows the admins controller pattern: config.get → mutate → config.set with baseHash.\n */\nexport async function addWhatsAppAccount(state: ChannelsState, name: string) {\n if (!state.client || !state.connected) return;\n if (state.whatsappAccountSaving) return;\n\n const trimmed = name.trim();\n if (!trimmed) {\n state.whatsappAccountError = \"Account name is required.\";\n return;\n }\n\n // Generate accountId from name: lowercase, replace spaces/special chars with hyphens\n const accountId = trimmed\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n if (!accountId) {\n state.whatsappAccountError = \"Invalid account name.\";\n return;\n }\n\n state.whatsappAccountSaving = true;\n state.whatsappAccountError = null;\n try {\n // Load fresh config\n const configRes = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n state.configSnapshot = configRes;\n const config = cloneConfigObject((configRes.config ?? {}) as Record<string, unknown>);\n\n // Ensure channels.whatsapp.accounts exists\n if (!config.channels || typeof config.channels !== \"object\") {\n config.channels = {};\n }\n const channels = config.channels as Record<string, unknown>;\n if (!channels.whatsapp || typeof channels.whatsapp !== \"object\") {\n channels.whatsapp = {};\n }\n const whatsapp = channels.whatsapp as Record<string, unknown>;\n if (!whatsapp.accounts || typeof whatsapp.accounts !== \"object\") {\n whatsapp.accounts = {};\n }\n const accounts = whatsapp.accounts as Record<string, unknown>;\n\n // Check for duplicate\n if (accounts[accountId]) {\n state.whatsappAccountError = `Account \"${accountId}\" already exists.`;\n return;\n }\n\n // Add the new account\n accounts[accountId] = { name: trimmed, provider: \"baileys\" };\n\n const baseHash = configRes.hash;\n if (!baseHash) {\n state.whatsappAccountError = \"Config hash missing; reload and retry.\";\n return;\n }\n const raw = serializeConfigForm(config);\n await state.client.request(\"config.set\", { raw, baseHash });\n\n // Reset form state\n state.addingWhatsAppAccount = false;\n state.newWhatsAppAccountName = \"\";\n\n // Reload channels to show the new account\n await loadChannels(state, true);\n\n // Start QR flow for the new account\n await startWhatsAppLogin(state, true, accountId);\n } catch (err) {\n state.whatsappAccountError = String(err);\n } finally {\n state.whatsappAccountSaving = false;\n }\n}\n\n/**\n * Remove a WhatsApp account from config.\n * Prevents removing the last remaining account.\n */\nexport async function removeWhatsAppAccount(state: ChannelsState, accountId: string) {\n if (!state.client || !state.connected) return;\n if (state.whatsappAccountSaving) return;\n\n state.whatsappAccountSaving = true;\n state.whatsappAccountError = null;\n try {\n // Load fresh config\n const configRes = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n state.configSnapshot = configRes;\n const config = cloneConfigObject((configRes.config ?? {}) as Record<string, unknown>);\n\n const channels = config.channels as Record<string, unknown> | undefined;\n const whatsapp = channels?.whatsapp as Record<string, unknown> | undefined;\n const accounts = whatsapp?.accounts as Record<string, unknown> | undefined;\n\n if (!accounts) {\n state.whatsappAccountError = \"No accounts found in config.\";\n return;\n }\n\n const accountKeys = Object.keys(accounts);\n if (accountKeys.length <= 1) {\n state.whatsappAccountError = \"Cannot remove the last account.\";\n return;\n }\n\n if (!accounts[accountId]) {\n state.whatsappAccountError = `Account \"${accountId}\" not found.`;\n return;\n }\n\n // Logout the account first\n try {\n await state.client.request(\"channels.logout\", { channel: \"whatsapp\", accountId });\n } catch {\n // Logout failure is non-fatal — account may already be disconnected\n }\n\n // Remove the account\n delete accounts[accountId];\n\n // Remove any bindings referencing this accountId\n if (Array.isArray(config.bindings)) {\n config.bindings = (config.bindings as Array<Record<string, unknown>>).filter((binding) => {\n const match = binding.match as Record<string, unknown> | undefined;\n if (!match) return true;\n if (match.channel !== \"whatsapp\") return true;\n return match.accountId !== accountId;\n });\n }\n\n const baseHash = configRes.hash;\n if (!baseHash) {\n state.whatsappAccountError = \"Config hash missing; reload and retry.\";\n return;\n }\n const raw = serializeConfigForm(config);\n await state.client.request(\"config.set\", { raw, baseHash });\n\n // Clear any active QR state for this account\n if (state.whatsappActiveQrAccountId === accountId) {\n state.whatsappActiveQrAccountId = null;\n state.whatsappLoginQrDataUrl = null;\n state.whatsappLoginMessage = null;\n }\n\n // Reload channels\n await loadChannels(state, true);\n } catch (err) {\n state.whatsappAccountError = String(err);\n } finally {\n state.whatsappAccountSaving = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { HealthSnapshot, StatusSummary } from \"../types\";\n\nexport type DebugState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n debugLoading: boolean;\n debugStatus: StatusSummary | null;\n debugHealth: HealthSnapshot | null;\n debugModels: unknown[];\n debugHeartbeat: unknown | null;\n debugCallMethod: string;\n debugCallParams: string;\n debugCallResult: string | null;\n debugCallError: string | null;\n};\n\nexport async function loadDebug(state: DebugState) {\n if (!state.client || !state.connected) return;\n if (state.debugLoading) return;\n state.debugLoading = true;\n try {\n const [status, health, models, heartbeat] = await Promise.all([\n state.client.request(\"status\", {}),\n state.client.request(\"health\", {}),\n state.client.request(\"models.list\", {}),\n state.client.request(\"last-heartbeat\", {}),\n ]);\n state.debugStatus = status as StatusSummary;\n state.debugHealth = health as HealthSnapshot;\n const modelPayload = models as { models?: unknown[] } | undefined;\n state.debugModels = Array.isArray(modelPayload?.models)\n ? modelPayload?.models\n : [];\n state.debugHeartbeat = heartbeat as unknown;\n } catch (err) {\n state.debugCallError = String(err);\n } finally {\n state.debugLoading = false;\n }\n}\n\nexport async function callDebugMethod(state: DebugState) {\n if (!state.client || !state.connected) return;\n state.debugCallError = null;\n state.debugCallResult = null;\n try {\n const params = state.debugCallParams.trim()\n ? (JSON.parse(state.debugCallParams) as unknown)\n : {};\n const res = await state.client.request(state.debugCallMethod.trim(), params);\n state.debugCallResult = JSON.stringify(res, null, 2);\n } catch (err) {\n state.debugCallError = String(err);\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\n\nconst ACCESS_SESSION_KEY = \"taskmaster-access-session\";\n\nexport type AccessAccount = {\n id: string;\n displayName: string;\n};\n\nexport type AccessState = {\n /** Whether we've checked access status with the server. */\n checked: boolean;\n /** Whether PINs are configured on this device. */\n hasPins: boolean;\n /** Whether a master PIN exists (device has been set up). */\n hasMasterPin: boolean;\n /** Whether the current session is authenticated. */\n authenticated: boolean;\n /** Workspace this session is scoped to (null = master/all). */\n workspace: string | null;\n /** Whether this is a master (device owner) session. */\n master: boolean;\n /** Available accounts for the login selector. */\n accounts: AccessAccount[];\n /** Error message from last verify attempt. */\n error: string | null;\n /** Whether a verify/set request is in flight. */\n busy: boolean;\n};\n\nexport const DEFAULT_ACCESS_STATE: AccessState = {\n checked: false,\n hasPins: false,\n hasMasterPin: false,\n authenticated: false,\n workspace: null,\n master: false,\n accounts: [],\n error: null,\n busy: false,\n};\n\nexport function getStoredSessionToken(): string | null {\n try {\n return localStorage.getItem(ACCESS_SESSION_KEY);\n } catch {\n return null;\n }\n}\n\nfunction storeSessionToken(token: string): void {\n try {\n localStorage.setItem(ACCESS_SESSION_KEY, token);\n } catch {\n // localStorage unavailable\n }\n}\n\nfunction clearSessionToken(): void {\n try {\n localStorage.removeItem(ACCESS_SESSION_KEY);\n } catch {\n // localStorage unavailable\n }\n}\n\ntype AccessHost = {\n client: GatewayBrowserClient | null;\n accessState: AccessState;\n};\n\n/**\n * Check access status with the server.\n * Called after gateway connects on every page load.\n */\nexport async function checkAccessStatus(host: AccessHost): Promise<void> {\n if (!host.client) return;\n try {\n const token = getStoredSessionToken();\n const result = (await host.client.request(\"access.status\", { token })) as {\n hasMasterPin: boolean;\n hasPins: boolean;\n accounts: AccessAccount[];\n authenticated: boolean;\n workspace: string | null;\n master: boolean;\n };\n host.accessState = {\n ...host.accessState,\n checked: true,\n hasPins: result.hasPins,\n hasMasterPin: result.hasMasterPin,\n accounts: result.accounts ?? [],\n authenticated: result.authenticated,\n workspace: result.workspace,\n master: result.master,\n error: null,\n };\n } catch {\n // If access.status fails, assume no PINs configured (backwards compatible)\n host.accessState = {\n ...host.accessState,\n checked: true,\n hasPins: false,\n hasMasterPin: false,\n accounts: [],\n authenticated: true,\n error: null,\n };\n }\n}\n\n/**\n * Verify a PIN for a specific account and establish a session.\n */\nexport async function verifyPin(\n host: AccessHost,\n account: string,\n pin: string,\n): Promise<void> {\n if (!host.client) return;\n host.accessState = { ...host.accessState, busy: true, error: null };\n try {\n const result = (await host.client.request(\"access.verify\", { account, pin })) as {\n ok: boolean;\n token?: string;\n workspace?: string | null;\n master?: boolean;\n message?: string;\n };\n if (result.ok && result.token) {\n storeSessionToken(result.token);\n host.accessState = {\n ...host.accessState,\n authenticated: true,\n workspace: result.workspace ?? null,\n master: result.master ?? false,\n busy: false,\n error: null,\n };\n } else {\n host.accessState = {\n ...host.accessState,\n busy: false,\n error: result.message ?? \"Incorrect PIN\",\n };\n }\n } catch {\n host.accessState = {\n ...host.accessState,\n busy: false,\n error: \"Failed to verify PIN\",\n };\n }\n}\n\n/**\n * Set the master PIN (first-time setup).\n */\nexport async function setMasterPin(host: AccessHost, pin: string): Promise<void> {\n if (!host.client) return;\n host.accessState = { ...host.accessState, busy: true, error: null };\n try {\n const result = (await host.client.request(\"access.setMasterPin\", { pin })) as {\n ok: boolean;\n token?: string;\n };\n if (result.ok && result.token) {\n storeSessionToken(result.token);\n host.accessState = {\n ...host.accessState,\n checked: true,\n hasPins: true,\n hasMasterPin: true,\n authenticated: true,\n workspace: null,\n master: true,\n busy: false,\n error: null,\n };\n } else {\n host.accessState = { ...host.accessState, busy: false, error: \"Failed to set PIN\" };\n }\n } catch {\n host.accessState = { ...host.accessState, busy: false, error: \"Failed to set PIN\" };\n }\n}\n\n/**\n * Set a per-workspace PIN.\n */\nexport async function setAccountPin(\n host: AccessHost,\n workspace: string,\n pin: string,\n): Promise<boolean> {\n if (!host.client) return false;\n try {\n const result = (await host.client.request(\"access.setAccountPin\", { workspace, pin })) as {\n ok: boolean;\n };\n return result.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Logout — clear session.\n */\nexport async function logout(host: AccessHost): Promise<void> {\n const token = getStoredSessionToken();\n if (host.client && token) {\n try {\n await host.client.request(\"access.logout\", { token });\n } catch {\n // best-effort\n }\n }\n clearSessionToken();\n host.accessState = {\n ...DEFAULT_ACCESS_STATE,\n checked: true,\n hasPins: true,\n hasMasterPin: host.accessState.hasMasterPin,\n accounts: host.accessState.accounts,\n };\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { LogEntry, LogLevel } from \"../types\";\nimport { getStoredSessionToken } from \"./access\";\n\nexport type LogsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n logsLoading: boolean;\n logsError: string | null;\n logsCursor: number | null;\n logsFile: string | null;\n logsEntries: LogEntry[];\n logsTruncated: boolean;\n logsLastFetchAt: number | null;\n logsLimit: number;\n logsMaxBytes: number;\n /** Selected date (YYYY-MM-DD) for historical log viewing. null = today (live). */\n logsDate: string | null;\n /** Available log dates discovered from the server, most recent first. */\n logsAvailableDates: string[];\n};\n\nconst LOG_BUFFER_LIMIT = 2000;\nconst LEVELS = new Set<LogLevel>([\n \"trace\",\n \"debug\",\n \"info\",\n \"warn\",\n \"error\",\n \"fatal\",\n]);\n\nfunction parseMaybeJsonString(value: unknown) {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"{\") || !trimmed.endsWith(\"}\")) return null;\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!parsed || typeof parsed !== \"object\") return null;\n return parsed as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction normalizeLevel(value: unknown): LogLevel | null {\n if (typeof value !== \"string\") return null;\n const lowered = value.toLowerCase() as LogLevel;\n return LEVELS.has(lowered) ? lowered : null;\n}\n\nexport function parseLogLine(line: string): LogEntry {\n if (!line.trim()) return { raw: line, message: line };\n try {\n const obj = JSON.parse(line) as Record<string, unknown>;\n const meta =\n obj && typeof obj._meta === \"object\" && obj._meta !== null\n ? (obj._meta as Record<string, unknown>)\n : null;\n const time =\n typeof obj.time === \"string\"\n ? obj.time\n : typeof meta?.date === \"string\"\n ? meta?.date\n : null;\n const level = normalizeLevel(meta?.logLevelName ?? meta?.level);\n\n const contextCandidate =\n typeof obj[\"0\"] === \"string\"\n ? (obj[\"0\"] as string)\n : typeof meta?.name === \"string\"\n ? (meta?.name as string)\n : null;\n const contextObj = parseMaybeJsonString(contextCandidate);\n let subsystem: string | null = null;\n if (contextObj) {\n if (typeof contextObj.subsystem === \"string\") subsystem = contextObj.subsystem;\n else if (typeof contextObj.module === \"string\") subsystem = contextObj.module;\n }\n if (!subsystem && contextCandidate && contextCandidate.length < 120) {\n subsystem = contextCandidate;\n }\n\n let message: string | null = null;\n if (typeof obj[\"1\"] === \"string\") message = obj[\"1\"] as string;\n else if (!contextObj && typeof obj[\"0\"] === \"string\") message = obj[\"0\"] as string;\n else if (typeof obj.message === \"string\") message = obj.message as string;\n\n return {\n raw: line,\n time,\n level,\n subsystem,\n message: message ?? line,\n meta: meta ?? undefined,\n };\n } catch {\n return { raw: line, message: line };\n }\n}\n\nexport async function loadLogs(\n state: LogsState,\n opts?: { reset?: boolean; quiet?: boolean },\n) {\n if (!state.client || !state.connected) return;\n if (state.logsLoading && !opts?.quiet) return;\n if (!opts?.quiet) state.logsLoading = true;\n state.logsError = null;\n try {\n const res = await state.client.request(\"logs.tail\", {\n cursor: opts?.reset ? undefined : state.logsCursor ?? undefined,\n limit: state.logsLimit,\n maxBytes: state.logsMaxBytes,\n date: state.logsDate ?? undefined,\n accessToken: getStoredSessionToken() ?? undefined,\n });\n const payload = res as {\n file?: string;\n cursor?: number;\n size?: number;\n lines?: unknown;\n truncated?: boolean;\n reset?: boolean;\n availableDates?: string[];\n };\n const lines = Array.isArray(payload.lines)\n ? (payload.lines.filter((line) => typeof line === \"string\") as string[])\n : [];\n const entries = lines.map(parseLogLine);\n const shouldReset = Boolean(opts?.reset || payload.reset || state.logsCursor == null);\n state.logsEntries = shouldReset\n ? entries\n : [...state.logsEntries, ...entries].slice(-LOG_BUFFER_LIMIT);\n if (typeof payload.cursor === \"number\") state.logsCursor = payload.cursor;\n if (typeof payload.file === \"string\") state.logsFile = payload.file;\n if (Array.isArray(payload.availableDates)) {\n state.logsAvailableDates = payload.availableDates.filter(\n (d) => typeof d === \"string\",\n ) as string[];\n }\n state.logsTruncated = Boolean(payload.truncated);\n state.logsLastFetchAt = Date.now();\n } catch (err) {\n state.logsError = String(err);\n } finally {\n if (!opts?.quiet) state.logsLoading = false;\n }\n}\n","/*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) */\n/**\n * 5KB JS implementation of ed25519 EdDSA signatures.\n * Compliant with RFC8032, FIPS 186-5 & ZIP215.\n * @module\n * @example\n * ```js\nimport * as ed from '@noble/ed25519';\n(async () => {\n const secretKey = ed.utils.randomSecretKey();\n const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);\n const pubKey = await ed.getPublicKeyAsync(secretKey); // Sync methods are also present\n const signature = await ed.signAsync(message, secretKey);\n const isValid = await ed.verifyAsync(signature, message, pubKey);\n})();\n```\n */\n/**\n * Curve params. ed25519 is twisted edwards curve. Equation is −x² + y² = -a + dx²y².\n * * P = `2n**255n - 19n` // field over which calculations are done\n * * N = `2n**252n + 27742317777372353535851937790883648493n` // group order, amount of curve points\n * * h = 8 // cofactor\n * * a = `Fp.create(BigInt(-1))` // equation param\n * * d = -121665/121666 a.k.a. `Fp.neg(121665 * Fp.inv(121666))` // equation param\n * * Gx, Gy are coordinates of Generator / base point\n */\nconst ed25519_CURVE = {\n p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,\n n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,\n h: 8n,\n a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,\n d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,\n Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,\n Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,\n};\nconst { p: P, n: N, Gx, Gy, a: _a, d: _d, h } = ed25519_CURVE;\nconst L = 32; // field / group byte length\nconst L2 = 64;\n// Helpers and Precomputes sections are reused between libraries\n// ## Helpers\n// ----------\nconst captureTrace = (...args) => {\n if ('captureStackTrace' in Error && typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(...args);\n }\n};\nconst err = (message = '') => {\n const e = new Error(message);\n captureTrace(e, err);\n throw e;\n};\nconst isBig = (n) => typeof n === 'bigint'; // is big integer\nconst isStr = (s) => typeof s === 'string'; // is string\nconst isBytes = (a) => a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n/** Asserts something is Uint8Array. */\nconst abytes = (value, length, title = '') => {\n const bytes = isBytes(value);\n const len = value?.length;\n const needsLen = length !== undefined;\n if (!bytes || (needsLen && len !== length)) {\n const prefix = title && `\"${title}\" `;\n const ofLen = needsLen ? ` of length ${length}` : '';\n const got = bytes ? `length=${len}` : `type=${typeof value}`;\n err(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);\n }\n return value;\n};\n/** create Uint8Array */\nconst u8n = (len) => new Uint8Array(len);\nconst u8fr = (buf) => Uint8Array.from(buf);\nconst padh = (n, pad) => n.toString(16).padStart(pad, '0');\nconst bytesToHex = (b) => Array.from(abytes(b))\n .map((e) => padh(e, 2))\n .join('');\nconst C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 }; // ASCII characters\nconst _ch = (ch) => {\n if (ch >= C._0 && ch <= C._9)\n return ch - C._0; // '2' => 50-48\n if (ch >= C.A && ch <= C.F)\n return ch - (C.A - 10); // 'B' => 66-(65-10)\n if (ch >= C.a && ch <= C.f)\n return ch - (C.a - 10); // 'b' => 98-(97-10)\n return;\n};\nconst hexToBytes = (hex) => {\n const e = 'hex invalid';\n if (!isStr(hex))\n return err(e);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n return err(e);\n const array = u8n(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n // treat each char as ASCII\n const n1 = _ch(hex.charCodeAt(hi)); // parse first char, multiply it by 16\n const n2 = _ch(hex.charCodeAt(hi + 1)); // parse second char\n if (n1 === undefined || n2 === undefined)\n return err(e);\n array[ai] = n1 * 16 + n2; // example: 'A9' => 10*16 + 9\n }\n return array;\n};\nconst cr = () => globalThis?.crypto; // WebCrypto is available in all modern environments\nconst subtle = () => cr()?.subtle ?? err('crypto.subtle must be defined, consider polyfill');\n// prettier-ignore\nconst concatBytes = (...arrs) => {\n const r = u8n(arrs.reduce((sum, a) => sum + abytes(a).length, 0)); // create u8a of summed length\n let pad = 0; // walk through each array,\n arrs.forEach(a => { r.set(a, pad); pad += a.length; }); // ensure they have proper type\n return r;\n};\n/** WebCrypto OS-level CSPRNG (random number generator). Will throw when not available. */\nconst randomBytes = (len = L) => {\n const c = cr();\n return c.getRandomValues(u8n(len));\n};\nconst big = BigInt;\nconst assertRange = (n, min, max, msg = 'bad number: out of range') => (isBig(n) && min <= n && n < max ? n : err(msg));\n/** modular division */\nconst M = (a, b = P) => {\n const r = a % b;\n return r >= 0n ? r : b + r;\n};\nconst modN = (a) => M(a, N);\n/** Modular inversion using euclidean GCD (non-CT). No negative exponent for now. */\n// prettier-ignore\nconst invert = (num, md) => {\n if (num === 0n || md <= 0n)\n err('no inverse n=' + num + ' mod=' + md);\n let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;\n while (a !== 0n) {\n const q = b / a, r = b % a;\n const m = x - u * q, n = y - v * q;\n b = a, a = r, x = u, y = v, u = m, v = n;\n }\n return b === 1n ? M(x, md) : err('no inverse'); // b is gcd at this point\n};\nconst callHash = (name) => {\n // @ts-ignore\n const fn = hashes[name];\n if (typeof fn !== 'function')\n err('hashes.' + name + ' not set');\n return fn;\n};\nconst hash = (msg) => callHash('sha512')(msg);\nconst apoint = (p) => (p instanceof Point ? p : err('Point expected'));\n// ## End of Helpers\n// -----------------\nconst B256 = 2n ** 256n;\n/** Point in XYZT extended coordinates. */\nclass Point {\n static BASE;\n static ZERO;\n X;\n Y;\n Z;\n T;\n constructor(X, Y, Z, T) {\n const max = B256;\n this.X = assertRange(X, 0n, max);\n this.Y = assertRange(Y, 0n, max);\n this.Z = assertRange(Z, 1n, max);\n this.T = assertRange(T, 0n, max);\n Object.freeze(this);\n }\n static CURVE() {\n return ed25519_CURVE;\n }\n static fromAffine(p) {\n return new Point(p.x, p.y, 1n, M(p.x * p.y));\n }\n /** RFC8032 5.1.3: Uint8Array to Point. */\n static fromBytes(hex, zip215 = false) {\n const d = _d;\n // Copy array to not mess it up.\n const normed = u8fr(abytes(hex, L));\n // adjust first LE byte = last BE byte\n const lastByte = hex[31];\n normed[31] = lastByte & ~0x80;\n const y = bytesToNumLE(normed);\n // zip215=true: 0 <= y < 2^256\n // zip215=false, RFC8032: 0 <= y < 2^255-19\n const max = zip215 ? B256 : P;\n assertRange(y, 0n, max);\n const y2 = M(y * y); // y²\n const u = M(y2 - 1n); // u=y²-1\n const v = M(d * y2 + 1n); // v=dy²+1\n let { isValid, value: x } = uvRatio(u, v); // (uv³)(uv⁷)^(p-5)/8; square root\n if (!isValid)\n err('bad point: y not sqrt'); // not square root: bad point\n const isXOdd = (x & 1n) === 1n; // adjust sign of x coordinate\n const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit\n if (!zip215 && x === 0n && isLastByteOdd)\n err('bad point: x==0, isLastByteOdd'); // x=0, x_0=1\n if (isLastByteOdd !== isXOdd)\n x = M(-x);\n return new Point(x, y, 1n, M(x * y)); // Z=1, T=xy\n }\n static fromHex(hex, zip215) {\n return Point.fromBytes(hexToBytes(hex), zip215);\n }\n get x() {\n return this.toAffine().x;\n }\n get y() {\n return this.toAffine().y;\n }\n /** Checks if the point is valid and on-curve. */\n assertValidity() {\n const a = _a;\n const d = _d;\n const p = this;\n if (p.is0())\n return err('bad point: ZERO'); // TODO: optimize, with vars below?\n // Equation in affine coordinates: ax² + y² = 1 + dx²y²\n // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²\n const { X, Y, Z, T } = p;\n const X2 = M(X * X); // X²\n const Y2 = M(Y * Y); // Y²\n const Z2 = M(Z * Z); // Z²\n const Z4 = M(Z2 * Z2); // Z⁴\n const aX2 = M(X2 * a); // aX²\n const left = M(Z2 * M(aX2 + Y2)); // (aX² + Y²)Z²\n const right = M(Z4 + M(d * M(X2 * Y2))); // Z⁴ + dX²Y²\n if (left !== right)\n return err('bad point: equation left != right (1)');\n // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T\n const XY = M(X * Y);\n const ZT = M(Z * T);\n if (XY !== ZT)\n return err('bad point: equation left != right (2)');\n return this;\n }\n /** Equality check: compare points P&Q. */\n equals(other) {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const { X: X2, Y: Y2, Z: Z2 } = apoint(other); // checks class equality\n const X1Z2 = M(X1 * Z2);\n const X2Z1 = M(X2 * Z1);\n const Y1Z2 = M(Y1 * Z2);\n const Y2Z1 = M(Y2 * Z1);\n return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;\n }\n is0() {\n return this.equals(I);\n }\n /** Flip point over y coordinate. */\n negate() {\n return new Point(M(-this.X), this.Y, this.Z, M(-this.T));\n }\n /** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */\n double() {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const a = _a;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd\n const A = M(X1 * X1);\n const B = M(Y1 * Y1);\n const C = M(2n * M(Z1 * Z1));\n const D = M(a * A);\n const x1y1 = X1 + Y1;\n const E = M(M(x1y1 * x1y1) - A - B);\n const G = D + B;\n const F = G - C;\n const H = D - B;\n const X3 = M(E * F);\n const Y3 = M(G * H);\n const T3 = M(E * H);\n const Z3 = M(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n /** Point addition. Complete formula. Cost: `8M + 1*k + 8add + 1*2`. */\n add(other) {\n const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;\n const { X: X2, Y: Y2, Z: Z2, T: T2 } = apoint(other); // doesn't check if other on-curve\n const a = _a;\n const d = _d;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3\n const A = M(X1 * X2);\n const B = M(Y1 * Y2);\n const C = M(T1 * d * T2);\n const D = M(Z1 * Z2);\n const E = M((X1 + Y1) * (X2 + Y2) - A - B);\n const F = M(D - C);\n const G = M(D + C);\n const H = M(B - a * A);\n const X3 = M(E * F);\n const Y3 = M(G * H);\n const T3 = M(E * H);\n const Z3 = M(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n subtract(other) {\n return this.add(apoint(other).negate());\n }\n /**\n * Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.\n * Uses {@link wNAF} for base point.\n * Uses fake point to mitigate side-channel leakage.\n * @param n scalar by which point is multiplied\n * @param safe safe mode guards against timing attacks; unsafe mode is faster\n */\n multiply(n, safe = true) {\n if (!safe && (n === 0n || this.is0()))\n return I;\n assertRange(n, 1n, N);\n if (n === 1n)\n return this;\n if (this.equals(G))\n return wNAF(n).p;\n // init result point & fake point\n let p = I;\n let f = G;\n for (let d = this; n > 0n; d = d.double(), n >>= 1n) {\n // if bit is present, add to point\n // if not present, add to fake, for timing safety\n if (n & 1n)\n p = p.add(d);\n else if (safe)\n f = f.add(d);\n }\n return p;\n }\n multiplyUnsafe(scalar) {\n return this.multiply(scalar, false);\n }\n /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */\n toAffine() {\n const { X, Y, Z } = this;\n // fast-paths for ZERO point OR Z=1\n if (this.equals(I))\n return { x: 0n, y: 1n };\n const iz = invert(Z, P);\n // (Z * Z^-1) must be 1, otherwise bad math\n if (M(Z * iz) !== 1n)\n err('invalid inverse');\n // x = X*Z^-1; y = Y*Z^-1\n const x = M(X * iz);\n const y = M(Y * iz);\n return { x, y };\n }\n toBytes() {\n const { x, y } = this.assertValidity().toAffine();\n const b = numTo32bLE(y);\n // store sign in first LE byte\n b[31] |= x & 1n ? 0x80 : 0;\n return b;\n }\n toHex() {\n return bytesToHex(this.toBytes());\n }\n clearCofactor() {\n return this.multiply(big(h), false);\n }\n isSmallOrder() {\n return this.clearCofactor().is0();\n }\n isTorsionFree() {\n // Multiply by big number N. We can't `mul(N)` because of checks. Instead, we `mul(N/2)*2+1`\n let p = this.multiply(N / 2n, false).double();\n if (N % 2n)\n p = p.add(this);\n return p.is0();\n }\n}\n/** Generator / base point */\nconst G = new Point(Gx, Gy, 1n, M(Gx * Gy));\n/** Identity / zero point */\nconst I = new Point(0n, 1n, 1n, 0n);\n// Static aliases\nPoint.BASE = G;\nPoint.ZERO = I;\nconst numTo32bLE = (num) => hexToBytes(padh(assertRange(num, 0n, B256), L2)).reverse();\nconst bytesToNumLE = (b) => big('0x' + bytesToHex(u8fr(abytes(b)).reverse()));\nconst pow2 = (x, power) => {\n // pow2(x, 4) == x^(2^4)\n let r = x;\n while (power-- > 0n) {\n r *= r;\n r %= P;\n }\n return r;\n};\n// prettier-ignore\nconst pow_2_252_3 = (x) => {\n const x2 = (x * x) % P; // x^2, bits 1\n const b2 = (x2 * x) % P; // x^3, bits 11\n const b4 = (pow2(b2, 2n) * b2) % P; // x^(2^4-1), bits 1111\n const b5 = (pow2(b4, 1n) * x) % P; // x^(2^5-1), bits 11111\n const b10 = (pow2(b5, 5n) * b5) % P; // x^(2^10)\n const b20 = (pow2(b10, 10n) * b10) % P; // x^(2^20)\n const b40 = (pow2(b20, 20n) * b20) % P; // x^(2^40)\n const b80 = (pow2(b40, 40n) * b40) % P; // x^(2^80)\n const b160 = (pow2(b80, 80n) * b80) % P; // x^(2^160)\n const b240 = (pow2(b160, 80n) * b80) % P; // x^(2^240)\n const b250 = (pow2(b240, 10n) * b10) % P; // x^(2^250)\n const pow_p_5_8 = (pow2(b250, 2n) * x) % P; // < To pow to (p+3)/8, multiply it by x.\n return { pow_p_5_8, b2 };\n};\nconst RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n; // √-1\n// for sqrt comp\n// prettier-ignore\nconst uvRatio = (u, v) => {\n const v3 = M(v * v * v); // v³\n const v7 = M(v3 * v3 * v); // v⁷\n const pow = pow_2_252_3(u * v7).pow_p_5_8; // (uv⁷)^(p-5)/8\n let x = M(u * v3 * pow); // (uv³)(uv⁷)^(p-5)/8\n const vx2 = M(v * x * x); // vx²\n const root1 = x; // First root candidate\n const root2 = M(x * RM1); // Second root candidate; RM1 is √-1\n const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root\n const useRoot2 = vx2 === M(-u); // If vx² = -u, set x <-- x * 2^((p-1)/4)\n const noRoot = vx2 === M(-u * RM1); // There is no valid root, vx² = -u√-1\n if (useRoot1)\n x = root1;\n if (useRoot2 || noRoot)\n x = root2; // We return root2 anyway, for const-time\n if ((M(x) & 1n) === 1n)\n x = M(-x); // edIsNegative\n return { isValid: useRoot1 || useRoot2, value: x };\n};\n// N == L, just weird naming\nconst modL_LE = (hash) => modN(bytesToNumLE(hash)); // modulo L; but little-endian\n/** hashes.sha512 should conform to the interface. */\n// TODO: rename\nconst sha512a = (...m) => hashes.sha512Async(concatBytes(...m)); // Async SHA512\nconst sha512s = (...m) => callHash('sha512')(concatBytes(...m));\n// RFC8032 5.1.5\nconst hash2extK = (hashed) => {\n // slice creates a copy, unlike subarray\n const head = hashed.slice(0, L);\n head[0] &= 248; // Clamp bits: 0b1111_1000\n head[31] &= 127; // 0b0111_1111\n head[31] |= 64; // 0b0100_0000\n const prefix = hashed.slice(L, L2); // secret key \"prefix\"\n const scalar = modL_LE(head); // modular division over curve order\n const point = G.multiply(scalar); // public key point\n const pointBytes = point.toBytes(); // point serialized to Uint8Array\n return { head, prefix, scalar, point, pointBytes };\n};\n// RFC8032 5.1.5; getPublicKey async, sync. Hash priv key and extract point.\nconst getExtendedPublicKeyAsync = (secretKey) => sha512a(abytes(secretKey, L)).then(hash2extK);\nconst getExtendedPublicKey = (secretKey) => hash2extK(sha512s(abytes(secretKey, L)));\n/** Creates 32-byte ed25519 public key from 32-byte secret key. Async. */\nconst getPublicKeyAsync = (secretKey) => getExtendedPublicKeyAsync(secretKey).then((p) => p.pointBytes);\n/** Creates 32-byte ed25519 public key from 32-byte secret key. To use, set `hashes.sha512` first. */\nconst getPublicKey = (priv) => getExtendedPublicKey(priv).pointBytes;\nconst hashFinishA = (res) => sha512a(res.hashable).then(res.finish);\nconst hashFinishS = (res) => res.finish(sha512s(res.hashable));\n// Code, shared between sync & async sign\nconst _sign = (e, rBytes, msg) => {\n const { pointBytes: P, scalar: s } = e;\n const r = modL_LE(rBytes); // r was created outside, reduce it modulo L\n const R = G.multiply(r).toBytes(); // R = [r]B\n const hashable = concatBytes(R, P, msg); // dom2(F, C) || R || A || PH(M)\n const finish = (hashed) => {\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n const S = modN(r + modL_LE(hashed) * s); // S = (r + k * s) mod L; 0 <= s < l\n return abytes(concatBytes(R, numTo32bLE(S)), L2); // 64-byte sig: 32b R.x + 32b LE(S)\n };\n return { hashable, finish };\n};\n/**\n * Signs message using secret key. Async.\n * Follows RFC8032 5.1.6.\n */\nconst signAsync = async (message, secretKey) => {\n const m = abytes(message);\n const e = await getExtendedPublicKeyAsync(secretKey);\n const rBytes = await sha512a(e.prefix, m); // r = SHA512(dom2(F, C) || prefix || PH(M))\n return hashFinishA(_sign(e, rBytes, m)); // gen R, k, S, then 64-byte signature\n};\n/**\n * Signs message using secret key. To use, set `hashes.sha512` first.\n * Follows RFC8032 5.1.6.\n */\nconst sign = (message, secretKey) => {\n const m = abytes(message);\n const e = getExtendedPublicKey(secretKey);\n const rBytes = sha512s(e.prefix, m); // r = SHA512(dom2(F, C) || prefix || PH(M))\n return hashFinishS(_sign(e, rBytes, m)); // gen R, k, S, then 64-byte signature\n};\nconst defaultVerifyOpts = { zip215: true };\nconst _verify = (sig, msg, pub, opts = defaultVerifyOpts) => {\n sig = abytes(sig, L2); // Signature hex str/Bytes, must be 64 bytes\n msg = abytes(msg); // Message hex str/Bytes\n pub = abytes(pub, L);\n const { zip215 } = opts; // switch between zip215 and rfc8032 verif\n let A;\n let R;\n let s;\n let SB;\n let hashable = Uint8Array.of();\n try {\n A = Point.fromBytes(pub, zip215); // public key A decoded\n R = Point.fromBytes(sig.slice(0, L), zip215); // 0 <= R < 2^256: ZIP215 R can be >= P\n s = bytesToNumLE(sig.slice(L, L2)); // Decode second half as an integer S\n SB = G.multiply(s, false); // in the range 0 <= s < L\n hashable = concatBytes(R.toBytes(), A.toBytes(), msg); // dom2(F, C) || R || A || PH(M)\n }\n catch (error) { }\n const finish = (hashed) => {\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n if (SB == null)\n return false; // false if try-catch catched an error\n if (!zip215 && A.isSmallOrder())\n return false; // false for SBS: Strongly Binding Signature\n const k = modL_LE(hashed); // decode in little-endian, modulo L\n const RkA = R.add(A.multiply(k, false)); // [8]R + [8][k]A'\n return RkA.add(SB.negate()).clearCofactor().is0(); // [8][S]B = [8]R + [8][k]A'\n };\n return { hashable, finish };\n};\n/** Verifies signature on message and public key. Async. Follows RFC8032 5.1.7. */\nconst verifyAsync = async (signature, message, publicKey, opts = defaultVerifyOpts) => hashFinishA(_verify(signature, message, publicKey, opts));\n/** Verifies signature on message and public key. To use, set `hashes.sha512` first. Follows RFC8032 5.1.7. */\nconst verify = (signature, message, publicKey, opts = defaultVerifyOpts) => hashFinishS(_verify(signature, message, publicKey, opts));\n/** Math, hex, byte helpers. Not in `utils` because utils share API with noble-curves. */\nconst etc = {\n bytesToHex: bytesToHex,\n hexToBytes: hexToBytes,\n concatBytes: concatBytes,\n mod: M,\n invert: invert,\n randomBytes: randomBytes,\n};\nconst hashes = {\n sha512Async: async (message) => {\n const s = subtle();\n const m = concatBytes(message);\n return u8n(await s.digest('SHA-512', m.buffer));\n },\n sha512: undefined,\n};\n// FIPS 186 B.4.1 compliant key generation produces private keys\n// with modulo bias being neglible. takes >N+16 bytes, returns (hash mod n-1)+1\nconst randomSecretKey = (seed = randomBytes(L)) => seed;\nconst keygen = (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = getPublicKey(secretKey);\n return { secretKey, publicKey };\n};\nconst keygenAsync = async (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = await getPublicKeyAsync(secretKey);\n return { secretKey, publicKey };\n};\n/** ed25519-specific key utilities. */\nconst utils = {\n getExtendedPublicKeyAsync: getExtendedPublicKeyAsync,\n getExtendedPublicKey: getExtendedPublicKey,\n randomSecretKey: randomSecretKey,\n};\n// ## Precomputes\n// --------------\nconst W = 8; // W is window size\nconst scalarBits = 256;\nconst pwindows = Math.ceil(scalarBits / W) + 1; // 33 for W=8, NOT 32 - see wNAF loop\nconst pwindowSize = 2 ** (W - 1); // 128 for W=8\nconst precompute = () => {\n const points = [];\n let p = G;\n let b = p;\n for (let w = 0; w < pwindows; w++) {\n b = p;\n points.push(b);\n for (let i = 1; i < pwindowSize; i++) {\n b = b.add(p);\n points.push(b);\n } // i=1, bc we skip 0\n p = b.double();\n }\n return points;\n};\nlet Gpows = undefined; // precomputes for base point G\n// const-time negate\nconst ctneg = (cnd, p) => {\n const n = p.negate();\n return cnd ? n : p;\n};\n/**\n * Precomputes give 12x faster getPublicKey(), 10x sign(), 2x verify() by\n * caching multiples of G (base point). Cache is stored in 32MB of RAM.\n * Any time `G.multiply` is done, precomputes are used.\n * Not used for getSharedSecret, which instead multiplies random pubkey `P.multiply`.\n *\n * w-ary non-adjacent form (wNAF) precomputation method is 10% slower than windowed method,\n * but takes 2x less RAM. RAM reduction is possible by utilizing `.subtract`.\n *\n * !! Precomputes can be disabled by commenting-out call of the wNAF() inside Point#multiply().\n */\nconst wNAF = (n) => {\n const comp = Gpows || (Gpows = precompute());\n let p = I;\n let f = G; // f must be G, or could become I in the end\n const pow_2_w = 2 ** W; // 256 for W=8\n const maxNum = pow_2_w; // 256 for W=8\n const mask = big(pow_2_w - 1); // 255 for W=8 == mask 0b11111111\n const shiftBy = big(W); // 8 for W=8\n for (let w = 0; w < pwindows; w++) {\n let wbits = Number(n & mask); // extract W bits.\n n >>= shiftBy; // shift number by W bits.\n // We use negative indexes to reduce size of precomputed table by 2x.\n // Instead of needing precomputes 0..256, we only calculate them for 0..128.\n // If an index > 128 is found, we do (256-index) - where 256 is next window.\n // Naive: index +127 => 127, +224 => 224\n // Optimized: index +127 => 127, +224 => 256-32\n if (wbits > pwindowSize) {\n wbits -= maxNum;\n n += 1n;\n }\n const off = w * pwindowSize;\n const offF = off; // offsets, evaluate both\n const offP = off + Math.abs(wbits) - 1;\n const isEven = w % 2 !== 0; // conditions, evaluate both\n const isNeg = wbits < 0;\n if (wbits === 0) {\n // off == I: can't add it. Adding random offF instead.\n f = f.add(ctneg(isEven, comp[offF])); // bits are 0: add garbage to fake point\n }\n else {\n p = p.add(ctneg(isNeg, comp[offP])); // bits are 1: add to result point\n }\n }\n if (n !== 0n)\n err('invalid wnaf');\n return { p, f }; // return both real and fake points for JIT\n};\n// !! Remove the export to easily use in REPL / browser console\nexport { etc, getPublicKey, getPublicKeyAsync, hash, hashes, keygen, keygenAsync, Point, sign, signAsync, utils, verify, verifyAsync, };\n","import { getPublicKeyAsync, signAsync, utils } from \"@noble/ed25519\";\n\ntype StoredIdentity = {\n version: 1;\n deviceId: string;\n publicKey: string;\n privateKey: string;\n createdAtMs: number;\n};\n\nexport type DeviceIdentity = {\n deviceId: string;\n publicKey: string;\n privateKey: string;\n};\n\nconst STORAGE_KEY = \"taskmaster-device-identity-v1\";\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction base64UrlDecode(input: string): Uint8Array {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const binary = atob(padded);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);\n return out;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nasync function fingerprintPublicKey(publicKey: Uint8Array): Promise<string> {\n const hash = await crypto.subtle.digest(\"SHA-256\", publicKey);\n return bytesToHex(new Uint8Array(hash));\n}\n\nasync function generateIdentity(): Promise<DeviceIdentity> {\n const privateKey = utils.randomSecretKey();\n const publicKey = await getPublicKeyAsync(privateKey);\n const deviceId = await fingerprintPublicKey(publicKey);\n return {\n deviceId,\n publicKey: base64UrlEncode(publicKey),\n privateKey: base64UrlEncode(privateKey),\n };\n}\n\nexport async function loadOrCreateDeviceIdentity(): Promise<DeviceIdentity> {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (raw) {\n const parsed = JSON.parse(raw) as StoredIdentity;\n if (\n parsed?.version === 1 &&\n typeof parsed.deviceId === \"string\" &&\n typeof parsed.publicKey === \"string\" &&\n typeof parsed.privateKey === \"string\"\n ) {\n const derivedId = await fingerprintPublicKey(base64UrlDecode(parsed.publicKey));\n if (derivedId !== parsed.deviceId) {\n const updated: StoredIdentity = {\n ...parsed,\n deviceId: derivedId,\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));\n return {\n deviceId: derivedId,\n publicKey: parsed.publicKey,\n privateKey: parsed.privateKey,\n };\n }\n return {\n deviceId: parsed.deviceId,\n publicKey: parsed.publicKey,\n privateKey: parsed.privateKey,\n };\n }\n }\n } catch {\n // fall through to regenerate\n }\n\n const identity = await generateIdentity();\n const stored: StoredIdentity = {\n version: 1,\n deviceId: identity.deviceId,\n publicKey: identity.publicKey,\n privateKey: identity.privateKey,\n createdAtMs: Date.now(),\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(stored));\n return identity;\n}\n\nexport async function signDevicePayload(privateKeyBase64Url: string, payload: string) {\n const key = base64UrlDecode(privateKeyBase64Url);\n const data = new TextEncoder().encode(payload);\n const sig = await signAsync(data, key);\n return base64UrlEncode(sig);\n}\n","export type DeviceAuthEntry = {\n token: string;\n role: string;\n scopes: string[];\n updatedAtMs: number;\n};\n\ntype DeviceAuthStore = {\n version: 1;\n deviceId: string;\n tokens: Record<string, DeviceAuthEntry>;\n};\n\nconst STORAGE_KEY = \"taskmaster.device.auth.v1\";\n\nfunction normalizeRole(role: string): string {\n return role.trim();\n}\n\nfunction normalizeScopes(scopes: string[] | undefined): string[] {\n if (!Array.isArray(scopes)) return [];\n const out = new Set<string>();\n for (const scope of scopes) {\n const trimmed = scope.trim();\n if (trimmed) out.add(trimmed);\n }\n return [...out].sort();\n}\n\nfunction readStore(): DeviceAuthStore | null {\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as DeviceAuthStore;\n if (!parsed || parsed.version !== 1) return null;\n if (!parsed.deviceId || typeof parsed.deviceId !== \"string\") return null;\n if (!parsed.tokens || typeof parsed.tokens !== \"object\") return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction writeStore(store: DeviceAuthStore) {\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(store));\n } catch {\n // best-effort\n }\n}\n\nexport function loadDeviceAuthToken(params: {\n deviceId: string;\n role: string;\n}): DeviceAuthEntry | null {\n const store = readStore();\n if (!store || store.deviceId !== params.deviceId) return null;\n const role = normalizeRole(params.role);\n const entry = store.tokens[role];\n if (!entry || typeof entry.token !== \"string\") return null;\n return entry;\n}\n\nexport function storeDeviceAuthToken(params: {\n deviceId: string;\n role: string;\n token: string;\n scopes?: string[];\n}): DeviceAuthEntry {\n const role = normalizeRole(params.role);\n const next: DeviceAuthStore = {\n version: 1,\n deviceId: params.deviceId,\n tokens: {},\n };\n const existing = readStore();\n if (existing && existing.deviceId === params.deviceId) {\n next.tokens = { ...existing.tokens };\n }\n const entry: DeviceAuthEntry = {\n token: params.token,\n role,\n scopes: normalizeScopes(params.scopes),\n updatedAtMs: Date.now(),\n };\n next.tokens[role] = entry;\n writeStore(next);\n return entry;\n}\n\nexport function clearDeviceAuthToken(params: { deviceId: string; role: string }) {\n const store = readStore();\n if (!store || store.deviceId !== params.deviceId) return;\n const role = normalizeRole(params.role);\n if (!store.tokens[role]) return;\n const next = { ...store, tokens: { ...store.tokens } };\n delete next.tokens[role];\n writeStore(next);\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { loadOrCreateDeviceIdentity } from \"../device-identity\";\nimport { clearDeviceAuthToken, storeDeviceAuthToken } from \"../device-auth\";\n\nexport type DeviceTokenSummary = {\n role: string;\n scopes?: string[];\n createdAtMs?: number;\n rotatedAtMs?: number;\n revokedAtMs?: number;\n lastUsedAtMs?: number;\n};\n\nexport type PendingDevice = {\n requestId: string;\n deviceId: string;\n displayName?: string;\n role?: string;\n remoteIp?: string;\n isRepair?: boolean;\n ts?: number;\n};\n\nexport type PairedDevice = {\n deviceId: string;\n displayName?: string;\n roles?: string[];\n scopes?: string[];\n remoteIp?: string;\n tokens?: DeviceTokenSummary[];\n createdAtMs?: number;\n approvedAtMs?: number;\n};\n\nexport type DevicePairingList = {\n pending: PendingDevice[];\n paired: PairedDevice[];\n};\n\nexport type DevicesState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n devicesLoading: boolean;\n devicesError: string | null;\n devicesList: DevicePairingList | null;\n};\n\nexport async function loadDevices(state: DevicesState, opts?: { quiet?: boolean }) {\n if (!state.client || !state.connected) return;\n if (state.devicesLoading) return;\n state.devicesLoading = true;\n if (!opts?.quiet) state.devicesError = null;\n try {\n const res = (await state.client.request(\"device.pair.list\", {})) as DevicePairingList | null;\n state.devicesList = {\n pending: Array.isArray(res?.pending) ? res!.pending : [],\n paired: Array.isArray(res?.paired) ? res!.paired : [],\n };\n } catch (err) {\n if (!opts?.quiet) state.devicesError = String(err);\n } finally {\n state.devicesLoading = false;\n }\n}\n\nexport async function approveDevicePairing(state: DevicesState, requestId: string) {\n if (!state.client || !state.connected) return;\n try {\n await state.client.request(\"device.pair.approve\", { requestId });\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n\nexport async function rejectDevicePairing(state: DevicesState, requestId: string) {\n if (!state.client || !state.connected) return;\n const confirmed = window.confirm(\"Reject this device pairing request?\");\n if (!confirmed) return;\n try {\n await state.client.request(\"device.pair.reject\", { requestId });\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n\nexport async function rotateDeviceToken(\n state: DevicesState,\n params: { deviceId: string; role: string; scopes?: string[] },\n) {\n if (!state.client || !state.connected) return;\n try {\n const res = (await state.client.request(\"device.token.rotate\", params)) as\n | { token?: string; role?: string; deviceId?: string; scopes?: string[] }\n | undefined;\n if (res?.token) {\n const identity = await loadOrCreateDeviceIdentity();\n const role = res.role ?? params.role;\n if (res.deviceId === identity.deviceId || params.deviceId === identity.deviceId) {\n storeDeviceAuthToken({\n deviceId: identity.deviceId,\n role,\n token: res.token,\n scopes: res.scopes ?? params.scopes ?? [],\n });\n }\n window.prompt(\"New device token (copy and store securely):\", res.token);\n }\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n\nexport async function revokeDeviceToken(\n state: DevicesState,\n params: { deviceId: string; role: string },\n) {\n if (!state.client || !state.connected) return;\n const confirmed = window.confirm(\n `Revoke token for ${params.deviceId} (${params.role})?`,\n );\n if (!confirmed) return;\n try {\n await state.client.request(\"device.token.revoke\", params);\n const identity = await loadOrCreateDeviceIdentity();\n if (params.deviceId === identity.deviceId) {\n clearDeviceAuthToken({ deviceId: identity.deviceId, role: params.role });\n }\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\n\nexport type NodesState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n nodesLoading: boolean;\n nodes: Array<Record<string, unknown>>;\n lastError: string | null;\n};\n\nexport async function loadNodes(\n state: NodesState,\n opts?: { quiet?: boolean },\n) {\n if (!state.client || !state.connected) return;\n if (state.nodesLoading) return;\n state.nodesLoading = true;\n if (!opts?.quiet) state.lastError = null;\n try {\n const res = (await state.client.request(\"node.list\", {})) as {\n nodes?: Array<Record<string, unknown>>;\n };\n state.nodes = Array.isArray(res.nodes) ? res.nodes : [];\n } catch (err) {\n if (!opts?.quiet) state.lastError = String(err);\n } finally {\n state.nodesLoading = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { cloneConfigObject, removePathValue, setPathValue } from \"./config/form-utils\";\n\nexport type ExecApprovalsDefaults = {\n security?: string;\n ask?: string;\n askFallback?: string;\n autoAllowSkills?: boolean;\n};\n\nexport type ExecApprovalsAllowlistEntry = {\n id?: string;\n pattern: string;\n lastUsedAt?: number;\n lastUsedCommand?: string;\n lastResolvedPath?: string;\n};\n\nexport type ExecApprovalsAgent = ExecApprovalsDefaults & {\n allowlist?: ExecApprovalsAllowlistEntry[];\n};\n\nexport type ExecApprovalsFile = {\n version?: number;\n socket?: { path?: string };\n defaults?: ExecApprovalsDefaults;\n agents?: Record<string, ExecApprovalsAgent>;\n};\n\nexport type ExecApprovalsSnapshot = {\n path: string;\n exists: boolean;\n hash: string;\n file: ExecApprovalsFile;\n};\n\nexport type ExecApprovalsTarget =\n | { kind: \"gateway\" }\n | { kind: \"node\"; nodeId: string };\n\nexport type ExecApprovalsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n execApprovalsLoading: boolean;\n execApprovalsSaving: boolean;\n execApprovalsDirty: boolean;\n execApprovalsSnapshot: ExecApprovalsSnapshot | null;\n execApprovalsForm: ExecApprovalsFile | null;\n execApprovalsSelectedAgent: string | null;\n lastError: string | null;\n};\n\nfunction resolveExecApprovalsRpc(target?: ExecApprovalsTarget | null): {\n method: string;\n params: Record<string, unknown>;\n} | null {\n if (!target || target.kind === \"gateway\") {\n return { method: \"exec.approvals.get\", params: {} };\n }\n const nodeId = target.nodeId.trim();\n if (!nodeId) return null;\n return { method: \"exec.approvals.node.get\", params: { nodeId } };\n}\n\nfunction resolveExecApprovalsSaveRpc(\n target: ExecApprovalsTarget | null | undefined,\n params: { file: ExecApprovalsFile; baseHash: string },\n): { method: string; params: Record<string, unknown> } | null {\n if (!target || target.kind === \"gateway\") {\n return { method: \"exec.approvals.set\", params };\n }\n const nodeId = target.nodeId.trim();\n if (!nodeId) return null;\n return { method: \"exec.approvals.node.set\", params: { ...params, nodeId } };\n}\n\nexport async function loadExecApprovals(\n state: ExecApprovalsState,\n target?: ExecApprovalsTarget | null,\n) {\n if (!state.client || !state.connected) return;\n if (state.execApprovalsLoading) return;\n state.execApprovalsLoading = true;\n state.lastError = null;\n try {\n const rpc = resolveExecApprovalsRpc(target);\n if (!rpc) {\n state.lastError = \"Select a node before loading exec approvals.\";\n return;\n }\n const res = (await state.client.request(rpc.method, rpc.params)) as ExecApprovalsSnapshot;\n applyExecApprovalsSnapshot(state, res);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.execApprovalsLoading = false;\n }\n}\n\nexport function applyExecApprovalsSnapshot(\n state: ExecApprovalsState,\n snapshot: ExecApprovalsSnapshot,\n) {\n state.execApprovalsSnapshot = snapshot;\n if (!state.execApprovalsDirty) {\n state.execApprovalsForm = cloneConfigObject(snapshot.file ?? {});\n }\n}\n\nexport async function saveExecApprovals(\n state: ExecApprovalsState,\n target?: ExecApprovalsTarget | null,\n) {\n if (!state.client || !state.connected) return;\n state.execApprovalsSaving = true;\n state.lastError = null;\n try {\n const baseHash = state.execApprovalsSnapshot?.hash;\n if (!baseHash) {\n state.lastError = \"Exec approvals hash missing; reload and retry.\";\n return;\n }\n const file =\n state.execApprovalsForm ??\n state.execApprovalsSnapshot?.file ??\n {};\n const rpc = resolveExecApprovalsSaveRpc(target, { file, baseHash });\n if (!rpc) {\n state.lastError = \"Select a node before saving exec approvals.\";\n return;\n }\n await state.client.request(rpc.method, rpc.params);\n state.execApprovalsDirty = false;\n await loadExecApprovals(state, target);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.execApprovalsSaving = false;\n }\n}\n\nexport function updateExecApprovalsFormValue(\n state: ExecApprovalsState,\n path: Array<string | number>,\n value: unknown,\n) {\n const base = cloneConfigObject(\n state.execApprovalsForm ?? state.execApprovalsSnapshot?.file ?? {},\n );\n setPathValue(base, path, value);\n state.execApprovalsForm = base;\n state.execApprovalsDirty = true;\n}\n\nexport function removeExecApprovalsFormValue(\n state: ExecApprovalsState,\n path: Array<string | number>,\n) {\n const base = cloneConfigObject(\n state.execApprovalsForm ?? state.execApprovalsSnapshot?.file ?? {},\n );\n removePathValue(base, path);\n state.execApprovalsForm = base;\n state.execApprovalsDirty = true;\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { PresenceEntry } from \"../types\";\n\nexport type PresenceState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n presenceLoading: boolean;\n presenceEntries: PresenceEntry[];\n presenceError: string | null;\n presenceStatus: string | null;\n};\n\nexport async function loadPresence(state: PresenceState) {\n if (!state.client || !state.connected) return;\n if (state.presenceLoading) return;\n state.presenceLoading = true;\n state.presenceError = null;\n state.presenceStatus = null;\n try {\n const res = (await state.client.request(\"system-presence\", {})) as\n | PresenceEntry[]\n | undefined;\n if (Array.isArray(res)) {\n state.presenceEntries = res;\n state.presenceStatus = res.length === 0 ? \"No instances yet.\" : null;\n } else {\n state.presenceEntries = [];\n state.presenceStatus = \"No presence payload.\";\n }\n } catch (err) {\n state.presenceError = String(err);\n } finally {\n state.presenceLoading = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { SkillStatusReport } from \"../types\";\n\nexport type SkillDetailData = {\n name: string;\n content: string;\n references: { name: string; content: string }[];\n alwaysActive?: boolean;\n};\n\nexport type SkillDraft = {\n name: string;\n skillContent: string;\n references: { name: string; content: string }[];\n};\n\nexport type AddSkillForm = {\n name: string;\n skillContent: string;\n references: { name: string; content: string }[];\n alwaysActive: boolean;\n};\n\nexport type SkillFormSource = \"draft\" | \"installed\";\n\nexport type SkillsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n skillsLoading: boolean;\n skillsReport: SkillStatusReport | null;\n skillsError: string | null;\n skillsBusyKey: string | null;\n skillEdits: Record<string, string>;\n skillMessages: SkillMessageMap;\n skillDetail: SkillDetailData | null;\n skillDetailTab: string;\n skillAddModal: boolean;\n skillAddForm: AddSkillForm;\n skillAddFormSource: SkillFormSource;\n skillEditTab: string;\n skillDrafts: SkillDraft[];\n};\n\nexport type SkillMessage = {\n kind: \"success\" | \"error\";\n message: string;\n};\n\nexport type SkillMessageMap = Record<string, SkillMessage>;\n\ntype LoadSkillsOptions = {\n clearMessages?: boolean;\n};\n\nfunction setSkillMessage(state: SkillsState, key: string, message?: SkillMessage) {\n if (!key.trim()) return;\n const next = { ...state.skillMessages };\n if (message) next[key] = message;\n else delete next[key];\n state.skillMessages = next;\n}\n\nfunction getErrorMessage(err: unknown) {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nexport function emptyAddForm(): AddSkillForm {\n return { name: \"\", skillContent: \"\", references: [], alwaysActive: false };\n}\n\nexport async function loadSkills(state: SkillsState, options?: LoadSkillsOptions) {\n if (options?.clearMessages && Object.keys(state.skillMessages).length > 0) {\n state.skillMessages = {};\n }\n if (!state.client || !state.connected) return;\n if (state.skillsLoading) return;\n state.skillsLoading = true;\n state.skillsError = null;\n try {\n const res = (await state.client.request(\"skills.status\", {})) as\n | SkillStatusReport\n | undefined;\n if (res) state.skillsReport = res;\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n } finally {\n state.skillsLoading = false;\n }\n}\n\nexport function updateSkillEdit(\n state: SkillsState,\n skillKey: string,\n value: string,\n) {\n state.skillEdits = { ...state.skillEdits, [skillKey]: value };\n}\n\nexport async function updateSkillEnabled(\n state: SkillsState,\n skillKey: string,\n enabled: boolean,\n) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = skillKey;\n state.skillsError = null;\n try {\n await state.client.request(\"skills.update\", { skillKey, enabled });\n await loadSkills(state);\n setSkillMessage(state, skillKey, {\n kind: \"success\",\n message: enabled ? \"Skill enabled\" : \"Skill disabled\",\n });\n } catch (err) {\n const message = getErrorMessage(err);\n state.skillsError = message;\n setSkillMessage(state, skillKey, {\n kind: \"error\",\n message,\n });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\nexport async function saveSkillApiKey(state: SkillsState, skillKey: string) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = skillKey;\n state.skillsError = null;\n try {\n const apiKey = state.skillEdits[skillKey] ?? \"\";\n await state.client.request(\"skills.update\", { skillKey, apiKey });\n await loadSkills(state);\n setSkillMessage(state, skillKey, {\n kind: \"success\",\n message: \"API key saved\",\n });\n } catch (err) {\n const message = getErrorMessage(err);\n state.skillsError = message;\n setSkillMessage(state, skillKey, {\n kind: \"error\",\n message,\n });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\nexport async function installSkill(\n state: SkillsState,\n skillKey: string,\n name: string,\n installId: string,\n) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = skillKey;\n state.skillsError = null;\n try {\n const result = (await state.client.request(\"skills.install\", {\n name,\n installId,\n timeoutMs: 120000,\n })) as { ok?: boolean; message?: string };\n await loadSkills(state);\n setSkillMessage(state, skillKey, {\n kind: \"success\",\n message: result?.message ?? \"Installed\",\n });\n } catch (err) {\n const message = getErrorMessage(err);\n state.skillsError = message;\n setSkillMessage(state, skillKey, {\n kind: \"error\",\n message,\n });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\n/* ── Detail modal ── */\n\nexport async function viewSkillDetail(state: SkillsState, name: string) {\n if (!state.client || !state.connected) return;\n try {\n const result = (await state.client.request(\"skills.read\", { name })) as SkillDetailData | undefined;\n if (result) {\n state.skillDetail = result;\n state.skillDetailTab = \"SKILL.md\";\n }\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n }\n}\n\nexport function closeSkillDetail(state: SkillsState) {\n state.skillDetail = null;\n state.skillDetailTab = \"\";\n}\n\nexport function setSkillDetailTab(state: SkillsState, tab: string) {\n state.skillDetailTab = tab;\n}\n\n/* ── Add skill modal ── */\n\nexport async function openAddSkillModal(state: SkillsState) {\n state.skillAddModal = true;\n state.skillAddForm = emptyAddForm();\n state.skillAddFormSource = \"draft\";\n state.skillEditTab = \"SKILL.md\";\n state.skillDrafts = [];\n if (!state.client || !state.connected) return;\n try {\n const result = (await state.client.request(\"skills.drafts\", {})) as\n | { drafts: SkillDraft[] }\n | undefined;\n if (result) state.skillDrafts = result.drafts;\n } catch {\n // drafts are optional — no error shown\n }\n}\n\nexport function closeAddSkillModal(state: SkillsState) {\n state.skillAddModal = false;\n state.skillAddForm = emptyAddForm();\n state.skillAddFormSource = \"draft\";\n state.skillEditTab = \"SKILL.md\";\n state.skillDrafts = [];\n}\n\nexport function importDraft(state: SkillsState, draft: SkillDraft) {\n state.skillAddForm = {\n name: draft.name,\n skillContent: draft.skillContent,\n references: draft.references.map((r) => ({ ...r })),\n alwaysActive: false,\n };\n state.skillAddFormSource = \"draft\";\n}\n\nexport async function installDraft(state: SkillsState, draft: SkillDraft) {\n state.skillAddForm = {\n name: draft.name,\n skillContent: draft.skillContent,\n references: draft.references.map((r) => ({ ...r })),\n alwaysActive: false,\n };\n state.skillAddFormSource = \"installed\";\n await saveNewSkill(state);\n}\n\nexport async function saveNewSkill(state: SkillsState) {\n if (!state.client || !state.connected) return;\n const form = state.skillAddForm;\n if (!form.name.trim() || !form.skillContent.trim()) return;\n state.skillsBusyKey = \"__add__\";\n state.skillsError = null;\n try {\n const refs = form.references\n .filter((r) => r.name.trim() && r.content.trim())\n .map((r) => ({ name: r.name.trim(), content: r.content }));\n const skillName = form.name.trim();\n\n if (state.skillAddFormSource === \"installed\") {\n // Editing an installed skill — overwrite in skills/\n await state.client.request(\"skills.create\", {\n name: skillName,\n skillContent: form.skillContent,\n references: refs.length > 0 ? refs : undefined,\n alwaysActive: form.alwaysActive,\n });\n state.skillAddModal = false;\n state.skillAddForm = emptyAddForm();\n state.skillAddFormSource = \"draft\";\n state.skillDrafts = [];\n await loadSkills(state);\n setSkillMessage(state, skillName, {\n kind: \"success\",\n message: \"Skill saved — active on next message\",\n });\n } else {\n // Editing a draft — save back to .skill-drafts/\n await state.client.request(\"skills.saveDraft\", {\n name: skillName,\n skillContent: form.skillContent,\n references: refs.length > 0 ? refs : undefined,\n });\n state.skillAddModal = false;\n state.skillAddForm = emptyAddForm();\n state.skillAddFormSource = \"draft\";\n state.skillDrafts = [];\n setSkillMessage(state, skillName, {\n kind: \"success\",\n message: \"Draft saved\",\n });\n }\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\n/* ── Delete draft ── */\n\nexport async function deleteDraft(state: SkillsState, name: string) {\n if (!state.client || !state.connected) return;\n try {\n await state.client.request(\"skills.deleteDraft\", { name });\n state.skillDrafts = state.skillDrafts.filter((d) => d.name !== name);\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n }\n}\n\n/* ── Edit skill ── */\n\nexport async function editSkill(state: SkillsState, name: string) {\n if (!state.client || !state.connected) return;\n try {\n const result = (await state.client.request(\"skills.read\", { name })) as SkillDetailData | undefined;\n if (!result) return;\n state.skillAddForm = {\n name: result.name,\n skillContent: result.content,\n references: result.references.map((r) => ({ ...r })),\n alwaysActive: result.alwaysActive ?? false,\n };\n state.skillAddFormSource = \"installed\";\n state.skillAddModal = true;\n state.skillDrafts = [];\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n }\n}\n\n/* ── Edit from detail modal ── */\n\nexport function editDetailSkill(state: SkillsState, activeTab?: string) {\n const detail = state.skillDetail;\n if (!detail) return;\n state.skillAddForm = {\n name: detail.name,\n skillContent: detail.content,\n references: detail.references.map((r) => ({ ...r })),\n alwaysActive: detail.alwaysActive ?? false,\n };\n state.skillAddFormSource = \"installed\";\n state.skillEditTab = activeTab && activeTab !== \"SKILL.md\" ? activeTab : \"SKILL.md\";\n state.skillDetail = null;\n state.skillDetailTab = \"\";\n state.skillAddModal = true;\n state.skillDrafts = [];\n}\n\n/* ── Update reference content in form ── */\n\nexport function updateFormReference(state: SkillsState, refName: string, content: string) {\n state.skillAddForm = {\n ...state.skillAddForm,\n references: state.skillAddForm.references.map((r) =>\n r.name === refName ? { ...r, content } : r,\n ),\n };\n}\n\n/* ── Switch edit tab ── */\n\nexport function setEditTab(state: SkillsState, tab: string) {\n state.skillEditTab = tab;\n}\n\n/* ── Toggle always active ── */\n\nexport async function toggleAlwaysActive(state: SkillsState, name: string, alwaysActive: boolean) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = name;\n state.skillsError = null;\n try {\n const result = (await state.client.request(\"skills.read\", { name })) as SkillDetailData | undefined;\n if (!result) return;\n const refs = result.references\n .filter((r) => r.name.trim() && r.content.trim())\n .map((r) => ({ name: r.name.trim(), content: r.content }));\n await state.client.request(\"skills.create\", {\n name,\n skillContent: result.content,\n references: refs.length > 0 ? refs : undefined,\n alwaysActive,\n });\n await loadSkills(state);\n setSkillMessage(state, name, {\n kind: \"success\",\n message: alwaysActive ? \"Skill is now always active\" : \"Skill loads on demand\",\n });\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n setSkillMessage(state, name, { kind: \"error\", message: getErrorMessage(err) });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\n/* ── Update skill agents ── */\n\nexport async function updateSkillAgents(\n state: SkillsState,\n skillKey: string,\n agents: string[],\n) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = skillKey;\n state.skillsError = null;\n try {\n await state.client.request(\"skills.update\", { skillKey, agents });\n await loadSkills(state);\n setSkillMessage(state, skillKey, {\n kind: \"success\",\n message: \"Agent access updated\",\n });\n } catch (err) {\n const message = getErrorMessage(err);\n state.skillsError = message;\n setSkillMessage(state, skillKey, { kind: \"error\", message });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\n/* ── Delete skill ── */\n\nexport async function deleteSkill(state: SkillsState, name: string) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = name;\n state.skillsError = null;\n try {\n await state.client.request(\"skills.delete\", { name });\n await loadSkills(state);\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n } finally {\n state.skillsBusyKey = null;\n }\n}\n","import type { IconName } from \"./icons.js\";\n\nexport const TAB_GROUPS = [\n { label: \"Chat\", tabs: [\"chat\"] },\n {\n label: \"Control\",\n tabs: [\"overview\", \"channels\", \"instances\", \"cron\"],\n },\n { label: \"Agent\", tabs: [\"skills\", \"nodes\"] },\n { label: \"Settings\", tabs: [\"admins\", \"config\", \"debug\", \"logs\"] },\n] as const;\n\nexport type Tab =\n | \"overview\"\n | \"channels\"\n | \"instances\"\n | \"cron\"\n | \"skills\"\n | \"nodes\"\n | \"chat\"\n | \"admins\"\n | \"config\"\n | \"debug\"\n | \"logs\";\n\nconst TAB_PATHS: Record<Tab, string> = {\n overview: \"/overview\",\n channels: \"/channels\",\n instances: \"/instances\",\n cron: \"/cron\",\n skills: \"/skills\",\n nodes: \"/nodes\",\n chat: \"/chat\",\n admins: \"/admins\",\n config: \"/config\",\n debug: \"/debug\",\n logs: \"/logs\",\n};\n\nconst PATH_TO_TAB = new Map(\n Object.entries(TAB_PATHS).map(([tab, path]) => [path, tab as Tab]),\n);\n\nexport function normalizeBasePath(basePath: string): string {\n if (!basePath) return \"\";\n let base = basePath.trim();\n if (!base.startsWith(\"/\")) base = `/${base}`;\n if (base === \"/\") return \"\";\n if (base.endsWith(\"/\")) base = base.slice(0, -1);\n return base;\n}\n\nexport function normalizePath(path: string): string {\n if (!path) return \"/\";\n let normalized = path.trim();\n if (!normalized.startsWith(\"/\")) normalized = `/${normalized}`;\n if (normalized.length > 1 && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function pathForTab(tab: Tab, basePath = \"\"): string {\n const base = normalizeBasePath(basePath);\n const path = TAB_PATHS[tab];\n return base ? `${base}${path}` : path;\n}\n\nexport function tabFromPath(pathname: string, basePath = \"\"): Tab | null {\n const base = normalizeBasePath(basePath);\n let path = pathname || \"/\";\n if (base) {\n if (path === base) {\n path = \"/\";\n } else if (path.startsWith(`${base}/`)) {\n path = path.slice(base.length);\n }\n }\n let normalized = normalizePath(path).toLowerCase();\n if (normalized.endsWith(\"/index.html\")) normalized = \"/\";\n if (normalized === \"/\") return \"chat\";\n return PATH_TO_TAB.get(normalized) ?? null;\n}\n\nexport function inferBasePathFromPathname(pathname: string): string {\n let normalized = normalizePath(pathname);\n if (normalized.endsWith(\"/index.html\")) {\n normalized = normalizePath(normalized.slice(0, -\"/index.html\".length));\n }\n if (normalized === \"/\") return \"\";\n const segments = normalized.split(\"/\").filter(Boolean);\n if (segments.length === 0) return \"\";\n for (let i = 0; i < segments.length; i++) {\n const candidate = `/${segments.slice(i).join(\"/\")}`.toLowerCase();\n if (PATH_TO_TAB.has(candidate)) {\n const prefix = segments.slice(0, i);\n return prefix.length ? `/${prefix.join(\"/\")}` : \"\";\n }\n }\n return `/${segments.join(\"/\")}`;\n}\n\nexport function iconForTab(tab: Tab): IconName {\n switch (tab) {\n case \"chat\":\n return \"messageSquare\";\n case \"overview\":\n return \"barChart\";\n case \"channels\":\n return \"link\";\n case \"instances\":\n return \"radio\";\n case \"cron\":\n return \"loader\";\n case \"skills\":\n return \"zap\";\n case \"nodes\":\n return \"monitor\";\n case \"admins\":\n return \"users\";\n case \"config\":\n return \"settings\";\n case \"debug\":\n return \"bug\";\n case \"logs\":\n return \"scrollText\";\n default:\n return \"folder\";\n }\n}\n\nexport function titleForTab(tab: Tab) {\n switch (tab) {\n case \"overview\":\n return \"Overview\";\n case \"channels\":\n return \"Channels\";\n case \"instances\":\n return \"Instances\";\n case \"cron\":\n return \"Events\";\n case \"skills\":\n return \"Skills\";\n case \"nodes\":\n return \"Nodes\";\n case \"chat\":\n return \"Chat\";\n case \"admins\":\n return \"Admins\";\n case \"config\":\n return \"Config\";\n case \"debug\":\n return \"Debug\";\n case \"logs\":\n return \"Logs\";\n default:\n return \"Control\";\n }\n}\n\nexport function subtitleForTab(tab: Tab) {\n switch (tab) {\n case \"overview\":\n return \"Gateway status, entry points, and a fast health read.\";\n case \"channels\":\n return \"Manage channels and settings.\";\n case \"instances\":\n return \"Presence beacons from connected clients and nodes.\";\n case \"cron\":\n return \"Reminders, recurring tasks, and automated routines.\";\n case \"skills\":\n return \"Manage skill availability and API key injection.\";\n case \"nodes\":\n return \"Paired devices, capabilities, and command exposure.\";\n case \"chat\":\n return \"Direct gateway chat session for quick interventions.\";\n case \"admins\":\n return \"Manage admin phone numbers for WhatsApp routing.\";\n case \"config\":\n return \"Edit ~/.taskmaster/taskmaster.json safely.\";\n case \"debug\":\n return \"Gateway snapshots, events, and manual RPC calls.\";\n case \"logs\":\n return \"Session transcripts and system logs.\";\n default:\n return \"\";\n }\n}\n","export type ThemeMode = \"system\" | \"light\" | \"dark\";\nexport type ResolvedTheme = \"light\" | \"dark\";\n\nexport function getSystemTheme(): ResolvedTheme {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return \"dark\";\n }\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n}\n\nexport function resolveTheme(mode: ThemeMode): ResolvedTheme {\n if (mode === \"system\") return getSystemTheme();\n return mode;\n}\n","import type { ThemeMode } from \"./theme\";\n\nexport type ThemeTransitionContext = {\n element?: HTMLElement | null;\n pointerClientX?: number;\n pointerClientY?: number;\n};\n\nexport type ThemeTransitionOptions = {\n nextTheme: ThemeMode;\n applyTheme: () => void;\n context?: ThemeTransitionContext;\n currentTheme?: ThemeMode | null;\n};\n\ntype DocumentWithViewTransition = Document & {\n startViewTransition?: (callback: () => void) => { finished: Promise<void> };\n};\n\nconst clamp01 = (value: number) => {\n if (Number.isNaN(value)) return 0.5;\n if (value <= 0) return 0;\n if (value >= 1) return 1;\n return value;\n};\n\nconst hasReducedMotionPreference = () => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return false;\n }\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches ?? false;\n};\n\nconst cleanupThemeTransition = (root: HTMLElement) => {\n root.classList.remove(\"theme-transition\");\n root.style.removeProperty(\"--theme-switch-x\");\n root.style.removeProperty(\"--theme-switch-y\");\n};\n\nexport const startThemeTransition = ({\n nextTheme,\n applyTheme,\n context,\n currentTheme,\n}: ThemeTransitionOptions) => {\n if (currentTheme === nextTheme) return;\n\n const documentReference = globalThis.document ?? null;\n if (!documentReference) {\n applyTheme();\n return;\n }\n\n const root = documentReference.documentElement;\n const document_ = documentReference as DocumentWithViewTransition;\n const prefersReducedMotion = hasReducedMotionPreference();\n\n const canUseViewTransition =\n Boolean(document_.startViewTransition) && !prefersReducedMotion;\n\n if (canUseViewTransition) {\n let xPercent = 0.5;\n let yPercent = 0.5;\n\n if (\n context?.pointerClientX !== undefined &&\n context?.pointerClientY !== undefined &&\n typeof window !== \"undefined\"\n ) {\n xPercent = clamp01(context.pointerClientX / window.innerWidth);\n yPercent = clamp01(context.pointerClientY / window.innerHeight);\n } else if (context?.element) {\n const rect = context.element.getBoundingClientRect();\n if (\n rect.width > 0 &&\n rect.height > 0 &&\n typeof window !== \"undefined\"\n ) {\n xPercent = clamp01((rect.left + rect.width / 2) / window.innerWidth);\n yPercent = clamp01((rect.top + rect.height / 2) / window.innerHeight);\n }\n }\n\n root.style.setProperty(\"--theme-switch-x\", `${xPercent * 100}%`);\n root.style.setProperty(\"--theme-switch-y\", `${yPercent * 100}%`);\n root.classList.add(\"theme-transition\");\n\n try {\n const transition = document_.startViewTransition?.(() => {\n applyTheme();\n });\n if (transition?.finished) {\n void transition.finished.finally(() => cleanupThemeTransition(root));\n } else {\n cleanupThemeTransition(root);\n }\n } catch {\n cleanupThemeTransition(root);\n applyTheme();\n }\n return;\n }\n\n applyTheme();\n cleanupThemeTransition(root);\n};\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { SessionTranscriptEntry } from \"../types\";\n\nexport type SessionLogsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n sessionLogsLoading: boolean;\n sessionLogsError: string | null;\n sessionLogsEntries: SessionTranscriptEntry[];\n sessionLogsCursors: Record<string, number>;\n sessionLogsAgents: string[];\n sessionLogsLastFetchAt: number | null;\n workspaceAgentIds?: string[];\n};\n\nconst SESSION_LOG_BUFFER_LIMIT = 2000;\n\nexport async function loadSessionLogs(\n state: SessionLogsState,\n opts?: { reset?: boolean; quiet?: boolean },\n) {\n if (!state.client || !state.connected) return;\n if (state.sessionLogsLoading && !opts?.quiet) return;\n if (!opts?.quiet) state.sessionLogsLoading = true;\n state.sessionLogsError = null;\n try {\n const rpcParams: Record<string, unknown> = {\n cursors: opts?.reset ? undefined : state.sessionLogsCursors,\n limit: 500,\n };\n if (Array.isArray(state.workspaceAgentIds) && state.workspaceAgentIds.length > 0) {\n rpcParams.agents = state.workspaceAgentIds;\n }\n const res = await state.client.request(\"sessions.transcript\", rpcParams);\n const payload = res as {\n entries?: unknown;\n cursors?: Record<string, number>;\n agents?: string[];\n };\n const entries = Array.isArray(payload.entries)\n ? (payload.entries as SessionTranscriptEntry[])\n : [];\n const shouldReset = Boolean(\n opts?.reset || Object.keys(state.sessionLogsCursors).length === 0,\n );\n state.sessionLogsEntries = shouldReset\n ? entries\n : [...state.sessionLogsEntries, ...entries].slice(-SESSION_LOG_BUFFER_LIMIT);\n if (payload.cursors) state.sessionLogsCursors = payload.cursors;\n if (Array.isArray(payload.agents)) state.sessionLogsAgents = payload.agents;\n state.sessionLogsLastFetchAt = Date.now();\n } catch (err) {\n state.sessionLogsError = String(err);\n } finally {\n if (!opts?.quiet) state.sessionLogsLoading = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\n\nexport type AuditEntry = {\n path: string;\n timestamp: number;\n agentId: string;\n};\n\nexport type AuditState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n auditEntries: AuditEntry[];\n auditLoading: boolean;\n};\n\nexport async function loadAuditEntries(state: AuditState, agentId?: string) {\n if (!state.client || !state.connected) return;\n try {\n const params: Record<string, unknown> = {};\n if (agentId) params.agentId = agentId;\n const res = (await state.client.request(\"memory.audit\", params)) as {\n ok?: boolean;\n entries?: AuditEntry[];\n } | undefined;\n if (res?.ok) {\n state.auditEntries = res.entries ?? [];\n }\n } catch {\n // Non-fatal — badge stays hidden\n }\n}\n\nexport async function clearAudit(state: AuditState, agentId?: string) {\n if (!state.client || !state.connected) return;\n try {\n const params: Record<string, unknown> = {};\n if (agentId) params.agentId = agentId;\n await state.client.request(\"memory.auditClear\", params);\n state.auditEntries = [];\n } catch {\n // Non-fatal\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\n\nexport type FileTreeEntry = {\n name: string;\n path: string;\n type: \"file\" | \"directory\" | \"symlink\";\n size?: number;\n children?: FileTreeEntry[];\n};\n\nexport type FilesState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n filesLoading: boolean;\n filesTree: FileTreeEntry[];\n filesRoot: string;\n filesError: string | null;\n filesSelectedPath: string | null;\n filesSelectedPaths: Set<string>;\n filesPreviewContent: string | null;\n filesPreviewLoading: boolean;\n filesPreviewBinary: boolean;\n filesPreviewSize: number | null;\n filesExpandedDirs: Set<string>;\n filesCurrentDir: string;\n filesPendingDeletePath: string | null;\n filesMessage: { kind: \"success\" | \"error\"; text: string } | null;\n filesUploadBusy: boolean;\n filesReindexBusy: boolean;\n filesMemoryStatus: { dirty: boolean; syncing?: boolean; syncProgress?: { completed: number; total: number; label?: string }; files: number; chunks: number; model?: string; embeddingState?: \"idle\" | \"downloading\" | \"ready\" | \"error\" } | null;\n filesSearchQuery: string;\n filesSearchResults: MemorySearchHit[] | null;\n filesSearchLoading: boolean;\n filesSearchAgentId: string | null;\n};\n\nexport type MemorySearchHit = {\n path: string;\n startLine: number;\n endLine: number;\n score: number;\n snippet: string;\n source: string;\n};\n\nfunction getErrorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nlet messageTimer: ReturnType<typeof setTimeout> | null = null;\n\nfunction setSuccessMessage(state: FilesState, text: string) {\n if (messageTimer) clearTimeout(messageTimer);\n state.filesMessage = { kind: \"success\", text };\n messageTimer = setTimeout(() => {\n state.filesMessage = null;\n messageTimer = null;\n }, 3000);\n}\n\nexport async function loadFileTree(state: FilesState, agentId?: string) {\n if (!state.client || !state.connected) return;\n if (!agentId) {\n // No workspace context yet — clear data and wait for workspace selection\n state.filesTree = [];\n state.filesRoot = \"\";\n return;\n }\n if (state.filesLoading) return;\n state.filesLoading = true;\n state.filesError = null;\n try {\n const params: Record<string, unknown> = {};\n if (agentId) params.agentId = agentId;\n const res = (await state.client.request(\"files.tree\", params)) as {\n root?: string;\n tree?: FileTreeEntry[];\n } | undefined;\n if (res?.tree) {\n state.filesTree = res.tree;\n state.filesRoot = res.root ?? \"\";\n }\n } catch (err) {\n state.filesError = getErrorMessage(err);\n } finally {\n state.filesLoading = false;\n }\n}\n\n/** Single-click: select one file, clear others, load preview. */\nexport async function selectFile(state: FilesState, filePath: string, agentId?: string) {\n state.filesSelectedPaths = new Set([filePath]);\n await previewFile(state, filePath, agentId);\n}\n\n/** Ctrl/Cmd+click: toggle a file in the multi-selection set. */\nexport async function toggleSelectFile(state: FilesState, filePath: string, agentId?: string) {\n const next = new Set(state.filesSelectedPaths);\n if (next.has(filePath)) {\n next.delete(filePath);\n } else {\n next.add(filePath);\n }\n state.filesSelectedPaths = next;\n // Show preview only when exactly one file is selected\n if (next.size === 1) {\n const remaining = [...next][0];\n await previewFile(state, remaining, agentId);\n } else {\n state.filesSelectedPath = null;\n state.filesPreviewContent = null;\n state.filesPreviewSize = null;\n state.filesPreviewBinary = false;\n }\n}\n\n/** Download all files in the current multi-selection. */\nexport async function bulkDownloadFiles(state: FilesState, agentId?: string) {\n if (!state.client || !state.connected) return;\n const paths = [...state.filesSelectedPaths];\n if (paths.length === 0) return;\n let successCount = 0;\n let errorMsg = \"\";\n for (const filePath of paths) {\n try {\n await downloadFile(state, filePath, agentId);\n successCount++;\n } catch (err) {\n errorMsg = getErrorMessage(err);\n }\n }\n if (errorMsg) {\n state.filesMessage = { kind: \"error\", text: `${successCount} downloaded, error: ${errorMsg}` };\n } else {\n setSuccessMessage(state, `${successCount} file${successCount !== 1 ? \"s\" : \"\"} downloaded`);\n }\n}\n\n/** Move a file into a directory (drag-and-drop). Constructs the destination path. */\nexport async function moveFileToDir(state: FilesState, filePath: string, targetDir: string, agentId?: string) {\n const fileName = filePath.split(\"/\").pop() ?? filePath;\n const dest = targetDir === \".\" ? fileName : `${targetDir}/${fileName}`;\n if (dest === filePath) return; // no-op: same location\n await moveFile(state, filePath, dest, agentId);\n}\n\nexport async function previewFile(state: FilesState, filePath: string, agentId?: string) {\n if (!state.client || !state.connected) return;\n state.filesSelectedPath = filePath;\n state.filesPreviewLoading = true;\n state.filesPreviewContent = null;\n state.filesPreviewBinary = false;\n state.filesPreviewSize = null;\n try {\n const params: Record<string, unknown> = { path: filePath };\n if (agentId) params.agentId = agentId;\n const res = (await state.client.request(\"files.read\", params)) as {\n content?: string | null;\n binary?: boolean;\n size?: number;\n } | undefined;\n state.filesPreviewContent = res?.content ?? null;\n state.filesPreviewBinary = res?.binary ?? false;\n state.filesPreviewSize = res?.size ?? null;\n } catch (err) {\n state.filesError = getErrorMessage(err);\n } finally {\n state.filesPreviewLoading = false;\n }\n}\n\nexport async function downloadFile(state: FilesState, filePath: string, agentId?: string) {\n if (!state.client || !state.connected) return;\n try {\n const params: Record<string, unknown> = { path: filePath };\n if (agentId) params.agentId = agentId;\n const res = (await state.client.request(\"files.download\", params)) as {\n base64?: string;\n name?: string;\n } | undefined;\n if (!res?.base64) {\n state.filesMessage = { kind: \"error\", text: \"Download failed: no data\" };\n return;\n }\n // Convert base64 to blob and trigger download\n const bytes = Uint8Array.from(atob(res.base64), (c) => c.charCodeAt(0));\n const blob = new Blob([bytes]);\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = res.name ?? filePath.split(\"/\").pop() ?? \"download\";\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n } catch (err) {\n state.filesMessage = { kind: \"error\", text: getErrorMessage(err) };\n }\n}\n\nexport async function uploadFiles(\n state: FilesState,\n dirPath: string,\n files: File[],\n agentId?: string,\n) {\n if (!state.client || !state.connected) return;\n state.filesUploadBusy = true;\n state.filesMessage = null;\n let successCount = 0;\n let errorMsg = \"\";\n for (const file of files) {\n try {\n const buffer = await file.arrayBuffer();\n const base64 = btoa(\n new Uint8Array(buffer).reduce((data, byte) => data + String.fromCharCode(byte), \"\"),\n );\n const params: Record<string, unknown> = {\n path: dirPath,\n name: file.name,\n data: base64,\n };\n if (agentId) params.agentId = agentId;\n await state.client.request(\"files.upload\", params);\n successCount++;\n } catch (err) {\n errorMsg = getErrorMessage(err);\n }\n }\n state.filesUploadBusy = false;\n if (errorMsg) {\n state.filesMessage = {\n kind: \"error\",\n text: successCount > 0 ? `${successCount} uploaded, error: ${errorMsg}` : errorMsg,\n };\n } else {\n setSuccessMessage(state, `${successCount} file${successCount !== 1 ? \"s\" : \"\"} uploaded`);\n }\n await loadFileTree(state, agentId);\n}\n\nexport async function createFolder(state: FilesState, parentDir: string, folderName: string, agentId?: string) {\n if (!state.client || !state.connected) return;\n state.filesMessage = null;\n const dirPath = parentDir === \".\" ? folderName : `${parentDir}/${folderName}`;\n try {\n const params: Record<string, unknown> = { path: dirPath };\n if (agentId) params.agentId = agentId;\n await state.client.request(\"files.mkdir\", params);\n setSuccessMessage(state, `Created ${dirPath}`);\n await loadFileTree(state, agentId);\n // Expand and select the new folder\n state.filesExpandedDirs = new Set([...state.filesExpandedDirs, dirPath]);\n state.filesCurrentDir = dirPath;\n } catch (err) {\n state.filesMessage = { kind: \"error\", text: getErrorMessage(err) };\n }\n}\n\nexport async function deleteFile(state: FilesState, filePath: string, agentId?: string) {\n if (!state.client || !state.connected) return;\n state.filesMessage = null;\n try {\n const params: Record<string, unknown> = { path: filePath };\n if (agentId) params.agentId = agentId;\n await state.client.request(\"files.delete\", params);\n setSuccessMessage(state, \"File deleted\");\n if (state.filesSelectedPath === filePath) {\n state.filesSelectedPath = null;\n state.filesPreviewContent = null;\n }\n await loadFileTree(state, agentId);\n } catch (err) {\n state.filesMessage = { kind: \"error\", text: getErrorMessage(err) };\n }\n}\n\nexport async function moveFile(state: FilesState, from: string, to: string, agentId?: string) {\n if (!state.client || !state.connected) return;\n state.filesMessage = null;\n try {\n const params: Record<string, unknown> = { from, to };\n if (agentId) params.agentId = agentId;\n await state.client.request(\"files.move\", params);\n setSuccessMessage(state, \"File moved\");\n if (state.filesSelectedPath === from) {\n state.filesSelectedPath = to;\n }\n await loadFileTree(state, agentId);\n } catch (err) {\n state.filesMessage = { kind: \"error\", text: getErrorMessage(err) };\n }\n}\n\nexport async function loadMemoryStatus(state: FilesState, agentId?: string) {\n if (!state.client || !state.connected) return;\n try {\n const params: Record<string, unknown> = {};\n if (agentId) params.agentId = agentId;\n const res = (await state.client.request(\"memory.status\", params)) as {\n ok?: boolean;\n dirty?: boolean;\n syncing?: boolean;\n syncProgress?: { completed: number; total: number; label?: string };\n files?: number;\n chunks?: number;\n model?: string;\n embeddingState?: \"idle\" | \"downloading\" | \"ready\" | \"error\";\n } | undefined;\n if (res?.ok) {\n state.filesMemoryStatus = {\n dirty: res.dirty ?? false,\n syncing: res.syncing,\n syncProgress: res.syncProgress,\n files: res.files ?? 0,\n chunks: res.chunks ?? 0,\n model: res.model,\n embeddingState: res.embeddingState,\n };\n }\n } catch {\n // Non-fatal — status indicator stays hidden\n }\n}\n\nexport async function reindexMemory(state: FilesState, agentId?: string) {\n if (!state.client || !state.connected) return;\n if (state.filesReindexBusy) return;\n state.filesReindexBusy = true;\n state.filesMessage = null;\n try {\n const params: Record<string, unknown> = { force: true };\n if (agentId) params.agentId = agentId;\n const res = (await state.client.request(\"memory.reindex\", params)) as {\n ok?: boolean;\n files?: number;\n chunks?: number;\n } | undefined;\n const files = res?.files ?? 0;\n const chunks = res?.chunks ?? 0;\n setSuccessMessage(state, `Re-indexed: ${files} files, ${chunks} chunks`);\n // Refresh status indicator after successful reindex\n await loadMemoryStatus(state, agentId);\n } catch (err) {\n state.filesMessage = { kind: \"error\", text: getErrorMessage(err) };\n } finally {\n state.filesReindexBusy = false;\n }\n}\n\nexport function toggleDirectory(state: FilesState, dirPath: string) {\n const next = new Set(state.filesExpandedDirs);\n if (next.has(dirPath)) {\n next.delete(dirPath);\n } else {\n next.add(dirPath);\n }\n state.filesExpandedDirs = next;\n // Always set as current dir (even when collapsing — the user clicked it)\n state.filesCurrentDir = dirPath;\n}\n\nexport async function searchMemory(state: FilesState, query: string, agentId?: string) {\n if (!state.client || !state.connected) return;\n if (!query.trim()) {\n state.filesSearchResults = null;\n return;\n }\n state.filesSearchLoading = true;\n state.filesSearchResults = null;\n try {\n const params: Record<string, unknown> = { query: query.trim(), maxResults: 20 };\n if (agentId) params.agentId = agentId;\n const res = (await state.client.request(\"memory.search\", params)) as {\n ok?: boolean;\n agentId?: string;\n results?: MemorySearchHit[];\n } | undefined;\n state.filesSearchResults = res?.results ?? [];\n } catch (err) {\n state.filesMessage = { kind: \"error\", text: getErrorMessage(err) };\n state.filesSearchResults = null;\n } finally {\n state.filesSearchLoading = false;\n }\n}\n\nexport function clearSearch(state: FilesState) {\n state.filesSearchQuery = \"\";\n state.filesSearchResults = null;\n}\n","import { loadLogs } from \"./controllers/logs\";\nimport { loadNodes } from \"./controllers/nodes\";\nimport { loadDebug } from \"./controllers/debug\";\nimport { loadSessionLogs } from \"./controllers/session-logs\";\nimport { loadAuditEntries } from \"./controllers/audit\";\nimport { loadMemoryStatus } from \"./controllers/files\";\nimport type { TaskmasterApp } from \"./app\";\n\ntype PollingHost = {\n nodesPollInterval: number | null;\n logsPollInterval: number | null;\n debugPollInterval: number | null;\n auditPollInterval: number | null;\n memoryStatusPollInterval?: number | null;\n tab: string;\n};\n\nexport function startNodesPolling(host: PollingHost) {\n if (host.nodesPollInterval != null) return;\n host.nodesPollInterval = window.setInterval(\n () => void loadNodes(host as unknown as TaskmasterApp, { quiet: true }),\n 5000,\n );\n}\n\nexport function stopNodesPolling(host: PollingHost) {\n if (host.nodesPollInterval == null) return;\n clearInterval(host.nodesPollInterval);\n host.nodesPollInterval = null;\n}\n\nexport function startLogsPolling(host: PollingHost & { advancedPage?: boolean; advancedTab?: string; logsSubTab?: string }) {\n if (host.logsPollInterval != null) return;\n host.logsPollInterval = window.setInterval(() => {\n const onLogsTab = host.advancedPage\n ? host.advancedTab === \"logs\"\n : host.tab === \"logs\";\n if (!onLogsTab) return;\n // Only poll system logs when the sub-tab is \"system\" (or when there is no sub-tab)\n if (host.logsSubTab === \"session\") return;\n // Skip polling when viewing historical (non-live) logs — the file won't change.\n if ((host as unknown as { logsDate: string | null }).logsDate != null) return;\n void loadLogs(host as unknown as TaskmasterApp, { quiet: true });\n }, 2000);\n}\n\nexport function stopLogsPolling(host: PollingHost) {\n if (host.logsPollInterval == null) return;\n clearInterval(host.logsPollInterval);\n host.logsPollInterval = null;\n}\n\nexport function startSessionLogsPolling(host: PollingHost & { sessionLogsPollInterval?: number | null; logsSubTab?: string; advancedPage?: boolean; advancedTab?: string }) {\n if (host.sessionLogsPollInterval != null) return;\n host.sessionLogsPollInterval = window.setInterval(() => {\n // On standalone Advanced page, check advancedTab; on dashboard, check tab\n const onLogsTab = host.advancedPage\n ? host.advancedTab === \"logs\"\n : host.tab === \"logs\";\n if (!onLogsTab || host.logsSubTab !== \"session\") return;\n void loadSessionLogs(host as unknown as TaskmasterApp, { quiet: true, reset: true });\n }, 3000);\n}\n\nexport function stopSessionLogsPolling(host: { sessionLogsPollInterval?: number | null }) {\n if (host.sessionLogsPollInterval == null) return;\n clearInterval(host.sessionLogsPollInterval);\n host.sessionLogsPollInterval = null;\n}\n\nexport function startDebugPolling(host: PollingHost) {\n if (host.debugPollInterval != null) return;\n host.debugPollInterval = window.setInterval(() => {\n if (host.tab !== \"debug\") return;\n void loadDebug(host as unknown as TaskmasterApp);\n }, 3000);\n}\n\nexport function stopDebugPolling(host: PollingHost) {\n if (host.debugPollInterval == null) return;\n clearInterval(host.debugPollInterval);\n host.debugPollInterval = null;\n}\n\nexport function startAuditPolling(host: PollingHost) {\n if (host.auditPollInterval != null) return;\n // Poll every 30s — audit is in the header on every page\n host.auditPollInterval = window.setInterval(() => {\n void loadAuditEntries(host as unknown as TaskmasterApp);\n }, 30_000);\n}\n\nexport function stopAuditPolling(host: PollingHost) {\n if (host.auditPollInterval == null) return;\n clearInterval(host.auditPollInterval);\n host.auditPollInterval = null;\n}\n\nexport function startMemoryStatusPolling(host: PollingHost) {\n if (host.memoryStatusPollInterval != null) return;\n host.memoryStatusPollInterval = window.setInterval(() => {\n const app = host as unknown as TaskmasterApp;\n if (!app.filesPage) return;\n void loadMemoryStatus(app, app.filesResolvedAgentId);\n }, 3_000);\n}\n\nexport function stopMemoryStatusPolling(host: PollingHost & { memoryStatusPollInterval?: number | null }) {\n if (host.memoryStatusPollInterval == null) return;\n clearInterval(host.memoryStatusPollInterval);\n host.memoryStatusPollInterval = null;\n}\n","import { loadConfig, loadConfigSchema } from \"./controllers/config\";\nimport { loadCronJobs, loadCronStatus } from \"./controllers/cron\";\nimport { loadChannels } from \"./controllers/channels\";\nimport { loadDebug } from \"./controllers/debug\";\nimport { loadLogs } from \"./controllers/logs\";\nimport { loadDevices } from \"./controllers/devices\";\nimport { loadNodes } from \"./controllers/nodes\";\nimport { loadExecApprovals } from \"./controllers/exec-approvals\";\nimport { loadPresence } from \"./controllers/presence\";\nimport { loadSessions } from \"./controllers/sessions\";\nimport { loadSkills } from \"./controllers/skills\";\nimport { inferBasePathFromPathname, normalizeBasePath, normalizePath, pathForTab, tabFromPath, type Tab } from \"./navigation\";\nimport { saveSettings, type UiSettings } from \"./storage\";\nimport { resolveTheme, type ResolvedTheme, type ThemeMode } from \"./theme\";\nimport { startThemeTransition, type ThemeTransitionContext } from \"./theme-transition\";\nimport { scheduleChatScroll, scheduleLogsScroll } from \"./app-scroll\";\nimport { startLogsPolling, stopLogsPolling, startDebugPolling, stopDebugPolling, startSessionLogsPolling, stopSessionLogsPolling } from \"./app-polling\";\nimport { refreshChat } from \"./app-chat\";\nimport type { TaskmasterApp } from \"./app\";\n\ntype SettingsHost = {\n settings: UiSettings;\n theme: ThemeMode;\n themeResolved: ResolvedTheme;\n applySessionKey: string;\n sessionKey: string;\n tab: Tab;\n connected: boolean;\n chatHasAutoScrolled: boolean;\n logsAtBottom: boolean;\n eventLog: unknown[];\n eventLogBuffer: unknown[];\n basePath: string;\n themeMedia: MediaQueryList | null;\n themeMediaHandler: ((event: MediaQueryListEvent) => void) | null;\n advancedPage?: boolean;\n chatPage?: boolean;\n};\n\nexport function applySettings(host: SettingsHost, next: UiSettings) {\n const normalized = {\n ...next,\n lastActiveSessionKey: next.lastActiveSessionKey?.trim() || next.sessionKey.trim() || \"main\",\n };\n host.settings = normalized;\n saveSettings(normalized);\n if (next.theme !== host.theme) {\n host.theme = next.theme;\n applyResolvedTheme(host, resolveTheme(next.theme));\n }\n host.applySessionKey = host.settings.lastActiveSessionKey;\n}\n\nexport function setLastActiveSessionKey(host: SettingsHost, next: string) {\n const trimmed = next.trim();\n if (!trimmed) return;\n if (host.settings.lastActiveSessionKey === trimmed) return;\n applySettings(host, { ...host.settings, lastActiveSessionKey: trimmed });\n}\n\nexport function applySettingsFromUrl(host: SettingsHost) {\n if (!window.location.search) return;\n const params = new URLSearchParams(window.location.search);\n const tokenRaw = params.get(\"token\");\n const passwordRaw = params.get(\"password\");\n const sessionRaw = params.get(\"session\");\n const gatewayUrlRaw = params.get(\"gatewayUrl\");\n let shouldCleanUrl = false;\n\n if (tokenRaw != null) {\n const token = tokenRaw.trim();\n if (token && token !== host.settings.token) {\n applySettings(host, { ...host.settings, token });\n }\n params.delete(\"token\");\n shouldCleanUrl = true;\n }\n\n if (passwordRaw != null) {\n const password = passwordRaw.trim();\n if (password) {\n (host as { password: string }).password = password;\n }\n params.delete(\"password\");\n shouldCleanUrl = true;\n }\n\n if (sessionRaw != null) {\n const session = sessionRaw.trim();\n if (session) {\n host.sessionKey = session;\n applySettings(host, {\n ...host.settings,\n sessionKey: session,\n lastActiveSessionKey: session,\n });\n }\n }\n\n if (gatewayUrlRaw != null) {\n const gatewayUrl = gatewayUrlRaw.trim();\n if (gatewayUrl && gatewayUrl !== host.settings.gatewayUrl) {\n applySettings(host, { ...host.settings, gatewayUrl });\n }\n params.delete(\"gatewayUrl\");\n shouldCleanUrl = true;\n }\n\n if (!shouldCleanUrl) return;\n const url = new URL(window.location.href);\n url.search = params.toString();\n window.history.replaceState({}, \"\", url.toString());\n}\n\nexport function setTab(host: SettingsHost, next: Tab) {\n if (host.tab !== next) host.tab = next;\n if (next === \"chat\") host.chatHasAutoScrolled = false;\n if (next === \"logs\") {\n const subTab = (host as unknown as { logsSubTab?: string }).logsSubTab;\n if (subTab === \"session\") {\n startSessionLogsPolling(host as unknown as Parameters<typeof startSessionLogsPolling>[0]);\n } else {\n startLogsPolling(host as unknown as Parameters<typeof startLogsPolling>[0]);\n }\n } else {\n stopLogsPolling(host as unknown as Parameters<typeof stopLogsPolling>[0]);\n stopSessionLogsPolling(host as unknown as Parameters<typeof stopSessionLogsPolling>[0]);\n }\n if (next === \"debug\")\n startDebugPolling(host as unknown as Parameters<typeof startDebugPolling>[0]);\n else stopDebugPolling(host as unknown as Parameters<typeof stopDebugPolling>[0]);\n void refreshActiveTab(host);\n syncUrlWithTab(host, next, false);\n}\n\nexport function setTheme(\n host: SettingsHost,\n next: ThemeMode,\n context?: ThemeTransitionContext,\n) {\n const applyTheme = () => {\n host.theme = next;\n applySettings(host, { ...host.settings, theme: next });\n applyResolvedTheme(host, resolveTheme(next));\n };\n startThemeTransition({\n nextTheme: next,\n applyTheme,\n context,\n currentTheme: host.theme,\n });\n}\n\nexport async function refreshActiveTab(host: SettingsHost) {\n if (host.tab === \"overview\") await loadOverview(host);\n if (host.tab === \"channels\") await loadChannelsTab(host);\n if (host.tab === \"instances\") await loadPresence(host as unknown as TaskmasterApp);\n if (host.tab === \"cron\") await loadCron(host);\n if (host.tab === \"skills\") await loadSkills(host as unknown as TaskmasterApp);\n if (host.tab === \"nodes\") {\n await loadNodes(host as unknown as TaskmasterApp);\n await loadDevices(host as unknown as TaskmasterApp);\n await loadConfig(host as unknown as TaskmasterApp);\n await loadExecApprovals(host as unknown as TaskmasterApp);\n }\n // For standalone chat page, skip early refresh — initWorkspaceSelection()\n // will call handleChatLoad() after workspaces are loaded with the correct\n // session key for the selected business.\n if (host.tab === \"chat\" && !host.advancedPage && !host.chatPage) {\n await refreshChat(host as unknown as Parameters<typeof refreshChat>[0]);\n scheduleChatScroll(\n host as unknown as Parameters<typeof scheduleChatScroll>[0],\n !host.chatHasAutoScrolled,\n );\n }\n if (host.tab === \"config\") {\n await loadConfigSchema(host as unknown as TaskmasterApp);\n await loadConfig(host as unknown as TaskmasterApp);\n }\n if (host.tab === \"debug\") {\n await loadDebug(host as unknown as TaskmasterApp);\n host.eventLog = host.eventLogBuffer;\n }\n if (host.tab === \"logs\") {\n host.logsAtBottom = true;\n const subTab = (host as unknown as { logsSubTab?: string }).logsSubTab;\n if (subTab === \"session\") {\n const { loadSessionLogs } = await import(\"./controllers/session-logs\");\n await loadSessionLogs(host as unknown as Parameters<typeof loadSessionLogs>[0], { reset: true });\n } else {\n await loadLogs(host as unknown as TaskmasterApp, { reset: true });\n }\n scheduleLogsScroll(\n host as unknown as Parameters<typeof scheduleLogsScroll>[0],\n true,\n );\n }\n}\n\nexport function inferBasePath() {\n if (typeof window === \"undefined\") return \"\";\n const configured = window.__TASKMASTER_CONTROL_UI_BASE_PATH__;\n if (typeof configured === \"string\" && configured.trim()) {\n return normalizeBasePath(configured);\n }\n return inferBasePathFromPathname(window.location.pathname);\n}\n\nexport function syncThemeWithSettings(host: SettingsHost) {\n host.theme = host.settings.theme ?? \"system\";\n applyResolvedTheme(host, resolveTheme(host.theme));\n}\n\nexport function applyResolvedTheme(host: SettingsHost, resolved: ResolvedTheme) {\n host.themeResolved = resolved;\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n root.dataset.theme = resolved;\n root.style.colorScheme = resolved;\n}\n\nexport function attachThemeListener(host: SettingsHost) {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n host.themeMedia = window.matchMedia(\"(prefers-color-scheme: dark)\");\n host.themeMediaHandler = (event) => {\n if (host.theme !== \"system\") return;\n applyResolvedTheme(host, event.matches ? \"dark\" : \"light\");\n };\n if (typeof host.themeMedia.addEventListener === \"function\") {\n host.themeMedia.addEventListener(\"change\", host.themeMediaHandler);\n return;\n }\n const legacy = host.themeMedia as MediaQueryList & {\n addListener: (cb: (event: MediaQueryListEvent) => void) => void;\n };\n legacy.addListener(host.themeMediaHandler);\n}\n\nexport function detachThemeListener(host: SettingsHost) {\n if (!host.themeMedia || !host.themeMediaHandler) return;\n if (typeof host.themeMedia.removeEventListener === \"function\") {\n host.themeMedia.removeEventListener(\"change\", host.themeMediaHandler);\n return;\n }\n const legacy = host.themeMedia as MediaQueryList & {\n removeListener: (cb: (event: MediaQueryListEvent) => void) => void;\n };\n legacy.removeListener(host.themeMediaHandler);\n host.themeMedia = null;\n host.themeMediaHandler = null;\n}\n\nexport function syncTabWithLocation(host: SettingsHost, replace: boolean) {\n if (typeof window === \"undefined\") return;\n const resolved = tabFromPath(window.location.pathname, host.basePath) ?? \"chat\";\n setTabFromRoute(host, resolved);\n syncUrlWithTab(host, resolved, replace);\n}\n\nexport function onPopState(host: SettingsHost) {\n if (typeof window === \"undefined\") return;\n const resolved = tabFromPath(window.location.pathname, host.basePath);\n if (!resolved) return;\n\n const url = new URL(window.location.href);\n const session = url.searchParams.get(\"session\")?.trim();\n if (session) {\n host.sessionKey = session;\n applySettings(host, {\n ...host.settings,\n sessionKey: session,\n lastActiveSessionKey: session,\n });\n }\n\n setTabFromRoute(host, resolved);\n}\n\nexport function setTabFromRoute(host: SettingsHost, next: Tab) {\n if (host.tab !== next) host.tab = next;\n if (next === \"chat\") host.chatHasAutoScrolled = false;\n if (next === \"logs\") {\n const subTab = (host as unknown as { logsSubTab?: string }).logsSubTab;\n if (subTab === \"session\") {\n startSessionLogsPolling(host as unknown as Parameters<typeof startSessionLogsPolling>[0]);\n } else {\n startLogsPolling(host as unknown as Parameters<typeof startLogsPolling>[0]);\n }\n } else {\n stopLogsPolling(host as unknown as Parameters<typeof stopLogsPolling>[0]);\n stopSessionLogsPolling(host as unknown as Parameters<typeof stopSessionLogsPolling>[0]);\n }\n if (next === \"debug\")\n startDebugPolling(host as unknown as Parameters<typeof startDebugPolling>[0]);\n else stopDebugPolling(host as unknown as Parameters<typeof stopDebugPolling>[0]);\n if (host.connected) void refreshActiveTab(host);\n}\n\nexport function syncUrlWithTab(host: SettingsHost, tab: Tab, replace: boolean) {\n if (typeof window === \"undefined\") return;\n const targetPath = normalizePath(pathForTab(tab, host.basePath));\n const currentPath = normalizePath(window.location.pathname);\n const url = new URL(window.location.href);\n\n if (tab === \"chat\" && host.sessionKey) {\n url.searchParams.set(\"session\", host.sessionKey);\n } else {\n url.searchParams.delete(\"session\");\n }\n\n if (currentPath !== targetPath) {\n url.pathname = targetPath;\n }\n\n if (replace) {\n window.history.replaceState({}, \"\", url.toString());\n } else {\n window.history.pushState({}, \"\", url.toString());\n }\n}\n\nexport function syncUrlWithSessionKey(\n host: SettingsHost,\n sessionKey: string,\n replace: boolean,\n) {\n if (typeof window === \"undefined\") return;\n const url = new URL(window.location.href);\n url.searchParams.set(\"session\", sessionKey);\n if (replace) window.history.replaceState({}, \"\", url.toString());\n else window.history.pushState({}, \"\", url.toString());\n}\n\nexport async function loadOverview(host: SettingsHost) {\n await Promise.all([\n loadChannels(host as unknown as TaskmasterApp, false),\n loadPresence(host as unknown as TaskmasterApp),\n loadSessions(host as unknown as TaskmasterApp),\n loadCronStatus(host as unknown as TaskmasterApp),\n loadDebug(host as unknown as TaskmasterApp),\n ]);\n}\n\nexport async function loadChannelsTab(host: SettingsHost) {\n await Promise.all([\n loadChannels(host as unknown as TaskmasterApp, true),\n loadConfigSchema(host as unknown as TaskmasterApp),\n loadConfig(host as unknown as TaskmasterApp),\n ]);\n}\n\nexport async function loadCron(host: SettingsHost) {\n await Promise.all([\n loadChannels(host as unknown as TaskmasterApp, false),\n loadCronStatus(host as unknown as TaskmasterApp),\n loadCronJobs(host as unknown as TaskmasterApp),\n ]);\n}\n","import { abortChatRun, loadChatHistory, sendChatMessage, CHAT_PAGE_SIZE } from \"./controllers/chat\";\nimport { loadSessions } from \"./controllers/sessions\";\nimport { generateUUID } from \"./uuid\";\nimport { resetToolStream } from \"./app-tool-stream\";\nimport { scheduleChatScroll } from \"./app-scroll\";\nimport { setLastActiveSessionKey } from \"./app-settings\";\nimport { clearDraft } from \"./storage\";\nimport { normalizeBasePath } from \"./navigation\";\nimport type { GatewayHelloOk } from \"./gateway\";\nimport { parseAgentSessionKey } from \"../../../src/sessions/session-key-utils.js\";\nimport type { TaskmasterApp } from \"./app\";\nimport type { ChatAttachment, ChatQueueItem } from \"./ui-types\";\n\ntype ChatHost = {\n connected: boolean;\n chatMessage: string;\n chatAttachments: ChatAttachment[];\n chatQueue: ChatQueueItem[];\n chatRunId: string | null;\n chatSending: boolean;\n sessionKey: string;\n selectedWorkspace: string | null;\n basePath: string;\n hello: GatewayHelloOk | null;\n chatAvatarUrl: string | null;\n};\n\nexport function isChatBusy(host: ChatHost) {\n return host.chatSending || Boolean(host.chatRunId);\n}\n\nexport function isChatStopCommand(text: string) {\n const trimmed = text.trim();\n if (!trimmed) return false;\n const normalized = trimmed.toLowerCase();\n if (normalized === \"/stop\") return true;\n return (\n normalized === \"stop\" ||\n normalized === \"esc\" ||\n normalized === \"abort\" ||\n normalized === \"wait\" ||\n normalized === \"exit\"\n );\n}\n\nexport async function handleAbortChat(host: ChatHost) {\n if (!host.connected) return;\n host.chatMessage = \"\";\n await abortChatRun(host as unknown as TaskmasterApp);\n}\n\nfunction enqueueChatMessage(host: ChatHost, text: string, attachments?: ChatAttachment[]) {\n const trimmed = text.trim();\n const hasAttachments = Boolean(attachments && attachments.length > 0);\n if (!trimmed && !hasAttachments) return;\n host.chatQueue = [\n ...host.chatQueue,\n {\n id: generateUUID(),\n text: trimmed,\n createdAt: Date.now(),\n attachments: hasAttachments ? attachments?.map((att) => ({ ...att })) : undefined,\n },\n ];\n scheduleChatScroll(host as unknown as Parameters<typeof scheduleChatScroll>[0]);\n}\n\nasync function sendChatMessageNow(\n host: ChatHost,\n message: string,\n opts?: {\n previousDraft?: string;\n restoreDraft?: boolean;\n attachments?: ChatAttachment[];\n previousAttachments?: ChatAttachment[];\n restoreAttachments?: boolean;\n },\n) {\n resetToolStream(host as unknown as Parameters<typeof resetToolStream>[0]);\n const ok = await sendChatMessage(host as unknown as TaskmasterApp, message, opts?.attachments);\n if (!ok && opts?.previousDraft != null) {\n host.chatMessage = opts.previousDraft;\n }\n if (!ok && opts?.previousAttachments) {\n host.chatAttachments = opts.previousAttachments;\n }\n if (ok) {\n setLastActiveSessionKey(host as unknown as Parameters<typeof setLastActiveSessionKey>[0], host.sessionKey);\n }\n if (ok && opts?.restoreDraft && opts.previousDraft?.trim()) {\n host.chatMessage = opts.previousDraft;\n }\n if (ok && opts?.restoreAttachments && opts.previousAttachments?.length) {\n host.chatAttachments = opts.previousAttachments;\n }\n scheduleChatScroll(host as unknown as Parameters<typeof scheduleChatScroll>[0]);\n if (ok && !host.chatRunId) {\n void flushChatQueue(host);\n }\n return ok;\n}\n\nasync function flushChatQueue(host: ChatHost) {\n if (!host.connected || isChatBusy(host)) return;\n const [next, ...rest] = host.chatQueue;\n if (!next) return;\n host.chatQueue = rest;\n const ok = await sendChatMessageNow(host, next.text, { attachments: next.attachments });\n if (!ok) {\n host.chatQueue = [next, ...host.chatQueue];\n }\n}\n\nexport function removeQueuedMessage(host: ChatHost, id: string) {\n host.chatQueue = host.chatQueue.filter((item) => item.id !== id);\n}\n\nexport async function handleSendChat(\n host: ChatHost,\n messageOverride?: string,\n opts?: { restoreDraft?: boolean },\n) {\n if (!host.connected) return;\n const previousDraft = host.chatMessage;\n const message = (messageOverride ?? host.chatMessage).trim();\n const attachments = host.chatAttachments ?? [];\n const attachmentsToSend = messageOverride == null ? attachments : [];\n const hasAttachments = attachmentsToSend.length > 0;\n\n // Allow sending with just attachments (no message text required)\n if (!message && !hasAttachments) return;\n\n if (isChatStopCommand(message)) {\n await handleAbortChat(host);\n return;\n }\n\n if (messageOverride == null) {\n host.chatMessage = \"\";\n host.chatAttachments = [];\n // Clear stored draft — message is being sent\n clearDraft(host.selectedWorkspace ?? \"\", host.sessionKey);\n }\n\n if (isChatBusy(host)) {\n enqueueChatMessage(host, message, attachmentsToSend);\n return;\n }\n\n await sendChatMessageNow(host, message, {\n previousDraft: messageOverride == null ? previousDraft : undefined,\n restoreDraft: Boolean(messageOverride && opts?.restoreDraft),\n attachments: hasAttachments ? attachmentsToSend : undefined,\n previousAttachments: messageOverride == null ? attachments : undefined,\n restoreAttachments: Boolean(messageOverride && opts?.restoreDraft),\n });\n}\n\nexport async function refreshChat(host: ChatHost) {\n const app = host as unknown as TaskmasterApp;\n const reloadLimit = Math.max((app.chatMessages?.length ?? 0) + 10, CHAT_PAGE_SIZE);\n await Promise.all([\n loadChatHistory(app, { limit: reloadLimit }),\n loadSessions(app),\n refreshChatAvatar(host),\n ]);\n scheduleChatScroll(host as unknown as Parameters<typeof scheduleChatScroll>[0], true);\n}\n\nexport const flushChatQueueForEvent = flushChatQueue;\n\ntype SessionDefaultsSnapshot = {\n defaultAgentId?: string;\n};\n\nfunction resolveAgentIdForSession(host: ChatHost): string | null {\n const parsed = parseAgentSessionKey(host.sessionKey);\n if (parsed?.agentId) return parsed.agentId;\n const snapshot = host.hello?.snapshot as { sessionDefaults?: SessionDefaultsSnapshot } | undefined;\n const fallback = snapshot?.sessionDefaults?.defaultAgentId?.trim();\n return fallback || \"main\";\n}\n\nfunction buildAvatarMetaUrl(basePath: string, agentId: string): string {\n const base = normalizeBasePath(basePath);\n const encoded = encodeURIComponent(agentId);\n return base ? `${base}/avatar/${encoded}?meta=1` : `/avatar/${encoded}?meta=1`;\n}\n\nexport async function refreshChatAvatar(host: ChatHost) {\n if (!host.connected) {\n host.chatAvatarUrl = null;\n return;\n }\n const agentId = resolveAgentIdForSession(host);\n if (!agentId) {\n host.chatAvatarUrl = null;\n return;\n }\n host.chatAvatarUrl = null;\n const url = buildAvatarMetaUrl(host.basePath, agentId);\n try {\n const res = await fetch(url, { method: \"GET\" });\n if (!res.ok) {\n host.chatAvatarUrl = null;\n return;\n }\n const data = (await res.json()) as { avatarUrl?: unknown };\n const avatarUrl = typeof data.avatarUrl === \"string\" ? data.avatarUrl.trim() : \"\";\n host.chatAvatarUrl = avatarUrl || null;\n } catch {\n host.chatAvatarUrl = null;\n }\n}\n","import { html, type TemplateResult } from \"lit\";\n\n// Lucide-style SVG icons\n// All icons use currentColor for stroke\n\nexport const icons = {\n // Navigation icons\n messageSquare: html`<svg viewBox=\"0 0 24 24\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"/></svg>`,\n barChart: html`<svg viewBox=\"0 0 24 24\"><line x1=\"12\" x2=\"12\" y1=\"20\" y2=\"10\"/><line x1=\"18\" x2=\"18\" y1=\"20\" y2=\"4\"/><line x1=\"6\" x2=\"6\" y1=\"20\" y2=\"16\"/></svg>`,\n link: html`<svg viewBox=\"0 0 24 24\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>`,\n unlink: html`<svg viewBox=\"0 0 24 24\"><path d=\"m18.84 12.25 1.72-1.71h-.02a5.004 5.004 0 0 0-.12-7.07 5.006 5.006 0 0 0-6.95 0l-1.72 1.71\"/><path d=\"m5.17 11.75-1.71 1.71a5.004 5.004 0 0 0 .12 7.07 5.006 5.006 0 0 0 6.95 0l1.71-1.71\"/><line x1=\"8\" x2=\"8\" y1=\"2\" y2=\"5\"/><line x1=\"2\" x2=\"5\" y1=\"8\" y2=\"8\"/><line x1=\"16\" x2=\"16\" y1=\"19\" y2=\"22\"/><line x1=\"19\" x2=\"22\" y1=\"16\" y2=\"16\"/></svg>`,\n radio: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"2\"/><path d=\"M16.24 7.76a6 6 0 0 1 0 8.49m-8.48-.01a6 6 0 0 1 0-8.49m11.31-2.82a10 10 0 0 1 0 14.14m-14.14 0a10 10 0 0 1 0-14.14\"/></svg>`,\n fileText: html`<svg viewBox=\"0 0 24 24\"><path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"/><polyline points=\"14 2 14 8 20 8\"/><line x1=\"16\" x2=\"8\" y1=\"13\" y2=\"13\"/><line x1=\"16\" x2=\"8\" y1=\"17\" y2=\"17\"/><line x1=\"10\" x2=\"8\" y1=\"9\" y2=\"9\"/></svg>`,\n zap: html`<svg viewBox=\"0 0 24 24\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/></svg>`,\n monitor: html`<svg viewBox=\"0 0 24 24\"><rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\"/><line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\"/><line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\"/></svg>`,\n settings: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`,\n bug: html`<svg viewBox=\"0 0 24 24\"><path d=\"m8 2 1.88 1.88\"/><path d=\"M14.12 3.88 16 2\"/><path d=\"M9 7.13v-1a3.003 3.003 0 1 1 6 0v1\"/><path d=\"M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6\"/><path d=\"M12 20v-9\"/><path d=\"M6.53 9C4.6 8.8 3 7.1 3 5\"/><path d=\"M6 13H2\"/><path d=\"M3 21c0-2.1 1.7-3.9 3.8-4\"/><path d=\"M20.97 5c0 2.1-1.6 3.8-3.5 4\"/><path d=\"M22 13h-4\"/><path d=\"M17.2 17c2.1.1 3.8 1.9 3.8 4\"/></svg>`,\n scrollText: html`<svg viewBox=\"0 0 24 24\"><path d=\"M8 21h12a2 2 0 0 0 2-2v-2H10v2a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v3h4\"/><path d=\"M19 17V5a2 2 0 0 0-2-2H4\"/><path d=\"M15 8h-5\"/><path d=\"M15 12h-5\"/></svg>`,\n folder: html`<svg viewBox=\"0 0 24 24\"><path d=\"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\"/></svg>`,\n users: html`<svg viewBox=\"0 0 24 24\"><path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"/><circle cx=\"9\" cy=\"7\" r=\"4\"/><path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"/><path d=\"M16 3.13a4 4 0 0 1 0 7.75\"/></svg>`,\n user: html`<svg viewBox=\"0 0 24 24\"><path d=\"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\"/><circle cx=\"12\" cy=\"7\" r=\"4\"/></svg>`,\n\n // UI icons\n menu: html`<svg viewBox=\"0 0 24 24\"><line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\"/><line x1=\"4\" x2=\"20\" y1=\"6\" y2=\"6\"/><line x1=\"4\" x2=\"20\" y1=\"18\" y2=\"18\"/></svg>`,\n x: html`<svg viewBox=\"0 0 24 24\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>`,\n check: html`<svg viewBox=\"0 0 24 24\"><path d=\"M20 6 9 17l-5-5\"/></svg>`,\n copy: html`<svg viewBox=\"0 0 24 24\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg>`,\n search: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/></svg>`,\n brain: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z\"/><path d=\"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z\"/><path d=\"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4\"/><path d=\"M17.599 6.5a3 3 0 0 0 .399-1.375\"/><path d=\"M6.003 5.125A3 3 0 0 0 6.401 6.5\"/><path d=\"M3.477 10.896a4 4 0 0 1 .585-.396\"/><path d=\"M19.938 10.5a4 4 0 0 1 .585.396\"/><path d=\"M6 18a4 4 0 0 1-1.967-.516\"/><path d=\"M19.967 17.484A4 4 0 0 1 18 18\"/></svg>`,\n book: html`<svg viewBox=\"0 0 24 24\"><path d=\"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20\"/></svg>`,\n loader: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 2v4\"/><path d=\"m16.2 7.8 2.9-2.9\"/><path d=\"M18 12h4\"/><path d=\"m16.2 16.2 2.9 2.9\"/><path d=\"M12 18v4\"/><path d=\"m4.9 19.1 2.9-2.9\"/><path d=\"M2 12h4\"/><path d=\"m4.9 4.9 2.9 2.9\"/></svg>`,\n rotateCw: html`<svg viewBox=\"0 0 24 24\"><path d=\"M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8\"/><path d=\"M21 3v5h-5\"/></svg>`,\n refreshCw: html`<svg viewBox=\"0 0 24 24\"><path d=\"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\"/><path d=\"M21 3v5h-5\"/><path d=\"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16\"/><path d=\"M8 16H3v5\"/></svg>`,\n download: html`<svg viewBox=\"0 0 24 24\"><path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"/><polyline points=\"7 10 12 15 17 10\"/><line x1=\"12\" x2=\"12\" y1=\"15\" y2=\"3\"/></svg>`,\n\n // Tool icons\n wrench: html`<svg viewBox=\"0 0 24 24\"><path d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z\"/></svg>`,\n fileCode: html`<svg viewBox=\"0 0 24 24\"><path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\"/><polyline points=\"14 2 14 8 20 8\"/><path d=\"m10 13-2 2 2 2\"/><path d=\"m14 17 2-2-2-2\"/></svg>`,\n edit: html`<svg viewBox=\"0 0 24 24\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`,\n penLine: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z\"/></svg>`,\n paperclip: html`<svg viewBox=\"0 0 24 24\"><path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\"/></svg>`,\n globe: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\"/><path d=\"M2 12h20\"/></svg>`,\n globeOff: html`<svg viewBox=\"0 0 24 24\"><path d=\"M21.54 15H17\"/><path d=\"M7 3.34V5a3 3 0 0 0 3 3 2 2 0 0 1 2 2c0 1.1.9 2 2 2a2 2 0 0 0 2-2c0-1.1.9-2 2-2h3.17\"/><path d=\"M11 21.95V18a2 2 0 0 0-2-2 2 2 0 0 1-2-2v-1a2 2 0 0 0-2-2H2.05\"/><circle cx=\"12\" cy=\"12\" r=\"10\"/><line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\"/></svg>`,\n image: html`<svg viewBox=\"0 0 24 24\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"/><circle cx=\"9\" cy=\"9\" r=\"2\"/><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\"/></svg>`,\n smartphone: html`<svg viewBox=\"0 0 24 24\"><rect width=\"14\" height=\"20\" x=\"5\" y=\"2\" rx=\"2\" ry=\"2\"/><path d=\"M12 18h.01\"/></svg>`,\n plug: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 22v-5\"/><path d=\"M9 8V2\"/><path d=\"M15 8V2\"/><path d=\"M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z\"/></svg>`,\n circle: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/></svg>`,\n circleCheck: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m9 12 2 2 4-4\"/></svg>`,\n circleX: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"m15 9-6 6\"/><path d=\"m9 9 6 6\"/></svg>`,\n puzzle: html`<svg viewBox=\"0 0 24 24\"><path d=\"M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.705.707 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.23 8.77c.24-.24.581-.353.917-.303.515.076.874.54 1.02 1.02a2.5 2.5 0 1 0 3.237-3.237c-.48-.146-.944-.505-1.02-1.02a.98.98 0 0 1 .303-.917l1.526-1.526A2.402 2.402 0 0 1 11.998 2c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.968a2.5 2.5 0 1 1 3.236 3.236c-.464.18-.894.527-.967 1.02Z\"/></svg>`,\n info: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4\"/><path d=\"M12 8h.01\"/></svg>`,\n send: html`<svg viewBox=\"0 0 24 24\"><path d=\"m22 2-7 20-4-9-9-4Z\"/><path d=\"M22 2 11 13\"/></svg>`,\n smile: html`<svg viewBox=\"0 0 24 24\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M8 14s1.5 2 4 2 4-2 4-2\"/><line x1=\"9\" y1=\"9\" x2=\"9.01\" y2=\"9\"/><line x1=\"15\" y1=\"9\" x2=\"15.01\" y2=\"9\"/></svg>`,\n slidersHorizontal: html`<svg viewBox=\"0 0 24 24\"><line x1=\"21\" x2=\"14\" y1=\"4\" y2=\"4\"/><line x1=\"10\" x2=\"3\" y1=\"4\" y2=\"4\"/><line x1=\"21\" x2=\"12\" y1=\"12\" y2=\"12\"/><line x1=\"8\" x2=\"3\" y1=\"12\" y2=\"12\"/><line x1=\"21\" x2=\"16\" y1=\"20\" y2=\"20\"/><line x1=\"12\" x2=\"3\" y1=\"20\" y2=\"20\"/><line x1=\"14\" x2=\"14\" y1=\"2\" y2=\"6\"/><line x1=\"8\" x2=\"8\" y1=\"10\" y2=\"14\"/><line x1=\"16\" x2=\"16\" y1=\"18\" y2=\"22\"/></svg>`,\n square: html`<svg viewBox=\"0 0 24 24\"><rect width=\"14\" height=\"14\" x=\"5\" y=\"5\" rx=\"2\"/></svg>`,\n eye: html`<svg viewBox=\"0 0 24 24\"><path d=\"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/></svg>`,\n eyeOff: html`<svg viewBox=\"0 0 24 24\"><path d=\"M9.88 9.88a3 3 0 1 0 4.24 4.24\"/><path d=\"M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68\"/><path d=\"M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61\"/><line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\"/></svg>`,\n trash: html`<svg viewBox=\"0 0 24 24\"><path d=\"M3 6h18\"/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"/><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\"/></svg>`,\n mic: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\"/><path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"/><line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\"/></svg>`,\n chevronDown: html`<svg viewBox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"/></svg>`,\n chevronLeft: html`<svg viewBox=\"0 0 24 24\"><path d=\"m15 18-6-6 6-6\"/></svg>`,\n chevronRight: html`<svg viewBox=\"0 0 24 24\"><path d=\"m9 18 6-6-6-6\"/></svg>`,\n film: html`<svg viewBox=\"0 0 24 24\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/><path d=\"M7 3v18\"/><path d=\"M3 7.5h4\"/><path d=\"M3 12h18\"/><path d=\"M3 16.5h4\"/><path d=\"M17 3v18\"/><path d=\"M17 7.5h4\"/><path d=\"M17 16.5h4\"/></svg>`,\n wifi: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 20h.01\"/><path d=\"M2 8.82a15 15 0 0 1 20 0\"/><path d=\"M5 12.859a10 10 0 0 1 14 0\"/><path d=\"M8.5 16.429a5 5 0 0 1 7 0\"/></svg>`,\n wifiOff: html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 20h.01\"/><path d=\"M8.5 16.429a5 5 0 0 1 7 0\"/><path d=\"M5 12.859a10 10 0 0 1 5.17-2.69\"/><path d=\"M13.41 10.28a10 10 0 0 1 5.59 2.58\"/><path d=\"M2 8.82a15 15 0 0 1 4.17-2.65\"/><path d=\"M10.66 5c4.01-.36 8.14.9 11.34 3.76\"/><line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\"/></svg>`,\n power: html`<svg viewBox=\"0 0 24 24\"><path d=\"M18.36 6.64a9 9 0 1 1-12.73 0\"/><line x1=\"12\" x2=\"12\" y1=\"2\" y2=\"12\"/></svg>`,\n powerOff: html`<svg viewBox=\"0 0 24 24\"><path d=\"M18.36 6.64A9 9 0 0 1 20.77 15\"/><path d=\"M6.16 6.16a9 9 0 1 0 12.68 12.68\"/><path d=\"M12 2v4\"/><path d=\"m2 2 20 20\"/></svg>`,\n} as const;\n\nexport type IconName = keyof typeof icons;\n\nexport function icon(name: IconName): TemplateResult {\n return icons[name];\n}\n\nexport function renderIcon(name: IconName, className = \"nav-item__icon\"): TemplateResult {\n return html`<span class=${className} aria-hidden=\"true\">${icons[name]}</span>`;\n}\n\n// Legacy function for compatibility\nexport function renderEmojiIcon(iconContent: string | TemplateResult, className: string): TemplateResult {\n return html`<span class=${className} aria-hidden=\"true\">${iconContent}</span>`;\n}\n\nexport function setEmojiIcon(target: HTMLElement | null, icon: string): void {\n if (!target) return;\n target.textContent = icon;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { WorkspaceInfo } from \"../controllers/workspaces\";\nimport { resolveBrand, getWorkspaceBrands } from \"../brand\";\n\nconst lockIcon = html`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"3\" y=\"11\" width=\"18\" height=\"11\" rx=\"2\" ry=\"2\"></rect><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"></path></svg>`;\n\nconst bellIcon = html`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9\"></path><path d=\"M13.73 21a2 2 0 0 1-3.46 0\"></path></svg>`;\n\nconst powerIcon = html`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18.36 6.64a9 9 0 1 1-12.73 0\"></path><line x1=\"12\" y1=\"2\" x2=\"12\" y2=\"12\"></line></svg>`;\n\nlet burgerListenerBound = false;\nfunction ensureBurgerOutsideClickListener() {\n if (burgerListenerBound) return;\n burgerListenerBound = true;\n document.addEventListener(\"click\", (e: MouseEvent) => {\n const cb = document.getElementById(\"nav-burger-toggle\") as HTMLInputElement | null;\n if (!cb?.checked) return;\n const header = cb.closest(\".setup-header\");\n if (header?.contains(e.target as Node)) return;\n cb.checked = false;\n });\n}\n\nexport type WorkspaceNavProps = {\n workspaces: WorkspaceInfo[];\n selectedWorkspace: string | null;\n onWorkspaceSelect: (name: string) => void;\n /** When set, \"Add Account\" triggers this callback instead of navigating to /setup. */\n onAddAccount?: () => void;\n /** Whether PINs are configured on this device. */\n hasPins?: boolean;\n /** Whether this is a master (device owner) session — shows all accounts. */\n isMaster?: boolean;\n /** Logout callback — shown when PINs are active. */\n onLogout?: () => void;\n /** Number of unreviewed memory audit entries. */\n auditCount?: number;\n /** Callback when audit icon is clicked. */\n onAuditClick?: () => void;\n /** Callback to restart the gateway. */\n onRestartGateway?: () => void;\n};\n\n/**\n * Shared fixed top header with logo + nav for all standalone pages.\n * Pass the current page name to highlight it.\n *\n * Uses a checkbox hack for the burger menu so no JS state is needed.\n * The checkbox is hidden; the burger label toggles it. A media query\n * hides the inline nav and shows the burger + dropdown below 768px.\n *\n * When wsProps is provided, renders an account selector dropdown\n * right-aligned in the header bar.\n */\nexport function renderPageNav(currentPage: string, wsProps?: WorkspaceNavProps) {\n const link = (label: string, href: string) =>\n label === currentPage\n ? html`<span class=\"sp-page-nav-current\">${label}</span>`\n : html`<a href=${href}>${label}</a>`;\n\n const links = html`\n ${link(\"Setup\", \"/setup\")}\n ${link(\"Chat\", \"/chat\")}\n ${link(\"Admins\", \"/admins\")}\n ${link(\"Contacts\", \"/contacts\")}\n ${link(\"Files\", \"/files\")}\n ${link(\"Browser\", \"/browser\")}\n ${link(\"Advanced\", \"/advanced\")}\n `;\n\n // Account-PIN sessions (not master) see only their workspace — hide selector\n const showSelector = wsProps && (wsProps.isMaster !== false || !wsProps.hasPins);\n const selectorEl = showSelector\n ? renderWorkspaceSelector(wsProps!)\n : nothing;\n\n const logoutEl = wsProps?.hasPins && wsProps.onLogout\n ? html`<button class=\"nav-logout-btn\" @click=${wsProps.onLogout} title=\"Lock\">${lockIcon}</button>`\n : nothing;\n\n const restartEl = wsProps?.onRestartGateway\n ? renderRestartButton(wsProps.onRestartGateway)\n : nothing;\n\n const auditCount = wsProps?.auditCount ?? 0;\n const auditEl = auditCount > 0 && wsProps?.onAuditClick\n ? html`<button class=\"nav-audit-btn\" @click=${wsProps.onAuditClick} title=\"Memory writes to review\">\n ${bellIcon}\n <span class=\"nav-audit-badge\">${auditCount > 99 ? \"99+\" : auditCount}</span>\n </button>`\n : nothing;\n\n const closeBurger = () => {\n const cb = document.getElementById(\"nav-burger-toggle\") as HTMLInputElement | null;\n if (cb) cb.checked = false;\n };\n\n // Close burger menu when clicking outside the header (once per page)\n ensureBurgerOutsideClickListener();\n\n return html`\n <div class=\"setup-header\">\n <input type=\"checkbox\" id=\"nav-burger-toggle\" class=\"nav-burger-checkbox\" />\n <div class=\"setup-header-inner\">\n <img class=\"setup-header-logo\" src=\"${(wsProps?.selectedWorkspace && getWorkspaceBrands()[wsProps.selectedWorkspace]?.logoUrl) || resolveBrand().iconUrl}\" alt=\"${resolveBrand().name}\" />\n <nav class=\"setup-header-nav\">\n ${links}\n </nav>\n <div class=\"setup-header-right\">\n ${selectorEl !== nothing\n ? html`<span class=\"nav-selector-inline\">${selectorEl}</span>`\n : nothing}\n ${auditEl}\n ${logoutEl}\n ${restartEl}\n <label for=\"nav-burger-toggle\" class=\"nav-burger-button\" aria-label=\"Toggle menu\">\n <span class=\"nav-burger-icon\"></span>\n </label>\n </div>\n </div>\n <nav class=\"setup-header-dropdown\" @click=${closeBurger}>\n ${selectorEl !== nothing\n ? html`<div class=\"nav-selector-mobile\">${selectorEl}</div>`\n : nothing}\n ${links}\n </nav>\n </div>\n `;\n}\n\nfunction renderRestartButton(onRestart: () => void) {\n let confirmOpen = false;\n\n const handleClick = (e: Event) => {\n const btn = (e.currentTarget as HTMLElement);\n const container = btn.closest(\".nav-restart-container\") as HTMLElement;\n if (!container) return;\n const modal = container.querySelector(\".nav-restart-confirm\") as HTMLElement;\n if (!modal) return;\n confirmOpen = !confirmOpen;\n modal.style.display = confirmOpen ? \"flex\" : \"none\";\n };\n\n const handleConfirm = (e: Event) => {\n const container = (e.currentTarget as HTMLElement).closest(\".nav-restart-container\") as HTMLElement;\n const modal = container?.querySelector(\".nav-restart-confirm\") as HTMLElement;\n if (modal) modal.style.display = \"none\";\n confirmOpen = false;\n onRestart();\n };\n\n const handleCancel = (e: Event) => {\n const container = (e.currentTarget as HTMLElement).closest(\".nav-restart-container\") as HTMLElement;\n const modal = container?.querySelector(\".nav-restart-confirm\") as HTMLElement;\n if (modal) modal.style.display = \"none\";\n confirmOpen = false;\n };\n\n return html`\n <span class=\"nav-restart-container\" style=\"position: relative;\">\n <button class=\"nav-restart-btn\" @click=${handleClick} title=\"Restart gateway\">\n ${powerIcon}\n </button>\n <div class=\"nav-restart-confirm\" style=\"display: none;\">\n <p>Restart the gateway?</p>\n <div class=\"nav-restart-confirm-actions\">\n <button class=\"nav-restart-confirm-yes\" @click=${handleConfirm}>Restart</button>\n <button class=\"nav-restart-confirm-no\" @click=${handleCancel}>Cancel</button>\n </div>\n </div>\n </span>\n `;\n}\n\nfunction renderWorkspaceSelector(wsProps: WorkspaceNavProps) {\n const { workspaces, selectedWorkspace, onWorkspaceSelect } = wsProps;\n\n const handleChange = (e: Event) => {\n const select = e.target as HTMLSelectElement;\n const value = select.value;\n if (value === \"__add__\") {\n // Reset dropdown back to current selection\n select.value = selectedWorkspace ?? \"\";\n if (wsProps.onAddAccount) {\n wsProps.onAddAccount();\n } else {\n window.location.href = \"/setup\";\n }\n return;\n }\n onWorkspaceSelect(value);\n };\n\n return html`\n <select\n class=\"sp-workspace-selector\"\n .value=${selectedWorkspace ?? \"\"}\n @change=${handleChange}\n >\n ${workspaces.map(\n (ws) => html`\n <option value=${ws.name} ?selected=${ws.name === selectedWorkspace}>\n ${ws.displayName ?? ws.name}\n </option>\n `,\n )}\n <option disabled>───</option>\n <option value=\"__add__\">+ Add Account</option>\n </select>\n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { icons } from \"../icons\";\nimport { renderPageNav } from \"./page-nav\";\n\nexport type BrowserViewerProps = {\n connected: boolean;\n active: boolean;\n loading: boolean;\n error: string | null;\n inputMode: boolean;\n fullscreen: boolean;\n handoffPending: boolean;\n handoffReason: string | null;\n onStart: () => void;\n onStop: () => void;\n onToggleInput: () => void;\n onToggleFullscreen: () => void;\n onCompleteHandoff: () => void;\n onCanvasMouseDown: (e: MouseEvent) => void;\n onCanvasMouseUp: (e: MouseEvent) => void;\n onCanvasMouseMove: (e: MouseEvent) => void;\n onCanvasKeyDown: (e: KeyboardEvent) => void;\n onCanvasKeyUp: (e: KeyboardEvent) => void;\n};\n\nexport function renderBrowserViewer(props: BrowserViewerProps) {\n if (!props.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting to gateway...</p>\n </div>\n </div>\n `;\n }\n\n if (props.fullscreen && props.active) {\n return html`\n <div class=\"sp-fullscreen-overlay\">\n <div class=\"sp-fullscreen-toolbar\">\n <button\n class=\"setup-button ${props.inputMode ? \"primary\" : \"secondary\"}\"\n style=\"padding: 6px 14px; font-size: 13px;\"\n @click=${props.onToggleInput}\n >\n ${props.inputMode ? \"Input: ON\" : \"Input: OFF\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"padding: 6px 14px; font-size: 13px;\"\n @click=${props.onToggleFullscreen}\n >\n Exit Fullscreen\n </button>\n <button\n class=\"setup-button danger\"\n style=\"padding: 6px 14px; font-size: 13px;\"\n ?disabled=${props.loading}\n @click=${props.onStop}\n >\n Stop\n </button>\n </div>\n <div class=\"sp-fullscreen-canvas-wrap ${props.inputMode ? \"sp-input-active\" : \"\"}\">\n <canvas\n id=\"browser-screencast-canvas\"\n class=\"sp-canvas sp-canvas-fullscreen\"\n tabindex=\"0\"\n @mousedown=${(e: MouseEvent) => props.onCanvasMouseDown(e)}\n @mouseup=${(e: MouseEvent) => props.onCanvasMouseUp(e)}\n @mousemove=${(e: MouseEvent) => props.onCanvasMouseMove(e)}\n @keydown=${(e: KeyboardEvent) => {\n e.preventDefault();\n props.onCanvasKeyDown(e);\n }}\n @keyup=${(e: KeyboardEvent) => {\n e.preventDefault();\n props.onCanvasKeyUp(e);\n }}\n @contextmenu=${(e: Event) => e.preventDefault()}\n ></canvas>\n </div>\n </div>\n `;\n }\n\n return html`\n <div class=\"setup-container\">\n ${renderPageNav(\"Browser\")}\n <div class=\"setup-card sp-card-wide\">\n <h1>Remote Browser</h1>\n <p style=\"margin-bottom: 16px;\">Live view of the headless Chrome instance.</p>\n\n <div class=\"sp-toolbar\">\n ${props.active\n ? html`\n <button\n class=\"setup-button ${props.inputMode ? \"primary\" : \"secondary\"}\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n @click=${props.onToggleInput}\n >\n ${props.inputMode ? \"Input: ON\" : \"Input: OFF\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n @click=${props.onToggleFullscreen}\n >\n Fullscreen\n </button>\n <button\n class=\"setup-button danger\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n ?disabled=${props.loading}\n @click=${props.onStop}\n >\n Stop\n </button>\n `\n : html`\n <button\n class=\"setup-button primary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n ?disabled=${props.loading}\n @click=${props.onStart}\n >\n ${props.loading ? \"Starting...\" : \"Start\"}\n </button>\n `}\n </div>\n\n ${props.error\n ? html`<div class=\"setup-error\" style=\"margin-top: 16px;\">${props.error}</div>`\n : nothing}\n\n ${props.handoffPending\n ? html`\n <div class=\"setup-warning\" style=\"margin-top: 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px; text-align: left;\">\n <div>\n <strong>Action required:</strong> ${props.handoffReason ?? \"The agent needs you to complete an action in the browser.\"}\n </div>\n <button class=\"setup-button primary\" style=\"flex-shrink: 0; padding: 10px 20px; font-size: 14px;\" @click=${props.onCompleteHandoff}>\n Done\n </button>\n </div>\n `\n : nothing}\n\n <div class=\"sp-canvas-area\" style=\"margin-top: 16px;\">\n ${props.active\n ? html`\n <div class=\"sp-canvas-wrap ${props.inputMode ? \"sp-input-active\" : \"\"}\">\n <canvas\n id=\"browser-screencast-canvas\"\n class=\"sp-canvas\"\n tabindex=\"0\"\n @mousedown=${(e: MouseEvent) => props.onCanvasMouseDown(e)}\n @mouseup=${(e: MouseEvent) => props.onCanvasMouseUp(e)}\n @mousemove=${(e: MouseEvent) => props.onCanvasMouseMove(e)}\n @keydown=${(e: KeyboardEvent) => {\n e.preventDefault();\n props.onCanvasKeyDown(e);\n }}\n @keyup=${(e: KeyboardEvent) => {\n e.preventDefault();\n props.onCanvasKeyUp(e);\n }}\n @contextmenu=${(e: Event) => e.preventDefault()}\n ></canvas>\n </div>\n `\n : html`\n <div class=\"sp-canvas-placeholder\">\n <div class=\"sp-canvas-placeholder-icon\">${icons.globe}</div>\n <p>Click Start to begin streaming the Chrome viewport.</p>\n </div>\n `}\n </div>\n\n ${props.active && props.inputMode\n ? html`<p class=\"setup-hint\" style=\"margin-top: 12px;\">\n Click the canvas to focus, then interact with the browser. Mouse and keyboard input are forwarded.\n </p>`\n : nothing}\n\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { icons } from \"../icons\";\nimport type { FileTreeEntry, MemorySearchHit } from \"../controllers/files\";\nimport { renderPageNav, type WorkspaceNavProps } from \"./page-nav\";\n\n/** Custom MIME type used to identify drags originating from within the file tree. */\nconst INTERNAL_DRAG_MIME = \"application/x-taskmaster-file-path\";\n\n/** Timer for auto-resetting delete confirmation. */\nlet pendingDeleteTimer: ReturnType<typeof setTimeout> | null = null;\n\nexport type FilesProps = {\n connected: boolean;\n wsProps?: WorkspaceNavProps;\n loading: boolean;\n tree: FileTreeEntry[];\n root: string;\n error: string | null;\n selectedPath: string | null;\n selectedPaths: Set<string>;\n previewContent: string | null;\n previewLoading: boolean;\n previewBinary: boolean;\n previewSize: number | null;\n expandedDirs: Set<string>;\n currentDir: string;\n message: { kind: \"success\" | \"error\"; text: string } | null;\n uploadBusy: boolean;\n reindexBusy: boolean;\n memoryStatus: { dirty: boolean; syncing?: boolean; syncProgress?: { completed: number; total: number; label?: string }; files: number; chunks: number; model?: string; embeddingState?: \"idle\" | \"downloading\" | \"ready\" | \"error\" } | null;\n onRefresh: () => void;\n onReindex: () => void;\n onSelectFile: (path: string) => void;\n onToggleSelectFile: (path: string) => void;\n onToggleDir: (path: string) => void;\n onUpload: (dirPath: string, files: File[]) => void;\n onNewFolder: (parentDir: string, name: string) => void;\n onDownload: (path: string) => void;\n onBulkDownload: () => void;\n onDelete: (path: string) => void;\n pendingDeletePath: string | null;\n onArmDelete: (path: string) => void;\n onMoveToDir: (filePath: string, targetDir: string) => void;\n searchQuery: string;\n searchResults: MemorySearchHit[] | null;\n searchLoading: boolean;\n searchAgentId: string | null;\n agentIds: string[];\n onSearch: (query: string) => void;\n onSearchAgentChange: (agentId: string) => void;\n onSearchClear: () => void;\n onSearchQueryChange: (query: string) => void;\n};\n\nfunction formatSize(bytes: number | undefined): string {\n if (bytes === undefined || bytes === null) return \"\";\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/** Return the parent directory of a file path, or \".\" for root-level files. */\nfunction parentDir(filePath: string): string {\n const parts = filePath.split(\"/\");\n return parts.length > 1 ? parts.slice(0, -1).join(\"/\") : \".\";\n}\n\nfunction handleDirDrop(e: DragEvent, dirPath: string, props: FilesProps) {\n e.preventDefault();\n e.stopPropagation();\n (e.currentTarget as HTMLElement).classList.remove(\"sp-drop-target\");\n\n // Internal tree drag — move file into this directory\n const internalPath = e.dataTransfer?.getData(INTERNAL_DRAG_MIME);\n if (internalPath) {\n // Don't move if already in this directory\n if (parentDir(internalPath) !== dirPath) {\n props.onMoveToDir(internalPath, dirPath);\n }\n return;\n }\n\n // External file drop — upload\n const files = e.dataTransfer?.files;\n if (files && files.length > 0) {\n const mdFiles = Array.from(files).filter((f) => f.name.toLowerCase().endsWith(\".md\"));\n if (mdFiles.length > 0) props.onUpload(dirPath, mdFiles);\n }\n}\n\nfunction renderTreeEntry(\n entry: FileTreeEntry,\n props: FilesProps,\n depth: number,\n): unknown {\n const isDir = entry.type === \"directory\" || (entry.type === \"symlink\" && entry.children != null);\n const isExpanded = props.expandedDirs.has(entry.path);\n const isSelected = props.selectedPaths.has(entry.path);\n const isCurrent = props.currentDir === entry.path;\n const indent = depth * 20 + 12;\n\n if (isDir) {\n return html`\n <div\n class=\"sp-tree-item sp-tree-dir ${isExpanded ? \"expanded\" : \"\"} ${isCurrent ? \"current\" : \"\"}\"\n style=\"padding-left: ${indent}px;\"\n @click=${() => props.onToggleDir(entry.path)}\n @dragover=${(e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) e.dataTransfer.dropEffect = \"move\";\n (e.currentTarget as HTMLElement).classList.add(\"sp-drop-target\");\n }}\n @dragleave=${(e: DragEvent) => {\n (e.currentTarget as HTMLElement).classList.remove(\"sp-drop-target\");\n }}\n @drop=${(e: DragEvent) => handleDirDrop(e, entry.path, props)}\n >\n <span class=\"sp-tree-chevron\">${isExpanded ? \"−\" : \"+\"}</span>\n <span class=\"sp-tree-icon\">${icons.folder}</span>\n <span class=\"sp-tree-name\">${entry.name}</span>\n ${isExpanded && entry.children?.length === 0\n ? html`<span\n class=\"sp-tree-dir-delete\"\n title=\"Delete empty folder\"\n @click=${(e: MouseEvent) => {\n e.stopPropagation();\n props.onDelete(entry.path);\n }}\n >×</span>`\n : nothing}\n </div>\n ${isExpanded && entry.children\n ? entry.children.map((child) => renderTreeEntry(child, props, depth + 1))\n : nothing}\n `;\n }\n\n return html`\n <div\n class=\"sp-tree-item sp-tree-file ${isSelected ? \"selected\" : \"\"}\"\n style=\"padding-left: ${indent}px;\"\n draggable=\"true\"\n @click=${(e: MouseEvent) => {\n if (e.metaKey || e.ctrlKey) {\n props.onToggleSelectFile(entry.path);\n } else {\n props.onSelectFile(entry.path);\n }\n }}\n @dragstart=${(e: DragEvent) => {\n if (!e.dataTransfer) return;\n e.dataTransfer.effectAllowed = \"move\";\n e.dataTransfer.setData(INTERNAL_DRAG_MIME, entry.path);\n e.dataTransfer.setData(\"text/plain\", entry.name);\n }}\n >\n <span class=\"sp-tree-icon\">${icons.fileText}</span>\n <span class=\"sp-tree-name\">${entry.name}</span>\n <span class=\"sp-tree-size\">${formatSize(entry.size)}</span>\n </div>\n `;\n}\n\nfunction renderBulkActions(props: FilesProps) {\n const count = props.selectedPaths.size;\n if (count < 2) return nothing;\n\n return html`\n <div class=\"sp-bulk-actions\">\n <span style=\"color: var(--tasker-muted-grey); font-size: 13px;\">${count} files selected</span>\n <button\n class=\"setup-button secondary\"\n style=\"padding: 8px 16px; font-size: 13px;\"\n @click=${props.onBulkDownload}\n >\n Download ${count} files\n </button>\n </div>\n `;\n}\n\nfunction renderPreview(props: FilesProps) {\n // Hide preview when multiple files are selected\n if (props.selectedPaths.size !== 1) return nothing;\n if (!props.selectedPath) return nothing;\n\n if (props.previewLoading) {\n return html`\n <div class=\"sp-file-preview\">\n <div class=\"setup-spinner\" style=\"width: 32px; height: 32px; margin: 24px auto;\"></div>\n </div>\n `;\n }\n\n const fileName = props.selectedPath.split(\"/\").pop() ?? props.selectedPath;\n\n return html`\n <div class=\"sp-file-preview\">\n <div class=\"sp-file-preview-header\">\n <div>\n <strong>${fileName}</strong>\n <div class=\"sp-file-preview-meta\">\n ${props.selectedPath}${props.previewSize != null ? ` — ${formatSize(props.previewSize)}` : \"\"}\n </div>\n </div>\n <div class=\"sp-file-actions\">\n <button class=\"setup-button secondary\" style=\"padding: 8px 16px; font-size: 13px;\" @click=${() => props.onDownload(props.selectedPath!)}>\n Download\n </button>\n <button class=\"setup-button danger\" style=\"padding: 8px 16px; font-size: 13px;\" @click=${() => {\n if (props.pendingDeletePath === props.selectedPath) {\n // Second click — confirmed\n if (pendingDeleteTimer) clearTimeout(pendingDeleteTimer);\n pendingDeleteTimer = null;\n props.onDelete(props.selectedPath!);\n } else {\n // First click — arm confirmation, auto-resets after 3s\n props.onArmDelete(props.selectedPath!);\n if (pendingDeleteTimer) clearTimeout(pendingDeleteTimer);\n pendingDeleteTimer = setTimeout(() => {\n props.onArmDelete(\"\");\n pendingDeleteTimer = null;\n }, 3000);\n }\n }}>\n ${props.pendingDeletePath === props.selectedPath ? \"Confirm delete?\" : \"Delete\"}\n </button>\n </div>\n </div>\n ${props.previewBinary\n ? html`<div class=\"sp-file-preview-body\"><p style=\"color: var(--tasker-muted-grey);\">Binary file — use Download to view.</p></div>`\n : props.previewContent != null\n ? html`<div class=\"sp-file-preview-body\"><pre class=\"sp-file-code\">${props.previewContent}</pre></div>`\n : html`<div class=\"sp-file-preview-body\"><p style=\"color: var(--tasker-muted-grey);\">File too large for preview — use Download.</p></div>`}\n </div>\n `;\n}\n\n/** Recursively compute total file count and total bytes from the file tree. */\nfunction computeTreeStats(entries: FileTreeEntry[]): { count: number; bytes: number } {\n let count = 0;\n let bytes = 0;\n for (const entry of entries) {\n if (entry.children) {\n const sub = computeTreeStats(entry.children);\n count += sub.count;\n bytes += sub.bytes;\n } else {\n count++;\n bytes += entry.size ?? 0;\n }\n }\n return { count, bytes };\n}\n\nfunction renderSearchBar(props: FilesProps) {\n return html`\n <div class=\"sp-search-bar\">\n <input\n type=\"text\"\n class=\"sp-search-input\"\n placeholder=\"Search memory...\"\n .value=${props.searchQuery}\n @input=${(e: Event) => props.onSearchQueryChange((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") props.onSearch(props.searchQuery);\n }}\n />\n ${props.agentIds.length > 1\n ? html`<select\n class=\"sp-search-agent-select\"\n @change=${(e: Event) => props.onSearchAgentChange((e.target as HTMLSelectElement).value)}\n >\n ${props.agentIds.map(\n (id) => html`<option value=${id} ?selected=${id === props.searchAgentId}>${id}</option>`,\n )}\n </select>`\n : nothing}\n <button\n class=\"setup-button secondary\"\n style=\"padding: 8px 16px; font-size: 13px;\"\n ?disabled=${props.searchLoading || !props.searchQuery.trim()}\n @click=${() => props.onSearch(props.searchQuery)}\n >\n ${props.searchLoading ? \"Searching...\" : \"Search\"}\n </button>\n ${props.searchResults !== null\n ? html`<button\n class=\"setup-button secondary\"\n style=\"padding: 8px 16px; font-size: 13px;\"\n @click=${props.onSearchClear}\n >\n Clear\n </button>`\n : nothing}\n </div>\n `;\n}\n\nfunction renderSearchResults(props: FilesProps) {\n if (!props.searchResults) return nothing;\n\n if (props.searchResults.length === 0) {\n return html`<div class=\"sp-search-results\">\n <div style=\"padding: 24px; color: var(--tasker-muted-grey); text-align: center;\">No results found.</div>\n </div>`;\n }\n\n return html`\n <div class=\"sp-search-results\">\n ${props.searchResults.map(\n (r) => html`\n <div\n class=\"sp-search-result ${props.selectedPath === r.path ? \"selected\" : \"\"}\"\n @click=${() => props.onSelectFile(r.path)}\n >\n <div class=\"sp-search-result-header\">\n <span class=\"sp-search-result-path\">${r.path}</span>\n <span class=\"sp-search-result-score\">${(r.score * 100).toFixed(0)}%</span>\n </div>\n <div class=\"sp-search-result-meta\">\n Lines ${r.startLine}\\u2013${r.endLine} \\u00b7 ${r.source}\n </div>\n <pre class=\"sp-search-result-snippet\">${r.snippet}</pre>\n </div>\n `,\n )}\n </div>\n `;\n}\n\nexport function renderFiles(props: FilesProps) {\n const uploadTarget = props.currentDir;\n\n if (!props.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting to gateway...</p>\n </div>\n </div>\n `;\n }\n\n return html`\n <div class=\"setup-container\">\n ${renderPageNav(\"Files\", props.wsProps)}\n <div class=\"setup-card sp-card-wide\">\n <h1>Workspace Files</h1>\n <p style=\"margin-bottom: 16px;\">Browse, upload, and manage files in your workspace. Drag files between folders to move them.</p>\n\n <div class=\"sp-toolbar\">\n <label class=\"setup-button secondary\" style=\"padding: 10px 20px; font-size: 14px; cursor: pointer;\">\n Upload${uploadTarget !== \".\" ? html` to <em>${uploadTarget}</em>` : nothing}\n <input\n type=\"file\"\n multiple\n accept=\".md\"\n style=\"display: none;\"\n @change=${(e: Event) => {\n const input = e.target as HTMLInputElement;\n if (input.files && input.files.length > 0) {\n props.onUpload(uploadTarget, Array.from(input.files));\n input.value = \"\";\n }\n }}\n />\n </label>\n <button\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n @click=${() => {\n const name = prompt(\"Folder name:\");\n if (name?.trim()) props.onNewFolder(uploadTarget, name.trim());\n }}\n >\n New Folder${uploadTarget !== \".\" ? html` in <em>${uploadTarget}</em>` : nothing}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n ?disabled=${props.loading}\n @click=${props.onRefresh}\n >\n ${props.loading ? \"Loading...\" : \"Refresh\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n ?disabled=${props.reindexBusy}\n @click=${props.onReindex}\n >\n ${props.reindexBusy ? \"Re-indexing...\" : \"Re-index\"}\n </button>\n ${props.memoryStatus\n ? props.memoryStatus.embeddingState === \"downloading\"\n ? html`<span style=\"display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--tasker-orange, #f59e0b);\">\n <span\n class=\"setup-status-light\"\n style=\"width: 10px; height: 10px; background: #f59e0b\"\n ></span>\n Downloading embedding model\\u2026\n </span>`\n : html`<span style=\"display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--tasker-text-grey);\">\n <span\n class=\"setup-status-light\"\n style=\"width: 10px; height: 10px; background: ${props.memoryStatus.syncing ? \"#f59e0b\" : props.memoryStatus.dirty ? \"#ef4444\" : \"#22c55e\"}\"\n ></span>\n ${(() => {\n // Show sync progress when indexing\n if (props.memoryStatus!.syncing && props.memoryStatus!.syncProgress) {\n const { completed, total, label } = props.memoryStatus!.syncProgress;\n if (label) return label;\n return total > 0 ? `Indexing ${completed}/${total} files\\u2026` : \"Indexing\\u2026\";\n }\n const indexed = props.memoryStatus!.files;\n const chunks = props.memoryStatus!.chunks;\n const filePart = `${indexed} file${indexed !== 1 ? \"s\" : \"\"}, ${chunks} chunks`;\n const model = props.memoryStatus?.model;\n if (!model) return filePart;\n // Extract friendly name: \"hf:ggml-org/embeddinggemma-300M-Q8_0-GGUF/...\" → \"embeddinggemma-300M\"\n const filename = model.includes(\"/\") ? model.split(\"/\").pop()! : model;\n const friendly = filename.replace(/[-_]Q\\d.*$/i, \"\").replace(/\\.gguf$/i, \"\");\n return `${filePart} · ${friendly}`;\n })()}\n </span>`\n : nothing}\n </div>\n\n ${props.error\n ? html`<div class=\"setup-error\" style=\"margin-top: 16px;\">${props.error}</div>`\n : nothing}\n\n ${props.message\n ? html`<div class=\"${props.message.kind === \"error\" ? \"setup-error\" : \"setup-success-message\"}\" style=\"margin-top: 12px;\">\n ${props.message.text}\n </div>`\n : nothing}\n\n ${props.uploadBusy\n ? html`<div style=\"margin-top: 12px; color: var(--tasker-orange); font-weight: 600; font-size: 14px;\">Uploading...</div>`\n : nothing}\n\n ${renderSearchBar(props)}\n\n ${props.searchResults !== null\n ? renderSearchResults(props)\n : html`<div\n class=\"sp-file-tree\"\n @dragover=${(e: DragEvent) => {\n e.preventDefault();\n if (e.dataTransfer) e.dataTransfer.dropEffect = e.dataTransfer.types.includes(INTERNAL_DRAG_MIME) ? \"move\" : \"copy\";\n }}\n @drop=${(e: DragEvent) => {\n e.preventDefault();\n // Internal drag to root — move file to workspace root\n const internalPath = e.dataTransfer?.getData(INTERNAL_DRAG_MIME);\n if (internalPath) {\n if (parentDir(internalPath) !== \".\") {\n props.onMoveToDir(internalPath, \".\");\n }\n return;\n }\n // External file drop — upload\n const files = e.dataTransfer?.files;\n if (files && files.length > 0) {\n const mdFiles = Array.from(files).filter((f) => f.name.toLowerCase().endsWith(\".md\"));\n if (mdFiles.length > 0) props.onUpload(uploadTarget, mdFiles);\n }\n }}\n >\n ${props.tree.length === 0 && !props.loading\n ? html`<div style=\"padding: 24px; color: var(--tasker-muted-grey); text-align: center;\">No files found. Drop .md files here to upload.</div>`\n : props.tree.map((entry) => renderTreeEntry(entry, props, 0))}\n </div>`}\n\n ${renderBulkActions(props)}\n ${renderPreview(props)}\n </div>\n </div>\n `;\n}\n","/**\n * Uninstall controller for the setup page.\n *\n * Calls system.uninstall RPC then handles the expected disconnect\n * (the gateway exits after removing itself).\n *\n * Uses localStorage to persist the \"done\" state across the WebSocket\n * disconnect that inevitably follows — the gateway exits after\n * uninstalling, so the UI loses connection before it can render the\n * done message from reactive state alone.\n */\n\nconst UNINSTALL_DONE_KEY = \"taskmaster_uninstall_done\";\n\nexport interface UninstallState {\n client: { request: (method: string, params: unknown) => Promise<unknown> } | null;\n connected: boolean;\n uninstallConfirm: boolean;\n uninstallBusy: boolean;\n uninstallDone: boolean;\n uninstallError: string | null;\n uninstallConfirmText: string;\n requestUpdate?: () => void;\n}\n\nexport async function runUninstall(state: UninstallState): Promise<void> {\n if (!state.client || !state.connected) return;\n if (state.uninstallBusy) return;\n\n state.uninstallBusy = true;\n state.uninstallError = null;\n state.requestUpdate?.();\n\n // Persist before the RPC — the gateway will exit and we'll lose the WebSocket\n markUninstallDone();\n\n try {\n await state.client.request(\"system.uninstall\", {\n scopes: [\"service\", \"state\", \"workspace\"],\n purge: true,\n });\n } catch {\n // Expected: WebSocket closes because the gateway exited.\n }\n\n state.uninstallBusy = false;\n state.uninstallDone = true;\n state.requestUpdate?.();\n}\n\nexport function checkUninstallDone(): boolean {\n try {\n return localStorage.getItem(UNINSTALL_DONE_KEY) === \"1\";\n } catch {\n return false;\n }\n}\n\nexport function clearUninstallDone(): void {\n try {\n localStorage.removeItem(UNINSTALL_DONE_KEY);\n } catch { /* ignore */ }\n}\n\nfunction markUninstallDone(): void {\n try {\n localStorage.setItem(UNINSTALL_DONE_KEY, \"1\");\n } catch { /* ignore */ }\n}\n","import { html, nothing } from \"lit\";\nimport { icons } from \"../icons.js\";\nimport type { ChannelAccountSnapshot } from \"../types\";\nimport type { WorkspaceInfo } from \"../controllers/workspaces\";\nimport type { UpdateProgressStep, UpdateLastResult } from \"../controllers/update\";\nimport { checkUninstallDone, clearUninstallDone } from \"../controllers/uninstall\";\nimport { renderPageNav, type WorkspaceNavProps } from \"./page-nav\";\nimport { resolveBrand } from \"../brand\";\n\nexport type SetupStep = \"license\" | \"auth\" | \"setup\";\n\nexport interface WhatsAppChannelStatus {\n running: boolean;\n connected: boolean;\n linked: boolean;\n lastError?: string | null;\n}\n\nexport interface SetupViewState {\n connected: boolean;\n /** Server OS platform (e.g. \"darwin\", \"linux\") from hello-ok. */\n serverPlatform: string | null;\n assistantName: string;\n // Current setup step\n currentStep: SetupStep;\n // License state\n licenseKey: string;\n licenseBusy: boolean;\n licenseValid: boolean | null;\n licenseMessage: string | null;\n licenseTier: string | null;\n licenseDeviceId: string | null;\n licenseStoredKey: string | null;\n onLicenseKeyChange: (key: string) => void;\n onLicenseActivate: () => void;\n onLicenseRemove: () => void;\n licenseRemoveConfirm: boolean;\n onLicenseRemoveConfirm: () => void;\n onLicenseRemoveCancel: () => void;\n // Auth state\n authConnected: boolean | null;\n authBusy: boolean;\n authMessage: string | null;\n authUrl: string | null;\n authCodeInput: string;\n authExpiresIn: number | null;\n authRefreshToken: string | null;\n // Claude auth modal\n claudeAuthModalOpen: boolean;\n authRefreshTokenInput: string;\n authRefreshTokenBusy: boolean;\n authRefreshTokenError: string | null;\n onClaudeAuthModalOpen: () => void;\n onClaudeAuthModalClose: () => void;\n onRefreshTokenInputChange: (value: string) => void;\n onImportRefreshToken: () => void;\n // WhatsApp login flow state\n whatsappBusy: boolean;\n whatsappLoginMessage: string | null;\n whatsappLoginQrDataUrl: string | null;\n whatsappLoginConnected: boolean | null;\n // Real WhatsApp channel status from channels.status\n whatsappChannelStatus: WhatsAppChannelStatus | null;\n // Multi-account WhatsApp\n whatsappAccounts: ChannelAccountSnapshot[];\n whatsappActiveQrAccountId: string | null;\n whatsappAccountSaving: boolean;\n // Gateway status\n gatewayHealthy: boolean | null;\n gatewayHealthLoading: boolean;\n gatewayHealthMessage: string | null;\n gatewayRestartBusy: boolean;\n // Callbacks\n onStartAuth: () => void;\n onSubmitAuthCode: (code: string) => void;\n onAuthCodeChange: (code: string) => void;\n onWhatsAppRelink: (accountId?: string) => void;\n onWhatsAppReset: (accountId?: string) => void;\n onWhatsAppUnlink: (accountId?: string) => void;\n onRefreshStatus: () => void;\n onRefreshGatewayStatus: () => void;\n onRefreshWhatsAppStatus: () => void;\n onWhatsAppBack: () => void;\n onRestartGateway: () => void;\n onRemoveWhatsAppAccount: (accountId: string) => void;\n // Workspaces\n workspaces: WorkspaceInfo[];\n workspacesLoading: boolean;\n workspacesError: string | null;\n addingWorkspace: boolean;\n newWorkspaceName: string;\n newWorkspacePath: string;\n workspaceSaving: boolean;\n workspaceRemoveConfirm: string | null;\n onWorkspaceCreate: (name: string, workspacePath?: string) => void;\n onWorkspaceRemove: (name: string) => void;\n onSetAddingWorkspace: (adding: boolean) => void;\n onSetNewWorkspaceName: (name: string) => void;\n onSetNewWorkspacePath: (path: string) => void;\n onSetWorkspaceRemoveConfirm: (name: string | null) => void;\n // Workspace rename\n renamingWorkspace: boolean;\n renameWorkspaceName: string;\n onWorkspaceRenameStart: () => void;\n onWorkspaceRenameCancel: () => void;\n onWorkspaceRename: (name: string, displayName: string) => void;\n // Account PIN\n newWorkspacePin: string;\n onSetNewWorkspacePin: (pin: string) => void;\n // Account PIN management (on the setup dashboard)\n accountHasPin: boolean;\n accountPinModalOpen: boolean;\n accountPinBusy: boolean;\n accountPinError: string | null;\n accountPinSuccess: string | null;\n onAccountPinModalOpen: () => void;\n onAccountPinModalClose: () => void;\n onAccountPinSave: (oldPin: string | null, newPin: string) => void;\n // iMessage state\n imessageConfigured: boolean;\n imessageRunning: boolean;\n imessageConnected: boolean;\n imessageLastError: string | null;\n imessageSelfChatMode: boolean;\n imessageCliPath: string | null;\n imessageEnabling: boolean;\n imessageEnableConfirm: boolean;\n /** Name of the workspace that currently owns iMessage (has bindings), or null */\n imessageOwnerWorkspace: string | null;\n onIMessageEnable: () => void;\n onIMessageEnableConfirm: () => void;\n onIMessageEnableCancel: () => void;\n onIMessageProbe: () => void;\n /** Reassign iMessage to the currently selected workspace (removes old bindings, creates new) */\n onIMessageReassign: () => void;\n /** Disconnect iMessage from the currently selected workspace (removes bindings, disables channel) */\n onIMessageDisconnect: () => void;\n // WhatsApp DM policy\n whatsappDmPolicy: string | null;\n /** Toggle WhatsApp public DM handling on/off */\n onWhatsAppDmToggle: () => void;\n // WhatsApp group chat\n whatsappGroupPolicy: \"open\" | \"disabled\" | \"allowlist\" | null;\n whatsappGroupRequireMention: boolean;\n onWhatsAppGroupToggle: () => void;\n onWhatsAppGroupMentionChange: (requireMention: boolean) => void;\n // WhatsApp settings modal\n whatsappSettingsOpen: boolean;\n onWhatsAppSettingsOpen: () => void;\n onWhatsAppSettingsClose: () => void;\n // API Keys management (global, admin-only)\n isMaster: boolean;\n apiKeyProviders: Array<{ id: string; name: string; category: string; hasKey: boolean; disabled: boolean; key?: string; primary?: boolean }>;\n apiKeyModalOpen: boolean;\n apiKeyBusy: boolean;\n apiKeyError: string | null;\n apiKeySuccess: string | null;\n apiKeySavingProvider: string | null;\n onApiKeyModalOpen: () => void;\n onApiKeyModalClose: () => void;\n onApiKeySave: (provider: string, apiKey: string) => void;\n onApiKeyRemove: (provider: string) => void;\n onApiKeyDisable: (provider: string, disabled: boolean) => void;\n // Auth step API key fallback\n authApiKeyMode: boolean;\n authApiKeyInput: string;\n authApiKeyBusy: boolean;\n authApiKeyError: string | null;\n onAuthApiKeyToggle: () => void;\n onAuthApiKeyChange: (key: string) => void;\n onAuthApiKeySubmit: () => void;\n // Software update\n updateAvailable: boolean | null;\n currentVersion: string | null;\n latestVersion: string | null;\n updateChecking: boolean;\n updateRunning: boolean;\n updateMessage: string | null;\n updateProgressSteps: UpdateProgressStep[];\n updateLastResult: UpdateLastResult | null;\n onUpdateCheck: () => void;\n onUpdateRun: () => void;\n onUpdateDismissResult: () => void;\n // Uninstall\n uninstallConfirm: boolean;\n uninstallBusy: boolean;\n uninstallDone: boolean;\n uninstallError: string | null;\n uninstallConfirmText: string;\n onUninstallConfirm: () => void;\n onUninstallCancel: () => void;\n onUninstallConfirmTextChange: (text: string) => void;\n onUninstallRun: () => void;\n onUninstallDismiss: () => void;\n // Public Chat toggle\n publicChatEnabled: boolean;\n publicChatAuthMode: \"anonymous\" | \"verified\" | \"choice\";\n publicChatBusy: boolean;\n onPublicChatToggle: () => void;\n onPublicChatAuthModeChange: (mode: \"anonymous\" | \"verified\" | \"choice\") => void;\n // Public Chat settings modal\n publicChatAccountId: string | null;\n publicChatSettingsOpen: boolean;\n onPublicChatSettingsOpen: () => void;\n onPublicChatSettingsClose: () => void;\n // Public Chat widget snippet modal\n publicChatWidgetModalOpen: boolean;\n onPublicChatWidgetModalOpen: () => void;\n onPublicChatWidgetModalClose: () => void;\n // Public Chat greeting\n publicChatGreeting: string;\n publicChatGreetingBusy: boolean;\n onPublicChatGreetingToggle: () => void;\n onPublicChatGreetingSave: (text: string) => void;\n onPublicChatGreetingRegenerate: () => void;\n // Public Chat email verification (auto-saved on blur / checkbox change)\n publicChatEmailFrom: string;\n publicChatEmailBusy: boolean;\n publicChatVerifyMethods: string[];\n onPublicChatEmailSave: (from: string, verifyMethods: string[]) => void;\n // Agent Settings (model + thinking per agent)\n agentSettingsOpen: boolean;\n agentSettingsAgents: Array<{\n id: string;\n label: string;\n model: string | null;\n thinkingLevel: string | null;\n }>;\n agentSettingsModelCatalog: Array<{ id: string; name: string; provider: string; reasoning?: boolean }>;\n onAgentSettingsToggle: () => void;\n onAgentModelChange: (agentId: string, modelRef: string) => void;\n onAgentThinkingChange: (agentId: string, level: string) => void;\n memoryProvider: string;\n memoryFallback: string;\n onMemoryProviderChange: (provider: string) => void;\n onMemoryFallbackChange: (fallback: string) => void;\n // Branding (per-workspace)\n brandAccentColor: string;\n brandBackgroundColor: string;\n brandHasLogo: boolean;\n brandingBusy: boolean;\n brandingExpanded: boolean;\n onBrandingToggle: () => void;\n onBrandAccentColorChange: (color: string) => void;\n onBrandBackgroundColorChange: (color: string) => void;\n onBrandLogoUpload: (file: File) => void;\n onBrandLogoRemove: () => void;\n onBrandReset: () => void;\n // Tailscale / Remote Access / Internet Access (admin-only)\n tailscaleStatus: {\n installed: boolean;\n running: boolean;\n loggedIn: boolean;\n hostname: string | null;\n serveEnabled: boolean;\n serveActive: boolean;\n tailnetUrl: string | null;\n funnelEnabled: boolean;\n funnelActive: boolean;\n publicUrl: string | null;\n } | null;\n tailscaleBusy: boolean;\n tailscaleAuthUrl: string | null;\n tailscaleError: string | null;\n tailscaleServeEnableUrl: string | null;\n tailscaleFunnelEnableUrl: string | null;\n tailscaleDisableConfirm: boolean;\n tailscaleConnectProgress: number;\n tailscaleConnectMessage: string;\n tailscaleConnectSuccess: boolean;\n onTailscaleEnable: () => void;\n onTailscaleErrorDismiss: () => void;\n onTailscaleServeEnable: () => void;\n onTailscaleServeDisable: () => void;\n onTailscaleFunnelEnable: () => void;\n onTailscaleFunnelDisable: () => void;\n onTailscaleDisableConfirmToggle: () => void;\n // WiFi management (Linux only)\n wifiStatus: {\n available: boolean;\n connected: boolean;\n ssid: string | null;\n signal: number | null;\n ip: string | null;\n savedSsid: string | null;\n autoconnect: boolean;\n } | null;\n wifiNetworks: Array<{\n ssid: string;\n signal: number;\n security: string;\n active: boolean;\n }>;\n wifiBusy: boolean;\n wifiError: string | null;\n wifiPassword: string;\n wifiSelectedSsid: string | null;\n onWifiScan: () => void;\n onWifiConnect: () => void;\n onWifiDisconnect: () => void;\n onWifiForget: () => void;\n onWifiDismiss: () => void;\n onWifiSelectSsid: (ssid: string | null) => void;\n onWifiPasswordChange: (password: string) => void;\n // Network settings (port + hostname, modal pattern)\n networkPort: number | null;\n networkHostname: string;\n networkPortInput: string;\n networkHostnameInput: string;\n networkModalOpen: boolean;\n networkBusy: boolean;\n networkError: string | null;\n networkSuccess: string | null;\n onNetworkModalToggle: () => void;\n onNetworkPortChange: (port: string) => void;\n onNetworkHostnameChange: (hostname: string) => void;\n onNetworkSave: () => void;\n // WiFi modal\n wifiModalOpen: boolean;\n onWifiModalToggle: () => void;\n // Info modals\n infoModalOpen: string | null;\n onInfoModalOpen: (id: string) => void;\n onInfoModalClose: () => void;\n // QR code data URLs (fetched lazily when info modals open)\n remoteAccessQrDataUrl: string | null;\n publicChatQrDataUrl: string | null;\n publicChatFullUrl: string | null;\n // Workspace nav props (for the account selector in the header)\n wsProps?: WorkspaceNavProps;\n}\n\n/** Status indicator light - green for good, red for bad, yellow for partial */\nfunction renderStatusLight(status: \"good\" | \"bad\" | \"partial\" | \"unknown\") {\n const colors = {\n good: \"#22c55e\", // green\n bad: \"#ef4444\", // red\n partial: \"#eab308\", // yellow\n unknown: \"#6b7280\", // gray\n };\n return html`\n <span\n class=\"setup-status-light\"\n style=\"background: ${colors[status]}\"\n ></span>\n `;\n}\n\n/** Small \"i\" circle button that opens an info modal */\nfunction renderInfoButton(id: string, state: SetupViewState) {\n return html`\n <button\n class=\"setup-info-btn\"\n @click=${() => state.onInfoModalOpen(id)}\n title=\"Details\"\n >\n ${icons.info}\n </button>\n `;\n}\n\n/** Info modal overlay with key/value rows */\nfunction renderInfoModal(state: SetupViewState) {\n if (!state.infoModalOpen) return nothing;\n\n let title = \"\";\n let rows: Array<{ label: string; value: string; copyable?: boolean }> = [];\n let headerContent: ReturnType<typeof html> | typeof nothing = nothing;\n\n switch (state.infoModalOpen) {\n case \"gateway\": {\n const addr = typeof window !== \"undefined\" ? window.location.host : \"unknown\";\n title = \"Gateway\";\n rows = [\n { label: \"Status\", value: state.gatewayHealthy === false ? \"Stopped\" : \"Running\" },\n { label: \"What\", value: \"The core service that powers Taskmaster — handles AI conversations, message routing, and all connected channels\" },\n { label: \"Address\", value: addr },\n { label: \"Health\", value: state.gatewayHealthMessage || \"OK\" },\n ];\n break;\n }\n case \"claude\": {\n const mins = state.authExpiresIn;\n let expiryText = \"N/A\";\n if (mins != null && mins > 0) {\n if (mins > 60) {\n const h = Math.floor(mins / 60);\n const m = mins % 60;\n expiryText = m > 0 ? `${h}h ${m}m` : `${h}h`;\n } else {\n expiryText = `${mins}m`;\n }\n }\n title = \"Claude\";\n rows = [\n { label: \"Status\", value: state.authConnected ? \"Connected\" : \"Disconnected\" },\n { label: \"What\", value: \"Connection to Claude, the AI that powers natural conversation and tool use\" },\n { label: \"How\", value: \"Authenticated via OAuth — tokens refresh automatically when they expire\" },\n { label: \"Token Expiry\", value: expiryText },\n ...(state.authMessage ? [{ label: \"Message\", value: state.authMessage }] : []),\n ];\n if (state.authRefreshToken) {\n const token = state.authRefreshToken;\n const truncated = token.length > 20\n ? `${token.slice(0, 8)}...${token.slice(-8)}`\n : token;\n headerContent = html`\n <div style=\"display: flex; align-items: center; gap: 6px; padding: 4px 0 8px; border-bottom: 1px solid rgba(255,255,255,0.08);\">\n <span style=\"font-size: 12px; color: var(--tasker-text-grey); min-width: 90px;\">Refresh Token</span>\n <code style=\"font-size: 12px; color: var(--tasker-white); word-break: break-all; flex: 1;\">${truncated}</code>\n <button class=\"setup-info-btn\" title=\"Copy refresh token\" @click=${async (e: Event) => {\n const btn = e.currentTarget as HTMLElement;\n try { await navigator.clipboard.writeText(token); } catch {\n const el = document.createElement(\"textarea\");\n el.value = token; el.style.position = \"fixed\"; el.style.opacity = \"0\";\n document.body.appendChild(el); el.select(); document.execCommand(\"copy\"); document.body.removeChild(el);\n }\n btn.classList.add(\"copied\");\n setTimeout(() => btn.classList.remove(\"copied\"), 1500);\n }}>${icons.copy}</button>\n </div>\n `;\n }\n break;\n }\n case \"license\": {\n const maskedKey = state.licenseStoredKey\n ? `\\u2026${state.licenseStoredKey.slice(-12)}`\n : \"N/A\";\n title = \"License\";\n rows = [\n { label: \"Status\", value: state.licenseValid ? \"Active\" : \"Inactive\" },\n { label: \"What\", value: \"Your Taskmaster license key, tied to this specific device\" },\n { label: \"Key\", value: maskedKey },\n { label: \"Tier\", value: state.licenseTier || \"Standard\" },\n { label: \"Device ID\", value: state.licenseDeviceId || \"N/A\", copyable: !!state.licenseDeviceId },\n ];\n break;\n }\n case \"whatsapp\": {\n const ws = getSelectedWorkspace(state);\n const account = ws ? resolveWorkspaceWhatsApp(ws, state) : null;\n title = \"WhatsApp\";\n rows = [\n { label: \"Status\", value: account?.connected ? \"Connected\" : \"Disconnected\" },\n { label: \"What\", value: \"WhatsApp integration — receive and respond to customer messages through WhatsApp\" },\n { label: \"How\", value: \"Links to your WhatsApp account by scanning a QR code, then routes messages to your AI assistant\" },\n { label: \"Account\", value: account?.name || account?.accountId || \"Default\" },\n { label: \"Phone\", value: account?.self?.e164 || \"Not paired\" },\n { label: \"Linked\", value: account?.linked ? \"Yes\" : \"No\" },\n ...(account?.lastError ? [{ label: \"Last Error\", value: formatChannelError(account.lastError) }] : []),\n ];\n break;\n }\n case \"imessage\": {\n const { thisWsOwns: imsgOwned } = resolveIMessageState(state);\n title = \"iMessage\";\n rows = [\n { label: \"Status\", value: imsgOwned && state.imessageConnected ? \"Connected\" : \"Disconnected\" },\n { label: \"What\", value: \"iMessage integration — communicate with your AI assistant through Apple Messages\" },\n { label: \"How\", value: \"Uses the Mac's built-in Messages app; only one account can own the iMessage channel at a time\" },\n { label: \"Assigned To\", value: state.imessageOwnerWorkspace ?? \"Not assigned\" },\n { label: \"Mode\", value: \"Self-chat only\" },\n ...(state.imessageLastError ? [{ label: \"Last Error\", value: state.imessageLastError }] : []),\n ];\n break;\n }\n case \"update\": {\n title = \"Software Update\";\n rows = [\n { label: \"Status\", value: state.updateAvailable === null ? \"Not checked\" : state.updateAvailable ? \"Update available\" : \"Up to date\" },\n { label: \"What\", value: \"Checks for new versions of Taskmaster and lets you update from the control panel\" },\n { label: \"Current\", value: state.currentVersion ? `v${state.currentVersion}` : \"Unknown\" },\n { label: \"Latest\", value: state.latestVersion ? `v${state.latestVersion}` : \"Unknown\" },\n ...(state.updateMessage ? [{ label: \"Message\", value: state.updateMessage }] : []),\n ];\n break;\n }\n case \"remote-access\": {\n const ts = state.tailscaleStatus;\n const status = !ts\n ? \"Checking...\"\n : !ts.installed\n ? \"Not installed\"\n : !ts.loggedIn\n ? \"Not connected\"\n : ts.serveEnabled && ts.serveActive\n ? \"Active\"\n : ts.serveEnabled && !ts.serveActive\n ? \"Enabled but not active\"\n : \"Off\";\n title = \"Remote Access\";\n rows = [\n { label: \"Status\", value: status },\n { label: \"What\", value: \"Access this control panel from anywhere — your phone, another computer, or while away from home\" },\n { label: \"How\", value: \"Uses Tailscale to create a private, encrypted connection with a trusted HTTPS certificate (no browser warnings)\" },\n { label: \"Requires\", value: \"Tailscale installed on this device and on any device you want to access the control panel from, all logged into the same Tailscale account\" },\n { label: \"Internet Access\", value: \"Enable internet access (globe icon) to make Public Chat reachable from the web\" },\n { label: \"Cost\", value: \"Tailscale is free for personal use (up to 100 devices)\" },\n ];\n if (ts?.tailnetUrl) {\n const url = ts.tailnetUrl;\n headerContent = html`\n ${state.remoteAccessQrDataUrl\n ? html`<div style=\"text-align: center; padding: 12px 0;\">\n <img src=${state.remoteAccessQrDataUrl} alt=\"QR code for remote access URL\" style=\"width: 180px; height: 180px; image-rendering: pixelated; border-radius: 8px;\" />\n </div>`\n : nothing}\n <div style=\"display: flex; align-items: center; gap: 6px; padding: 4px 0 8px; border-bottom: 1px solid rgba(255,255,255,0.08);\">\n <a href=\"${url}\" target=\"_blank\" rel=\"noopener\"\n style=\"color: var(--tasker-link, #60a5fa); font-size: 13px; word-break: break-all;\"\n >${url}</a>\n <button class=\"setup-info-btn\" title=\"Copy URL\" @click=${async (e: Event) => {\n const btn = e.currentTarget as HTMLElement;\n try { await navigator.clipboard.writeText(url); } catch {\n const el = document.createElement(\"textarea\");\n el.value = url; el.style.position = \"fixed\"; el.style.opacity = \"0\";\n document.body.appendChild(el); el.select(); document.execCommand(\"copy\"); document.body.removeChild(el);\n }\n btn.classList.add(\"copied\");\n setTimeout(() => btn.classList.remove(\"copied\"), 1500);\n }}>${icons.copy}</button>\n </div>\n `;\n }\n break;\n }\n case \"public-chat\": {\n title = \"Public Chat\";\n rows = [\n { label: \"Status\", value: state.publicChatEnabled ? \"Enabled\" : \"Disabled\" },\n { label: \"What\", value: \"A chat widget anyone can use to message your business from a web browser\" },\n { label: \"Requires\", value: \"Remote Access with internet access enabled — this gives your device a public URL that visitors can reach\" },\n { label: \"Access mode\", value: AUTH_MODE_LABELS[state.publicChatAuthMode] ?? \"Open access\" },\n { label: \"WhatsApp\", value: \"Sends verification codes via WhatsApp. Requires a connected WhatsApp account.\" },\n { label: \"SMS\", value: \"Sends verification codes via text message. Uses Brevo — same API key as email. Requires prepaid SMS credits in your Brevo account.\" },\n { label: \"Email\", value: \"Sends verification codes via email. Uses Brevo (free, 300 emails/day). Sender address is auto-detected from your verified sender in Brevo.\" },\n { label: \"Provider\", value: \"SMS and email both use Brevo — one API key, configured in API Keys above. WhatsApp uses your connected account.\" },\n ];\n if (state.publicChatEnabled && state.publicChatFullUrl) {\n const url = state.publicChatFullUrl;\n headerContent = html`\n ${state.publicChatQrDataUrl\n ? html`<div style=\"text-align: center; padding: 12px 0;\">\n <img src=${state.publicChatQrDataUrl} alt=\"QR code for public chat URL\" style=\"width: 180px; height: 180px; image-rendering: pixelated; border-radius: 8px;\" />\n </div>`\n : nothing}\n <div style=\"display: flex; align-items: center; gap: 6px; padding: 4px 0 8px; border-bottom: 1px solid rgba(255,255,255,0.08);\">\n <a href=\"${url}\" target=\"_blank\" rel=\"noopener\"\n style=\"color: var(--tasker-link, #60a5fa); font-size: 13px; word-break: break-all;\"\n >${url}</a>\n <button class=\"setup-info-btn\" title=\"Copy URL\" @click=${async (e: Event) => {\n const btn = e.currentTarget as HTMLElement;\n try { await navigator.clipboard.writeText(url); } catch {\n const el = document.createElement(\"textarea\");\n el.value = url; el.style.position = \"fixed\"; el.style.opacity = \"0\";\n document.body.appendChild(el); el.select(); document.execCommand(\"copy\"); document.body.removeChild(el);\n }\n btn.classList.add(\"copied\");\n setTimeout(() => btn.classList.remove(\"copied\"), 1500);\n }}>${icons.copy}</button>\n </div>\n `;\n }\n break;\n }\n case \"sms-fallback\": {\n title = \"SMS Fallback\";\n rows = [\n { label: \"What\", value: \"When WhatsApp is not connected, verification codes are sent via SMS instead\" },\n { label: \"Provider\", value: \"Brevo — uses the same API key as email verification\" },\n { label: \"When used\", value: \"Only when a visitor requests phone verification and WhatsApp is unavailable\" },\n { label: \"Setup\", value: \"Add your Brevo API key in API Keys above, then purchase SMS credits in the Brevo dashboard\" },\n ];\n break;\n }\n case \"account-pin\": {\n title = \"Account PIN\";\n rows = [\n { label: \"Status\", value: state.accountHasPin ? \"Set\" : \"Not set\" },\n { label: \"What\", value: \"A numeric PIN that protects this account on the control panel\" },\n { label: \"When needed\", value: \"Required when switching to this account or after the session expires\" },\n { label: \"Format\", value: \"4 to 6 digits\" },\n ];\n break;\n }\n case \"branding\": {\n const hasAny = Boolean(state.brandAccentColor || state.brandBackgroundColor || state.brandHasLogo);\n title = \"Branding\";\n rows = [\n { label: \"Status\", value: hasAny ? \"Customised\" : \"Default\" },\n { label: \"What\", value: \"Your business logo and colour scheme, displayed on the control panel and public chat pages\" },\n { label: \"Logo\", value: \"Shown on public chat pages alongside your business name\" },\n { label: \"Accent colour\", value: \"Used for buttons, links, and interactive elements\" },\n { label: \"Background tint\", value: \"A subtle colour wash applied to page and card backgrounds\" },\n { label: \"Scope\", value: \"Each account has its own branding — switch accounts to customise each one separately\" },\n ];\n break;\n }\n case \"api-keys\": {\n const akProviders = state.apiKeyProviders;\n const akConfigured = akProviders.filter((p) => p.hasKey).length;\n title = \"API Keys\";\n rows = [\n { label: \"Status\", value: akConfigured > 0 ? `${akConfigured} configured` : \"None configured\" },\n { label: \"What\", value: \"API keys let Taskmaster connect to AI providers (Google, OpenAI, etc.) and services (Tavily search, Brave search)\" },\n { label: \"Required\", value: \"At least one AI provider key is needed for the assistant to work\" },\n { label: \"Scope\", value: \"API keys are shared across all accounts on this device\" },\n ];\n break;\n }\n case \"network\": {\n title = \"Network\";\n rows = [\n { label: \"Address\", value: state.networkHostname ? `${state.networkHostname}.local:${state.networkPort}` : `Port ${state.networkPort}` },\n { label: \"What\", value: \"The hostname and port this device uses on your local network\" },\n { label: \"When to change\", value: \"If you have multiple devices on the same network, give each a unique hostname and port so they don't conflict\" },\n { label: \"After saving\", value: \"The gateway restarts and your browser redirects to the new address\" },\n ];\n break;\n }\n default:\n return nothing;\n }\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onInfoModalClose();\n }\n }}>\n <div class=\"setup-info-card\">\n <h3>${title}</h3>\n ${headerContent}\n ${rows.map(\n (row) => html`\n <div class=\"setup-info-row\">\n <span class=\"setup-info-label\">${row.label}</span>\n <span class=\"setup-info-value\">${row.value}</span>\n ${row.copyable\n ? html`<button\n class=\"setup-info-btn\"\n title=\"Copy ${row.label}\"\n @click=${async (e: Event) => {\n const btn = e.currentTarget as HTMLElement;\n try {\n await navigator.clipboard.writeText(row.value);\n btn.textContent = \"Copied!\";\n setTimeout(() => { btn.textContent = \"Copy\"; }, 1500);\n } catch {\n const el = document.createElement(\"textarea\");\n el.value = row.value;\n el.style.position = \"fixed\";\n el.style.opacity = \"0\";\n document.body.appendChild(el);\n el.select();\n document.execCommand(\"copy\");\n document.body.removeChild(el);\n btn.textContent = \"Copied!\";\n setTimeout(() => { btn.textContent = \"Copy\"; }, 1500);\n }\n }}\n >Copy</button>`\n : nothing}\n </div>\n `,\n )}\n <button\n class=\"setup-button secondary\"\n style=\"margin-top: 16px; width: 100%; padding: 10px;\"\n @click=${state.onInfoModalClose}\n >\n Close\n </button>\n </div>\n </div>\n `;\n}\n\nfunction renderStepIndicator(currentStep: SetupStep) {\n const steps = [\n { id: \"license\", label: \"1. Activate License\" },\n { id: \"auth\", label: \"2. Connect Claude\" },\n { id: \"setup\", label: \"3. Link WhatsApp\" },\n ];\n\n const stepOrder = [\"license\", \"auth\", \"setup\"];\n const currentIndex = stepOrder.indexOf(currentStep);\n\n return html`\n <div class=\"setup-steps\">\n ${steps.map((step) => {\n const stepIndex = stepOrder.indexOf(step.id);\n const isActive = currentStep === step.id;\n const isCompleted = currentIndex > stepIndex;\n return html`\n <div\n class=\"setup-step ${isActive ? \"active\" : \"\"} ${isCompleted ? \"completed\" : \"\"}\"\n >\n <span class=\"setup-step-dot\"></span>\n <span class=\"setup-step-label\">${step.label}</span>\n </div>\n `;\n })}\n </div>\n `;\n}\n\nfunction renderLicenseStep(state: SetupViewState) {\n const {\n licenseKey,\n licenseBusy,\n licenseValid,\n licenseMessage,\n licenseDeviceId,\n onLicenseKeyChange,\n onLicenseActivate,\n } = state;\n\n // Successfully activated — show brief success before moving on\n if (licenseValid === true) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card setup-success\">\n ${renderStepIndicator(\"license\")}\n <div class=\"setup-status-row\">\n ${renderStatusLight(\"good\")}\n <span>License Activated</span>\n </div>\n <p>${licenseMessage ?? \"Your license is active.\"}</p>\n </div>\n </div>\n `;\n }\n\n // Loading state\n if (licenseBusy && !licenseKey) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"license\")}\n <div class=\"setup-spinner\"></div>\n <p>Checking license...</p>\n </div>\n </div>\n `;\n }\n\n // Main license entry form\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"license\")}\n <h1>Activate License</h1>\n <p>Enter your license key to get started.</p>\n ${licenseDeviceId\n ? html`\n <p class=\"setup-hint\" style=\"margin-top: 0;\">\n Send this ID along with your order number to our WhatsApp to receive your license key.\n </p>\n <div class=\"setup-device-id\">\n <span class=\"setup-device-id-label\">Your Device ID</span>\n <code class=\"setup-device-id-value\">${licenseDeviceId}</code>\n <button\n class=\"setup-device-id-copy\"\n title=\"Copy Device ID\"\n @click=${async (e: Event) => {\n const btn = e.currentTarget as HTMLButtonElement;\n try {\n await navigator.clipboard.writeText(licenseDeviceId);\n btn.textContent = \"Copied!\";\n setTimeout(() => { btn.textContent = \"Copy\"; }, 1500);\n } catch {\n // Fallback for non-HTTPS\n const el = document.createElement(\"textarea\");\n el.value = licenseDeviceId;\n el.style.position = \"fixed\";\n el.style.opacity = \"0\";\n document.body.appendChild(el);\n el.select();\n document.execCommand(\"copy\");\n document.body.removeChild(el);\n btn.textContent = \"Copied!\";\n setTimeout(() => { btn.textContent = \"Copy\"; }, 1500);\n }\n }}\n >Copy</button>\n </div>\n `\n : nothing}\n <div class=\"setup-code-input\">\n <input\n type=\"text\"\n placeholder=\"Paste your license key here\"\n .value=${licenseKey}\n @input=${(e: Event) =>\n onLicenseKeyChange((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\" && licenseKey.trim()) {\n onLicenseActivate();\n }\n }}\n />\n <button\n class=\"setup-button\"\n ?disabled=${!licenseKey.trim() || licenseBusy}\n @click=${onLicenseActivate}\n >\n ${licenseBusy ? \"Activating...\" : \"Activate\"}\n </button>\n </div>\n ${licenseValid === false && licenseMessage\n ? html`\n <div class=\"setup-status-row\" style=\"margin-top: 12px;\">\n ${renderStatusLight(\"bad\")}\n <span class=\"setup-error\">${licenseMessage}</span>\n </div>\n `\n : nothing}\n <p class=\"setup-hint\">\n Need a license?\n <a href=\"https://taskmaster.bot\" target=\"_blank\" rel=\"noopener\">\n Purchase at taskmaster.bot\n </a>\n </p>\n </div>\n </div>\n `;\n}\n\nfunction renderAuthStep(state: SetupViewState) {\n const {\n authConnected,\n authBusy,\n authMessage,\n authUrl,\n authCodeInput,\n authExpiresIn,\n onStartAuth,\n onSubmitAuthCode,\n onAuthCodeChange,\n } = state;\n\n // Already connected\n if (authConnected === true) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card setup-success\">\n ${renderStepIndicator(\"auth\")}\n <div class=\"setup-status-row\">\n ${renderStatusLight(\"good\")}\n <span>Claude Connected</span>\n </div>\n <p>\n Your Claude Pro subscription is linked.\n ${authExpiresIn\n ? html`<br /><span class=\"setup-hint\"\n >Expires in ${authExpiresIn} minutes</span\n >`\n : nothing}\n </p>\n <p style=\"color: var(--tasker-text-grey); font-size: 14px;\">\n Head to Chat to introduce yourself and finish setting up your assistant.\n </p>\n <a href=\"/chat\" class=\"setup-button primary\">\n Continue to Chat →\n </a>\n </div>\n </div>\n `;\n }\n\n // Waiting for auth URL\n if (authBusy && !authUrl) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"auth\")}\n <div class=\"setup-spinner\"></div>\n <p>Starting Claude connection...</p>\n </div>\n </div>\n `;\n }\n\n // Have auth URL - waiting for user to authenticate\n if (authUrl) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"auth\")}\n <h1>Connect to Claude</h1>\n <p>Click the button below to sign in with your Claude Pro account.</p>\n <a\n href=${authUrl}\n target=\"_blank\"\n rel=\"noopener\"\n class=\"setup-button primary\"\n >\n Sign in with Claude →\n </a>\n <div class=\"setup-divider\">\n <span>Then enter the code shown</span>\n </div>\n <div class=\"setup-code-input\">\n <input\n type=\"text\"\n placeholder=\"Enter authorization code\"\n .value=${authCodeInput}\n @input=${(e: Event) =>\n onAuthCodeChange((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\" && authCodeInput.trim()) {\n onSubmitAuthCode(authCodeInput.trim());\n }\n }}\n />\n <button\n class=\"setup-button\"\n ?disabled=${!authCodeInput.trim() || authBusy}\n @click=${() => onSubmitAuthCode(authCodeInput.trim())}\n >\n ${authBusy ? \"Verifying...\" : \"Submit\"}\n </button>\n </div>\n ${authMessage\n ? html`<p class=\"setup-hint\">${authMessage}</p>`\n : nothing}\n <p class=\"setup-hint\" style=\"margin-top: 16px;\">\n <a href=\"#\" class=\"setup-link\" @click=${(e: Event) => { e.preventDefault(); state.onAuthApiKeyToggle(); }}>\n Or use an API key instead\n </a>\n </p>\n </div>\n </div>\n `;\n }\n\n // API key input mode\n if (state.authApiKeyMode) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"auth\")}\n <h1>Enter API Key</h1>\n <p>Paste your Anthropic API key below.</p>\n <div class=\"setup-code-input\">\n <input\n type=\"password\"\n placeholder=\"sk-ant-...\"\n .value=${state.authApiKeyInput}\n @input=${(e: Event) => state.onAuthApiKeyChange((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\" && state.authApiKeyInput.trim()) {\n state.onAuthApiKeySubmit();\n }\n }}\n ?disabled=${state.authApiKeyBusy}\n autofocus\n />\n <button\n class=\"setup-button\"\n ?disabled=${!state.authApiKeyInput.trim() || state.authApiKeyBusy}\n @click=${() => state.onAuthApiKeySubmit()}\n >${state.authApiKeyBusy ? \"Saving...\" : \"Save\"}</button>\n </div>\n ${state.authApiKeyError\n ? html`<p class=\"setup-error\">${state.authApiKeyError}</p>`\n : nothing}\n <p class=\"setup-hint\" style=\"margin-top: 16px;\">\n <a href=\"#\" class=\"setup-link\" @click=${(e: Event) => { e.preventDefault(); state.onAuthApiKeyToggle(); }}>\n Use OAuth instead\n </a>\n </p>\n <p class=\"setup-hint\">\n Get an API key from\n <a href=\"https://console.anthropic.com/settings/keys\" target=\"_blank\" rel=\"noopener\">\n console.anthropic.com\n </a>\n </p>\n </div>\n </div>\n `;\n }\n\n // Initial state (or error — show connect screen with error inline, not a dead-end)\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"auth\")}\n <h1>Connect to Claude</h1>\n ${authConnected === false && authMessage\n ? html`<p class=\"setup-error\">${authMessage}</p>`\n : html`<p>\n First, let's connect your Claude Pro subscription.<br />\n This powers your AI assistant.\n </p>`}\n <button class=\"setup-button primary\" @click=${onStartAuth}>\n Connect to Claude →\n </button>\n <p class=\"setup-hint\" style=\"margin-top: 8px;\">\n <a href=\"#\" class=\"setup-link\" @click=${(e: Event) => { e.preventDefault(); state.onAuthApiKeyToggle(); }}>\n Or enter your API key\n </a>\n </p>\n <p class=\"setup-hint\">\n Need a Claude subscription?\n <a href=\"https://claude.ai/upgrade\" target=\"_blank\" rel=\"noopener\">\n Get Claude Pro\n </a>\n </p>\n </div>\n </div>\n `;\n}\n\n/** Resolve WhatsApp account status for a workspace card */\nfunction resolveWorkspaceWhatsApp(\n ws: WorkspaceInfo,\n state: SetupViewState,\n): ChannelAccountSnapshot | null {\n const accountMap = new Map(\n state.whatsappAccounts.map((a) => [a.accountId, a]),\n );\n if (ws.whatsappAccountId) {\n return accountMap.get(ws.whatsappAccountId) ?? null;\n }\n // Default workspace fallback: if single account, assume it's this one\n if (ws.isDefault && state.whatsappAccounts.length === 1) {\n return state.whatsappAccounts[0] ?? null;\n }\n return null;\n}\n\n/** Resolve the selected workspace from wsProps */\nfunction getSelectedWorkspace(state: SetupViewState): WorkspaceInfo | null {\n const selected = state.wsProps?.selectedWorkspace;\n if (!selected) return state.workspaces[0] ?? null;\n return state.workspaces.find((ws) => ws.name === selected) ?? null;\n}\n\n/** Render dashboard header with business name, pencil rename, and refresh button */\nfunction renderDashboardHeader(state: SetupViewState) {\n const ws = getSelectedWorkspace(state);\n const businessName = ws?.displayName ?? ws?.name ?? resolveBrand().name;\n\n // Edit mode: inline text input with save/cancel\n if (state.renamingWorkspace && ws) {\n const handleSave = () => {\n const val = state.renameWorkspaceName.trim();\n if (val) state.onWorkspaceRename(ws.name, val);\n };\n return html`\n <div style=\"display: flex; align-items: center; gap: 6px; margin-bottom: 4px;\">\n <input\n type=\"text\"\n .value=${state.renameWorkspaceName}\n @input=${(e: Event) => { state.renameWorkspaceName = (e.target as HTMLInputElement).value; }}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") handleSave();\n if (e.key === \"Escape\") state.onWorkspaceRenameCancel();\n }}\n style=\"flex: 1; font-size: 18px; font-weight: 600; background: var(--tasker-bg-input, rgba(255,255,255,0.08)); border: 1px solid var(--tasker-border, rgba(255,255,255,0.15)); border-radius: 6px; color: var(--tasker-white); padding: 4px 8px; outline: none;\"\n autofocus\n />\n <button\n class=\"setup-status-action\"\n @click=${handleSave}\n title=\"Save\"\n style=\"color: #22c55e;\"\n >${icons.check}</button>\n <button\n class=\"setup-status-action\"\n @click=${state.onWorkspaceRenameCancel}\n title=\"Cancel\"\n >${icons.x}</button>\n </div>\n `;\n }\n\n // View mode: business name + pencil\n return html`\n <div style=\"display: flex; align-items: center; gap: 6px; margin-bottom: 4px;\">\n <h2 style=\"margin: 0; font-size: 20px; font-weight: 600; color: var(--tasker-white);\">${businessName}</h2>\n <button\n class=\"setup-status-action\"\n @click=${state.onWorkspaceRenameStart}\n title=\"Rename\"\n style=\"opacity: 0.5; transform: scale(0.8);\"\n >${icons.edit}</button>\n </div>\n `;\n}\n\n/** Render gateway status row in the dashboard */\nfunction renderGatewayStatusRow(state: SetupViewState) {\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(state.gatewayHealthy === false ? \"bad\" : \"good\")}\n <div class=\"setup-status-info\">\n <strong>Gateway</strong>\n <span>${state.gatewayHealthMessage || \"Running\"}</span>\n </div>\n ${renderInfoButton(\"gateway\", state)}\n <button\n class=\"setup-status-action ${state.gatewayHealthLoading ? \"spinning\" : \"\"}\"\n ?disabled=${state.gatewayHealthLoading}\n @click=${state.onRefreshGatewayStatus}\n title=\"Refresh status\"\n >\n ${icons.rotateCw}\n </button>\n </div>\n `;\n}\n\n/** Render Claude status row in the dashboard */\nfunction renderClaudeStatusRow(state: SetupViewState) {\n const isConnected = state.authConnected === true;\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(isConnected ? \"good\" : \"bad\")}\n <div class=\"setup-status-info\">\n <strong>Claude</strong>\n <span>\n ${isConnected ? \"Connected\" : \"Not connected\"}${isConnected && state.authExpiresIn\n ? html` <span style=\"color: var(--tasker-text-grey); font-size: 12px;\">(${state.authExpiresIn > 60 ? `${Math.floor(state.authExpiresIn / 60)}h ${state.authExpiresIn % 60}m` : `${state.authExpiresIn}m`})</span>`\n : nothing}\n </span>\n </div>\n ${renderInfoButton(\"claude\", state)}\n ${isConnected\n ? html`\n <button\n class=\"setup-status-action ${state.authBusy ? \"spinning\" : \"\"}\"\n ?disabled=${state.authBusy}\n @click=${state.onClaudeAuthModalOpen}\n title=\"Manage Connection\"\n >\n ${icons.refreshCw}\n </button>\n `\n : html`\n <button\n class=\"setup-status-action\"\n @click=${state.onClaudeAuthModalOpen}\n title=\"Connect Claude\"\n >\n ${icons.refreshCw}\n </button>\n `}\n </div>\n `;\n}\n\n/** Render license status row in the dashboard */\nfunction renderLicenseStatusRow(state: SetupViewState) {\n return html`\n <div class=\"setup-status-item\" style=\"flex-wrap: wrap;\">\n ${renderStatusLight(\"good\")}\n <div class=\"setup-status-info\">\n <strong>License</strong>\n <span>Active</span>\n </div>\n ${renderInfoButton(\"license\", state)}\n <button\n class=\"setup-status-action\"\n @click=${() => {\n if (state.licenseRemoveConfirm) {\n state.onLicenseRemoveCancel();\n } else {\n state.onLicenseRemoveConfirm();\n }\n }}\n title=\"Manage License\"\n >\n ${icons.refreshCw}\n </button>\n ${state.licenseRemoveConfirm\n ? html`\n <div style=\"width: 100%; margin-top: 8px; margin-left: 30px;\">\n <p style=\"color: var(--tasker-text-grey); font-size: 13px; margin: 0 0 8px;\">\n Removing your license will disable ${resolveBrand().name} until you enter a new key.\n </p>\n <div style=\"display: flex; gap: 8px;\">\n <button\n class=\"setup-button danger\"\n style=\"font-size: 12px; padding: 4px 12px;\"\n ?disabled=${state.licenseBusy}\n @click=${state.onLicenseRemove}\n >\n ${state.licenseBusy ? \"Removing\\u2026\" : \"Remove License\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"font-size: 12px; padding: 4px 12px;\"\n @click=${state.onLicenseRemoveCancel}\n >\n Cancel\n </button>\n </div>\n </div>\n `\n : nothing}\n </div>\n `;\n}\n\n/** Extract a human-readable message from a raw error string (often serialized JSON). */\nfunction formatChannelError(raw: string): string {\n try {\n const obj = JSON.parse(raw);\n // Boom-style: { error: { output: { payload: { message } } } } or top-level\n const boom = obj?.error ?? obj;\n const msg = boom?.output?.payload?.message ?? boom?.message ?? obj?.message;\n if (msg && typeof msg === \"string\") return msg;\n } catch {\n // Not JSON — use as-is\n }\n return raw;\n}\n\n/** Render WhatsApp status row for the selected workspace in the dashboard */\nfunction renderWhatsAppStatusRow(state: SetupViewState) {\n const ws = getSelectedWorkspace(state);\n if (!ws) return nothing;\n\n const account = resolveWorkspaceWhatsApp(ws, state);\n const isConnected = account?.running && account?.connected;\n const isLinked = account?.linked && !isConnected;\n const hasAccount = Boolean(account);\n const waStatus: \"good\" | \"bad\" | \"partial\" | \"unknown\" = isConnected\n ? \"good\"\n : isLinked\n ? \"partial\"\n : hasAccount\n ? \"bad\"\n : \"unknown\";\n const waStatusText = isConnected\n ? \"Connected\"\n : isLinked\n ? \"Linked, not connected\"\n : hasAccount\n ? (account?.lastError ? formatChannelError(account.lastError) : \"Not connected\")\n : \"Not paired\";\n const isBaileys = !account?.provider || account?.provider === \"baileys\";\n const accountId = ws.whatsappAccountId ?? (ws.isDefault && state.whatsappAccounts.length === 1 ? state.whatsappAccounts[0]?.accountId : undefined);\n const isActiveQr = accountId != null && state.whatsappActiveQrAccountId === accountId;\n\n return html`\n <div class=\"setup-status-item\" style=\"flex-wrap: wrap;\">\n ${renderStatusLight(waStatus)}\n <div class=\"setup-status-info\">\n <strong>WhatsApp</strong>\n <span>${waStatusText}</span>\n </div>\n ${renderInfoButton(\"whatsapp\", state)}\n ${hasAccount\n ? html`<button\n class=\"setup-info-btn\"\n @click=${state.onWhatsAppSettingsOpen}\n title=\"WhatsApp settings\"\n >${icons.settings}</button>`\n : nothing}\n ${isBaileys && accountId\n ? html`<button\n class=\"setup-status-action\"\n @click=${state.onRefreshWhatsAppStatus}\n title=\"Refresh status\"\n >${icons.rotateCw}</button>`\n : nothing}\n ${isActiveQr && state.whatsappLoginQrDataUrl\n ? html`\n <div style=\"width: 100%; margin-top: 8px; margin-left: 30px;\">\n <div class=\"setup-qr\" style=\"display: inline-flex;\">\n <img\n src=${state.whatsappLoginQrDataUrl}\n alt=\"WhatsApp QR\"\n style=\"width: 140px; height: 140px;\"\n />\n </div>\n ${state.whatsappLoginMessage\n ? html`<p class=\"setup-hint\" style=\"margin-top: 4px;\">${state.whatsappLoginMessage}</p>`\n : nothing}\n </div>\n `\n : nothing}\n </div>\n `;\n}\n\n/** WhatsApp settings modal — info, link/unlink, agent settings */\nfunction renderWhatsAppSettingsModal(state: SetupViewState) {\n if (!state.whatsappSettingsOpen) return nothing;\n\n const ws = getSelectedWorkspace(state);\n if (!ws) return nothing;\n const account = resolveWorkspaceWhatsApp(ws, state);\n if (!account) return nothing;\n\n const isConnected = account.running && account.connected;\n const isBaileys = !account.provider || account.provider === \"baileys\";\n const accountId = ws.whatsappAccountId ?? (ws.isDefault && state.whatsappAccounts.length === 1 ? state.whatsappAccounts[0]?.accountId : undefined);\n const closeModal = () => state.onWhatsAppSettingsClose();\n\n // Info rows\n const infoStyle = \"display: flex; justify-content: space-between; font-size: 13px;\";\n const labelStyle = \"color: var(--tasker-text-grey);\";\n const valueStyle = \"color: var(--tasker-white); text-align: right;\";\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) closeModal();\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 360px;\">\n <h3>WhatsApp</h3>\n <div style=\"display: flex; flex-direction: column; gap: 8px; margin-top: 12px;\">\n <div style=\"${infoStyle}\"><span style=\"${labelStyle}\">Account</span><span style=\"${valueStyle}\">${account.name || account.accountId || \"Default\"}</span></div>\n <div style=\"${infoStyle}\"><span style=\"${labelStyle}\">Phone</span><span style=\"${valueStyle}\">${account.self?.e164 || \"Not paired\"}</span></div>\n <div style=\"${infoStyle}\"><span style=\"${labelStyle}\">Connected</span><span style=\"${valueStyle}\">${isConnected ? \"Yes\" : \"No\"}</span></div>\n <div style=\"${infoStyle}\"><span style=\"${labelStyle}\">Linked</span><span style=\"${valueStyle}\">${account.linked ? \"Yes\" : \"No\"}</span></div>\n ${account.lastError ? html`<div style=\"font-size: 13px;\"><div style=\"${labelStyle}\">Error</div><div style=\"color: #ef4444; margin-top: 4px; line-height: 1.4;\">${formatChannelError(account.lastError)}</div></div>` : nothing}\n </div>\n ${isBaileys && accountId\n ? html`\n <div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin: 16px 0 12px;\"></div>\n ${account.linked\n ? html`<button\n class=\"setup-button secondary\"\n style=\"width: 100%; padding: 10px;\"\n ?disabled=${state.whatsappBusy}\n @click=${() => { state.onWhatsAppUnlink(accountId); closeModal(); }}\n >Unlink WhatsApp</button>`\n : html`<button\n class=\"setup-button secondary\"\n style=\"width: 100%; padding: 10px;\"\n ?disabled=${state.whatsappBusy}\n @click=${() => { state.onWhatsAppRelink(accountId); closeModal(); }}\n >Link WhatsApp</button>`}\n `\n : nothing}\n ${isConnected\n ? html`\n <div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin: 16px 0 12px;\"></div>\n <div style=\"display: flex; flex-direction: column; gap: 16px;\">\n <label style=\"display: flex; align-items: flex-start; gap: 8px; cursor: pointer;\">\n <input\n type=\"checkbox\"\n .checked=${state.whatsappDmPolicy !== \"disabled\" && state.whatsappDmPolicy !== null}\n @change=${state.onWhatsAppDmToggle}\n style=\"accent-color: #22c55e; margin-top: 2px;\"\n />\n <div>\n <div style=\"font-size: 13px; color: var(--tasker-white);\">Enabled</div>\n <div style=\"font-size: 12px; color: var(--tasker-text-grey); opacity: 0.7;\">Agent replies to 3rd party messages</div>\n </div>\n </label>\n <div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin: 4px 0;\"></div>\n <label style=\"display: flex; align-items: flex-start; gap: 8px; cursor: pointer;\">\n <input\n type=\"checkbox\"\n .checked=${state.whatsappGroupPolicy === \"open\"}\n @change=${state.onWhatsAppGroupToggle}\n style=\"accent-color: #22c55e; margin-top: 2px;\"\n />\n <div>\n <div style=\"font-size: 13px; color: var(--tasker-white);\">Group chats</div>\n <div style=\"font-size: 12px; color: var(--tasker-text-grey); opacity: 0.7;\">Agent responds in WhatsApp groups</div>\n </div>\n </label>\n ${state.whatsappGroupPolicy === \"open\"\n ? html`\n <div style=\"display: flex; flex-direction: column; gap: 6px; padding-left: 24px;\">\n <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer;\">\n <input\n type=\"radio\"\n name=\"wa-group-mention\"\n .checked=${state.whatsappGroupRequireMention}\n @change=${() => state.onWhatsAppGroupMentionChange(true)}\n style=\"accent-color: #22c55e;\"\n />\n <div>\n <div style=\"font-size: 13px; color: var(--tasker-white);\">When mentioned</div>\n <div style=\"font-size: 11px; color: var(--tasker-text-grey); opacity: 0.7;\">Only responds when @mentioned</div>\n </div>\n </label>\n <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer;\">\n <input\n type=\"radio\"\n name=\"wa-group-mention\"\n .checked=${!state.whatsappGroupRequireMention}\n @change=${() => state.onWhatsAppGroupMentionChange(false)}\n style=\"accent-color: #22c55e;\"\n />\n <div>\n <div style=\"font-size: 13px; color: var(--tasker-white);\">Always respond</div>\n <div style=\"font-size: 11px; color: var(--tasker-text-grey); opacity: 0.7;\">Responds to every message in groups</div>\n </div>\n </label>\n </div>\n `\n : nothing}\n </div>\n `\n : nothing}\n <button\n class=\"setup-button secondary\"\n style=\"margin-top: 20px; width: 100%; padding: 10px;\"\n @click=${closeModal}\n >\n Close\n </button>\n </div>\n </div>\n `;\n}\n\n/** Render iMessage status row in the dashboard */\nfunction resolveIMessageState(state: SetupViewState) {\n const selectedWs = getSelectedWorkspace(state);\n const ownerWs = state.imessageOwnerWorkspace;\n const thisWsOwns = Boolean(selectedWs && ownerWs === selectedWs.name);\n const anotherWsOwns = Boolean(ownerWs && selectedWs && ownerWs !== selectedWs.name);\n return { selectedWs, ownerWs, thisWsOwns, anotherWsOwns };\n}\n\nfunction renderIMessageStatusRow(state: SetupViewState) {\n const { ownerWs, thisWsOwns, anotherWsOwns } = resolveIMessageState(state);\n\n // \"Connected\" requires this business to own iMessage via bindings.\n let status: \"good\" | \"bad\" | \"partial\" | \"unknown\";\n let statusText: string;\n if (anotherWsOwns) {\n status = \"partial\";\n statusText = `Connected to ${ownerWs}`;\n } else if (thisWsOwns && state.imessageConnected) {\n status = \"good\";\n statusText = \"Connected\";\n } else if (thisWsOwns && state.imessageRunning) {\n status = \"partial\";\n statusText = \"Running, not connected\";\n } else if (thisWsOwns) {\n status = \"bad\";\n statusText = \"Not running\";\n } else if (state.imessageConfigured) {\n status = \"unknown\";\n statusText = \"Not connected\";\n } else {\n status = \"bad\";\n statusText = \"Not configured\";\n }\n\n return html`\n <div class=\"setup-status-item\" style=\"flex-wrap: wrap;\">\n ${renderStatusLight(status)}\n <div class=\"setup-status-info\">\n <strong>iMessage</strong>\n <span>${statusText}</span>\n </div>\n ${renderInfoButton(\"imessage\", state)}\n <button\n class=\"setup-status-action ${state.imessageEnabling ? \"spinning\" : \"\"}\"\n ?disabled=${state.imessageEnabling}\n @click=${state.onIMessageEnable}\n title=\"${thisWsOwns ? \"Manage iMessage\" : \"Connect iMessage\"}\"\n >\n ${icons.refreshCw}\n </button>\n ${nothing}\n </div>\n `;\n}\n\nfunction renderIMessageActionModal(state: SetupViewState) {\n if (!state.imessageEnableConfirm) return nothing;\n const { ownerWs, thisWsOwns, anotherWsOwns } = resolveIMessageState(state);\n\n const closeModal = () => { state.onIMessageEnableCancel(); };\n\n // --- Connected to THIS business: show manage/disconnect ---\n if (thisWsOwns) {\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) closeModal();\n }}>\n <div class=\"setup-info-card\" style=\"text-align: center;\">\n <h3>iMessage</h3>\n <p style=\"color: var(--tasker-text-grey); font-size: 13px; margin: 8px 0 16px;\">\n iMessage is connected to this business.\n </p>\n <p style=\"font-size: 12px; color: var(--tasker-text-grey); opacity: 0.6; margin-bottom: 16px;\">\n Self-chat only. Third-party iMessage DMs are not processed.\n </p>\n <button\n class=\"setup-button secondary\"\n style=\"width: 100%; padding: 10px; color: #ef4444; border-color: #ef4444;\"\n ?disabled=${state.imessageEnabling}\n @click=${() => { state.onIMessageDisconnect(); }}\n >\n ${state.imessageEnabling ? \"Disconnecting\\u2026\" : \"Disconnect iMessage\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"width: 100%; padding: 10px; margin-top: 8px;\"\n @click=${closeModal}\n >\n Close\n </button>\n </div>\n </div>\n `;\n }\n\n // --- Connected to ANOTHER business: offer to reassign ---\n if (anotherWsOwns) {\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) closeModal();\n }}>\n <div class=\"setup-info-card\" style=\"text-align: center;\">\n <h3>Connect iMessage</h3>\n <p style=\"color: var(--tasker-text-grey); font-size: 13px; margin: 8px 0 16px;\">\n iMessage is currently connected to <strong style=\"text-transform: capitalize;\">${ownerWs}</strong>.\n Move it to this business?\n </p>\n <button\n class=\"setup-button primary\"\n style=\"width: 100%; padding: 10px;\"\n ?disabled=${state.imessageEnabling}\n @click=${() => { state.onIMessageReassign(); }}\n >\n ${state.imessageEnabling ? \"Connecting\\u2026\" : \"Connect to This Business\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"width: 100%; padding: 10px; margin-top: 8px;\"\n @click=${closeModal}\n >\n Cancel\n </button>\n </div>\n </div>\n `;\n }\n\n // --- Not connected: offer to connect ---\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) closeModal();\n }}>\n <div class=\"setup-info-card\" style=\"text-align: center;\">\n <h3>Enable iMessage</h3>\n <p style=\"color: var(--tasker-text-grey); font-size: 13px; margin: 8px 0 16px;\">\n ${resolveBrand().name} will respond to messages in Messages.app for this business.\n </p>\n <button\n class=\"setup-button primary\"\n style=\"width: 100%; padding: 10px;\"\n ?disabled=${state.imessageEnabling}\n @click=${() => { state.onIMessageEnableConfirm(); }}\n >\n ${state.imessageEnabling ? \"Connecting\\u2026\" : \"Connect\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"width: 100%; padding: 10px; margin-top: 8px;\"\n @click=${closeModal}\n >\n Cancel\n </button>\n </div>\n </div>\n `;\n}\n\n/** Render the Account PIN status row with Set/Change action */\n/** Global admin section showing API key management (below account dashboard) */\nfunction renderApiKeysSection(state: SetupViewState) {\n if (!state.isMaster) return nothing;\n\n const providers = state.apiKeyProviders;\n const configured = providers.filter((p) => p.hasKey).length;\n\n return html`\n <div style=\"margin-top: 16px; border-top: 1px solid var(--tasker-border, rgba(255,255,255,0.1)); padding-top: 16px;\">\n <div class=\"setup-status-item\">\n ${renderStatusLight(configured > 0 ? \"good\" : \"bad\")}\n <div class=\"setup-status-info\">\n <strong>API Keys</strong>\n <span>${configured} configured</span>\n </div>\n ${renderInfoButton(\"api-keys\", state)}\n <button\n class=\"setup-link-btn\"\n @click=${() => state.onApiKeyModalOpen()}\n >Manage</button>\n </div>\n </div>\n ${renderApiKeysModal(state)}\n `;\n}\n\n/** Modal for managing API keys across all providers */\nfunction renderApiKeysModal(state: SetupViewState) {\n if (!state.apiKeyModalOpen) return nothing;\n\n const providers = state.apiKeyProviders;\n\n // Build a map of stored key values for comparison\n const storedKeys: Record<string, string> = {};\n for (const p of providers) if (p.key) storedKeys[p.id] = p.key;\n\n const handleSave = (providerId: string, el?: HTMLElement) => {\n const row = el?.closest(\".setup-apikey-input\") as HTMLElement | null;\n const input = row?.querySelector(\"input\") as HTMLInputElement | null;\n const value = input?.value.trim();\n if (!value || value === storedKeys[providerId]) return;\n state.onApiKeySave(providerId, value);\n };\n\n const toggleVisibility = (e: Event) => {\n const btn = (e.currentTarget as HTMLElement);\n const row = btn.closest(\".setup-apikey-input\") as HTMLElement;\n const input = row?.querySelector(\"input\") as HTMLInputElement | null;\n if (!input) return;\n const visible = input.type === \"text\";\n input.type = visible ? \"password\" : \"text\";\n btn.classList.toggle(\"active\", !visible);\n };\n\n const handleInput = (providerId: string, e: Event) => {\n const input = e.target as HTMLInputElement;\n const row = input.closest(\".setup-apikey-input\") as HTMLElement;\n const value = input.value.trim();\n const changed = value.length > 0 && value !== storedKeys[providerId];\n // Save only appears when value differs from stored\n const saveBtn = row?.querySelector(\".setup-apikey-save\") as HTMLElement | null;\n if (saveBtn) saveBtn.style.display = changed ? \"\" : \"none\";\n // Eye appears when there's any text in the input\n const eyeBtn = row?.querySelector(\".setup-apikey-eye\") as HTMLElement | null;\n if (eyeBtn) eyeBtn.style.display = value.length > 0 ? \"\" : \"none\";\n };\n\n const primary = providers.filter((p) => p.primary);\n const advanced = providers.filter((p) => !p.primary);\n\n const renderProviderRow = (p: typeof providers[0]) => {\n const isSaving = state.apiKeySavingProvider === p.id && state.apiKeyBusy;\n const justSaved = !state.apiKeyBusy && state.apiKeySuccess === `${p.id} key saved`;\n const justRemoved = !state.apiKeyBusy && state.apiKeySuccess === `${p.id} key removed`;\n const justDisabled = !state.apiKeyBusy && state.apiKeySuccess === `${p.id} disabled`;\n const justEnabled = !state.apiKeyBusy && state.apiKeySuccess === `${p.id} enabled`;\n\n return html`\n <div class=\"setup-apikey-row ${p.disabled ? \"disabled\" : \"\"}\">\n <div class=\"setup-apikey-info\">\n <strong>${p.name}</strong>\n <span class=\"setup-apikey-category\">${p.category}</span>\n ${justSaved ? html`<span class=\"setup-apikey-badge saved\">Saved</span>` : nothing}\n ${justRemoved ? html`<span class=\"setup-apikey-badge removed\">Removed</span>` : nothing}\n ${justDisabled ? html`<span class=\"setup-apikey-badge removed\">Disabled</span>` : nothing}\n ${justEnabled ? html`<span class=\"setup-apikey-badge saved\">Enabled</span>` : nothing}\n ${p.disabled && !justEnabled ? html`<span class=\"setup-apikey-badge apikey-disabled\">Off</span>` : nothing}\n </div>\n <div class=\"setup-apikey-input\">\n <input\n type=\"password\"\n .value=${p.key ?? \"\"}\n placeholder=\"Enter key\"\n ?disabled=${state.apiKeyBusy || p.disabled}\n @input=${(e: Event) => handleInput(p.id, e)}\n @keydown=${(e: KeyboardEvent) => { if (e.key === \"Enter\") handleSave(p.id, e.target as HTMLElement); }}\n />\n <button\n class=\"setup-apikey-icon-btn setup-apikey-eye\"\n style=${p.hasKey ? \"\" : \"display: none;\"}\n title=\"Toggle visibility\"\n @click=${toggleVisibility}\n >${icons.eye}</button>\n ${isSaving\n ? html`<span class=\"setup-apikey-badge saving\">Saving\\u2026</span>`\n : html`<button\n class=\"setup-apikey-save setup-button\"\n style=\"display: none;\"\n ?disabled=${state.apiKeyBusy}\n @click=${(e: Event) => handleSave(p.id, e.currentTarget as HTMLElement)}\n >Save</button>`\n }\n ${p.hasKey && !isSaving ? html`\n <button\n class=\"setup-apikey-icon-btn ${p.disabled ? \"\" : \"active\"}\"\n title=\"${p.disabled ? \"Enable\" : \"Disable\"}\"\n ?disabled=${state.apiKeyBusy}\n @click=${() => state.onApiKeyDisable(p.id, !p.disabled)}\n >${icons.power}</button>\n <button\n class=\"setup-apikey-icon-btn danger\"\n title=\"Remove key\"\n ?disabled=${state.apiKeyBusy}\n @click=${() => state.onApiKeyRemove(p.id)}\n >${icons.trash}</button>\n ` : nothing}\n </div>\n </div>\n `;\n };\n\n return html`\n <div class=\"setup-info-overlay\" style=\"align-items: flex-start; padding-top: 72px;\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onApiKeyModalClose();\n }\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 480px;\">\n <h3 style=\"margin: 0 0 4px; text-align: center;\">API Keys</h3>\n <div class=\"setup-apikey-list\">\n ${state.apiKeyError ? html`<p class=\"setup-error\" style=\"margin: 0;\">${state.apiKeyError}</p>` : nothing}\n ${primary.map(renderProviderRow)}\n ${advanced.length > 0 ? html`\n <details class=\"setup-apikey-advanced\">\n <summary>Additional keys</summary>\n ${advanced.map(renderProviderRow)}\n </details>\n ` : nothing}\n </div>\n </div>\n </div>\n `;\n}\n\n/** Render software update status row in the dashboard */\nfunction renderUpdateRow(state: SetupViewState) {\n const statusLight: \"good\" | \"partial\" | \"unknown\" =\n state.updateAvailable === null\n ? \"unknown\"\n : state.updateAvailable\n ? \"partial\"\n : \"good\";\n\n const versionText =\n state.updateAvailable && state.latestVersion\n ? `v${state.currentVersion} → v${state.latestVersion}`\n : state.currentVersion\n ? `v${state.currentVersion}`\n : \"Unknown\";\n\n const isBusy = state.updateChecking || state.updateRunning;\n\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(statusLight)}\n <div class=\"setup-status-info\">\n <strong>Software</strong>\n <span>${versionText}</span>\n </div>\n ${renderInfoButton(\"update\", state)}\n ${state.updateAvailable\n ? html`\n <button\n class=\"setup-status-action ${isBusy ? \"spinning\" : \"\"}\"\n ?disabled=${isBusy}\n @click=${state.onUpdateRun}\n title=\"Update Now\"\n >\n ${state.updateRunning ? icons.loader : icons.download}\n </button>\n `\n : html`\n <button\n class=\"setup-status-action ${isBusy ? \"spinning\" : \"\"}\"\n ?disabled=${isBusy}\n @click=${state.onUpdateCheck}\n title=\"Check for Updates\"\n >\n ${icons.rotateCw}\n </button>\n `}\n </div>\n `;\n}\n\n/** Auth mode labels for display */\nconst AUTH_MODE_LABELS: Record<string, string> = {\n anonymous: \"Open access\",\n verified: \"Phone OTP\",\n choice: \"Visitor chooses\",\n};\n\n/** Render Public Chat toggle row in the dashboard */\nfunction renderPublicChatRow(state: SetupViewState) {\n const enabled = state.publicChatEnabled;\n const status: \"good\" | \"unknown\" = enabled ? \"good\" : \"unknown\";\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(status)}\n <div class=\"setup-status-info\">\n <strong>Public Chat</strong>\n <span>${enabled ? \"Enabled\" : \"Disabled\"}</span>\n </div>\n ${renderInfoButton(\"public-chat\", state)}\n ${enabled ? html`<button\n class=\"setup-info-btn\"\n @click=${state.onPublicChatSettingsOpen}\n title=\"Public Chat settings\"\n >${icons.settings}</button>` : nothing}\n <button\n class=\"setup-info-btn\"\n title=\"${enabled ? \"Disable public chat\" : \"Enable public chat\"}\"\n ?disabled=${state.publicChatBusy}\n @click=${state.onPublicChatToggle}\n >${enabled ? icons.powerOff : icons.power}</button>\n </div>\n `;\n}\n\n/** Public Chat settings modal — auth mode, greeting, SMS, email, widget code */\nfunction renderPublicChatSettingsModal(state: SetupViewState) {\n if (!state.publicChatSettingsOpen) return nothing;\n\n const closeModal = () => state.onPublicChatSettingsClose();\n const hasGreeting = Boolean(state.publicChatGreeting);\n const showVerify = state.publicChatAuthMode === \"verified\" || state.publicChatAuthMode === \"choice\";\n const verifyMethods = state.publicChatVerifyMethods.length > 0 ? state.publicChatVerifyMethods : [\"whatsapp\", \"sms\"];\n const hasWhatsApp = verifyMethods.includes(\"whatsapp\");\n const hasSms = verifyMethods.includes(\"sms\");\n const hasEmail = verifyMethods.includes(\"email\");\n // Use per-account WhatsApp status (not the global channel status) so multi-account\n // setups correctly reflect whether THIS account has a paired WhatsApp device.\n const ws = getSelectedWorkspace(state);\n const waAccount = ws ? resolveWorkspaceWhatsApp(ws, state) : null;\n const whatsAppConnected = !!(waAccount?.connected);\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) closeModal();\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 380px; max-height: 80vh; overflow-y: auto;\">\n <h3 style=\"margin: 0 0 12px; display: flex; align-items: center; justify-content: space-between;\">\n Public Chat\n <button\n style=\"background: transparent; border: none; color: var(--tasker-muted-grey); cursor: pointer; padding: 4px; font-size: 18px; line-height: 1;\"\n @click=${closeModal}\n title=\"Close\"\n >&times;</button>\n </h3>\n\n <!-- Auth mode -->\n <div style=\"display: flex; flex-direction: column; gap: 16px;\">\n <div>\n <div style=\"font-size: 13px; color: var(--tasker-white); margin-bottom: 6px;\">Visitor access</div>\n <select\n class=\"setup-select-sm\"\n style=\"width: 100%;\"\n ?disabled=${state.publicChatBusy}\n @change=${(e: Event) => {\n const val = (e.target as HTMLSelectElement).value;\n state.onPublicChatAuthModeChange(val as \"anonymous\" | \"verified\" | \"choice\");\n }}\n >\n <option value=\"anonymous\" ?selected=${state.publicChatAuthMode === \"anonymous\"}>Open access</option>\n <option value=\"verified\" ?selected=${state.publicChatAuthMode === \"verified\"}>Identity verification</option>\n <option value=\"choice\" ?selected=${state.publicChatAuthMode === \"choice\"}>Visitor chooses</option>\n </select>\n </div>\n\n <div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin: 4px 0;\"></div>\n\n <!-- Greeting -->\n <div>\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer; flex: 1;\">\n <input\n type=\"checkbox\"\n .checked=${hasGreeting}\n ?disabled=${state.publicChatGreetingBusy}\n @change=${state.onPublicChatGreetingToggle}\n style=\"accent-color: #22c55e;\"\n />\n <span style=\"font-size: 13px; color: var(--tasker-white);\">Greeting</span>\n </label>\n ${hasGreeting ? html`<button\n class=\"setup-info-btn\"\n title=\"Regenerate greeting\"\n ?disabled=${state.publicChatGreetingBusy}\n @click=${state.onPublicChatGreetingRegenerate}\n >${state.publicChatGreetingBusy ? icons.loader : icons.refreshCw}</button>` : nothing}\n </div>\n ${hasGreeting || state.publicChatGreetingBusy ? html`\n <textarea\n style=\"width: 100%; margin-top: 8px; font-size: 12px; padding: 8px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.1); background: rgba(0,0,0,0.2); color: var(--tasker-white); resize: vertical; min-height: 60px; font-family: inherit; box-sizing: border-box;\"\n ?disabled=${state.publicChatGreetingBusy}\n .value=${state.publicChatGreetingBusy ? \"Generating...\" : state.publicChatGreeting}\n @blur=${(e: Event) => {\n const text = (e.target as HTMLTextAreaElement).value.trim();\n if (text && text !== state.publicChatGreeting) {\n state.onPublicChatGreetingSave(text);\n }\n }}\n ></textarea>\n ` : html`\n <div style=\"font-size: 12px; color: var(--tasker-text-grey); opacity: 0.7; margin-top: 4px;\">\n Agent sends a welcome message when chat opens\n </div>\n `}\n </div>\n\n ${showVerify ? html`\n <div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin: 4px 0;\"></div>\n\n <!-- Verify methods -->\n <div>\n <div style=\"font-size: 13px; color: var(--tasker-white); margin-bottom: 6px;\">Verification methods</div>\n <div style=\"display: flex; flex-direction: column; gap: 8px; text-align: left;\">\n <label style=\"display: flex; align-items: flex-start; gap: 6px; ${whatsAppConnected ? \"cursor: pointer;\" : \"cursor: not-allowed; opacity: 0.5;\"}\">\n <input\n type=\"checkbox\"\n .checked=${hasWhatsApp && whatsAppConnected}\n ?disabled=${!whatsAppConnected || state.publicChatEmailBusy || (!hasSms && !hasEmail && hasWhatsApp)}\n @change=${(e: Event) => {\n const checked = (e.target as HTMLInputElement).checked;\n const next = checked\n ? [...verifyMethods.filter((m: string) => m !== \"whatsapp\"), \"whatsapp\"]\n : verifyMethods.filter((m: string) => m !== \"whatsapp\");\n if (next.length > 0) state.onPublicChatEmailSave(state.publicChatEmailFrom, next);\n }}\n style=\"accent-color: #22c55e; margin-top: 2px;\"\n />\n <div>\n <span style=\"font-size: 12px; color: var(--tasker-white);\">WhatsApp</span>\n <div style=\"font-size: 11px; color: var(--tasker-text-grey); opacity: 0.7;\">\n ${whatsAppConnected ? \"Phone OTP via WhatsApp\" : \"No WhatsApp account connected on this account\"}\n </div>\n </div>\n </label>\n <label style=\"display: flex; align-items: flex-start; gap: 6px; cursor: pointer;\">\n <input\n type=\"checkbox\"\n .checked=${hasSms}\n ?disabled=${state.publicChatEmailBusy || (!hasWhatsApp && !hasEmail && hasSms)}\n @change=${(e: Event) => {\n const checked = (e.target as HTMLInputElement).checked;\n const next = checked\n ? [...verifyMethods.filter((m: string) => m !== \"sms\"), \"sms\"]\n : verifyMethods.filter((m: string) => m !== \"sms\");\n if (next.length > 0) state.onPublicChatEmailSave(state.publicChatEmailFrom, next);\n }}\n style=\"accent-color: #22c55e; margin-top: 2px;\"\n />\n <div>\n <span style=\"font-size: 12px; color: var(--tasker-white);\">SMS</span>\n <div style=\"font-size: 11px; color: var(--tasker-text-grey); opacity: 0.7;\">Brevo API key + SMS credits</div>\n </div>\n </label>\n <label style=\"display: flex; align-items: flex-start; gap: 6px; cursor: pointer;\">\n <input\n type=\"checkbox\"\n .checked=${hasEmail}\n ?disabled=${state.publicChatEmailBusy || (!hasWhatsApp && !hasSms && hasEmail)}\n @change=${(e: Event) => {\n const checked = (e.target as HTMLInputElement).checked;\n const next = checked\n ? [...verifyMethods.filter((m: string) => m !== \"email\"), \"email\"]\n : verifyMethods.filter((m: string) => m !== \"email\");\n if (next.length > 0) state.onPublicChatEmailSave(state.publicChatEmailFrom, next);\n }}\n style=\"accent-color: #22c55e; margin-top: 2px;\"\n />\n <div>\n <span style=\"font-size: 12px; color: var(--tasker-white);\">Email</span>\n <div style=\"font-size: 11px; color: var(--tasker-text-grey); opacity: 0.7;\">Brevo API key</div>\n </div>\n </label>\n </div>\n </div>\n\n ` : nothing}\n\n <div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin: 4px 0;\"></div>\n\n <!-- Widget code snippet -->\n <button\n class=\"btn\"\n style=\"width: 100%; font-size: 12px; padding: 8px;\"\n @click=${() => { closeModal(); state.onPublicChatWidgetModalOpen(); }}\n >Widget embed code</button>\n </div>\n </div>\n </div>\n `;\n}\n\n/** Render the widget embed code snippet modal */\nfunction renderWidgetSnippetModal(state: SetupViewState) {\n if (!state.publicChatWidgetModalOpen) return nothing;\n\n const publicUrl = state.tailscaleStatus?.publicUrl ?? state.tailscaleStatus?.tailnetUrl ?? null;\n const accountId = state.publicChatAccountId ?? \"your-account-id\";\n const serverUrl = publicUrl ?? \"https://YOUR-PUBLIC-URL\";\n\n const snippet = `<script src=\"${serverUrl}/public/widget.js\"><\\/script>\n<script>\n Taskmaster.init({\n server: \"${serverUrl}\",\n accountId: \"${accountId}\"\n });\n<\\/script>`;\n\n const handleCopy = async (e: Event) => {\n const btn = e.currentTarget as HTMLButtonElement;\n try {\n await navigator.clipboard.writeText(snippet);\n } catch {\n const el = document.createElement(\"textarea\");\n el.value = snippet;\n el.style.position = \"fixed\";\n el.style.opacity = \"0\";\n document.body.appendChild(el);\n el.select();\n document.execCommand(\"copy\");\n document.body.removeChild(el);\n }\n const prev = btn.textContent;\n btn.textContent = \"Copied!\";\n setTimeout(() => { btn.textContent = prev; }, 1500);\n };\n\n const handleDownload = () => {\n const a = document.createElement(\"a\");\n a.href = \"data:text/plain;charset=utf-8,\" + encodeURIComponent(snippet);\n a.download = \"taskmaster-widget.txt\";\n a.click();\n };\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onPublicChatWidgetModalClose();\n }\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 480px; position: relative;\">\n <h3 style=\"margin: 0 0 12px; display: flex; align-items: center; justify-content: space-between;\">\n Widget Code Snippet\n <button\n style=\"background: transparent; border: none; color: var(--tasker-muted-grey); cursor: pointer; padding: 4px; font-size: 18px; line-height: 1;\"\n @click=${() => state.onPublicChatWidgetModalClose()}\n title=\"Close\"\n >&times;</button>\n </h3>\n <p style=\"font-size: 0.85em; opacity: 0.7; margin: 0 0 12px;\">\n Paste this snippet into your website's HTML to add the chat widget.\n </p>\n ${!publicUrl ? html`<p style=\"font-size: 0.8em; color: #eab308; margin: 0 0 12px;\">\n No public URL detected. Enable Remote Access with internet access to get a live URL.\n </p>` : nothing}\n <pre style=\"background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.1); border-radius: 8px; padding: 14px; font-size: 12px; line-height: 1.5; overflow-x: auto; white-space: pre-wrap; word-break: break-all; margin: 0 0 16px;\">${snippet}</pre>\n <div style=\"display: flex; gap: 8px;\">\n <button class=\"btn primary\" style=\"flex: 1;\" @click=${handleCopy}>Copy</button>\n <button class=\"btn\" style=\"flex: 1;\" @click=${handleDownload}>Download</button>\n </div>\n </div>\n </div>\n `;\n}\n\n\n// ── Agent Settings ──────────────────────────────────────────────────\n\n/** Curated Anthropic models for the agent model selector. */\nconst AGENT_CURATED_MODELS: Array<{ id: string; shortName: string; description: string }> = [\n { id: \"claude-opus-4-6\", shortName: \"Opus\", description: \"Most capable\" },\n { id: \"claude-sonnet-4-5-20250929\", shortName: \"Sonnet\", description: \"Fast & capable\" },\n { id: \"claude-haiku-4-5-20251001\", shortName: \"Haiku\", description: \"Fastest\" },\n];\n\nconst AGENT_THINKING_LEVELS: Array<{ value: string; label: string }> = [\n { value: \"off\", label: \"Off\" },\n { value: \"minimal\", label: \"Minimal\" },\n { value: \"low\", label: \"Low\" },\n { value: \"medium\", label: \"Medium\" },\n { value: \"high\", label: \"High\" },\n];\n\n/** Default model when none is explicitly configured. */\nconst AGENT_DEFAULT_MODEL_KEY = \"anthropic/claude-sonnet-4-5-20250929\";\n\nfunction renderAgentSettingsRow(state: SetupViewState) {\n const agents = state.agentSettingsAgents ?? [];\n const summary = agents.length > 0\n ? agents.map((a) => {\n const shortModel = a.model\n ? AGENT_CURATED_MODELS.find((m) => a.model === `anthropic/${m.id}`)?.shortName ?? a.model.split(\"/\").pop()\n : \"Sonnet\";\n return shortModel;\n }).join(\" / \")\n : \"Default\";\n\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"good\")}\n <div class=\"setup-status-info\">\n <strong>Agents</strong>\n <span>${summary}</span>\n </div>\n <button class=\"setup-link-btn\" @click=${state.onAgentSettingsToggle}>Edit</button>\n </div>\n `;\n}\n\nfunction renderAgentSettingsModal(state: SetupViewState) {\n if (!state.agentSettingsOpen) return nothing;\n\n const agents = state.agentSettingsAgents ?? [];\n if (agents.length === 0) return nothing;\n\n const catalog = state.agentSettingsModelCatalog ?? [];\n const available = new Set(catalog.filter((m) => m.provider === \"anthropic\").map((m) => m.id));\n const models = AGENT_CURATED_MODELS.filter((m) => available.has(m.id));\n\n const closeModal = () => state.onAgentSettingsToggle();\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) closeModal();\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 400px;\">\n <h3>Agent Settings</h3>\n <div style=\"display: flex; flex-direction: column; gap: 20px; margin-top: 16px;\">\n ${agents.map((agent) => {\n const currentModelKey = agent.model ?? AGENT_DEFAULT_MODEL_KEY;\n const currentThinking = agent.thinkingLevel ?? \"off\";\n const isAdmin = agent.id.endsWith(\"-admin\") || agent.id === \"admin\";\n\n return html`\n <div style=\"display: flex; flex-direction: column; gap: 10px;\">\n <div style=\"font-size: 14px; font-weight: 600; color: var(--tasker-white);\">\n ${agent.label || (isAdmin ? \"Admin\" : \"Public\")}\n </div>\n ${models.length > 0\n ? html`\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <div style=\"font-size: 13px; color: var(--tasker-text-grey); min-width: 70px;\">Model</div>\n <select\n class=\"setup-model-select\"\n style=\"flex: 1;\"\n .value=${currentModelKey}\n @change=${(e: Event) => {\n state.onAgentModelChange(agent.id, (e.target as HTMLSelectElement).value);\n }}\n >\n ${models.map(\n (m) => html`\n <option value=${\"anthropic/\" + m.id} ?selected=${currentModelKey === \"anthropic/\" + m.id}>\n ${m.shortName} — ${m.description}\n </option>\n `,\n )}\n </select>\n </div>\n `\n : nothing}\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <div style=\"font-size: 13px; color: var(--tasker-text-grey); min-width: 70px;\">Thinking</div>\n <select\n class=\"setup-model-select\"\n style=\"flex: 1;\"\n .value=${currentThinking}\n @change=${(e: Event) => {\n state.onAgentThinkingChange(agent.id, (e.target as HTMLSelectElement).value);\n }}\n >\n ${AGENT_THINKING_LEVELS.map(\n (l) => html`\n <option value=${l.value} ?selected=${currentThinking === l.value}>\n ${l.label}\n </option>\n `,\n )}\n </select>\n </div>\n ${agent !== agents[agents.length - 1]\n ? html`<div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin-top: 4px;\"></div>`\n : nothing}\n </div>\n `;\n })}\n </div>\n <div style=\"border-top: 1px solid rgba(255,255,255,0.1); margin-top: 16px; padding-top: 16px;\">\n <div style=\"font-size: 13px; font-weight: 600; color: var(--tasker-text-grey); margin-bottom: 12px; text-transform: uppercase; letter-spacing: 0.05em;\">Memory Search</div>\n <div style=\"display: flex; flex-direction: column; gap: 10px;\">\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <div style=\"font-size: 13px; color: var(--tasker-text-grey); min-width: 70px;\">Provider</div>\n <select\n class=\"setup-model-select\"\n style=\"flex: 1;\"\n .value=${state.memoryProvider}\n @change=${(e: Event) => {\n state.onMemoryProviderChange((e.target as HTMLSelectElement).value);\n }}\n >\n <option value=\"local\" ?selected=${state.memoryProvider === \"local\"}>Local (on-device)</option>\n <option value=\"auto\" ?selected=${state.memoryProvider === \"auto\"}>Auto (remote if key available)</option>\n <option value=\"gemini\" ?selected=${state.memoryProvider === \"gemini\"}>Google AI</option>\n <option value=\"openai\" ?selected=${state.memoryProvider === \"openai\"}>OpenAI</option>\n </select>\n </div>\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <div style=\"font-size: 13px; color: var(--tasker-text-grey); min-width: 70px;\">Fallback</div>\n <select\n class=\"setup-model-select\"\n style=\"flex: 1;\"\n .value=${state.memoryFallback}\n @change=${(e: Event) => {\n state.onMemoryFallbackChange((e.target as HTMLSelectElement).value);\n }}\n >\n <option value=\"none\" ?selected=${state.memoryFallback === \"none\"}>None</option>\n <option value=\"local\" ?selected=${state.memoryFallback === \"local\"}>Local (on-device)</option>\n <option value=\"gemini\" ?selected=${state.memoryFallback === \"gemini\"}>Google AI</option>\n <option value=\"openai\" ?selected=${state.memoryFallback === \"openai\"}>OpenAI</option>\n </select>\n </div>\n </div>\n </div>\n <button\n class=\"setup-button secondary\"\n style=\"margin-top: 20px; width: 100%; padding: 10px;\"\n @click=${closeModal}\n >\n Close\n </button>\n </div>\n </div>\n `;\n}\n\n\n/** Render Branding row with expandable colour/logo editor */\nfunction renderBrandingRow(state: SetupViewState) {\n const hasAny = Boolean(state.brandAccentColor || state.brandBackgroundColor || state.brandHasLogo);\n const status: \"good\" | \"unknown\" = hasAny ? \"good\" : \"unknown\";\n const busy = state.brandingBusy;\n\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(status)}\n <div class=\"setup-status-info\">\n <strong>Branding</strong>\n <span>${hasAny ? \"Customised\" : \"Default\"}</span>\n </div>\n ${renderInfoButton(\"branding\", state)}\n <button\n class=\"setup-link-btn\"\n ?disabled=${busy}\n @click=${state.onBrandingToggle}\n >${busy ? \"...\" : \"Edit\"}</button>\n </div>\n `;\n}\n\nfunction renderBrandingModal(state: SetupViewState) {\n if (!state.brandingExpanded) return nothing;\n\n const busy = state.brandingBusy;\n const workspace = state.wsProps?.selectedWorkspace;\n const logoUrl = state.brandHasLogo && workspace ? `/brand-logo/${encodeURIComponent(workspace)}` : \"\";\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onBrandingToggle();\n }\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 400px; position: relative;\">\n <h3 style=\"margin-right: 24px;\">Branding</h3>\n <button class=\"branding-modal-close\" @click=${state.onBrandingToggle}>&times;</button>\n\n <!-- Logo upload -->\n <div class=\"branding-row\">\n <label class=\"branding-label\">Logo</label>\n <div class=\"branding-logo-area\">\n ${logoUrl\n ? html`\n <img class=\"branding-logo-preview\" src=\"${logoUrl}?t=${Date.now()}\" alt=\"Logo\" />\n <button class=\"branding-remove-btn\" ?disabled=${busy} @click=${state.onBrandLogoRemove}>Remove</button>\n `\n : html`<span class=\"branding-no-logo\">No logo</span>`}\n <label class=\"branding-upload-btn ${busy ? \"disabled\" : \"\"}\">\n Upload\n <input\n type=\"file\"\n accept=\"image/png,image/jpeg,image/svg+xml,image/webp\"\n style=\"display: none;\"\n ?disabled=${busy}\n @change=${(e: Event) => {\n const input = e.target as HTMLInputElement;\n const file = input.files?.[0];\n if (file) state.onBrandLogoUpload(file);\n input.value = \"\";\n }}\n />\n </label>\n </div>\n </div>\n\n <!-- Accent colour -->\n <div class=\"branding-row\">\n <label class=\"branding-label\">Accent colour</label>\n <div class=\"branding-color-pick\">\n <input\n type=\"color\"\n .value=${state.brandAccentColor || \"#00d4ff\"}\n ?disabled=${busy}\n @change=${(e: Event) => {\n state.onBrandAccentColorChange((e.target as HTMLInputElement).value);\n }}\n />\n <input\n type=\"text\"\n class=\"branding-color-hex-input\"\n .value=${state.brandAccentColor || \"#00d4ff\"}\n ?disabled=${busy}\n placeholder=\"#00d4ff\"\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") {\n const val = (e.target as HTMLInputElement).value.trim();\n if (/^#[0-9a-fA-F]{6}$/.test(val)) state.onBrandAccentColorChange(val);\n }\n }}\n @blur=${(e: Event) => {\n const val = (e.target as HTMLInputElement).value.trim();\n if (/^#[0-9a-fA-F]{6}$/.test(val) && val !== (state.brandAccentColor || \"#00d4ff\")) {\n state.onBrandAccentColorChange(val);\n }\n }}\n />\n ${state.brandAccentColor\n ? html`<button class=\"branding-clear-btn\" ?disabled=${busy} @click=${() => state.onBrandAccentColorChange(\"\")}>Clear</button>`\n : nothing}\n </div>\n </div>\n\n <!-- Background colour -->\n <div class=\"branding-row\">\n <label class=\"branding-label\">Background tint</label>\n <div class=\"branding-color-pick\">\n <input\n type=\"color\"\n .value=${state.brandBackgroundColor || \"#12141a\"}\n ?disabled=${busy}\n @change=${(e: Event) => {\n state.onBrandBackgroundColorChange((e.target as HTMLInputElement).value);\n }}\n />\n <input\n type=\"text\"\n class=\"branding-color-hex-input\"\n .value=${state.brandBackgroundColor || \"#12141a\"}\n ?disabled=${busy}\n placeholder=\"#12141a\"\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") {\n const val = (e.target as HTMLInputElement).value.trim();\n if (/^#[0-9a-fA-F]{6}$/.test(val)) state.onBrandBackgroundColorChange(val);\n }\n }}\n @blur=${(e: Event) => {\n const val = (e.target as HTMLInputElement).value.trim();\n if (/^#[0-9a-fA-F]{6}$/.test(val) && val !== (state.brandBackgroundColor || \"#12141a\")) {\n state.onBrandBackgroundColorChange(val);\n }\n }}\n />\n ${state.brandBackgroundColor\n ? html`<button class=\"branding-clear-btn\" ?disabled=${busy} @click=${() => state.onBrandBackgroundColorChange(\"\")}>Clear</button>`\n : nothing}\n </div>\n </div>\n\n ${state.brandAccentColor || state.brandBackgroundColor || state.brandHasLogo\n ? html`\n <button class=\"branding-reset-btn\" ?disabled=${busy} @click=${state.onBrandReset}>\n Reset to defaults\n </button>\n `\n : nothing}\n\n </div>\n </div>\n `;\n}\n\n/** Tailscale connection modal — connecting, auth, success, error phases */\nfunction renderTailscaleConnectModal(state: SetupViewState) {\n const busy = state.tailscaleBusy;\n const authUrl = state.tailscaleAuthUrl;\n const error = state.tailscaleError;\n const success = state.tailscaleConnectSuccess;\n const progress = state.tailscaleConnectProgress;\n const message = state.tailscaleConnectMessage;\n\n // Only show when busy OR showing a brief success/error flash\n if (!busy && !success && !error) return nothing;\n\n // Error phase\n if (error && !busy) {\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) state.onTailscaleErrorDismiss();\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 380px; text-align: center;\">\n <h3>Remote Access</h3>\n <div style=\"color: #ef4444; font-size: 40px; margin: 12px 0;\">&#x2717;</div>\n <p style=\"color: #ef4444; font-size: 14px; margin: 0 0 16px;\">${error}</p>\n <div style=\"display: flex; gap: 12px; justify-content: center;\">\n <button\n class=\"setup-button primary\"\n @click=${() => { state.onTailscaleEnable(); }}\n >Try Again</button>\n <button\n class=\"setup-button\"\n @click=${state.onTailscaleErrorDismiss}\n >Close</button>\n </div>\n </div>\n </div>\n `;\n }\n\n // Success phase\n if (success) {\n return html`\n <div class=\"setup-info-overlay\">\n <div class=\"setup-info-card\" style=\"max-width: 380px; text-align: center;\">\n <h3>Remote Access</h3>\n <div style=\"color: #22c55e; font-size: 48px; margin: 12px 0;\">&#x2713;</div>\n <p style=\"color: #22c55e; font-size: 16px; font-weight: 600; margin: 0;\">Connected!</p>\n </div>\n </div>\n `;\n }\n\n // Auth phase — QR code + link\n if (authUrl) {\n return html`\n <div class=\"setup-info-overlay\">\n <div class=\"setup-info-card\" style=\"max-width: 380px; text-align: center;\">\n <h3>Remote Access</h3>\n <div class=\"tailscale-progress-bar\">\n <div class=\"tailscale-progress-fill\" style=\"width: ${progress}%;\"></div>\n </div>\n <p style=\"color: var(--tasker-text-grey); font-size: 13px; margin: 12px 0 16px;\">\n Scan the QR code with your phone or open the link to sign in to your Tailscale account.\n </p>\n <div style=\"margin: 0 0 12px;\">\n <img\n src=\"https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=${encodeURIComponent(authUrl)}\"\n alt=\"Tailscale auth QR code\"\n style=\"width: 180px; height: 180px; border-radius: 8px; background: #fff; padding: 8px;\"\n />\n </div>\n <div style=\"margin-bottom: 16px;\">\n <a\n href=\"${authUrl}\"\n target=\"_blank\"\n rel=\"noopener\"\n style=\"color: var(--tasker-link, #60a5fa); font-size: 13px; word-break: break-all;\"\n >${authUrl}</a>\n </div>\n <p class=\"tailscale-pulse\" style=\"font-size: 13px; color: var(--tasker-text-grey); margin: 0;\">\n Waiting for authentication...\n </p>\n </div>\n </div>\n `;\n }\n\n // Connecting phase — spinner + progress bar + rotating messages\n return html`\n <div class=\"setup-info-overlay\">\n <div class=\"setup-info-card\" style=\"max-width: 380px; text-align: center;\">\n <h3>Remote Access</h3>\n <div class=\"setup-spinner\" style=\"margin: 16px auto;\"></div>\n <div class=\"tailscale-progress-bar\">\n <div class=\"tailscale-progress-fill\" style=\"width: ${progress}%;\"></div>\n </div>\n <p style=\"font-size: 14px; color: var(--tasker-text-grey); margin: 12px 0 0;\">${message}</p>\n </div>\n </div>\n `;\n}\n\n/** Render combined Remote Access (Tailscale) row — admin-only */\nfunction renderRemoteAccessRow(state: SetupViewState) {\n if (!state.isMaster) return nothing;\n\n const ts = state.tailscaleStatus;\n const busy = state.tailscaleBusy;\n const authUrl = state.tailscaleAuthUrl;\n\n // Still loading status\n if (!ts) {\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"unknown\")}\n <div class=\"setup-status-info\">\n <strong>Remote Access</strong>\n <span>Checking...</span>\n </div>\n ${renderInfoButton(\"remote-access\", state)}\n </div>\n `;\n }\n\n // Not installed\n if (!ts.installed) {\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"unknown\")}\n <div class=\"setup-status-info\">\n <strong>Remote Access</strong>\n <span>Tailscale not installed</span>\n </div>\n ${renderInfoButton(\"remote-access\", state)}\n </div>\n `;\n }\n\n // Not logged in (connect modal handles QR/progress when busy)\n if (authUrl || !ts.loggedIn) {\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"partial\")}\n <div class=\"setup-status-info\">\n <strong>Remote Access</strong>\n <span>${busy ? \"Connecting...\" : \"Not connected\"}</span>\n </div>\n ${renderInfoButton(\"remote-access\", state)}\n <button\n class=\"setup-link-btn\"\n ?disabled=${busy}\n @click=${state.onTailscaleEnable}\n >${busy ? \"...\" : \"Connect\"}</button>\n </div>\n `;\n }\n\n // Logged in, serve not enabled\n if (!ts.serveEnabled) {\n const serveEnableUrl = state.tailscaleServeEnableUrl;\n return html`\n <div class=\"setup-status-item\" style=\"flex-wrap: wrap;\">\n ${renderStatusLight(\"partial\")}\n <div class=\"setup-status-info\">\n <strong>Remote Access</strong>\n <span>Connected (not enabled)</span>\n </div>\n ${renderInfoButton(\"remote-access\", state)}\n <button\n class=\"setup-info-btn\"\n title=\"Enable remote access\"\n ?disabled=${busy}\n @click=${state.onTailscaleServeEnable}\n >${icons.power}</button>\n ${serveEnableUrl\n ? html`<div style=\"flex-basis: 100%; padding-top: 6px;\">\n <p style=\"margin: 0 0 4px; font-size: 13px; color: #f59e0b;\">\n Serve must be enabled on your Tailscale account first.\n </p>\n <a\n href=\"${serveEnableUrl}\"\n target=\"_blank\"\n rel=\"noopener\"\n style=\"color: var(--tasker-link, #60a5fa); font-size: 13px; word-break: break-all;\"\n >Open Tailscale admin to enable Serve &rarr;</a>\n </div>`\n : state.tailscaleError\n ? html`<p style=\"flex-basis: 100%; margin: 6px 0 0; font-size: 13px; color: #ef4444;\">${state.tailscaleError}</p>`\n : nothing}\n </div>\n `;\n }\n\n // Serve enabled in config but not actually active\n if (!ts.serveActive) {\n return html`\n <div class=\"setup-status-item\" style=\"flex-wrap: wrap;\">\n ${renderStatusLight(\"bad\")}\n <div class=\"setup-status-info\">\n <strong>Remote Access</strong>\n <span>Enabled but not active</span>\n </div>\n ${renderInfoButton(\"remote-access\", state)}\n <div style=\"flex-basis: 100%; padding-top: 4px;\">\n <p style=\"margin: 0; font-size: 13px; color: #f59e0b;\">\n Remote access is configured but not running. Try disabling and re-enabling, or check that Tailscale is connected.\n </p>\n </div>\n </div>\n `;\n }\n\n // Serve active — show tailnet URL, mode, and actions\n const tailnetUrl = ts.tailnetUrl ?? `https://${ts.hostname}`;\n const enableUrl = state.tailscaleFunnelEnableUrl;\n\n // Confirm flow drops below; errors/enableUrl drop below\n const confirmOrError = state.tailscaleDisableConfirm\n ? html`<div style=\"flex-basis: 100%; padding-top: 6px; display: flex; gap: 8px; align-items: center;\">\n <span style=\"font-size: 12px; opacity: 0.8;\">Disable remote access?</span>\n <button\n class=\"setup-link-btn\"\n style=\"font-size: 12px; padding: 2px 8px; color: #ef4444;\"\n ?disabled=${busy}\n @click=${state.onTailscaleServeDisable}\n >Confirm</button>\n <button\n class=\"setup-link-btn\"\n style=\"font-size: 12px; padding: 2px 8px;\"\n @click=${state.onTailscaleDisableConfirmToggle}\n >Cancel</button>\n </div>`\n : enableUrl\n ? html`<div style=\"flex-basis: 100%; padding-top: 6px;\">\n <p style=\"margin: 0 0 4px; font-size: 13px; color: #f59e0b;\">\n Funnel must be enabled on your Tailscale account first.\n </p>\n <a\n href=\"${enableUrl}\"\n target=\"_blank\"\n rel=\"noopener\"\n style=\"color: var(--tasker-link, #60a5fa); font-size: 13px; word-break: break-all;\"\n >Open Tailscale admin to enable Funnel &rarr;</a>\n </div>`\n : state.tailscaleError\n ? html`<p style=\"flex-basis: 100%; margin: 6px 0 0; font-size: 13px; color: #ef4444;\">${state.tailscaleError}</p>`\n : nothing;\n\n return html`\n <div class=\"setup-status-item\" style=\"flex-wrap: wrap;\">\n ${renderStatusLight(\"good\")}\n <div class=\"setup-status-info\">\n <strong>Remote Access</strong>\n <span>Active</span>\n </div>\n ${renderInfoButton(\"remote-access\", state)}\n ${ts.funnelEnabled\n ? html`<button\n class=\"setup-info-btn\"\n title=\"Disable internet access\"\n ?disabled=${busy}\n @click=${state.onTailscaleFunnelDisable}\n >${icons.globeOff}</button>`\n : html`<button\n class=\"setup-info-btn\"\n title=\"Enable internet access\"\n ?disabled=${busy}\n @click=${state.onTailscaleFunnelEnable}\n >${icons.globe}</button>`}\n <button\n class=\"setup-info-btn\"\n title=\"Disable remote access\"\n ?disabled=${busy}\n @click=${state.onTailscaleDisableConfirmToggle}\n >${icons.powerOff}</button>\n ${confirmOrError}\n </div>\n `;\n}\n\n// ---------------------------------------------------------------------------\n// WiFi row (Linux / Raspberry Pi only)\n// ---------------------------------------------------------------------------\n\n/** CSS signal-strength bars: 4 bars with increasing height, brand accent for active. */\nfunction renderSignalBars(signal: number) {\n const activeBars = signal >= 70 ? 4 : signal >= 50 ? 3 : signal >= 30 ? 2 : 1;\n const heights = [4, 7, 10, 14];\n return html`\n <span style=\"display: inline-flex; align-items: flex-end; gap: 2px; height: 14px; vertical-align: middle;\">\n ${heights.map(\n (h, i) => html`<span style=\"\n width: 3px;\n height: ${h}px;\n border-radius: 1px;\n background: ${i < activeBars ? \"var(--tasker-accent, #00e5ff)\" : \"rgba(255,255,255,0.15)\"};\n \"></span>`,\n )}\n </span>\n `;\n}\n\nfunction renderWifiRow(state: SetupViewState) {\n // Only show on Linux (Raspberry Pi)\n if (state.serverPlatform !== \"linux\") return nothing;\n\n const ws = state.wifiStatus;\n const busy = state.wifiBusy;\n\n // Still loading\n if (!ws) {\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"unknown\")}\n <div class=\"setup-status-info\">\n <strong>WiFi</strong>\n <span>Checking...</span>\n </div>\n </div>\n `;\n }\n\n // nmcli not available\n if (!ws.available) {\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"unknown\")}\n <div class=\"setup-status-info\">\n <strong>WiFi</strong>\n <span>NetworkManager not available</span>\n </div>\n </div>\n `;\n }\n\n const hasSaved = !!ws.savedSsid && !ws.connected;\n const statusLight = ws.connected ? \"good\" : \"partial\";\n const statusText = ws.connected\n ? html`${ws.ssid} ${ws.signal != null ? html`<span style=\"margin-left: 4px;\">${renderSignalBars(ws.signal)}</span>` : nothing}`\n : hasSaved\n ? html`${ws.savedSsid} <span style=\"opacity: 0.4;\">\\u2014 reconnecting\\u2026</span>`\n : \"Not connected\";\n\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(statusLight)}\n <div class=\"setup-status-info\">\n <strong>WiFi</strong>\n <span>${statusText}</span>\n ${ws.connected && ws.ip\n ? html`<span style=\"font-size: 11px; opacity: 0.5;\">${ws.ip}</span>`\n : nothing}\n </div>\n <button\n class=\"setup-link-btn\"\n ?disabled=${busy}\n @click=${state.onWifiModalToggle}\n >${busy ? \"...\" : \"Edit\"}</button>\n </div>\n `;\n}\n\n/** WiFi settings modal — scan, connect, disconnect, forget. */\nfunction renderWifiModal(state: SetupViewState) {\n if (!state.wifiModalOpen) return nothing;\n\n const ws = state.wifiStatus;\n const busy = state.wifiBusy;\n const networks = state.wifiNetworks;\n const selected = state.wifiSelectedSsid;\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onWifiModalToggle();\n }\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 420px; position: relative;\">\n <h3 style=\"margin-right: 24px;\">WiFi</h3>\n <button class=\"branding-modal-close\" @click=${state.onWifiModalToggle}>&times;</button>\n\n <!-- Current status -->\n ${ws?.connected\n ? html`\n <div style=\"display: flex; align-items: center; gap: 8px; margin-bottom: 12px;\">\n <span style=\"color: #22c55e;\">${icons.wifi}</span>\n <span style=\"font-size: 13px;\">${ws.ssid}${ws.signal != null ? html` ${renderSignalBars(ws.signal)}` : nothing}${ws.ip ? html` <span style=\"opacity: 0.5;\">(${ws.ip})</span>` : nothing}</span>\n <button\n class=\"setup-link-btn\"\n style=\"margin-left: auto; font-size: 12px;\"\n ?disabled=${busy}\n @click=${state.onWifiDisconnect}\n >Disconnect</button>\n </div>\n `\n : ws?.savedSsid\n ? html`\n <div style=\"display: flex; align-items: center; gap: 8px; margin-bottom: 12px;\">\n <span style=\"color: #eab308; opacity: 0.6;\">${icons.wifi}</span>\n <span style=\"font-size: 13px; opacity: 0.6;\">${ws.savedSsid} \\u2014 reconnecting\\u2026</span>\n </div>\n `\n : nothing}\n\n <!-- Scan button -->\n <button\n class=\"setup-button primary\"\n style=\"padding: 6px 16px; font-size: 13px; margin-bottom: 12px; width: 100%;\"\n ?disabled=${busy}\n @click=${state.onWifiScan}\n >${busy && networks.length === 0 ? \"Scanning...\" : \"Scan for networks\"}</button>\n\n ${state.wifiError\n ? html`<p style=\"margin: 0 0 8px; font-size: 13px; color: #ef4444;\">${state.wifiError}</p>`\n : nothing}\n\n <!-- Network list -->\n ${networks.length > 0\n ? html`\n <div style=\"\n max-height: 240px;\n overflow-y: auto;\n border: 1px solid rgba(255,255,255,0.1);\n border-radius: 6px;\n margin-bottom: 12px;\n \">\n ${networks.map((n) => {\n const isSaved = ws?.savedSsid === n.ssid;\n return html`\n <button\n style=\"\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: 8px 12px;\n background: ${selected === n.ssid ? \"rgba(255,255,255,0.1)\" : \"transparent\"};\n border: none;\n border-bottom: 1px solid rgba(255,255,255,0.06);\n color: inherit;\n font-size: 13px;\n cursor: pointer;\n text-align: left;\n \"\n @click=${() => {\n if (n.active) return;\n state.onWifiSelectSsid(selected === n.ssid ? null : n.ssid);\n }}\n >\n <span style=\"display: flex; align-items: center; gap: 8px;\">\n ${n.active\n ? html`<span style=\"color: #22c55e;\" title=\"Connected\">\\u2713</span>`\n : isSaved\n ? html`<span style=\"opacity: 0.4; font-size: 11px;\" title=\"Saved\">\\u2605</span>`\n : nothing}\n <span>${n.ssid}</span>\n </span>\n <span style=\"display: flex; align-items: center; gap: 8px;\">\n ${n.security !== \"Open\"\n ? html`<span style=\"opacity: 0.4; font-size: 11px;\" title=\"${n.security}\">\\uD83D\\uDD12</span>`\n : nothing}\n <span title=\"Signal: ${n.signal}%\">${renderSignalBars(n.signal)}</span>\n </span>\n </button>\n `;\n })}\n </div>\n\n ${selected && !networks.find((n) => n.ssid === selected && n.active)\n ? html`\n <div style=\"display: flex; gap: 8px; align-items: center;\">\n ${(() => {\n const net = networks.find((n) => n.ssid === selected);\n const needsPassword = net?.security !== \"Open\";\n const isSaved = ws?.savedSsid === selected;\n if (needsPassword && !isSaved) {\n return html`\n <input\n type=\"password\"\n placeholder=\"Password\"\n .value=${state.wifiPassword}\n @input=${(e: Event) =>\n state.onWifiPasswordChange((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") state.onWifiConnect();\n }}\n ?disabled=${busy}\n style=\"\n flex: 1;\n padding: 6px 10px;\n background: rgba(255,255,255,0.06);\n border: 1px solid rgba(255,255,255,0.15);\n border-radius: 4px;\n color: inherit;\n font-size: 13px;\n outline: none;\n \"\n />`;\n }\n return nothing;\n })()}\n <button\n class=\"setup-button primary\"\n style=\"padding: 6px 16px; font-size: 13px;\"\n ?disabled=${busy}\n @click=${state.onWifiConnect}\n >${busy ? \"Connecting...\" : \"Connect\"}</button>\n ${ws?.savedSsid === selected\n ? html`<button\n class=\"setup-link-btn\"\n ?disabled=${busy}\n @click=${state.onWifiForget}\n style=\"font-size: 12px; opacity: 0.6;\"\n >Forget</button>`\n : nothing}\n </div>\n `\n : nothing}\n `\n : nothing}\n </div>\n </div>\n `;\n}\n\n/** Network status row — compact, with Edit button that opens modal. */\nfunction renderNetworkRow(state: SetupViewState) {\n if (!state.isMaster) return nothing;\n\n // Still loading\n if (state.networkPort == null) {\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"unknown\")}\n <div class=\"setup-status-info\">\n <strong>Network</strong>\n <span>Loading...</span>\n </div>\n </div>\n `;\n }\n\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(\"good\")}\n <div class=\"setup-status-info\">\n <strong>Network</strong>\n <span>${state.networkHostname}.local:${state.networkPort}</span>\n </div>\n ${renderInfoButton(\"network\", state)}\n <button\n class=\"setup-link-btn\"\n @click=${state.onNetworkModalToggle}\n >Edit</button>\n </div>\n `;\n}\n\n/** Network settings modal — hostname + port with explicit Save. */\nfunction renderNetworkModal(state: SetupViewState) {\n if (!state.networkModalOpen) return nothing;\n\n const busy = state.networkBusy;\n const portChanged = state.networkPortInput !== String(state.networkPort);\n const hostnameChanged = state.networkHostnameInput !== state.networkHostname;\n const hasChanges = portChanged || hostnameChanged;\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onNetworkModalToggle();\n }\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 400px; position: relative;\">\n <h3 style=\"margin-right: 24px;\">Network</h3>\n <button class=\"branding-modal-close\" @click=${state.onNetworkModalToggle}>&times;</button>\n\n <!-- Hostname -->\n <div class=\"branding-row\">\n <label class=\"branding-label\">Hostname</label>\n <div style=\"display: flex; align-items: center; gap: 8px; flex: 1;\">\n <input\n type=\"text\"\n .value=${state.networkHostnameInput}\n ?disabled=${busy}\n @input=${(e: Event) =>\n state.onNetworkHostnameChange((e.target as HTMLInputElement).value)}\n style=\"\n flex: 1;\n padding: 6px 10px;\n background: rgba(255,255,255,0.06);\n border: 1px solid rgba(255,255,255,0.15);\n border-radius: 4px;\n color: inherit;\n font-size: 13px;\n outline: none;\n \"\n />\n <span style=\"font-size: 13px; opacity: 0.5;\">.local</span>\n </div>\n </div>\n\n <!-- Port -->\n <div class=\"branding-row\">\n <label class=\"branding-label\">Port</label>\n <div style=\"display: flex; align-items: center; flex: 1;\">\n <input\n type=\"number\"\n min=\"1024\"\n max=\"65535\"\n .value=${state.networkPortInput}\n ?disabled=${busy}\n @input=${(e: Event) =>\n state.onNetworkPortChange((e.target as HTMLInputElement).value)}\n style=\"\n width: 110px;\n padding: 6px 10px;\n background: rgba(255,255,255,0.06);\n border: 1px solid rgba(255,255,255,0.15);\n border-radius: 4px;\n color: inherit;\n font-size: 13px;\n outline: none;\n -moz-appearance: textfield;\n \"\n />\n </div>\n </div>\n\n ${state.networkError\n ? html`<p style=\"margin: 8px 0 0; font-size: 13px; color: #ef4444;\">${state.networkError}</p>`\n : nothing}\n ${state.networkSuccess\n ? html`<p style=\"margin: 8px 0 0; font-size: 13px; color: #22c55e;\">${state.networkSuccess}</p>`\n : nothing}\n\n <div style=\"margin-top: 16px; display: flex; gap: 8px; align-items: center;\">\n <button\n class=\"setup-button primary\"\n style=\"padding: 8px 20px; font-size: 13px;\"\n ?disabled=${busy || !hasChanges}\n @click=${state.onNetworkSave}\n >${busy ? \"Saving...\" : \"Save\"}</button>\n ${hasChanges\n ? html`<span style=\"font-size: 12px; opacity: 0.5;\">Gateway will restart</span>`\n : nothing}\n </div>\n </div>\n </div>\n `;\n}\n\n/** Update modal overlay — shows progress during update and result after reconnect */\nfunction renderUpdateModal(state: SetupViewState) {\n const showProgress = state.updateRunning;\n const result = state.updateLastResult;\n if (!showProgress && !result) return nothing;\n\n // During update: show live progress steps\n if (showProgress) {\n return html`\n <div class=\"setup-info-overlay\">\n <div class=\"setup-info-card\" style=\"max-width: 400px;\">\n <h3>Software Update</h3>\n ${state.updateProgressSteps.length > 0\n ? html`\n <div class=\"setup-update-progress\">\n ${state.updateProgressSteps.map(\n (step) => html`\n <div class=\"setup-update-step ${step.status}\">\n <span class=\"setup-update-step-icon\">\n ${step.status === \"running\"\n ? html`<span class=\"setup-update-spinner\"></span>`\n : step.status === \"done\"\n ? html`<span class=\"setup-update-icon-ok\">${icons.check}</span>`\n : html`<span class=\"setup-update-icon-fail\">${icons.x}</span>`}\n </span>\n <span class=\"setup-update-step-name\">${step.name}</span>\n ${step.durationMs != null\n ? html`<span class=\"setup-update-step-time\">${formatDuration(step.durationMs)}</span>`\n : nothing}\n </div>\n `,\n )}\n </div>\n `\n : html`<div class=\"setup-spinner\" style=\"margin: 16px auto;\"></div>`}\n ${state.updateMessage\n ? html`<p style=\"text-align: center; color: var(--tasker-text-grey); font-size: 13px; margin: 12px 0 0;\">${state.updateMessage}</p>`\n : nothing}\n </div>\n </div>\n `;\n }\n\n // After update: show result\n if (result) {\n const isSuccess = result.status === \"ok\";\n let message: string;\n if (isSuccess) {\n const before = result.before?.version;\n const after = result.after?.version ?? result.currentVersion;\n message = before ? `v${before} \\u2192 v${after}` : `Updated to v${after}`;\n } else {\n const reason = result.reason ?? result.failedStep?.name ?? \"unknown error\";\n message = reason;\n }\n const durationText = result.durationMs != null ? formatDuration(result.durationMs) : null;\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onUpdateDismissResult();\n }\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 360px; text-align: center;\">\n <div class=\"setup-update-result-icon ${isSuccess ? \"ok\" : \"fail\"}\">${isSuccess ? icons.circleCheck : icons.circleX}</div>\n <h3 style=\"color: ${isSuccess ? \"#22c55e\" : \"#ef4444\"};\">\n ${isSuccess ? \"Update Complete\" : \"Update Failed\"}\n </h3>\n <p style=\"color: var(--tasker-text-grey); font-size: 14px; margin: 8px 0;\">\n ${message}\n </p>\n ${durationText\n ? html`<p style=\"color: rgba(255,255,255,0.3); font-size: 12px; margin: 4px 0 0;\">${durationText}</p>`\n : nothing}\n <button\n class=\"setup-button secondary\"\n style=\"margin-top: 20px; width: 100%; padding: 10px;\"\n @click=${state.onUpdateDismissResult}\n >\n Close\n </button>\n </div>\n </div>\n `;\n }\n\n return nothing;\n}\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n const s = Math.round(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n const rem = s % 60;\n return rem > 0 ? `${m}m ${rem}s` : `${m}m`;\n}\n\nfunction renderAccountPinRow(state: SetupViewState) {\n const hasPin = state.accountHasPin;\n const status: \"good\" | \"bad\" = hasPin ? \"good\" : \"bad\";\n\n return html`\n <div class=\"setup-status-item\">\n ${renderStatusLight(status)}\n <div class=\"setup-status-info\">\n <strong>Account PIN</strong>\n <span>${hasPin ? \"Set\" : \"Not set\"}</span>\n </div>\n ${renderInfoButton(\"account-pin\", state)}\n <button\n class=\"setup-link-btn\"\n @click=${() => state.onAccountPinModalOpen()}\n >${hasPin ? \"Change\" : \"Set PIN\"}</button>\n </div>\n `;\n}\n\n/** Modal for setting or changing an account PIN */\nfunction renderAccountPinModal(state: SetupViewState) {\n if (!state.accountPinModalOpen) return nothing;\n\n const hasPin = state.accountHasPin;\n const busy = state.accountPinBusy;\n\n let oldPin = \"\";\n let newPin = \"\";\n let confirmPin = \"\";\n\n const pinInputHandler = (setter: (v: string) => void) => (e: Event) => {\n const input = e.target as HTMLInputElement;\n input.value = input.value.replace(/\\D/g, \"\").slice(0, 6);\n setter(input.value);\n };\n\n const showValidationError = (form: HTMLFormElement, msg: string) => {\n let el = form.querySelector(\".pin-modal-validation\") as HTMLElement | null;\n if (!el) {\n el = document.createElement(\"p\");\n el.className = \"login-error pin-modal-validation\";\n form.querySelector(\"button[type=submit]\")?.before(el);\n }\n el.textContent = msg;\n };\n\n const handleSubmit = (e: Event) => {\n e.preventDefault();\n const form = e.target as HTMLFormElement;\n if (busy) return;\n if (hasPin && !oldPin) { showValidationError(form, \"Enter your current PIN\"); return; }\n if (!newPin) { showValidationError(form, \"Enter a new PIN\"); return; }\n if (!confirmPin) { showValidationError(form, \"Confirm your new PIN\"); return; }\n if (newPin !== confirmPin) { showValidationError(form, \"PINs do not match\"); return; }\n if (newPin.length < 4) { showValidationError(form, \"PIN must be 4–6 digits\"); return; }\n state.onAccountPinSave(hasPin ? oldPin : null, newPin);\n };\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) {\n state.onAccountPinModalClose();\n }\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 340px;\">\n <div class=\"setup-info-header\">\n <h3>${hasPin ? \"Change Account PIN\" : \"Set Account PIN\"}</h3>\n <button class=\"setup-info-close\" @click=${() => state.onAccountPinModalClose()}>\n ${icons.close}\n </button>\n </div>\n <form @submit=${handleSubmit} style=\"display: flex; flex-direction: column; gap: 12px; padding: 16px 0 8px;\">\n ${hasPin ? html`\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"Current PIN\"\n ?disabled=${busy}\n @input=${pinInputHandler((v: string) => { oldPin = v; })}\n autofocus\n />\n ` : nothing}\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"New PIN (4–6 digits)\"\n ?disabled=${busy}\n @input=${pinInputHandler((v: string) => { newPin = v; })}\n ${hasPin ? nothing : html`autofocus`}\n />\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"Confirm PIN\"\n ?disabled=${busy}\n @input=${pinInputHandler((v: string) => { confirmPin = v; })}\n />\n ${state.accountPinError\n ? html`<p class=\"login-error\">${state.accountPinError}</p>`\n : nothing}\n ${state.accountPinSuccess\n ? html`<p class=\"login-success\">${state.accountPinSuccess}</p>`\n : nothing}\n <button\n class=\"login-submit\"\n type=\"submit\"\n ?disabled=${busy}\n >${busy ? html`<span class=\"login-spinner\"></span>` : hasPin ? \"Change PIN\" : \"Set PIN\"}</button>\n </form>\n </div>\n </div>\n `;\n}\n\n/** Render the add-account form (triggered from dropdown \"Add Account\") */\nfunction renderAddAccountForm(state: SetupViewState) {\n if (!state.addingWorkspace) return nothing;\n const { workspaceSaving } = state;\n\n const submitForm = () => {\n if (state.newWorkspaceName.trim() && state.newWorkspacePin.match(/^\\d{4,6}$/)) {\n state.onWorkspaceCreate(\n state.newWorkspaceName,\n state.newWorkspacePath || undefined,\n );\n }\n };\n\n const togglePinVisibility = (e: Event) => {\n const btn = (e.currentTarget as HTMLElement);\n const wrapper = btn.closest(\".login-pin-wrapper\") as HTMLElement;\n const input = wrapper?.querySelector(\"input\") as HTMLInputElement | null;\n if (!input) return;\n const visible = input.type === \"text\";\n input.type = visible ? \"password\" : \"text\";\n btn.classList.toggle(\"active\", !visible);\n };\n\n return html`\n <div style=\"margin-top: 16px; border-top: 1px solid var(--tasker-border, rgba(255,255,255,0.1)); padding-top: 16px;\">\n <div class=\"setup-add-account\">\n <strong>New Account</strong>\n <label class=\"setup-add-account-label\">Account name</label>\n <input\n type=\"text\"\n class=\"setup-add-account-input\"\n placeholder=\"e.g. My Business\"\n .value=${state.newWorkspaceName}\n @input=${(e: Event) => state.onSetNewWorkspaceName((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => { if (e.key === \"Enter\") submitForm(); }}\n />\n <label class=\"setup-add-account-label\">PIN (4–6 digits)</label>\n <div class=\"login-pin-wrapper\" style=\"margin-top: 10px;\">\n <input\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n class=\"setup-add-account-input login-pin-input\"\n style=\"margin-top: 0;\"\n placeholder=\"Enter a PIN\"\n .value=${state.newWorkspacePin}\n @input=${(e: Event) => {\n const input = e.target as HTMLInputElement;\n input.value = input.value.replace(/\\D/g, \"\").slice(0, 6);\n state.onSetNewWorkspacePin(input.value);\n }}\n @keydown=${(e: KeyboardEvent) => { if (e.key === \"Enter\") submitForm(); }}\n />\n <button class=\"login-pin-toggle\" type=\"button\" @click=${togglePinVisibility}>\n <span class=\"pin-eye-show\">${icons.eye}</span>\n <span class=\"pin-eye-hide\">${icons.eyeOff}</span>\n </button>\n </div>\n <details style=\"margin-top: 8px;\">\n <summary style=\"cursor: pointer; font-size: 12px; color: var(--tasker-text-grey);\">\n Use existing workspace (advanced)\n </summary>\n <input\n type=\"text\"\n class=\"setup-add-account-input\"\n placeholder=\"/path/to/workspace\"\n style=\"margin-top: 8px;\"\n .value=${state.newWorkspacePath}\n @input=${(e: Event) => state.onSetNewWorkspacePath((e.target as HTMLInputElement).value)}\n />\n </details>\n <div class=\"setup-add-account-actions\" style=\"margin-top: 8px;\">\n <button\n class=\"setup-button primary\"\n ?disabled=${workspaceSaving || !state.newWorkspaceName.trim() || !state.newWorkspacePin.match(/^\\d{4,6}$/)}\n @click=${submitForm}\n >\n ${workspaceSaving ? \"Creating\\u2026\" : \"Create\"}\n </button>\n <button\n class=\"setup-button secondary\"\n @click=${() => {\n state.onSetAddingWorkspace(false);\n state.onSetNewWorkspaceName(\"\");\n state.onSetNewWorkspacePath(\"\");\n state.onSetNewWorkspacePin(\"\");\n }}\n >\n Cancel\n </button>\n </div>\n </div>\n </div>\n `;\n}\n\n/** Render the remove-account confirmation (shown for non-default workspaces) */\nfunction renderRemoveAccountSection(state: SetupViewState) {\n const ws = getSelectedWorkspace(state);\n if (!ws || ws.isDefault) return nothing;\n\n const isRemoveConfirm = state.workspaceRemoveConfirm === ws.name;\n if (isRemoveConfirm) {\n return html`\n <div style=\"margin-top: 16px; border-top: 1px solid var(--tasker-border, rgba(255,255,255,0.1)); padding-top: 12px;\">\n <div style=\"font-size: 13px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;\">\n <span style=\"color: var(--tasker-danger, #ef4444);\">Remove \"${ws.displayName ?? ws.name}\" and its WhatsApp account?</span>\n <button\n class=\"setup-button danger\"\n style=\"font-size: 12px; padding: 4px 12px;\"\n ?disabled=${state.workspaceSaving}\n @click=${() => state.onWorkspaceRemove(ws.name)}\n >\n ${state.workspaceSaving ? \"Removing\\u2026\" : \"Remove\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"font-size: 12px; padding: 4px 12px;\"\n @click=${() => state.onSetWorkspaceRemoveConfirm(null)}\n >\n Cancel\n </button>\n </div>\n </div>\n `;\n }\n\n return html`\n <p class=\"setup-hint\" style=\"margin-top: 12px;\">\n <a\n href=\"#\"\n class=\"setup-link-danger\"\n @click=${(e: Event) => {\n e.preventDefault();\n state.onSetWorkspaceRemoveConfirm(ws.name);\n }}\n >Remove Account</a>\n </p>\n `;\n}\n\n/** Render the uninstall section at the bottom of the setup dashboard */\nfunction renderUninstallSection(state: SetupViewState) {\n // After uninstall completes, show a final message\n if (state.uninstallDone) {\n return html`\n <div style=\"margin-top: 24px; border-top: 1px solid var(--tasker-border, rgba(255,255,255,0.1)); padding-top: 16px;\">\n <p style=\"color: var(--tasker-danger, #ef4444); font-size: 13px; font-weight: 600; margin: 0 0 8px 0;\">\n Taskmaster has been uninstalled.\n </p>\n <p style=\"font-size: 12px; color: var(--tasker-text-grey); margin: 0;\">\n If the npm package was not removed automatically, run:<br/>\n <code style=\"font-size: 11px; background: rgba(255,255,255,0.06); padding: 2px 6px; border-radius: 3px;\">sudo npm uninstall -g @rubytech/taskmaster</code>\n </p>\n </div>\n `;\n }\n\n // Confirmation expanded: type UNINSTALL to proceed\n if (state.uninstallConfirm) {\n const confirmed = state.uninstallConfirmText === \"UNINSTALL\";\n return html`\n <div style=\"margin-top: 24px; border-top: 1px solid var(--tasker-border, rgba(255,255,255,0.1)); padding-top: 16px;\">\n <p style=\"color: var(--tasker-danger, #ef4444); font-size: 13px; font-weight: 600; margin: 0 0 8px 0;\">\n Uninstall Taskmaster\n </p>\n <p style=\"font-size: 12px; color: var(--tasker-text-grey); margin: 0 0 12px 0;\">\n This will stop the gateway, remove all configuration, workspace files, and the npm package.\n This cannot be undone.\n </p>\n <div style=\"display: flex; align-items: center; gap: 8px; flex-wrap: wrap;\">\n <input\n type=\"text\"\n placeholder=\"Type UNINSTALL to confirm\"\n .value=${state.uninstallConfirmText}\n ?disabled=${state.uninstallBusy}\n @input=${(e: Event) => state.onUninstallConfirmTextChange((e.target as HTMLInputElement).value)}\n style=\"font-size: 12px; padding: 4px 8px; background: rgba(255,255,255,0.06); border: 1px solid rgba(255,255,255,0.15); border-radius: 4px; color: inherit; width: 180px;\"\n />\n <button\n class=\"setup-button danger\"\n style=\"font-size: 12px; padding: 4px 12px;\"\n ?disabled=${!confirmed || state.uninstallBusy}\n @click=${state.onUninstallRun}\n >\n ${state.uninstallBusy ? \"Uninstalling\\u2026\" : \"Uninstall\"}\n </button>\n <button\n class=\"setup-button secondary\"\n style=\"font-size: 12px; padding: 4px 12px;\"\n ?disabled=${state.uninstallBusy}\n @click=${state.onUninstallCancel}\n >\n Cancel\n </button>\n </div>\n ${state.uninstallError\n ? html`<p class=\"setup-error\" style=\"margin-top: 8px; font-size: 12px;\">${state.uninstallError}</p>`\n : nothing}\n </div>\n `;\n }\n\n // Default: danger link\n return html`\n <p class=\"setup-hint\" style=\"margin-top: 8px;\">\n <a\n href=\"#\"\n class=\"setup-link-danger\"\n @click=${(e: Event) => {\n e.preventDefault();\n state.onUninstallConfirm();\n }}\n >Uninstall Taskmaster</a>\n </p>\n `;\n}\n\nfunction renderSupportLink() {\n return html`\n <p class=\"setup-hint\" style=\"margin-top: 4px; font-size: 12px; opacity: 0.6;\">\n Need help? <a href=\"https://wa.me/447591215452\" target=\"_blank\" rel=\"noopener\" style=\"color: var(--tasker-orange);\">Message Tuesday on WhatsApp</a>\n </p>\n `;\n}\n\nfunction renderWhatsAppStep(state: SetupViewState) {\n const {\n whatsappBusy,\n whatsappLoginMessage,\n whatsappLoginQrDataUrl,\n whatsappLoginConnected,\n whatsappChannelStatus,\n } = state;\n\n // PRIORITY 1: Show QR code if we have one (user clicked Link WhatsApp)\n if (whatsappLoginQrDataUrl) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <h1>Scan with WhatsApp</h1>\n <p>\n On your phone: WhatsApp → Settings → Linked Devices → Link a Device\n </p>\n <div class=\"setup-qr\">\n <img src=${whatsappLoginQrDataUrl} alt=\"WhatsApp QR Code\" />\n </div>\n ${whatsappBusy\n ? html`<p class=\"setup-waiting\">Waiting for scan...</p>`\n : html`<p class=\"setup-hint\">\n Scan the code above with your phone\n </p>`}\n <p class=\"setup-hint\" style=\"margin-top: 16px;\">\n <strong>Important:</strong> If you see \"${resolveBrand().name}\" in your Linked\n Devices, remove it first before scanning.\n </p>\n <div class=\"setup-actions\" style=\"margin-top: 24px;\">\n <button\n class=\"setup-button secondary\"\n @click=${state.onWhatsAppBack}\n >\n ← Back\n </button>\n </div>\n </div>\n </div>\n `;\n }\n\n // PRIORITY 2: Show loading state\n if (whatsappBusy) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>${whatsappLoginMessage || \"Connecting to WhatsApp...\"}</p>\n </div>\n </div>\n `;\n }\n\n // Determine the REAL WhatsApp status\n const isReallyConnected =\n whatsappChannelStatus?.running && whatsappChannelStatus?.connected;\n\n // PRIORITY 3: Show status dashboard when we have channel status\n if (whatsappChannelStatus) {\n const hasMultipleAccounts = state.whatsappAccounts.length > 1;\n\n // For multi-account: overall status is \"good\" if ALL baileys accounts are connected\n const allConnected = hasMultipleAccounts\n ? state.whatsappAccounts.every((a) => a.running && a.connected)\n : isReallyConnected;\n\n const allGood = allConnected && state.authConnected;\n\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card ${allGood ? \"setup-success\" : \"\"} setup-dashboard-wide\">\n ${renderDashboardHeader(state)}\n <div class=\"setup-status-dashboard\">\n ${renderGatewayStatusRow(state)}\n ${renderClaudeStatusRow(state)}\n ${renderLicenseStatusRow(state)}\n ${renderWhatsAppStatusRow(state)}\n ${state.serverPlatform === \"darwin\" ? renderIMessageStatusRow(state) : nothing}\n ${renderAgentSettingsRow(state)}\n ${renderAccountPinRow(state)}\n ${renderUpdateRow(state)}\n ${renderPublicChatRow(state)}\n ${renderBrandingRow(state)}\n ${renderRemoteAccessRow(state)}\n ${renderNetworkRow(state)}\n ${renderWifiRow(state)}\n </div>\n\n ${renderAgentSettingsModal(state)}\n ${renderAccountPinModal(state)}\n ${renderBrandingModal(state)}\n ${renderPublicChatSettingsModal(state)}\n ${renderNetworkModal(state)}\n ${renderWifiModal(state)}\n ${renderTailscaleConnectModal(state)}\n ${renderApiKeysSection(state)}\n ${renderAddAccountForm(state)}\n ${renderRemoveAccountSection(state)}\n ${renderUninstallSection(state)}\n ${renderSupportLink()}\n ${state.workspacesError\n ? html`<p class=\"setup-error\" style=\"margin-top: 8px;\">${state.workspacesError}</p>`\n : nothing}\n </div>\n </div>\n `;\n }\n\n // No channel status yet - need to fetch it\n // Don't show success without real channel confirmation\n if (!whatsappChannelStatus) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"setup\")}\n <div class=\"setup-spinner\"></div>\n <p>Checking connection status...</p>\n <button\n class=\"setup-button secondary\"\n style=\"margin-top: 16px;\"\n @click=${state.onRefreshStatus}\n >\n Refresh Status\n </button>\n </div>\n </div>\n `;\n }\n\n // Error state - login failed\n const isError =\n whatsappLoginConnected === false && whatsappLoginMessage && !whatsappBusy;\n if (isError) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"setup\")}\n <div class=\"setup-status-row\">\n ${renderStatusLight(\"bad\")}\n <span>Connection Failed</span>\n </div>\n <p class=\"setup-error\">${whatsappLoginMessage}</p>\n <button\n class=\"setup-button primary\"\n ?disabled=${whatsappBusy}\n @click=${state.onWhatsAppRelink}\n >\n Try Again\n </button>\n </div>\n </div>\n `;\n }\n\n // QR code and loading states are now handled at the top of the function\n\n // Initial/waiting state\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n ${renderStepIndicator(\"setup\")}\n ${whatsappLoginMessage\n ? html`<p class=\"setup-error\">${whatsappLoginMessage}</p>`\n : html`<div class=\"setup-spinner\"></div>\n <p>Preparing...</p>`}\n </div>\n </div>\n `;\n}\n\nfunction renderClaudeAuthModal(state: SetupViewState) {\n if (!state.claudeAuthModalOpen) return nothing;\n\n const closeModal = () => state.onClaudeAuthModalClose();\n const isConnected = state.authConnected === true;\n\n return html`\n <div class=\"setup-info-overlay\" @click=${(e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"setup-info-overlay\")) closeModal();\n }}>\n <div class=\"setup-info-card\" style=\"max-width: 420px;\">\n <h3>${isConnected ? \"Claude Connected\" : \"Connect to Claude\"}</h3>\n\n ${isConnected\n ? html`\n <div style=\"margin: 12px 0;\">\n <div style=\"display: flex; align-items: center; gap: 8px; margin-bottom: 8px;\">\n ${renderStatusLight(\"good\")}\n <span style=\"font-size: 14px;\">Connected</span>\n ${state.authExpiresIn\n ? html`<span style=\"color: var(--tasker-text-grey); font-size: 12px;\">(expires in ${state.authExpiresIn}m)</span>`\n : nothing}\n </div>\n ${state.authMessage\n ? html`<p style=\"font-size: 13px; color: var(--tasker-text-grey); margin: 0 0 12px;\">${state.authMessage}</p>`\n : nothing}\n <button class=\"setup-button secondary\" style=\"width: 100%;\" @click=${state.onStartAuth}>\n Reconnect\n </button>\n </div>\n `\n : nothing}\n\n ${!isConnected && !state.authUrl\n ? html`\n <p style=\"font-size: 13px; color: var(--tasker-text-grey); margin: 8px 0 16px;\">\n Connect your Claude Pro subscription to power your AI assistant.\n </p>\n ${state.authMessage\n ? html`<p class=\"setup-error\" style=\"margin-bottom: 12px;\">${state.authMessage}</p>`\n : nothing}\n <button\n class=\"setup-button primary\"\n style=\"width: 100%;\"\n ?disabled=${state.authBusy}\n @click=${state.onStartAuth}\n >\n ${state.authBusy ? \"Starting...\" : \"Connect to Claude\"}\n </button>\n `\n : nothing}\n\n ${state.authUrl\n ? html`\n <div style=\"margin: 12px 0;\">\n <p style=\"font-size: 13px; color: var(--tasker-text-grey); margin: 0 0 8px;\">\n Sign in with your Claude Pro account, then paste the code shown:\n </p>\n <a href=${state.authUrl} target=\"_blank\" rel=\"noopener\" class=\"setup-button primary\" style=\"display: block; text-align: center; margin-bottom: 12px;\">\n Sign in with Claude\n </a>\n <div class=\"setup-code-input\">\n <input\n type=\"text\"\n placeholder=\"Enter authorization code\"\n .value=${state.authCodeInput}\n @input=${(e: Event) => state.onAuthCodeChange((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\" && state.authCodeInput.trim()) {\n state.onSubmitAuthCode(state.authCodeInput.trim());\n }\n }}\n />\n <button\n class=\"setup-button\"\n ?disabled=${!state.authCodeInput.trim() || state.authBusy}\n @click=${() => state.onSubmitAuthCode(state.authCodeInput.trim())}\n >\n ${state.authBusy ? \"Verifying...\" : \"Submit\"}\n </button>\n </div>\n </div>\n `\n : nothing}\n\n ${!isConnected\n ? html`\n <div style=\"border-top: 1px solid rgba(255,255,255,0.08); margin-top: 16px; padding-top: 16px;\">\n <p style=\"font-size: 13px; color: var(--tasker-text-grey); margin: 0 0 8px;\">\n Or paste a refresh token from another device:\n </p>\n <div class=\"setup-code-input\">\n <input\n type=\"text\"\n placeholder=\"Paste refresh token\"\n .value=${state.authRefreshTokenInput}\n @input=${(e: Event) => state.onRefreshTokenInputChange((e.target as HTMLInputElement).value)}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\" && state.authRefreshTokenInput.trim()) {\n state.onImportRefreshToken();\n }\n }}\n ?disabled=${state.authRefreshTokenBusy}\n />\n <button\n class=\"setup-button\"\n ?disabled=${!state.authRefreshTokenInput.trim() || state.authRefreshTokenBusy}\n @click=${state.onImportRefreshToken}\n >\n ${state.authRefreshTokenBusy ? \"Importing...\" : \"Connect\"}\n </button>\n </div>\n ${state.authRefreshTokenError\n ? html`<p class=\"setup-error\" style=\"margin-top: 8px;\">${state.authRefreshTokenError}</p>`\n : nothing}\n </div>\n `\n : nothing}\n\n <button\n class=\"setup-button secondary\"\n style=\"margin-top: 16px; width: 100%; padding: 10px;\"\n @click=${closeModal}\n >\n Close\n </button>\n </div>\n </div>\n `;\n}\n\nexport function renderSetup(state: SetupViewState) {\n const { connected, currentStep } = state;\n\n // Gateway connected — clear any stale uninstall flag from a previous session.\n // A running gateway means the product is installed regardless of what localStorage says.\n // (onHello also clears it, but this catches any render race.)\n if (connected && checkUninstallDone()) {\n clearUninstallDone();\n }\n\n // Show uninstall page when:\n // - Current session uninstall completed (reactive state), OR\n // - localStorage flag set AND gateway not reachable (genuinely uninstalled)\n // The localStorage check alone is NOT trusted — it persists across reinstalls.\n if (state.uninstallDone || (!connected && checkUninstallDone())) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <p style=\"color: var(--tasker-danger, #ef4444); font-size: 16px; font-weight: 600; margin: 0 0 12px 0;\">\n Taskmaster has been uninstalled.\n </p>\n <p style=\"font-size: 13px; color: var(--tasker-text-grey); margin: 0 0 16px 0;\">\n The gateway service, configuration, and workspace files have been removed.\n </p>\n <p style=\"font-size: 13px; color: var(--tasker-text-grey); margin: 0 0 16px 0;\">\n If the npm package was not removed automatically, run:\n </p>\n <code style=\"display: block; font-size: 12px; background: rgba(255,255,255,0.06); padding: 8px 12px; border-radius: 4px; margin: 0 0 16px 0;\">sudo npm uninstall -g @rubytech/taskmaster</code>\n <p style=\"font-size: 12px; color: var(--tasker-text-grey); margin: 0;\">You can close this tab.</p>\n </div>\n </div>\n `;\n }\n\n // Not connected to gateway\n if (!connected) {\n const isUpdating = state.updateRunning;\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>${isUpdating ? \"Restarting gateway after update\\u2026\" : \"Connecting to gateway...\"}</p>\n </div>\n </div>\n `;\n }\n\n // Render current step\n let stepContent;\n switch (currentStep) {\n case \"license\":\n stepContent = renderLicenseStep(state);\n break;\n case \"auth\":\n stepContent = renderAuthStep(state);\n break;\n case \"setup\":\n stepContent = renderWhatsAppStep(state);\n break;\n default:\n stepContent = renderLicenseStep(state);\n }\n\n const pageNav = renderPageNav(\"Setup\", state.wsProps);\n return html`${stepContent}${renderInfoModal(state)}${renderClaudeAuthModal(state)}${renderIMessageActionModal(state)}${renderWhatsAppSettingsModal(state)}${renderUpdateModal(state)}${renderWidgetSnippetModal(state)}${pageNav}`;\n}\n","import { html, nothing } from \"lit\";\nimport type { AdminPhoneEntry } from \"../types.admins\";\nimport { renderPageNav, type WorkspaceNavProps } from \"./page-nav\";\n\nexport type { AdminPhoneEntry } from \"../types.admins\";\n\nexport type AdminsProps = {\n connected?: boolean;\n loading: boolean;\n saving: boolean;\n phones: AdminPhoneEntry[];\n error: string | null;\n newPhone: string;\n wsProps?: WorkspaceNavProps;\n onRefresh: () => void;\n onAdd: (phone: string) => void;\n onRemove: (phone: string) => void;\n onNewPhoneChange: (value: string) => void;\n};\n\nfunction renderPhoneEntry(entry: AdminPhoneEntry, props: AdminsProps) {\n const subtitle = entry.paired\n ? \"Paired phone (used to link WhatsApp)\"\n : \"Admin access via WhatsApp DM\";\n\n return html`\n <div class=\"sp-list-item\">\n <div class=\"sp-list-item-main\">\n <div class=\"sp-list-item-title\">${entry.phone}</div>\n <div class=\"sp-list-item-sub\">${subtitle}</div>\n </div>\n ${entry.paired\n ? html`<span style=\"color: var(--tasker-orange); font-size: 13px; padding: 8px 16px;\">Primary</span>`\n : html`<button\n class=\"setup-button danger\"\n style=\"padding: 8px 16px; font-size: 13px;\"\n ?disabled=${props.saving}\n @click=${() => props.onRemove(entry.phone)}\n >\n Remove\n </button>`}\n </div>\n `;\n}\n\n/**\n * Render admins page as a standalone dark-themed page (like Setup/Files/Browser).\n */\nexport function renderAdminsPage(props: AdminsProps) {\n if (!props.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting to gateway...</p>\n </div>\n </div>\n `;\n }\n\n const handleSubmit = (e: Event) => {\n e.preventDefault();\n if (props.newPhone.trim()) {\n props.onAdd(props.newPhone);\n }\n };\n\n return html`\n <div class=\"setup-container\">\n ${renderPageNav(\"Admins\", props.wsProps)}\n <div class=\"setup-card\" style=\"max-width: 520px;\">\n <h1>Admin Phones</h1>\n <p style=\"margin-bottom: 16px;\">\n Phone numbers that route to the admin agent instead of the public agent.\n </p>\n\n <div class=\"sp-toolbar\">\n <button\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n ?disabled=${props.loading}\n @click=${props.onRefresh}\n >\n ${props.loading ? \"Loading...\" : \"Refresh\"}\n </button>\n </div>\n\n ${props.error\n ? html`<div class=\"setup-error\" style=\"margin-top: 16px;\">${props.error}</div>`\n : nothing}\n\n <form style=\"display: flex; flex-direction: row; gap: 12px; margin-top: 20px; align-items: stretch;\" @submit=${handleSubmit}>\n <input\n type=\"tel\"\n style=\"flex: 1; padding: 10px 14px; font-size: 14px; border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.15); background: rgba(0, 0, 0, 0.3); color: var(--tasker-white); font-family: inherit;\"\n placeholder=\"+44...\"\n .value=${props.newPhone}\n @input=${(e: Event) => props.onNewPhoneChange((e.target as HTMLInputElement).value)}\n ?disabled=${props.saving}\n />\n <button\n type=\"submit\"\n class=\"setup-button primary\"\n style=\"padding: 10px 20px; font-size: 14px; flex-shrink: 0;\"\n ?disabled=${props.saving || !props.newPhone.trim()}\n >\n ${props.saving ? \"Saving...\" : \"Add\"}\n </button>\n </form>\n\n <div class=\"sp-list\" style=\"margin-top: 20px;\">\n ${props.phones.length === 0\n ? html`<div class=\"sp-list-empty\">No admin phones configured yet.</div>`\n : props.phones.map((entry) => renderPhoneEntry(entry, props))}\n </div>\n\n <div class=\"setup-hint\" style=\"margin-top: 20px; padding: 14px; background: rgba(0, 0, 0, 0.2); border-radius: 8px; text-align: left;\">\n <strong style=\"color: var(--tasker-white);\">How it works:</strong><br/>\n Messages from admin phones route to the <code style=\"background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 4px; color: var(--tasker-orange);\">admin</code> agent with full tool access.\n All other numbers go to <code style=\"background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 4px; color: var(--tasker-orange);\">public</code> with restricted access.\n </div>\n\n </div>\n </div>\n `;\n}\n\n/**\n * Render admins as an embedded card (for use in the main dashboard).\n */\nexport function renderAdmins(props: AdminsProps) {\n const handleSubmit = (e: Event) => {\n e.preventDefault();\n if (props.newPhone.trim()) {\n props.onAdd(props.newPhone);\n }\n };\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Admin Phone Numbers</div>\n <div class=\"card-sub\">\n Phone numbers that route to the admin agent instead of the public agent.\n </div>\n </div>\n <button class=\"btn\" ?disabled=${props.loading} @click=${props.onRefresh}>\n ${props.loading ? \"Loading...\" : \"Refresh\"}\n </button>\n </div>\n\n ${props.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${props.error}\n </div>`\n : nothing}\n\n <form class=\"row\" style=\"margin-top: 16px; gap: 8px;\" @submit=${handleSubmit}>\n <input\n type=\"tel\"\n class=\"input\"\n placeholder=\"+44...\"\n .value=${props.newPhone}\n @input=${(e: Event) => props.onNewPhoneChange((e.target as HTMLInputElement).value)}\n style=\"flex: 1; min-width: 180px;\"\n ?disabled=${props.saving}\n />\n <button\n type=\"submit\"\n class=\"btn primary\"\n ?disabled=${props.saving || !props.newPhone.trim()}\n >\n ${props.saving ? \"Saving...\" : \"Add Admin\"}\n </button>\n </form>\n\n <div class=\"list\" style=\"margin-top: 16px;\">\n ${props.phones.length === 0\n ? html`<div class=\"muted\">No admin phones configured yet.</div>`\n : props.phones.map((entry) => renderPhoneEntryDashboard(entry, props))}\n </div>\n\n <div class=\"callout\" style=\"margin-top: 16px;\">\n <strong>How it works:</strong> Messages from admin phone numbers are routed to the\n <code>admin</code> agent, which has full access to all tools. All other numbers\n go to the <code>public</code> agent with restricted access.\n </div>\n </section>\n `;\n}\n\nfunction renderPhoneEntryDashboard(entry: AdminPhoneEntry, props: AdminsProps) {\n const subtitle = entry.paired\n ? \"Paired phone (used to link WhatsApp)\"\n : \"Admin access via WhatsApp DM\";\n\n return html`\n <div class=\"list-item\">\n <div class=\"list-main\">\n <div class=\"list-title\">${entry.phone}</div>\n <div class=\"list-sub\">${subtitle}</div>\n </div>\n <div class=\"list-actions\">\n ${entry.paired\n ? html`<span class=\"muted\" style=\"font-size: 13px;\">Primary</span>`\n : html`<button\n class=\"btn small danger\"\n ?disabled=${props.saving}\n @click=${() => props.onRemove(entry.phone)}\n >\n Remove\n </button>`}\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport type { ContactRecord } from \"../controllers/contacts\";\nimport { renderPageNav, type WorkspaceNavProps } from \"./page-nav\";\n\nconst iconX = html`<svg viewBox=\"0 0 24 24\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>`;\n\nexport type ContactsProps = {\n connected: boolean;\n wsProps?: WorkspaceNavProps;\n loading: boolean;\n saving: boolean;\n records: ContactRecord[];\n error: string | null;\n searchQuery: string;\n editingId: string | null;\n showAddForm: boolean;\n newRecordPhone: string;\n newRecordName: string;\n deleteConfirmId: string | null;\n addFieldForId: string | null;\n addFieldKey: string;\n addFieldValue: string;\n onSearch: (query: string) => void;\n onSearchSubmit: () => void;\n onAdd: (phone: string, name: string) => void;\n onDelete: (id: string) => void;\n onSetField: (id: string, key: string, value: string) => void;\n onDeleteField: (id: string, key: string) => void;\n onToggleExpand: (id: string) => void;\n onShowAddForm: () => void;\n onCancelAddForm: () => void;\n onNewRecordPhoneChange: (value: string) => void;\n onNewRecordNameChange: (value: string) => void;\n onRefresh: () => void;\n onDeleteConfirmOpen: (id: string) => void;\n onDeleteConfirmClose: () => void;\n onAddFieldOpen: (id: string) => void;\n onAddFieldClose: () => void;\n onAddFieldKeyChange: (value: string) => void;\n onAddFieldValueChange: (value: string) => void;\n onAddFieldSubmit: () => void;\n};\n\nfunction fieldCount(record: ContactRecord): number {\n return Object.keys(record.fields).length;\n}\n\nfunction renderDeleteConfirmModal(record: ContactRecord, props: ContactsProps) {\n return html`\n <div class=\"event-modal-overlay\" @click=${props.onDeleteConfirmClose}>\n <div class=\"event-modal\" style=\"width: min(400px, 100%);\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"event-modal__header\">\n <div class=\"event-modal__title\">Delete Contact</div>\n <button class=\"event-modal__close\" @click=${props.onDeleteConfirmClose}>\n ${iconX}\n </button>\n </div>\n <p style=\"margin: 0 0 8px; color: rgba(255,255,255,0.7); font-size: 14px; line-height: 1.5;\">\n Are you sure you want to delete this contact?\n </p>\n <div class=\"contacts-modal-record-preview\">\n <span class=\"contacts-record-name\">${record.name}</span>\n <span class=\"contacts-record-phone\">${record.id}</span>\n </div>\n <div class=\"contacts-modal-actions\">\n <button\n class=\"setup-button secondary\"\n @click=${props.onDeleteConfirmClose}\n >\n Cancel\n </button>\n <button\n class=\"setup-button danger\"\n @click=${() => {\n props.onDelete(record.id);\n props.onDeleteConfirmClose();\n }}\n >\n Delete\n </button>\n </div>\n </div>\n </div>\n `;\n}\n\nfunction renderAddFieldModal(record: ContactRecord, props: ContactsProps) {\n const canSubmit = props.addFieldKey.trim().length > 0;\n\n const handleSubmit = (e: Event) => {\n e.preventDefault();\n if (canSubmit) props.onAddFieldSubmit();\n };\n\n return html`\n <div class=\"event-modal-overlay\" @click=${props.onAddFieldClose}>\n <div class=\"event-modal\" style=\"width: min(400px, 100%);\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"event-modal__header\">\n <div class=\"event-modal__title\">Add Field</div>\n <button class=\"event-modal__close\" @click=${props.onAddFieldClose}>\n ${iconX}\n </button>\n </div>\n <p style=\"margin: 0 0 16px; color: rgba(255,255,255,0.5); font-size: 13px;\">\n Adding field to <strong style=\"color: var(--tasker-white);\">${record.name}</strong>\n </p>\n <form @submit=${handleSubmit} class=\"contacts-modal-form\">\n <label class=\"contacts-modal-label\">\n Field name\n <input\n type=\"text\"\n placeholder=\"e.g. status, plan, notes\"\n .value=${props.addFieldKey}\n @input=${(e: Event) => props.onAddFieldKeyChange((e.target as HTMLInputElement).value)}\n autofocus\n />\n </label>\n <label class=\"contacts-modal-label\">\n Value\n <input\n type=\"text\"\n placeholder=\"Field value\"\n .value=${props.addFieldValue}\n @input=${(e: Event) => props.onAddFieldValueChange((e.target as HTMLInputElement).value)}\n />\n </label>\n <div class=\"contacts-modal-actions\">\n <button\n type=\"button\"\n class=\"setup-button secondary\"\n @click=${props.onAddFieldClose}\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n class=\"setup-button primary\"\n ?disabled=${!canSubmit}\n >\n Add\n </button>\n </div>\n </form>\n </div>\n </div>\n `;\n}\n\nfunction renderFieldEditor(record: ContactRecord, props: ContactsProps) {\n const entries = Object.entries(record.fields);\n\n return html`\n <div class=\"contacts-record-fields\">\n ${entries.length === 0\n ? html`<div style=\"color: rgba(255,255,255,0.4); font-size: 13px; margin-top: 12px;\">No fields yet. Add one below.</div>`\n : entries.map(\n ([key, value]) => html`\n <div class=\"contacts-field-row\">\n <input\n class=\"field-key\"\n type=\"text\"\n .value=${key}\n disabled\n title=\"Field name\"\n />\n <input\n class=\"field-value\"\n type=\"text\"\n .value=${value}\n @change=${(e: Event) =>\n props.onSetField(record.id, key, (e.target as HTMLInputElement).value)}\n ?disabled=${props.saving}\n title=\"Field value\"\n />\n <button\n class=\"setup-button danger field-delete\"\n ?disabled=${props.saving}\n @click=${() => props.onDeleteField(record.id, key)}\n >\n ×\n </button>\n </div>\n `,\n )}\n <div class=\"contacts-record-actions\">\n <button\n class=\"setup-button secondary\"\n style=\"font-size: 13px; padding: 8px 14px;\"\n ?disabled=${props.saving}\n @click=${() => props.onAddFieldOpen(record.id)}\n >\n + Add Field\n </button>\n <button\n class=\"setup-button danger\"\n style=\"font-size: 13px; padding: 8px 14px;\"\n ?disabled=${props.saving}\n @click=${() => props.onDeleteConfirmOpen(record.id)}\n >\n Delete Contact\n </button>\n </div>\n </div>\n `;\n}\n\nfunction renderRecord(record: ContactRecord, props: ContactsProps) {\n const expanded = props.editingId === record.id;\n const fields = fieldCount(record);\n const fieldLabel = fields === 0 ? \"No fields\" : `${fields} field${fields > 1 ? \"s\" : \"\"}`;\n\n return html`\n <div class=\"contacts-record\">\n <div\n class=\"contacts-record-header\"\n @click=${() => props.onToggleExpand(record.id)}\n >\n <div class=\"contacts-record-info\">\n <span class=\"contacts-record-name\">${record.name}</span>\n <span class=\"contacts-record-phone\">${record.id}</span>\n </div>\n <span class=\"contacts-record-meta\">${fieldLabel}</span>\n </div>\n ${expanded ? renderFieldEditor(record, props) : nothing}\n </div>\n `;\n}\n\nexport function renderContactsPage(props: ContactsProps) {\n if (!props.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting to gateway...</p>\n </div>\n </div>\n `;\n }\n\n const handleSearchSubmit = (e: Event) => {\n e.preventDefault();\n props.onSearchSubmit();\n };\n\n const handleAddSubmit = (e: Event) => {\n e.preventDefault();\n if (props.newRecordPhone.trim() && props.newRecordName.trim()) {\n props.onAdd(props.newRecordPhone, props.newRecordName);\n }\n };\n\n // Resolve records for active modals\n const deleteRecord = props.deleteConfirmId\n ? props.records.find((r) => r.id === props.deleteConfirmId)\n : null;\n const addFieldRecord = props.addFieldForId\n ? props.records.find((r) => r.id === props.addFieldForId)\n : null;\n\n return html`\n <div class=\"setup-container\">\n ${renderPageNav(\"Contacts\", props.wsProps)}\n <div class=\"setup-card\" style=\"max-width: 620px;\">\n <h1>Contact Records</h1>\n <p style=\"margin-bottom: 16px;\">\n Verified contact data managed by the business owner. Agents can read these records but cannot modify them.\n </p>\n\n <div class=\"sp-toolbar\" style=\"display: flex; gap: 8px;\">\n <button\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n ?disabled=${props.loading}\n @click=${props.onRefresh}\n >\n ${props.loading ? \"Loading...\" : \"Refresh\"}\n </button>\n <button\n class=\"setup-button primary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n @click=${props.onShowAddForm}\n >\n + Add Contact\n </button>\n </div>\n\n ${props.error\n ? html`<div class=\"setup-error\" style=\"margin-top: 16px;\">${props.error}</div>`\n : nothing}\n\n ${props.showAddForm\n ? html`\n <form class=\"contacts-add-form\" @submit=${handleAddSubmit}>\n <input\n type=\"tel\"\n placeholder=\"+447490553305\"\n .value=${props.newRecordPhone}\n @input=${(e: Event) =>\n props.onNewRecordPhoneChange((e.target as HTMLInputElement).value)}\n ?disabled=${props.saving}\n />\n <input\n type=\"text\"\n placeholder=\"Contact name\"\n .value=${props.newRecordName}\n @input=${(e: Event) =>\n props.onNewRecordNameChange((e.target as HTMLInputElement).value)}\n ?disabled=${props.saving}\n />\n <div class=\"contacts-add-form-buttons\">\n <button\n type=\"submit\"\n class=\"setup-button primary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n ?disabled=${props.saving || !props.newRecordPhone.trim() || !props.newRecordName.trim()}\n >\n ${props.saving ? \"Saving...\" : \"Add\"}\n </button>\n <button\n type=\"button\"\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px;\"\n @click=${props.onCancelAddForm}\n >\n Cancel\n </button>\n </div>\n </form>\n `\n : nothing}\n\n <form\n class=\"contacts-search\"\n style=\"margin-top: 16px;\"\n @submit=${handleSearchSubmit}\n >\n <input\n type=\"text\"\n placeholder=\"Search by name or phone...\"\n .value=${props.searchQuery}\n @input=${(e: Event) => props.onSearch((e.target as HTMLInputElement).value)}\n />\n <button\n type=\"submit\"\n class=\"setup-button secondary\"\n style=\"padding: 10px 20px; font-size: 14px; flex-shrink: 0;\"\n >\n Search\n </button>\n </form>\n\n <div style=\"margin-top: 16px;\">\n ${props.records.length === 0\n ? html`<div class=\"contacts-empty\">\n ${props.searchQuery.trim()\n ? `No records matching \"${props.searchQuery}\".`\n : \"No contact records yet. Add one to get started.\"}\n </div>`\n : props.records.map((record) => renderRecord(record, props))}\n </div>\n\n <div class=\"setup-hint\" style=\"margin-top: 20px; padding: 14px; background: rgba(0, 0, 0, 0.2); border-radius: 8px; text-align: left;\">\n <strong style=\"color: var(--tasker-white);\">How it works:</strong><br/>\n Public agents use the\n <code style=\"background: rgba(255,255,255,0.1); padding: 2px 6px; border-radius: 4px; color: var(--tasker-orange);\">contact_lookup</code>\n tool to check payment status and account details (read-only). The admin agent can also create, update, and delete records. Keeping writes admin-only prevents prompt injection from altering sensitive data.\n </div>\n </div>\n </div>\n\n ${deleteRecord ? renderDeleteConfirmModal(deleteRecord, props) : nothing}\n ${addFieldRecord ? renderAddFieldModal(addFieldRecord, props) : nothing}\n `;\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},e=t=>(...e)=>({_$litDirective$:t,values:e});class i{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}export{i as Directive,t as PartType,e as directive};\n//# sourceMappingURL=directive.js.map\n","import{_$LH as o}from\"./lit-html.js\";\n/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const{I:t}=o,i=o=>o,n=o=>null===o||\"object\"!=typeof o&&\"function\"!=typeof o,e={HTML:1,SVG:2,MATHML:3},l=(o,t)=>void 0===t?void 0!==o?._$litType$:o?._$litType$===t,d=o=>null!=o?._$litType$?.h,c=o=>void 0!==o?._$litDirective$,f=o=>o?._$litDirective$,r=o=>void 0===o.strings,s=()=>document.createComment(\"\"),v=(o,n,e)=>{const l=o._$AA.parentNode,d=void 0===n?o._$AB:n._$AA;if(void 0===e){const i=l.insertBefore(s(),d),n=l.insertBefore(s(),d);e=new t(i,n,o,o.options)}else{const t=e._$AB.nextSibling,n=e._$AM,c=n!==o;if(c){let t;e._$AQ?.(o),e._$AM=o,void 0!==e._$AP&&(t=o._$AU)!==n._$AU&&e._$AP(t)}if(t!==d||c){let o=e._$AA;for(;o!==t;){const t=i(o).nextSibling;i(l).insertBefore(o,d),o=t}}}return e},u=(o,t,i=o)=>(o._$AI(t,i),o),m={},p=(o,t=m)=>o._$AH=t,M=o=>o._$AH,h=o=>{o._$AR(),o._$AA.remove()},j=o=>{o._$AR()};export{e as TemplateResultType,j as clearPart,M as getCommittedValue,f as getDirectiveClass,v as insertPart,d as isCompiledTemplateResult,c as isDirectiveResult,n as isPrimitive,r as isSingleExpression,l as isTemplateResult,h as removePart,u as setChildPartValue,p as setCommittedValue};\n//# sourceMappingURL=directive-helpers.js.map\n","import{noChange as e}from\"../lit-html.js\";import{directive as s,Directive as t,PartType as r}from\"../directive.js\";import{getCommittedValue as l,setChildPartValue as o,insertPart as i,removePart as n,setCommittedValue as f}from\"../directive-helpers.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst u=(e,s,t)=>{const r=new Map;for(let l=s;l<=t;l++)r.set(e[l],l);return r},c=s(class extends t{constructor(e){if(super(e),e.type!==r.CHILD)throw Error(\"repeat() can only be used in text expressions\")}dt(e,s,t){let r;void 0===t?t=s:void 0!==s&&(r=s);const l=[],o=[];let i=0;for(const s of e)l[i]=r?r(s,i):i,o[i]=t(s,i),i++;return{values:o,keys:l}}render(e,s,t){return this.dt(e,s,t).values}update(s,[t,r,c]){const d=l(s),{values:p,keys:a}=this.dt(t,r,c);if(!Array.isArray(d))return this.ut=a,p;const h=this.ut??=[],v=[];let m,y,x=0,j=d.length-1,k=0,w=p.length-1;for(;x<=j&&k<=w;)if(null===d[x])x++;else if(null===d[j])j--;else if(h[x]===a[k])v[k]=o(d[x],p[k]),x++,k++;else if(h[j]===a[w])v[w]=o(d[j],p[w]),j--,w--;else if(h[x]===a[w])v[w]=o(d[x],p[w]),i(s,v[w+1],d[x]),x++,w--;else if(h[j]===a[k])v[k]=o(d[j],p[k]),i(s,d[x],d[j]),j--,k++;else if(void 0===m&&(m=u(a,k,w),y=u(h,x,j)),m.has(h[x]))if(m.has(h[j])){const e=y.get(a[k]),t=void 0!==e?d[e]:null;if(null===t){const e=i(s,d[x]);o(e,p[k]),v[k]=e}else v[k]=o(t,p[k]),i(s,d[x],t),d[e]=null;k++}else n(d[j]),j--;else n(d[x]),x++;for(;k<=w;){const e=i(s,v[w+1]);o(e,p[k]),v[k++]=e}for(;x<=j;){const e=d[x++];null!==e&&n(e)}return this.ut=a,f(s,v),e}});export{c as repeat};\n//# sourceMappingURL=repeat.js.map\n","import{nothing as t,noChange as i}from\"../lit-html.js\";import{directive as r,Directive as s,PartType as n}from\"../directive.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */class e extends s{constructor(i){if(super(i),this.it=t,i.type!==n.CHILD)throw Error(this.constructor.directiveName+\"() can only be used in child bindings\")}render(r){if(r===t||null==r)return this._t=void 0,this.it=r;if(r===i)return r;if(\"string\"!=typeof r)throw Error(this.constructor.directiveName+\"() called with a non-string value\");if(r===this.it)return this._t;this.it=r;const s=[r];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}}e.directiveName=\"unsafeHTML\",e.resultType=1;const o=r(e);export{e as UnsafeHTMLDirective,o as unsafeHTML};\n//# sourceMappingURL=unsafe-html.js.map\n","/*! @license DOMPurify 3.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.1/LICENSE */\n\nconst {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n} = Object;\nlet {\n freeze,\n seal,\n create\n} = Object; // eslint-disable-line import/no-mutable-exports\nlet {\n apply,\n construct\n} = typeof Reflect !== 'undefined' && Reflect;\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\nif (!apply) {\n apply = function apply(func, thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n args[_key - 2] = arguments[_key];\n }\n return func.apply(thisArg, args);\n };\n}\nif (!construct) {\n construct = function construct(Func) {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n return new Func(...args);\n };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst arraySplice = unapply(Array.prototype.splice);\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n return function (thisArg) {\n if (thisArg instanceof RegExp) {\n thisArg.lastIndex = 0;\n }\n for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n args[_key3 - 1] = arguments[_key3];\n }\n return apply(func, thisArg, args);\n };\n}\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(Func) {\n return function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return construct(Func, args);\n };\n}\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n}\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n}\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n}\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n}\n\nconst html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\nconst svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\nconst svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nconst svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\nconst mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\nconst mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n// eslint-disable-next-line unicorn/better-regex\nconst MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nconst ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\nconst TMPLIT_EXPR = seal(/\\$\\{[\\w\\W]*/gm); // eslint-disable-line unicorn/better-regex\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\nvar EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n ARIA_ATTR: ARIA_ATTR,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n DATA_ATTR: DATA_ATTR,\n DOCTYPE_NAME: DOCTYPE_NAME,\n ERB_EXPR: ERB_EXPR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR\n});\n\n/* eslint-disable @typescript-eslint/indent */\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n progressingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n};\nconst getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\nconst _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n};\nfunction createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.3.1';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */\n const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {\n tagCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n }\n }));\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with <html>... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n /**\n * _parseConfig\n *\n * @param cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;\n HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (typeof cfg.ADD_TAGS === 'function') {\n EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;\n } else {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n }\n if (cfg.ADD_ATTR) {\n if (typeof cfg.ADD_ATTR === 'function') {\n EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;\n } else {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n if (cfg.ADD_FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);\n }\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n /**\n * @param element a DOM element whose namespace is being checked\n * @returns Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via <svg>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either <annotation-xml> or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via <math>. If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n // The only way to switch from SVG to MathML is via\n // <math> and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n /**\n * _forceRemove\n *\n * @param node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n getParentNode(node).removeChild(node);\n } catch (_) {\n remove(node);\n }\n };\n /**\n * _removeAttribute\n *\n * @param name an Attribute name\n * @param element a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, element) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: element.getAttributeNode(name),\n from: element\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: element\n });\n }\n element.removeAttribute(name);\n // We void attribute values for unremovable \"is\" attributes\n if (name === 'is') {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(element);\n } catch (_) {}\n } else {\n try {\n element.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n /**\n * _initDocument\n *\n * @param dirty - a string of dirty markup\n * @return a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '<remove></remove>' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '<html xmlns=\"http://www.w3.org/1999/xhtml\"><head></head><body>' + dirty + '</body></html>';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param root The root element or node to start traversing on.\n * @return The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n /**\n * _isClobbered\n *\n * @param element element to check for clobbering attacks\n * @return true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(element) {\n return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');\n };\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param value object to check whether it's a DOM node\n * @return true is object is a DOM node\n */\n const _isNode = function _isNode(value) {\n return typeof Node === 'function' && value instanceof Node;\n };\n function _executeHooks(hooks, currentNode, data) {\n arrayForEach(hooks, hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n }\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n * @param currentNode to check for permission to exist\n * @return true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeElement, currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n /* Detect mXSS attempts abusing namespace confusion */\n if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\\w!]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any occurrence of processing instructions */\n if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove element if anything forbids its presence */\n if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n const childClone = cloneNode(childNodes[i], true);\n childClone.__removalCount = (currentNode.__removalCount || 0) + 1;\n parentNode.insertBefore(childClone, getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n return false;\n };\n /**\n * _isValidAttribute\n *\n * @param lcTag Lowercase tag name of containing element.\n * @param lcName Lowercase attribute name.\n * @param value Attribute value.\n * @return Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param tagName name of the tag of the node to sanitize\n * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n const {\n attributes\n } = currentNode;\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes || _isClobbered(currentNode)) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR,\n forceKeepAttr: undefined\n };\n let l = attributes.length;\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n const initValue = attrValue;\n let value = name === 'value' ? initValue : stringTrim(initValue);\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n /* Work around a security issue with comments inside attributes */\n if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\\/(style|title|textarea)/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Make sure we cannot easily use animated hrefs, even if animations are allowed */\n if (lcName === 'attributename' && stringMatch(value, 'href')) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n /* Handle invalid data-* attribute set by try-catching it */\n if (value !== initValue) {\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n } else {\n arrayPop(DOMPurify.removed);\n }\n } catch (_) {\n _removeAttribute(name, currentNode);\n }\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n };\n /**\n * _sanitizeShadowDOM\n *\n * @param fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n /* Sanitize tags and elements */\n _sanitizeElements(shadowNode);\n /* Check attributes next */\n _sanitizeAttributes(shadowNode);\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\n };\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '<!-->';\n }\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n /* Clean up removed elements */\n DOMPurify.removed = [];\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('<!---->');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n _sanitizeElements(currentNode);\n /* Check attributes next */\n _sanitizeAttributes(currentNode);\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n }\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\\n' + serializedHTML;\n }\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n arrayPush(hooks[entryPoint], hookFunction);\n };\n DOMPurify.removeHook = function (entryPoint, hookFunction) {\n if (hookFunction !== undefined) {\n const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);\n return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];\n }\n return arrayPop(hooks[entryPoint]);\n };\n DOMPurify.removeHooks = function (entryPoint) {\n hooks[entryPoint] = [];\n };\n DOMPurify.removeAllHooks = function () {\n hooks = _createHooksMap();\n };\n return DOMPurify;\n}\nvar purify = createDOMPurify();\n\nexport { purify as default };\n//# sourceMappingURL=purify.es.mjs.map\n","/**\n * marked v17.0.1 - a markdown parser\n * Copyright (c) 2018-2025, MarkedJS. (MIT License)\n * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT License)\n * https://github.com/markedjs/marked\n */\n\n/**\n * DO NOT EDIT THIS FILE\n * The code in this file is generated from files in ./src/\n */\n\nfunction L(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var T=L();function Z(u){T=u}var C={exec:()=>null};function k(u,e=\"\"){let t=typeof u==\"string\"?u:u.source,n={replace:(r,i)=>{let s=typeof i==\"string\"?i:i.source;return s=s.replace(m.caret,\"$1\"),t=t.replace(r,s),n},getRegex:()=>new RegExp(t,e)};return n}var me=(()=>{try{return!!new RegExp(\"(?<=1)(?<!1)\")}catch{return!1}})(),m={codeRemoveIndent:/^(?: {1,4}| {0,3}\\t)/gm,outputLinkReplace:/\\\\([\\[\\]])/g,indentCodeCompensation:/^(\\s+)(?:```)/,beginningSpace:/^\\s+/,endingHash:/#$/,startingSpaceChar:/^ /,endingSpaceChar:/ $/,nonSpaceChar:/[^ ]/,newLineCharGlobal:/\\n/g,tabCharGlobal:/\\t/g,multipleSpaceGlobal:/\\s+/g,blankLine:/^[ \\t]*$/,doubleBlankLine:/\\n[ \\t]*\\n[ \\t]*$/,blockquoteStart:/^ {0,3}>/,blockquoteSetextReplace:/\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \\t]?/gm,listReplaceTabs:/^\\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\\[[ xX]\\] +\\S/,listReplaceTask:/^\\[[ xX]\\] +/,listTaskCheckbox:/\\[[ xX]\\]/,anyLine:/\\n.*\\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\\||\\| *$/g,tableRowBlankLine:/\\n[ \\t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^<a /i,endATag:/^<\\/a>/i,startPreScriptTag:/^<(pre|code|kbd|script)(\\s|>)/i,endPreScriptTag:/^<\\/(pre|code|kbd|script)(\\s|>)/i,startAngleBracket:/^</,endAngleBracket:/>$/,pedanticHrefTitle:/^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/,unicodeAlphaNumeric:/[\\p{L}\\p{N}]/u,escapeTest:/[&<>\"']/,escapeReplace:/[&<>\"']/g,escapeTestNoEncode:/[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,escapeReplaceNoEncode:/[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,unescapeTest:/&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/ig,caret:/(^|[^\\[])\\^/g,percentDecode:/%25/g,findPipe:/\\|/g,splitPipe:/ \\|/,slashPipe:/\\\\\\|/g,carriageReturn:/\\r\\n|\\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\\S*/,endingNewline:/\\n$/,listItemRegex:u=>new RegExp(`^( {0,3}${u})((?:[\t ][^\\\\n]*)?(?:\\\\n|$))`),nextBulletRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \t][^\\\\n]*)?(?:\\\\n|$))`),hrRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`),fencesBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:\\`\\`\\`|~~~)`),headingBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}#`),htmlBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}<(?:[a-z].*>|!--)`,\"i\")},xe=/^(?:[ \\t]*(?:\\n|$))+/,be=/^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/,Re=/^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/,I=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,Te=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,N=/(?:[*+-]|\\d{1,9}[.)])/,re=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,se=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/\\|table/g,\"\").getRegex(),Oe=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/table/g,/ {0,3}\\|?(?:[:\\- ]*\\|)+[\\:\\- ]*\\n/).getRegex(),Q=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\\n)[^\\n]+)*)/,we=/^[^\\n]+/,F=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,ye=k(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace(\"label\",F).replace(\"title\",/(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/).getRegex(),Pe=k(/^( {0,3}bull)([ \\t][^\\n]+?)?(?:\\n|$)/).replace(/bull/g,N).getRegex(),v=\"address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul\",j=/<!--(?:-?>|[\\s\\S]*?(?:-->|$))/,Se=k(\"^ {0,3}(?:<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:</\\\\1>[^\\\\n]*\\\\n+|$)|comment[^\\\\n]*(\\\\n+|$)|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>\\\\n*|$)|<![A-Z][\\\\s\\\\S]*?(?:>\\\\n*|$)|<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?(?:\\\\]\\\\]>\\\\n*|$)|</?(tag)(?: +|\\\\n|/?>)[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$)|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$)|</(?!script|pre|style|textarea)[a-z][\\\\w-]*\\\\s*>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$))\",\"i\").replace(\"comment\",j).replace(\"tag\",v).replace(\"attribute\",/ +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/).getRegex(),ie=k(Q).replace(\"hr\",I).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"|lheading\",\"\").replace(\"|table\",\"\").replace(\"blockquote\",\" {0,3}>\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)]) \").replace(\"html\",\"</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",v).getRegex(),$e=k(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace(\"paragraph\",ie).getRegex(),U={blockquote:$e,code:be,def:ye,fences:Re,heading:Te,hr:I,html:Se,lheading:se,list:Pe,newline:xe,paragraph:ie,table:C,text:we},te=k(\"^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)\").replace(\"hr\",I).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"blockquote\",\" {0,3}>\").replace(\"code\",\"(?: {4}| {0,3}\t)[^\\\\n]\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)]) \").replace(\"html\",\"</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",v).getRegex(),_e={...U,lheading:Oe,table:te,paragraph:k(Q).replace(\"hr\",I).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"|lheading\",\"\").replace(\"table\",te).replace(\"blockquote\",\" {0,3}>\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)]) \").replace(\"html\",\"</?(?:tag)(?: +|\\\\n|/?>)|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",v).getRegex()},Le={...U,html:k(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+?</\\\\1> *(?:\\\\n{2,}|\\\\s*$)|<tag(?:\"[^\"]*\"|'[^']*'|\\\\s[^'\"/>\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace(\"comment\",j).replace(/tag/g,\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b\").getRegex(),def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,heading:/^(#{1,6})(.*)(?:\\n+|$)/,fences:C,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:k(Q).replace(\"hr\",I).replace(\"heading\",` *#{1,6} *[^\n]`).replace(\"lheading\",se).replace(\"|table\",\"\").replace(\"blockquote\",\" {0,3}>\").replace(\"|fences\",\"\").replace(\"|list\",\"\").replace(\"|html\",\"\").replace(\"|tag\",\"\").getRegex()},Me=/^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,ze=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,oe=/^( {2,}|\\\\)\\n(?!\\s*$)/,Ae=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*_]|\\b_|$)|[^ ](?= {2,}\\n)))/,D=/[\\p{P}\\p{S}]/u,K=/[\\s\\p{P}\\p{S}]/u,ae=/[^\\s\\p{P}\\p{S}]/u,Ce=k(/^((?![*_])punctSpace)/,\"u\").replace(/punctSpace/g,K).getRegex(),le=/(?!~)[\\p{P}\\p{S}]/u,Ie=/(?!~)[\\s\\p{P}\\p{S}]/u,Ee=/(?:[^\\s\\p{P}\\p{S}]|~)/u,Be=k(/link|precode-code|html/,\"g\").replace(\"link\",/\\[(?:[^\\[\\]`]|(?<a>`+)[^`]+\\k<a>(?!`))*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)/).replace(\"precode-\",me?\"(?<!`)()\":\"(^^|[^`])\").replace(\"code\",/(?<b>`+)[^`]+\\k<b>(?!`)/).replace(\"html\",/<(?! )[^<>]*?>/).getRegex(),ue=/^(?:\\*+(?:((?!\\*)punct)|[^\\s*]))|^_+(?:((?!_)punct)|([^\\s_]))/,qe=k(ue,\"u\").replace(/punct/g,D).getRegex(),ve=k(ue,\"u\").replace(/punct/g,le).getRegex(),pe=\"^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)\",De=k(pe,\"gu\").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),He=k(pe,\"gu\").replace(/notPunctSpace/g,Ee).replace(/punctSpace/g,Ie).replace(/punct/g,le).getRegex(),Ze=k(\"^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)\",\"gu\").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),Ge=k(/\\\\(punct)/,\"gu\").replace(/punct/g,D).getRegex(),Ne=k(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/).replace(\"scheme\",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace(\"email\",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Qe=k(j).replace(\"(?:-->|$)\",\"-->\").getRegex(),Fe=k(\"^comment|^</[a-zA-Z][\\\\w:-]*\\\\s*>|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>|^<\\\\?[\\\\s\\\\S]*?\\\\?>|^<![a-zA-Z]+\\\\s[\\\\s\\\\S]*?>|^<!\\\\[CDATA\\\\[[\\\\s\\\\S]*?\\\\]\\\\]>\").replace(\"comment\",Qe).replace(\"attribute\",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/).getRegex(),q=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+[^`]*?`+(?!`)|[^\\[\\]\\\\`])*?/,je=k(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]*(?:\\n[ \\t]*)?)(title))?\\s*\\)/).replace(\"label\",q).replace(\"href\",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]*/).replace(\"title\",/\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),ce=k(/^!?\\[(label)\\]\\[(ref)\\]/).replace(\"label\",q).replace(\"ref\",F).getRegex(),he=k(/^!?\\[(ref)\\](?:\\[\\])?/).replace(\"ref\",F).getRegex(),Ue=k(\"reflink|nolink(?!\\\\()\",\"g\").replace(\"reflink\",ce).replace(\"nolink\",he).getRegex(),ne=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,W={_backpedal:C,anyPunctuation:Ge,autolink:Ne,blockSkip:Be,br:oe,code:ze,del:C,emStrongLDelim:qe,emStrongRDelimAst:De,emStrongRDelimUnd:Ze,escape:Me,link:je,nolink:he,punctuation:Ce,reflink:ce,reflinkSearch:Ue,tag:Fe,text:Ae,url:C},Ke={...W,link:k(/^!?\\[(label)\\]\\((.*?)\\)/).replace(\"label\",q).getRegex(),reflink:k(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace(\"label\",q).getRegex()},G={...W,emStrongRDelimAst:He,emStrongLDelim:ve,url:k(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace(\"protocol\",ne).replace(\"email\",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,del:/^(~~?)(?=[^\\s~])((?:\\\\[\\s\\S]|[^\\\\])*?(?:\\\\[\\s\\S]|[^\\s~\\\\]))\\1(?=[^~]|$)/,text:k(/^([`~]+|[^`~])(?:(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\<!\\[`*~_]|\\b_|protocol:\\/\\/|www\\.|$)|[^ ](?= {2,}\\n)|[^a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-](?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)))/).replace(\"protocol\",ne).getRegex()},We={...G,br:k(oe).replace(\"{2,}\",\"*\").getRegex(),text:k(G.text).replace(\"\\\\b_\",\"\\\\b_| {2,}\\\\n\").replace(/\\{2,\\}/g,\"*\").getRegex()},E={normal:U,gfm:_e,pedantic:Le},M={normal:W,gfm:G,breaks:We,pedantic:Ke};var Xe={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#39;\"},ke=u=>Xe[u];function w(u,e){if(e){if(m.escapeTest.test(u))return u.replace(m.escapeReplace,ke)}else if(m.escapeTestNoEncode.test(u))return u.replace(m.escapeReplaceNoEncode,ke);return u}function X(u){try{u=encodeURI(u).replace(m.percentDecode,\"%\")}catch{return null}return u}function J(u,e){let t=u.replace(m.findPipe,(i,s,a)=>{let o=!1,l=s;for(;--l>=0&&a[l]===\"\\\\\";)o=!o;return o?\"|\":\" |\"}),n=t.split(m.splitPipe),r=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length<e;)n.push(\"\");for(;r<n.length;r++)n[r]=n[r].trim().replace(m.slashPipe,\"|\");return n}function z(u,e,t){let n=u.length;if(n===0)return\"\";let r=0;for(;r<n;){let i=u.charAt(n-r-1);if(i===e&&!t)r++;else if(i!==e&&t)r++;else break}return u.slice(0,n-r)}function de(u,e){if(u.indexOf(e[1])===-1)return-1;let t=0;for(let n=0;n<u.length;n++)if(u[n]===\"\\\\\")n++;else if(u[n]===e[0])t++;else if(u[n]===e[1]&&(t--,t<0))return n;return t>0?-2:-1}function ge(u,e,t,n,r){let i=e.href,s=e.title||null,a=u[1].replace(r.other.outputLinkReplace,\"$1\");n.state.inLink=!0;let o={type:u[0].charAt(0)===\"!\"?\"image\":\"link\",raw:t,href:i,title:s,text:a,tokens:n.inlineTokens(a)};return n.state.inLink=!1,o}function Je(u,e,t){let n=u.match(t.other.indentCodeCompensation);if(n===null)return e;let r=n[1];return e.split(`\n`).map(i=>{let s=i.match(t.other.beginningSpace);if(s===null)return i;let[a]=s;return a.length>=r.length?i.slice(r.length):i}).join(`\n`)}var y=class{options;rules;lexer;constructor(e){this.options=e||T}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:\"space\",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=t[0].replace(this.rules.other.codeRemoveIndent,\"\");return{type:\"code\",raw:t[0],codeBlockStyle:\"indented\",text:this.options.pedantic?n:z(n,`\n`)}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],r=Je(n,t[3]||\"\",this.rules);return{type:\"code\",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,\"$1\"):t[2],text:r}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let r=z(n,\"#\");(this.options.pedantic||!r||this.rules.other.endingSpaceChar.test(r))&&(n=r.trim())}return{type:\"heading\",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return{type:\"hr\",raw:z(t[0],`\n`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=z(t[0],`\n`).split(`\n`),r=\"\",i=\"\",s=[];for(;n.length>0;){let a=!1,o=[],l;for(l=0;l<n.length;l++)if(this.rules.other.blockquoteStart.test(n[l]))o.push(n[l]),a=!0;else if(!a)o.push(n[l]);else break;n=n.slice(l);let p=o.join(`\n`),c=p.replace(this.rules.other.blockquoteSetextReplace,`\n $1`).replace(this.rules.other.blockquoteSetextReplace2,\"\");r=r?`${r}\n${p}`:p,i=i?`${i}\n${c}`:c;let g=this.lexer.state.top;if(this.lexer.state.top=!0,this.lexer.blockTokens(c,s,!0),this.lexer.state.top=g,n.length===0)break;let h=s.at(-1);if(h?.type===\"code\")break;if(h?.type===\"blockquote\"){let R=h,f=R.raw+`\n`+n.join(`\n`),O=this.blockquote(f);s[s.length-1]=O,r=r.substring(0,r.length-R.raw.length)+O.raw,i=i.substring(0,i.length-R.text.length)+O.text;break}else if(h?.type===\"list\"){let R=h,f=R.raw+`\n`+n.join(`\n`),O=this.list(f);s[s.length-1]=O,r=r.substring(0,r.length-h.raw.length)+O.raw,i=i.substring(0,i.length-R.raw.length)+O.raw,n=f.substring(s.at(-1).raw.length).split(`\n`);continue}}return{type:\"blockquote\",raw:r,tokens:s,text:i}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim(),r=n.length>1,i={type:\"list\",raw:\"\",ordered:r,start:r?+n.slice(0,-1):\"\",loose:!1,items:[]};n=r?`\\\\d{1,9}\\\\${n.slice(-1)}`:`\\\\${n}`,this.options.pedantic&&(n=r?n:\"[*+-]\");let s=this.rules.other.listItemRegex(n),a=!1;for(;e;){let l=!1,p=\"\",c=\"\";if(!(t=s.exec(e))||this.rules.block.hr.test(e))break;p=t[0],e=e.substring(p.length);let g=t[2].split(`\n`,1)[0].replace(this.rules.other.listReplaceTabs,O=>\" \".repeat(3*O.length)),h=e.split(`\n`,1)[0],R=!g.trim(),f=0;if(this.options.pedantic?(f=2,c=g.trimStart()):R?f=t[1].length+1:(f=t[2].search(this.rules.other.nonSpaceChar),f=f>4?1:f,c=g.slice(f),f+=t[1].length),R&&this.rules.other.blankLine.test(h)&&(p+=h+`\n`,e=e.substring(h.length+1),l=!0),!l){let O=this.rules.other.nextBulletRegex(f),V=this.rules.other.hrRegex(f),Y=this.rules.other.fencesBeginRegex(f),ee=this.rules.other.headingBeginRegex(f),fe=this.rules.other.htmlBeginRegex(f);for(;e;){let H=e.split(`\n`,1)[0],A;if(h=H,this.options.pedantic?(h=h.replace(this.rules.other.listReplaceNesting,\" \"),A=h):A=h.replace(this.rules.other.tabCharGlobal,\" \"),Y.test(h)||ee.test(h)||fe.test(h)||O.test(h)||V.test(h))break;if(A.search(this.rules.other.nonSpaceChar)>=f||!h.trim())c+=`\n`+A.slice(f);else{if(R||g.replace(this.rules.other.tabCharGlobal,\" \").search(this.rules.other.nonSpaceChar)>=4||Y.test(g)||ee.test(g)||V.test(g))break;c+=`\n`+h}!R&&!h.trim()&&(R=!0),p+=H+`\n`,e=e.substring(H.length+1),g=A.slice(f)}}i.loose||(a?i.loose=!0:this.rules.other.doubleBlankLine.test(p)&&(a=!0)),i.items.push({type:\"list_item\",raw:p,task:!!this.options.gfm&&this.rules.other.listIsTask.test(c),loose:!1,text:c,tokens:[]}),i.raw+=p}let o=i.items.at(-1);if(o)o.raw=o.raw.trimEnd(),o.text=o.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let l of i.items){if(this.lexer.state.top=!1,l.tokens=this.lexer.blockTokens(l.text,[]),l.task){if(l.text=l.text.replace(this.rules.other.listReplaceTask,\"\"),l.tokens[0]?.type===\"text\"||l.tokens[0]?.type===\"paragraph\"){l.tokens[0].raw=l.tokens[0].raw.replace(this.rules.other.listReplaceTask,\"\"),l.tokens[0].text=l.tokens[0].text.replace(this.rules.other.listReplaceTask,\"\");for(let c=this.lexer.inlineQueue.length-1;c>=0;c--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[c].src)){this.lexer.inlineQueue[c].src=this.lexer.inlineQueue[c].src.replace(this.rules.other.listReplaceTask,\"\");break}}let p=this.rules.other.listTaskCheckbox.exec(l.raw);if(p){let c={type:\"checkbox\",raw:p[0]+\" \",checked:p[0]!==\"[ ]\"};l.checked=c.checked,i.loose?l.tokens[0]&&[\"paragraph\",\"text\"].includes(l.tokens[0].type)&&\"tokens\"in l.tokens[0]&&l.tokens[0].tokens?(l.tokens[0].raw=c.raw+l.tokens[0].raw,l.tokens[0].text=c.raw+l.tokens[0].text,l.tokens[0].tokens.unshift(c)):l.tokens.unshift({type:\"paragraph\",raw:c.raw,text:c.raw,tokens:[c]}):l.tokens.unshift(c)}}if(!i.loose){let p=l.tokens.filter(g=>g.type===\"space\"),c=p.length>0&&p.some(g=>this.rules.other.anyLine.test(g.raw));i.loose=c}}if(i.loose)for(let l of i.items){l.loose=!0;for(let p of l.tokens)p.type===\"text\"&&(p.type=\"paragraph\")}return i}}html(e){let t=this.rules.block.html.exec(e);if(t)return{type:\"html\",block:!0,raw:t[0],pre:t[1]===\"pre\"||t[1]===\"script\"||t[1]===\"style\",text:t[0]}}def(e){let t=this.rules.block.def.exec(e);if(t){let n=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal,\" \"),r=t[2]?t[2].replace(this.rules.other.hrefBrackets,\"$1\").replace(this.rules.inline.anyPunctuation,\"$1\"):\"\",i=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,\"$1\"):t[3];return{type:\"def\",tag:n,raw:t[0],href:r,title:i}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=J(t[1]),r=t[2].replace(this.rules.other.tableAlignChars,\"\").split(\"|\"),i=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,\"\").split(`\n`):[],s={type:\"table\",raw:t[0],header:[],align:[],rows:[]};if(n.length===r.length){for(let a of r)this.rules.other.tableAlignRight.test(a)?s.align.push(\"right\"):this.rules.other.tableAlignCenter.test(a)?s.align.push(\"center\"):this.rules.other.tableAlignLeft.test(a)?s.align.push(\"left\"):s.align.push(null);for(let a=0;a<n.length;a++)s.header.push({text:n[a],tokens:this.lexer.inline(n[a]),header:!0,align:s.align[a]});for(let a of i)s.rows.push(J(a,s.header.length).map((o,l)=>({text:o,tokens:this.lexer.inline(o),header:!1,align:s.align[l]})));return s}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t)return{type:\"heading\",raw:t[0],depth:t[2].charAt(0)===\"=\"?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===`\n`?t[1].slice(0,-1):t[1];return{type:\"paragraph\",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return{type:\"text\",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return{type:\"escape\",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:\"html\",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let s=z(n.slice(0,-1),\"\\\\\");if((n.length-s.length)%2===0)return}else{let s=de(t[2],\"()\");if(s===-2)return;if(s>-1){let o=(t[0].indexOf(\"!\")===0?5:4)+t[1].length+s;t[2]=t[2].substring(0,s),t[0]=t[0].substring(0,o).trim(),t[3]=\"\"}}let r=t[2],i=\"\";if(this.options.pedantic){let s=this.rules.other.pedanticHrefTitle.exec(r);s&&(r=s[1],i=s[3])}else i=t[3]?t[3].slice(1,-1):\"\";return r=r.trim(),this.rules.other.startAngleBracket.test(r)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?r=r.slice(1):r=r.slice(1,-1)),ge(t,{href:r&&r.replace(this.rules.inline.anyPunctuation,\"$1\"),title:i&&i.replace(this.rules.inline.anyPunctuation,\"$1\")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let r=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal,\" \"),i=t[r.toLowerCase()];if(!i){let s=n[0].charAt(0);return{type:\"text\",raw:s,text:s}}return ge(n,i,n[0],this.lexer,this.rules)}}emStrong(e,t,n=\"\"){let r=this.rules.inline.emStrongLDelim.exec(e);if(!r||r[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(r[1]||r[2]||\"\")||!n||this.rules.inline.punctuation.exec(n)){let s=[...r[0]].length-1,a,o,l=s,p=0,c=r[0][0]===\"*\"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(c.lastIndex=0,t=t.slice(-1*e.length+s);(r=c.exec(t))!=null;){if(a=r[1]||r[2]||r[3]||r[4]||r[5]||r[6],!a)continue;if(o=[...a].length,r[3]||r[4]){l+=o;continue}else if((r[5]||r[6])&&s%3&&!((s+o)%3)){p+=o;continue}if(l-=o,l>0)continue;o=Math.min(o,o+l+p);let g=[...r[0]][0].length,h=e.slice(0,s+r.index+g+o);if(Math.min(s,o)%2){let f=h.slice(1,-1);return{type:\"em\",raw:h,text:f,tokens:this.lexer.inlineTokens(f)}}let R=h.slice(2,-2);return{type:\"strong\",raw:h,text:R,tokens:this.lexer.inlineTokens(R)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal,\" \"),r=this.rules.other.nonSpaceChar.test(n),i=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return r&&i&&(n=n.substring(1,n.length-1)),{type:\"codespan\",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:\"br\",raw:t[0]}}del(e){let t=this.rules.inline.del.exec(e);if(t)return{type:\"del\",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,r;return t[2]===\"@\"?(n=t[1],r=\"mailto:\"+n):(n=t[1],r=n),{type:\"link\",raw:t[0],text:n,href:r,tokens:[{type:\"text\",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,r;if(t[2]===\"@\")n=t[0],r=\"mailto:\"+n;else{let i;do i=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??\"\";while(i!==t[0]);n=t[0],t[1]===\"www.\"?r=\"http://\"+t[0]:r=t[0]}return{type:\"link\",raw:t[0],text:n,href:r,tokens:[{type:\"text\",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return{type:\"text\",raw:t[0],text:t[0],escaped:n}}}};var x=class u{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||T,this.options.tokenizer=this.options.tokenizer||new y,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let t={other:m,block:E.normal,inline:M.normal};this.options.pedantic?(t.block=E.pedantic,t.inline=M.pedantic):this.options.gfm&&(t.block=E.gfm,this.options.breaks?t.inline=M.breaks:t.inline=M.gfm),this.tokenizer.rules=t}static get rules(){return{block:E,inline:M}}static lex(e,t){return new u(t).lex(e)}static lexInline(e,t){return new u(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,`\n`),this.blockTokens(e,this.tokens);for(let t=0;t<this.inlineQueue.length;t++){let n=this.inlineQueue[t];this.inlineTokens(n.src,n.tokens)}return this.inlineQueue=[],this.tokens}blockTokens(e,t=[],n=!1){for(this.options.pedantic&&(e=e.replace(m.tabCharGlobal,\" \").replace(m.spaceLine,\"\"));e;){let r;if(this.options.extensions?.block?.some(s=>(r=s.call({lexer:this},e,t))?(e=e.substring(r.raw.length),t.push(r),!0):!1))continue;if(r=this.tokenizer.space(e)){e=e.substring(r.raw.length);let s=t.at(-1);r.raw.length===1&&s!==void 0?s.raw+=`\n`:t.push(r);continue}if(r=this.tokenizer.code(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type===\"paragraph\"||s?.type===\"text\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.text,this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(r=this.tokenizer.fences(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.heading(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.hr(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.blockquote(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.list(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.html(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.def(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type===\"paragraph\"||s?.type===\"text\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.raw,this.inlineQueue.at(-1).src=s.text):this.tokens.links[r.tag]||(this.tokens.links[r.tag]={href:r.href,title:r.title},t.push(r));continue}if(r=this.tokenizer.table(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.lheading(e)){e=e.substring(r.raw.length),t.push(r);continue}let i=e;if(this.options.extensions?.startBlock){let s=1/0,a=e.slice(1),o;this.options.extensions.startBlock.forEach(l=>{o=l.call({lexer:this},a),typeof o==\"number\"&&o>=0&&(s=Math.min(s,o))}),s<1/0&&s>=0&&(i=e.substring(0,s+1))}if(this.state.top&&(r=this.tokenizer.paragraph(i))){let s=t.at(-1);n&&s?.type===\"paragraph\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r),n=i.length!==e.length,e=e.substring(r.raw.length);continue}if(r=this.tokenizer.text(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type===\"text\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(e){let s=\"Infinite loop on byte: \"+e.charCodeAt(0);if(this.options.silent){console.error(s);break}else throw new Error(s)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,r=null;if(this.tokens.links){let o=Object.keys(this.tokens.links);if(o.length>0)for(;(r=this.tokenizer.rules.inline.reflinkSearch.exec(n))!=null;)o.includes(r[0].slice(r[0].lastIndexOf(\"[\")+1,-1))&&(n=n.slice(0,r.index)+\"[\"+\"a\".repeat(r[0].length-2)+\"]\"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(r=this.tokenizer.rules.inline.anyPunctuation.exec(n))!=null;)n=n.slice(0,r.index)+\"++\"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let i;for(;(r=this.tokenizer.rules.inline.blockSkip.exec(n))!=null;)i=r[2]?r[2].length:0,n=n.slice(0,r.index+i)+\"[\"+\"a\".repeat(r[0].length-i-2)+\"]\"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=this.options.hooks?.emStrongMask?.call({lexer:this},n)??n;let s=!1,a=\"\";for(;e;){s||(a=\"\"),s=!1;let o;if(this.options.extensions?.inline?.some(p=>(o=p.call({lexer:this},e,t))?(e=e.substring(o.raw.length),t.push(o),!0):!1))continue;if(o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length);let p=t.at(-1);o.type===\"text\"&&p?.type===\"text\"?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(o=this.tokenizer.emStrong(e,n,a)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.autolink(e)){e=e.substring(o.raw.length),t.push(o);continue}if(!this.state.inLink&&(o=this.tokenizer.url(e))){e=e.substring(o.raw.length),t.push(o);continue}let l=e;if(this.options.extensions?.startInline){let p=1/0,c=e.slice(1),g;this.options.extensions.startInline.forEach(h=>{g=h.call({lexer:this},c),typeof g==\"number\"&&g>=0&&(p=Math.min(p,g))}),p<1/0&&p>=0&&(l=e.substring(0,p+1))}if(o=this.tokenizer.inlineText(l)){e=e.substring(o.raw.length),o.raw.slice(-1)!==\"_\"&&(a=o.raw.slice(-1)),s=!0;let p=t.at(-1);p?.type===\"text\"?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(e){let p=\"Infinite loop on byte: \"+e.charCodeAt(0);if(this.options.silent){console.error(p);break}else throw new Error(p)}}return t}};var P=class{options;parser;constructor(e){this.options=e||T}space(e){return\"\"}code({text:e,lang:t,escaped:n}){let r=(t||\"\").match(m.notSpaceStart)?.[0],i=e.replace(m.endingNewline,\"\")+`\n`;return r?'<pre><code class=\"language-'+w(r)+'\">'+(n?i:w(i,!0))+`</code></pre>\n`:\"<pre><code>\"+(n?i:w(i,!0))+`</code></pre>\n`}blockquote({tokens:e}){return`<blockquote>\n${this.parser.parse(e)}</blockquote>\n`}html({text:e}){return e}def(e){return\"\"}heading({tokens:e,depth:t}){return`<h${t}>${this.parser.parseInline(e)}</h${t}>\n`}hr(e){return`<hr>\n`}list(e){let t=e.ordered,n=e.start,r=\"\";for(let a=0;a<e.items.length;a++){let o=e.items[a];r+=this.listitem(o)}let i=t?\"ol\":\"ul\",s=t&&n!==1?' start=\"'+n+'\"':\"\";return\"<\"+i+s+`>\n`+r+\"</\"+i+`>\n`}listitem(e){return`<li>${this.parser.parse(e.tokens)}</li>\n`}checkbox({checked:e}){return\"<input \"+(e?'checked=\"\" ':\"\")+'disabled=\"\" type=\"checkbox\"> '}paragraph({tokens:e}){return`<p>${this.parser.parseInline(e)}</p>\n`}table(e){let t=\"\",n=\"\";for(let i=0;i<e.header.length;i++)n+=this.tablecell(e.header[i]);t+=this.tablerow({text:n});let r=\"\";for(let i=0;i<e.rows.length;i++){let s=e.rows[i];n=\"\";for(let a=0;a<s.length;a++)n+=this.tablecell(s[a]);r+=this.tablerow({text:n})}return r&&(r=`<tbody>${r}</tbody>`),`<table>\n<thead>\n`+t+`</thead>\n`+r+`</table>\n`}tablerow({text:e}){return`<tr>\n${e}</tr>\n`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?\"th\":\"td\";return(e.align?`<${n} align=\"${e.align}\">`:`<${n}>`)+t+`</${n}>\n`}strong({tokens:e}){return`<strong>${this.parser.parseInline(e)}</strong>`}em({tokens:e}){return`<em>${this.parser.parseInline(e)}</em>`}codespan({text:e}){return`<code>${w(e,!0)}</code>`}br(e){return\"<br>\"}del({tokens:e}){return`<del>${this.parser.parseInline(e)}</del>`}link({href:e,title:t,tokens:n}){let r=this.parser.parseInline(n),i=X(e);if(i===null)return r;e=i;let s='<a href=\"'+e+'\"';return t&&(s+=' title=\"'+w(t)+'\"'),s+=\">\"+r+\"</a>\",s}image({href:e,title:t,text:n,tokens:r}){r&&(n=this.parser.parseInline(r,this.parser.textRenderer));let i=X(e);if(i===null)return w(n);e=i;let s=`<img src=\"${e}\" alt=\"${n}\"`;return t&&(s+=` title=\"${w(t)}\"`),s+=\">\",s}text(e){return\"tokens\"in e&&e.tokens?this.parser.parseInline(e.tokens):\"escaped\"in e&&e.escaped?e.text:w(e.text)}};var $=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return\"\"+e}image({text:e}){return\"\"+e}br(){return\"\"}checkbox({raw:e}){return e}};var b=class u{options;renderer;textRenderer;constructor(e){this.options=e||T,this.options.renderer=this.options.renderer||new P,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new $}static parse(e,t){return new u(t).parse(e)}static parseInline(e,t){return new u(t).parseInline(e)}parse(e){let t=\"\";for(let n=0;n<e.length;n++){let r=e[n];if(this.options.extensions?.renderers?.[r.type]){let s=r,a=this.options.extensions.renderers[s.type].call({parser:this},s);if(a!==!1||![\"space\",\"hr\",\"heading\",\"code\",\"table\",\"blockquote\",\"list\",\"html\",\"def\",\"paragraph\",\"text\"].includes(s.type)){t+=a||\"\";continue}}let i=r;switch(i.type){case\"space\":{t+=this.renderer.space(i);break}case\"hr\":{t+=this.renderer.hr(i);break}case\"heading\":{t+=this.renderer.heading(i);break}case\"code\":{t+=this.renderer.code(i);break}case\"table\":{t+=this.renderer.table(i);break}case\"blockquote\":{t+=this.renderer.blockquote(i);break}case\"list\":{t+=this.renderer.list(i);break}case\"checkbox\":{t+=this.renderer.checkbox(i);break}case\"html\":{t+=this.renderer.html(i);break}case\"def\":{t+=this.renderer.def(i);break}case\"paragraph\":{t+=this.renderer.paragraph(i);break}case\"text\":{t+=this.renderer.text(i);break}default:{let s='Token with \"'+i.type+'\" type was not found.';if(this.options.silent)return console.error(s),\"\";throw new Error(s)}}}return t}parseInline(e,t=this.renderer){let n=\"\";for(let r=0;r<e.length;r++){let i=e[r];if(this.options.extensions?.renderers?.[i.type]){let a=this.options.extensions.renderers[i.type].call({parser:this},i);if(a!==!1||![\"escape\",\"html\",\"link\",\"image\",\"strong\",\"em\",\"codespan\",\"br\",\"del\",\"text\"].includes(i.type)){n+=a||\"\";continue}}let s=i;switch(s.type){case\"escape\":{n+=t.text(s);break}case\"html\":{n+=t.html(s);break}case\"link\":{n+=t.link(s);break}case\"image\":{n+=t.image(s);break}case\"checkbox\":{n+=t.checkbox(s);break}case\"strong\":{n+=t.strong(s);break}case\"em\":{n+=t.em(s);break}case\"codespan\":{n+=t.codespan(s);break}case\"br\":{n+=t.br(s);break}case\"del\":{n+=t.del(s);break}case\"text\":{n+=t.text(s);break}default:{let a='Token with \"'+s.type+'\" type was not found.';if(this.options.silent)return console.error(a),\"\";throw new Error(a)}}}return n}};var S=class{options;block;constructor(e){this.options=e||T}static passThroughHooks=new Set([\"preprocess\",\"postprocess\",\"processAllTokens\",\"emStrongMask\"]);static passThroughHooksRespectAsync=new Set([\"preprocess\",\"postprocess\",\"processAllTokens\"]);preprocess(e){return e}postprocess(e){return e}processAllTokens(e){return e}emStrongMask(e){return e}provideLexer(){return this.block?x.lex:x.lexInline}provideParser(){return this.block?b.parse:b.parseInline}};var B=class{defaults=L();options=this.setOptions;parse=this.parseMarkdown(!0);parseInline=this.parseMarkdown(!1);Parser=b;Renderer=P;TextRenderer=$;Lexer=x;Tokenizer=y;Hooks=S;constructor(...e){this.use(...e)}walkTokens(e,t){let n=[];for(let r of e)switch(n=n.concat(t.call(this,r)),r.type){case\"table\":{let i=r;for(let s of i.header)n=n.concat(this.walkTokens(s.tokens,t));for(let s of i.rows)for(let a of s)n=n.concat(this.walkTokens(a.tokens,t));break}case\"list\":{let i=r;n=n.concat(this.walkTokens(i.items,t));break}default:{let i=r;this.defaults.extensions?.childTokens?.[i.type]?this.defaults.extensions.childTokens[i.type].forEach(s=>{let a=i[s].flat(1/0);n=n.concat(this.walkTokens(a,t))}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let r={...n};if(r.async=this.defaults.async||r.async||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error(\"extension name required\");if(\"renderer\"in i){let s=t.renderers[i.name];s?t.renderers[i.name]=function(...a){let o=i.renderer.apply(this,a);return o===!1&&(o=s.apply(this,a)),o}:t.renderers[i.name]=i.renderer}if(\"tokenizer\"in i){if(!i.level||i.level!==\"block\"&&i.level!==\"inline\")throw new Error(\"extension level must be 'block' or 'inline'\");let s=t[i.level];s?s.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level===\"block\"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level===\"inline\"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]))}\"childTokens\"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens)}),r.extensions=t),n.renderer){let i=this.defaults.renderer||new P(this.defaults);for(let s in n.renderer){if(!(s in i))throw new Error(`renderer '${s}' does not exist`);if([\"options\",\"parser\"].includes(s))continue;let a=s,o=n.renderer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c||\"\"}}r.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new y(this.defaults);for(let s in n.tokenizer){if(!(s in i))throw new Error(`tokenizer '${s}' does not exist`);if([\"options\",\"rules\",\"lexer\"].includes(s))continue;let a=s,o=n.tokenizer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c}}r.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new S;for(let s in n.hooks){if(!(s in i))throw new Error(`hook '${s}' does not exist`);if([\"options\",\"block\"].includes(s))continue;let a=s,o=n.hooks[a],l=i[a];S.passThroughHooks.has(s)?i[a]=p=>{if(this.defaults.async&&S.passThroughHooksRespectAsync.has(s))return(async()=>{let g=await o.call(i,p);return l.call(i,g)})();let c=o.call(i,p);return l.call(i,c)}:i[a]=(...p)=>{if(this.defaults.async)return(async()=>{let g=await o.apply(i,p);return g===!1&&(g=await l.apply(i,p)),g})();let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c}}r.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,s=n.walkTokens;r.walkTokens=function(a){let o=[];return o.push(s.call(this,a)),i&&(o=o.concat(i.call(this,a))),o}}this.defaults={...this.defaults,...r}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return(n,r)=>{let i={...r},s={...this.defaults,...i},a=this.onError(!!s.silent,!!s.async);if(this.defaults.async===!0&&i.async===!1)return a(new Error(\"marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.\"));if(typeof n>\"u\"||n===null)return a(new Error(\"marked(): input parameter is undefined or null\"));if(typeof n!=\"string\")return a(new Error(\"marked(): input parameter is of type \"+Object.prototype.toString.call(n)+\", string expected\"));if(s.hooks&&(s.hooks.options=s,s.hooks.block=e),s.async)return(async()=>{let o=s.hooks?await s.hooks.preprocess(n):n,p=await(s.hooks?await s.hooks.provideLexer():e?x.lex:x.lexInline)(o,s),c=s.hooks?await s.hooks.processAllTokens(p):p;s.walkTokens&&await Promise.all(this.walkTokens(c,s.walkTokens));let h=await(s.hooks?await s.hooks.provideParser():e?b.parse:b.parseInline)(c,s);return s.hooks?await s.hooks.postprocess(h):h})().catch(a);try{s.hooks&&(n=s.hooks.preprocess(n));let l=(s.hooks?s.hooks.provideLexer():e?x.lex:x.lexInline)(n,s);s.hooks&&(l=s.hooks.processAllTokens(l)),s.walkTokens&&this.walkTokens(l,s.walkTokens);let c=(s.hooks?s.hooks.provideParser():e?b.parse:b.parseInline)(l,s);return s.hooks&&(c=s.hooks.postprocess(c)),c}catch(o){return a(o)}}}onError(e,t){return n=>{if(n.message+=`\nPlease report this to https://github.com/markedjs/marked.`,e){let r=\"<p>An error occurred:</p><pre>\"+w(n.message+\"\",!0)+\"</pre>\";return t?Promise.resolve(r):r}if(t)return Promise.reject(n);throw n}}};var _=new B;function d(u,e){return _.parse(u,e)}d.options=d.setOptions=function(u){return _.setOptions(u),d.defaults=_.defaults,Z(d.defaults),d};d.getDefaults=L;d.defaults=T;d.use=function(...u){return _.use(...u),d.defaults=_.defaults,Z(d.defaults),d};d.walkTokens=function(u,e){return _.walkTokens(u,e)};d.parseInline=_.parseInline;d.Parser=b;d.parser=b.parse;d.Renderer=P;d.TextRenderer=$;d.Lexer=x;d.lexer=x.lex;d.Tokenizer=y;d.Hooks=S;d.parse=d;var Dt=d.options,Ht=d.setOptions,Zt=d.use,Gt=d.walkTokens,Nt=d.parseInline,Qt=d,Ft=b.parse,jt=x.lex;export{S as Hooks,x as Lexer,B as Marked,b as Parser,P as Renderer,$ as TextRenderer,y as Tokenizer,T as defaults,L as getDefaults,jt as lexer,d as marked,Dt as options,Qt as parse,Nt as parseInline,Ft as parser,Ht as setOptions,Zt as use,Gt as walkTokens};\n//# sourceMappingURL=marked.esm.js.map\n","import DOMPurify from \"dompurify\";\nimport { marked } from \"marked\";\nimport { truncateText } from \"./format\";\n\nmarked.setOptions({\n gfm: true,\n breaks: true,\n mangle: false,\n});\n\nconst allowedTags = [\n \"a\",\n \"b\",\n \"blockquote\",\n \"br\",\n \"code\",\n \"del\",\n \"em\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"hr\",\n \"i\",\n \"li\",\n \"ol\",\n \"p\",\n \"pre\",\n \"strong\",\n \"table\",\n \"tbody\",\n \"td\",\n \"th\",\n \"thead\",\n \"tr\",\n \"ul\",\n];\n\nconst allowedAttrs = [\"class\", \"href\", \"rel\", \"target\", \"title\", \"start\"];\n\nlet hooksInstalled = false;\nconst MARKDOWN_CHAR_LIMIT = 140_000;\nconst MARKDOWN_PARSE_LIMIT = 40_000;\nconst MARKDOWN_CACHE_LIMIT = 200;\nconst MARKDOWN_CACHE_MAX_CHARS = 50_000;\nconst markdownCache = new Map<string, string>();\n\nfunction getCachedMarkdown(key: string): string | null {\n const cached = markdownCache.get(key);\n if (cached === undefined) return null;\n markdownCache.delete(key);\n markdownCache.set(key, cached);\n return cached;\n}\n\nfunction setCachedMarkdown(key: string, value: string) {\n markdownCache.set(key, value);\n if (markdownCache.size <= MARKDOWN_CACHE_LIMIT) return;\n const oldest = markdownCache.keys().next().value;\n if (oldest) markdownCache.delete(oldest);\n}\n\nfunction installHooks() {\n if (hooksInstalled) return;\n hooksInstalled = true;\n\n DOMPurify.addHook(\"afterSanitizeAttributes\", (node) => {\n if (!(node instanceof HTMLAnchorElement)) return;\n const href = node.getAttribute(\"href\");\n if (!href) return;\n node.setAttribute(\"rel\", \"noreferrer noopener\");\n node.setAttribute(\"target\", \"_blank\");\n });\n}\n\nexport function toSanitizedMarkdownHtml(markdown: string): string {\n const input = markdown.trim();\n if (!input) return \"\";\n installHooks();\n if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {\n const cached = getCachedMarkdown(input);\n if (cached !== null) return cached;\n }\n const truncated = truncateText(input, MARKDOWN_CHAR_LIMIT);\n const suffix = truncated.truncated\n ? `\\n\\n… truncated (${truncated.total} chars, showing first ${truncated.text.length}).`\n : \"\";\n if (truncated.text.length > MARKDOWN_PARSE_LIMIT) {\n const escaped = escapeHtml(`${truncated.text}${suffix}`);\n const html = `<pre class=\"code-block\">${escaped}</pre>`;\n const sanitized = DOMPurify.sanitize(html, {\n ALLOWED_TAGS: allowedTags,\n ALLOWED_ATTR: allowedAttrs,\n });\n if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {\n setCachedMarkdown(input, sanitized);\n }\n return sanitized;\n }\n const rendered = marked.parse(`${truncated.text}${suffix}`) as string;\n const sanitized = DOMPurify.sanitize(rendered, {\n ALLOWED_TAGS: allowedTags,\n ALLOWED_ATTR: allowedAttrs,\n });\n if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {\n setCachedMarkdown(input, sanitized);\n }\n return sanitized;\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&#39;\");\n}\n","import { html, type TemplateResult } from \"lit\";\nimport { icons } from \"../icons\";\n\nconst COPIED_FOR_MS = 1500;\nconst ERROR_FOR_MS = 2000;\nconst COPY_LABEL = \"Copy as markdown\";\nconst COPIED_LABEL = \"Copied\";\nconst ERROR_LABEL = \"Copy failed\";\n\ntype CopyButtonOptions = {\n text: () => string;\n label?: string;\n};\n\nasync function copyTextToClipboard(text: string): Promise<boolean> {\n if (!text) return false;\n\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n // Fallback for non-HTTPS (e.g. http://taskmaster.local on Pi)\n try {\n const el = document.createElement(\"textarea\");\n el.value = text;\n el.style.position = \"fixed\";\n el.style.opacity = \"0\";\n document.body.appendChild(el);\n el.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(el);\n return ok;\n } catch {\n return false;\n }\n }\n}\n\nfunction setButtonLabel(button: HTMLButtonElement, label: string) {\n button.title = label;\n button.setAttribute(\"aria-label\", label);\n}\n\nfunction createCopyButton(options: CopyButtonOptions): TemplateResult {\n const idleLabel = options.label ?? COPY_LABEL;\n return html`\n <button\n class=\"chat-copy-btn\"\n type=\"button\"\n title=${idleLabel}\n aria-label=${idleLabel}\n @click=${async (e: Event) => {\n const btn = e.currentTarget as HTMLButtonElement | null;\n const iconContainer = btn?.querySelector(\n \".chat-copy-btn__icon\",\n ) as HTMLElement | null;\n\n if (!btn || btn.dataset.copying === \"1\") return;\n\n btn.dataset.copying = \"1\";\n btn.setAttribute(\"aria-busy\", \"true\");\n btn.disabled = true;\n\n const copied = await copyTextToClipboard(options.text());\n if (!btn.isConnected) return;\n\n delete btn.dataset.copying;\n btn.removeAttribute(\"aria-busy\");\n btn.disabled = false;\n\n if (!copied) {\n btn.dataset.error = \"1\";\n setButtonLabel(btn, ERROR_LABEL);\n\n window.setTimeout(() => {\n if (!btn.isConnected) return;\n delete btn.dataset.error;\n setButtonLabel(btn, idleLabel);\n }, ERROR_FOR_MS);\n return;\n }\n\n btn.dataset.copied = \"1\";\n setButtonLabel(btn, COPIED_LABEL);\n\n window.setTimeout(() => {\n if (!btn.isConnected) return;\n delete btn.dataset.copied;\n setButtonLabel(btn, idleLabel);\n }, COPIED_FOR_MS);\n }}\n >\n <span class=\"chat-copy-btn__icon\" aria-hidden=\"true\">\n <span class=\"chat-copy-btn__icon-copy\">${icons.copy}</span>\n <span class=\"chat-copy-btn__icon-check\">${icons.check}</span>\n </span>\n </button>\n `;\n}\n\nexport function renderCopyAsMarkdownButton(markdown: string): TemplateResult {\n return createCopyButton({ text: () => markdown, label: COPY_LABEL });\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatToolDetail, resolveToolDisplay } from \"../tool-display\";\nimport { icons } from \"../icons\";\nimport type { ToolCard } from \"../types/chat-types\";\nimport { TOOL_INLINE_THRESHOLD } from \"./constants\";\nimport {\n formatToolOutputForSidebar,\n getTruncatedPreview,\n} from \"./tool-helpers\";\nimport { isToolResultMessage } from \"./message-normalizer\";\nimport { extractTextCached } from \"./message-extract\";\n\nexport function extractToolCards(message: unknown): ToolCard[] {\n const m = message as Record<string, unknown>;\n const content = normalizeContent(m.content);\n const cards: ToolCard[] = [];\n\n for (const item of content) {\n const kind = String(item.type ?? \"\").toLowerCase();\n const isToolCall =\n [\"toolcall\", \"tool_call\", \"tooluse\", \"tool_use\"].includes(kind) ||\n (typeof item.name === \"string\" && item.arguments != null);\n if (isToolCall) {\n cards.push({\n kind: \"call\",\n name: (item.name as string) ?? \"tool\",\n args: coerceArgs(item.arguments ?? item.args),\n });\n }\n }\n\n for (const item of content) {\n const kind = String(item.type ?? \"\").toLowerCase();\n if (kind !== \"toolresult\" && kind !== \"tool_result\") continue;\n const text = extractToolText(item);\n const name = typeof item.name === \"string\" ? item.name : \"tool\";\n cards.push({ kind: \"result\", name, text });\n }\n\n if (\n isToolResultMessage(message) &&\n !cards.some((card) => card.kind === \"result\")\n ) {\n const name =\n (typeof m.toolName === \"string\" && m.toolName) ||\n (typeof m.tool_name === \"string\" && m.tool_name) ||\n \"tool\";\n const text = extractTextCached(message) ?? undefined;\n cards.push({ kind: \"result\", name, text });\n }\n\n return cards;\n}\n\nexport function renderToolCardSidebar(\n card: ToolCard,\n onOpenSidebar?: (content: string) => void,\n) {\n const display = resolveToolDisplay({ name: card.name, args: card.args });\n const detail = formatToolDetail(display);\n const hasText = Boolean(card.text?.trim());\n\n const canClick = Boolean(onOpenSidebar);\n const handleClick = canClick\n ? () => {\n if (hasText) {\n onOpenSidebar!(formatToolOutputForSidebar(card.text!));\n return;\n }\n const info = `## ${display.label}\\n\\n${\n detail ? `**Command:** \\`${detail}\\`\\n\\n` : \"\"\n }*No output — tool completed successfully.*`;\n onOpenSidebar!(info);\n }\n : undefined;\n\n const isShort = hasText && (card.text?.length ?? 0) <= TOOL_INLINE_THRESHOLD;\n const showCollapsed = hasText && !isShort;\n const showInline = hasText && isShort;\n const isEmpty = !hasText;\n\n return html`\n <div\n class=\"chat-tool-card ${canClick ? \"chat-tool-card--clickable\" : \"\"}\"\n @click=${handleClick}\n role=${canClick ? \"button\" : nothing}\n tabindex=${canClick ? \"0\" : nothing}\n @keydown=${canClick\n ? (e: KeyboardEvent) => {\n if (e.key !== \"Enter\" && e.key !== \" \") return;\n e.preventDefault();\n handleClick?.();\n }\n : nothing}\n >\n <div class=\"chat-tool-card__header\">\n <div class=\"chat-tool-card__title\">\n <span class=\"chat-tool-card__icon\">${icons[display.icon]}</span>\n <span>${display.label}</span>\n </div>\n ${canClick\n ? html`<span class=\"chat-tool-card__action\">${hasText ? \"View\" : \"\"} ${icons.check}</span>`\n : nothing}\n ${isEmpty && !canClick ? html`<span class=\"chat-tool-card__status\">${icons.check}</span>` : nothing}\n </div>\n ${detail\n ? html`<div class=\"chat-tool-card__detail\">${detail}</div>`\n : nothing}\n ${isEmpty\n ? html`<div class=\"chat-tool-card__status-text muted\">Completed</div>`\n : nothing}\n ${showCollapsed\n ? html`<div class=\"chat-tool-card__preview mono\">${getTruncatedPreview(card.text!)}</div>`\n : nothing}\n ${showInline\n ? html`<div class=\"chat-tool-card__inline mono\">${card.text}</div>`\n : nothing}\n </div>\n `;\n}\n\nfunction normalizeContent(content: unknown): Array<Record<string, unknown>> {\n if (!Array.isArray(content)) return [];\n return content.filter(Boolean) as Array<Record<string, unknown>>;\n}\n\nfunction coerceArgs(value: unknown): unknown {\n if (typeof value !== \"string\") return value;\n const trimmed = value.trim();\n if (!trimmed) return value;\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) return value;\n try {\n return JSON.parse(trimmed);\n } catch {\n return value;\n }\n}\n\nfunction extractToolText(item: Record<string, unknown>): string | undefined {\n if (typeof item.text === \"string\") return item.text;\n if (typeof item.content === \"string\") return item.content;\n return undefined;\n}\n","import { html, nothing } from \"lit\";\n\n/**\n * WhatsApp-style voice note player.\n *\n * Design: Lit renders the static structure. Audio event handlers update the\n * dynamic parts (bars, time, icons) imperatively via DOM queries, avoiding\n * full Lit re-renders on every timeupdate (~4 Hz). External state is kept\n * in sync so Lit re-renders (e.g. new message arrives) produce the correct\n * output without flicker.\n */\n\n// ── Waveform extraction ──────────────────────────────────────────────\n\nconst WAVEFORM_BARS = 40;\nconst waveformCache = new Map<string, number[]>();\n\nasync function extractWaveform(url: string): Promise<number[]> {\n const cached = waveformCache.get(url);\n if (cached) return cached;\n\n try {\n const ctx = new (window.AudioContext || (window as any).webkitAudioContext)();\n const res = await fetch(url);\n const buf = await res.arrayBuffer();\n const decoded = await ctx.decodeAudioData(buf);\n const raw = decoded.getChannelData(0);\n\n const step = Math.floor(raw.length / WAVEFORM_BARS);\n const peaks: number[] = [];\n for (let i = 0; i < WAVEFORM_BARS; i++) {\n let max = 0;\n const start = i * step;\n const end = Math.min(start + step, raw.length);\n for (let j = start; j < end; j++) {\n const v = Math.abs(raw[j]);\n if (v > max) max = v;\n }\n peaks.push(max);\n }\n\n const peak = Math.max(...peaks, 0.01);\n const normalized = peaks.map((v) => Math.max(v / peak, 0.08));\n waveformCache.set(url, normalized);\n void ctx.close();\n return normalized;\n } catch {\n // Deterministic pseudo-random waveform from URL hash\n const hash = Array.from(url).reduce((h, c) => ((h << 5) - h + c.charCodeAt(0)) | 0, 0);\n const bars: number[] = [];\n for (let i = 0; i < WAVEFORM_BARS; i++) {\n const seed = Math.abs(((hash * (i + 1) * 9301 + 49297) % 233280) / 233280);\n bars.push(0.15 + seed * 0.85);\n }\n waveformCache.set(url, bars);\n return bars;\n }\n}\n\n// ── Player state ─────────────────────────────────────────────────────\n\ninterface PlayerState {\n audio: HTMLAudioElement;\n playing: boolean;\n currentTime: number;\n duration: number;\n speed: number;\n waveform: number[];\n}\n\nconst SPEEDS = [1, 1.5, 2];\nconst playerStates = new Map<string, PlayerState>();\n\nfunction getOrCreateState(url: string): PlayerState {\n let state = playerStates.get(url);\n if (state) return state;\n\n const audio = new Audio();\n audio.preload = \"metadata\";\n audio.src = url;\n\n state = {\n audio,\n playing: false,\n currentTime: 0,\n duration: 0,\n speed: 1,\n waveform: [],\n };\n\n playerStates.set(url, state);\n\n // Load waveform asynchronously, then paint bars when ready\n extractWaveform(url).then((w) => {\n state!.waveform = w;\n paintWaveform(url);\n });\n\n return state;\n}\n\n// ── SVG icon builders (safe DOM, no innerHTML) ───────────────────────\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\nfunction createPlaySvg(): SVGSVGElement {\n const svg = document.createElementNS(SVG_NS, \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"currentColor\");\n const poly = document.createElementNS(SVG_NS, \"polygon\");\n poly.setAttribute(\"points\", \"6,3 20,12 6,21\");\n svg.appendChild(poly);\n return svg;\n}\n\nfunction createPauseSvg(): SVGSVGElement {\n const svg = document.createElementNS(SVG_NS, \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"fill\", \"currentColor\");\n const r1 = document.createElementNS(SVG_NS, \"rect\");\n r1.setAttribute(\"x\", \"5\"); r1.setAttribute(\"y\", \"3\");\n r1.setAttribute(\"width\", \"4\"); r1.setAttribute(\"height\", \"18\"); r1.setAttribute(\"rx\", \"1\");\n const r2 = document.createElementNS(SVG_NS, \"rect\");\n r2.setAttribute(\"x\", \"15\"); r2.setAttribute(\"y\", \"3\");\n r2.setAttribute(\"width\", \"4\"); r2.setAttribute(\"height\", \"18\"); r2.setAttribute(\"rx\", \"1\");\n svg.append(r1, r2);\n return svg;\n}\n\n// ── Imperative DOM helpers ───────────────────────────────────────────\n\nfunction findContainer(url: string): HTMLElement | null {\n return document.querySelector(`.vnp[data-url=\"${CSS.escape(url)}\"]`);\n}\n\nfunction paintWaveform(url: string) {\n const container = findContainer(url);\n if (!container) return;\n const state = playerStates.get(url);\n if (!state || state.waveform.length === 0) return;\n\n const waveformEl = container.querySelector(\".vnp__waveform\");\n if (!waveformEl) return;\n\n // Only populate if bars haven't been painted yet\n if (waveformEl.children.length === 0) {\n const frag = document.createDocumentFragment();\n for (const h of state.waveform) {\n const bar = document.createElement(\"span\");\n bar.className = \"vnp__bar\";\n bar.style.height = `${Math.round(h * 100)}%`;\n frag.appendChild(bar);\n }\n waveformEl.appendChild(frag);\n }\n\n updateProgress(container, state);\n}\n\nfunction updateProgress(container: HTMLElement, state: PlayerState) {\n const progress = state.duration > 0 ? state.currentTime / state.duration : 0;\n const bars = container.querySelectorAll(\".vnp__bar\");\n const barCount = bars.length;\n bars.forEach((bar, i) => {\n bar.classList.toggle(\"vnp__bar--active\", i / barCount < progress);\n });\n\n const timeEl = container.querySelector(\".vnp__time\");\n if (timeEl) {\n timeEl.textContent =\n state.playing || state.currentTime > 0\n ? formatTime(state.currentTime)\n : formatTime(state.duration);\n }\n}\n\nfunction updatePlayIcon(container: HTMLElement, playing: boolean) {\n const btn = container.querySelector(\".vnp__play\");\n if (!btn) return;\n // Replace the SVG child safely (no innerHTML)\n const oldSvg = btn.querySelector(\"svg\");\n const newSvg = playing ? createPauseSvg() : createPlaySvg();\n if (oldSvg) {\n btn.replaceChild(newSvg, oldSvg);\n } else {\n btn.appendChild(newSvg);\n }\n}\n\n// ── Formatting ───────────────────────────────────────────────────────\n\nfunction formatTime(seconds: number): string {\n if (!isFinite(seconds) || seconds < 0) return \"0:00\";\n const m = Math.floor(seconds / 60);\n const s = Math.floor(seconds % 60);\n return `${m}:${s.toString().padStart(2, \"0\")}`;\n}\n\n// ── Audio event wiring ───────────────────────────────────────────────\n\nconst wiredUrls = new Set<string>();\n\nfunction wireAudioEvents(url: string) {\n if (wiredUrls.has(url)) return;\n wiredUrls.add(url);\n\n const state = playerStates.get(url);\n if (!state) return;\n const { audio } = state;\n\n audio.addEventListener(\"loadedmetadata\", () => {\n state.duration = audio.duration;\n const container = findContainer(url);\n if (container) updateProgress(container, state);\n });\n\n audio.addEventListener(\"timeupdate\", () => {\n state.currentTime = audio.currentTime;\n const container = findContainer(url);\n if (container) updateProgress(container, state);\n });\n\n audio.addEventListener(\"ended\", () => {\n state.playing = false;\n audio.currentTime = 0;\n state.currentTime = 0;\n const container = findContainer(url);\n if (container) {\n updateProgress(container, state);\n updatePlayIcon(container, false);\n }\n });\n\n audio.addEventListener(\"pause\", () => {\n state.playing = false;\n const container = findContainer(url);\n if (container) updatePlayIcon(container, false);\n });\n\n audio.addEventListener(\"play\", () => {\n state.playing = true;\n const container = findContainer(url);\n if (container) updatePlayIcon(container, true);\n });\n}\n\n// ── Render ───────────────────────────────────────────────────────────\n\nexport function renderVoiceNotePlayer(url: string, name: string) {\n const state = getOrCreateState(url);\n wireAudioEvents(url);\n\n const togglePlay = (e: Event) => {\n e.stopPropagation();\n if (state.playing) {\n state.audio.pause();\n } else {\n void state.audio.play();\n }\n };\n\n const cycleSpeed = (e: Event) => {\n e.stopPropagation();\n const idx = SPEEDS.indexOf(state.speed);\n const next = SPEEDS[(idx + 1) % SPEEDS.length];\n state.speed = next;\n state.audio.playbackRate = next;\n const btn = (e.target as HTMLElement).closest(\".vnp__speed\") as HTMLElement;\n if (btn) btn.textContent = `${next}×`;\n };\n\n const seekFromClick = (e: MouseEvent) => {\n e.stopPropagation();\n const target = (e.target as HTMLElement).closest(\".vnp__waveform\") as HTMLElement;\n if (!target) return;\n const rect = target.getBoundingClientRect();\n const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));\n if (state.duration > 0) {\n state.audio.currentTime = ratio * state.duration;\n state.currentTime = state.audio.currentTime;\n const container = target.closest(\".vnp\") as HTMLElement;\n if (container) updateProgress(container, state);\n }\n };\n\n const elapsed =\n state.playing || state.currentTime > 0\n ? formatTime(state.currentTime)\n : formatTime(state.duration);\n\n // Waveform bars are painted imperatively after async decode.\n // On Lit re-render the container is fresh, so schedule a repaint.\n queueMicrotask(() => paintWaveform(url));\n\n return html`\n <div class=\"vnp\" data-url=${url} @click=${(e: Event) => e.stopPropagation()}>\n <button class=\"vnp__play\" @click=${togglePlay} aria-label=${state.playing ? \"Pause\" : \"Play\"}>\n ${state.playing ? pauseIcon() : playIcon()}\n </button>\n\n <div class=\"vnp__body\">\n <div class=\"vnp__waveform\" @click=${seekFromClick}></div>\n\n <div class=\"vnp__meta\">\n <span class=\"vnp__time\">${elapsed}</span>\n <button class=\"vnp__speed\" @click=${cycleSpeed}>${state.speed}×</button>\n ${name\n ? html`<a class=\"vnp__name\" href=${url} target=\"_blank\" rel=\"noreferrer noopener\">${name}</a>`\n : nothing}\n </div>\n </div>\n </div>\n `;\n}\n\n// ── Lit template SVG icons (for initial/re-render only) ──────────────\n\nfunction playIcon() {\n return html`<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><polygon points=\"6,3 20,12 6,21\" /></svg>`;\n}\n\nfunction pauseIcon() {\n return html`<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><rect x=\"5\" y=\"3\" width=\"4\" height=\"18\" rx=\"1\"/><rect x=\"15\" y=\"3\" width=\"4\" height=\"18\" rx=\"1\"/></svg>`;\n}\n","import { html, nothing } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\n\nimport type { AssistantIdentity } from \"../assistant-identity\";\nimport { toSanitizedMarkdownHtml } from \"../markdown\";\nimport type { MessageGroup } from \"../types/chat-types\";\nimport { renderCopyAsMarkdownButton } from \"./copy-as-markdown\";\nimport { isToolResultMessage, normalizeRoleForGrouping } from \"./message-normalizer\";\nimport {\n extractTextCached,\n extractThinkingCached,\n formatReasoningMarkdown,\n} from \"./message-extract\";\nimport { extractToolCards, renderToolCardSidebar } from \"./tool-cards\";\nimport { renderVoiceNotePlayer } from \"./voice-note-player\";\n\ntype ImageBlock = {\n url: string;\n alt?: string;\n};\n\ntype FileBlock = {\n url: string;\n name: string;\n mimeType: string;\n};\n\nfunction extractImages(message: unknown): ImageBlock[] {\n const m = message as Record<string, unknown>;\n const content = m.content;\n const images: ImageBlock[] = [];\n\n if (Array.isArray(content)) {\n for (const block of content) {\n if (typeof block !== \"object\" || block === null) continue;\n const b = block as Record<string, unknown>;\n\n if (b.type === \"image\") {\n // Anthropic API format: { type: \"image\", source: { type: \"base64\", data, media_type } }\n if ((b.source as Record<string, unknown> | undefined)?.type === \"base64\") {\n const source = b.source as Record<string, unknown>;\n const data = source.data as string;\n const mediaType = (source.media_type as string) || \"image/png\";\n const url = data.startsWith(\"data:\")\n ? data\n : `data:${mediaType};base64,${data}`;\n images.push({ url });\n // Session transcript format: { type: \"image\", data: base64, mimeType: \"...\" }\n } else if (typeof b.data === \"string\" && b.data) {\n const data = b.data as string;\n const mimeType = (b.mimeType as string) || (b.media_type as string) || \"image/png\";\n const url = data.startsWith(\"data:\")\n ? data\n : `data:${mimeType};base64,${data}`;\n images.push({ url });\n } else if (typeof b.url === \"string\") {\n images.push({ url: b.url });\n }\n } else if (b.type === \"image_url\") {\n // OpenAI format\n const imageUrl = b.image_url as Record<string, unknown> | undefined;\n if (typeof imageUrl?.url === \"string\") {\n images.push({ url: imageUrl.url });\n }\n }\n }\n }\n\n return images;\n}\n\nfunction extractFiles(message: unknown): FileBlock[] {\n const m = message as Record<string, unknown>;\n const content = m.content;\n const files: FileBlock[] = [];\n\n if (Array.isArray(content)) {\n for (const block of content) {\n if (typeof block !== \"object\" || block === null) continue;\n const b = block as Record<string, unknown>;\n if (\n b.type === \"file\" &&\n typeof b.url === \"string\" &&\n typeof b.name === \"string\"\n ) {\n files.push({\n url: b.url,\n name: b.name as string,\n mimeType: (b.mimeType as string) ?? \"application/octet-stream\",\n });\n }\n }\n }\n\n return files;\n}\n\nfunction fileIcon(mimeType: string): string {\n if (mimeType === \"application/pdf\") return \"\\u{1F4C4}\";\n if (mimeType.startsWith(\"audio/\")) return \"\\u{1F3B5}\";\n return \"\\u{1F4CE}\";\n}\n\nexport function renderReadingIndicatorGroup(_assistant?: AssistantIdentity) {\n return html`\n <div class=\"chat-group assistant\">\n <div class=\"chat-group-messages\">\n <div class=\"chat-bubble chat-reading-indicator\" aria-hidden=\"true\">\n <span class=\"chat-reading-indicator__dots\">\n <span></span><span></span><span></span>\n </span>\n </div>\n </div>\n </div>\n `;\n}\n\nexport function renderInterimGroup(text: string) {\n return html`\n <div class=\"chat-group assistant\">\n <div class=\"chat-group-messages\">\n <div class=\"chat-interim fade-in\">\n ${unsafeHTML(toSanitizedMarkdownHtml(text))}\n </div>\n </div>\n </div>\n `;\n}\n\nexport function renderStreamingGroup(\n text: string,\n startedAt: number,\n onOpenSidebar?: (content: string) => void,\n _assistant?: AssistantIdentity,\n) {\n return html`\n <div class=\"chat-group assistant\">\n <div class=\"chat-group-messages\">\n ${renderGroupedMessage(\n {\n role: \"assistant\",\n content: [{ type: \"text\", text }],\n timestamp: startedAt,\n },\n { isStreaming: false, showReasoning: false },\n onOpenSidebar,\n )}\n </div>\n </div>\n `;\n}\n\nexport function renderMessageGroup(\n group: MessageGroup,\n opts: {\n onOpenSidebar?: (content: string) => void;\n showReasoning: boolean;\n assistantName?: string;\n assistantAvatar?: string | null;\n },\n) {\n const normalizedRole = normalizeRoleForGrouping(group.role);\n const roleClass =\n normalizedRole === \"user\"\n ? \"user\"\n : normalizedRole === \"assistant\"\n ? \"assistant\"\n : \"other\";\n const timestamp = new Date(group.timestamp).toLocaleString(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"medium\",\n });\n\n // Pre-render messages so we can skip empty groups (e.g. assistant turns\n // that only contain thinking/tool_use blocks with no visible text).\n const rendered = group.messages.map((item, index) =>\n renderGroupedMessage(\n item.message,\n {\n isStreaming:\n group.isStreaming && index === group.messages.length - 1,\n showReasoning: opts.showReasoning,\n },\n opts.onOpenSidebar,\n ),\n );\n if (rendered.every((r) => r === nothing)) return nothing;\n\n return html`\n <div class=\"chat-group ${roleClass}\">\n <div class=\"chat-group-messages\">\n ${rendered}\n <div class=\"chat-group-footer\">\n <span class=\"chat-group-timestamp\">${timestamp}</span>\n </div>\n </div>\n </div>\n `;\n}\n\nfunction renderMessageImages(images: ImageBlock[]) {\n if (images.length === 0) return nothing;\n\n return html`\n <div class=\"chat-message-images\">\n ${images.map(\n (img) => html`\n <img\n src=${img.url}\n alt=${img.alt ?? \"Attached image\"}\n class=\"chat-message-image\"\n @click=${() => window.open(img.url, \"_blank\")}\n />\n `,\n )}\n </div>\n `;\n}\n\nfunction renderMessageFiles(files: FileBlock[]) {\n if (files.length === 0) return nothing;\n\n return html`\n <div class=\"chat-message-files\">\n ${files.map((f) =>\n f.mimeType === \"application/pdf\"\n ? renderPdfPreview(f)\n : f.mimeType.startsWith(\"audio/\")\n ? renderVoiceNotePlayer(f.url, f.name)\n : renderFileCard(f),\n )}\n </div>\n `;\n}\n\nfunction openPdfModal(url: string, name: string) {\n const overlay = document.createElement(\"div\");\n overlay.className = \"chat-pdf-modal-overlay\";\n\n const modal = document.createElement(\"div\");\n modal.className = \"chat-pdf-modal\";\n\n // Header\n const header = document.createElement(\"div\");\n header.className = \"chat-pdf-modal__header\";\n\n const title = document.createElement(\"span\");\n title.className = \"chat-pdf-modal__title\";\n title.textContent = name;\n\n const openLink = document.createElement(\"a\");\n openLink.className = \"chat-pdf-modal__open\";\n openLink.href = url;\n openLink.target = \"_blank\";\n openLink.rel = \"noreferrer noopener\";\n openLink.textContent = \"Open in new tab\";\n\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"chat-pdf-modal__close\";\n closeBtn.setAttribute(\"aria-label\", \"Close\");\n const svg = document.createElementNS(\"http://www.w3.org/2000/svg\", \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n const line1 = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n line1.setAttribute(\"x1\", \"18\"); line1.setAttribute(\"y1\", \"6\");\n line1.setAttribute(\"x2\", \"6\"); line1.setAttribute(\"y2\", \"18\");\n const line2 = document.createElementNS(\"http://www.w3.org/2000/svg\", \"line\");\n line2.setAttribute(\"x1\", \"6\"); line2.setAttribute(\"y1\", \"6\");\n line2.setAttribute(\"x2\", \"18\"); line2.setAttribute(\"y2\", \"18\");\n svg.append(line1, line2);\n closeBtn.appendChild(svg);\n\n header.append(title, openLink, closeBtn);\n\n // PDF iframe\n const frame = document.createElement(\"iframe\");\n frame.className = \"chat-pdf-modal__frame\";\n frame.src = url;\n frame.title = name;\n\n modal.append(header, frame);\n overlay.appendChild(modal);\n\n overlay.addEventListener(\"click\", (e) => {\n if (e.target === overlay) overlay.remove();\n });\n closeBtn.addEventListener(\"click\", () => overlay.remove());\n document.body.appendChild(overlay);\n}\n\nfunction renderPdfPreview(f: FileBlock) {\n return html`\n <div class=\"chat-pdf-preview\" @click=${() => openPdfModal(f.url, f.name)}>\n <iframe\n src=${f.url}\n class=\"chat-pdf-preview__frame\"\n title=${f.name}\n ></iframe>\n <a\n class=\"chat-pdf-preview__link\"\n href=${f.url}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n @click=${(e: Event) => e.stopPropagation()}\n >${f.name}</a>\n </div>\n `;\n}\n\n\nfunction renderFileCard(f: FileBlock) {\n return html`\n <a\n class=\"chat-file-card\"\n href=${f.url}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n >\n <span class=\"chat-file-card__icon\">${fileIcon(f.mimeType)}</span>\n <span class=\"chat-file-card__name\">${f.name}</span>\n </a>\n `;\n}\n\nfunction renderGroupedMessage(\n message: unknown,\n opts: { isStreaming: boolean; showReasoning: boolean },\n onOpenSidebar?: (content: string) => void,\n) {\n const m = message as Record<string, unknown>;\n const role = typeof m.role === \"string\" ? m.role : \"unknown\";\n const isToolResult =\n isToolResultMessage(message) ||\n role.toLowerCase() === \"toolresult\" ||\n role.toLowerCase() === \"tool_result\" ||\n typeof m.toolCallId === \"string\" ||\n typeof m.tool_call_id === \"string\";\n\n const toolCards = extractToolCards(message);\n const hasToolCards = toolCards.length > 0;\n const images = extractImages(message);\n const hasImages = images.length > 0;\n const files = extractFiles(message);\n const hasFiles = files.length > 0;\n\n const extractedText = extractTextCached(message);\n const extractedThinking =\n opts.showReasoning && role === \"assistant\"\n ? extractThinkingCached(message)\n : null;\n const markdownBase = extractedText?.trim() ? extractedText : null;\n const reasoningMarkdown = extractedThinking\n ? formatReasoningMarkdown(extractedThinking)\n : null;\n const markdown = markdownBase;\n const canCopyMarkdown = (role === \"assistant\" || role === \"user\") && Boolean(markdown?.trim());\n\n const bubbleClasses = [\n \"chat-bubble\",\n canCopyMarkdown ? \"has-copy\" : \"\",\n opts.isStreaming ? \"streaming\" : \"\",\n \"fade-in\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n // Hide tool-only messages (tool results, tool calls with no text)\n if (!markdown && (hasToolCards || isToolResult)) return nothing;\n\n if (!markdown && !hasImages && !hasFiles) return nothing;\n\n return html`\n <div class=\"${bubbleClasses}\">\n ${canCopyMarkdown ? renderCopyAsMarkdownButton(markdown!) : nothing}\n ${renderMessageImages(images)}\n ${renderMessageFiles(files)}\n ${reasoningMarkdown\n ? html`<div class=\"chat-thinking\">${unsafeHTML(\n toSanitizedMarkdownHtml(reasoningMarkdown),\n )}</div>`\n : nothing}\n ${markdown\n ? html`<div class=\"chat-text\">${unsafeHTML(toSanitizedMarkdownHtml(markdown))}</div>`\n : nothing}\n </div>\n `;\n}\n","import { html, nothing, type TemplateResult } from \"lit\";\nimport { icons } from \"../icons\";\nimport { generateUUID } from \"../uuid\";\nimport type { ChatAttachment } from \"../ui-types\";\n\n// ---------------------------------------------------------------------------\n// Voice recorder — WhatsApp-style dual-mode recording\n// ---------------------------------------------------------------------------\n// Tap mode: tap mic → recording starts → trash/send buttons → tap to stop+send or trash\n// Hold mode: long-press mic → recording starts → release to send, slide left to cancel\n// ---------------------------------------------------------------------------\n\nexport type VoiceRecorderCallbacks = {\n onSend: (attachment: ChatAttachment) => void;\n onRequestRender: () => void;\n};\n\ntype RecorderState = {\n active: boolean;\n mode: \"tap\" | \"hold\";\n startTime: number;\n elapsed: number;\n mediaRecorder: MediaRecorder | null;\n audioChunks: Blob[];\n stream: MediaStream | null;\n timerId: ReturnType<typeof setInterval> | null;\n // Hold-mode gesture tracking\n startX: number;\n cancelled: boolean;\n};\n\nconst state: RecorderState = {\n active: false,\n mode: \"tap\",\n startTime: 0,\n elapsed: 0,\n mediaRecorder: null,\n audioChunks: [],\n stream: null,\n timerId: null,\n startX: 0,\n cancelled: false,\n};\n\nlet callbacks: VoiceRecorderCallbacks | null = null;\n\n// Hold-mode detection: if mic button is held for >300ms, switch to hold mode\nlet holdTimer: ReturnType<typeof setTimeout> | null = null;\nlet pointerDown = false;\n\nfunction formatDuration(seconds: number): string {\n const m = Math.floor(seconds / 60);\n const s = seconds % 60;\n return `${m}:${s.toString().padStart(2, \"0\")}`;\n}\n\nfunction cleanup() {\n if (state.timerId) {\n clearInterval(state.timerId);\n state.timerId = null;\n }\n if (state.stream) {\n for (const track of state.stream.getTracks()) track.stop();\n state.stream = null;\n }\n if (holdTimer) {\n clearTimeout(holdTimer);\n holdTimer = null;\n }\n removeGlobalPointerUp();\n state.mediaRecorder = null;\n state.audioChunks = [];\n state.active = false;\n state.cancelled = false;\n pointerDown = false;\n}\n\nasync function startRecording(mode: \"tap\" | \"hold\"): Promise<boolean> {\n try {\n if (!navigator.mediaDevices?.getUserMedia) {\n console.warn(\"[voice] getUserMedia unavailable (requires secure context)\");\n cleanup();\n return false;\n }\n\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n state.stream = stream;\n\n // Prefer opus/webm for quality+size, fall back to whatever the browser supports\n const mimeType = MediaRecorder.isTypeSupported(\"audio/webm;codecs=opus\")\n ? \"audio/webm;codecs=opus\"\n : MediaRecorder.isTypeSupported(\"audio/mp4\")\n ? \"audio/mp4\"\n : \"\";\n\n const recorder = mimeType\n ? new MediaRecorder(stream, { mimeType })\n : new MediaRecorder(stream);\n\n state.mediaRecorder = recorder;\n state.audioChunks = [];\n state.mode = mode;\n state.startTime = Date.now();\n state.elapsed = 0;\n state.active = true;\n state.cancelled = false;\n\n recorder.ondataavailable = (e) => {\n if (e.data.size > 0) state.audioChunks.push(e.data);\n };\n\n recorder.onstop = () => {\n if (state.cancelled) {\n cleanup();\n callbacks?.onRequestRender();\n return;\n }\n\n const blob = new Blob(state.audioChunks, { type: recorder.mimeType });\n if (blob.size === 0) {\n cleanup();\n callbacks?.onRequestRender();\n return;\n }\n\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const ext = recorder.mimeType.includes(\"mp4\") ? \"m4a\" : \"webm\";\n const attachment: ChatAttachment = {\n id: generateUUID(),\n dataUrl,\n mimeType: recorder.mimeType || \"audio/webm\",\n fileName: `voice-note-${Date.now()}.${ext}`,\n };\n cleanup();\n callbacks?.onSend(attachment);\n callbacks?.onRequestRender();\n };\n reader.onerror = () => {\n cleanup();\n callbacks?.onRequestRender();\n };\n reader.readAsDataURL(blob);\n };\n\n recorder.start(250); // Collect data every 250ms for responsiveness\n\n state.timerId = setInterval(() => {\n state.elapsed = Math.floor((Date.now() - state.startTime) / 1000);\n callbacks?.onRequestRender();\n }, 1000);\n\n callbacks?.onRequestRender();\n return true;\n } catch (err) {\n console.warn(\"[voice] startRecording failed:\", err);\n cleanup();\n return false;\n }\n}\n\nfunction stopAndSend() {\n if (!state.active || !state.mediaRecorder) return;\n state.cancelled = false;\n if (state.mediaRecorder.state === \"recording\") {\n state.mediaRecorder.stop();\n }\n}\n\nfunction cancelRecording() {\n if (!state.active || !state.mediaRecorder) return;\n state.cancelled = true;\n if (state.mediaRecorder.state === \"recording\") {\n state.mediaRecorder.stop();\n } else {\n cleanup();\n callbacks?.onRequestRender();\n }\n}\n\n// ── Event handlers for the mic button ──────────────────────────────\n// Hold-mode recording replaces the mic button with a recording UI, so\n// @pointerup on the mic button never fires. A global document listener\n// captures the release regardless of which element the pointer is over.\n\nfunction addGlobalPointerUp() {\n document.addEventListener(\"pointerup\", onGlobalPointerUp);\n}\n\nfunction removeGlobalPointerUp() {\n document.removeEventListener(\"pointerup\", onGlobalPointerUp);\n}\n\nfunction onGlobalPointerUp(e: PointerEvent) {\n if (!pointerDown && !state.active) {\n removeGlobalPointerUp();\n return;\n }\n pointerDown = false;\n removeGlobalPointerUp();\n\n // If hold timer hasn't fired yet, this was a quick tap → start tap-mode\n if (holdTimer) {\n clearTimeout(holdTimer);\n holdTimer = null;\n if (!state.active) {\n void startRecording(\"tap\");\n return;\n }\n }\n\n // Hold mode release → send (unless cancelled by sliding)\n if (state.active && state.mode === \"hold\") {\n if (state.cancelled) {\n cancelRecording();\n } else {\n stopAndSend();\n }\n }\n\n e.preventDefault();\n}\n\nfunction onMicPointerDown(e: PointerEvent) {\n if (state.active) return; // Already recording (tap mode — handled by buttons)\n pointerDown = true;\n state.startX = e.clientX;\n\n // Register global listener so release is captured even after the mic\n // button is replaced by recording UI.\n addGlobalPointerUp();\n\n // Start a hold-mode timer. If held >300ms, start hold-mode recording.\n holdTimer = setTimeout(async () => {\n if (!pointerDown) return;\n const ok = await startRecording(\"hold\");\n if (!ok) {\n pointerDown = false;\n removeGlobalPointerUp();\n }\n }, 300);\n}\n\nfunction onRecordingPointerMove(e: PointerEvent) {\n if (!state.active || state.mode !== \"hold\" || !pointerDown) return;\n const dx = state.startX - e.clientX;\n // Slide left > 80px to cancel\n if (dx > 80) {\n state.cancelled = true;\n callbacks?.onRequestRender();\n } else if (state.cancelled && dx <= 60) {\n state.cancelled = false;\n callbacks?.onRequestRender();\n }\n}\n\n// ── Public API ─────────────────────────────────────────────────────\n\nexport function isRecording(): boolean {\n return state.active;\n}\n\nexport function setCallbacks(cbs: VoiceRecorderCallbacks) {\n callbacks = cbs;\n}\n\n/** Render the mic button (shown when compose input is empty). */\nexport function renderMicButton(connected: boolean): TemplateResult {\n return html`\n <button\n class=\"btn btn--icon chat-compose__mic\"\n ?disabled=${!connected}\n @pointerdown=${onMicPointerDown}\n aria-label=\"Record voice note\"\n title=\"Tap to record, hold to send on release\"\n >\n ${icons.mic}\n </button>\n `;\n}\n\n/** Render the recording UI (replaces compose row when recording). */\nexport function renderRecordingUI(): TemplateResult | typeof nothing {\n if (!state.active) return nothing;\n\n if (state.mode === \"tap\") {\n return html`\n <div class=\"chat-voice-recording\" @pointermove=${onRecordingPointerMove}>\n <button\n class=\"btn btn--icon chat-voice-recording__trash\"\n @click=${cancelRecording}\n aria-label=\"Cancel recording\"\n title=\"Discard\"\n >\n ${icons.trash}\n </button>\n <div class=\"chat-voice-recording__indicator\">\n <span class=\"chat-voice-recording__dot\"></span>\n <span class=\"chat-voice-recording__timer\">${formatDuration(state.elapsed)}</span>\n </div>\n <button\n class=\"btn btn--icon chat-voice-recording__send primary\"\n @click=${stopAndSend}\n aria-label=\"Send voice note\"\n title=\"Send\"\n >\n ${icons.send}\n </button>\n </div>\n `;\n }\n\n // Hold mode\n return html`\n <div class=\"chat-voice-recording hold\" @pointermove=${onRecordingPointerMove}>\n <div class=\"chat-voice-recording__indicator\">\n <span class=\"chat-voice-recording__dot\"></span>\n <span class=\"chat-voice-recording__timer\">${formatDuration(state.elapsed)}</span>\n <span class=\"chat-voice-recording__slide ${state.cancelled ? \"cancelled\" : \"\"}\">\n ${state.cancelled ? \"Release to cancel\" : \"\\u2190 Slide to cancel\"}\n </span>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\n\nimport { icons } from \"../icons\";\nimport { toSanitizedMarkdownHtml } from \"../markdown\";\n\nexport type MarkdownSidebarProps = {\n content: string | null;\n error: string | null;\n onClose: () => void;\n onViewRawText: () => void;\n};\n\nexport function renderMarkdownSidebar(props: MarkdownSidebarProps) {\n return html`\n <div class=\"sidebar-panel\">\n <div class=\"sidebar-header\">\n <div class=\"sidebar-title\">Tool Output</div>\n <button @click=${props.onClose} class=\"btn\" title=\"Close sidebar\">\n ${icons.x}\n </button>\n </div>\n <div class=\"sidebar-content\">\n ${props.error\n ? html`\n <div class=\"callout danger\">${props.error}</div>\n <button @click=${props.onViewRawText} class=\"btn\" style=\"margin-top: 12px;\">\n View Raw Text\n </button>\n `\n : props.content\n ? html`<div class=\"sidebar-markdown\">${unsafeHTML(toSanitizedMarkdownHtml(props.content))}</div>`\n : html`<div class=\"muted\">No content available</div>`}\n </div>\n </div>\n `;\n}\n","import { LitElement, html, css } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\n\n/**\n * A draggable divider for resizable split views.\n * Dispatches 'resize' events with { splitRatio: number } detail.\n */\n@customElement(\"resizable-divider\")\nexport class ResizableDivider extends LitElement {\n @property({ type: Number }) splitRatio = 0.6;\n @property({ type: Number }) minRatio = 0.4;\n @property({ type: Number }) maxRatio = 0.7;\n\n private isDragging = false;\n private startX = 0;\n private startRatio = 0;\n\n static styles = css`\n :host {\n width: 4px;\n cursor: col-resize;\n background: var(--border, #333);\n transition: background 150ms ease-out;\n flex-shrink: 0;\n position: relative;\n }\n\n :host::before {\n content: \"\";\n position: absolute;\n top: 0;\n left: -4px;\n right: -4px;\n bottom: 0;\n }\n\n :host(:hover) {\n background: var(--accent, #007bff);\n }\n\n :host(.dragging) {\n background: var(--accent, #007bff);\n }\n `;\n\n render() {\n return html``;\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener(\"mousedown\", this.handleMouseDown);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"mousedown\", this.handleMouseDown);\n document.removeEventListener(\"mousemove\", this.handleMouseMove);\n document.removeEventListener(\"mouseup\", this.handleMouseUp);\n }\n\n private handleMouseDown = (e: MouseEvent) => {\n this.isDragging = true;\n this.startX = e.clientX;\n this.startRatio = this.splitRatio;\n this.classList.add(\"dragging\");\n\n document.addEventListener(\"mousemove\", this.handleMouseMove);\n document.addEventListener(\"mouseup\", this.handleMouseUp);\n\n e.preventDefault();\n };\n\n private handleMouseMove = (e: MouseEvent) => {\n if (!this.isDragging) return;\n\n const container = this.parentElement;\n if (!container) return;\n\n const containerWidth = container.getBoundingClientRect().width;\n const deltaX = e.clientX - this.startX;\n const deltaRatio = deltaX / containerWidth;\n\n let newRatio = this.startRatio + deltaRatio;\n newRatio = Math.max(this.minRatio, Math.min(this.maxRatio, newRatio));\n\n this.dispatchEvent(\n new CustomEvent(\"resize\", {\n detail: { splitRatio: newRatio },\n bubbles: true,\n composed: true,\n })\n );\n };\n\n private handleMouseUp = () => {\n this.isDragging = false;\n this.classList.remove(\"dragging\");\n\n document.removeEventListener(\"mousemove\", this.handleMouseMove);\n document.removeEventListener(\"mouseup\", this.handleMouseUp);\n };\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"resizable-divider\": ResizableDivider;\n }\n}\n","function assertNonEmptyString (str) {\n if (typeof str !== 'string' || !str) {\n throw new Error('expected a non-empty string, got: ' + str)\n }\n}\n\nfunction assertNumber (number) {\n if (typeof number !== 'number') {\n throw new Error('expected a number, got: ' + number)\n }\n}\n\nconst DB_VERSION_CURRENT = 1;\nconst DB_VERSION_INITIAL = 1;\nconst STORE_EMOJI = 'emoji';\nconst STORE_KEYVALUE = 'keyvalue';\nconst STORE_FAVORITES = 'favorites';\nconst FIELD_TOKENS = 'tokens';\nconst INDEX_TOKENS = 'tokens';\nconst FIELD_UNICODE = 'unicode';\nconst INDEX_COUNT = 'count';\nconst FIELD_GROUP = 'group';\nconst FIELD_ORDER = 'order';\nconst INDEX_GROUP_AND_ORDER = 'group-order';\nconst KEY_ETAG = 'eTag';\nconst KEY_URL = 'url';\nconst KEY_PREFERRED_SKINTONE = 'skinTone';\nconst MODE_READONLY = 'readonly';\nconst MODE_READWRITE = 'readwrite';\nconst INDEX_SKIN_UNICODE = 'skinUnicodes';\nconst FIELD_SKIN_UNICODE = 'skinUnicodes';\n\nconst DEFAULT_DATA_SOURCE = 'https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/en/emojibase/data.json';\nconst DEFAULT_LOCALE = 'en';\n\n// like lodash's uniqBy but much smaller\nfunction uniqBy (arr, func) {\n const set = new Set();\n const res = [];\n for (const item of arr) {\n const key = func(item);\n if (!set.has(key)) {\n set.add(key);\n res.push(item);\n }\n }\n return res\n}\n\nfunction uniqEmoji (emojis) {\n return uniqBy(emojis, _ => _.unicode)\n}\n\nfunction initialMigration (db) {\n function createObjectStore (name, keyPath, indexes) {\n const store = keyPath\n ? db.createObjectStore(name, { keyPath })\n : db.createObjectStore(name);\n if (indexes) {\n for (const [indexName, [keyPath, multiEntry]] of Object.entries(indexes)) {\n store.createIndex(indexName, keyPath, { multiEntry });\n }\n }\n return store\n }\n\n createObjectStore(STORE_KEYVALUE);\n createObjectStore(STORE_EMOJI, /* keyPath */ FIELD_UNICODE, {\n [INDEX_TOKENS]: [FIELD_TOKENS, /* multiEntry */ true],\n [INDEX_GROUP_AND_ORDER]: [[FIELD_GROUP, FIELD_ORDER]],\n [INDEX_SKIN_UNICODE]: [FIELD_SKIN_UNICODE, /* multiEntry */ true]\n });\n createObjectStore(STORE_FAVORITES, undefined, {\n [INDEX_COUNT]: ['']\n });\n}\n\nconst openIndexedDBRequests = {};\nconst databaseCache = {};\nconst onCloseListeners = {};\n\nfunction handleOpenOrDeleteReq (resolve, reject, req) {\n // These things are almost impossible to test with fakeIndexedDB sadly\n /* istanbul ignore next */\n req.onerror = () => reject(req.error);\n /* istanbul ignore next */\n req.onblocked = () => reject(new Error('IDB blocked'));\n req.onsuccess = () => resolve(req.result);\n}\n\nasync function createDatabase (dbName) {\n const db = await new Promise((resolve, reject) => {\n const req = indexedDB.open(dbName, DB_VERSION_CURRENT);\n openIndexedDBRequests[dbName] = req;\n req.onupgradeneeded = e => {\n // Technically there is only one version, so we don't need this `if` check\n // But if an old version of the JS is in another browser tab\n // and it gets upgraded in the future and we have a new DB version, well...\n // better safe than sorry.\n /* istanbul ignore else */\n if (e.oldVersion < DB_VERSION_INITIAL) {\n initialMigration(req.result);\n }\n };\n handleOpenOrDeleteReq(resolve, reject, req);\n });\n // Handle abnormal closes, e.g. \"delete database\" in chrome dev tools.\n // No need for removeEventListener, because once the DB can no longer\n // fire \"close\" events, it will auto-GC.\n db.onclose = () => closeDatabase(dbName);\n return db\n}\n\nfunction openDatabase (dbName) {\n if (!databaseCache[dbName]) {\n databaseCache[dbName] = createDatabase(dbName);\n }\n return databaseCache[dbName]\n}\n\nfunction dbPromise (db, storeName, readOnlyOrReadWrite, cb) {\n return new Promise((resolve, reject) => {\n // Use relaxed durability because neither the emoji data nor the favorites/preferred skin tone\n // are really irreplaceable data. IndexedDB is just a cache in this case.\n const txn = db.transaction(storeName, readOnlyOrReadWrite, { durability: 'relaxed' });\n const store = typeof storeName === 'string'\n ? txn.objectStore(storeName)\n : storeName.map(name => txn.objectStore(name));\n let res;\n cb(store, txn, (result) => {\n res = result;\n });\n\n txn.oncomplete = () => resolve(res);\n /* istanbul ignore next */\n txn.onerror = () => reject(txn.error);\n })\n}\n\nfunction closeDatabase (dbName) {\n // close any open requests\n const req = openIndexedDBRequests[dbName];\n const db = req && req.result;\n if (db) {\n db.close();\n const listeners = onCloseListeners[dbName];\n /* istanbul ignore else */\n if (listeners) {\n for (const listener of listeners) {\n listener();\n }\n }\n }\n delete openIndexedDBRequests[dbName];\n delete databaseCache[dbName];\n delete onCloseListeners[dbName];\n}\n\nfunction deleteDatabase (dbName) {\n return new Promise((resolve, reject) => {\n // close any open requests\n closeDatabase(dbName);\n const req = indexedDB.deleteDatabase(dbName);\n handleOpenOrDeleteReq(resolve, reject, req);\n })\n}\n\n// The \"close\" event occurs during an abnormal shutdown, e.g. a user clearing their browser data.\n// However, it doesn't occur with the normal \"close\" event, so we handle that separately.\n// https://www.w3.org/TR/IndexedDB/#close-a-database-connection\nfunction addOnCloseListener (dbName, listener) {\n let listeners = onCloseListeners[dbName];\n if (!listeners) {\n listeners = onCloseListeners[dbName] = [];\n }\n listeners.push(listener);\n}\n\n// list of emoticons that don't match a simple \\W+ regex\n// extracted using:\n// require('emoji-picker-element-data/en/emojibase/data.json').map(_ => _.emoticon).filter(Boolean).filter(_ => !/^\\W+$/.test(_))\nconst irregularEmoticons = new Set([\n ':D', 'XD', \":'D\", 'O:)',\n ':X', ':P', ';P', 'XP',\n ':L', ':Z', ':j', '8D',\n 'XO', '8)', ':B', ':O',\n ':S', \":'o\", 'Dx', 'X(',\n 'D:', ':C', '>0)', ':3',\n '</3', '<3', '\\\\M/', ':E',\n '8#'\n]);\n\nfunction extractTokens (str) {\n return str\n .split(/[\\s_]+/)\n .map(word => {\n if (!word.match(/\\w/) || irregularEmoticons.has(word)) {\n // for pure emoticons like :) or :-), just leave them as-is\n return word.toLowerCase()\n }\n\n return word\n .replace(/[)(:,]/g, '')\n .replace(/’/g, \"'\")\n .toLowerCase()\n }).filter(Boolean)\n}\n\nconst MIN_SEARCH_TEXT_LENGTH = 2;\n\n// This is an extra step in addition to extractTokens(). The difference here is that we expect\n// the input to have already been run through extractTokens(). This is useful for cases like\n// emoticons, where we don't want to do any tokenization (because it makes no sense to split up\n// \">:)\" by the colon) but we do want to lowercase it to have consistent search results, so that\n// the user can type ':P' or ':p' and still get the same result.\nfunction normalizeTokens (str) {\n return str\n .filter(Boolean)\n .map(_ => _.toLowerCase())\n .filter(_ => _.length >= MIN_SEARCH_TEXT_LENGTH)\n}\n\n// Transform emoji data for storage in IDB\nfunction transformEmojiData (emojiData) {\n const res = emojiData.map(({ annotation, emoticon, group, order, shortcodes, skins, tags, emoji, version }) => {\n const tokens = [...new Set(\n normalizeTokens([\n ...(shortcodes || []).map(extractTokens).flat(),\n ...(tags || []).map(extractTokens).flat(),\n ...extractTokens(annotation),\n emoticon\n ])\n )].sort();\n const res = {\n annotation,\n group,\n order,\n tags,\n tokens,\n unicode: emoji,\n version\n };\n if (emoticon) {\n res.emoticon = emoticon;\n }\n if (shortcodes) {\n res.shortcodes = shortcodes;\n }\n if (skins) {\n res.skinTones = [];\n res.skinUnicodes = [];\n res.skinVersions = [];\n for (const { tone, emoji, version } of skins) {\n res.skinTones.push(tone);\n res.skinUnicodes.push(emoji);\n res.skinVersions.push(version);\n }\n }\n return res\n });\n return res\n}\n\n// helper functions that help compress the code better\n\nfunction callStore (store, method, key, cb) {\n store[method](key).onsuccess = e => (cb && cb(e.target.result));\n}\n\nfunction getIDB (store, key, cb) {\n callStore(store, 'get', key, cb);\n}\n\nfunction getAllIDB (store, key, cb) {\n callStore(store, 'getAll', key, cb);\n}\n\nfunction commit (txn) {\n /* istanbul ignore else */\n if (txn.commit) {\n txn.commit();\n }\n}\n\n// like lodash's minBy\nfunction minBy (array, func) {\n let minItem = array[0];\n for (let i = 1; i < array.length; i++) {\n const item = array[i];\n if (func(minItem) > func(item)) {\n minItem = item;\n }\n }\n return minItem\n}\n\n// return an array of results representing all items that are found in each one of the arrays\n//\n\nfunction findCommonMembers (arrays, uniqByFunc) {\n const shortestArray = minBy(arrays, _ => _.length);\n const results = [];\n for (const item of shortestArray) {\n // if this item is included in every array in the intermediate results, add it to the final results\n if (!arrays.some(array => array.findIndex(_ => uniqByFunc(_) === uniqByFunc(item)) === -1)) {\n results.push(item);\n }\n }\n return results\n}\n\nasync function isEmpty (db) {\n return !(await get(db, STORE_KEYVALUE, KEY_URL))\n}\n\nasync function hasData (db, url, eTag) {\n const [oldETag, oldUrl] = await Promise.all([KEY_ETAG, KEY_URL]\n .map(key => get(db, STORE_KEYVALUE, key)));\n return (oldETag === eTag && oldUrl === url)\n}\n\nasync function doFullDatabaseScanForSingleResult (db, predicate) {\n // This batching algorithm is just a perf improvement over a basic\n // cursor. The BATCH_SIZE is an estimate of what would give the best\n // perf for doing a full DB scan (worst case).\n //\n // Mini-benchmark for determining the best batch size:\n //\n // PERF=1 pnpm build:rollup && pnpm test:adhoc\n //\n // (async () => {\n // performance.mark('start')\n // await $('emoji-picker').database.getEmojiByShortcode('doesnotexist')\n // performance.measure('total', 'start')\n // console.log(performance.getEntriesByName('total').slice(-1)[0].duration)\n // })()\n const BATCH_SIZE = 50; // Typically around 150ms for 6x slowdown in Chrome for above benchmark\n return dbPromise(db, STORE_EMOJI, MODE_READONLY, (emojiStore, txn, cb) => {\n let lastKey;\n\n const processNextBatch = () => {\n emojiStore.getAll(lastKey && IDBKeyRange.lowerBound(lastKey, true), BATCH_SIZE).onsuccess = e => {\n const results = e.target.result;\n for (const result of results) {\n lastKey = result.unicode;\n if (predicate(result)) {\n return cb(result)\n }\n }\n if (results.length < BATCH_SIZE) {\n return cb()\n }\n processNextBatch();\n };\n };\n processNextBatch();\n })\n}\n\nasync function loadData (db, emojiData, url, eTag) {\n try {\n const transformedData = transformEmojiData(emojiData);\n await dbPromise(db, [STORE_EMOJI, STORE_KEYVALUE], MODE_READWRITE, ([emojiStore, metaStore], txn) => {\n let oldETag;\n let oldUrl;\n let todo = 0;\n\n function checkFetched () {\n if (++todo === 2) { // 2 requests made\n onFetched();\n }\n }\n\n function onFetched () {\n if (oldETag === eTag && oldUrl === url) {\n // check again within the transaction to guard against concurrency, e.g. multiple browser tabs\n return\n }\n // delete old data\n emojiStore.clear();\n // insert new data\n for (const data of transformedData) {\n emojiStore.put(data);\n }\n metaStore.put(eTag, KEY_ETAG);\n metaStore.put(url, KEY_URL);\n commit(txn);\n }\n\n getIDB(metaStore, KEY_ETAG, result => {\n oldETag = result;\n checkFetched();\n });\n\n getIDB(metaStore, KEY_URL, result => {\n oldUrl = result;\n checkFetched();\n });\n });\n } finally {\n }\n}\n\nasync function getEmojiByGroup (db, group) {\n return dbPromise(db, STORE_EMOJI, MODE_READONLY, (emojiStore, txn, cb) => {\n const range = IDBKeyRange.bound([group, 0], [group + 1, 0], false, true);\n getAllIDB(emojiStore.index(INDEX_GROUP_AND_ORDER), range, cb);\n })\n}\n\nasync function getEmojiBySearchQuery (db, query) {\n const tokens = normalizeTokens(extractTokens(query));\n\n if (!tokens.length) {\n return []\n }\n\n return dbPromise(db, STORE_EMOJI, MODE_READONLY, (emojiStore, txn, cb) => {\n // get all results that contain all tokens (i.e. an AND query)\n const intermediateResults = [];\n\n const checkDone = () => {\n if (intermediateResults.length === tokens.length) {\n onDone();\n }\n };\n\n const onDone = () => {\n const results = findCommonMembers(intermediateResults, _ => _.unicode);\n cb(results.sort((a, b) => a.order < b.order ? -1 : 1));\n };\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n const range = i === tokens.length - 1\n ? IDBKeyRange.bound(token, token + '\\uffff', false, true) // treat last token as a prefix search\n : IDBKeyRange.only(token); // treat all other tokens as an exact match\n getAllIDB(emojiStore.index(INDEX_TOKENS), range, result => {\n intermediateResults.push(result);\n checkDone();\n });\n }\n })\n}\n\n// This could have been implemented as an IDB index on shortcodes, but it seemed wasteful to do that\n// when we can already query by tokens and this will give us what we're looking for 99.9% of the time\nasync function getEmojiByShortcode (db, shortcode) {\n const emojis = await getEmojiBySearchQuery(db, shortcode);\n\n // In very rare cases (e.g. the shortcode \"v\" as in \"v for victory\"), we cannot search because\n // there are no usable tokens (too short in this case). In that case, we have to do an inefficient\n // full-database scan, which I believe is an acceptable tradeoff for not having to have an extra\n // index on shortcodes.\n\n if (!emojis.length) {\n const predicate = _ => ((_.shortcodes || []).includes(shortcode.toLowerCase()));\n return (await doFullDatabaseScanForSingleResult(db, predicate)) || null\n }\n\n return emojis.filter(_ => {\n const lowerShortcodes = (_.shortcodes || []).map(_ => _.toLowerCase());\n return lowerShortcodes.includes(shortcode.toLowerCase())\n })[0] || null\n}\n\nasync function getEmojiByUnicode (db, unicode) {\n return dbPromise(db, STORE_EMOJI, MODE_READONLY, (emojiStore, txn, cb) => (\n getIDB(emojiStore, unicode, result => {\n if (result) {\n return cb(result)\n }\n getIDB(emojiStore.index(INDEX_SKIN_UNICODE), unicode, result => cb(result || null));\n })\n ))\n}\n\nfunction get (db, storeName, key) {\n return dbPromise(db, storeName, MODE_READONLY, (store, txn, cb) => (\n getIDB(store, key, cb)\n ))\n}\n\nfunction set (db, storeName, key, value) {\n return dbPromise(db, storeName, MODE_READWRITE, (store, txn) => {\n store.put(value, key);\n commit(txn);\n })\n}\n\nfunction incrementFavoriteEmojiCount (db, unicode) {\n return dbPromise(db, STORE_FAVORITES, MODE_READWRITE, (store, txn) => (\n getIDB(store, unicode, result => {\n store.put((result || 0) + 1, unicode);\n commit(txn);\n })\n ))\n}\n\nfunction getTopFavoriteEmoji (db, customEmojiIndex, limit) {\n if (limit === 0) {\n return []\n }\n return dbPromise(db, [STORE_FAVORITES, STORE_EMOJI], MODE_READONLY, ([favoritesStore, emojiStore], txn, cb) => {\n const results = [];\n favoritesStore.index(INDEX_COUNT).openCursor(undefined, 'prev').onsuccess = e => {\n const cursor = e.target.result;\n if (!cursor) { // no more results\n return cb(results)\n }\n\n function addResult (result) {\n results.push(result);\n if (results.length === limit) {\n return cb(results) // done, reached the limit\n }\n cursor.continue();\n }\n\n const unicodeOrName = cursor.primaryKey;\n const custom = customEmojiIndex.byName(unicodeOrName);\n if (custom) {\n return addResult(custom)\n }\n // This could be done in parallel (i.e. make the cursor and the get()s parallelized),\n // but my testing suggests it's not actually faster.\n getIDB(emojiStore, unicodeOrName, emoji => {\n if (emoji) {\n return addResult(emoji)\n }\n // emoji not found somehow, ignore (may happen if custom emoji change)\n cursor.continue();\n });\n };\n })\n}\n\n// trie data structure for prefix searches\n// loosely based on https://github.com/nolanlawson/substring-trie\n\nconst CODA_MARKER = ''; // marks the end of the string\n\nfunction trie (arr, itemToTokens) {\n const map = new Map();\n for (const item of arr) {\n const tokens = itemToTokens(item);\n for (const token of tokens) {\n let currentMap = map;\n for (let i = 0; i < token.length; i++) {\n const char = token.charAt(i);\n let nextMap = currentMap.get(char);\n if (!nextMap) {\n nextMap = new Map();\n currentMap.set(char, nextMap);\n }\n currentMap = nextMap;\n }\n let valuesAtCoda = currentMap.get(CODA_MARKER);\n if (!valuesAtCoda) {\n valuesAtCoda = [];\n currentMap.set(CODA_MARKER, valuesAtCoda);\n }\n valuesAtCoda.push(item);\n }\n }\n\n const search = (query, exact) => {\n let currentMap = map;\n for (let i = 0; i < query.length; i++) {\n const char = query.charAt(i);\n const nextMap = currentMap.get(char);\n if (nextMap) {\n currentMap = nextMap;\n } else {\n return []\n }\n }\n\n if (exact) {\n const results = currentMap.get(CODA_MARKER);\n return results || []\n }\n\n const results = [];\n // traverse\n const queue = [currentMap];\n while (queue.length) {\n const currentMap = queue.shift();\n const entriesSortedByKey = [...currentMap.entries()].sort((a, b) => a[0] < b[0] ? -1 : 1);\n for (const [key, value] of entriesSortedByKey) {\n if (key === CODA_MARKER) { // CODA_MARKER always comes first; it's the empty string\n results.push(...value);\n } else {\n queue.push(value);\n }\n }\n }\n return results\n };\n\n return search\n}\n\nconst requiredKeys$1 = [\n 'name',\n 'url'\n];\n\nfunction assertCustomEmojis (customEmojis) {\n const isArray = customEmojis && Array.isArray(customEmojis);\n const firstItemIsFaulty = isArray &&\n customEmojis.length &&\n (!customEmojis[0] || requiredKeys$1.some(key => !(key in customEmojis[0])));\n if (!isArray || firstItemIsFaulty) {\n throw new Error('Custom emojis are in the wrong format')\n }\n}\n\nfunction customEmojiIndex (customEmojis) {\n assertCustomEmojis(customEmojis);\n\n const sortByName = (a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;\n\n //\n // all()\n //\n const all = customEmojis.sort(sortByName);\n\n //\n // search()\n //\n const emojiToTokens = emoji => {\n const set = new Set();\n if (emoji.shortcodes) {\n for (const shortcode of emoji.shortcodes) {\n for (const token of extractTokens(shortcode)) {\n set.add(token);\n }\n }\n }\n return set\n };\n const searchTrie = trie(customEmojis, emojiToTokens);\n const searchByExactMatch = _ => searchTrie(_, true);\n const searchByPrefix = _ => searchTrie(_, false);\n\n // Search by query for custom emoji. Similar to how we do this in IDB, the last token\n // is treated as a prefix search, but every other one is treated as an exact match.\n // Then we AND the results together\n const search = query => {\n const tokens = extractTokens(query);\n const intermediateResults = tokens.map((token, i) => (\n (i < tokens.length - 1 ? searchByExactMatch : searchByPrefix)(token)\n ));\n return findCommonMembers(intermediateResults, _ => _.name).sort(sortByName)\n };\n\n //\n // byShortcode, byName\n //\n const shortcodeToEmoji = new Map();\n const nameToEmoji = new Map();\n for (const customEmoji of customEmojis) {\n nameToEmoji.set(customEmoji.name.toLowerCase(), customEmoji);\n for (const shortcode of (customEmoji.shortcodes || [])) {\n shortcodeToEmoji.set(shortcode.toLowerCase(), customEmoji);\n }\n }\n\n const byShortcode = shortcode => shortcodeToEmoji.get(shortcode.toLowerCase());\n const byName = name => nameToEmoji.get(name.toLowerCase());\n\n return {\n all,\n search,\n byShortcode,\n byName\n }\n}\n\nconst isFirefoxContentScript = typeof wrappedJSObject !== 'undefined';\n\n// remove some internal implementation details, i.e. the \"tokens\" array on the emoji object\n// essentially, convert the emoji from the version stored in IDB to the version used in-memory\nfunction cleanEmoji (emoji) {\n if (!emoji) {\n return emoji\n }\n // if inside a Firefox content script, need to clone the emoji object to prevent Firefox from complaining about\n // cross-origin object. See: https://github.com/nolanlawson/emoji-picker-element/issues/356\n /* istanbul ignore if */\n if (isFirefoxContentScript) {\n emoji = structuredClone(emoji);\n }\n delete emoji.tokens;\n if (emoji.skinTones) {\n const len = emoji.skinTones.length;\n emoji.skins = Array(len);\n for (let i = 0; i < len; i++) {\n emoji.skins[i] = {\n tone: emoji.skinTones[i],\n unicode: emoji.skinUnicodes[i],\n version: emoji.skinVersions[i]\n };\n }\n delete emoji.skinTones;\n delete emoji.skinUnicodes;\n delete emoji.skinVersions;\n }\n return emoji\n}\n\nfunction warnETag (eTag) {\n if (!eTag) {\n console.warn('emoji-picker-element is more efficient if the dataSource server exposes an ETag header.');\n }\n}\n\nconst requiredKeys = [\n 'annotation',\n 'emoji',\n 'group',\n 'order',\n 'version'\n];\n\nfunction assertEmojiData (emojiData) {\n if (!emojiData ||\n !Array.isArray(emojiData) ||\n !emojiData[0] ||\n (typeof emojiData[0] !== 'object') ||\n requiredKeys.some(key => (!(key in emojiData[0])))) {\n throw new Error('Emoji data is in the wrong format')\n }\n}\n\nfunction assertStatus (response, dataSource) {\n if (Math.floor(response.status / 100) !== 2) {\n throw new Error('Failed to fetch: ' + dataSource + ': ' + response.status)\n }\n}\n\nasync function getETag (dataSource) {\n const response = await fetch(dataSource, { method: 'HEAD' });\n assertStatus(response, dataSource);\n const eTag = response.headers.get('etag');\n warnETag(eTag);\n return eTag\n}\n\nasync function getETagAndData (dataSource) {\n const response = await fetch(dataSource);\n assertStatus(response, dataSource);\n const eTag = response.headers.get('etag');\n warnETag(eTag);\n const emojiData = await response.json();\n assertEmojiData(emojiData);\n return [eTag, emojiData]\n}\n\n// TODO: including these in blob-util.ts causes typedoc to generate docs for them,\n// even with --excludePrivate ¯\\_(ツ)_/¯\n/** @private */\n/**\n * Convert an `ArrayBuffer` to a binary string.\n *\n * Example:\n *\n * ```js\n * var myString = blobUtil.arrayBufferToBinaryString(arrayBuff)\n * ```\n *\n * @param buffer - array buffer\n * @returns binary string\n */\nfunction arrayBufferToBinaryString(buffer) {\n var binary = '';\n var bytes = new Uint8Array(buffer);\n var length = bytes.byteLength;\n var i = -1;\n while (++i < length) {\n binary += String.fromCharCode(bytes[i]);\n }\n return binary;\n}\n/**\n * Convert a binary string to an `ArrayBuffer`.\n *\n * ```js\n * var myBuffer = blobUtil.binaryStringToArrayBuffer(binaryString)\n * ```\n *\n * @param binary - binary string\n * @returns array buffer\n */\nfunction binaryStringToArrayBuffer(binary) {\n var length = binary.length;\n var buf = new ArrayBuffer(length);\n var arr = new Uint8Array(buf);\n var i = -1;\n while (++i < length) {\n arr[i] = binary.charCodeAt(i);\n }\n return buf;\n}\n\n// generate a checksum based on the stringified JSON\nasync function jsonChecksum (object) {\n const inString = JSON.stringify(object);\n let inBuffer = binaryStringToArrayBuffer(inString);\n\n // this does not need to be cryptographically secure, SHA-1 is fine\n const outBuffer = await crypto.subtle.digest('SHA-1', inBuffer);\n const outBinString = arrayBufferToBinaryString(outBuffer);\n const res = btoa(outBinString);\n return res\n}\n\nasync function doCheckForUpdates (db, dataSource) {\n // just do a simple HEAD request first to see if the eTags match\n let emojiData;\n let eTag = await getETag(dataSource);\n if (!eTag) { // work around lack of ETag/Access-Control-Expose-Headers\n const eTagAndData = await getETagAndData(dataSource);\n eTag = eTagAndData[0];\n emojiData = eTagAndData[1];\n if (!eTag) {\n eTag = await jsonChecksum(emojiData);\n }\n }\n if (await hasData(db, dataSource, eTag)) ; else {\n if (!emojiData) {\n const eTagAndData = await getETagAndData(dataSource);\n emojiData = eTagAndData[1];\n }\n await loadData(db, emojiData, dataSource, eTag);\n }\n}\n\nasync function loadDataForFirstTime (db, dataSource) {\n let [eTag, emojiData] = await getETagAndData(dataSource);\n if (!eTag) {\n // Handle lack of support for ETag or Access-Control-Expose-Headers\n // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers#Browser_compatibility\n eTag = await jsonChecksum(emojiData);\n }\n\n await loadData(db, emojiData, dataSource, eTag);\n}\n\nasync function checkForUpdates (db, dataSource) {\n try {\n await doCheckForUpdates(db, dataSource);\n } catch (err) {\n // Checking for updates is not a critical operation, and it can fail if e.g. the picker is quickly removed and\n // re-added to the DOM. In those cases, we may get an IndexedDB InvalidStateError because we are attempting to close\n // the database connection, possibly while another request is inflight. So there's effectively no way to prevent\n // InvalidStateErrors unless we were to carefully sequence our IndexedDB operations. Much more simply, we can just\n // ignore IndexedDB InvalidStateErrors here and give users one less useless error message in their console.\n if (err.name !== 'InvalidStateError') {\n throw err\n }\n }\n}\n\nclass Database {\n constructor ({ dataSource = DEFAULT_DATA_SOURCE, locale = DEFAULT_LOCALE, customEmoji = [] } = {}) {\n this.dataSource = dataSource;\n this.locale = locale;\n this._dbName = `emoji-picker-element-${this.locale}`;\n this._db = undefined;\n this._lazyUpdate = undefined;\n this._custom = customEmojiIndex(customEmoji);\n\n this._clear = this._clear.bind(this);\n this._ready = this._init();\n }\n\n async _init () {\n const db = this._db = await openDatabase(this._dbName);\n\n addOnCloseListener(this._dbName, this._clear);\n const dataSource = this.dataSource;\n const empty = await isEmpty(db);\n\n if (empty) {\n await loadDataForFirstTime(db, dataSource);\n } else { // offline-first - do an update asynchronously\n this._lazyUpdate = checkForUpdates(db, dataSource);\n }\n }\n\n async ready () {\n const checkReady = async () => {\n if (!this._ready) {\n this._ready = this._init();\n }\n return this._ready\n };\n await checkReady();\n // There's a possibility of a race condition where the element gets added, removed, and then added again\n // with a particular timing, which would set the _db to undefined.\n // We *could* do a while loop here, but that seems excessive and could lead to an infinite loop.\n if (!this._db) {\n await checkReady();\n }\n }\n\n async getEmojiByGroup (group) {\n assertNumber(group);\n await this.ready();\n return uniqEmoji(await getEmojiByGroup(this._db, group)).map(cleanEmoji)\n }\n\n async getEmojiBySearchQuery (query) {\n assertNonEmptyString(query);\n await this.ready();\n const customs = this._custom.search(query);\n const natives = uniqEmoji(await getEmojiBySearchQuery(this._db, query)).map(cleanEmoji);\n return [\n ...customs,\n ...natives\n ]\n }\n\n async getEmojiByShortcode (shortcode) {\n assertNonEmptyString(shortcode);\n await this.ready();\n const custom = this._custom.byShortcode(shortcode);\n if (custom) {\n return custom\n }\n return cleanEmoji(await getEmojiByShortcode(this._db, shortcode))\n }\n\n async getEmojiByUnicodeOrName (unicodeOrName) {\n assertNonEmptyString(unicodeOrName);\n await this.ready();\n const custom = this._custom.byName(unicodeOrName);\n if (custom) {\n return custom\n }\n return cleanEmoji(await getEmojiByUnicode(this._db, unicodeOrName))\n }\n\n async getPreferredSkinTone () {\n await this.ready();\n return (await get(this._db, STORE_KEYVALUE, KEY_PREFERRED_SKINTONE)) || 0\n }\n\n async setPreferredSkinTone (skinTone) {\n assertNumber(skinTone);\n await this.ready();\n return set(this._db, STORE_KEYVALUE, KEY_PREFERRED_SKINTONE, skinTone)\n }\n\n async incrementFavoriteEmojiCount (unicodeOrName) {\n assertNonEmptyString(unicodeOrName);\n await this.ready();\n return incrementFavoriteEmojiCount(this._db, unicodeOrName)\n }\n\n async getTopFavoriteEmoji (limit) {\n assertNumber(limit);\n await this.ready();\n return (await getTopFavoriteEmoji(this._db, this._custom, limit)).map(cleanEmoji)\n }\n\n set customEmoji (customEmojis) {\n this._custom = customEmojiIndex(customEmojis);\n }\n\n get customEmoji () {\n return this._custom.all\n }\n\n async _shutdown () {\n await this.ready(); // reopen if we've already been closed/deleted\n try {\n await this._lazyUpdate; // allow any lazy updates to process before closing/deleting\n } catch (err) { /* ignore network errors (offline-first) */ }\n }\n\n // clear references to IDB, e.g. during a close event\n _clear () {\n // We don't need to call removeEventListener or remove the manual \"close\" listeners.\n // The memory leak tests prove this is unnecessary. It's because:\n // 1) IDBDatabases that can no longer fire \"close\" automatically have listeners GCed\n // 2) we clear the manual close listeners in databaseLifecycle.js.\n this._db = this._ready = this._lazyUpdate = undefined;\n }\n\n async close () {\n await this._shutdown();\n await closeDatabase(this._dbName);\n }\n\n async delete () {\n await this._shutdown();\n await deleteDatabase(this._dbName);\n }\n}\n\nexport { Database as default };\n","import Database from './database.js';\n\n// via https://unpkg.com/browse/emojibase-data@6.0.0/meta/groups.json\nconst allGroups = [\n [-1, '✨', 'custom'],\n [0, '😀', 'smileys-emotion'],\n [1, '👋', 'people-body'],\n [3, '🐱', 'animals-nature'],\n [4, '🍎', 'food-drink'],\n [5, '🏠️', 'travel-places'],\n [6, '⚽', 'activities'],\n [7, '📝', 'objects'],\n [8, '⛔️', 'symbols'],\n [9, '🏁', 'flags']\n].map(([id, emoji, name]) => ({ id, emoji, name }));\n\nconst groups = allGroups.slice(1);\n\nconst MIN_SEARCH_TEXT_LENGTH = 2;\nconst NUM_SKIN_TONES = 6;\n\n/* istanbul ignore next */\nconst rIC = typeof requestIdleCallback === 'function' ? requestIdleCallback : setTimeout;\n\n// check for ZWJ (zero width joiner) character\nfunction hasZwj (emoji) {\n return emoji.unicode.includes('\\u200d')\n}\n\n// Find one good representative emoji from each version to test by checking its color.\n// Ideally it should have color in the center. For some inspiration, see:\n// https://about.gitlab.com/blog/2018/05/30/journey-in-native-unicode-emoji/\n//\n// Note that for certain versions (12.1, 13.1), there is no point in testing them explicitly, because\n// all the emoji from this version are compound-emoji from previous versions. So they would pass a color\n// test, even in browsers that display them as double emoji. (E.g. \"face in clouds\" might render as\n// \"face without mouth\" plus \"fog\".) These emoji can only be filtered using the width test,\n// which happens in checkZwjSupport.js.\nconst versionsAndTestEmoji = {\n '🫪': 17, // distorted face\n '🫩': 16, // face with bags under eyes\n '🫨': 15.1, // shaking head, technically from v15 but see note above\n '🫠': 14,\n '🥲': 13.1, // smiling face with tear, technically from v13 but see note above\n '🥻': 12.1, // sari, technically from v12 but see note above\n '🥰': 11,\n '🤩': 5,\n '👱‍♀️': 4,\n '🤣': 3,\n '👁️‍🗨️': 2,\n '😀': 1,\n '😐️': 0.7,\n '😃': 0.6\n};\n\nconst TIMEOUT_BEFORE_LOADING_MESSAGE = 1000; // 1 second\nconst DEFAULT_SKIN_TONE_EMOJI = '🖐️';\nconst DEFAULT_NUM_COLUMNS = 8;\n\n// Based on https://fivethirtyeight.com/features/the-100-most-used-emojis/ and\n// https://blog.emojipedia.org/facebook-reveals-most-and-least-used-emojis/ with\n// a bit of my own curation. (E.g. avoid the \"OK\" gesture because of connotations:\n// https://emojipedia.org/ok-hand/)\nconst MOST_COMMONLY_USED_EMOJI = [\n '😊',\n '😒',\n '❤️',\n '👍️',\n '😍',\n '😂',\n '😭',\n '☺️',\n '😔',\n '😩',\n '😏',\n '💕',\n '🙌',\n '😘'\n];\n\n// It's important to list Twemoji Mozilla before everything else, because Mozilla bundles their\n// own font on some platforms (notably Windows and Linux as of this writing). Typically, Mozilla\n// updates faster than the underlying OS, and we don't want to render older emoji in one font and\n// newer emoji in another font:\n// https://github.com/nolanlawson/emoji-picker-element/pull/268#issuecomment-1073347283\nconst FONT_FAMILY = '\"Twemoji Mozilla\",\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",' +\n '\"Noto Color Emoji\",\"EmojiOne Color\",\"Android Emoji\",sans-serif';\n\n/* istanbul ignore next */\nconst DEFAULT_CATEGORY_SORTING = (a, b) => a < b ? -1 : a > b ? 1 : 0;\n\n// Test if an emoji is supported by rendering it to canvas and checking that the color is not black\n// See https://about.gitlab.com/blog/2018/05/30/journey-in-native-unicode-emoji/\n// and https://www.npmjs.com/package/if-emoji for inspiration\n// This implementation is largely borrowed from if-emoji, adding the font-family\n\n\nconst getTextFeature = (text, color) => {\n const canvas = document.createElement('canvas');\n canvas.width = canvas.height = 1;\n\n const ctx = canvas.getContext('2d', {\n // Improves the performance of `getImageData()`\n // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getContextAttributes#willreadfrequently\n willReadFrequently: true\n });\n ctx.textBaseline = 'top';\n ctx.font = `100px ${FONT_FAMILY}`;\n ctx.fillStyle = color;\n ctx.scale(0.01, 0.01);\n ctx.fillText(text, 0, 0);\n\n return ctx.getImageData(0, 0, 1, 1).data\n};\n\nconst compareFeatures = (feature1, feature2) => {\n const feature1Str = [...feature1].join(',');\n const feature2Str = [...feature2].join(',');\n // This is RGBA, so for 0,0,0, we are checking that the first RGB is not all zeroes.\n // Most of the time when unsupported this is 0,0,0,0, but on Chrome on Mac it is\n // 0,0,0,61 - there is a transparency here.\n return feature1Str === feature2Str && !feature1Str.startsWith('0,0,0,')\n};\n\nfunction testColorEmojiSupported (text) {\n // Render white and black and then compare them to each other and ensure they're the same\n // color, and neither one is black. This shows that the emoji was rendered in color.\n const feature1 = getTextFeature(text, '#000');\n const feature2 = getTextFeature(text, '#fff');\n return feature1 && feature2 && compareFeatures(feature1, feature2)\n}\n\n// rather than check every emoji ever, which would be expensive, just check some representatives from the\n// different emoji releases to determine what the font supports\n\nfunction determineEmojiSupportLevel () {\n const entries = Object.entries(versionsAndTestEmoji);\n try {\n // start with latest emoji and work backwards\n for (const [emoji, version] of entries) {\n if (testColorEmojiSupported(emoji)) {\n return version\n }\n }\n } catch (e) { // canvas error\n } finally {\n }\n // In case of an error, be generous and just assume all emoji are supported (e.g. for canvas errors\n // due to anti-fingerprinting add-ons). Better to show some gray boxes than nothing at all.\n return entries[0][1] // first one in the list is the most recent version\n}\n\n// Check which emojis we know for sure aren't supported, based on Unicode version level\nlet promise;\nconst detectEmojiSupportLevel = () => {\n if (!promise) {\n // Delay so it can run while the IDB database is being created by the browser (on another thread).\n // This helps especially with first load – we want to start pre-populating the database on the main thread,\n // and then wait for IDB to commit everything, and while waiting we run this check.\n promise = new Promise(resolve => (\n rIC(() => (\n resolve(determineEmojiSupportLevel()) // delay so ideally this can run while IDB is first populating\n ))\n ));\n }\n return promise\n};\n// determine which emojis containing ZWJ (zero width joiner) characters\n// are supported (rendered as one glyph) rather than unsupported (rendered as two or more glyphs)\nconst supportedZwjEmojis = new Map();\n\nconst VARIATION_SELECTOR = '\\ufe0f';\nconst SKINTONE_MODIFIER = '\\ud83c';\nconst ZWJ = '\\u200d';\nconst LIGHT_SKIN_TONE = 0x1F3FB;\nconst LIGHT_SKIN_TONE_MODIFIER = 0xdffb;\n\n// TODO: this is a naive implementation, we can improve it later\n// It's only used for the skintone picker, so as long as people don't customize with\n// really exotic emoji then it should work fine\nfunction applySkinTone (str, skinTone) {\n if (skinTone === 0) {\n return str\n }\n const zwjIndex = str.indexOf(ZWJ);\n if (zwjIndex !== -1) {\n return str.substring(0, zwjIndex) +\n String.fromCodePoint(LIGHT_SKIN_TONE + skinTone - 1) +\n str.substring(zwjIndex)\n }\n if (str.endsWith(VARIATION_SELECTOR)) {\n str = str.substring(0, str.length - 1);\n }\n return str + SKINTONE_MODIFIER + String.fromCodePoint(LIGHT_SKIN_TONE_MODIFIER + skinTone - 1)\n}\n\nfunction halt (event) {\n event.preventDefault();\n event.stopPropagation();\n}\n\n// Implementation left/right or up/down navigation, circling back when you\n// reach the start/end of the list\nfunction incrementOrDecrement (decrement, val, arr) {\n val += (decrement ? -1 : 1);\n if (val < 0) {\n val = arr.length - 1;\n } else if (val >= arr.length) {\n val = 0;\n }\n return val\n}\n\n// like lodash's uniqBy but much smaller\nfunction uniqBy (arr, func) {\n const set = new Set();\n const res = [];\n for (const item of arr) {\n const key = func(item);\n if (!set.has(key)) {\n set.add(key);\n res.push(item);\n }\n }\n return res\n}\n\n// We don't need all the data on every emoji, and there are specific things we need\n// for the UI, so build a \"view model\" from the emoji object we got from the database\n\nfunction summarizeEmojisForUI (emojis, emojiSupportLevel) {\n const toSimpleSkinsMap = skins => {\n const res = {};\n for (const skin of skins) {\n // ignore arrays like [1, 2] with multiple skin tones\n // also ignore variants that are in an unsupported emoji version\n // (these do exist - variants from a different version than their base emoji)\n if (typeof skin.tone === 'number' && skin.version <= emojiSupportLevel) {\n res[skin.tone] = skin.unicode;\n }\n }\n return res\n };\n\n return emojis.map(({ unicode, skins, shortcodes, url, name, category, annotation }) => ({\n unicode,\n name,\n shortcodes,\n url,\n category,\n annotation,\n id: unicode || name,\n skins: skins && toSimpleSkinsMap(skins)\n }))\n}\n\n// import rAF from one place so that the bundle size is a bit smaller\nconst rAF = requestAnimationFrame;\n\n// \"Svelte action\"-like utility to detect layout changes via ResizeObserver.\n// If ResizeObserver is unsupported, we just use rAF once and don't bother to update.\n\n\nlet resizeObserverSupported = typeof ResizeObserver === 'function';\n\nfunction resizeObserverAction (node, abortSignal, onUpdate) {\n let resizeObserver;\n if (resizeObserverSupported) {\n resizeObserver = new ResizeObserver(onUpdate);\n resizeObserver.observe(node);\n } else { // just run once, don't bother trying to track it\n rAF(onUpdate);\n }\n\n // cleanup function (called on destroy)\n abortSignal.addEventListener('abort', () => {\n if (resizeObserver) {\n resizeObserver.disconnect();\n }\n });\n}\n\n// get the width of the text inside of a DOM node, via https://stackoverflow.com/a/59525891/680742\nfunction calculateTextWidth (node) {\n // skip running this in jest/vitest because we don't need to check for emoji support in that environment\n /* istanbul ignore else */\n {\n const range = document.createRange();\n range.selectNode(node.firstChild);\n return range.getBoundingClientRect().width\n }\n}\n\nlet baselineEmojiWidth;\n\n/**\n * Check if the given emojis containing ZWJ characters are supported by the current browser (don't render\n * as double characters) and return true if all are supported.\n * @param zwjEmojisToCheck\n * @param baselineEmoji\n * @param emojiToDomNode\n */\nfunction checkZwjSupport (zwjEmojisToCheck, baselineEmoji, emojiToDomNode) {\n let allSupported = true;\n let shouldWarn = false;\n for (const emoji of zwjEmojisToCheck) {\n const domNode = emojiToDomNode(emoji);\n // sanity check to make sure the node is defined properly\n /* istanbul ignore if */\n if (!domNode) {\n // This is a race condition that can occur when the component is unmounted/remounted\n // It doesn't really matter what we do here since the old context is not going to render anymore.\n // Just bail out of emoji support detection and return `allSupported=true` since the rendering context is gone\n continue\n }\n const emojiWidth = calculateTextWidth(domNode);\n /* istanbul ignore if */\n if (emojiWidth === 0) {\n shouldWarn = true;\n }\n if (typeof baselineEmojiWidth === 'undefined') { // calculate the baseline emoji width only once\n baselineEmojiWidth = calculateTextWidth(baselineEmoji);\n }\n // On Windows, some supported emoji are ~50% bigger than the baseline emoji, but what we really want to guard\n // against are the ones that are 2x the size, because those are truly broken (person with red hair = person with\n // floating red wig, black cat = cat with black square, polar bear = bear with snowflake, etc.)\n // So here we set the threshold at 1.8 times the size of the baseline emoji.\n const supported = emojiWidth / 1.8 < baselineEmojiWidth;\n supportedZwjEmojis.set(emoji.unicode, supported);\n\n if (!supported) {\n allSupported = false;\n }\n }\n // Warn exactly once since we don't want to spam the console\n /* istanbul ignore if */\n if (shouldWarn) {\n console.warn('Emoji support detection failed - emoji character is 0 width.\\n' +\n 'This is likely due to using `display:none` which is unsupported.\\n' +\n 'If this is a Jest/Vitest environment, you can ignore this warning.\\n' +\n 'For details see: https://github.com/nolanlawson/emoji-picker-element/issues/514'\n );\n }\n return allSupported\n}\n\n// like lodash's uniq\n\nfunction uniq (arr) {\n return uniqBy(arr, _ => _)\n}\n\n// Note we put this in its own function outside Picker.js to avoid Svelte doing an invalidation on the \"setter\" here.\n// At best the invalidation is useless, at worst it can cause infinite loops:\n// https://github.com/nolanlawson/emoji-picker-element/pull/180\n// https://github.com/sveltejs/svelte/issues/6521\n// Also note tabpanelElement can be null if the element is disconnected immediately after connected\nfunction resetScrollTopIfPossible (element) {\n /* istanbul ignore else */\n if (element) { // Makes me nervous not to have this `if` guard\n element.scrollTop = 0;\n }\n}\n\nfunction getFromMap (cache, key, func) {\n let cached = cache.get(key);\n if (!cached) {\n cached = func();\n cache.set(key, cached);\n }\n return cached\n}\n\nfunction toString (value) {\n return '' + value\n}\n\nfunction parseTemplate (htmlString) {\n const template = document.createElement('template');\n template.innerHTML = htmlString;\n return template\n}\n\nconst parseCache = new WeakMap();\nconst domInstancesCache = new WeakMap();\n// This needs to be a symbol because it needs to be different from any possible output of a key function\nconst unkeyedSymbol = Symbol('un-keyed');\n\n// Not supported in Safari <=13\nconst hasReplaceChildren = 'replaceChildren' in Element.prototype;\nfunction replaceChildren (parentNode, newChildren) {\n /* istanbul ignore else */\n if (hasReplaceChildren) {\n parentNode.replaceChildren(...newChildren);\n } else { // minimal polyfill for Element.prototype.replaceChildren\n parentNode.innerHTML = '';\n parentNode.append(...newChildren);\n }\n}\n\nfunction doChildrenNeedRerender (parentNode, newChildren) {\n let oldChild = parentNode.firstChild;\n let oldChildrenCount = 0;\n // iterate using firstChild/nextSibling because browsers use a linked list under the hood\n while (oldChild) {\n const newChild = newChildren[oldChildrenCount];\n // check if the old child and new child are the same\n if (newChild !== oldChild) {\n return true\n }\n oldChild = oldChild.nextSibling;\n oldChildrenCount++;\n }\n // if new children length is different from old, we must re-render\n return oldChildrenCount !== newChildren.length\n}\n\nfunction patchChildren (newChildren, instanceBinding) {\n const { targetNode } = instanceBinding;\n let { targetParentNode } = instanceBinding;\n\n let needsRerender = false;\n\n if (targetParentNode) { // already rendered once\n needsRerender = doChildrenNeedRerender(targetParentNode, newChildren);\n } else { // first render of list\n needsRerender = true;\n instanceBinding.targetNode = undefined; // placeholder node not needed anymore, free memory\n instanceBinding.targetParentNode = targetParentNode = targetNode.parentNode;\n }\n // avoid re-rendering list if the dom nodes are exactly the same before and after\n if (needsRerender) {\n replaceChildren(targetParentNode, newChildren);\n }\n}\n\nfunction patch (expressions, instanceBindings) {\n for (const instanceBinding of instanceBindings) {\n const {\n targetNode,\n currentExpression,\n binding: {\n expressionIndex,\n attributeName,\n attributeValuePre,\n attributeValuePost\n }\n } = instanceBinding;\n\n const expression = expressions[expressionIndex];\n\n if (currentExpression === expression) {\n // no need to update, same as before\n continue\n }\n\n instanceBinding.currentExpression = expression;\n\n if (attributeName) { // attribute replacement\n if (expression === null) {\n // null is treated as a special case by the framework - we don't render an attribute at all in this case\n targetNode.removeAttribute(attributeName);\n } else {\n // attribute value is not null; set a new attribute\n const newValue = attributeValuePre + toString(expression) + attributeValuePost;\n targetNode.setAttribute(attributeName, newValue);\n }\n } else { // text node / child element / children replacement\n let newNode;\n if (Array.isArray(expression)) { // array of DOM elements produced by tag template literals\n patchChildren(expression, instanceBinding);\n } else if (expression instanceof Element) { // html tag template returning a DOM element\n newNode = expression;\n targetNode.replaceWith(newNode);\n } else { // primitive - string, number, etc\n // nodeValue is faster than textContent supposedly https://www.youtube.com/watch?v=LY6y3HbDVmg\n // note we may be replacing the value in a placeholder text node\n targetNode.nodeValue = toString(expression);\n }\n if (newNode) {\n instanceBinding.targetNode = newNode;\n }\n }\n }\n}\n\nfunction parse (tokens) {\n let htmlString = '';\n\n let withinTag = false;\n let withinAttribute = false;\n let elementIndexCounter = -1; // depth-first traversal order\n\n const elementsToBindings = new Map();\n const elementIndexes = [];\n\n let skipTokenChars = 0;\n for (let i = 0, len = tokens.length; i < len; i++) {\n const token = tokens[i];\n htmlString += token.slice(skipTokenChars);\n\n if (i === len - 1) {\n break // no need to process characters - no more expressions to be found\n }\n\n for (let j = 0; j < token.length; j++) {\n const char = token.charAt(j);\n switch (char) {\n case '<': {\n const nextChar = token.charAt(j + 1);\n if (nextChar === '/') { // closing tag\n // leaving an element\n elementIndexes.pop();\n } else { // not a closing tag\n withinTag = true;\n elementIndexes.push(++elementIndexCounter);\n }\n break\n }\n case '>': {\n withinTag = false;\n withinAttribute = false;\n break\n }\n case '=': {\n withinAttribute = true;\n break\n }\n }\n }\n\n const elementIndex = elementIndexes[elementIndexes.length - 1];\n const bindings = getFromMap(elementsToBindings, elementIndex, () => []);\n\n let attributeName;\n let attributeValuePre;\n let attributeValuePost;\n if (withinAttribute) {\n // I never use single-quotes for attribute values in HTML, so just support double-quotes or no-quotes\n const attributePreMatch = /(\\S+)=\"?([^\"=]*)$/.exec(token);\n attributeName = attributePreMatch[1];\n attributeValuePre = attributePreMatch[2];\n const attributePostMatch = /^([^\">]*)(\"?)/.exec(tokens[i + 1]);\n attributeValuePost = attributePostMatch[1];\n // Optimization: remove the attribute itself, so we don't create a default attribute which is either empty or just\n // the \"pre\" text, e.g. `<div foo>` or `<div foo=\"prefix\">`. It will be replaced by the expression anyway.\n htmlString = htmlString.slice(0, -1 * attributePreMatch[0].length);\n skipTokenChars = attributePostMatch[0].length;\n } else {\n skipTokenChars = 0;\n }\n\n const binding = {\n attributeName,\n attributeValuePre,\n attributeValuePost,\n expressionIndex: i\n };\n\n bindings.push(binding);\n\n if (!withinTag && !withinAttribute) {\n // Add a placeholder text node, so we can find it later. Note we only support one dynamic child text node\n htmlString += ' ';\n }\n }\n\n const template = parseTemplate(htmlString);\n\n return {\n template,\n elementsToBindings\n }\n}\n\nfunction applyBindings (bindings, element, instanceBindings) {\n for (let i = 0; i < bindings.length; i++) {\n const binding = bindings[i];\n\n const targetNode = binding.attributeName\n ? element // attribute binding, just use the element itself\n : element.firstChild; // not an attribute binding, so has a placeholder text node\n\n const instanceBinding = {\n binding,\n targetNode,\n targetParentNode: undefined,\n currentExpression: undefined\n };\n\n instanceBindings.push(instanceBinding);\n }\n}\n\nfunction traverseAndSetupBindings (rootElement, elementsToBindings) {\n const instanceBindings = [];\n\n let topLevelBindings;\n if (elementsToBindings.size === 1 && (topLevelBindings = elementsToBindings.get(0))) {\n // Optimization for the common case where there's only one element and one binding\n // Skip creating a TreeWalker entirely and just handle the root DOM element\n applyBindings(topLevelBindings, rootElement, instanceBindings);\n } else {\n // traverse dom\n const treeWalker = document.createTreeWalker(rootElement, NodeFilter.SHOW_ELEMENT);\n\n let element = rootElement;\n let elementIndex = -1;\n do {\n const bindings = elementsToBindings.get(++elementIndex);\n if (bindings) {\n applyBindings(bindings, element, instanceBindings);\n }\n } while ((element = treeWalker.nextNode()))\n }\n\n return instanceBindings\n}\n\nfunction parseHtml (tokens) {\n // All templates and bound expressions are unique per tokens array\n const { template, elementsToBindings } = getFromMap(parseCache, tokens, () => parse(tokens));\n\n // When we parseHtml, we always return a fresh DOM instance ready to be updated\n const dom = template.cloneNode(true).content.firstElementChild;\n const instanceBindings = traverseAndSetupBindings(dom, elementsToBindings);\n\n return function updateDomInstance (expressions) {\n patch(expressions, instanceBindings);\n return dom\n }\n}\n\nfunction createFramework (state) {\n const domInstances = getFromMap(domInstancesCache, state, () => new Map());\n let domInstanceCacheKey = unkeyedSymbol;\n\n function html (tokens, ...expressions) {\n // Each unique lexical usage of map() is considered unique due to the html`` tagged template call it makes,\n // which has lexically unique tokens. The unkeyed symbol is just used for html`` usage outside of a map().\n const domInstancesForTokens = getFromMap(domInstances, tokens, () => new Map());\n const updateDomInstance = getFromMap(domInstancesForTokens, domInstanceCacheKey, () => parseHtml(tokens));\n\n return updateDomInstance(expressions) // update with expressions\n }\n\n function map (array, callback, keyFunction) {\n return array.map((item, index) => {\n const originalCacheKey = domInstanceCacheKey;\n domInstanceCacheKey = keyFunction(item);\n try {\n return callback(item, index)\n } finally {\n domInstanceCacheKey = originalCacheKey;\n }\n })\n }\n\n return { map, html }\n}\n\nfunction render (container, state, helpers, events, actions, refs, abortSignal, actionContext, firstRender) {\n const { labelWithSkin, titleForEmoji, unicodeWithSkin } = helpers;\n const { html, map } = createFramework(state);\n\n function emojiList (emojis, searchMode, prefix) {\n return map(emojis, (emoji, i) => {\n return html`<button role=\"${searchMode ? 'option' : 'menuitem'}\" aria-selected=\"${searchMode ? i === state.activeSearchItem : null}\" aria-label=\"${labelWithSkin(emoji, state.currentSkinTone)}\" title=\"${titleForEmoji(emoji)}\" class=\"${\n 'emoji' +\n (searchMode && i === state.activeSearchItem ? ' active' : '') +\n (emoji.unicode ? '' : ' custom-emoji')\n }\" id=\"${`${prefix}-${emoji.id}`}\" style=\"${emoji.unicode ? null : `--custom-emoji-background: url(${JSON.stringify(emoji.url)})`}\">${\n emoji.unicode\n ? unicodeWithSkin(emoji, state.currentSkinTone)\n : ''\n }</button>`\n // It's important for the cache key to be unique based on the prefix, because the framework caches based on the\n // unique tokens + cache key, and the same emoji may be used in the tab as well as in the fav bar\n }, emoji => `${prefix}-${emoji.id}`)\n }\n\n const section = () => {\n return html`<section data-ref=\"rootElement\" class=\"picker\" aria-label=\"${state.i18n.regionLabel}\" style=\"${state.pickerStyle || ''}\"><div class=\"pad-top\"></div><div class=\"search-row\"><div class=\"search-wrapper\"><input id=\"search\" class=\"search\" type=\"search\" role=\"combobox\" enterkeyhint=\"search\" placeholder=\"${state.i18n.searchLabel}\" autocapitalize=\"none\" autocomplete=\"off\" spellcheck=\"true\" aria-expanded=\"${!!(state.searchMode && state.currentEmojis.length)}\" aria-controls=\"search-results\" aria-describedby=\"search-description\" aria-autocomplete=\"list\" aria-activedescendant=\"${state.activeSearchItemId ? `emo-${state.activeSearchItemId}` : null}\" data-ref=\"searchElement\" data-on-input=\"onSearchInput\" data-on-keydown=\"onSearchKeydown\"><label class=\"sr-only\" for=\"search\">${state.i18n.searchLabel}</label> <span id=\"search-description\" class=\"sr-only\">${state.i18n.searchDescription}</span></div><div class=\"skintone-button-wrapper ${state.skinTonePickerExpandedAfterAnimation ? 'expanded' : ''}\"><button id=\"skintone-button\" class=\"emoji ${state.skinTonePickerExpanded ? 'hide-focus' : ''}\" aria-label=\"${state.skinToneButtonLabel}\" title=\"${state.skinToneButtonLabel}\" aria-describedby=\"skintone-description\" aria-haspopup=\"listbox\" aria-expanded=\"${state.skinTonePickerExpanded}\" aria-controls=\"skintone-list\" data-on-click=\"onClickSkinToneButton\">${state.skinToneButtonText || ''}</button></div><span id=\"skintone-description\" class=\"sr-only\">${state.i18n.skinToneDescription}</span><div data-ref=\"skinToneDropdown\" id=\"skintone-list\" class=\"skintone-list hide-focus ${state.skinTonePickerExpanded ? '' : 'hidden no-animate'}\" style=\"transform:translateY(${state.skinTonePickerExpanded ? 0 : 'calc(-1 * var(--num-skintones) * var(--total-emoji-size))'})\" role=\"listbox\" aria-label=\"${state.i18n.skinTonesLabel}\" aria-activedescendant=\"skintone-${state.activeSkinTone}\" aria-hidden=\"${!state.skinTonePickerExpanded}\" tabIndex=\"-1\" data-on-focusout=\"onSkinToneOptionsFocusOut\" data-on-click=\"onSkinToneOptionsClick\" data-on-keydown=\"onSkinToneOptionsKeydown\" data-on-keyup=\"onSkinToneOptionsKeyup\">${\n map(state.skinTones, (skinTone, i) => {\n return html`<div id=\"skintone-${i}\" class=\"emoji ${i === state.activeSkinTone ? 'active' : ''}\" aria-selected=\"${i === state.activeSkinTone}\" role=\"option\" title=\"${state.i18n.skinTones[i]}\" aria-label=\"${state.i18n.skinTones[i]}\">${skinTone}</div>`\n }, skinTone => skinTone)\n }</div></div><div class=\"nav\" role=\"tablist\" style=\"grid-template-columns:repeat(${state.groups.length},1fr)\" aria-label=\"${state.i18n.categoriesLabel}\" data-on-keydown=\"onNavKeydown\" data-on-click=\"onNavClick\">${\n map(state.groups, (group) => {\n return html`<button role=\"tab\" class=\"nav-button\" aria-controls=\"tab-${group.id}\" aria-label=\"${state.i18n.categories[group.name]}\" aria-selected=\"${!state.searchMode && state.currentGroup.id === group.id}\" title=\"${state.i18n.categories[group.name]}\" data-group-id=\"${group.id}\"><div class=\"nav-emoji emoji\">${group.emoji}</div></button>`\n }, group => group.id)\n }</div><div class=\"indicator-wrapper\"><div class=\"indicator\" style=\"transform:translateX(${(/* istanbul ignore next */ (state.isRtl ? -1 : 1)) * state.currentGroupIndex * 100}%)\"></div></div><div class=\"message ${state.message ? '' : 'gone'}\" role=\"alert\" aria-live=\"polite\">${state.message || ''}</div><div data-ref=\"tabpanelElement\" class=\"tabpanel ${(!state.databaseLoaded || state.message) ? 'gone' : ''}\" role=\"${state.searchMode ? 'region' : 'tabpanel'}\" aria-label=\"${state.searchMode ? state.i18n.searchResultsLabel : state.i18n.categories[state.currentGroup.name]}\" id=\"${state.searchMode ? null : `tab-${state.currentGroup.id}`}\" tabIndex=\"0\" data-on-click=\"onEmojiClick\"><div data-action=\"calculateEmojiGridStyle\">${\n map(state.currentEmojisWithCategories, (emojiWithCategory, i) => {\n return html`<div><div id=\"menu-label-${i}\" class=\"category ${state.currentEmojisWithCategories.length === 1 && state.currentEmojisWithCategories[0].category === '' ? 'gone' : ''}\" aria-hidden=\"true\">${\n state.searchMode\n ? state.i18n.searchResultsLabel\n : (\n emojiWithCategory.category\n ? emojiWithCategory.category\n : (\n state.currentEmojisWithCategories.length > 1\n ? state.i18n.categories.custom\n : state.i18n.categories[state.currentGroup.name]\n )\n )\n }</div><div class=\"emoji-menu ${i !== 0 && !state.searchMode && state.currentGroup.id === -1 ? 'visibility-auto' : ''}\" style=\"${`--num-rows: ${Math.ceil(emojiWithCategory.emojis.length / state.numColumns)}`}\" data-action=\"updateOnIntersection\" role=\"${state.searchMode ? 'listbox' : 'menu'}\" aria-labelledby=\"menu-label-${i}\" id=\"${state.searchMode ? 'search-results' : null}\">${\n emojiList(emojiWithCategory.emojis, state.searchMode, /* prefix */ 'emo')\n }</div></div>`\n }, emojiWithCategory => emojiWithCategory.category)\n }</div></div><div class=\"favorites onscreen emoji-menu ${state.message ? 'gone' : ''}\" role=\"menu\" aria-label=\"${state.i18n.favoritesLabel}\" data-on-click=\"onEmojiClick\">${\n emojiList(state.currentFavorites, /* searchMode */ false, /* prefix */ 'fav')\n }</div><button data-ref=\"baselineEmoji\" aria-hidden=\"true\" tabindex=\"-1\" class=\"abs-pos hidden emoji baseline-emoji\">😀</button></section>`\n };\n\n const rootDom = section();\n\n // helper for traversing the dom, finding elements by an attribute, and getting the attribute value\n const forElementWithAttribute = (attributeName, callback) => {\n for (const element of container.querySelectorAll(`[${attributeName}]`)) {\n callback(element, element.getAttribute(attributeName));\n }\n };\n\n if (firstRender) { // not a re-render\n container.appendChild(rootDom);\n\n // we only bind events/refs once - there is no need to find them again given this component structure\n\n // bind events\n for (const eventName of ['click', 'focusout', 'input', 'keydown', 'keyup']) {\n forElementWithAttribute(`data-on-${eventName}`, (element, listenerName) => {\n element.addEventListener(eventName, events[listenerName]);\n });\n }\n\n // find refs\n forElementWithAttribute('data-ref', (element, ref) => {\n refs[ref] = element;\n });\n\n // destroy/abort logic\n abortSignal.addEventListener('abort', () => {\n container.removeChild(rootDom);\n });\n }\n\n // set up actions - these are re-bound on every render\n forElementWithAttribute('data-action', (element, action) => {\n let boundActions = actionContext.get(action);\n if (!boundActions) {\n actionContext.set(action, (boundActions = new WeakSet()));\n }\n\n // avoid applying the same action to the same element multiple times\n if (!boundActions.has(element)) {\n boundActions.add(element);\n actions[action](element);\n }\n });\n}\n\n/* istanbul ignore next */\nconst qM = typeof queueMicrotask === 'function' ? queueMicrotask : callback => Promise.resolve().then(callback);\n\nfunction createState (abortSignal) {\n let destroyed = false;\n let currentObserver;\n\n const propsToObservers = new Map();\n const dirtyObservers = new Set();\n\n let queued;\n\n const flush = () => {\n if (destroyed) {\n return\n }\n const observersToRun = [...dirtyObservers];\n dirtyObservers.clear(); // clear before running to force any new updates to run in another tick of the loop\n try {\n for (const observer of observersToRun) {\n observer();\n }\n } finally {\n queued = false;\n if (dirtyObservers.size) { // new updates, queue another one\n queued = true;\n qM(flush);\n }\n }\n };\n\n const state = new Proxy({}, {\n get (target, prop) {\n if (currentObserver) {\n let observers = propsToObservers.get(prop);\n if (!observers) {\n observers = new Set();\n propsToObservers.set(prop, observers);\n }\n observers.add(currentObserver);\n }\n return target[prop]\n },\n set (target, prop, newValue) {\n if (target[prop] !== newValue) {\n target[prop] = newValue;\n const observers = propsToObservers.get(prop);\n if (observers) {\n for (const observer of observers) {\n dirtyObservers.add(observer);\n }\n if (!queued) {\n queued = true;\n qM(flush);\n }\n }\n }\n return true\n }\n });\n\n const createEffect = (callback) => {\n const runnable = () => {\n const oldObserver = currentObserver;\n currentObserver = runnable;\n try {\n return callback()\n } finally {\n currentObserver = oldObserver;\n }\n };\n return runnable()\n };\n\n // destroy logic\n abortSignal.addEventListener('abort', () => {\n destroyed = true;\n });\n\n return {\n state,\n createEffect\n }\n}\n\n// Compare two arrays, with a function called on each item in the two arrays that returns true if the items are equal\nfunction arraysAreEqualByFunction (left, right, areEqualFunc) {\n if (left.length !== right.length) {\n return false\n }\n for (let i = 0; i < left.length; i++) {\n if (!areEqualFunc(left[i], right[i])) {\n return false\n }\n }\n return true\n}\n\nconst intersectionObserverCache = new WeakMap();\n\nfunction intersectionObserverAction (node, abortSignal, listener) {\n /* istanbul ignore else */\n {\n // The scroll root is always `.tabpanel`\n const root = node.closest('.tabpanel');\n\n let observer = intersectionObserverCache.get(root);\n if (!observer) {\n // TODO: replace this with the contentvisibilityautostatechange event when all supported browsers support it.\n // For now we use IntersectionObserver because it has better cross-browser support, and it would be bad for\n // old Safari versions if they eagerly downloaded all custom emoji all at once.\n observer = new IntersectionObserver(listener, {\n root,\n // trigger if we are 1/2 scroll container height away so that the images load a bit quicker while scrolling\n rootMargin: '50% 0px 50% 0px',\n // trigger if any part of the emoji grid is intersecting\n threshold: 0\n });\n\n // avoid creating a new IntersectionObserver for every category; just use one for the whole root\n intersectionObserverCache.set(root, observer);\n\n // assume that the abortSignal is always the same for this root node; just add one event listener\n abortSignal.addEventListener('abort', () => {\n observer.disconnect();\n });\n }\n\n observer.observe(node);\n }\n}\n\n/* eslint-disable prefer-const,no-labels,no-inner-declarations */\n\n// constants\nconst EMPTY_ARRAY = [];\n\nconst { assign } = Object;\n\nfunction createRoot (shadowRoot, props) {\n const refs = {};\n const abortController = new AbortController();\n const abortSignal = abortController.signal;\n const { state, createEffect } = createState(abortSignal);\n const actionContext = new Map();\n\n // initial state\n assign(state, {\n skinToneEmoji: undefined,\n i18n: undefined,\n database: undefined,\n customEmoji: undefined,\n customCategorySorting: undefined,\n emojiVersion: undefined\n });\n\n // public props\n assign(state, props);\n\n // private props\n assign(state, {\n initialLoad: true,\n currentEmojis: [],\n currentEmojisWithCategories: [],\n rawSearchText: '',\n searchText: '',\n searchMode: false,\n activeSearchItem: -1,\n message: undefined,\n skinTonePickerExpanded: false,\n skinTonePickerExpandedAfterAnimation: false,\n currentSkinTone: 0,\n activeSkinTone: 0,\n skinToneButtonText: undefined,\n pickerStyle: undefined,\n skinToneButtonLabel: '',\n skinTones: [],\n currentFavorites: [],\n defaultFavoriteEmojis: undefined,\n numColumns: DEFAULT_NUM_COLUMNS,\n isRtl: false,\n currentGroupIndex: 0,\n groups: groups,\n databaseLoaded: false,\n activeSearchItemId: undefined\n });\n\n //\n // Update the current group based on the currentGroupIndex\n //\n createEffect(() => {\n if (state.currentGroup !== state.groups[state.currentGroupIndex]) {\n state.currentGroup = state.groups[state.currentGroupIndex];\n }\n });\n\n //\n // Utils/helpers\n //\n\n const focus = id => {\n shadowRoot.getElementById(id).focus();\n };\n\n const emojiToDomNode = emoji => shadowRoot.getElementById(`emo-${emoji.id}`);\n\n // fire a custom event that crosses the shadow boundary\n const fireEvent = (name, detail) => {\n refs.rootElement.dispatchEvent(new CustomEvent(name, {\n detail,\n bubbles: true,\n composed: true\n }));\n };\n\n //\n // Comparison utils\n //\n\n const compareEmojiArrays = (a, b) => a.id === b.id;\n\n const compareCurrentEmojisWithCategories = (a, b) => {\n const { category: aCategory, emojis: aEmojis } = a;\n const { category: bCategory, emojis: bEmojis } = b;\n\n if (aCategory !== bCategory) {\n return false\n }\n\n return arraysAreEqualByFunction(aEmojis, bEmojis, compareEmojiArrays)\n };\n\n //\n // Update utils to avoid excessive re-renders\n //\n\n // avoid excessive re-renders by checking the value before setting\n const updateCurrentEmojis = (newEmojis) => {\n if (!arraysAreEqualByFunction(state.currentEmojis, newEmojis, compareEmojiArrays)) {\n state.currentEmojis = newEmojis;\n }\n };\n\n // avoid excessive re-renders\n const updateSearchMode = (newSearchMode) => {\n if (state.searchMode !== newSearchMode) {\n state.searchMode = newSearchMode;\n }\n };\n\n // avoid excessive re-renders\n const updateCurrentEmojisWithCategories = (newEmojisWithCategories) => {\n if (!arraysAreEqualByFunction(state.currentEmojisWithCategories, newEmojisWithCategories, compareCurrentEmojisWithCategories)) {\n state.currentEmojisWithCategories = newEmojisWithCategories;\n }\n };\n\n // Helpers used by PickerTemplate\n\n const unicodeWithSkin = (emoji, currentSkinTone) => (\n (currentSkinTone && emoji.skins && emoji.skins[currentSkinTone]) || emoji.unicode\n );\n\n const labelWithSkin = (emoji, currentSkinTone) => (\n uniq([\n (emoji.name || unicodeWithSkin(emoji, currentSkinTone)),\n emoji.annotation,\n ...(emoji.shortcodes || EMPTY_ARRAY)\n ].filter(Boolean)).join(', ')\n );\n\n const titleForEmoji = (emoji) => (\n emoji.annotation || (emoji.shortcodes || EMPTY_ARRAY).join(', ')\n );\n\n const helpers = {\n labelWithSkin, titleForEmoji, unicodeWithSkin\n };\n const events = {\n onClickSkinToneButton,\n onEmojiClick,\n onNavClick,\n onNavKeydown,\n onSearchKeydown,\n onSkinToneOptionsClick,\n onSkinToneOptionsFocusOut,\n onSkinToneOptionsKeydown,\n onSkinToneOptionsKeyup,\n onSearchInput\n };\n const actions = {\n calculateEmojiGridStyle,\n updateOnIntersection\n };\n\n let firstRender = true;\n createEffect(() => {\n render(shadowRoot, state, helpers, events, actions, refs, abortSignal, actionContext, firstRender);\n firstRender = false;\n });\n\n //\n // Determine the emoji support level (in requestIdleCallback)\n //\n\n // mount logic\n if (!state.emojiVersion) {\n detectEmojiSupportLevel().then(level => {\n // Can't actually test emoji support in Jest/Vitest/JSDom, emoji never render in color in Cairo\n /* istanbul ignore next */\n if (!level) {\n state.message = state.i18n.emojiUnsupportedMessage;\n }\n });\n }\n\n //\n // Set or update the database object\n //\n\n createEffect(() => {\n // show a Loading message if it takes a long time, or show an error if there's a network/IDB error\n async function handleDatabaseLoading () {\n let showingLoadingMessage = false;\n const timeoutHandle = setTimeout(() => {\n showingLoadingMessage = true;\n state.message = state.i18n.loadingMessage;\n }, TIMEOUT_BEFORE_LOADING_MESSAGE);\n try {\n await state.database.ready();\n state.databaseLoaded = true; // eslint-disable-line no-unused-vars\n } catch (err) {\n console.error(err);\n state.message = state.i18n.networkErrorMessage;\n } finally {\n clearTimeout(timeoutHandle);\n if (showingLoadingMessage) { // Seems safer than checking the i18n string, which may change\n showingLoadingMessage = false;\n state.message = ''; // eslint-disable-line no-unused-vars\n }\n }\n }\n\n if (state.database) {\n /* no await */\n handleDatabaseLoading();\n }\n });\n\n //\n // Global styles for the entire picker\n //\n\n createEffect(() => {\n state.pickerStyle = `\n --num-groups: ${state.groups.length}; \n --indicator-opacity: ${state.searchMode ? 0 : 1}; \n --num-skintones: ${NUM_SKIN_TONES};`;\n });\n\n //\n // Set or update the customEmoji\n //\n\n createEffect(() => {\n if (state.customEmoji && state.database) {\n updateCustomEmoji(); // re-run whenever customEmoji change\n }\n });\n\n createEffect(() => {\n if (state.customEmoji && state.customEmoji.length) {\n if (state.groups !== allGroups) { // don't update unnecessarily\n state.groups = allGroups;\n }\n } else if (state.groups !== groups) {\n if (state.currentGroupIndex) {\n // If the current group is anything other than \"custom\" (which is first), decrement.\n // This fixes the odd case where you set customEmoji, then pick a category, then unset customEmoji\n state.currentGroupIndex--;\n }\n state.groups = groups;\n }\n });\n\n //\n // Set or update the preferred skin tone\n //\n\n createEffect(() => {\n async function updatePreferredSkinTone () {\n if (state.databaseLoaded) {\n state.currentSkinTone = await state.database.getPreferredSkinTone();\n }\n }\n\n /* no await */ updatePreferredSkinTone();\n });\n\n createEffect(() => {\n state.skinTones = Array(NUM_SKIN_TONES).fill().map((_, i) => applySkinTone(state.skinToneEmoji, i));\n });\n\n createEffect(() => {\n state.skinToneButtonText = state.skinTones[state.currentSkinTone];\n });\n\n createEffect(() => {\n state.skinToneButtonLabel = state.i18n.skinToneLabel.replace('{skinTone}', state.i18n.skinTones[state.currentSkinTone]);\n });\n\n //\n // Set or update the favorites emojis\n //\n\n createEffect(() => {\n async function updateDefaultFavoriteEmojis () {\n const { database } = state;\n const favs = (await Promise.all(MOST_COMMONLY_USED_EMOJI.map(unicode => (\n database.getEmojiByUnicodeOrName(unicode)\n )))).filter(Boolean); // filter because in Jest/Vitest tests we don't have all the emoji in the DB\n state.defaultFavoriteEmojis = favs;\n }\n\n if (state.databaseLoaded) {\n /* no await */ updateDefaultFavoriteEmojis();\n }\n });\n\n function updateCustomEmoji () {\n // Certain effects have an implicit dependency on customEmoji since it affects the database\n // Getting it here on the state ensures this effect re-runs when customEmoji change.\n const { customEmoji, database } = state;\n const databaseCustomEmoji = customEmoji || EMPTY_ARRAY;\n if (database.customEmoji !== databaseCustomEmoji) {\n // Avoid setting this if the customEmoji have _not_ changed, because the setter triggers a re-computation of the\n // `customEmojiIndex`. Note we don't bother with deep object changes.\n database.customEmoji = databaseCustomEmoji;\n }\n }\n\n createEffect(() => {\n async function updateFavorites () {\n updateCustomEmoji(); // re-run whenever customEmoji change\n const { database, defaultFavoriteEmojis, numColumns } = state;\n const dbFavorites = await database.getTopFavoriteEmoji(numColumns);\n const favorites = await summarizeEmojis(uniqBy([\n ...dbFavorites,\n ...defaultFavoriteEmojis\n ], _ => (_.unicode || _.name)).slice(0, numColumns));\n state.currentFavorites = favorites;\n }\n\n if (state.databaseLoaded && state.defaultFavoriteEmojis) {\n /* no await */ updateFavorites();\n }\n });\n\n //\n // Re-run whenever the emoji grid changes size, and re-calc style/layout-related state variables:\n // 1) Re-calculate the --num-columns var because it may have changed\n // 2) Re-calculate whether we're in RTL mode or not.\n //\n // The benefit of doing this in one place is to align with rAF/ResizeObserver\n // and do all the calculations in one go. RTL vs LTR is not strictly layout-related,\n // but since we're already reading the style here, and since it's already aligned with\n // the rAF loop, this is the most appropriate place to do it perf-wise.\n //\n\n function calculateEmojiGridStyle (node) {\n resizeObserverAction(node, abortSignal, () => {\n /* istanbul ignore next */\n { // jsdom throws errors for this kind of fancy stuff\n // read all the style/layout calculations we need to make\n const style = getComputedStyle(refs.rootElement);\n const newNumColumns = parseInt(style.getPropertyValue('--num-columns'), 10);\n const newIsRtl = style.getPropertyValue('direction') === 'rtl';\n\n // write to state variables\n state.numColumns = newNumColumns;\n state.isRtl = newIsRtl;\n }\n });\n }\n\n // Re-run whenever the custom emoji in a category are shown/hidden. This is an optimization that simulates\n // what we'd get from `<img loading=lazy>` but without rendering an `<img>`.\n function updateOnIntersection (node) {\n intersectionObserverAction(node, abortSignal, (entries) => {\n for (const { target, isIntersecting } of entries) {\n target.classList.toggle('onscreen', isIntersecting);\n }\n });\n }\n\n //\n // Set or update the currentEmojis. Check for invalid ZWJ renderings\n // (i.e. double emoji).\n //\n\n createEffect(() => {\n async function updateEmojis () {\n const { searchText, currentGroup, databaseLoaded, customEmoji } = state;\n if (!databaseLoaded) {\n state.currentEmojis = [];\n state.searchMode = false;\n } else if (searchText.length >= MIN_SEARCH_TEXT_LENGTH) {\n const newEmojis = await getEmojisBySearchQuery(searchText);\n if (state.searchText === searchText) { // if the situation changes asynchronously, do not update\n updateCurrentEmojis(newEmojis);\n updateSearchMode(true);\n }\n } else { // database is loaded and we're not in search mode, so we're in normal category mode\n const { id: currentGroupId } = currentGroup;\n // avoid race condition where currentGroupId is -1 and customEmoji is undefined/empty\n if (currentGroupId !== -1 || (customEmoji && customEmoji.length)) {\n const newEmojis = await getEmojisByGroup(currentGroupId);\n if (state.currentGroup.id === currentGroupId) { // if the situation changes asynchronously, do not update\n updateCurrentEmojis(newEmojis);\n updateSearchMode(false);\n }\n }\n }\n }\n\n /* no await */ updateEmojis();\n });\n\n const resetScrollTopInRaf = () => {\n rAF(() => resetScrollTopIfPossible(refs.tabpanelElement));\n };\n\n // Some emojis have their ligatures rendered as two or more consecutive emojis\n // We want to treat these the same as unsupported emojis, so we compare their\n // widths against the baseline widths and remove them as necessary\n createEffect(() => {\n const { currentEmojis, emojiVersion } = state;\n const zwjEmojisToCheck = currentEmojis\n .filter(emoji => emoji.unicode) // filter custom emoji\n .filter(emoji => hasZwj(emoji) && !supportedZwjEmojis.has(emoji.unicode));\n if (!emojiVersion && zwjEmojisToCheck.length) {\n // render now, check their length later\n updateCurrentEmojis(currentEmojis);\n rAF(() => checkZwjSupportAndUpdate(zwjEmojisToCheck));\n } else {\n const newEmojis = emojiVersion ? currentEmojis : currentEmojis.filter(isZwjSupported);\n updateCurrentEmojis(newEmojis);\n // Reset scroll top to 0 when emojis change\n resetScrollTopInRaf();\n }\n });\n\n function checkZwjSupportAndUpdate (zwjEmojisToCheck) {\n const allSupported = checkZwjSupport(zwjEmojisToCheck, refs.baselineEmoji, emojiToDomNode);\n if (allSupported) {\n // Even if all emoji are supported, we still need to reset the scroll top to 0 when emojis change\n resetScrollTopInRaf();\n } else {\n // Force update. We only do this if there are any unsupported ZWJ characters since otherwise,\n // for browsers that support all emoji, it would be an unnecessary extra re-render.\n state.currentEmojis = [...state.currentEmojis];\n }\n }\n\n function isZwjSupported (emoji) {\n return !emoji.unicode || !hasZwj(emoji) || supportedZwjEmojis.get(emoji.unicode)\n }\n\n async function filterEmojisByVersion (emojis) {\n const emojiSupportLevel = state.emojiVersion || await detectEmojiSupportLevel();\n // !version corresponds to custom emoji\n return emojis.filter(({ version }) => !version || version <= emojiSupportLevel)\n }\n\n async function summarizeEmojis (emojis) {\n return summarizeEmojisForUI(emojis, state.emojiVersion || await detectEmojiSupportLevel())\n }\n\n async function getEmojisByGroup (group) {\n // -1 is custom emoji\n const emoji = group === -1 ? state.customEmoji : await state.database.getEmojiByGroup(group);\n return summarizeEmojis(await filterEmojisByVersion(emoji))\n }\n\n async function getEmojisBySearchQuery (query) {\n return summarizeEmojis(await filterEmojisByVersion(await state.database.getEmojiBySearchQuery(query)))\n }\n\n createEffect(() => {\n });\n\n //\n // Derive currentEmojisWithCategories from currentEmojis. This is always done even if there\n // are no categories, because it's just easier to code the HTML this way.\n //\n\n createEffect(() => {\n function calculateCurrentEmojisWithCategories () {\n const { searchMode, currentEmojis } = state;\n if (searchMode) {\n return [\n {\n category: '',\n emojis: currentEmojis\n }\n ]\n }\n const categoriesToEmoji = new Map();\n for (const emoji of currentEmojis) {\n const category = emoji.category || '';\n let emojis = categoriesToEmoji.get(category);\n if (!emojis) {\n emojis = [];\n categoriesToEmoji.set(category, emojis);\n }\n emojis.push(emoji);\n }\n return [...categoriesToEmoji.entries()]\n .map(([category, emojis]) => ({ category, emojis }))\n .sort((a, b) => state.customCategorySorting(a.category, b.category))\n }\n\n const newEmojisWithCategories = calculateCurrentEmojisWithCategories();\n updateCurrentEmojisWithCategories(newEmojisWithCategories);\n });\n\n //\n // Handle active search item (i.e. pressing up or down while searching)\n //\n\n createEffect(() => {\n state.activeSearchItemId = state.activeSearchItem !== -1 && state.currentEmojis[state.activeSearchItem].id;\n });\n\n //\n // Handle user input on the search input\n //\n\n createEffect(() => {\n const { rawSearchText } = state;\n rIC(() => {\n state.searchText = (rawSearchText || '').trim(); // defer to avoid input delays, plus we can trim here\n state.activeSearchItem = -1;\n });\n });\n\n function onSearchKeydown (event) {\n if (!state.searchMode || !state.currentEmojis.length) {\n return\n }\n\n const goToNextOrPrevious = (previous) => {\n halt(event);\n state.activeSearchItem = incrementOrDecrement(previous, state.activeSearchItem, state.currentEmojis);\n };\n\n switch (event.key) {\n case 'ArrowDown':\n return goToNextOrPrevious(false)\n case 'ArrowUp':\n return goToNextOrPrevious(true)\n case 'Enter':\n if (state.activeSearchItem === -1) {\n // focus the first option in the list since the list must be non-empty at this point (it's verified above)\n state.activeSearchItem = 0;\n } else { // there is already an active search item\n halt(event);\n return clickEmoji(state.currentEmojis[state.activeSearchItem].id)\n }\n }\n }\n\n //\n // Handle user input on nav\n //\n\n function onNavClick (event) {\n const { target } = event;\n const closestTarget = target.closest('.nav-button');\n /* istanbul ignore if */\n if (!closestTarget) {\n return // This should never happen, but makes me nervous not to have it\n }\n const groupId = parseInt(closestTarget.dataset.groupId, 10);\n refs.searchElement.value = ''; // clear search box input\n state.rawSearchText = '';\n state.searchText = '';\n state.activeSearchItem = -1;\n state.currentGroupIndex = state.groups.findIndex(_ => _.id === groupId);\n }\n\n function onNavKeydown (event) {\n const { target, key } = event;\n\n const doFocus = el => {\n if (el) {\n halt(event);\n el.focus();\n }\n };\n\n switch (key) {\n case 'ArrowLeft':\n return doFocus(target.previousElementSibling)\n case 'ArrowRight':\n return doFocus(target.nextElementSibling)\n case 'Home':\n return doFocus(target.parentElement.firstElementChild)\n case 'End':\n return doFocus(target.parentElement.lastElementChild)\n }\n }\n\n async function getDetailForClickEvent (unicodeOrName) {\n const emoji = await state.database.getEmojiByUnicodeOrName(unicodeOrName);\n const emojiSummary = [...state.currentEmojis, ...state.currentFavorites]\n .find(_ => (_.id === unicodeOrName));\n const skinTonedUnicode = emojiSummary.unicode && unicodeWithSkin(emojiSummary, state.currentSkinTone);\n await state.database.incrementFavoriteEmojiCount(unicodeOrName);\n return {\n emoji,\n skinTone: state.currentSkinTone,\n ...(skinTonedUnicode && { unicode: skinTonedUnicode }),\n ...(emojiSummary.name && { name: emojiSummary.name })\n }\n }\n\n //\n // Handle user input on an emoji\n //\n async function clickEmoji (unicodeOrName) {\n const promiseForDetail = getDetailForClickEvent(unicodeOrName);\n // sync event to work around a safari bug: https://bugs.webkit.org/show_bug.cgi?id=222262\n fireEvent('emoji-click-sync', promiseForDetail);\n // async event for most normal use cases that don't need to work around the safari bug\n fireEvent('emoji-click', await promiseForDetail);\n }\n\n function onEmojiClick (event) {\n const { target } = event;\n /* istanbul ignore if */\n if (!target.classList.contains('emoji')) {\n // This should never happen, but makes me nervous not to have it\n return\n }\n halt(event);\n const id = target.id.substring(4); // replace 'emo-' or 'fav-' prefix\n\n /* no await */ clickEmoji(id);\n }\n\n //\n // Handle user input on the skintone picker\n //\n\n function changeSkinTone (skinTone) {\n state.currentSkinTone = skinTone;\n state.skinTonePickerExpanded = false;\n focus('skintone-button');\n fireEvent('skin-tone-change', { skinTone });\n /* no await */ state.database.setPreferredSkinTone(skinTone);\n }\n\n function onSkinToneOptionsClick (event) {\n const { target: { id } } = event;\n const match = id && id.match(/^skintone-(\\d)/); // skintone option format\n /* istanbul ignore if */\n if (!match) { // not a skintone option\n return // This should never happen, but makes me nervous not to have it\n }\n halt(event);\n const skinTone = parseInt(match[1], 10); // remove 'skintone-' prefix\n changeSkinTone(skinTone);\n }\n\n function onClickSkinToneButton (event) {\n state.skinTonePickerExpanded = !state.skinTonePickerExpanded;\n state.activeSkinTone = state.currentSkinTone;\n // this should always be true, since the button is obscured by the listbox, so this `if` is just to be sure\n if (state.skinTonePickerExpanded) {\n halt(event);\n rAF(() => focus('skintone-list'));\n }\n }\n\n // To make the animation nicer, change the z-index of the skintone picker button\n // *after* the animation has played. This makes it appear that the picker box\n // is expanding \"below\" the button\n createEffect(() => {\n if (state.skinTonePickerExpanded) {\n refs.skinToneDropdown.addEventListener('transitionend', () => {\n state.skinTonePickerExpandedAfterAnimation = true; // eslint-disable-line no-unused-vars\n }, { once: true });\n } else {\n state.skinTonePickerExpandedAfterAnimation = false; // eslint-disable-line no-unused-vars\n }\n });\n\n function onSkinToneOptionsKeydown (event) {\n // this should never happen, but makes me nervous not to have it\n /* istanbul ignore if */\n if (!state.skinTonePickerExpanded) {\n return\n }\n const changeActiveSkinTone = async nextSkinTone => {\n halt(event);\n state.activeSkinTone = nextSkinTone;\n };\n\n switch (event.key) {\n case 'ArrowUp':\n return changeActiveSkinTone(incrementOrDecrement(true, state.activeSkinTone, state.skinTones))\n case 'ArrowDown':\n return changeActiveSkinTone(incrementOrDecrement(false, state.activeSkinTone, state.skinTones))\n case 'Home':\n return changeActiveSkinTone(0)\n case 'End':\n return changeActiveSkinTone(state.skinTones.length - 1)\n case 'Enter':\n // enter on keydown, space on keyup. this is just how browsers work for buttons\n // https://lists.w3.org/Archives/Public/w3c-wai-ig/2019JanMar/0086.html\n halt(event);\n return changeSkinTone(state.activeSkinTone)\n case 'Escape':\n halt(event);\n state.skinTonePickerExpanded = false;\n return focus('skintone-button')\n }\n }\n\n function onSkinToneOptionsKeyup (event) {\n // this should never happen, but makes me nervous not to have it\n /* istanbul ignore if */\n if (!state.skinTonePickerExpanded) {\n return\n }\n switch (event.key) {\n case ' ':\n // enter on keydown, space on keyup. this is just how browsers work for buttons\n // https://lists.w3.org/Archives/Public/w3c-wai-ig/2019JanMar/0086.html\n halt(event);\n return changeSkinTone(state.activeSkinTone)\n }\n }\n\n async function onSkinToneOptionsFocusOut (event) {\n // On blur outside of the skintone listbox, collapse the skintone picker.\n const { relatedTarget } = event;\n // The `else` should never happen, but makes me nervous not to have it\n /* istanbul ignore else */\n if (!relatedTarget || relatedTarget.id !== 'skintone-list') {\n state.skinTonePickerExpanded = false;\n }\n }\n\n function onSearchInput (event) {\n state.rawSearchText = event.target.value;\n }\n\n return {\n $set (newState) {\n assign(state, newState);\n },\n $destroy () {\n abortController.abort();\n }\n }\n}\n\nconst DEFAULT_DATA_SOURCE = 'https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/en/emojibase/data.json';\nconst DEFAULT_LOCALE = 'en';\n\nvar enI18n = {\n categoriesLabel: 'Categories',\n emojiUnsupportedMessage: 'Your browser does not support color emoji.',\n favoritesLabel: 'Favorites',\n loadingMessage: 'Loading…',\n networkErrorMessage: 'Could not load emoji.',\n regionLabel: 'Emoji picker',\n searchDescription: 'When search results are available, press up or down to select and enter to choose.',\n searchLabel: 'Search',\n searchResultsLabel: 'Search results',\n skinToneDescription: 'When expanded, press up or down to select and enter to choose.',\n skinToneLabel: 'Choose a skin tone (currently {skinTone})',\n skinTonesLabel: 'Skin tones',\n skinTones: [\n 'Default',\n 'Light',\n 'Medium-Light',\n 'Medium',\n 'Medium-Dark',\n 'Dark'\n ],\n categories: {\n custom: 'Custom',\n 'smileys-emotion': 'Smileys and emoticons',\n 'people-body': 'People and body',\n 'animals-nature': 'Animals and nature',\n 'food-drink': 'Food and drink',\n 'travel-places': 'Travel and places',\n activities: 'Activities',\n objects: 'Objects',\n symbols: 'Symbols',\n flags: 'Flags'\n }\n};\n\nvar baseStyles = \":host{--emoji-size:1.375rem;--emoji-padding:0.5rem;--category-emoji-size:var(--emoji-size);--category-emoji-padding:var(--emoji-padding);--indicator-height:3px;--input-border-radius:0.5rem;--input-border-size:1px;--input-font-size:1rem;--input-line-height:1.5;--input-padding:0.25rem;--num-columns:8;--outline-size:2px;--border-size:1px;--border-radius:0;--skintone-border-radius:1rem;--category-font-size:1rem;display:flex;width:min-content;height:400px}:host,:host(.light){color-scheme:light;--background:#fff;--border-color:#e0e0e0;--indicator-color:#385ac1;--input-border-color:#999;--input-font-color:#111;--input-placeholder-color:#999;--outline-color:#999;--category-font-color:#111;--button-active-background:#e6e6e6;--button-hover-background:#d9d9d9}:host(.dark){color-scheme:dark;--background:#222;--border-color:#444;--indicator-color:#5373ec;--input-border-color:#ccc;--input-font-color:#efefef;--input-placeholder-color:#ccc;--outline-color:#fff;--category-font-color:#efefef;--button-active-background:#555555;--button-hover-background:#484848}@media (prefers-color-scheme:dark){:host{color-scheme:dark;--background:#222;--border-color:#444;--indicator-color:#5373ec;--input-border-color:#ccc;--input-font-color:#efefef;--input-placeholder-color:#ccc;--outline-color:#fff;--category-font-color:#efefef;--button-active-background:#555555;--button-hover-background:#484848}}:host([hidden]){display:none}button{margin:0;padding:0;border:0;background:0 0;box-shadow:none;-webkit-tap-highlight-color:transparent}button::-moz-focus-inner{border:0}input{padding:0;margin:0;line-height:1.15;font-family:inherit}input[type=search]{-webkit-appearance:none}:focus{outline:var(--outline-color) solid var(--outline-size);outline-offset:calc(-1*var(--outline-size))}:host([data-js-focus-visible]) :focus:not([data-focus-visible-added]){outline:0}:focus:not(:focus-visible){outline:0}.hide-focus{outline:0}*{box-sizing:border-box}.picker{contain:content;display:flex;flex-direction:column;background:var(--background);border:var(--border-size) solid var(--border-color);border-radius:var(--border-radius);width:100%;height:100%;overflow:hidden;--total-emoji-size:calc(var(--emoji-size) + (2 * var(--emoji-padding)));--total-category-emoji-size:calc(var(--category-emoji-size) + (2 * var(--category-emoji-padding)))}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.hidden{opacity:0;pointer-events:none}.abs-pos{position:absolute;left:0;top:0}.gone{display:none!important}.skintone-button-wrapper,.skintone-list{background:var(--background);z-index:3}.skintone-button-wrapper.expanded{z-index:1}.skintone-list{position:absolute;inset-inline-end:0;top:0;z-index:2;overflow:visible;border-bottom:var(--border-size) solid var(--border-color);border-radius:0 0 var(--skintone-border-radius) var(--skintone-border-radius);will-change:transform;transition:transform .2s ease-in-out;transform-origin:center 0}@media (prefers-reduced-motion:reduce){.skintone-list{transition-duration:.001s}}@supports not (inset-inline-end:0){.skintone-list{right:0}}.skintone-list.no-animate{transition:none}.tabpanel{overflow-y:auto;scrollbar-gutter:stable;-webkit-overflow-scrolling:touch;will-change:transform;min-height:0;flex:1;contain:content}.emoji-menu{display:grid;grid-template-columns:repeat(var(--num-columns),var(--total-emoji-size));justify-content:space-around;align-items:flex-start;width:100%}.emoji-menu.visibility-auto{content-visibility:auto;contain-intrinsic-size:calc(var(--num-columns)*var(--total-emoji-size)) calc(var(--num-rows)*var(--total-emoji-size))}.category{padding:var(--emoji-padding);font-size:var(--category-font-size);color:var(--category-font-color)}.emoji,button.emoji{font-size:var(--emoji-size);display:flex;align-items:center;justify-content:center;border-radius:100%;height:var(--total-emoji-size);width:var(--total-emoji-size);line-height:1;overflow:hidden;font-family:var(--emoji-font-family);cursor:pointer}@media (hover:hover) and (pointer:fine){.emoji:hover,button.emoji:hover{background:var(--button-hover-background)}}.emoji.active,.emoji:active,button.emoji.active,button.emoji:active{background:var(--button-active-background)}.onscreen .custom-emoji::after{content:\\\"\\\";width:var(--emoji-size);height:var(--emoji-size);background-repeat:no-repeat;background-position:center center;background-size:contain;background-image:var(--custom-emoji-background)}.nav,.nav-button{align-items:center}.nav{display:grid;justify-content:space-between;contain:content}.nav-button{display:flex;justify-content:center}.nav-emoji{font-size:var(--category-emoji-size);width:var(--total-category-emoji-size);height:var(--total-category-emoji-size)}.indicator-wrapper{display:flex;border-bottom:1px solid var(--border-color)}.indicator{width:calc(100%/var(--num-groups));height:var(--indicator-height);opacity:var(--indicator-opacity);background-color:var(--indicator-color);will-change:transform,opacity;transition:opacity .1s linear,transform .25s ease-in-out}@media (prefers-reduced-motion:reduce){.indicator{will-change:opacity;transition:opacity .1s linear}}.pad-top,input.search{background:var(--background);width:100%}.pad-top{height:var(--emoji-padding);z-index:3}.search-row{display:flex;align-items:center;position:relative;padding-inline-start:var(--emoji-padding);padding-bottom:var(--emoji-padding)}.search-wrapper{flex:1;min-width:0}input.search{padding:var(--input-padding);border-radius:var(--input-border-radius);border:var(--input-border-size) solid var(--input-border-color);color:var(--input-font-color);font-size:var(--input-font-size);line-height:var(--input-line-height)}input.search::placeholder{color:var(--input-placeholder-color)}.favorites{overflow-y:auto;scrollbar-gutter:stable;display:flex;flex-direction:row;border-top:var(--border-size) solid var(--border-color);contain:content}.message{padding:var(--emoji-padding)}\";\n\nconst PROPS = [\n 'customEmoji',\n 'customCategorySorting',\n 'database',\n 'dataSource',\n 'i18n',\n 'locale',\n 'skinToneEmoji',\n 'emojiVersion'\n];\n\n// Styles injected ourselves, so we can declare the FONT_FAMILY variable in one place\nconst EXTRA_STYLES = `:host{--emoji-font-family:${FONT_FAMILY}}`;\n\nclass PickerElement extends HTMLElement {\n constructor (props) {\n super();\n this.attachShadow({ mode: 'open' });\n const style = document.createElement('style');\n style.textContent = baseStyles + EXTRA_STYLES;\n this.shadowRoot.appendChild(style);\n this._ctx = {\n // Set defaults\n locale: DEFAULT_LOCALE,\n dataSource: DEFAULT_DATA_SOURCE,\n skinToneEmoji: DEFAULT_SKIN_TONE_EMOJI,\n customCategorySorting: DEFAULT_CATEGORY_SORTING,\n customEmoji: null,\n i18n: enI18n,\n emojiVersion: null,\n ...props\n };\n // Handle properties set before the element was upgraded\n for (const prop of PROPS) {\n if (prop !== 'database' && Object.prototype.hasOwnProperty.call(this, prop)) {\n this._ctx[prop] = this[prop];\n delete this[prop];\n }\n }\n this._dbFlush(); // wait for a flush before creating the db, in case the user calls e.g. a setter or setAttribute\n }\n\n connectedCallback () {\n rescueElementPrototype(this);\n // The _cmp may be defined if the component was immediately disconnected and then reconnected. In that case,\n // do nothing (preserve the state)\n if (!this._cmp) {\n this._cmp = createRoot(this.shadowRoot, this._ctx);\n }\n }\n\n disconnectedCallback () {\n rescueElementPrototype(this);\n // Check in a microtask if the element is still connected. If so, treat this as a \"move\" rather than a disconnect\n // Inspired by Vue: https://vuejs.org/guide/extras/web-components.html#building-custom-elements-with-vue\n qM(() => {\n // this._cmp may be defined if connect-disconnect-connect-disconnect occurs synchronously\n if (!this.isConnected && this._cmp) {\n this._cmp.$destroy();\n this._cmp = undefined;\n\n const { database } = this._ctx;\n database.close()\n // only happens if the database failed to load in the first place, so we don't care\n .catch(err => console.error(err));\n }\n });\n }\n\n static get observedAttributes () {\n return ['locale', 'data-source', 'skin-tone-emoji', 'emoji-version'] // complex objects aren't supported, also use kebab-case\n }\n\n attributeChangedCallback (attrName, oldValue, newValue) {\n this._set(\n // convert from kebab-case to camelcase\n // see https://github.com/sveltejs/svelte/issues/3852#issuecomment-665037015\n attrName.replace(/-([a-z])/g, (_, up) => up.toUpperCase()),\n // convert string attribute to float if necessary\n attrName === 'emoji-version' ? parseFloat(newValue) : newValue\n );\n }\n\n _set (prop, newValue) {\n this._ctx[prop] = newValue;\n if (this._cmp) {\n this._cmp.$set({ [prop]: newValue });\n }\n if (['locale', 'dataSource'].includes(prop)) {\n this._dbFlush();\n }\n }\n\n _dbCreate () {\n const { locale, dataSource, database } = this._ctx;\n // only create a new database if we really need to\n if (!database || database.locale !== locale || database.dataSource !== dataSource) {\n this._set('database', new Database({ locale, dataSource }));\n }\n }\n\n // Update the Database in one microtask if the locale/dataSource change. We do one microtask\n // so we don't create two Databases if e.g. both the locale and the dataSource change\n _dbFlush () {\n qM(() => (\n this._dbCreate()\n ));\n }\n}\n\nconst definitions = {};\n\nfor (const prop of PROPS) {\n definitions[prop] = {\n get () {\n if (prop === 'database') {\n // in rare cases, the microtask may not be flushed yet, so we need to instantiate the DB\n // now if the user is asking for it\n this._dbCreate();\n }\n return this._ctx[prop]\n },\n set (val) {\n if (prop === 'database') {\n throw new Error('database is read-only')\n }\n this._set(prop, val);\n }\n };\n}\n\nObject.defineProperties(PickerElement.prototype, definitions);\n\n// See https://jakearchibald.com/2025/firefox-custom-elements-iframes-bug/\n// TODO: remove when the Firefox bug is fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=1502814\nfunction rescueElementPrototype (element) {\n /* istanbul ignore if */\n if (!(element instanceof PickerElement)) {\n Object.setPrototypeOf(element, customElements.get(element.tagName.toLowerCase()).prototype);\n }\n}\n\n/* istanbul ignore else */\nif (!customElements.get('emoji-picker')) { // if already defined, do nothing (e.g. same script imported twice)\n customElements.define('emoji-picker', PickerElement);\n}\n\nexport { PickerElement as default, rescueElementPrototype };\n","import { html, nothing } from \"lit\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport type { SessionsListResult } from \"../types\";\nimport type { ChatAttachment, ChatQueueItem } from \"../ui-types\";\nimport type { ChatItem, MessageGroup } from \"../types/chat-types\";\nimport { icons } from \"../icons\";\nimport {\n normalizeMessage,\n normalizeRoleForGrouping,\n} from \"../chat/message-normalizer\";\nimport {\n renderInterimGroup,\n renderMessageGroup,\n renderReadingIndicatorGroup,\n renderStreamingGroup,\n} from \"../chat/grouped-render\";\nimport {\n isRecording,\n renderMicButton,\n renderRecordingUI,\n setCallbacks as setVoiceCallbacks,\n} from \"../chat/voice-recorder\";\nimport { renderMarkdownSidebar } from \"./markdown-sidebar\";\nimport \"../components/resizable-divider\";\nimport \"emoji-picker-element\";\n\n/** Auto-grow textarea to fit content, clamped by CSS min/max-height. */\nfunction autoGrow(el: HTMLTextAreaElement): void {\n // Reset to min-height so scrollHeight reflects true content size\n el.style.height = \"0\";\n const desired = Math.max(el.scrollHeight, 44);\n el.style.height = `${desired}px`;\n el.style.overflowY = el.scrollHeight > el.offsetHeight ? \"auto\" : \"hidden\";\n}\n\n/** Reset textarea to single-line height. */\nfunction resetGrow(el: HTMLTextAreaElement): void {\n el.style.height = \"44px\";\n el.style.overflowY = \"hidden\";\n}\n\nexport type CompactionIndicatorStatus = {\n active: boolean;\n startedAt: number | null;\n completedAt: number | null;\n};\n\nexport type ChatProps = {\n sessionKey: string;\n onSessionKeyChange: (next: string) => void;\n showThinking: boolean;\n loading: boolean;\n sending: boolean;\n canAbort?: boolean;\n compactionStatus?: CompactionIndicatorStatus | null;\n messages: unknown[];\n toolMessages: unknown[];\n stream: string | null;\n streamStartedAt: number | null;\n interimText: string | null;\n assistantAvatarUrl?: string | null;\n draft: string;\n queue: ChatQueueItem[];\n connected: boolean;\n canSend: boolean;\n disabledReason: string | null;\n error: string | null;\n sessions: SessionsListResult | null;\n /** When true, hides admin-only UI: model selector, thinking level, verbose/filler controls. */\n publicMode?: boolean;\n // Focus mode\n focusMode: boolean;\n // Sidebar state\n sidebarOpen?: boolean;\n sidebarContent?: string | null;\n sidebarError?: string | null;\n splitRatio?: number;\n assistantName: string;\n assistantAvatar: string | null;\n verboseLevel?: string | null;\n // Image attachments\n attachments?: ChatAttachment[];\n onAttachmentsChange?: (attachments: ChatAttachment[]) => void;\n suggestions?: string[];\n onSuggestionClick?: (text: string) => void;\n // Event handlers\n onRefresh: () => void;\n onToggleFocusMode: () => void;\n onDraftChange: (next: string) => void;\n onSend: () => void;\n onAbort?: () => void;\n onQueueRemove: (id: string) => void;\n onNewSession: () => void;\n onOpenSidebar?: (content: string) => void;\n onCloseSidebar?: () => void;\n onSplitRatioChange?: (ratio: number) => void;\n onChatScroll?: (event: Event) => void;\n nearBottom?: boolean;\n requestUpdate?: () => void;\n // Pagination\n hasMore?: boolean;\n loadingOlder?: boolean;\n onLoadOlder?: () => void;\n};\n\nconst COMPACTION_TOAST_DURATION_MS = 5000;\n\nfunction renderCompactionIndicator(status: CompactionIndicatorStatus | null | undefined) {\n if (!status) return nothing;\n\n // Show \"compacting...\" while active\n if (status.active) {\n return html`\n <div class=\"callout info compaction-indicator compaction-indicator--active\">\n ${icons.loader} Compacting context...\n </div>\n `;\n }\n\n // Show \"compaction complete\" briefly after completion\n if (status.completedAt) {\n const elapsed = Date.now() - status.completedAt;\n if (elapsed < COMPACTION_TOAST_DURATION_MS) {\n return html`\n <div class=\"callout success compaction-indicator compaction-indicator--complete\">\n ${icons.check} Context compacted\n </div>\n `;\n }\n }\n\n return nothing;\n}\n\nconst MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024; // 5 MB — must match server limit\n\nfunction generateAttachmentId(): string {\n return `att-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n}\n\nfunction showAttachmentError(el: HTMLElement, message: string) {\n // Find or create the error toast inside the chat section\n let toast = el.closest(\".chat\")?.querySelector(\".chat-attachment-error\") as HTMLElement | null;\n if (!toast) {\n toast = document.createElement(\"div\");\n toast.className = \"callout danger chat-attachment-error\";\n toast.style.cssText = \"margin: 8px 4px; animation: fade-in 200ms ease-out;\";\n const compose = el.closest(\".chat\")?.querySelector(\".chat-compose\");\n compose?.parentElement?.insertBefore(toast, compose);\n }\n toast.textContent = message;\n setTimeout(() => toast?.remove(), 4000);\n}\n\nconst TEXT_EXTENSIONS = /\\.(md|txt|csv|json|xml|html|css|js|ts|py|sh|yaml|yml|toml|ini|cfg|log|sql)$/i;\n\nfunction isImageFile(file: File): boolean {\n return file.type.startsWith(\"image/\") ||\n /\\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(file.name);\n}\n\nfunction isTextFile(file: File): boolean {\n return file.type.startsWith(\"text/\") ||\n file.type === \"application/json\" ||\n file.type === \"application/xml\" ||\n TEXT_EXTENSIONS.test(file.name);\n}\n\nfunction isPdfFile(file: File): boolean {\n return file.type === \"application/pdf\" || /\\.pdf$/i.test(file.name);\n}\n\nfunction isVideoFile(file: File): boolean {\n return file.type.startsWith(\"video/\") ||\n /\\.(mp4|webm|mov|avi|mkv|m4v)$/i.test(file.name);\n}\n\n/** Process a single File into a ChatAttachment and append it. Shared by drag-drop and file picker. */\nfunction processAttachmentFile(file: File, props: ChatProps) {\n if (!props.onAttachmentsChange) return;\n const errorEl = document.querySelector(\".chat\") as HTMLElement | null;\n\n if (isImageFile(file)) {\n if (file.size > MAX_ATTACHMENT_BYTES) {\n if (errorEl) showAttachmentError(errorEl, `Image too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n return;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const newAtt: ChatAttachment = { id: generateAttachmentId(), dataUrl: reader.result as string, mimeType: file.type };\n props.onAttachmentsChange?.([...(props.attachments ?? []), newAtt]);\n };\n reader.readAsDataURL(file);\n } else if (isTextFile(file)) {\n if (file.size > MAX_ATTACHMENT_BYTES) {\n if (errorEl) showAttachmentError(errorEl, `File too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n return;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const newAtt: ChatAttachment = { id: generateAttachmentId(), dataUrl: \"\", mimeType: file.type || \"text/plain\", fileName: file.name, textContent: reader.result as string };\n props.onAttachmentsChange?.([...(props.attachments ?? []), newAtt]);\n };\n reader.readAsText(file);\n } else if (isPdfFile(file)) {\n if (file.size > MAX_ATTACHMENT_BYTES) {\n if (errorEl) showAttachmentError(errorEl, `PDF too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n return;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const newAtt: ChatAttachment = { id: generateAttachmentId(), dataUrl: reader.result as string, mimeType: \"application/pdf\", fileName: file.name };\n props.onAttachmentsChange?.([...(props.attachments ?? []), newAtt]);\n };\n reader.readAsDataURL(file);\n } else if (isVideoFile(file)) {\n if (file.size > MAX_ATTACHMENT_BYTES) {\n if (errorEl) showAttachmentError(errorEl, `Video too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n return;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const newAtt: ChatAttachment = { id: generateAttachmentId(), dataUrl: reader.result as string, mimeType: file.type || \"video/mp4\", fileName: file.name };\n props.onAttachmentsChange?.([...(props.attachments ?? []), newAtt]);\n };\n reader.readAsDataURL(file);\n } else {\n if (errorEl) showAttachmentError(errorEl, `Unsupported file type: ${file.name}. Use the Files page to upload to workspace.`);\n }\n}\n\nfunction handleDrop(e: DragEvent, props: ChatProps) {\n e.preventDefault();\n e.stopPropagation();\n const target = (e.currentTarget as HTMLElement);\n target.classList.remove(\"chat--dragover\");\n\n const files = e.dataTransfer?.files;\n if (!files || files.length === 0) return;\n\n for (let i = 0; i < files.length; i++) {\n const file = files[i];\n\n if (isImageFile(file)) {\n if (!props.onAttachmentsChange) continue;\n if (file.size > MAX_ATTACHMENT_BYTES) {\n showAttachmentError(target, `Image too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n continue;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const newAttachment: ChatAttachment = {\n id: generateAttachmentId(),\n dataUrl,\n mimeType: file.type,\n };\n const current = props.attachments ?? [];\n props.onAttachmentsChange?.([...current, newAttachment]);\n };\n reader.readAsDataURL(file);\n } else if (isTextFile(file)) {\n if (!props.onAttachmentsChange) continue;\n if (file.size > MAX_ATTACHMENT_BYTES) {\n showAttachmentError(target, `File too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n continue;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const text = reader.result as string;\n const newAttachment: ChatAttachment = {\n id: generateAttachmentId(),\n dataUrl: \"\",\n mimeType: file.type || \"text/plain\",\n fileName: file.name,\n textContent: text,\n };\n const current = props.attachments ?? [];\n props.onAttachmentsChange?.([...current, newAttachment]);\n };\n reader.readAsText(file);\n } else if (isPdfFile(file)) {\n if (!props.onAttachmentsChange) continue;\n if (file.size > MAX_ATTACHMENT_BYTES) {\n showAttachmentError(target, `PDF too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n continue;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const newAttachment: ChatAttachment = {\n id: generateAttachmentId(),\n dataUrl,\n mimeType: \"application/pdf\",\n fileName: file.name,\n };\n const current = props.attachments ?? [];\n props.onAttachmentsChange?.([...current, newAttachment]);\n };\n reader.readAsDataURL(file);\n } else if (isVideoFile(file)) {\n if (!props.onAttachmentsChange) continue;\n if (file.size > MAX_ATTACHMENT_BYTES) {\n showAttachmentError(target, `Video too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n continue;\n }\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const newAttachment: ChatAttachment = {\n id: generateAttachmentId(),\n dataUrl,\n mimeType: file.type || \"video/mp4\",\n fileName: file.name,\n };\n const current = props.attachments ?? [];\n props.onAttachmentsChange?.([...current, newAttachment]);\n };\n reader.readAsDataURL(file);\n } else {\n showAttachmentError(target, `Unsupported file type: ${file.name}. Use the Files page to upload to workspace.`);\n }\n }\n}\n\nfunction handleDragOver(e: DragEvent) {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) e.dataTransfer.dropEffect = \"copy\";\n (e.currentTarget as HTMLElement).classList.add(\"chat--dragover\");\n}\n\nfunction handleDragLeave(e: DragEvent) {\n e.preventDefault();\n e.stopPropagation();\n const container = e.currentTarget as HTMLElement;\n // Only remove class when truly leaving the container, not entering a child\n const related = e.relatedTarget as Node | null;\n if (!related || !container.contains(related)) {\n container.classList.remove(\"chat--dragover\");\n }\n}\n\nfunction handlePaste(\n e: ClipboardEvent,\n props: ChatProps,\n) {\n const items = e.clipboardData?.items;\n if (!items || !props.onAttachmentsChange) return;\n\n const mediaItems: DataTransferItem[] = [];\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (item.type.startsWith(\"image/\") || item.type.startsWith(\"video/\")) {\n mediaItems.push(item);\n }\n }\n\n if (mediaItems.length === 0) return;\n\n e.preventDefault();\n\n for (const item of mediaItems) {\n const file = item.getAsFile();\n if (!file) continue;\n const label = file.type.startsWith(\"video/\") ? \"Video\" : \"Image\";\n if (file.size > MAX_ATTACHMENT_BYTES) {\n const chatEl = (e.target as HTMLElement)?.closest?.(\".chat\") ?? document.querySelector(\".chat\");\n if (chatEl) showAttachmentError(chatEl as HTMLElement, `${label} too large (${(file.size / 1024 / 1024).toFixed(1)} MB). Maximum is 5 MB.`);\n continue;\n }\n\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const isVideo = file.type.startsWith(\"video/\");\n const newAttachment: ChatAttachment = {\n id: generateAttachmentId(),\n dataUrl,\n mimeType: file.type,\n fileName: isVideo ? (file.name || \"video.mp4\") : undefined,\n };\n const current = props.attachments ?? [];\n props.onAttachmentsChange?.([...current, newAttachment]);\n };\n reader.readAsDataURL(file);\n }\n}\n\n/** Toggle emoji picker visibility via DOM class. */\nfunction toggleEmojiPicker(e: Event) {\n const btn = (e.currentTarget as HTMLElement);\n const compose = btn.closest(\".chat-compose\");\n const popup = compose?.querySelector(\".emoji-picker-popup\") as HTMLElement | null;\n if (!popup) return;\n\n const isOpen = popup.classList.toggle(\"active\");\n btn.classList.toggle(\"active\", isOpen);\n\n if (isOpen) {\n // Close on click outside — single-use listener\n const close = (ev: MouseEvent) => {\n if (popup.contains(ev.target as Node) || btn.contains(ev.target as Node)) return;\n popup.classList.remove(\"active\");\n btn.classList.remove(\"active\");\n document.removeEventListener(\"click\", close, true);\n };\n // Delay to avoid the current click immediately closing\n requestAnimationFrame(() => document.addEventListener(\"click\", close, true));\n }\n}\n\n/** Insert selected emoji at textarea cursor position. */\nfunction handleEmojiSelect(e: Event, props: ChatProps) {\n const detail = (e as CustomEvent).detail;\n const unicode: string | undefined = detail?.unicode;\n if (!unicode) return;\n\n const compose = (e.currentTarget as HTMLElement).closest(\".chat-compose\");\n const ta = compose?.querySelector(\"textarea\") as HTMLTextAreaElement | null;\n if (!ta) return;\n\n // Insert at cursor position\n const start = ta.selectionStart ?? props.draft.length;\n const end = ta.selectionEnd ?? start;\n const before = props.draft.slice(0, start);\n const after = props.draft.slice(end);\n props.onDraftChange(before + unicode + after);\n\n // Close picker\n const popup = compose?.querySelector(\".emoji-picker-popup\") as HTMLElement | null;\n const btn = compose?.querySelector(\".chat-compose__emoji\") as HTMLElement | null;\n popup?.classList.remove(\"active\");\n btn?.classList.remove(\"active\");\n\n // Restore focus to textarea after next render\n requestAnimationFrame(() => {\n ta.focus();\n const pos = start + unicode.length;\n ta.setSelectionRange(pos, pos);\n });\n}\n\nfunction renderAttachmentPreview(props: ChatProps) {\n const attachments = props.attachments ?? [];\n if (attachments.length === 0) return nothing;\n\n return html`\n <div class=\"chat-attachments\">\n ${attachments.map(\n (att) => att.fileName\n ? html`\n <div class=\"chat-attachment chat-attachment--file\">\n <span class=\"chat-attachment__icon\">${att.mimeType?.startsWith(\"video/\") ? icons.film : icons.fileText}</span>\n <span class=\"chat-attachment__name\" title=${att.fileName}>${att.fileName}</span>\n <button\n class=\"chat-attachment__remove chat-attachment__remove--file\"\n type=\"button\"\n aria-label=\"Remove attachment\"\n @click=${() => {\n const next = (props.attachments ?? []).filter(\n (a) => a.id !== att.id,\n );\n props.onAttachmentsChange?.(next);\n }}\n >\n ${icons.x}\n </button>\n </div>\n `\n : html`\n <div class=\"chat-attachment\">\n <img\n src=${att.dataUrl}\n alt=\"Attachment preview\"\n class=\"chat-attachment__img\"\n />\n <button\n class=\"chat-attachment__remove\"\n type=\"button\"\n aria-label=\"Remove attachment\"\n @click=${() => {\n const next = (props.attachments ?? []).filter(\n (a) => a.id !== att.id,\n );\n props.onAttachmentsChange?.(next);\n }}\n >\n ${icons.x}\n </button>\n </div>\n `,\n )}\n </div>\n `;\n}\n\nexport function renderChat(props: ChatProps) {\n const canCompose = props.connected;\n const isBusy = props.sending || props.stream !== null;\n const canAbort = Boolean(props.canAbort && props.onAbort);\n const activeSession = props.sessions?.sessions?.find(\n (row) => row.key === props.sessionKey,\n );\n const reasoningLevel = activeSession?.reasoningLevel ?? \"off\";\n const showReasoning = props.showThinking && reasoningLevel !== \"off\";\n const assistantIdentity = {\n name: props.assistantName,\n avatar: props.assistantAvatar ?? props.assistantAvatarUrl ?? null,\n };\n\n const hasAttachments = (props.attachments?.length ?? 0) > 0;\n const composePlaceholder = props.connected\n ? hasAttachments\n ? \"Add a message...\"\n : \"Message...\"\n : \"Connecting…\";\n\n // Wire up voice recorder callbacks\n setVoiceCallbacks({\n onSend: (attachment) => {\n if (props.onAttachmentsChange) {\n props.onAttachmentsChange([...(props.attachments ?? []), attachment]);\n }\n // Auto-send the voice note immediately\n requestAnimationFrame(() => props.onSend());\n },\n onRequestRender: () => {\n props.requestUpdate?.();\n },\n });\n\n const recording = isRecording();\n const showMic = !recording && !props.draft.trim() && !hasAttachments && !isBusy;\n\n const splitRatio = props.splitRatio ?? 0.6;\n const sidebarOpen = Boolean(props.sidebarOpen && props.onCloseSidebar);\n const thread = html`\n <div\n class=\"chat-thread\"\n role=\"log\"\n aria-live=\"polite\"\n @scroll=${props.onChatScroll}\n >\n ${props.hasMore\n ? html`<div class=\"chat-load-more\">\n ${props.loadingOlder\n ? html`<span class=\"chat-load-more__spinner\">${icons.loader}</span> Loading older messages…`\n : html`<button class=\"chat-load-more__btn\" type=\"button\" @click=${props.onLoadOlder}>Load older messages</button>`}\n </div>`\n : nothing}\n ${props.loading ? html`<div class=\"muted\">Loading chat…</div>` : nothing}\n ${repeat(buildChatItems(props), (item) => item.key, (item) => {\n if (item.kind === \"interim\") {\n return renderInterimGroup(item.text);\n }\n\n if (item.kind === \"reading-indicator\") {\n return renderReadingIndicatorGroup(assistantIdentity);\n }\n\n if (item.kind === \"stream\") {\n return renderStreamingGroup(\n item.text,\n item.startedAt,\n props.onOpenSidebar,\n assistantIdentity,\n );\n }\n\n if (item.kind === \"group\") {\n return renderMessageGroup(item, {\n onOpenSidebar: props.onOpenSidebar,\n showReasoning,\n assistantName: props.assistantName,\n assistantAvatar: assistantIdentity.avatar,\n });\n }\n\n return nothing;\n })}\n </div>\n `;\n\n return html`\n <section\n class=\"card chat\"\n @drop=${(e: DragEvent) => handleDrop(e, props)}\n @dragover=${handleDragOver}\n @dragleave=${handleDragLeave}\n >\n ${props.disabledReason\n ? html`<div class=\"callout\">${props.disabledReason}</div>`\n : nothing}\n\n ${props.error\n ? html`<div class=\"callout danger\">${props.error}</div>`\n : nothing}\n\n ${renderCompactionIndicator(props.compactionStatus)}\n\n ${props.focusMode\n ? html`\n <button\n class=\"chat-focus-exit\"\n type=\"button\"\n @click=${props.onToggleFocusMode}\n aria-label=\"Exit focus mode\"\n title=\"Exit focus mode\"\n >\n ${icons.x}\n </button>\n `\n : nothing}\n\n <div\n class=\"chat-split-container ${sidebarOpen ? \"chat-split-container--open\" : \"\"}\"\n >\n <div\n class=\"chat-main\"\n style=\"flex: ${sidebarOpen ? `0 0 ${splitRatio * 100}%` : \"1 1 100%\"}\"\n >\n ${thread}\n ${props.nearBottom === false\n ? html`\n <button\n class=\"chat-scroll-bottom\"\n type=\"button\"\n @click=${(e: Event) => {\n const main = (e.currentTarget as HTMLElement).closest(\".chat-main\");\n const container = main?.querySelector(\".chat-thread\") as HTMLElement | null;\n if (container) {\n container.scrollTo({ top: container.scrollHeight, behavior: \"smooth\" });\n }\n }}\n aria-label=\"Scroll to bottom\"\n title=\"Scroll to bottom\"\n >\n ${icons.chevronDown}\n </button>\n `\n : nothing}\n </div>\n\n ${sidebarOpen\n ? html`\n <resizable-divider\n .splitRatio=${splitRatio}\n @resize=${(e: CustomEvent) =>\n props.onSplitRatioChange?.(e.detail.splitRatio)}\n ></resizable-divider>\n <div class=\"chat-sidebar\">\n ${renderMarkdownSidebar({\n content: props.sidebarContent ?? null,\n error: props.sidebarError ?? null,\n onClose: props.onCloseSidebar!,\n onViewRawText: () => {\n if (!props.sidebarContent || !props.onOpenSidebar) return;\n props.onOpenSidebar(`\\`\\`\\`\\n${props.sidebarContent}\\n\\`\\`\\``);\n },\n })}\n </div>\n `\n : nothing}\n </div>\n\n ${props.suggestions && props.suggestions.length > 0\n ? html`\n <div class=\"chat-suggestions\">\n ${props.suggestions.map(\n (text) => html`\n <button\n class=\"chat-suggestion-chip\"\n type=\"button\"\n @click=${() => props.onSuggestionClick?.(text)}\n >\n ${text}\n </button>\n `,\n )}\n </div>\n `\n : nothing}\n\n <div class=\"chat-compose\">\n ${renderAttachmentPreview(props)}\n ${recording\n ? renderRecordingUI()\n : html`\n <div class=\"chat-compose__row\">\n <button\n class=\"chat-compose__emoji\"\n type=\"button\"\n @click=${toggleEmojiPicker}\n aria-label=\"Emoji\"\n title=\"Emoji\"\n >\n ${icons.smile}\n </button>\n <button\n class=\"chat-compose__attach\"\n type=\"button\"\n @click=${(e: Event) => {\n const input = (e.currentTarget as HTMLElement)\n .closest(\".chat-compose__row\")\n ?.querySelector<HTMLInputElement>(\".chat-compose__file-input\");\n input?.click();\n }}\n aria-label=\"Attach file\"\n title=\"Attach file\"\n >\n ${icons.paperclip}\n </button>\n <input\n class=\"chat-compose__file-input\"\n type=\"file\"\n multiple\n accept=\"image/*,video/*,.pdf,.md,.txt,.csv,.json,.xml,.html,.css,.js,.ts,.py,.sh,.yaml,.yml,.toml,.ini,.cfg,.log,.sql\"\n style=\"display:none\"\n @change=${(e: Event) => {\n const input = e.target as HTMLInputElement;\n const files = input.files;\n if (!files || files.length === 0 || !props.onAttachmentsChange) return;\n for (let i = 0; i < files.length; i++) {\n processAttachmentFile(files[i], props);\n }\n input.value = \"\";\n }}\n />\n <label class=\"field chat-compose__field\">\n <span>Message</span>\n <textarea\n .value=${props.draft}\n ?disabled=${!props.connected}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key !== \"Enter\") return;\n if (e.isComposing || e.keyCode === 229) return;\n if (e.shiftKey) return; // Allow Shift+Enter for line breaks\n if (!props.connected) return;\n e.preventDefault();\n if (canCompose) {\n props.onSend();\n resetGrow(e.target as HTMLTextAreaElement);\n }\n }}\n @input=${(e: Event) => {\n const ta = e.target as HTMLTextAreaElement;\n props.onDraftChange(ta.value);\n autoGrow(ta);\n }}\n @paste=${(e: ClipboardEvent) => handlePaste(e, props)}\n placeholder=${composePlaceholder}\n ></textarea>\n </label>\n ${canAbort\n ? html`\n <button\n class=\"btn btn--icon chat-compose__send\"\n @click=${props.onAbort}\n aria-label=\"Stop\"\n title=\"Stop generating\"\n >\n ${icons.square}\n </button>\n `\n : nothing}\n ${showMic\n ? renderMicButton(props.connected)\n : html`\n <button\n class=\"btn btn--icon chat-compose__send primary\"\n ?disabled=${!props.connected}\n @click=${(e: Event) => {\n props.onSend();\n const ta = (e.target as HTMLElement).closest(\".chat-compose\")?.querySelector(\"textarea\");\n if (ta) resetGrow(ta);\n }}\n aria-label=\"${isBusy ? \"Queue\" : \"Send\"}\"\n title=\"${isBusy ? \"Queue message\" : \"Send (Enter)\"}\"\n >\n ${icons.send}\n </button>`}\n </div>`}\n <div class=\"emoji-picker-popup\">\n <emoji-picker\n @emoji-click=${(e: Event) => handleEmojiSelect(e, props)}\n ></emoji-picker>\n </div>\n </div>\n </section>\n `;\n}\n\nfunction groupMessages(items: ChatItem[]): Array<ChatItem | MessageGroup> {\n return items.map((item) => {\n if (item.kind !== \"message\") return item;\n const normalized = normalizeMessage(item.message);\n const role = normalizeRoleForGrouping(normalized.role);\n const timestamp = normalized.timestamp || Date.now();\n return {\n kind: \"group\" as const,\n key: `group:${role}:${item.key}`,\n role,\n messages: [{ message: item.message, key: item.key }],\n timestamp,\n isStreaming: false,\n };\n });\n}\n\nfunction buildChatItems(props: ChatProps): Array<ChatItem | MessageGroup> {\n const items: ChatItem[] = [];\n const history = Array.isArray(props.messages) ? props.messages : [];\n const tools = Array.isArray(props.toolMessages) ? props.toolMessages : [];\n const showToolDetail = props.showThinking || props.verboseLevel === \"on\" || props.verboseLevel === \"full\";\n for (let i = 0; i < history.length; i++) {\n const msg = history[i];\n const normalized = normalizeMessage(msg);\n\n if (!showToolDetail && normalized.role.toLowerCase() === \"toolresult\") {\n // Tool results with images or files (e.g. image_generate, document_to_pdf)\n // should still render as assistant messages so the user sees them inline.\n const raw = msg as Record<string, unknown>;\n const rawContent = Array.isArray(raw.content) ? raw.content : [];\n const mediaBlocks = rawContent.filter(\n (block: unknown) => {\n const t = (block as Record<string, unknown>).type;\n return t === \"image\" || t === \"file\";\n },\n );\n if (mediaBlocks.length > 0) {\n items.push({\n kind: \"message\",\n key: messageKey(msg, i),\n message: {\n role: \"assistant\",\n content: mediaBlocks,\n timestamp: normalized.timestamp,\n },\n });\n }\n continue;\n }\n\n items.push({\n kind: \"message\",\n key: messageKey(msg, i),\n message: msg,\n });\n }\n if (showToolDetail) {\n for (let i = 0; i < tools.length; i++) {\n items.push({\n kind: \"message\",\n key: messageKey(tools[i], i + history.length),\n message: tools[i],\n });\n }\n }\n\n // Show interim \"thinking\" text (grey italic) while tools are running\n if (props.interimText) {\n items.push({ kind: \"interim\", key: \"interim:thinking\", text: props.interimText });\n }\n\n if (props.stream !== null) {\n const key = `stream:${props.sessionKey}:${props.streamStartedAt ?? \"live\"}`;\n if (props.stream.trim().length > 0) {\n items.push({\n kind: \"stream\",\n key,\n text: props.stream,\n startedAt: props.streamStartedAt ?? Date.now(),\n });\n } else {\n items.push({ kind: \"reading-indicator\", key });\n }\n }\n\n // Render queued messages as normal user bubbles so they appear immediately\n for (const qi of props.queue) {\n const fileNames = qi.attachments?.filter((a) => a.fileName).map((a) => a.fileName) ?? [];\n const displayText = fileNames.length > 0\n ? (qi.text ? `${fileNames.join(\", \")}\\n\\n${qi.text}` : fileNames.join(\", \"))\n : qi.text;\n items.push({\n kind: \"message\",\n key: `queue:${qi.id}`,\n message: {\n role: \"user\",\n content: [{ type: \"text\", text: displayText }],\n timestamp: qi.createdAt,\n },\n });\n }\n\n return groupMessages(items);\n}\n\nfunction messageKey(message: unknown, index: number): string {\n const m = message as Record<string, unknown>;\n const toolCallId = typeof m.toolCallId === \"string\" ? m.toolCallId : \"\";\n if (toolCallId) return `tool:${toolCallId}`;\n const id = typeof m.id === \"string\" ? m.id : \"\";\n if (id) return `msg:${id}`;\n const messageId = typeof m.messageId === \"string\" ? m.messageId : \"\";\n if (messageId) return `msg:${messageId}`;\n const timestamp = typeof m.timestamp === \"number\" ? m.timestamp : null;\n const role = typeof m.role === \"string\" ? m.role : \"unknown\";\n if (timestamp != null) return `msg:${role}:${timestamp}:${index}`;\n return `msg:${role}:${index}`;\n}\n","import { html, nothing, type TemplateResult } from \"lit\";\nimport type { WhatsAppTabState, WhatsAppConversation, WhatsAppGroupInfo, WhatsAppMessage } from \"../controllers/whatsapp.js\";\nimport { icons } from \"../icons.js\";\n\nexport type WhatsAppTabProps = WhatsAppTabState & {\n onSelectConversation: (jid: string) => void;\n onBack: () => void;\n onSearchChange: (query: string) => void;\n onActivationChange: (jid: string, activation: \"always\" | \"mention\" | \"off\") => void;\n onRefresh: () => void;\n requestUpdate: () => void;\n};\n\nfunction formatTimestamp(ts: number): string {\n if (!ts) return \"\";\n const d = new Date(ts * 1000);\n return d.toLocaleDateString([], { year: \"numeric\", month: \"short\", day: \"numeric\" }) +\n \" \" + d.toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\" });\n}\n\nfunction jidToDisplay(jid: string): string {\n return jid.replace(/@s\\.whatsapp\\.net$/, \"\").replace(/@g\\.us$/, \"\");\n}\n\nfunction renderConversationList(props: WhatsAppTabProps): TemplateResult {\n const query = props.searchQuery.toLowerCase();\n const filtered = query\n ? props.conversations.filter((c) => c.name.toLowerCase().includes(query) || c.jid.includes(query))\n : props.conversations;\n\n return html`\n <div class=\"wa-list\">\n <div class=\"wa-list__header\">\n <input\n class=\"wa-list__search\"\n type=\"text\"\n placeholder=\"Search conversations...\"\n .value=${props.searchQuery}\n @input=${(e: Event) => props.onSearchChange((e.target as HTMLInputElement).value)}\n />\n <button class=\"wa-list__refresh\" @click=${props.onRefresh} title=\"Refresh\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"23 4 23 10 17 10\"></polyline><polyline points=\"1 20 1 14 7 14\"></polyline><path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\"></path></svg>\n </button>\n </div>\n <div class=\"wa-list__items\">\n ${props.loading\n ? html`<div class=\"wa-list__empty\">Loading...</div>`\n : filtered.length === 0\n ? html`<div class=\"wa-list__empty\">${props.conversations.length === 0 ? \"No conversations yet\" : \"No matches\"}</div>`\n : filtered.map((c) => renderConversationRow(c, c.jid === props.selectedJid, () => props.onSelectConversation(c.jid)))}\n </div>\n </div>\n `;\n}\n\nfunction renderConversationRow(conv: WhatsAppConversation, selected: boolean, onSelect: () => void): TemplateResult {\n const activationBadge = conv.type === \"group\" && conv.activation\n ? html`<span class=\"wa-badge wa-badge--${conv.activation}\">${conv.activation}</span>`\n : nothing;\n\n return html`\n <button class=\"wa-list__item ${selected ? \"wa-list__item--selected\" : \"\"}\" @click=${onSelect}>\n <span class=\"wa-list__icon ${conv.type === \"group\" ? \"wa-list__icon--group\" : \"\"}\">${conv.type === \"group\" ? icons.users : icons.user}</span>\n <div class=\"wa-list__info\">\n <span class=\"wa-list__name\">${conv.name}</span>\n <span class=\"wa-list__jid\">${jidToDisplay(conv.jid)}</span>\n </div>\n ${activationBadge}\n </button>\n `;\n}\n\nfunction renderConversationHeader(props: WhatsAppTabProps): TemplateResult {\n const conv = props.conversations.find((c) => c.jid === props.selectedJid);\n if (!conv) return html``;\n\n return html`\n <div class=\"wa-header\">\n <button class=\"wa-header__back\" @click=${props.onBack} title=\"Back to conversations\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 18 9 12 15 6\"></polyline></svg>\n </button>\n <div class=\"wa-header__info\">\n <span class=\"wa-header__name\">${conv.name}</span>\n <span class=\"wa-header__jid\">${jidToDisplay(conv.jid)}</span>\n </div>\n </div>\n `;\n}\n\nfunction renderGroupSettings(props: WhatsAppTabProps): TemplateResult {\n const info = props.groupInfo;\n if (!info || !props.selectedJid?.endsWith(\"@g.us\")) return html``;\n\n return html`\n <div class=\"wa-group-settings\">\n <div class=\"wa-group-settings__row\">\n <label class=\"wa-group-settings__label\">Activation</label>\n <select\n class=\"wa-group-settings__select\"\n .value=${info.activation ?? \"mention\"}\n @change=${(e: Event) => props.onActivationChange(props.selectedJid!, (e.target as HTMLSelectElement).value as \"always\" | \"mention\" | \"off\")}\n >\n <option value=\"always\">Always respond</option>\n <option value=\"mention\">Mention only</option>\n <option value=\"off\">Off</option>\n </select>\n </div>\n <div class=\"wa-group-settings__meta\">\n ${info.participants.length} members\n ${info.desc ? html` · ${info.desc}` : nothing}\n </div>\n </div>\n `;\n}\n\nfunction renderMessages(messages: WhatsAppMessage[]): TemplateResult {\n if (messages.length === 0) {\n return html`<div class=\"wa-messages__empty\">No messages available</div>`;\n }\n return html`\n ${messages.map((msg) => html`\n <div class=\"wa-bubble ${msg.fromMe ? \"wa-bubble--me\" : \"\"}\">\n ${!msg.fromMe && msg.senderName ? html`<div class=\"wa-bubble__sender\">${msg.senderName}</div>` : nothing}\n ${msg.quoted ? html`<div class=\"wa-bubble__quoted\">${msg.quoted.body}</div>` : nothing}\n <div class=\"wa-bubble__body\">${msg.body}</div>\n <div class=\"wa-bubble__time\">${formatTimestamp(msg.timestamp)}</div>\n </div>\n `)}\n `;\n}\n\nexport function renderWhatsAppTab(props: WhatsAppTabProps): TemplateResult {\n return html`\n <div class=\"wa-container ${props.selectedJid ? \"wa-container--detail\" : \"\"}\">\n ${renderConversationList(props)}\n <div class=\"wa-view\">\n ${props.selectedJid\n ? html`\n ${renderConversationHeader(props)}\n ${renderGroupSettings(props)}\n <div class=\"wa-messages\">\n ${props.messagesLoading\n ? html`<div class=\"wa-messages__empty\">Loading messages...</div>`\n : renderMessages(props.messages)}\n </div>\n `\n : html`<div class=\"wa-view__empty\">Select a conversation</div>`}\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { ChatProps } from \"./chat\";\nimport { renderChat } from \"./chat\";\nimport { renderPageNav, type WorkspaceNavProps } from \"./page-nav\";\nimport { renderWhatsAppTab, type WhatsAppTabProps } from \"./whatsapp-tab\";\n\nconst externalLinkIcon = html`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\"></path><polyline points=\"15 3 21 3 21 9\"></polyline><line x1=\"10\" y1=\"14\" x2=\"21\" y2=\"3\"></line></svg>`;\n\nexport type ChatPageTab = \"chat\" | \"whatsapp\";\n\nexport type ChatPageProps = ChatProps & {\n /** Whether the WebSocket connection is established. */\n connected: boolean;\n wsProps?: WorkspaceNavProps;\n /** When true, shows a \"Public\" button that opens /public/chat/:accountId in a new tab. */\n publicChatEnabled?: boolean;\n /** The currently selected account (workspace) name for the public chat URL. */\n publicChatAccountId?: string;\n /** Which tab is active in the chat page. */\n chatPageTab?: ChatPageTab;\n /** Called when the user switches tabs. */\n onChatPageTabChange?: (tab: ChatPageTab) => void;\n /** Props for the WhatsApp conversation browser tab. */\n whatsappProps?: WhatsAppTabProps;\n};\n\nexport function renderChatPage(props: ChatPageProps) {\n if (!props.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting to gateway...</p>\n </div>\n </div>\n `;\n }\n\n const activeTab: ChatPageTab = props.chatPageTab ?? \"chat\";\n\n const publicBtn = props.publicChatEnabled && props.publicChatAccountId\n ? html`<a\n class=\"chat-public-link\"\n href=\"/public/chat/${props.publicChatAccountId}\"\n target=\"_blank\"\n rel=\"noopener\"\n title=\"Open public chat in new tab\"\n >Public ${externalLinkIcon}</a>`\n : nothing;\n\n const tabBar = props.whatsappProps\n ? html`\n <div class=\"chat-page-tabs\">\n <button\n class=\"chat-page-tab ${activeTab === \"chat\" ? \"active\" : \"\"}\"\n @click=${() => props.onChatPageTabChange?.(\"chat\")}\n >Chat</button>\n <button\n class=\"chat-page-tab ${activeTab === \"whatsapp\" ? \"active\" : \"\"}\"\n @click=${() => props.onChatPageTabChange?.(\"whatsapp\")}\n >WhatsApp</button>\n </div>\n `\n : nothing;\n\n return html`\n <div class=\"setup-container setup-container--full chat-page\">\n ${renderPageNav(\"Chat\", props.wsProps)}\n ${publicBtn}\n ${tabBar}\n <div class=\"chat-viewport\">\n ${activeTab === \"whatsapp\" && props.whatsappProps\n ? renderWhatsAppTab(props.whatsappProps)\n : renderChat(props)}\n </div>\n </div>\n `;\n}\n","import type { GatewayBrowserClient } from \"../gateway.js\";\n\nexport type WhatsAppConversation = {\n jid: string;\n type: \"group\" | \"dm\";\n name: string;\n lastMessageTimestamp?: number;\n activation?: \"always\" | \"mention\" | \"off\";\n};\n\nexport type WhatsAppMessage = {\n id: string;\n sender: string;\n senderName?: string;\n body: string;\n timestamp: number;\n fromMe: boolean;\n quoted?: { id: string; body: string; sender: string };\n};\n\nexport type WhatsAppGroupInfo = {\n subject: string;\n participants: Array<{ jid: string; name?: string; admin: boolean }>;\n creation?: number;\n desc?: string;\n activation?: \"always\" | \"mention\" | \"off\";\n};\n\nexport type WhatsAppTabState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n conversations: WhatsAppConversation[];\n selectedJid: string | null;\n messages: WhatsAppMessage[];\n groupInfo: WhatsAppGroupInfo | null;\n loading: boolean;\n messagesLoading: boolean;\n searchQuery: string;\n composeDraft: string;\n sending: boolean;\n lastError: string | null;\n accountId?: string;\n};\n\nexport function createInitialWhatsAppState(): Omit<WhatsAppTabState, \"client\" | \"connected\"> {\n return {\n conversations: [],\n selectedJid: null,\n messages: [],\n groupInfo: null,\n loading: false,\n messagesLoading: false,\n searchQuery: \"\",\n composeDraft: \"\",\n sending: false,\n lastError: null,\n };\n}\n\nexport async function loadConversations(state: WhatsAppTabState) {\n if (!state.client || !state.connected) return;\n state.loading = true;\n state.lastError = null;\n try {\n const res = (await state.client.request(\"whatsapp.conversations\", {\n accountId: state.accountId,\n })) as { conversations: WhatsAppConversation[] };\n state.conversations = res.conversations;\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.loading = false;\n }\n}\n\nexport async function selectConversation(state: WhatsAppTabState, jid: string) {\n if (!state.client || !state.connected) return;\n state.selectedJid = jid;\n state.messagesLoading = true;\n state.messages = [];\n state.groupInfo = null;\n state.lastError = null;\n try {\n const msgsRes = (await state.client.request(\"whatsapp.messages\", {\n jid, limit: 100, accountId: state.accountId,\n })) as { messages: WhatsAppMessage[] };\n state.messages = msgsRes.messages;\n } catch (err) {\n state.lastError = String(err);\n }\n if (jid.endsWith(\"@g.us\")) {\n try {\n const groupRes = (await state.client.request(\"whatsapp.groupInfo\", {\n jid, accountId: state.accountId,\n })) as WhatsAppGroupInfo;\n state.groupInfo = groupRes;\n } catch {\n // Group metadata unavailable — messages still load fine\n }\n }\n state.messagesLoading = false;\n}\n\nexport async function setGroupActivation(\n state: WhatsAppTabState,\n jid: string,\n activation: \"always\" | \"mention\" | \"off\",\n) {\n if (!state.client || !state.connected) return;\n try {\n await state.client.request(\"whatsapp.setActivation\", { jid, activation, accountId: state.accountId });\n if (state.groupInfo) state.groupInfo.activation = activation;\n const conv = state.conversations.find((c) => c.jid === jid);\n if (conv) conv.activation = activation;\n } catch (err) {\n state.lastError = String(err);\n }\n}\n\nexport async function sendWhatsAppMessage(state: WhatsAppTabState, jid: string, body: string) {\n if (!state.client || !state.connected || !body.trim()) return;\n state.sending = true;\n state.lastError = null;\n try {\n const res = (await state.client.request(\"whatsapp.sendMessage\", {\n jid, body: body.trim(), accountId: state.accountId,\n })) as { id: string; timestamp: number };\n state.messages = [\n ...state.messages,\n { id: res.id, sender: \"\", body: body.trim(), timestamp: res.timestamp, fromMe: true },\n ];\n state.composeDraft = \"\";\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.sending = false;\n }\n}\n","import { formatAgo, formatDurationMs, formatMs } from \"./format\";\nimport type { CronJob, GatewaySessionRow, PresenceEntry } from \"./types\";\n\nexport function formatPresenceSummary(entry: PresenceEntry): string {\n const host = entry.host ?? \"unknown\";\n const ip = entry.ip ? `(${entry.ip})` : \"\";\n const mode = entry.mode ?? \"\";\n const version = entry.version ?? \"\";\n return `${host} ${ip} ${mode} ${version}`.trim();\n}\n\nexport function formatPresenceAge(entry: PresenceEntry): string {\n const ts = entry.ts ?? null;\n return ts ? formatAgo(ts) : \"n/a\";\n}\n\nexport function formatNextRun(ms?: number | null) {\n if (!ms) return \"n/a\";\n return `${formatMs(ms)} (${formatAgo(ms)})`;\n}\n\nexport function formatSessionTokens(row: GatewaySessionRow) {\n if (row.totalTokens == null) return \"n/a\";\n const total = row.totalTokens ?? 0;\n const ctx = row.contextTokens ?? 0;\n return ctx ? `${total} / ${ctx}` : String(total);\n}\n\nexport function formatEventPayload(payload: unknown): string {\n if (payload == null) return \"\";\n try {\n return JSON.stringify(payload, null, 2);\n } catch {\n return String(payload);\n }\n}\n\nexport function formatCronState(job: CronJob) {\n const state = job.state ?? {};\n const status = state.lastStatus ?? \"n/a\";\n const last = state.lastRunAtMs ? formatAgo(state.lastRunAtMs) : \"never\";\n return `${status} · last ${last}`;\n}\n\nexport function formatCronSchedule(job: CronJob) {\n const s = job.schedule;\n if (s.kind === \"at\") return `One-time: ${formatMs(s.atMs)}`;\n if (s.kind === \"every\") return `Every ${formatDurationMs(s.everyMs)}`;\n return humanizeCron(s.expr, s.tz);\n}\n\n/**\n * Convert a 5-field cron expression to human-readable text.\n * Handles common patterns; falls back to the raw expression for complex ones.\n */\nfunction humanizeCron(expr: string, tz?: string): string {\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) return expr;\n const [minute, hour, dom, month, dow] = parts;\n\n const tzSuffix = tz ? ` (${tz.replace(/^.*\\//, \"\").replace(/_/g, \" \")})` : \"\";\n\n // Format a single hour:minute as locale time string\n const fmtTime = (h: number, m: number) => {\n const d = new Date(2000, 0, 1, h, m);\n return d.toLocaleTimeString(undefined, { hour: \"numeric\", minute: \"2-digit\" });\n };\n\n // Parse minute field — only handle single values\n const min = /^\\d{1,2}$/.test(minute) ? parseInt(minute, 10) : null;\n\n // Parse hour field — single value, comma-separated, or range\n const hours = parseField(hour);\n\n // If we can't parse minute or hour, fall back\n if (min === null || !hours) return `${expr}${tz ? ` (${tz})` : \"\"}`;\n\n const timeList = hours.map((h) => fmtTime(h, min));\n const timeStr =\n timeList.length <= 3\n ? timeList.join(\" & \")\n : `${timeList.slice(0, -1).join(\", \")} & ${timeList[timeList.length - 1]}`;\n\n // Day-of-week names\n const DOW_NAMES = [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"];\n\n // Determine frequency prefix\n if (dom === \"*\" && month === \"*\") {\n if (dow === \"*\") return `Daily at ${timeStr}${tzSuffix}`;\n if (dow === \"1-5\") return `Weekdays at ${timeStr}${tzSuffix}`;\n if (dow === \"0,6\" || dow === \"6,0\") return `Weekends at ${timeStr}${tzSuffix}`;\n const days = parseField(dow);\n if (days) {\n const dayNames = days.map((d) => DOW_NAMES[d % 7] ?? String(d));\n return `${dayNames.join(\", \")} at ${timeStr}${tzSuffix}`;\n }\n }\n\n return `${expr}${tz ? ` (${tz})` : \"\"}`;\n}\n\n/** Parse a cron field into an array of numbers (handles single, comma, range). */\nfunction parseField(field: string): number[] | null {\n if (field === \"*\") return null;\n // Comma-separated: \"8,20\"\n if (/^\\d+(,\\d+)*$/.test(field)) {\n return field.split(\",\").map(Number);\n }\n // Range: \"1-5\"\n if (/^\\d+-\\d+$/.test(field)) {\n const [start, end] = field.split(\"-\").map(Number);\n if (start > end) return null;\n const result: number[] = [];\n for (let i = start; i <= end; i++) result.push(i);\n return result;\n }\n return null;\n}\n\nexport function formatCronPayload(job: CronJob, truncate = true) {\n const p = job.payload;\n if (p.kind === \"systemEvent\") {\n const text = truncate && p.text.length > 60 ? `${p.text.slice(0, 57)}\\u2026` : p.text;\n return `Task: ${text}`;\n }\n const msg = truncate && p.message.length > 60 ? `${p.message.slice(0, 57)}\\u2026` : p.message;\n return `Message: ${msg}`;\n}\n\nexport function formatCronDeliveryTarget(job: CronJob): string | null {\n const p = job.payload;\n if (p.kind !== \"agentTurn\") return null;\n // Runtime data uses \"channel\" but the UI type declares \"provider\".\n const channel = (p as Record<string, unknown>).channel ?? p.provider;\n const to = p.to;\n if (!to && !channel) return null;\n const parts: string[] = [];\n if (to) {\n // Format multi-recipient and \"admins\" token for card display\n const recipients = to.split(\",\").map((s) => s.trim()).filter(Boolean);\n const labels = recipients.map((r) => (r.toLowerCase() === \"admins\" ? \"All admins\" : r));\n parts.push(labels.join(\", \"));\n }\n if (channel && channel !== \"last\") parts.push(`via ${channel}`);\n return parts.join(\" \") || null;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo, formatDurationMs } from \"../format\";\nimport {\n formatCronDeliveryTarget,\n formatCronPayload,\n formatCronSchedule,\n formatCronState,\n formatNextRun,\n} from \"../presenter\";\nimport type { ChannelUiMetaEntry, CronJob, CronRunLogEntry, CronStatus } from \"../types\";\nimport type { CronFormState } from \"../ui-types\";\nimport type { CronRunResult } from \"../controllers/cron\";\n\nexport type CronProps = {\n loading: boolean;\n status: CronStatus | null;\n jobs: CronJob[];\n error: string | null;\n busy: boolean;\n form: CronFormState;\n channels: string[];\n channelLabels?: Record<string, string>;\n channelMeta?: ChannelUiMetaEntry[];\n agentIds: string[];\n runsJobId: string | null;\n runs: CronRunLogEntry[];\n newEventModalOpen: boolean;\n onNewEventModalOpen: () => void;\n onNewEventModalClose: () => void;\n detailJobId: string | null;\n editJobId: string | null;\n onDetailOpen: (job: CronJob) => void;\n onDetailClose: () => void;\n onEdit: (job: CronJob) => void;\n onEditSave: () => void;\n onFormChange: (patch: Partial<CronFormState>) => void;\n onRefresh: () => void;\n onAdd: () => void;\n onToggle: (job: CronJob, enabled: boolean) => void;\n onRun: (job: CronJob) => void;\n onRemove: (job: CronJob) => void;\n pendingDeleteId: string | null;\n onArmDelete: (jobId: string) => void;\n onLoadRuns: (jobId: string) => void;\n runModalJobId: string | null;\n runModalJobName: string;\n runResult: CronRunResult | null;\n onRunModalClose: () => void;\n};\n\nlet pendingDeleteTimer: ReturnType<typeof setTimeout> | null = null;\n\n/* ── Helpers ── */\n\nfunction buildChannelOptions(props: CronProps): string[] {\n const options = [\"last\", ...props.channels.filter(Boolean)];\n const current = props.form.channel?.trim();\n if (current && !options.includes(current)) {\n options.push(current);\n }\n const seen = new Set<string>();\n return options.filter((value) => {\n if (seen.has(value)) return false;\n seen.add(value);\n return true;\n });\n}\n\nfunction resolveChannelLabel(props: CronProps, channel: string): string {\n if (channel === \"last\") return \"last\";\n const meta = props.channelMeta?.find((entry) => entry.id === channel);\n if (meta?.label) return meta.label;\n return props.channelLabels?.[channel] ?? channel;\n}\n\n/** Format a comma-separated `to` field for display, labelling the \"admins\" token. */\nfunction formatRecipients(to: string): string {\n const parts = to.split(\",\").map((s) => s.trim()).filter(Boolean);\n return parts.map((p) => (p.toLowerCase() === \"admins\" ? \"All admins\" : p)).join(\", \");\n}\n\n/** Friendly agent label: \"foo-public\" → \"foo-public\", empty → \"Default\" */\nfunction agentLabel(agentId?: string): string {\n if (!agentId) return \"Default\";\n return agentId;\n}\n\n/* ── SVG icon fragments (inline, small) ── */\n\nconst iconPlay = html`<svg viewBox=\"0 0 24 24\"><polygon points=\"5 3 19 12 5 21 5 3\"/></svg>`;\nconst iconPause = html`<svg viewBox=\"0 0 24 24\"><rect x=\"6\" y=\"4\" width=\"4\" height=\"16\"/><rect x=\"14\" y=\"4\" width=\"4\" height=\"16\"/></svg>`;\nconst iconTrash = html`<svg viewBox=\"0 0 24 24\"><path d=\"M3 6h18\"/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"/><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\"/></svg>`;\nconst iconX = html`<svg viewBox=\"0 0 24 24\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>`;\nconst iconZap = html`<svg viewBox=\"0 0 24 24\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"/></svg>`;\nconst iconPlus = html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 5v14\"/><path d=\"M5 12h14\"/></svg>`;\nconst iconEdit = html`<svg viewBox=\"0 0 24 24\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"/></svg>`;\n\n/* ── Main render ── */\n\nexport function renderCron(props: CronProps) {\n const detailJob = props.detailJobId\n ? props.jobs.find((j) => j.id === props.detailJobId) ?? null\n : null;\n\n const formModalOpen = props.newEventModalOpen || !!props.editJobId;\n\n return html`\n ${renderStatusBar(props)}\n ${renderEventGrid(props)}\n ${formModalOpen ? renderEventFormModal(props) : nothing}\n ${detailJob ? renderDetailModal(detailJob, props) : nothing}\n ${props.runModalJobId ? renderRunModal(props) : nothing}\n `;\n}\n\n/* ── Status bar ── */\n\nfunction renderStatusBar(props: CronProps) {\n const s = props.status;\n const enabled = s?.enabled ?? false;\n const jobCount = props.jobs.length;\n const nextWake = s?.nextWakeAtMs;\n\n return html`\n <div class=\"event-status-bar\">\n <div class=\"event-status-bar__info\">\n <span class=\"statusDot ${enabled ? \"ok\" : \"\"}\"></span>\n <span>${enabled ? \"Active\" : \"Inactive\"}</span>\n <span class=\"event-status-bar__sep\">\\u00b7</span>\n <span>${jobCount} event${jobCount !== 1 ? \"s\" : \"\"}</span>\n ${nextWake\n ? html`\n <span class=\"event-status-bar__sep\">\\u00b7</span>\n <span>Next: ${formatAgo(nextWake)}</span>\n `\n : nothing}\n <button\n class=\"btn btn--sm\"\n ?disabled=${props.loading}\n @click=${props.onRefresh}\n style=\"margin-left: 4px;\"\n >\n ${props.loading ? \"Refreshing\\u2026\" : \"Refresh\"}\n </button>\n ${props.error ? html`<span class=\"muted\">${props.error}</span>` : nothing}\n </div>\n <button class=\"btn primary btn--sm\" @click=${props.onNewEventModalOpen}>\n ${iconPlus} New Event\n </button>\n </div>\n `;\n}\n\n/* ── Event cards grid ── */\n\nfunction renderEventGrid(props: CronProps) {\n if (props.jobs.length === 0) {\n return html`<div class=\"muted\" style=\"padding: 20px 0;\">No events yet. Create one to get started.</div>`;\n }\n\n return html`\n <div class=\"event-grid\">\n ${props.jobs.map((job) => renderEventCard(job, props))}\n </div>\n `;\n}\n\nfunction renderEventCard(job: CronJob, props: CronProps) {\n return html`\n <div\n class=\"event-card ${job.enabled ? \"\" : \"disabled\"}\"\n @click=${() => props.onDetailOpen(job)}\n >\n <div class=\"event-card__header\">\n <div class=\"event-card__name\">${job.name || \"Untitled\"}</div>\n <span class=\"chip ${job.enabled ? \"chip-ok\" : \"\"}\" style=\"font-size: 11px; padding: 2px 8px;\">\n ${job.enabled ? \"On\" : \"Off\"}\n </span>\n </div>\n <div class=\"event-card__schedule\">${formatCronSchedule(job)}</div>\n ${job.agentId\n ? html`<div class=\"event-card__agent\">${agentLabel(job.agentId)}</div>`\n : nothing}\n ${formatCronDeliveryTarget(job)\n ? html`<div class=\"event-card__agent muted\" style=\"font-size: 11px;\">\\u2192 ${formatCronDeliveryTarget(job)}</div>`\n : nothing}\n <div class=\"event-card__footer\">\n <div class=\"event-card__status\">\n <span class=\"muted\" style=\"font-size: 11px;\">${formatCronState(job)}</span>\n </div>\n <div class=\"event-card__actions\" @click=${(e: Event) => e.stopPropagation()}>\n <button\n class=\"btn-icon\"\n title=\"${job.enabled ? \"Pause\" : \"Resume\"}\"\n ?disabled=${props.busy}\n @click=${() => props.onToggle(job, !job.enabled)}\n >\n ${job.enabled ? iconPause : iconPlay}\n </button>\n <button\n class=\"btn-icon\"\n title=\"Run now\"\n ?disabled=${props.busy}\n @click=${() => props.onRun(job)}\n >\n ${iconZap}\n </button>\n ${props.pendingDeleteId === job.id\n ? html`<button\n class=\"btn danger btn--sm\"\n ?disabled=${props.busy}\n @click=${() => {\n if (pendingDeleteTimer) clearTimeout(pendingDeleteTimer);\n pendingDeleteTimer = null;\n props.onRemove(job);\n }}\n >Confirm delete?</button>`\n : html`<button\n class=\"btn-icon danger\"\n title=\"Delete\"\n ?disabled=${props.busy}\n @click=${() => {\n props.onArmDelete(job.id);\n if (pendingDeleteTimer) clearTimeout(pendingDeleteTimer);\n pendingDeleteTimer = setTimeout(() => {\n props.onArmDelete(\"\");\n pendingDeleteTimer = null;\n }, 3000);\n }}\n >${iconTrash}</button>`\n }\n </div>\n </div>\n </div>\n `;\n}\n\n/* ── Event form modal (create & edit) ── */\n\nfunction renderEventFormModal(props: CronProps) {\n const isEdit = !!props.editJobId;\n const channelOptions = buildChannelOptions(props);\n const onClose = () => {\n if (isEdit) {\n // The onEditSave handler in app-render also handles closing;\n // here we just close without saving.\n props.onNewEventModalClose();\n } else {\n props.onNewEventModalClose();\n }\n };\n\n return html`\n <div class=\"event-modal-overlay\" @click=${onClose}>\n <div class=\"event-modal\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"event-modal__header\">\n <div class=\"event-modal__title\">${isEdit ? \"Edit Event\" : \"New Event\"}</div>\n <button class=\"event-modal__close\" @click=${onClose}>\n ${iconX}\n </button>\n </div>\n\n <div class=\"form-grid\">\n <label class=\"field\">\n <span>Name</span>\n <input\n .value=${props.form.name}\n @input=${(e: Event) =>\n props.onFormChange({ name: (e.target as HTMLInputElement).value })}\n placeholder=\"e.g. Morning briefing\"\n />\n </label>\n <label class=\"field\">\n <span>Description</span>\n <input\n .value=${props.form.description}\n @input=${(e: Event) =>\n props.onFormChange({ description: (e.target as HTMLInputElement).value })}\n placeholder=\"What does this event do?\"\n />\n </label>\n <label class=\"field\">\n <span>Agent</span>\n <select\n .value=${props.form.agentId}\n @change=${(e: Event) =>\n props.onFormChange({ agentId: (e.target as HTMLSelectElement).value })}\n >\n <option value=\"\">Default</option>\n ${props.agentIds.map(\n (id) => html`<option value=${id}>${id}</option>`,\n )}\n </select>\n </label>\n <label class=\"field checkbox\">\n <span>Enabled</span>\n <input\n type=\"checkbox\"\n .checked=${props.form.enabled}\n @change=${(e: Event) =>\n props.onFormChange({ enabled: (e.target as HTMLInputElement).checked })}\n />\n </label>\n <label class=\"field\">\n <span>Timing</span>\n <select\n .value=${props.form.scheduleKind}\n @change=${(e: Event) =>\n props.onFormChange({\n scheduleKind: (e.target as HTMLSelectElement).value as CronFormState[\"scheduleKind\"],\n })}\n >\n <option value=\"every\">Repeating</option>\n <option value=\"at\">One-time</option>\n <option value=\"cron\">Custom schedule</option>\n </select>\n </label>\n </div>\n\n ${renderScheduleFields(props)}\n\n <div class=\"form-grid\" style=\"margin-top: 12px;\">\n <label class=\"field\">\n <span>Session type</span>\n <select\n .value=${props.form.sessionTarget}\n @change=${(e: Event) => {\n const target = (e.target as HTMLSelectElement).value as CronFormState[\"sessionTarget\"];\n props.onFormChange({\n sessionTarget: target,\n payloadKind: target === \"isolated\" ? \"agentTurn\" : \"systemEvent\",\n });\n }}\n >\n <option value=\"main\">Shared session</option>\n <option value=\"isolated\">Separate session</option>\n </select>\n </label>\n <label class=\"field\">\n <span>When to run</span>\n <select\n .value=${props.form.wakeMode}\n @change=${(e: Event) =>\n props.onFormChange({\n wakeMode: (e.target as HTMLSelectElement).value as CronFormState[\"wakeMode\"],\n })}\n >\n <option value=\"next-heartbeat\">Next available time</option>\n <option value=\"now\">Right away</option>\n </select>\n </label>\n <label class=\"field\">\n <span>Action type</span>\n <select\n .value=${props.form.payloadKind}\n @change=${(e: Event) => {\n const kind = (e.target as HTMLSelectElement).value as CronFormState[\"payloadKind\"];\n props.onFormChange({\n payloadKind: kind,\n sessionTarget: kind === \"agentTurn\" ? \"isolated\" : \"main\",\n });\n }}\n >\n <option value=\"systemEvent\">Background task</option>\n <option value=\"agentTurn\">Send a message</option>\n </select>\n </label>\n </div>\n\n <label class=\"field\" style=\"margin-top: 12px;\">\n <span>${props.form.payloadKind === \"systemEvent\" ? \"Task description\" : \"Message to send\"}</span>\n <textarea\n .value=${props.form.payloadText}\n @input=${(e: Event) =>\n props.onFormChange({\n payloadText: (e.target as HTMLTextAreaElement).value,\n })}\n rows=\"4\"\n placeholder=\"${props.form.payloadKind === \"systemEvent\"\n ? \"Describe what the assistant should do\\u2026\"\n : \"Type the message to send\\u2026\"}\"\n ></textarea>\n </label>\n\n ${props.form.payloadKind === \"agentTurn\"\n ? html`\n <div class=\"form-grid\" style=\"margin-top: 12px;\">\n <label class=\"field checkbox\">\n <span>Deliver response</span>\n <input\n type=\"checkbox\"\n .checked=${props.form.deliver}\n @change=${(e: Event) =>\n props.onFormChange({\n deliver: (e.target as HTMLInputElement).checked,\n })}\n />\n </label>\n <label class=\"field\">\n <span>Channel</span>\n <select\n .value=${props.form.channel || \"last\"}\n @change=${(e: Event) =>\n props.onFormChange({\n channel: (e.target as HTMLSelectElement).value as CronFormState[\"channel\"],\n })}\n >\n ${channelOptions.map(\n (channel) =>\n html`<option value=${channel}>\n ${resolveChannelLabel(props, channel)}\n </option>`,\n )}\n </select>\n </label>\n <label class=\"field checkbox\">\n <span>All admins</span>\n <input\n type=\"checkbox\"\n .checked=${props.form.toAdmins}\n @change=${(e: Event) =>\n props.onFormChange({\n toAdmins: (e.target as HTMLInputElement).checked,\n })}\n />\n </label>\n </div>\n ${renderRecipientsList(props)}\n <div class=\"form-grid\" style=\"margin-top: 12px;\">\n <label class=\"field\">\n <span>Timeout (seconds)</span>\n <input\n .value=${props.form.timeoutSeconds}\n @input=${(e: Event) =>\n props.onFormChange({\n timeoutSeconds: (e.target as HTMLInputElement).value,\n })}\n />\n </label>\n ${props.form.sessionTarget === \"isolated\"\n ? html`\n <label class=\"field\">\n <span>Summary prefix</span>\n <input\n .value=${props.form.postToMainPrefix}\n @input=${(e: Event) =>\n props.onFormChange({\n postToMainPrefix: (e.target as HTMLInputElement).value,\n })}\n />\n </label>\n `\n : nothing}\n </div>\n `\n : nothing}\n\n <div class=\"row\" style=\"margin-top: 16px; justify-content: flex-end;\">\n <button class=\"btn\" @click=${onClose}>Cancel</button>\n ${isEdit\n ? html`<button class=\"btn primary\" ?disabled=${props.busy} @click=${props.onEditSave}>\n ${props.busy ? \"Saving\\u2026\" : \"Save Changes\"}\n </button>`\n : html`<button class=\"btn primary\" ?disabled=${props.busy} @click=${props.onAdd}>\n ${props.busy ? \"Creating\\u2026\" : \"Create Event\"}\n </button>`}\n </div>\n </div>\n </div>\n `;\n}\n\n/* ── Recipients list (multi-recipient input) ── */\n\nfunction renderRecipientsList(props: CronProps) {\n const recipients = props.form.recipients;\n\n return html`\n <div style=\"margin-top: 8px;\">\n <div style=\"display: flex; align-items: center; gap: 8px; margin-bottom: 8px;\">\n <span style=\"font-size: 13px; color: var(--muted);\">Recipients</span>\n <button\n class=\"btn btn--sm\"\n @click=${() => {\n props.onFormChange({ recipients: [...recipients, \"\"] });\n }}\n >\n ${iconPlus} Add\n </button>\n </div>\n ${recipients.length === 0 && !props.form.toAdmins\n ? html`<div class=\"muted\" style=\"font-size: 12px; padding: 4px 0;\">No recipients. Add a phone number or enable \"All admins\".</div>`\n : nothing}\n ${recipients.map(\n (recipient, index) => html`\n <div style=\"display: flex; align-items: center; gap: 6px; margin-bottom: 6px;\">\n <input\n style=\"flex: 1;\"\n .value=${recipient}\n @input=${(e: Event) => {\n const updated = [...recipients];\n updated[index] = (e.target as HTMLInputElement).value;\n props.onFormChange({ recipients: updated });\n }}\n placeholder=\"+1555\\u2026 or chat id\"\n />\n <button\n class=\"btn-icon danger\"\n title=\"Remove\"\n @click=${() => {\n const updated = recipients.filter((_, i) => i !== index);\n props.onFormChange({ recipients: updated });\n }}\n >\n ${iconX}\n </button>\n </div>\n `,\n )}\n </div>\n `;\n}\n\n/* ── Schedule fields (shared by modal) ── */\n\nfunction renderScheduleFields(props: CronProps) {\n const form = props.form;\n if (form.scheduleKind === \"at\") {\n return html`\n <label class=\"field\" style=\"margin-top: 12px;\">\n <span>Run at</span>\n <input\n type=\"datetime-local\"\n .value=${form.scheduleAt}\n @input=${(e: Event) =>\n props.onFormChange({\n scheduleAt: (e.target as HTMLInputElement).value,\n })}\n />\n </label>\n `;\n }\n if (form.scheduleKind === \"every\") {\n return html`\n <div class=\"form-grid\" style=\"margin-top: 12px;\">\n <label class=\"field\">\n <span>Repeat every</span>\n <input\n .value=${form.everyAmount}\n @input=${(e: Event) =>\n props.onFormChange({\n everyAmount: (e.target as HTMLInputElement).value,\n })}\n />\n </label>\n <label class=\"field\">\n <span>Unit</span>\n <select\n .value=${form.everyUnit}\n @change=${(e: Event) =>\n props.onFormChange({\n everyUnit: (e.target as HTMLSelectElement).value as CronFormState[\"everyUnit\"],\n })}\n >\n <option value=\"minutes\">Minutes</option>\n <option value=\"hours\">Hours</option>\n <option value=\"days\">Days</option>\n </select>\n </label>\n </div>\n `;\n }\n return html`\n <div class=\"form-grid\" style=\"margin-top: 12px;\">\n <label class=\"field\">\n <span>Cron expression</span>\n <input\n .value=${form.cronExpr}\n @input=${(e: Event) =>\n props.onFormChange({ cronExpr: (e.target as HTMLInputElement).value })}\n placeholder=\"e.g. 0 7 * * *\"\n />\n </label>\n <label class=\"field\">\n <span>Timezone (optional)</span>\n <input\n .value=${form.cronTz}\n @input=${(e: Event) =>\n props.onFormChange({ cronTz: (e.target as HTMLInputElement).value })}\n placeholder=\"e.g. America/New_York\"\n />\n </label>\n </div>\n `;\n}\n\n/* ── Detail modal ── */\n\nfunction renderDetailModal(job: CronJob, props: CronProps) {\n return html`\n <div class=\"event-modal-overlay\" @click=${props.onDetailClose}>\n <div class=\"event-modal\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"event-modal__header\">\n <div class=\"event-modal__title\">${job.name || \"Untitled Event\"}</div>\n <button class=\"event-modal__close\" @click=${props.onDetailClose}>\n ${iconX}\n </button>\n </div>\n\n ${job.description\n ? html`<div style=\"color: var(--muted); font-size: 13px; margin-bottom: 16px;\">${job.description}</div>`\n : nothing}\n\n <div class=\"row\" style=\"margin-bottom: 16px; gap: 8px; justify-content: flex-start;\">\n <button\n class=\"btn\"\n ?disabled=${props.busy}\n @click=${() => props.onEdit(job)}\n >\n ${iconEdit} Edit\n </button>\n <button\n class=\"btn\"\n ?disabled=${props.busy}\n @click=${() => props.onToggle(job, !job.enabled)}\n >\n ${job.enabled ? \"Disable\" : \"Enable\"}\n </button>\n <button\n class=\"btn primary\"\n ?disabled=${props.busy}\n @click=${() => props.onRun(job)}\n >\n Run Now\n </button>\n <button\n class=\"btn danger\"\n ?disabled=${props.busy}\n @click=${() => {\n if (props.pendingDeleteId === job.id) {\n if (pendingDeleteTimer) clearTimeout(pendingDeleteTimer);\n pendingDeleteTimer = null;\n props.onRemove(job);\n props.onDetailClose();\n } else {\n props.onArmDelete(job.id);\n if (pendingDeleteTimer) clearTimeout(pendingDeleteTimer);\n pendingDeleteTimer = setTimeout(() => {\n props.onArmDelete(\"\");\n pendingDeleteTimer = null;\n }, 3000);\n }\n }}\n >\n ${props.pendingDeleteId === job.id ? \"Confirm delete?\" : \"Delete\"}\n </button>\n </div>\n\n <div class=\"event-detail-section\">\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Status</span>\n <span class=\"event-detail-value\">\n <span class=\"chip ${job.enabled ? \"chip-ok\" : \"\"}\" style=\"font-size: 11px; padding: 2px 8px;\">\n ${job.enabled ? \"Enabled\" : \"Disabled\"}\n </span>\n </span>\n </div>\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Schedule</span>\n <span class=\"event-detail-value\">${formatCronSchedule(job)}</span>\n </div>\n ${job.agentId\n ? html`\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Agent</span>\n <span class=\"event-detail-value mono\">${job.agentId}</span>\n </div>\n `\n : nothing}\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Session</span>\n <span class=\"event-detail-value\">\n ${job.sessionTarget === \"main\" ? \"Shared\" : \"Separate\"}\n </span>\n </div>\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Run mode</span>\n <span class=\"event-detail-value\">\n ${job.wakeMode === \"now\" ? \"Right away\" : \"Next available time\"}\n </span>\n </div>\n <div class=\"event-detail-row\" style=\"flex-direction: column; align-items: stretch; gap: 4px;\">\n <span class=\"event-detail-label\">Action</span>\n <span class=\"event-detail-value\" style=\"text-align: left; white-space: pre-wrap; font-size: 12px; color: var(--muted); line-height: 1.5;\">${formatCronPayload(job, false)}</span>\n </div>\n ${job.payload.kind === \"agentTurn\" && job.payload.to\n ? html`\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Send to</span>\n <span class=\"event-detail-value mono\">${formatRecipients(job.payload.to)}</span>\n </div>\n `\n : nothing}\n ${job.payload.kind === \"agentTurn\" && ((job.payload as Record<string, unknown>).channel ?? job.payload.provider)\n ? html`\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Channel</span>\n <span class=\"event-detail-value\">${(job.payload as Record<string, unknown>).channel ?? job.payload.provider}</span>\n </div>\n `\n : nothing}\n ${job.payload.kind === \"agentTurn\"\n ? html`\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Auto-deliver</span>\n <span class=\"event-detail-value\">${job.payload.deliver ? \"Yes\" : \"No\"}</span>\n </div>\n `\n : nothing}\n </div>\n\n <div class=\"event-detail-section\">\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Last run</span>\n <span class=\"event-detail-value\">${formatCronState(job)}</span>\n </div>\n ${job.state?.nextRunAtMs\n ? html`\n <div class=\"event-detail-row\">\n <span class=\"event-detail-label\">Next run</span>\n <span class=\"event-detail-value\">${formatNextRun(job.state.nextRunAtMs)}</span>\n </div>\n `\n : nothing}\n </div>\n\n <div class=\"event-detail-section\">\n <div style=\"display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px;\">\n <span class=\"event-detail-label\" style=\"font-size: 14px;\">Recent Activity</span>\n </div>\n ${props.runs.length === 0\n ? html`<div class=\"muted\" style=\"font-size: 13px;\">No runs recorded yet.</div>`\n : html`\n <div class=\"list\">\n ${[...props.runs].sort((a, b) => b.ts - a.ts).map((entry) => renderRun(entry))}\n </div>\n `}\n </div>\n\n </div>\n </div>\n `;\n}\n\n/* ── Run-now modal ── */\n\nfunction renderRunModal(props: CronProps) {\n const result = props.runResult;\n const running = !result;\n const statusLabel = result?.status === \"ok\" ? \"Completed\" : result?.status === \"error\" ? \"Error\" : result?.status === \"skipped\" ? \"Skipped\" : result?.status ?? \"\";\n\n return html`\n <div class=\"event-modal-overlay\" @click=${props.onRunModalClose}>\n <div class=\"event-modal\" style=\"max-width: 480px;\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"event-modal__header\">\n <div class=\"event-modal__title\">${props.runModalJobName}</div>\n <button class=\"event-modal__close\" @click=${props.onRunModalClose}>\n ${iconX}\n </button>\n </div>\n\n ${running\n ? html`\n <div style=\"display: flex; align-items: center; gap: 12px; padding: 24px 0;\">\n <span class=\"chat-reading-indicator__dots\" style=\"display: inline-flex; gap: 3px;\">\n <span></span><span></span><span></span>\n </span>\n <span>Running\\u2026</span>\n </div>\n `\n : html`\n <div style=\"padding: 8px 0;\">\n <div style=\"display: flex; align-items: center; gap: 8px; margin-bottom: 16px;\">\n <span\n class=\"chip ${result.status === \"ok\" ? \"chip-ok\" : result.status === \"error\" || result.status === \"skipped\" ? \"chip-warn\" : \"\"}\"\n style=\"font-size: 12px; padding: 3px 10px;\"\n >\n ${statusLabel}\n </span>\n ${result.durationMs != null\n ? html`<span class=\"muted\" style=\"font-size: 13px;\">${formatDurationMs(result.durationMs)}</span>`\n : nothing}\n </div>\n ${result.outputText || result.summary\n ? html`\n <div style=\"white-space: pre-wrap; font-size: 13px; line-height: 1.6; max-height: 400px; overflow-y: auto; color: var(--fg);\">${result.outputText ?? result.summary}</div>\n `\n : nothing}\n ${result.error\n ? html`\n <details style=\"margin-top: 12px;\" open>\n <summary class=\"muted\" style=\"cursor: pointer; font-size: 13px;\">Error details</summary>\n <div class=\"muted\" style=\"margin-top: 6px; white-space: pre-wrap; font-size: 12px;\">${result.error}</div>\n </details>\n `\n : nothing}\n ${!result.outputText && !result.summary && !result.error\n ? html`<div class=\"muted\" style=\"font-size: 13px;\">Job completed with no output.</div>`\n : nothing}\n </div>\n <div style=\"display: flex; justify-content: flex-end; margin-top: 16px;\">\n <button class=\"btn primary\" @click=${props.onRunModalClose}>Close</button>\n </div>\n `}\n </div>\n </div>\n `;\n}\n\n/* ── Run log entry ── */\n\nfunction runStatusClass(status: string): string {\n const s = status.toLowerCase();\n if (s === \"ok\" || s === \"success\") return \"chip chip-ok\";\n if (s === \"error\" || s === \"fail\" || s === \"failed\" || s === \"skipped\") return \"chip chip-warn\";\n return \"chip\";\n}\n\nfunction renderRun(entry: CronRunLogEntry) {\n return html`\n <div class=\"list-item\" style=\"grid-template-columns: 1fr; gap: 6px;\">\n <div style=\"display: flex; align-items: center; gap: 8px; flex-wrap: wrap;\">\n <span class=${runStatusClass(entry.status)} style=\"font-size: 11px; padding: 2px 8px;\">\n ${entry.status}\n </span>\n <span class=\"muted\" style=\"font-size: 12px;\">${formatAgo(entry.ts)}</span>\n <span class=\"muted\" style=\"font-size: 12px;\">${formatDurationMs(entry.durationMs)}</span>\n </div>\n ${entry.summary\n ? html`<div class=\"muted\" style=\"font-size: 12px;\">${entry.summary}</div>`\n : nothing}\n ${entry.error\n ? html`\n <details style=\"margin-top: 2px;\">\n <summary class=\"muted\" style=\"cursor: pointer; font-size: 12px;\">Error details</summary>\n <div class=\"muted\" style=\"margin-top: 4px; white-space: pre-wrap; font-size: 12px;\">${entry.error}</div>\n </details>\n `\n : nothing}\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { clampText } from \"../format\";\nimport type { SkillStatusEntry, SkillStatusReport } from \"../types\";\nimport type { SkillMessageMap, SkillDetailData, SkillDraft, SkillFormSource } from \"../controllers/skills\";\n\nexport type SkillTypeFilter = \"all\" | \"preloaded\" | \"user\" | \"licensed\";\nexport type SkillAgentFilter = \"all\" | \"admin\" | \"public\";\n\nexport type SkillsProps = {\n loading: boolean;\n report: SkillStatusReport | null;\n error: string | null;\n filter: string;\n typeFilter: SkillTypeFilter;\n edits: Record<string, string>;\n busyKey: string | null;\n messages: SkillMessageMap;\n detail: SkillDetailData | null;\n detailTab: string;\n addModal: boolean;\n addForm: { name: string; skillContent: string; references: { name: string; content: string }[] };\n formSource: SkillFormSource;\n editTab: string;\n drafts: SkillDraft[];\n onFilterChange: (next: string) => void;\n onTypeFilterChange: (next: SkillTypeFilter) => void;\n onRefresh: () => void;\n onToggle: (skillKey: string, enabled: boolean) => void;\n onEdit: (skillKey: string, value: string) => void;\n onSaveKey: (skillKey: string) => void;\n onInstall: (skillKey: string, name: string, installId: string) => void;\n onViewDetail: (name: string) => void;\n onDetailClose: () => void;\n onDetailTab: (tab: string) => void;\n onAddOpen: () => void;\n onAddClose: () => void;\n onImportDraft: (draft: SkillDraft) => void;\n onInstallDraft: (draft: SkillDraft) => void;\n onDeleteDraft: (name: string) => void;\n onAddSave: () => void;\n onAddFormUpdate: (field: \"name\" | \"skillContent\", value: string) => void;\n onAlwaysActiveToggle: (name: string, alwaysActive: boolean) => void;\n onDelete: (name: string) => void;\n onEditSkill: (name: string) => void;\n onEditDetail: (activeTab?: string) => void;\n onRefUpdate: (refName: string, content: string) => void;\n onEditTab: (tab: string) => void;\n agentFilter: SkillAgentFilter;\n onAgentFilterChange: (next: SkillAgentFilter) => void;\n onAgentsChange: (skillKey: string, agents: string[]) => void;\n};\n\nexport function renderSkills(props: SkillsProps) {\n const skills = props.report?.skills ?? [];\n const filter = props.filter.trim().toLowerCase();\n const typeFilter = props.typeFilter;\n const agentFilter = props.agentFilter;\n const filtered = skills.filter((skill) => {\n if (typeFilter === \"preloaded\" && !skill.preloaded) return false;\n if (typeFilter === \"user\" && (skill.preloaded || skill.marketplace)) return false;\n if (typeFilter === \"licensed\" && !skill.marketplace) return false;\n if (agentFilter !== \"all\" && !skill.agents?.includes(agentFilter)) return false;\n if (filter) {\n return [skill.name, skill.description]\n .join(\" \")\n .toLowerCase()\n .includes(filter);\n }\n return true;\n });\n\n const typeChip = (label: string, value: SkillTypeFilter) => html`\n <button\n class=\"chip ${typeFilter === value ? \"chip-ok\" : \"\"}\"\n style=\"cursor: pointer; border: none; background: ${\n typeFilter === value ? \"var(--accent, #3b82f6)\" : \"var(--bg-hover, rgba(255,255,255,0.06))\"\n }; color: ${typeFilter === value ? \"#fff\" : \"var(--text)\"}; padding: 4px 10px; border-radius: 4px; font-size: 12px;\"\n @click=${() => props.onTypeFilterChange(value)}\n >${label}</button>\n `;\n\n const agentChip = (label: string, value: SkillAgentFilter) => html`\n <button\n class=\"chip ${agentFilter === value ? \"chip-ok\" : \"\"}\"\n style=\"cursor: pointer; border: none; background: ${\n agentFilter === value ? \"var(--accent, #3b82f6)\" : \"var(--bg-hover, rgba(255,255,255,0.06))\"\n }; color: ${agentFilter === value ? \"#fff\" : \"var(--text)\"}; padding: 4px 10px; border-radius: 4px; font-size: 12px;\"\n @click=${() => props.onAgentFilterChange(value)}\n >${label}</button>\n `;\n\n return html`\n <section class=\"card\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Skills</div>\n <div class=\"card-sub\">Preloaded and user skills.</div>\n </div>\n <div class=\"row\" style=\"gap: 8px;\">\n <button class=\"btn primary\" @click=${props.onAddOpen}>Drafts</button>\n <button class=\"btn\" ?disabled=${props.loading} @click=${props.onRefresh}>\n ${props.loading ? \"Loading…\" : \"Refresh\"}\n </button>\n </div>\n </div>\n\n <div class=\"filters\" style=\"margin-top: 14px;\">\n <label class=\"field\" style=\"flex: 1;\">\n <span>Filter</span>\n <input\n .value=${props.filter}\n @input=${(e: Event) =>\n props.onFilterChange((e.target as HTMLInputElement).value)}\n placeholder=\"Search skills\"\n />\n </label>\n <div class=\"chip-row\" style=\"gap: 4px;\">\n ${typeChip(\"All\", \"all\")}\n ${typeChip(\"Preloaded\", \"preloaded\")}\n ${typeChip(\"User\", \"user\")}\n ${typeChip(\"Licensed\", \"licensed\")}\n </div>\n <div class=\"chip-row\" style=\"gap: 4px;\">\n ${agentChip(\"All Agents\", \"all\")}\n ${agentChip(\"Admin\", \"admin\")}\n ${agentChip(\"Public\", \"public\")}\n </div>\n <div class=\"muted\">${filtered.length} shown</div>\n </div>\n\n ${props.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${props.error}</div>`\n : nothing}\n\n ${filtered.length === 0\n ? html`<div class=\"muted\" style=\"margin-top: 16px;\">No skills found.</div>`\n : html`\n <div class=\"list\" style=\"margin-top: 16px;\">\n ${filtered.map((skill) => renderSkill(skill, props))}\n </div>\n `}\n </section>\n\n ${props.detail ? renderDetailModal(props) : nothing}\n ${props.addModal ? renderAddModal(props) : nothing}\n `;\n}\n\nfunction renderSkill(skill: SkillStatusEntry, props: SkillsProps) {\n const busy = props.busyKey === skill.skillKey;\n const apiKey = props.edits[skill.skillKey] ?? \"\";\n const message = props.messages[skill.skillKey] ?? null;\n const canInstall =\n skill.install.length > 0 && skill.missing.bins.length > 0;\n const missing = [\n ...skill.missing.bins.map((b) => `bin:${b}`),\n ...skill.missing.env.map((e) => `env:${e}`),\n ...skill.missing.config.map((c) => `config:${c}`),\n ...skill.missing.os.map((o) => `os:${o}`),\n ];\n const reasons: string[] = [];\n if (skill.disabled) reasons.push(\"disabled\");\n if (skill.blockedByAllowlist) reasons.push(\"blocked by allowlist\");\n return html`\n <div class=\"list-item\" style=\"cursor: pointer;\" @click=${() => props.onViewDetail(skill.name)}>\n <div class=\"list-main\">\n <div class=\"list-title\">\n ${skill.emoji ? `${skill.emoji} ` : \"\"}${skill.name}\n </div>\n <div class=\"list-sub\">${clampText(skill.description, 140)}</div>\n <div class=\"chip-row\" style=\"margin-top: 6px;\">\n <span class=\"chip ${skill.preloaded ? \"chip-ok\" : \"\"}\">\n ${skill.marketplace ? \"Licensed\" : skill.preloaded ? \"Preloaded\" : \"User\"}\n </span>\n ${skill.marketplace && skill.marketplaceVersion\n ? html`<span class=\"chip\" style=\"color: var(--ok); border-color: rgba(34, 197, 94, 0.3); background: var(--ok-subtle);\">v${skill.marketplaceVersion}</span>`\n : nothing}\n ${skill.disabled ? html`<span class=\"chip chip-warn\">Disabled</span>` : nothing}\n ${!skill.preloaded\n ? html`<span\n class=\"chip ${skill.alwaysActive ? \"chip-ok\" : \"\"}\"\n style=\"cursor: pointer; user-select: none;\"\n title=${skill.alwaysActive\n ? \"This skill is part of every conversation. Click to switch to on-demand.\"\n : \"This skill loads only when relevant. Click to make it always active.\"}\n @click=${(e: Event) => {\n e.stopPropagation();\n props.onAlwaysActiveToggle(skill.name, !skill.alwaysActive);\n }}\n >${skill.alwaysActive ? \"Always active\" : \"On demand\"}</span>`\n : nothing}\n ${renderAgentCheckboxes(skill, props)}\n </div>\n ${missing.length > 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 6px;\">\n Missing: ${missing.join(\", \")}\n </div>\n `\n : nothing}\n ${reasons.length > 0\n ? html`\n <div class=\"muted\" style=\"margin-top: 6px;\">\n Reason: ${reasons.join(\", \")}\n </div>\n `\n : nothing}\n </div>\n <div class=\"list-meta\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"row\" style=\"justify-content: flex-end; flex-wrap: wrap; gap: 6px;\">\n ${skill.preloaded\n ? nothing\n : html`<button\n class=\"btn\"\n ?disabled=${busy}\n @click=${() => props.onToggle(skill.skillKey, skill.disabled)}\n >\n ${skill.disabled ? \"Enable\" : \"Disable\"}\n </button>`}\n ${!skill.preloaded\n ? html`<button\n class=\"btn\"\n ?disabled=${busy}\n @click=${() => props.onEditSkill(skill.name)}\n >\n Edit\n </button>`\n : nothing}\n ${!skill.preloaded\n ? html`<button\n class=\"btn danger\"\n ?disabled=${busy}\n @click=${() => {\n if (confirm(`Delete skill \"${skill.name}\"?`)) {\n props.onDelete(skill.name);\n }\n }}\n >\n Delete\n </button>`\n : nothing}\n ${canInstall\n ? html`<button\n class=\"btn\"\n ?disabled=${busy}\n @click=${() =>\n props.onInstall(skill.skillKey, skill.name, skill.install[0].id)}\n >\n ${busy ? \"Installing…\" : skill.install[0].label}\n </button>`\n : nothing}\n </div>\n ${message\n ? html`<div\n class=\"muted\"\n style=\"margin-top: 8px; color: ${\n message.kind === \"error\"\n ? \"var(--danger-color, #d14343)\"\n : \"var(--success-color, #0a7f5a)\"\n };\"\n >\n ${message.message}\n </div>`\n : nothing}\n ${skill.primaryEnv\n ? html`\n <div class=\"field\" style=\"margin-top: 10px;\">\n <span>API key</span>\n <input\n type=\"password\"\n .value=${apiKey}\n @input=${(e: Event) =>\n props.onEdit(skill.skillKey, (e.target as HTMLInputElement).value)}\n />\n </div>\n <button\n class=\"btn primary\"\n style=\"margin-top: 8px;\"\n ?disabled=${busy}\n @click=${() => props.onSaveKey(skill.skillKey)}\n >\n Save key\n </button>\n `\n : nothing}\n </div>\n </div>\n `;\n}\n\nfunction renderAgentCheckboxes(skill: SkillStatusEntry, props: SkillsProps) {\n const agents = skill.agents ?? [\"admin\", \"public\"];\n const locked = skill.agentsLocked;\n const hasAdmin = agents.includes(\"admin\");\n const hasPublic = agents.includes(\"public\");\n\n const toggle = (agent: string, checked: boolean) => {\n const next = checked\n ? [...agents, agent]\n : agents.filter((a) => a !== agent);\n if (next.length === 0) return;\n props.onAgentsChange(skill.skillKey, next);\n };\n\n return html`\n <span\n style=\"display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--text-muted, #888); margin-left: 4px; opacity: ${locked ? 0.6 : 1};\"\n @click=${(e: Event) => e.stopPropagation()}\n >\n <label style=\"display: inline-flex; align-items: center; gap: 2px; cursor: ${locked ? \"default\" : \"pointer\"};\">\n <input\n type=\"checkbox\"\n .checked=${hasAdmin}\n ?disabled=${locked}\n @change=${(e: Event) => toggle(\"admin\", (e.target as HTMLInputElement).checked)}\n style=\"margin: 0; accent-color: var(--accent, #3b82f6);\"\n />\n Admin\n </label>\n <label style=\"display: inline-flex; align-items: center; gap: 2px; cursor: ${locked ? \"default\" : \"pointer\"};\">\n <input\n type=\"checkbox\"\n .checked=${hasPublic}\n ?disabled=${locked}\n @change=${(e: Event) => toggle(\"public\", (e.target as HTMLInputElement).checked)}\n style=\"margin: 0; accent-color: var(--accent, #3b82f6);\"\n />\n Public\n </label>\n </span>\n `;\n}\n\n/* ── Detail modal ── */\n\nfunction renderDetailModal(props: SkillsProps) {\n const detail = props.detail!;\n const tabs = [\"SKILL.md\", ...detail.references.map((r) => r.name)];\n const activeTab = props.detailTab || \"SKILL.md\";\n const activeContent =\n activeTab === \"SKILL.md\"\n ? detail.content\n : detail.references.find((r) => r.name === activeTab)?.content ?? \"\";\n\n const handleOverlayClick = (e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"event-modal-overlay\")) {\n props.onDetailClose();\n }\n };\n\n // Check if this is a user skill (non-preloaded) by looking at the skills report\n const skillEntry = props.report?.skills?.find((s) => s.name === detail.name);\n const isUserSkill = skillEntry ? !skillEntry.preloaded : false;\n\n return html`\n <div class=\"event-modal-overlay\" @click=${handleOverlayClick}>\n <div class=\"event-modal\" style=\"width: min(720px, 100%);\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"event-modal__header\">\n <div class=\"event-modal__title\">${detail.name}</div>\n <div class=\"row\" style=\"gap: 8px;\">\n ${isUserSkill\n ? html`<button class=\"btn\" @click=${() => props.onEditDetail(activeTab)}>Edit</button>`\n : nothing}\n <button class=\"event-modal__close\" @click=${props.onDetailClose}>&times;</button>\n </div>\n </div>\n ${tabs.length > 1\n ? html`\n <div class=\"chip-row\" style=\"margin-bottom: 12px; flex-wrap: wrap;\">\n ${tabs.map(\n (tab) => html`\n <button\n class=\"chip ${tab === activeTab ? \"chip-ok\" : \"\"}\"\n style=\"cursor: pointer; border: none; background: ${\n tab === activeTab ? \"var(--accent, #3b82f6)\" : \"var(--bg-hover, rgba(255,255,255,0.06))\"\n }; color: ${tab === activeTab ? \"#fff\" : \"var(--text)\"}; padding: 4px 10px; border-radius: 4px; font-size: 12px;\"\n @click=${() => props.onDetailTab(tab)}\n >\n ${tab}\n </button>\n `,\n )}\n </div>\n `\n : nothing}\n <pre style=\"white-space: pre-wrap; word-break: break-word; font-size: 12px; line-height: 1.5; max-height: 60vh; overflow-y: auto; background: var(--bg, #111); padding: 16px; border-radius: 8px; border: 1px solid var(--border);\">${activeContent}</pre>\n </div>\n </div>\n `;\n}\n\n/* ── Add Skill modal ── */\n\nfunction renderAddModal(props: SkillsProps) {\n const hasDrafts = props.drafts.length > 0;\n const busy = props.busyKey === \"__add__\";\n const formActive = props.addForm.name.trim() !== \"\";\n const isInstalled = props.formSource === \"installed\";\n\n const handleOverlayClick = (e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"event-modal-overlay\")) {\n props.onAddClose();\n }\n };\n\n const title = formActive\n ? isInstalled\n ? `Edit Skill: ${props.addForm.name}`\n : `Edit Draft: ${props.addForm.name}`\n : \"Skill Drafts\";\n\n return html`\n <div class=\"event-modal-overlay\" @click=${handleOverlayClick}>\n <div class=\"event-modal\" style=\"width: min(620px, 100%);\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"event-modal__header\">\n <div class=\"event-modal__title\">${title}</div>\n <button class=\"event-modal__close\" @click=${props.onAddClose}>&times;</button>\n </div>\n\n ${formActive\n ? renderSkillForm(props, busy)\n : hasDrafts\n ? renderDraftsList(props, busy)\n : html`\n <div class=\"muted\" style=\"text-align: center; padding: 32px 16px;\">\n No drafts available. Ask your assistant to create a skill and it will appear here.\n </div>\n `}\n </div>\n </div>\n `;\n}\n\nfunction renderSkillForm(props: SkillsProps, busy: boolean) {\n const form = props.addForm;\n const isInstalled = props.formSource === \"installed\";\n const saveLabel = isInstalled ? \"Save Skill\" : \"Save Draft\";\n const hasRefs = form.references.length > 0;\n const activeTab = props.editTab || \"SKILL.md\";\n const activeRef = form.references.find((r) => r.name === activeTab);\n\n const tabChip = (tab: string) => html`\n <button\n class=\"chip ${tab === activeTab ? \"chip-ok\" : \"\"}\"\n style=\"cursor: pointer; border: none; background: ${\n tab === activeTab ? \"var(--accent, #3b82f6)\" : \"var(--bg-hover, rgba(255,255,255,0.06))\"\n }; color: ${tab === activeTab ? \"#fff\" : \"var(--text)\"}; padding: 4px 10px; border-radius: 4px; font-size: 12px;\"\n @click=${() => props.onEditTab(tab)}\n >${tab}</button>\n `;\n\n return html`\n <label class=\"field\" style=\"margin-bottom: 12px;\">\n <span>Name</span>\n <input\n .value=${form.name}\n @input=${(e: Event) => props.onAddFormUpdate(\"name\", (e.target as HTMLInputElement).value)}\n placeholder=\"my-skill\"\n />\n </label>\n ${hasRefs\n ? html`\n <div class=\"chip-row\" style=\"margin-bottom: 12px; flex-wrap: wrap; gap: 4px;\">\n ${tabChip(\"SKILL.md\")}\n ${form.references.map((r) => tabChip(r.name))}\n </div>\n `\n : nothing}\n ${activeRef\n ? html`\n <label class=\"field\" style=\"margin-bottom: 12px;\">\n <span>${activeRef.name}</span>\n <textarea\n .value=${activeRef.content}\n @input=${(e: Event) => props.onRefUpdate(activeRef.name, (e.target as HTMLTextAreaElement).value)}\n style=\"min-height: 260px; font-family: monospace; font-size: 12px; line-height: 1.5; resize: vertical; overflow-wrap: break-word; white-space: pre-wrap;\"\n ></textarea>\n </label>\n `\n : html`\n <label class=\"field\" style=\"margin-bottom: 12px;\">\n <span>SKILL.md</span>\n <textarea\n .value=${form.skillContent}\n @input=${(e: Event) => props.onAddFormUpdate(\"skillContent\", (e.target as HTMLTextAreaElement).value)}\n style=\"min-height: 260px; font-family: monospace; font-size: 12px; line-height: 1.5; resize: vertical; overflow-wrap: break-word; white-space: pre-wrap;\"\n placeholder=\"---\\nname: my-skill\\ndescription: What this skill does\\n---\\n\\n# My Skill\\n...\"\n ></textarea>\n </label>\n `}\n <div class=\"row\" style=\"gap: 8px; justify-content: flex-end;\">\n <button class=\"btn\" @click=${props.onAddClose}>Cancel</button>\n <button\n class=\"btn primary\"\n ?disabled=${busy || !form.name.trim() || !form.skillContent.trim()}\n @click=${props.onAddSave}\n >\n ${busy ? \"Saving…\" : saveLabel}\n </button>\n </div>\n `;\n}\n\nfunction renderDraftsList(props: SkillsProps, busy: boolean) {\n return html`\n <div class=\"card-sub\" style=\"margin-bottom: 16px;\">\n Skills prepared by your assistant. Review, install, or delete.\n </div>\n <div class=\"list\">\n ${props.drafts.map(\n (draft) => {\n const alreadyInstalled = props.report?.skills?.some((s) => s.name === draft.name) ?? false;\n return html`\n <div class=\"list-item\">\n <div class=\"list-main\">\n <div class=\"list-title\">${draft.name}</div>\n <div class=\"list-sub\">\n ${draft.references.length > 0\n ? `SKILL.md + ${draft.references.length} reference${draft.references.length > 1 ? \"s\" : \"\"}`\n : \"SKILL.md\"}\n </div>\n </div>\n <div class=\"list-meta\">\n <div class=\"row\" style=\"gap: 6px;\">\n <button\n class=\"btn\"\n ?disabled=${busy}\n @click=${() => props.onImportDraft(draft)}\n >\n Edit\n </button>\n ${alreadyInstalled\n ? html`<span class=\"chip chip-ok\" style=\"padding: 4px 10px; font-size: 12px;\">Installed</span>`\n : html`<button\n class=\"btn primary\"\n ?disabled=${busy}\n @click=${() => props.onInstallDraft(draft)}\n >\n ${busy ? \"Installing…\" : \"Install\"}\n </button>`}\n <button\n class=\"btn danger\"\n ?disabled=${busy}\n @click=${() => props.onDeleteDraft(draft.name)}\n >\n Delete\n </button>\n </div>\n </div>\n </div>\n `},\n )}\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { SessionTranscriptEntry, SessionLogType } from \"../types\";\nimport { icons } from \"../icons\";\n\n/** Filter chip types shown in the UI. Legacy \"tool\" entries are treated as tool_call. */\nconst TYPES: SessionLogType[] = [\n \"user\",\n \"assistant\",\n \"tool_call\",\n \"tool_result\",\n \"thinking\",\n \"error\",\n];\n\nexport type SessionLogsProps = {\n loading: boolean;\n error: string | null;\n entries: SessionTranscriptEntry[];\n agents: string[];\n filterText: string;\n typeFilters: Record<SessionLogType, boolean>;\n agentFilters: Record<string, boolean>;\n autoFollow: boolean;\n chipsExpanded: boolean;\n expandedIds: Set<string>;\n onFilterTextChange: (next: string) => void;\n onTypeToggle: (type: SessionLogType, enabled: boolean) => void;\n onAgentToggle: (agent: string, enabled: boolean) => void;\n onToggleAutoFollow: (next: boolean) => void;\n onToggleChips: () => void;\n onToggleExpand: (id: string) => void;\n onRefresh: () => void;\n onExport: (lines: string[], label: string) => void;\n onScroll: (event: Event) => void;\n};\n\nconst TYPE_LABELS: Record<SessionLogType, string> = {\n user: \"User\",\n assistant: \"Assistant\",\n tool: \"Tool\",\n tool_call: \"Call\",\n tool_result: \"Result\",\n thinking: \"Thinking\",\n error: \"Error\",\n system: \"System\",\n};\n\n/** Resolve the display type for an entry.\n * - Legacy \"tool\" maps to \"tool_call\".\n * - \"tool_result\" entries with [error] content are surfaced as \"error\". */\nfunction resolveDisplayType(type: SessionLogType, content?: string): SessionLogType {\n if (type === \"tool\") return \"tool_call\";\n if (type === \"tool_result\" && typeof content === \"string\" && content.startsWith(\"[error]\")) return \"error\";\n return type;\n}\n\nfunction formatTime(value?: string) {\n if (!value) return \"\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n return date.toLocaleString(undefined, {\n day: \"numeric\",\n month: \"short\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n}\n\nfunction formatSessionLabel(key: string): string {\n // \"agent:public:dm:+447...\" → \"+447...\"\n // \"agent:admin:main\" → \"main\"\n const parts = key.split(\":\");\n return parts.slice(2).join(\":\") || key;\n}\n\nfunction matchesFilter(entry: SessionTranscriptEntry, needle: string) {\n if (!needle) return true;\n const haystack = [entry.content, entry.agentId, entry.sessionKey, entry.sessionId, entry.toolName, entry.toolCallId]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return haystack.includes(needle);\n}\n\n/** Generate a stable key for expand/collapse state. */\nfunction entryKey(entry: SessionTranscriptEntry, index: number): string {\n return `${entry.sessionId}:${entry.timestamp}:${index}`;\n}\n\nconst CONTENT_PREVIEW_LENGTH = 300;\n\nfunction passesTypeFilter(\n entry: SessionTranscriptEntry,\n typeFilters: Record<SessionLogType, boolean>,\n): boolean {\n const display = resolveDisplayType(entry.type, entry.content);\n return typeFilters[display] ?? true;\n}\n\nexport function renderSessionLogs(props: SessionLogsProps) {\n const needle = props.filterText.trim().toLowerCase();\n const filtered = props.entries.filter((entry) => {\n if (!passesTypeFilter(entry, props.typeFilters)) return false;\n if (props.agents.length > 0 && !(props.agentFilters[entry.agentId] ?? true)) return false;\n return matchesFilter(entry, needle);\n });\n\n return html`\n <div>\n <button class=\"chips-toggle\" style=\"margin-top: 10px;\" @click=${props.onToggleChips}>\n <span class=\"chips-toggle-icon ${props.chipsExpanded ? \"expanded\" : \"\"}\">${icons.chevronDown}</span>\n Filters\n </button>\n ${props.chipsExpanded ? html`\n <div class=\"chip-row\" style=\"margin-top: 6px;\">\n ${TYPES.map(\n (type) => html`\n <label class=\"chip session-log-chip ${type}\">\n <input\n type=\"checkbox\"\n .checked=${props.typeFilters[type]}\n @change=${(e: Event) =>\n props.onTypeToggle(type, (e.target as HTMLInputElement).checked)}\n />\n <span>${TYPE_LABELS[type]}</span>\n </label>\n `,\n )}\n ${props.agents.map(\n (agent) => html`\n <label class=\"chip agent-chip\">\n <input\n type=\"checkbox\"\n .checked=${props.agentFilters[agent] ?? true}\n @change=${(e: Event) =>\n props.onAgentToggle(agent, (e.target as HTMLInputElement).checked)}\n />\n <span>${agent}</span>\n </label>\n `,\n )}\n <label class=\"chip\">\n <input\n type=\"checkbox\"\n .checked=${props.autoFollow}\n @change=${(e: Event) =>\n props.onToggleAutoFollow((e.target as HTMLInputElement).checked)}\n />\n <span>Auto-follow</span>\n </label>\n </div>\n ` : nothing}\n\n ${props.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 10px;\">${props.error}</div>`\n : nothing}\n\n <div class=\"log-stream\" style=\"margin-top: 10px;\" @scroll=${props.onScroll}>\n ${filtered.length === 0\n ? html`<div class=\"muted\" style=\"padding: 12px;\">No session log entries.</div>`\n : filtered.map((entry, idx) => {\n const display = resolveDisplayType(entry.type, entry.content);\n const id = entryKey(entry, idx);\n const expanded = props.expandedIds.has(id);\n const isLong = entry.content.length > CONTENT_PREVIEW_LENGTH;\n const content = expanded || !isLong\n ? entry.content\n : entry.content.slice(0, CONTENT_PREVIEW_LENGTH) + \"\\u2026\";\n\n return html`\n <div class=\"log-row session-entry ${display}\">\n <div class=\"log-row-header\">\n <span class=\"log-time mono\">${formatTime(entry.timestamp)}</span>\n <span class=\"session-log-type ${display}\">${TYPE_LABELS[display]}</span>\n <span class=\"log-subsystem mono\">${entry.agentId}</span>\n <span class=\"session-label mono\">${formatSessionLabel(entry.sessionKey)}</span>\n ${entry.toolName\n ? html`<span class=\"session-tool mono\">${entry.toolName}</span>`\n : nothing}\n ${entry.toolCallId\n ? html`<span class=\"session-call-id mono\">${entry.toolCallId.slice(0, 12)}</span>`\n : nothing}\n ${entry.model\n ? html`<span class=\"session-model mono\">${entry.model}</span>`\n : nothing}\n </div>\n <div class=\"log-message mono\">${content}</div>\n ${isLong\n ? html`<button\n class=\"log-expand-btn\"\n @click=${() => props.onToggleExpand(id)}\n >${expanded ? \"Collapse\" : \"Expand\"}</button>`\n : nothing}\n </div>\n `;\n })}\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { LogEntry, LogLevel } from \"../types\";\nimport { icons } from \"../icons\";\nimport { renderSessionLogs, type SessionLogsProps } from \"./session-logs\";\n\nconst LEVELS: LogLevel[] = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"];\n\nexport type LogsProps = {\n // Sub-tab state\n logsSubTab: \"system\" | \"session\";\n onSubTabChange: (tab: \"system\" | \"session\") => void;\n /** True when the current PIN session is master (admin). System logs are only shown to admin. */\n isAdmin: boolean;\n // Session logs props (passed through when sub-tab is \"session\")\n sessionLogsProps: SessionLogsProps;\n // Existing system logs props\n loading: boolean;\n error: string | null;\n file: string | null;\n entries: LogEntry[];\n filterText: string;\n levelFilters: Record<LogLevel, boolean>;\n autoFollow: boolean;\n truncated: boolean;\n /** Currently selected date (YYYY-MM-DD), or null for today (live). */\n selectedDate: string | null;\n /** Available log dates, most recent first. */\n availableDates: string[];\n onDateChange: (date: string | null) => void;\n onFilterTextChange: (next: string) => void;\n onLevelToggle: (level: LogLevel, enabled: boolean) => void;\n onToggleAutoFollow: (next: boolean) => void;\n chipsExpanded: boolean;\n onToggleChips: () => void;\n onRefresh: () => void;\n onExport: (lines: string[], label: string) => void;\n onScroll: (event: Event) => void;\n};\n\nfunction formatTime(value?: string | null) {\n if (!value) return \"\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n return date.toLocaleTimeString();\n}\n\nfunction matchesFilter(entry: LogEntry, needle: string) {\n if (!needle) return true;\n const haystack = [entry.message, entry.subsystem, entry.raw]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return haystack.includes(needle);\n}\n\nexport function renderLogs(props: LogsProps) {\n // Non-admin users cannot access system logs (cross-account, unscoped).\n // Force the sub-tab to \"session\" if the user is not admin.\n const isSession = !props.isAdmin || props.logsSubTab === \"session\";\n\n return html`\n <section class=\"card\">\n <div class=\"logs-toolbar\">\n <div class=\"sp-tabs\" style=\"margin: 0;\">\n <button class=\"sp-tab ${isSession ? 'active' : ''}\"\n @click=${() => props.onSubTabChange('session')}>\n Session\n </button>\n ${props.isAdmin ? html`\n <button class=\"sp-tab ${!isSession ? 'active' : ''}\"\n @click=${() => props.onSubTabChange('system')}>\n System\n </button>\n ` : nothing}\n </div>\n\n ${isSession ? html`\n <input\n class=\"logs-filter-input\"\n .value=${props.sessionLogsProps.filterText}\n @input=${(e: Event) =>\n props.sessionLogsProps.onFilterTextChange((e.target as HTMLInputElement).value)}\n placeholder=\"Filter\"\n />\n ` : html`\n <input\n class=\"logs-filter-input\"\n .value=${props.filterText}\n @input=${(e: Event) =>\n props.onFilterTextChange((e.target as HTMLInputElement).value)}\n placeholder=\"Filter\"\n />\n `}\n\n <div class=\"row\" style=\"gap: 6px; flex-shrink: 0;\">\n ${isSession ? html`\n <button class=\"btn btn-sm\" ?disabled=${props.sessionLogsProps.loading} @click=${props.sessionLogsProps.onRefresh}>\n ${props.sessionLogsProps.loading ? \"Loading\\u2026\" : \"Refresh\"}\n </button>\n <button\n class=\"btn btn-sm\"\n ?disabled=${props.sessionLogsProps.entries.length === 0}\n @click=${() => {\n const sp = props.sessionLogsProps;\n const needle = sp.filterText.trim().toLowerCase();\n const filtered = sp.entries.filter((entry) => {\n const displayType = entry.type === \"tool\" ? \"tool_call\" : entry.type;\n if (!sp.typeFilters[displayType]) return false;\n if (sp.agents.length > 0 && !(sp.agentFilters[entry.agentId] ?? true)) return false;\n if (!needle) return true;\n return [entry.content, entry.agentId, entry.sessionKey, entry.sessionId, entry.toolName, entry.toolCallId]\n .filter(Boolean).join(\" \").toLowerCase().includes(needle);\n });\n const lines = filtered.map((e) =>\n `${e.timestamp}\\t[${e.type}]\\t${e.agentId}\\t${e.sessionKey}\\t${e.toolName ?? \"\"}\\t${e.content}`);\n sp.onExport(lines, needle ? \"filtered\" : \"visible\");\n }}\n >\n Export\n </button>\n ` : html`\n <button class=\"btn btn-sm\" ?disabled=${props.loading} @click=${props.onRefresh}>\n ${props.loading ? \"Loading\\u2026\" : \"Refresh\"}\n </button>\n <button\n class=\"btn btn-sm\"\n ?disabled=${props.entries.length === 0}\n @click=${() => {\n const needle = props.filterText.trim().toLowerCase();\n const levelFiltered = LEVELS.some((level) => !props.levelFilters[level]);\n const filtered = props.entries.filter((entry) => {\n if (entry.level && !props.levelFilters[entry.level]) return false;\n return matchesFilter(entry, needle);\n });\n const exportLabel = needle || levelFiltered ? \"filtered\" : \"visible\";\n props.onExport(filtered.map((entry) => entry.raw), exportLabel);\n }}\n >\n Export\n </button>\n `}\n </div>\n </div>\n\n ${isSession\n ? renderSessionLogs(props.sessionLogsProps)\n : renderSystemLogs(props)}\n </section>\n `;\n}\n\nfunction renderSystemLogs(props: LogsProps) {\n const needle = props.filterText.trim().toLowerCase();\n const levelFiltered = LEVELS.some((level) => !props.levelFilters[level]);\n const filtered = props.entries.filter((entry) => {\n if (entry.level && !props.levelFilters[entry.level]) return false;\n return matchesFilter(entry, needle);\n });\n\n const dates = props.availableDates;\n const currentDate = props.selectedDate ?? (dates.length > 0 ? dates[0] : null);\n const currentIndex = currentDate ? dates.indexOf(currentDate) : 0;\n const hasNewer = currentIndex > 0 || props.selectedDate != null;\n const hasOlder = currentIndex >= 0 && currentIndex < dates.length - 1;\n\n return html`\n ${dates.length > 1 ? html`\n <div class=\"logs-date-nav\">\n <button class=\"btn btn-sm\" ?disabled=${!hasOlder}\n @click=${() => {\n const nextIdx = currentIndex + 1;\n if (nextIdx < dates.length) props.onDateChange(dates[nextIdx]);\n }}>${icons.chevronLeft} Older</button>\n <span class=\"logs-date-label\">${currentDate ?? \"Today\"}</span>\n <button class=\"btn btn-sm\" ?disabled=${!hasNewer}\n @click=${() => {\n if (currentIndex <= 0) {\n props.onDateChange(null);\n } else {\n props.onDateChange(dates[currentIndex - 1]);\n }\n }}>Newer ${icons.chevronRight}</button>\n ${props.selectedDate != null ? html`\n <button class=\"btn btn-sm\" @click=${() => props.onDateChange(null)}>\n Today\n </button>\n ` : nothing}\n </div>\n ` : nothing}\n\n <button class=\"chips-toggle\" @click=${props.onToggleChips}>\n <span class=\"chips-toggle-icon ${props.chipsExpanded ? \"expanded\" : \"\"}\">${icons.chevronDown}</span>\n Filters\n </button>\n ${props.chipsExpanded ? html`\n <div class=\"chip-row\" style=\"margin-top: 6px; align-items: center;\">\n ${LEVELS.map(\n (level) => html`\n <label class=\"chip log-chip ${level}\">\n <input\n type=\"checkbox\"\n .checked=${props.levelFilters[level]}\n @change=${(e: Event) =>\n props.onLevelToggle(level, (e.target as HTMLInputElement).checked)}\n />\n <span>${level}</span>\n </label>\n `,\n )}\n <label class=\"chip\">\n <input\n type=\"checkbox\"\n .checked=${props.autoFollow}\n @change=${(e: Event) =>\n props.onToggleAutoFollow((e.target as HTMLInputElement).checked)}\n />\n <span>Auto-follow</span>\n </label>\n </div>\n ` : nothing}\n\n ${props.file\n ? html`<div class=\"muted\" style=\"margin-top: 10px;\">File: ${props.file}</div>`\n : nothing}\n ${props.truncated\n ? html`<div class=\"callout\" style=\"margin-top: 10px;\">\n Log output truncated; showing latest chunk.\n </div>`\n : nothing}\n ${props.error\n ? html`<div class=\"callout danger\" style=\"margin-top: 10px;\">${props.error}</div>`\n : nothing}\n\n <div class=\"log-stream\" style=\"margin-top: 10px;\" @scroll=${props.onScroll}>\n ${filtered.length === 0\n ? html`<div class=\"muted\" style=\"padding: 12px;\">No log entries.</div>`\n : [...filtered].reverse().map(\n (entry) => html`\n <div class=\"log-row\">\n <div class=\"log-row-header\">\n <span class=\"log-time mono\">${formatTime(entry.time)}</span>\n <span class=\"log-level ${entry.level ?? \"\"}\">${entry.level ?? \"\"}</span>\n <span class=\"log-subsystem mono\">${entry.subsystem ?? \"\"}</span>\n </div>\n <div class=\"log-message mono\">${entry.message ?? entry.raw}</div>\n </div>\n `,\n )}\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport type { OpeningHoursFormState } from \"../controllers/opening-hours.js\";\n\n/* ── Props ── */\n\nexport type OpeningHoursProps = {\n loading: boolean;\n error: string | null;\n busy: boolean;\n form: OpeningHoursFormState;\n onFormChange: (patch: Partial<OpeningHoursFormState>) => void;\n onDayChange: (day: string, field: string, value: string | boolean) => void;\n onAddClosedDate: (date: string) => void;\n onRemoveClosedDate: (date: string) => void;\n onSave: () => void;\n};\n\n/* ── Constants ── */\n\nconst DAY_LABELS: { key: string; label: string }[] = [\n { key: \"monday\", label: \"Monday\" },\n { key: \"tuesday\", label: \"Tuesday\" },\n { key: \"wednesday\", label: \"Wednesday\" },\n { key: \"thursday\", label: \"Thursday\" },\n { key: \"friday\", label: \"Friday\" },\n { key: \"saturday\", label: \"Saturday\" },\n { key: \"sunday\", label: \"Sunday\" },\n];\n\n/* ── SVG icons ── */\n\nconst iconX = html`<svg viewBox=\"0 0 24 24\"><path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/></svg>`;\nconst iconPlus = html`<svg viewBox=\"0 0 24 24\"><path d=\"M12 5v14\"/><path d=\"M5 12h14\"/></svg>`;\n\n/* ── Main render ── */\n\nexport function renderOpeningHours(props: OpeningHoursProps) {\n return html`\n ${renderEnabledToggle(props)}\n ${renderPublicAgentToggle(props)}\n ${renderWeeklySchedule(props)}\n ${renderClosedDates(props)}\n ${renderSaveButton(props)}\n `;\n}\n\n/* ── Enabled toggle ── */\n\nfunction renderEnabledToggle(props: OpeningHoursProps) {\n return html`\n <label class=\"field checkbox\" style=\"margin: 16px 0;\">\n <input\n type=\"checkbox\"\n .checked=${props.form.enabled}\n @change=${(e: Event) =>\n props.onFormChange({ enabled: (e.target as HTMLInputElement).checked })}\n />\n <span style=\"margin-left: 8px;\">\n Enable opening hours\n <span class=\"muted\" style=\"font-size: 12px; display: block; margin-top: 2px;\">\n When enabled, the public assistant does not respond outside the scheduled hours below.\n </span>\n </span>\n </label>\n `;\n}\n\n/* ── Public agent responds toggle ── */\n\nfunction renderPublicAgentToggle(props: OpeningHoursProps) {\n const hoursEnabled = props.form.enabled;\n return html`\n <label\n class=\"field checkbox\"\n style=\"margin: 0 0 16px; ${hoursEnabled ? \"\" : \"opacity: 0.4; pointer-events: none;\"}\"\n >\n <input\n type=\"checkbox\"\n .checked=${props.form.publicAgentEnabled}\n ?disabled=${!hoursEnabled}\n @change=${(e: Event) =>\n props.onFormChange({ publicAgentEnabled: (e.target as HTMLInputElement).checked })}\n />\n <span style=\"margin-left: 8px;\">\n Public agent responds during opening hours\n <span class=\"muted\" style=\"font-size: 12px; display: block; margin-top: 2px;\">\n ${hoursEnabled\n ? \"When disabled, the assistant is silenced during opening hours — useful as a temporary override without changing the schedule.\"\n : \"Enable opening hours first.\"}\n </span>\n </span>\n </label>\n `;\n}\n\n/* ── Weekly schedule ── */\n\nfunction renderWeeklySchedule(props: OpeningHoursProps) {\n return html`\n <div style=\"margin-bottom: 20px;\">\n <div style=\"font-size: 14px; font-weight: 500; margin-bottom: 12px;\">Weekly Schedule</div>\n <div class=\"oh-schedule\">\n ${DAY_LABELS.map((day) => renderDayRow(day, props))}\n </div>\n </div>\n `;\n}\n\nfunction renderDayRow(day: { key: string; label: string }, props: OpeningHoursProps) {\n const dayState = props.form.days[day.key];\n if (!dayState) return nothing;\n const isClosed = dayState.closed;\n\n return html`\n <div class=\"oh-day-row\">\n <div class=\"oh-day-label\">${day.label}</div>\n <div class=\"oh-day-times\" style=\"${isClosed ? \"opacity: 0.35; pointer-events: none;\" : \"\"}\">\n <input\n type=\"time\"\n .value=${dayState.start}\n @input=${(e: Event) =>\n props.onDayChange(day.key, \"start\", (e.target as HTMLInputElement).value)}\n />\n <span class=\"oh-time-sep\">&ndash;</span>\n <input\n type=\"time\"\n .value=${dayState.end}\n @input=${(e: Event) =>\n props.onDayChange(day.key, \"end\", (e.target as HTMLInputElement).value)}\n />\n </div>\n <label class=\"oh-closed-toggle\">\n <input\n type=\"checkbox\"\n .checked=${isClosed}\n @change=${(e: Event) =>\n props.onDayChange(day.key, \"closed\", (e.target as HTMLInputElement).checked)}\n />\n <span>Closed</span>\n </label>\n </div>\n `;\n}\n\n/* ── Closed dates ── */\n\nlet _newClosedDate = \"\";\n\nfunction renderClosedDates(props: OpeningHoursProps) {\n const dates = props.form.closedDates;\n\n return html`\n <div style=\"margin-bottom: 20px;\">\n <div style=\"font-size: 14px; font-weight: 500; margin-bottom: 10px;\">Closed Dates</div>\n <div style=\"display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px;\">\n ${dates.length === 0\n ? html`<span class=\"muted\" style=\"font-size: 13px;\">No closed dates.</span>`\n : dates.map(\n (date) => html`\n <span class=\"chip chip-warn\" style=\"display: inline-flex; align-items: center; gap: 4px;\">\n ${date}\n <button\n class=\"btn-icon\"\n style=\"width: 16px; height: 16px; padding: 0;\"\n @click=${() => props.onRemoveClosedDate(date)}\n >\n ${iconX}\n </button>\n </span>\n `,\n )}\n </div>\n <div style=\"display: flex; align-items: center; gap: 8px;\">\n <input\n type=\"date\"\n id=\"oh-new-closed-date\"\n class=\"oh-date-input\"\n @change=${(e: Event) => { _newClosedDate = (e.target as HTMLInputElement).value; }}\n />\n <button\n class=\"btn btn--sm\"\n @click=${() => {\n if (_newClosedDate) {\n props.onAddClosedDate(_newClosedDate);\n const el = document.getElementById(\"oh-new-closed-date\") as HTMLInputElement | null;\n if (el) el.value = \"\";\n _newClosedDate = \"\";\n }\n }}\n >\n ${iconPlus} Add\n </button>\n </div>\n </div>\n `;\n}\n\n/* ── Save button ── */\n\nfunction renderSaveButton(props: OpeningHoursProps) {\n return html`\n <div style=\"display: flex; justify-content: flex-end; padding-top: 8px;\">\n <button\n class=\"btn primary\"\n ?disabled=${props.busy}\n @click=${props.onSave}\n >\n ${props.busy ? \"Saving\\u2026\" : \"Save\"}\n </button>\n </div>\n `;\n}\n","import { html } from \"lit\";\n\nimport type { CronProps } from \"./cron\";\nimport type { SkillsProps } from \"./skills\";\nimport type { LogsProps } from \"./logs\";\nimport type { OpeningHoursProps } from \"./opening-hours\";\nimport { renderCron } from \"./cron\";\nimport { renderSkills } from \"./skills\";\nimport { renderLogs } from \"./logs\";\nimport { renderOpeningHours } from \"./opening-hours\";\nimport { renderPageNav, type WorkspaceNavProps } from \"./page-nav\";\n\nexport type AdvancedTab = \"cron\" | \"skills\" | \"logs\" | \"opening-hours\";\n\nexport type AdvancedPageProps = {\n connected: boolean;\n wsProps?: WorkspaceNavProps;\n activeTab: AdvancedTab;\n onTabChange: (tab: AdvancedTab) => void;\n cronProps: CronProps;\n skillsProps: SkillsProps;\n logsProps: LogsProps;\n openingHoursProps: OpeningHoursProps;\n};\n\nconst TABS: { id: AdvancedTab; label: string }[] = [\n { id: \"cron\", label: \"Events\" },\n { id: \"skills\", label: \"Skills\" },\n { id: \"opening-hours\", label: \"Opening Hours\" },\n { id: \"logs\", label: \"Logs\" },\n];\n\nfunction renderTabContent(props: AdvancedPageProps) {\n switch (props.activeTab) {\n case \"cron\":\n return renderCron(props.cronProps);\n case \"skills\":\n return renderSkills(props.skillsProps);\n case \"opening-hours\":\n return renderOpeningHours(props.openingHoursProps);\n case \"logs\":\n return renderLogs(props.logsProps);\n default:\n return renderCron(props.cronProps);\n }\n}\n\nexport function renderAdvancedPage(props: AdvancedPageProps) {\n if (!props.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting to gateway...</p>\n </div>\n </div>\n `;\n }\n\n return html`\n <div class=\"setup-container\">\n ${renderPageNav(\"Advanced\", props.wsProps)}\n <div class=\"setup-card sp-card-advanced\" style=\"text-align: left;\">\n <div class=\"sp-tabs\">\n ${TABS.map(\n (tab) => html`\n <button\n class=\"sp-tab ${props.activeTab === tab.id ? \"active\" : \"\"}\"\n @click=${() => props.onTabChange(tab.id)}\n >\n ${tab.label}\n </button>\n `,\n )}\n </div>\n ${renderTabContent(props)}\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { resolveBrand } from \"../brand\";\nimport type { AccessAccount } from \"../controllers/access\";\nimport { icons } from \"../icons\";\n\nexport type LoginOverlayState = {\n /** Whether the login overlay should be visible. */\n show: boolean;\n /** Whether this is first-time setup (no master PIN yet). */\n isFirstTime: boolean;\n /** Available accounts for the selector. */\n accounts: AccessAccount[];\n /** Error message from last attempt. */\n error: string | null;\n /** Whether a request is in flight. */\n busy: boolean;\n /** Callback when PIN is submitted. For login: (account, pin). For first-time: (pin) only. */\n onSubmit: (accountOrPin: string, pin?: string) => void;\n /** Whether Change PIN mode is active. */\n changePinMode?: boolean;\n /** Toggle between login and change-PIN mode. */\n onToggleChangePinMode?: () => void;\n /** Whether a change-PIN request is in flight. */\n changePinBusy?: boolean;\n /** Error from the change-PIN flow. */\n changePinError?: string | null;\n /** Success message after PIN changed. */\n changePinSuccess?: string | null;\n /** Callback to change PIN: (account, oldPin, newPin). */\n onChangePin?: (account: string, oldPin: string, newPin: string) => void;\n};\n\n/**\n * Full-screen login overlay.\n * First-time: \"Set your device PIN\" (no account selector).\n * Returning: account selector + PIN input + \"Change PIN\" link.\n * Change-PIN mode: account selector + current PIN + new PIN + confirm.\n */\nexport function renderLoginOverlay(state: LoginOverlayState) {\n if (!state.show) return nothing;\n\n const brand = resolveBrand();\n const isFirstTime = state.isFirstTime;\n const isChangeMode = state.changePinMode === true && !isFirstTime;\n const changeBusy = state.changePinBusy === true;\n\n let selectedAccount = state.accounts.length > 0 ? state.accounts[0].id : \"\";\n\n const handleAccountChange = (e: Event) => {\n selectedAccount = (e.target as HTMLSelectElement).value;\n // Toggle \"Change PIN\" link visibility — only shown for admin\n const link = (e.target as HTMLElement).closest(\".login-card\")?.querySelector(\".login-change-pin\");\n if (link) (link as HTMLElement).style.display = selectedAccount === \"__master__\" ? \"\" : \"none\";\n };\n\n const pinInputHandler = (setter: (v: string) => void) => (e: Event) => {\n const input = e.target as HTMLInputElement;\n input.value = input.value.replace(/\\D/g, \"\").slice(0, 6);\n setter(input.value);\n };\n\n const togglePinVisibility = (e: Event) => {\n const btn = (e.currentTarget as HTMLElement);\n const wrapper = btn.closest(\".login-pin-wrapper\") as HTMLElement;\n const input = wrapper?.querySelector(\"input\") as HTMLInputElement | null;\n if (!input) return;\n const visible = input.type === \"text\";\n input.type = visible ? \"password\" : \"text\";\n btn.classList.toggle(\"active\", !visible);\n };\n\n // Account selector (shared by login and change-PIN modes)\n const accountSelector = !isFirstTime && state.accounts.length > 1\n ? html`\n <select\n class=\"login-account-select\"\n @change=${handleAccountChange}\n ?disabled=${state.busy || changeBusy}\n >\n ${state.accounts.map(\n (acc, i) => html`\n <option value=${acc.id} ?selected=${i === 0}>\n ${acc.displayName}\n </option>\n `,\n )}\n </select>\n `\n : nothing;\n\n // ─── Change PIN Mode ───\n if (isChangeMode) {\n let oldPin = \"\";\n let newPin = \"\";\n let confirmPin = \"\";\n\n const handleChangePinSubmit = (e: Event) => {\n e.preventDefault();\n if (changeBusy) return;\n if (!oldPin || !newPin || !confirmPin) return;\n if (newPin !== confirmPin) return;\n if (!selectedAccount) return;\n state.onChangePin?.(selectedAccount, oldPin, newPin);\n };\n\n return html`\n <div class=\"login-overlay\">\n <div class=\"login-card\">\n <img class=\"login-logo\" src=\"${brand.iconUrl}\" alt=\"${brand.name}\" />\n <h2 class=\"login-title\">Change PIN</h2>\n <p class=\"login-subtitle\">Enter your current PIN, then choose a new one</p>\n <form class=\"login-form\" @submit=${handleChangePinSubmit}>\n ${accountSelector}\n <div class=\"login-pin-wrapper\">\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"Current PIN\"\n ?disabled=${changeBusy}\n @input=${pinInputHandler((v) => { oldPin = v; })}\n autofocus\n />\n <button class=\"login-pin-toggle\" type=\"button\" @click=${togglePinVisibility}>\n <span class=\"pin-eye-show\">${icons.eye}</span>\n <span class=\"pin-eye-hide\">${icons.eyeOff}</span>\n </button>\n </div>\n <div class=\"login-pin-wrapper\">\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"New PIN (4-6 digits)\"\n ?disabled=${changeBusy}\n @input=${pinInputHandler((v) => { newPin = v; })}\n />\n <button class=\"login-pin-toggle\" type=\"button\" @click=${togglePinVisibility}>\n <span class=\"pin-eye-show\">${icons.eye}</span>\n <span class=\"pin-eye-hide\">${icons.eyeOff}</span>\n </button>\n </div>\n <div class=\"login-pin-wrapper\">\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"Confirm new PIN\"\n ?disabled=${changeBusy}\n @input=${pinInputHandler((v) => { confirmPin = v; })}\n />\n <button class=\"login-pin-toggle\" type=\"button\" @click=${togglePinVisibility}>\n <span class=\"pin-eye-show\">${icons.eye}</span>\n <span class=\"pin-eye-hide\">${icons.eyeOff}</span>\n </button>\n </div>\n ${state.changePinError\n ? html`<p class=\"login-error\">${state.changePinError}</p>`\n : nothing}\n ${state.changePinSuccess\n ? html`<p class=\"login-success\">${state.changePinSuccess}</p>`\n : nothing}\n <button\n class=\"login-submit\"\n type=\"submit\"\n ?disabled=${changeBusy}\n >${changeBusy ? html`<span class=\"login-spinner\"></span>` : \"Change PIN\"}</button>\n </form>\n <p class=\"login-hint\" style=\"margin-top: 16px;\">\n <a\n class=\"login-link\"\n href=\"#\"\n @click=${(e: Event) => { e.preventDefault(); state.onToggleChangePinMode?.(); }}\n >Back to login</a>\n </p>\n </div>\n </div>\n `;\n }\n\n // ─── Normal Login / First-Time Setup ───\n let pinValue = \"\";\n let confirmValue = \"\";\n\n const handleSubmit = (e: Event) => {\n e.preventDefault();\n if (state.busy) return;\n if (isFirstTime) {\n if (!pinValue || !confirmValue) return;\n if (pinValue !== confirmValue) return;\n state.onSubmit(pinValue);\n } else {\n if (!pinValue || !selectedAccount) return;\n state.onSubmit(selectedAccount, pinValue);\n }\n };\n\n return html`\n <div class=\"login-overlay\">\n <div class=\"login-card\">\n <img class=\"login-logo\" src=\"${brand.iconUrl}\" alt=\"${brand.name}\" />\n <h2 class=\"login-title\">${brand.name}</h2>\n <p class=\"login-subtitle\">\n ${isFirstTime\n ? \"Set a PIN to protect this device\"\n : \"Enter your PIN to continue\"}\n </p>\n <form class=\"login-form\" @submit=${handleSubmit}>\n ${accountSelector}\n <div class=\"login-pin-wrapper\">\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"${isFirstTime ? \"Choose a 4-6 digit PIN\" : \"PIN\"}\"\n ?disabled=${state.busy}\n @input=${pinInputHandler((v) => { pinValue = v; })}\n autofocus\n />\n <button class=\"login-pin-toggle\" type=\"button\" @click=${togglePinVisibility}>\n <span class=\"pin-eye-show\">${icons.eye}</span>\n <span class=\"pin-eye-hide\">${icons.eyeOff}</span>\n </button>\n </div>\n ${isFirstTime\n ? html`\n <div class=\"login-pin-wrapper\">\n <input\n class=\"login-pin-input\"\n type=\"password\"\n inputmode=\"numeric\"\n pattern=\"[0-9]*\"\n minlength=\"4\"\n maxlength=\"6\"\n placeholder=\"Confirm PIN\"\n ?disabled=${state.busy}\n @input=${pinInputHandler((v) => { confirmValue = v; })}\n />\n <button class=\"login-pin-toggle\" type=\"button\" @click=${togglePinVisibility}>\n <span class=\"pin-eye-show\">${icons.eye}</span>\n <span class=\"pin-eye-hide\">${icons.eyeOff}</span>\n </button>\n </div>\n `\n : nothing}\n ${state.error\n ? html`<p class=\"login-error\">${state.error}</p>`\n : nothing}\n <button\n class=\"login-submit\"\n type=\"submit\"\n ?disabled=${state.busy}\n >\n ${state.busy\n ? html`<span class=\"login-spinner\"></span>`\n : isFirstTime\n ? \"Set PIN\"\n : \"Unlock\"}\n </button>\n </form>\n ${isFirstTime\n ? html`<p class=\"login-hint\">This PIN protects all accounts on this device. You'll need it every time you open the dashboard.</p>`\n : state.accounts.some((a) => a.id === \"__master__\")\n ? html`<p class=\"login-hint login-change-pin\" style=\"margin-top: 16px;${selectedAccount !== \"__master__\" ? \" display: none;\" : \"\"}\">\n <a\n class=\"login-link\"\n href=\"#\"\n @click=${(e: Event) => { e.preventDefault(); state.onToggleChangePinMode?.(); }}\n >Change PIN</a>\n </p>`\n : nothing}\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { ChatProps } from \"./chat\";\nimport { renderChat } from \"./chat\";\n\nexport type PublicChatPageProps = Omit<ChatProps, \"sessions\" | \"focusMode\" | \"showThinking\" | \"thinkingLevel\" | \"onToggleFocusMode\" | \"onSessionKeyChange\" | \"onNewSession\"> & {\n connected: boolean;\n};\n\nexport function renderPublicChatPage(props: PublicChatPageProps) {\n if (!props.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting...</p>\n </div>\n </div>\n `;\n }\n\n // Build full ChatProps with public-mode defaults\n const chatProps: ChatProps = {\n ...props,\n sessions: null,\n focusMode: false,\n showThinking: false,\n thinkingLevel: null,\n publicMode: true,\n onToggleFocusMode: () => {},\n onSessionKeyChange: () => {},\n onNewSession: () => {},\n };\n\n const name = props.assistantName || \"Assistant\";\n\n return html`\n <div class=\"setup-container setup-container--full public-chat-page\">\n <div class=\"public-chat-header\">\n <span class=\"public-chat-header__name\">${name}</span>\n </div>\n <div class=\"chat-viewport\">\n ${renderChat(chatProps)}\n </div>\n </div>\n `;\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { AgentsListResult } from \"../types\";\n\nexport type AgentsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n agentsLoading: boolean;\n agentsError: string | null;\n agentsList: AgentsListResult | null;\n};\n\nexport async function loadAgents(state: AgentsState) {\n if (!state.client || !state.connected) return;\n if (state.agentsLoading) return;\n state.agentsLoading = true;\n state.agentsError = null;\n try {\n const res = (await state.client.request(\"agents.list\", {})) as AgentsListResult | undefined;\n if (res) state.agentsList = res;\n } catch (err) {\n state.agentsError = String(err);\n } finally {\n state.agentsLoading = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { ConfigSnapshot } from \"../types\";\nimport { cloneConfigObject, serializeConfigForm } from \"./config/form-utils\";\n\nexport type WorkspaceInfo = {\n name: string;\n displayName?: string;\n workspaceDir: string;\n isDefault: boolean;\n agents: Array<{ id: string; name?: string; isDefault: boolean }>;\n whatsappAccountId?: string;\n};\n\nexport type WorkspacesState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n configSnapshot: ConfigSnapshot | null;\n workspaces: WorkspaceInfo[];\n workspacesLoading: boolean;\n workspacesError: string | null;\n addingWorkspace: boolean;\n newWorkspaceName: string;\n newWorkspacePath: string;\n workspaceSaving: boolean;\n workspaceRemoveConfirm: string | null;\n};\n\nexport async function loadWorkspaces(state: WorkspacesState): Promise<void> {\n if (!state.client || !state.connected) return;\n if (state.workspacesLoading) return;\n state.workspacesLoading = true;\n state.workspacesError = null;\n try {\n const res = (await state.client.request(\"workspaces.list\", {})) as {\n workspaces: WorkspaceInfo[];\n };\n state.workspaces = res.workspaces;\n } catch (err) {\n state.workspacesError = String(err);\n } finally {\n state.workspacesLoading = false;\n }\n}\n\nexport async function createWorkspace(\n state: WorkspacesState,\n params: {\n name: string;\n workspacePath?: string;\n onCreated?: (res: { whatsappAccountId?: string }) => void;\n },\n): Promise<void> {\n if (!state.client || !state.connected) return;\n if (state.workspaceSaving) return;\n\n const name = params.name.trim();\n if (!name) {\n state.workspacesError = \"Account name is required.\";\n return;\n }\n\n state.workspaceSaving = true;\n state.workspacesError = null;\n try {\n // Need config hash for optimistic concurrency\n const configRes = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n state.configSnapshot = configRes;\n const baseHash = configRes.hash;\n if (!baseHash) {\n state.workspacesError = \"Config hash missing; reload and retry.\";\n return;\n }\n\n const rpcParams: Record<string, unknown> = {\n name,\n baseHash,\n whatsappAccountName: name,\n };\n if (params.workspacePath?.trim()) {\n rpcParams.workspaceDir = params.workspacePath.trim();\n }\n\n const res = (await state.client.request(\"workspaces.create\", rpcParams)) as {\n whatsappAccountId?: string;\n };\n\n // Reset form state\n state.addingWorkspace = false;\n state.newWorkspaceName = \"\";\n state.newWorkspacePath = \"\";\n\n // Reload workspaces to show the new one\n await loadWorkspaces(state);\n\n // Notify caller so it can start QR flow\n params.onCreated?.(res);\n } catch (err) {\n state.workspacesError = String(err);\n } finally {\n state.workspaceSaving = false;\n }\n}\n\nexport async function removeWorkspace(\n state: WorkspacesState,\n name: string,\n): Promise<void> {\n if (!state.client || !state.connected) return;\n if (state.workspaceSaving) return;\n\n state.workspaceSaving = true;\n state.workspacesError = null;\n try {\n // Need config hash for optimistic concurrency\n const configRes = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n state.configSnapshot = configRes;\n const baseHash = configRes.hash;\n if (!baseHash) {\n state.workspacesError = \"Config hash missing; reload and retry.\";\n return;\n }\n\n await state.client.request(\"workspaces.remove\", { name, baseHash });\n\n state.workspaceRemoveConfirm = null;\n\n // Reload workspaces\n await loadWorkspaces(state);\n } catch (err) {\n state.workspacesError = String(err);\n } finally {\n state.workspaceSaving = false;\n }\n}\n\nexport async function renameWorkspace(\n state: WorkspacesState,\n name: string,\n displayName: string,\n): Promise<void> {\n if (!state.client || !state.connected) return;\n\n state.workspacesError = null;\n try {\n const configRes = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n state.configSnapshot = configRes;\n const baseHash = configRes.hash;\n if (!baseHash) {\n state.workspacesError = \"Config hash missing; reload and retry.\";\n return;\n }\n\n await state.client.request(\"workspaces.rename\", { name, displayName, baseHash });\n\n // Reload workspaces to reflect the new name\n await loadWorkspaces(state);\n } catch (err) {\n state.workspacesError = String(err);\n }\n}\n","export const GATEWAY_CLIENT_IDS = {\n WEBCHAT_UI: \"webchat-ui\",\n CONTROL_UI: \"taskmaster-control-ui\",\n SETUP_UI: \"setup-ui\",\n WEBCHAT: \"webchat\",\n CLI: \"cli\",\n GATEWAY_CLIENT: \"gateway-client\",\n MACOS_APP: \"taskmaster-macos\",\n IOS_APP: \"taskmaster-ios\",\n ANDROID_APP: \"taskmaster-android\",\n NODE_HOST: \"node-host\",\n TEST: \"test\",\n FINGERPRINT: \"fingerprint\",\n PROBE: \"taskmaster-probe\",\n PUBLIC_CHAT: \"public-chat\",\n} as const;\n\nexport type GatewayClientId = (typeof GATEWAY_CLIENT_IDS)[keyof typeof GATEWAY_CLIENT_IDS];\n\n// Back-compat naming (internal): these values are IDs, not display names.\nexport const GATEWAY_CLIENT_NAMES = GATEWAY_CLIENT_IDS;\nexport type GatewayClientName = GatewayClientId;\n\nexport const GATEWAY_CLIENT_MODES = {\n WEBCHAT: \"webchat\",\n CLI: \"cli\",\n UI: \"ui\",\n BACKEND: \"backend\",\n NODE: \"node\",\n PROBE: \"probe\",\n TEST: \"test\",\n} as const;\n\nexport type GatewayClientMode = (typeof GATEWAY_CLIENT_MODES)[keyof typeof GATEWAY_CLIENT_MODES];\n\nexport type GatewayClientInfo = {\n id: GatewayClientId;\n displayName?: string;\n version: string;\n platform: string;\n deviceFamily?: string;\n modelIdentifier?: string;\n mode: GatewayClientMode;\n instanceId?: string;\n};\n\nconst GATEWAY_CLIENT_ID_SET = new Set<GatewayClientId>(Object.values(GATEWAY_CLIENT_IDS));\nconst GATEWAY_CLIENT_MODE_SET = new Set<GatewayClientMode>(Object.values(GATEWAY_CLIENT_MODES));\n\nexport function normalizeGatewayClientId(raw?: string | null): GatewayClientId | undefined {\n const normalized = raw?.trim().toLowerCase();\n if (!normalized) return undefined;\n return GATEWAY_CLIENT_ID_SET.has(normalized as GatewayClientId)\n ? (normalized as GatewayClientId)\n : undefined;\n}\n\nexport function normalizeGatewayClientName(raw?: string | null): GatewayClientName | undefined {\n return normalizeGatewayClientId(raw);\n}\n\nexport function normalizeGatewayClientMode(raw?: string | null): GatewayClientMode | undefined {\n const normalized = raw?.trim().toLowerCase();\n if (!normalized) return undefined;\n return GATEWAY_CLIENT_MODE_SET.has(normalized as GatewayClientMode)\n ? (normalized as GatewayClientMode)\n : undefined;\n}\n","export type DeviceAuthPayloadParams = {\n deviceId: string;\n clientId: string;\n clientMode: string;\n role: string;\n scopes: string[];\n signedAtMs: number;\n token?: string | null;\n nonce?: string | null;\n version?: \"v1\" | \"v2\";\n};\n\nexport function buildDeviceAuthPayload(params: DeviceAuthPayloadParams): string {\n const version = params.version ?? (params.nonce ? \"v2\" : \"v1\");\n const scopes = params.scopes.join(\",\");\n const token = params.token ?? \"\";\n const base = [\n version,\n params.deviceId,\n params.clientId,\n params.clientMode,\n params.role,\n scopes,\n String(params.signedAtMs),\n token,\n ];\n if (version === \"v2\") {\n base.push(params.nonce ?? \"\");\n }\n return base.join(\"|\");\n}\n","import { generateUUID } from \"./uuid\";\nimport {\n GATEWAY_CLIENT_MODES,\n GATEWAY_CLIENT_NAMES,\n type GatewayClientMode,\n type GatewayClientName,\n} from \"../../../src/gateway/protocol/client-info.js\";\nimport { buildDeviceAuthPayload } from \"../../../src/gateway/device-auth.js\";\nimport { loadOrCreateDeviceIdentity, signDevicePayload } from \"./device-identity\";\nimport { clearDeviceAuthToken, loadDeviceAuthToken, storeDeviceAuthToken } from \"./device-auth\";\n\nexport type GatewayEventFrame = {\n type: \"event\";\n event: string;\n payload?: unknown;\n seq?: number;\n stateVersion?: { presence: number; health: number };\n};\n\nexport type GatewayResponseFrame = {\n type: \"res\";\n id: string;\n ok: boolean;\n payload?: unknown;\n error?: { code: string; message: string; details?: unknown };\n};\n\nexport type GatewayHelloOk = {\n type: \"hello-ok\";\n protocol: number;\n server?: { platform?: string; version?: string; commit?: string };\n features?: { methods?: string[]; events?: string[] };\n snapshot?: unknown;\n auth?: {\n deviceToken?: string;\n role?: string;\n scopes?: string[];\n issuedAtMs?: number;\n };\n policy?: { tickIntervalMs?: number };\n};\n\ntype Pending = {\n resolve: (value: unknown) => void;\n reject: (err: unknown) => void;\n};\n\nexport type GatewayBrowserClientOptions = {\n url: string;\n token?: string;\n password?: string;\n clientName?: GatewayClientName;\n clientVersion?: string;\n platform?: string;\n mode?: GatewayClientMode;\n instanceId?: string;\n /** Override the default \"operator\" role. */\n role?: string;\n /** Override the default operator scopes. */\n scopes?: string[];\n onHello?: (hello: GatewayHelloOk) => void;\n onEvent?: (evt: GatewayEventFrame) => void;\n onClose?: (info: { code: number; reason: string }) => void;\n onGap?: (info: { expected: number; received: number }) => void;\n};\n\n// 4008 = application-defined code (browser rejects 1008 \"Policy Violation\")\nconst CONNECT_FAILED_CLOSE_CODE = 4008;\n\nexport class GatewayBrowserClient {\n private ws: WebSocket | null = null;\n private pending = new Map<string, Pending>();\n private closed = false;\n private lastSeq: number | null = null;\n private connectNonce: string | null = null;\n private connectSent = false;\n private connectTimer: number | null = null;\n private backoffMs = 800;\n\n constructor(private opts: GatewayBrowserClientOptions) {}\n\n start() {\n this.closed = false;\n this.connect();\n }\n\n stop() {\n this.closed = true;\n this.ws?.close();\n this.ws = null;\n this.flushPending(new Error(\"gateway client stopped\"));\n }\n\n get connected() {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n private connect() {\n if (this.closed) return;\n this.ws = new WebSocket(this.opts.url);\n this.ws.onopen = () => this.queueConnect();\n this.ws.onmessage = (ev) => this.handleMessage(String(ev.data ?? \"\"));\n this.ws.onclose = (ev) => {\n const reason = String(ev.reason ?? \"\");\n this.ws = null;\n this.flushPending(new Error(`gateway closed (${ev.code}): ${reason}`));\n this.opts.onClose?.({ code: ev.code, reason });\n this.scheduleReconnect();\n };\n this.ws.onerror = () => {\n // ignored; close handler will fire\n };\n }\n\n private scheduleReconnect() {\n if (this.closed) return;\n const delay = this.backoffMs;\n this.backoffMs = Math.min(this.backoffMs * 1.7, 15_000);\n window.setTimeout(() => this.connect(), delay);\n }\n\n private flushPending(err: Error) {\n for (const [, p] of this.pending) p.reject(err);\n this.pending.clear();\n }\n\n private async sendConnect() {\n if (this.connectSent) return;\n this.connectSent = true;\n if (this.connectTimer !== null) {\n window.clearTimeout(this.connectTimer);\n this.connectTimer = null;\n }\n\n const role = this.opts.role ?? \"operator\";\n const scopes = this.opts.scopes ?? [\"operator.admin\", \"operator.approvals\", \"operator.pairing\"];\n const skipDeviceIdentity = role !== \"operator\";\n\n // crypto.subtle is only available in secure contexts (HTTPS, localhost).\n // Over plain HTTP, we skip device identity and fall back to token-only auth.\n // Gateways may reject this unless gateway.controlUi.allowInsecureAuth is enabled.\n const isSecureContext = !skipDeviceIdentity && typeof crypto !== \"undefined\" && !!crypto.subtle;\n\n let deviceIdentity: Awaited<ReturnType<typeof loadOrCreateDeviceIdentity>> | null = null;\n let canFallbackToShared = false;\n let authToken = this.opts.token;\n\n if (isSecureContext) {\n deviceIdentity = await loadOrCreateDeviceIdentity();\n const storedToken = loadDeviceAuthToken({\n deviceId: deviceIdentity.deviceId,\n role,\n })?.token;\n authToken = storedToken ?? this.opts.token;\n canFallbackToShared = Boolean(storedToken && this.opts.token);\n }\n const auth =\n authToken || this.opts.password\n ? {\n token: authToken,\n password: this.opts.password,\n }\n : undefined;\n\n let device:\n | {\n id: string;\n publicKey: string;\n signature: string;\n signedAt: number;\n nonce: string | undefined;\n }\n | undefined;\n\n if (isSecureContext && deviceIdentity) {\n const signedAtMs = Date.now();\n const nonce = this.connectNonce ?? undefined;\n const payload = buildDeviceAuthPayload({\n deviceId: deviceIdentity.deviceId,\n clientId: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.CONTROL_UI,\n clientMode: this.opts.mode ?? GATEWAY_CLIENT_MODES.WEBCHAT,\n role,\n scopes,\n signedAtMs,\n token: authToken ?? null,\n nonce,\n });\n const signature = await signDevicePayload(deviceIdentity.privateKey, payload);\n device = {\n id: deviceIdentity.deviceId,\n publicKey: deviceIdentity.publicKey,\n signature,\n signedAt: signedAtMs,\n nonce,\n };\n }\n const params = {\n minProtocol: 3,\n maxProtocol: 3,\n client: {\n id: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.CONTROL_UI,\n version: this.opts.clientVersion ?? \"dev\",\n platform: this.opts.platform ?? navigator.platform ?? \"web\",\n mode: this.opts.mode ?? GATEWAY_CLIENT_MODES.WEBCHAT,\n instanceId: this.opts.instanceId,\n },\n role,\n scopes,\n device,\n caps: [],\n auth,\n userAgent: navigator.userAgent,\n locale: navigator.language,\n };\n\n void this.request<GatewayHelloOk>(\"connect\", params)\n .then((hello) => {\n if (hello?.auth?.deviceToken && deviceIdentity) {\n storeDeviceAuthToken({\n deviceId: deviceIdentity.deviceId,\n role: hello.auth.role ?? role,\n token: hello.auth.deviceToken,\n scopes: hello.auth.scopes ?? [],\n });\n }\n this.backoffMs = 800;\n this.opts.onHello?.(hello);\n })\n .catch(() => {\n if (canFallbackToShared && deviceIdentity) {\n clearDeviceAuthToken({ deviceId: deviceIdentity.deviceId, role });\n }\n this.ws?.close(CONNECT_FAILED_CLOSE_CODE, \"connect failed\");\n });\n }\n\n private handleMessage(raw: string) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return;\n }\n\n const frame = parsed as { type?: unknown };\n if (frame.type === \"event\") {\n const evt = parsed as GatewayEventFrame;\n if (evt.event === \"connect.challenge\") {\n const payload = evt.payload as { nonce?: unknown } | undefined;\n const nonce = payload && typeof payload.nonce === \"string\" ? payload.nonce : null;\n if (nonce) {\n this.connectNonce = nonce;\n void this.sendConnect();\n }\n return;\n }\n const seq = typeof evt.seq === \"number\" ? evt.seq : null;\n if (seq !== null) {\n if (this.lastSeq !== null && seq > this.lastSeq + 1) {\n this.opts.onGap?.({ expected: this.lastSeq + 1, received: seq });\n }\n this.lastSeq = seq;\n }\n try {\n this.opts.onEvent?.(evt);\n } catch (err) {\n console.error(\"[gateway] event handler error:\", err);\n }\n return;\n }\n\n if (frame.type === \"res\") {\n const res = parsed as GatewayResponseFrame;\n const pending = this.pending.get(res.id);\n if (!pending) return;\n this.pending.delete(res.id);\n if (res.ok) pending.resolve(res.payload);\n else {\n const err = new Error(res.error?.message ?? \"request failed\") as Error & {\n payload?: unknown;\n details?: unknown;\n };\n err.payload = res.payload;\n err.details = res.error?.details;\n pending.reject(err);\n }\n return;\n }\n }\n\n request<T = unknown>(method: string, params?: unknown): Promise<T> {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new Error(\"gateway not connected\"));\n }\n const id = generateUUID();\n const frame = { type: \"req\", id, method, params };\n const p = new Promise<T>((resolve, reject) => {\n this.pending.set(id, { resolve: (v) => resolve(v as T), reject });\n });\n this.ws.send(JSON.stringify(frame));\n return p;\n }\n\n private queueConnect() {\n this.connectNonce = null;\n this.connectSent = false;\n if (this.connectTimer !== null) window.clearTimeout(this.connectTimer);\n this.connectTimer = window.setTimeout(() => {\n void this.sendConnect();\n }, 750);\n }\n}\n","export type ExecApprovalRequestPayload = {\n command: string;\n cwd?: string | null;\n host?: string | null;\n security?: string | null;\n ask?: string | null;\n agentId?: string | null;\n resolvedPath?: string | null;\n sessionKey?: string | null;\n};\n\nexport type ExecApprovalRequest = {\n id: string;\n request: ExecApprovalRequestPayload;\n createdAtMs: number;\n expiresAtMs: number;\n};\n\nexport type ExecApprovalResolved = {\n id: string;\n decision?: string | null;\n resolvedBy?: string | null;\n ts?: number | null;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function parseExecApprovalRequested(payload: unknown): ExecApprovalRequest | null {\n if (!isRecord(payload)) return null;\n const id = typeof payload.id === \"string\" ? payload.id.trim() : \"\";\n const request = payload.request;\n if (!id || !isRecord(request)) return null;\n const command = typeof request.command === \"string\" ? request.command.trim() : \"\";\n if (!command) return null;\n const createdAtMs = typeof payload.createdAtMs === \"number\" ? payload.createdAtMs : 0;\n const expiresAtMs = typeof payload.expiresAtMs === \"number\" ? payload.expiresAtMs : 0;\n if (!createdAtMs || !expiresAtMs) return null;\n return {\n id,\n request: {\n command,\n cwd: typeof request.cwd === \"string\" ? request.cwd : null,\n host: typeof request.host === \"string\" ? request.host : null,\n security: typeof request.security === \"string\" ? request.security : null,\n ask: typeof request.ask === \"string\" ? request.ask : null,\n agentId: typeof request.agentId === \"string\" ? request.agentId : null,\n resolvedPath: typeof request.resolvedPath === \"string\" ? request.resolvedPath : null,\n sessionKey: typeof request.sessionKey === \"string\" ? request.sessionKey : null,\n },\n createdAtMs,\n expiresAtMs,\n };\n}\n\nexport function parseExecApprovalResolved(payload: unknown): ExecApprovalResolved | null {\n if (!isRecord(payload)) return null;\n const id = typeof payload.id === \"string\" ? payload.id.trim() : \"\";\n if (!id) return null;\n return {\n id,\n decision: typeof payload.decision === \"string\" ? payload.decision : null,\n resolvedBy: typeof payload.resolvedBy === \"string\" ? payload.resolvedBy : null,\n ts: typeof payload.ts === \"number\" ? payload.ts : null,\n };\n}\n\nexport function pruneExecApprovalQueue(queue: ExecApprovalRequest[]): ExecApprovalRequest[] {\n const now = Date.now();\n return queue.filter((entry) => entry.expiresAtMs > now);\n}\n\nexport function addExecApproval(\n queue: ExecApprovalRequest[],\n entry: ExecApprovalRequest,\n): ExecApprovalRequest[] {\n const next = pruneExecApprovalQueue(queue).filter((item) => item.id !== entry.id);\n next.push(entry);\n return next;\n}\n\nexport function removeExecApproval(queue: ExecApprovalRequest[], id: string): ExecApprovalRequest[] {\n return pruneExecApprovalQueue(queue).filter((entry) => entry.id !== id);\n}\n","/**\n * Canvas renderer for browser screencast frames.\n * Manages requestAnimationFrame batching and coordinate translation.\n */\nexport class BrowserCanvasRenderer {\n private canvas: HTMLCanvasElement | null = null;\n private ctx: CanvasRenderingContext2D | null = null;\n private img = new Image();\n private pendingFrame: string | null = null;\n private rafId: number | null = null;\n private deviceWidth = 1280;\n private deviceHeight = 720;\n private lastMouseMoveAt = 0;\n private readonly MOUSE_THROTTLE_MS = 30;\n\n attach(canvas: HTMLCanvasElement): void {\n this.canvas = canvas;\n this.ctx = canvas.getContext(\"2d\");\n }\n\n detach(): void {\n if (this.rafId != null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n this.canvas = null;\n this.ctx = null;\n this.pendingFrame = null;\n }\n\n updateFrame(\n base64Data: string,\n metadata?: { deviceWidth?: number; deviceHeight?: number },\n ): void {\n if (metadata?.deviceWidth) this.deviceWidth = metadata.deviceWidth;\n if (metadata?.deviceHeight) this.deviceHeight = metadata.deviceHeight;\n\n this.pendingFrame = base64Data;\n\n // Auto-attach to the canvas element if not yet attached.\n // The canvas is rendered by Lit after browserScreencastActive becomes true,\n // so it may not exist when the first frame arrives.\n if (!this.canvas) {\n const el = document.getElementById(\"browser-screencast-canvas\") as HTMLCanvasElement | null;\n if (el) this.attach(el);\n }\n\n if (this.rafId == null) {\n this.rafId = requestAnimationFrame(() => this.renderFrame());\n }\n }\n\n private renderFrame(): void {\n this.rafId = null;\n const data = this.pendingFrame;\n if (!data || !this.canvas || !this.ctx) return;\n this.pendingFrame = null;\n\n this.img.onload = () => {\n if (!this.canvas || !this.ctx) return;\n // Resize canvas to match frame dimensions\n if (\n this.canvas.width !== this.img.width ||\n this.canvas.height !== this.img.height\n ) {\n this.canvas.width = this.img.width;\n this.canvas.height = this.img.height;\n }\n this.ctx.drawImage(this.img, 0, 0);\n };\n this.img.src = `data:image/jpeg;base64,${data}`;\n }\n\n /**\n * Translate canvas pixel coordinates to CDP viewport coordinates.\n */\n translateCoordinates(\n canvasX: number,\n canvasY: number,\n ): { x: number; y: number } {\n if (!this.canvas) return { x: canvasX, y: canvasY };\n\n const rect = this.canvas.getBoundingClientRect();\n // Scale from displayed size to actual canvas pixel size\n const scaleX = this.canvas.width / rect.width;\n const scaleY = this.canvas.height / rect.height;\n\n // Then scale from canvas pixels to device viewport\n const viewportScaleX = this.deviceWidth / this.canvas.width;\n const viewportScaleY = this.deviceHeight / this.canvas.height;\n\n return {\n x: Math.round(canvasX * scaleX * viewportScaleX),\n y: Math.round(canvasY * scaleY * viewportScaleY),\n };\n }\n\n /**\n * Check if a mouse move event should be throttled.\n */\n shouldThrottleMouseMove(): boolean {\n const now = performance.now();\n if (now - this.lastMouseMoveAt < this.MOUSE_THROTTLE_MS) {\n return true;\n }\n this.lastMouseMoveAt = now;\n return false;\n }\n\n getDeviceDimensions(): { width: number; height: number } {\n return { width: this.deviceWidth, height: this.deviceHeight };\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { BrowserCanvasRenderer } from \"../browser-canvas\";\n\nexport type BrowserViewerState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n browserScreencastActive: boolean;\n browserScreencastFrame: string | null;\n browserScreencastMetadata: { deviceWidth?: number; deviceHeight?: number } | null;\n browserHandoffPending: boolean;\n browserHandoffReason: string | null;\n browserHandoffId: string | null;\n browserInputMode: boolean;\n browserFullscreen: boolean;\n browserLoading: boolean;\n browserError: string | null;\n};\n\nlet canvasRenderer: BrowserCanvasRenderer | null = null;\n\nexport function getCanvasRenderer(): BrowserCanvasRenderer {\n if (!canvasRenderer) {\n canvasRenderer = new BrowserCanvasRenderer();\n }\n return canvasRenderer;\n}\n\nfunction getErrorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nexport async function startScreencast(state: BrowserViewerState) {\n if (!state.client) {\n console.error(\"[browser] startScreencast: no client\");\n state.browserError = \"Not connected to gateway\";\n return;\n }\n if (!state.connected) {\n console.error(\"[browser] startScreencast: client exists but not connected\");\n state.browserError = \"Not connected to gateway\";\n return;\n }\n console.log(\"[browser] startScreencast: sending request\");\n state.browserLoading = true;\n state.browserError = null;\n try {\n const res = (await state.client.request(\"browser.screencast.start\", {\n quality: 60,\n maxWidth: 1280,\n maxHeight: 720,\n })) as { ok?: boolean } | undefined;\n console.log(\"[browser] startScreencast response:\", res);\n if (res?.ok) {\n state.browserScreencastActive = true;\n } else {\n console.warn(\"[browser] startScreencast: response did not have ok=true\", res);\n state.browserError = \"Screencast start failed (no ok in response)\";\n }\n } catch (err) {\n console.error(\"[browser] startScreencast error:\", err);\n state.browserError = getErrorMessage(err);\n } finally {\n state.browserLoading = false;\n }\n}\n\nexport async function stopScreencast(state: BrowserViewerState) {\n if (!state.client || !state.connected) return;\n state.browserLoading = true;\n state.browserFullscreen = false;\n try {\n await state.client.request(\"browser.screencast.stop\", {});\n state.browserScreencastActive = false;\n state.browserScreencastFrame = null;\n state.browserScreencastMetadata = null;\n } catch (err) {\n state.browserError = getErrorMessage(err);\n } finally {\n state.browserLoading = false;\n }\n}\n\nexport async function sendMouseInput(\n state: BrowserViewerState,\n action: \"mousePressed\" | \"mouseReleased\" | \"mouseMoved\",\n x: number,\n y: number,\n button?: \"left\" | \"right\" | \"middle\",\n) {\n if (!state.client || !state.connected || !state.browserInputMode) return;\n try {\n await state.client.request(\"browser.screencast.input\", {\n type: \"mouse\",\n action,\n x,\n y,\n button: button ?? \"left\",\n clickCount: action === \"mousePressed\" ? 1 : 0,\n });\n } catch {\n // Ignore input errors to avoid disrupting the experience\n }\n}\n\nexport async function sendKeyInput(\n state: BrowserViewerState,\n action: \"keyDown\" | \"keyUp\" | \"char\",\n key: string,\n opts?: { text?: string; code?: string; modifiers?: number },\n) {\n if (!state.client || !state.connected || !state.browserInputMode) return;\n try {\n await state.client.request(\"browser.screencast.input\", {\n type: \"key\",\n action,\n key,\n ...(opts?.text ? { text: opts.text } : {}),\n ...(opts?.code ? { code: opts.code } : {}),\n ...(opts?.modifiers ? { modifiers: opts.modifiers } : {}),\n });\n } catch {\n // Ignore input errors\n }\n}\n\nexport async function completeHandoff(state: BrowserViewerState) {\n if (!state.client || !state.connected) return;\n try {\n await state.client.request(\"browser.handoff.complete\", {});\n state.browserHandoffPending = false;\n state.browserHandoffReason = null;\n state.browserHandoffId = null;\n } catch (err) {\n state.browserError = getErrorMessage(err);\n }\n}\n\nexport function toggleInputMode(state: BrowserViewerState) {\n state.browserInputMode = !state.browserInputMode;\n}\n\nexport function toggleFullscreen(state: BrowserViewerState) {\n state.browserFullscreen = !state.browserFullscreen;\n // Detach canvas so it re-attaches to the new DOM element\n const renderer = getCanvasRenderer();\n renderer.detach();\n}\n\n/**\n * Handle incoming screencast frame from gateway event.\n */\nexport function handleScreencastFrame(\n state: BrowserViewerState,\n payload: { data?: string; metadata?: { deviceWidth?: number; deviceHeight?: number } } | undefined,\n) {\n if (!payload?.data) return;\n state.browserScreencastFrame = payload.data;\n state.browserScreencastMetadata = payload.metadata ?? null;\n\n // Update canvas renderer directly\n const renderer = getCanvasRenderer();\n renderer.updateFrame(payload.data, payload.metadata);\n}\n\n/**\n * Handle handoff event from gateway.\n */\nexport function handleHandoffEvent(\n state: BrowserViewerState,\n payload: { id?: string; reason?: string } | undefined,\n) {\n if (!payload) return;\n state.browserHandoffPending = true;\n state.browserHandoffReason = payload.reason ?? \"Action required\";\n state.browserHandoffId = payload.id ?? null;\n}\n\n/**\n * Handle handoff resolved event from gateway.\n */\nexport function handleHandoffResolved(state: BrowserViewerState) {\n state.browserHandoffPending = false;\n state.browserHandoffReason = null;\n state.browserHandoffId = null;\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport {\n normalizeAssistantIdentity,\n type AssistantIdentity,\n} from \"../assistant-identity\";\n\nexport type AssistantIdentityState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n sessionKey: string;\n assistantName: string;\n assistantAvatar: string | null;\n assistantAgentId: string | null;\n};\n\nexport async function loadAssistantIdentity(\n state: AssistantIdentityState,\n opts?: { sessionKey?: string },\n) {\n if (!state.client || !state.connected) return;\n const sessionKey = opts?.sessionKey?.trim() || state.sessionKey.trim();\n const params = sessionKey ? { sessionKey } : {};\n try {\n const res = (await state.client.request(\"agent.identity.get\", params)) as\n | Partial<AssistantIdentity>\n | undefined;\n if (!res) return;\n const normalized = normalizeAssistantIdentity(res);\n state.assistantName = normalized.name;\n state.assistantAvatar = normalized.avatar;\n state.assistantAgentId = normalized.agentId ?? null;\n } catch {\n // Ignore errors; keep last known identity.\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\n\nexport type ApiKeyProvider = {\n id: string;\n name: string;\n category: string;\n hasKey: boolean;\n disabled: boolean;\n key?: string;\n primary?: boolean;\n};\n\nexport type ApiKeysState = {\n apiKeyProviders: ApiKeyProvider[];\n apiKeyModalOpen: boolean;\n apiKeyBusy: boolean;\n apiKeyError: string | null;\n apiKeySuccess: string | null;\n apiKeySavingProvider: string | null;\n // Auth step API key fallback\n authApiKeyMode: boolean;\n authApiKeyInput: string;\n authApiKeyBusy: boolean;\n authApiKeyError: string | null;\n};\n\nexport const DEFAULT_API_KEYS_STATE: ApiKeysState = {\n apiKeyProviders: [],\n apiKeyModalOpen: false,\n apiKeyBusy: false,\n apiKeyError: null,\n apiKeySuccess: null,\n apiKeySavingProvider: null,\n authApiKeyMode: false,\n authApiKeyInput: \"\",\n authApiKeyBusy: false,\n authApiKeyError: null,\n};\n\nexport async function loadApiKeyProviders(\n client: GatewayBrowserClient,\n): Promise<ApiKeyProvider[]> {\n const result = await client.request<{ providers: ApiKeyProvider[] }>(\"apikeys.list\");\n return result.providers ?? [];\n}\n\nexport async function saveApiKey(\n client: GatewayBrowserClient,\n provider: string,\n apiKey: string,\n): Promise<void> {\n await client.request(\"apikeys.set\", { provider, apiKey });\n}\n\nexport async function removeApiKey(\n client: GatewayBrowserClient,\n provider: string,\n): Promise<void> {\n await client.request(\"apikeys.remove\", { provider });\n}\n\nexport async function disableApiKey(\n client: GatewayBrowserClient,\n provider: string,\n disabled: boolean,\n): Promise<void> {\n await client.request(\"apikeys.disable\", { provider, disabled });\n}\n","/**\n * Software update controller for setup page\n */\n\nexport type UpdateProgressStep = {\n name: string;\n index: number;\n total: number;\n status: \"running\" | \"done\" | \"failed\";\n durationMs?: number;\n};\n\nexport type UpdateLastResult = {\n status: \"ok\" | \"error\" | \"skipped\";\n ts: number;\n mode: string | null;\n before: { sha?: string; version?: string } | null;\n after: { sha?: string; version?: string } | null;\n reason: string | null;\n durationMs: number | null;\n failedStep: { name: string; exitCode: number | null } | null;\n currentVersion: string;\n};\n\nexport interface UpdateState {\n client: { request: (method: string, params: unknown) => Promise<unknown> } | null;\n connected: boolean;\n updateAvailable: boolean | null;\n currentVersion: string | null;\n latestVersion: string | null;\n updateChecking: boolean;\n updateRunning: boolean;\n updateMessage: string | null;\n updateProgressSteps: UpdateProgressStep[];\n updateLastResult: UpdateLastResult | null;\n requestUpdate?: () => void;\n}\n\ninterface UpdateStatusResponse {\n ok: boolean;\n current: string;\n latest: string | null;\n updateAvailable: boolean;\n installKind: string;\n channel: string;\n error?: string;\n}\n\ninterface UpdateRunResponse {\n ok: boolean;\n result: {\n status: string;\n mode: string;\n reason?: string;\n before?: string;\n after?: string;\n };\n restart: {\n ok: boolean;\n delayMs?: number;\n };\n}\n\ninterface UpdateLastResultResponse {\n ok: boolean;\n result: UpdateLastResult | null;\n}\n\nconst UPDATE_PENDING_KEY = \"taskmaster_update_pending\";\n\nexport async function checkForUpdates(state: UpdateState): Promise<void> {\n if (!state.client || !state.connected) return;\n if (state.updateChecking) return;\n\n state.updateChecking = true;\n state.updateMessage = null;\n state.requestUpdate?.();\n\n try {\n const res = (await state.client.request(\"update.status\", {})) as UpdateStatusResponse;\n state.currentVersion = res.current;\n state.latestVersion = res.latest;\n state.updateAvailable = res.updateAvailable;\n state.updateMessage = res.updateAvailable\n ? `v${res.latest} available`\n : \"Up to date\";\n } catch (err) {\n state.updateMessage = `Check failed: ${String(err)}`;\n state.updateAvailable = null;\n } finally {\n state.updateChecking = false;\n state.requestUpdate?.();\n }\n}\n\nexport async function runUpdate(state: UpdateState): Promise<void> {\n if (!state.client || state.updateRunning) return;\n\n state.updateRunning = true;\n state.updateMessage = \"Starting update...\";\n state.updateProgressSteps = [];\n state.updateLastResult = null;\n state.requestUpdate?.();\n\n // Mark update in progress so we can check after reconnect\n try {\n localStorage.setItem(UPDATE_PENDING_KEY, String(Date.now()));\n localStorage.removeItem(DISMISS_KEY);\n } catch { /* localStorage may be unavailable */ }\n\n try {\n const res = (await state.client.request(\"update.run\", {\n restartDelayMs: 2000,\n note: \"Update from setup page\",\n })) as UpdateRunResponse;\n\n if (res.ok && res.result.status === \"ok\") {\n state.updateMessage = \"Updated — restarting gateway...\";\n state.requestUpdate?.();\n // Don't reload — the WebSocket will reconnect automatically\n // and fetchLastUpdateResult will show the outcome\n } else if (res.ok && res.result.status === \"skipped\") {\n clearUpdatePending();\n state.updateMessage = res.result.reason || \"Update skipped\";\n state.updateRunning = false;\n state.requestUpdate?.();\n } else {\n clearUpdatePending();\n throw new Error(res.result.reason || \"Update failed\");\n }\n } catch (err) {\n clearUpdatePending();\n state.updateMessage = `Update failed: ${String(err)}`;\n state.updateRunning = false;\n state.updateProgressSteps = [];\n state.requestUpdate?.();\n }\n}\n\n/** Called when the UI receives an update.progress event from gateway */\nexport function handleUpdateProgress(\n state: UpdateState,\n payload: Record<string, unknown>,\n): void {\n const phase = payload.phase as string;\n\n if (phase === \"step-start\") {\n const name = payload.name as string;\n const index = payload.index as number;\n const total = payload.total as number;\n state.updateMessage = `Updating: ${name} (${index + 1}/${total})`;\n\n // Add or update the step\n const existing = state.updateProgressSteps.find((s) => s.index === index);\n if (existing) {\n existing.status = \"running\";\n existing.name = name;\n } else {\n state.updateProgressSteps = [\n ...state.updateProgressSteps,\n { name, index, total, status: \"running\" },\n ];\n }\n state.requestUpdate?.();\n } else if (phase === \"step-done\") {\n const name = payload.name as string;\n const index = payload.index as number;\n const total = payload.total as number;\n const ok = payload.ok as boolean;\n const durationMs = payload.durationMs as number | undefined;\n\n const existing = state.updateProgressSteps.find((s) => s.index === index);\n if (existing) {\n existing.status = ok ? \"done\" : \"failed\";\n existing.durationMs = durationMs;\n } else {\n state.updateProgressSteps = [\n ...state.updateProgressSteps,\n { name, index, total, status: ok ? \"done\" : \"failed\", durationMs },\n ];\n }\n const errorDetail = !ok && payload.error ? `: ${(payload.error as string).slice(0, 200)}` : \"\";\n state.updateMessage = ok\n ? `Updating: ${name} done (${index + 1}/${total})`\n : `Update step failed: ${name}${errorDetail}`;\n state.requestUpdate?.();\n } else if (phase === \"complete\") {\n const status = payload.status as string;\n if (status === \"ok\") {\n state.updateMessage = \"Update complete — restarting gateway...\";\n } else {\n const reason = payload.reason as string | null;\n state.updateMessage = reason ? `Update failed: ${reason}` : \"Update failed\";\n state.updateRunning = false;\n clearUpdatePending();\n }\n state.requestUpdate?.();\n }\n}\n\n/**\n * Check for update results on every connect.\n * Two triggers: (1) localStorage flag set by this code during runUpdate,\n * or (2) a recent update sentinel on the gateway (covers updates initiated\n * by older code that didn't set the flag — the chicken-and-egg case).\n */\nexport async function fetchLastUpdateResult(state: UpdateState): Promise<void> {\n if (!state.client || !state.connected) return;\n\n const hadPendingFlag = isUpdatePending();\n clearUpdatePending();\n\n try {\n const res = (await state.client.request(\n \"update.lastResult\",\n {},\n )) as UpdateLastResultResponse;\n if (!res.ok || !res.result) return;\n\n // If we didn't set the localStorage flag ourselves, only show results\n // from sentinels written in the last 5 minutes (avoids showing stale\n // results from days-old updates on every page load).\n const RECENT_MS = 5 * 60_000;\n const isRecent = Date.now() - res.result.ts < RECENT_MS;\n if (!hadPendingFlag && !isRecent) return;\n\n // Skip if the user dismissed this result\n if (isDismissedResult(res.result.ts)) return;\n\n state.updateLastResult = res.result;\n // Use after.version for successful updates (currentVersion is from the old code)\n const afterVersion = (res.result.after as Record<string, unknown>)?.version as string | undefined;\n if (res.result.status === \"ok\" && afterVersion) {\n state.currentVersion = afterVersion;\n }\n state.updateAvailable = false;\n if (res.result.status === \"ok\") {\n const before = res.result.before?.version;\n const after = afterVersion ?? res.result.currentVersion;\n state.updateMessage = before\n ? `Updated: v${before} → v${after}`\n : `Updated to v${after}`;\n } else {\n const reason = res.result.reason ?? res.result.failedStep?.name ?? \"unknown error\";\n state.updateMessage = `Update failed: ${reason}`;\n }\n } catch {\n // Gateway may not support this method yet — ignore\n } finally {\n state.updateRunning = false;\n state.updateProgressSteps = [];\n state.requestUpdate?.();\n }\n}\n\nconst DISMISS_KEY = \"taskmaster_update_dismissed\";\n\nexport function dismissUpdateResult(state: UpdateState): void {\n state.updateLastResult = null;\n state.updateMessage = null;\n try {\n localStorage.setItem(DISMISS_KEY, String(Date.now()));\n } catch { /* ignore */ }\n state.requestUpdate?.();\n}\n\nfunction isUpdatePending(): boolean {\n try {\n const ts = localStorage.getItem(UPDATE_PENDING_KEY);\n if (!ts) return false;\n // Consider stale after 30 minutes\n const age = Date.now() - Number(ts);\n if (age > 30 * 60_000) {\n localStorage.removeItem(UPDATE_PENDING_KEY);\n return false;\n }\n return true;\n } catch {\n return false;\n }\n}\n\nfunction clearUpdatePending(): void {\n try {\n localStorage.removeItem(UPDATE_PENDING_KEY);\n } catch { /* ignore */ }\n}\n\nfunction isDismissedResult(resultTs: number): boolean {\n try {\n const dismissedAt = localStorage.getItem(DISMISS_KEY);\n if (!dismissedAt) return false;\n // The result was dismissed if the dismiss timestamp is after the result timestamp\n return Number(dismissedAt) >= resultTs;\n } catch {\n return false;\n }\n}\n","/**\n * Notification banner — renders a dismissible warning bar at the top of\n * the main content area. Called imperatively from the gateway event handler\n * when an infra alert (e.g. model-fallback) arrives via WebSocket.\n *\n * Uses textContent exclusively — never innerHTML — to prevent injection.\n */\n\nconst BANNER_ID = \"notification-banner\";\n\nexport function renderNotificationBanner(\n notification: { ts: number; category: string; message: string } | null,\n): void {\n const existing = document.getElementById(BANNER_ID);\n if (!notification) {\n existing?.remove();\n return;\n }\n if (existing) existing.remove();\n\n const banner = document.createElement(\"div\");\n banner.id = BANNER_ID;\n Object.assign(banner.style, {\n background: \"rgba(255, 180, 50, 0.15)\",\n border: \"1px solid rgba(255, 180, 50, 0.3)\",\n borderRadius: \"8px\",\n padding: \"12px 16px\",\n margin: \"0 0 16px 0\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: \"12px\",\n color: \"rgba(255, 255, 255, 0.9)\",\n fontSize: \"14px\",\n });\n\n const msg = document.createElement(\"span\");\n msg.textContent = notification.message;\n banner.appendChild(msg);\n\n const dismiss = document.createElement(\"button\");\n dismiss.setAttribute(\"aria-label\", \"Dismiss\");\n dismiss.textContent = \"\\u00d7\";\n Object.assign(dismiss.style, {\n background: \"none\",\n border: \"none\",\n color: \"rgba(255, 255, 255, 0.7)\",\n cursor: \"pointer\",\n fontSize: \"18px\",\n padding: \"0 4px\",\n });\n dismiss.addEventListener(\"click\", () => banner.remove());\n banner.appendChild(dismiss);\n\n const main = document.querySelector(\"main\") ?? document.body;\n main.prepend(banner);\n}\n","import { loadChatHistory, CHAT_PAGE_SIZE } from \"./controllers/chat\";\nimport { loadConfig } from \"./controllers/config\";\nimport { handleCronRunEvent } from \"./controllers/cron\";\nimport { loadDevices } from \"./controllers/devices\";\nimport { loadNodes } from \"./controllers/nodes\";\nimport { loadAgents } from \"./controllers/agents\";\nimport { loadWorkspaces } from \"./controllers/workspaces\";\nimport type { GatewayEventFrame, GatewayHelloOk } from \"./gateway\";\nimport { GatewayBrowserClient } from \"./gateway\";\nimport type { EventLogEntry } from \"./app-events\";\nimport type { AgentsListResult, PresenceEntry, HealthSnapshot, StatusSummary } from \"./types\";\nimport type { Tab } from \"./navigation\";\nimport { loadDraft, type UiSettings } from \"./storage\";\nimport { handleAgentEvent, resetToolStream, type AgentEventPayload } from \"./app-tool-stream\";\nimport { flushChatQueueForEvent } from \"./app-chat\";\nimport {\n applySettings,\n loadCron,\n refreshActiveTab,\n setLastActiveSessionKey,\n} from \"./app-settings\";\nimport { handleChatEvent, type ChatEventPayload } from \"./controllers/chat\";\nimport {\n addExecApproval,\n parseExecApprovalRequested,\n parseExecApprovalResolved,\n removeExecApproval,\n} from \"./controllers/exec-approval\";\nimport type { TaskmasterApp } from \"./app\";\nimport type { ExecApprovalRequest } from \"./controllers/exec-approval\";\nimport {\n handleScreencastFrame,\n handleHandoffEvent,\n handleHandoffResolved,\n} from \"./controllers/browser-viewer\";\nimport { loadAssistantIdentity } from \"./controllers/assistant-identity\";\nimport { checkUninstallDone, clearUninstallDone } from \"./controllers/uninstall\";\nimport { loadApiKeyProviders as fetchApiKeyProviders } from \"./controllers/apikeys\";\nimport {\n handleUpdateProgress,\n fetchLastUpdateResult,\n checkForUpdates,\n} from \"./controllers/update\";\nimport { renderNotificationBanner } from \"./views/notification-banner\";\n\ntype GatewayHost = {\n settings: UiSettings;\n password: string;\n client: GatewayBrowserClient | null;\n connected: boolean;\n hello: GatewayHelloOk | null;\n lastError: string | null;\n onboarding?: boolean;\n setup?: boolean;\n filesPage?: boolean;\n browserPage?: boolean;\n chatPage?: boolean;\n adminsPage?: boolean;\n contactsPage?: boolean;\n advancedPage?: boolean;\n // Public chat mode\n publicChat?: boolean;\n publicChatConfig?: { accountId?: string; auth?: string; cookieTtlDays?: number; otpChannels?: string[]; verifyMethods?: string[] };\n publicChatSessionKey?: string | null;\n publicChatAuthenticated?: boolean;\n publicChatAuthStep?: \"idle\" | \"phone\" | \"email\" | \"otp\" | \"ready\";\n eventLogBuffer: EventLogEntry[];\n eventLog: EventLogEntry[];\n tab: Tab;\n presenceEntries: PresenceEntry[];\n presenceError: string | null;\n presenceStatus: StatusSummary | null;\n agentsLoading: boolean;\n agentsList: AgentsListResult | null;\n agentsError: string | null;\n debugHealth: HealthSnapshot | null;\n assistantName: string;\n assistantAvatar: string | null;\n assistantAgentId: string | null;\n sessionKey: string;\n chatRunId: string | null;\n chatModelCatalog: Array<{ id: string; name: string; provider: string; reasoning?: boolean }>;\n execApprovalQueue: ExecApprovalRequest[];\n execApprovalError: string | null;\n};\n\ntype SessionDefaultsSnapshot = {\n defaultAgentId?: string;\n mainKey?: string;\n mainSessionKey?: string;\n scope?: string;\n};\n\nfunction normalizeSessionKeyForDefaults(\n value: string | undefined,\n defaults: SessionDefaultsSnapshot,\n): string {\n const raw = (value ?? \"\").trim();\n const mainSessionKey = defaults.mainSessionKey?.trim();\n if (!mainSessionKey) return raw;\n if (!raw) return mainSessionKey;\n const mainKey = defaults.mainKey?.trim() || \"main\";\n const defaultAgentId = defaults.defaultAgentId?.trim();\n const isAlias =\n raw === \"main\" ||\n raw === mainKey ||\n (defaultAgentId &&\n (raw === `agent:${defaultAgentId}:main` ||\n raw === `agent:${defaultAgentId}:${mainKey}`));\n return isAlias ? mainSessionKey : raw;\n}\n\nfunction applySessionDefaults(host: GatewayHost, defaults?: SessionDefaultsSnapshot) {\n if (!defaults?.mainSessionKey) return;\n const resolvedSessionKey = normalizeSessionKeyForDefaults(host.sessionKey, defaults);\n const resolvedSettingsSessionKey = normalizeSessionKeyForDefaults(\n host.settings.sessionKey,\n defaults,\n );\n const resolvedLastActiveSessionKey = normalizeSessionKeyForDefaults(\n host.settings.lastActiveSessionKey,\n defaults,\n );\n const nextSessionKey = resolvedSessionKey || resolvedSettingsSessionKey || host.sessionKey;\n const nextSettings = {\n ...host.settings,\n sessionKey: resolvedSettingsSessionKey || nextSessionKey,\n lastActiveSessionKey: resolvedLastActiveSessionKey || nextSessionKey,\n };\n const shouldUpdateSettings =\n nextSettings.sessionKey !== host.settings.sessionKey ||\n nextSettings.lastActiveSessionKey !== host.settings.lastActiveSessionKey;\n if (nextSessionKey !== host.sessionKey) {\n host.sessionKey = nextSessionKey;\n }\n if (shouldUpdateSettings) {\n applySettings(host as unknown as Parameters<typeof applySettings>[0], nextSettings);\n }\n}\n\nexport function connectGateway(host: GatewayHost) {\n host.lastError = null;\n host.hello = null;\n host.connected = false;\n host.execApprovalQueue = [];\n host.execApprovalError = null;\n\n // Track the server version seen on first connect. If the version changes on\n // a subsequent reconnect (i.e. software was upgraded while the page was open),\n // reload the page so the browser picks up the new JS bundle.\n let connectedVersion: string | null = null;\n\n const isPublic = Boolean(host.publicChat);\n\n // All standalone pages use \"setup-ui\" — device identity (crypto.subtle) is only available in\n // secure contexts (HTTPS / localhost), but the control panel is typically accessed via .local\n // mDNS over plain HTTP. PIN auth is the security layer, not gateway-level client identity.\n const isStandalonePage = host.setup || host.filesPage || host.browserPage\n || host.chatPage || host.adminsPage || host.contactsPage || host.advancedPage;\n const clientName = isPublic ? \"public-chat\" : isStandalonePage ? \"setup-ui\" : \"taskmaster-control-ui\";\n\n host.client?.stop();\n host.client = new GatewayBrowserClient({\n url: host.settings.gatewayUrl,\n token: isPublic ? undefined : (host.settings.token.trim() ? host.settings.token : undefined),\n password: isPublic ? undefined : (host.password.trim() ? host.password : undefined),\n clientName,\n mode: \"webchat\",\n role: isPublic ? \"public\" : undefined,\n scopes: isPublic ? [] : undefined,\n onHello: (hello) => {\n const incomingVersion = hello.server?.version ?? null;\n if (connectedVersion !== null && incomingVersion !== null && incomingVersion !== connectedVersion) {\n // Server version changed — a software upgrade occurred while this page\n // was open. Reload to pick up the new JS bundle before the user unlocks.\n window.location.reload();\n return;\n }\n if (connectedVersion === null) {\n connectedVersion = incomingVersion;\n }\n\n host.connected = true;\n host.lastError = null;\n host.hello = hello;\n\n // Public chat: skip all admin-level initialization\n if (isPublic) {\n applySnapshot(host, hello);\n void loadAssistantIdentity(host as unknown as TaskmasterApp);\n // Auto-resolve anonymous session if auth mode is \"anonymous\"\n const authMode = host.publicChatConfig?.auth ?? \"anonymous\";\n if (authMode === \"anonymous\") {\n void resolveAnonymousSession(host);\n }\n return;\n }\n\n // Gateway is running — clear any stale uninstall flag from a previous session.\n // This prevents a reinstalled gateway from showing the \"uninstalled\" page.\n if (checkUninstallDone()) {\n clearUninstallDone();\n (host as unknown as TaskmasterApp).uninstallDone = false;\n }\n applySnapshot(host, hello);\n // Check access (PIN) status before loading page data\n void (host as unknown as TaskmasterApp).handleAccessCheck();\n void fetchLastUpdateResult(host as unknown as TaskmasterApp).then(() => {\n void checkForUpdates(host as unknown as TaskmasterApp);\n });\n void loadAssistantIdentity(host as unknown as TaskmasterApp);\n void loadAgents(host as unknown as TaskmasterApp);\n // Load model catalog for chat model selector and setup model selector\n if (host.chatPage || host.setup) {\n void loadModelCatalog(host);\n }\n void loadNodes(host as unknown as TaskmasterApp, { quiet: true });\n void loadDevices(host as unknown as TaskmasterApp, { quiet: true });\n void loadWorkspaces(host as unknown as TaskmasterApp).then(() => {\n (host as unknown as TaskmasterApp).initWorkspaceSelection();\n });\n // Check if embedding model is downloading — show blocking overlay if so\n (host as unknown as TaskmasterApp).startEmbeddingPoll();\n // Setup page needs config snapshot for iMessage per-account binding info.\n // Chat page needs it for the \"Public\" button visibility.\n if (host.setup || host.chatPage) {\n void loadConfig(host as unknown as TaskmasterApp);\n }\n if (host.setup) {\n void loadApiKeyProviders(host as unknown as TaskmasterApp);\n // Load Tailscale status for Internet Access section\n void loadTailscaleStatus(host as unknown as TaskmasterApp);\n // Load WiFi status for WiFi section (Linux only)\n void loadWifiStatus(host as unknown as TaskmasterApp);\n // Load network settings (port + hostname) for Network section\n void loadNetworkStatus(host as unknown as TaskmasterApp);\n }\n void refreshActiveTab(host as unknown as Parameters<typeof refreshActiveTab>[0]);\n },\n onClose: ({ code, reason }) => {\n host.connected = false;\n // Code 1012 = Service Restart (expected during config saves, don't show as error)\n if (code !== 1012) {\n host.lastError = `disconnected (${code}): ${reason || \"no reason\"}`;\n }\n },\n onEvent: (evt) => handleGatewayEvent(host, evt),\n onGap: ({ expected, received }) => {\n // Small gaps are normal (e.g. dropIfSlow screencast frames). Silently\n // refresh active tab data instead of alarming the user with a technical\n // error message. Only log for debugging.\n console.warn(`[gateway] event gap: expected seq ${expected}, got ${received}`);\n void refreshActiveTab(host as unknown as Parameters<typeof refreshActiveTab>[0]);\n },\n });\n host.client.start();\n}\n\nexport function handleGatewayEvent(host: GatewayHost, evt: GatewayEventFrame) {\n try {\n handleGatewayEventUnsafe(host, evt);\n } catch (err) {\n console.error(\"[gateway] handleGatewayEvent error:\", evt.event, err);\n }\n}\n\nfunction handleGatewayEventUnsafe(host: GatewayHost, evt: GatewayEventFrame) {\n host.eventLogBuffer = [\n { ts: Date.now(), event: evt.event, payload: evt.payload },\n ...host.eventLogBuffer,\n ].slice(0, 250);\n if (host.tab === \"debug\") {\n host.eventLog = host.eventLogBuffer;\n }\n\n if (evt.event === \"agent\") {\n if (host.onboarding) return;\n handleAgentEvent(\n host as unknown as Parameters<typeof handleAgentEvent>[0],\n evt.payload as AgentEventPayload | undefined,\n );\n return;\n }\n\n if (evt.event === \"chat\") {\n const payload = evt.payload as ChatEventPayload | undefined;\n if (payload?.sessionKey) {\n setLastActiveSessionKey(\n host as unknown as Parameters<typeof setLastActiveSessionKey>[0],\n payload.sessionKey,\n );\n }\n const state = handleChatEvent(host as unknown as TaskmasterApp, payload);\n if (state === \"final\" || state === \"error\" || state === \"aborted\") {\n resetToolStream(host as unknown as Parameters<typeof resetToolStream>[0]);\n void flushChatQueueForEvent(\n host as unknown as Parameters<typeof flushChatQueueForEvent>[0],\n );\n }\n if (state === \"final\") {\n // Reload with enough limit to cover all currently loaded messages plus the new response\n const app = host as unknown as TaskmasterApp;\n const reloadLimit = Math.max((app.chatMessages?.length ?? 0) + 10, CHAT_PAGE_SIZE);\n void loadChatHistory(app, { limit: reloadLimit });\n }\n return;\n }\n\n if (evt.event === \"suggestions\") {\n const payload = evt.payload as { sessionKey?: string; suggestions?: string[] } | undefined;\n if (\n payload?.sessionKey === host.sessionKey &&\n Array.isArray(payload.suggestions) &&\n payload.suggestions.length > 0\n ) {\n (host as unknown as TaskmasterApp).chatSuggestions = payload.suggestions;\n }\n return;\n }\n\n if (evt.event === \"presence\") {\n const payload = evt.payload as { presence?: PresenceEntry[] } | undefined;\n if (payload?.presence && Array.isArray(payload.presence)) {\n host.presenceEntries = payload.presence;\n host.presenceError = null;\n host.presenceStatus = null;\n }\n return;\n }\n\n if (evt.event === \"cron\") {\n const payload = evt.payload as { jobId?: string; action?: string; status?: string; durationMs?: number; summary?: string; error?: string } | undefined;\n if (payload) handleCronRunEvent(host, payload);\n if (host.tab === \"cron\") {\n void (host as unknown as TaskmasterApp).loadCron();\n }\n }\n\n if (evt.event === \"device.pair.requested\" || evt.event === \"device.pair.resolved\") {\n void loadDevices(host as unknown as TaskmasterApp, { quiet: true });\n }\n\n if (evt.event === \"exec.approval.requested\") {\n const entry = parseExecApprovalRequested(evt.payload);\n if (entry) {\n host.execApprovalQueue = addExecApproval(host.execApprovalQueue, entry);\n host.execApprovalError = null;\n const delay = Math.max(0, entry.expiresAtMs - Date.now() + 500);\n window.setTimeout(() => {\n host.execApprovalQueue = removeExecApproval(host.execApprovalQueue, entry.id);\n }, delay);\n }\n return;\n }\n\n if (evt.event === \"browser.screencast.frame\") {\n handleScreencastFrame(\n host as unknown as TaskmasterApp,\n evt.payload as { data?: string; metadata?: { deviceWidth?: number; deviceHeight?: number } } | undefined,\n );\n return;\n }\n\n if (evt.event === \"browser.handoff\") {\n handleHandoffEvent(\n host as unknown as TaskmasterApp,\n evt.payload as { id?: string; reason?: string } | undefined,\n );\n // Navigate to browser page when handoff is requested\n if (!host.browserPage) {\n window.location.href = \"/browser\";\n }\n return;\n }\n\n if (evt.event === \"browser.handoff.resolved\") {\n handleHandoffResolved(host as unknown as TaskmasterApp);\n return;\n }\n\n if (evt.event === \"exec.approval.resolved\") {\n const resolved = parseExecApprovalResolved(evt.payload);\n if (resolved) {\n host.execApprovalQueue = removeExecApproval(host.execApprovalQueue, resolved.id);\n }\n return;\n }\n\n if (evt.event === \"update.progress\") {\n handleUpdateProgress(\n host as unknown as TaskmasterApp,\n evt.payload as Record<string, unknown>,\n );\n return;\n }\n\n if (evt.event === \"notification\") {\n const payload = evt.payload as\n | { ts: number; category: string; message: string }\n | undefined;\n if (payload?.category === \"model-fallback\") {\n renderNotificationBanner(payload);\n }\n return;\n }\n}\n\nexport function applySnapshot(host: GatewayHost, hello: GatewayHelloOk) {\n const snapshot = hello.snapshot as\n | {\n presence?: PresenceEntry[];\n health?: HealthSnapshot;\n sessionDefaults?: SessionDefaultsSnapshot;\n }\n | undefined;\n if (snapshot?.presence && Array.isArray(snapshot.presence)) {\n host.presenceEntries = snapshot.presence;\n }\n if (snapshot?.health) {\n host.debugHealth = snapshot.health;\n }\n if (snapshot?.sessionDefaults) {\n applySessionDefaults(host, snapshot.sessionDefaults);\n }\n}\n\nasync function loadModelCatalog(host: GatewayHost) {\n if (!host.client || !host.connected) return;\n try {\n const res = (await host.client.request(\"models.list\", {})) as {\n models?: Array<{ id: string; name: string; provider: string; reasoning?: boolean }>;\n };\n if (Array.isArray(res?.models)) {\n host.chatModelCatalog = res.models;\n }\n } catch {\n // Non-critical — selector will just be hidden\n }\n}\n\nasync function loadApiKeyProviders(host: TaskmasterApp) {\n if (!host.client || !host.connected) return;\n try {\n host.apiKeyProviders = await fetchApiKeyProviders(host.client);\n } catch {\n // Non-critical — modal will show empty state\n }\n}\n\nasync function loadTailscaleStatus(host: TaskmasterApp) {\n if (!host.client || !host.connected) return;\n try {\n host.tailscaleStatus = await host.client.request(\"tailscale.status\");\n host.remoteAccessQrDataUrl = null;\n host.publicChatQrDataUrl = null;\n } catch {\n // Non-critical — row will show \"Checking...\"\n }\n}\n\nasync function loadWifiStatus(host: TaskmasterApp) {\n if (!host.client || !host.connected) return;\n try {\n const status = await host.client.request<NonNullable<typeof host.wifiStatus>>(\"wifi.status\");\n host.wifiStatus = status;\n\n // If connected but signal/IP missing (stale nmcli cache), trigger a scan\n // to refresh — the scan forces a radio probe that populates signal data.\n if (status?.connected && status.signal == null) {\n try {\n const [scanResult, freshStatus] = await Promise.all([\n host.client!.request<{ networks: Array<{ ssid: string; signal: number; security: string; active: boolean }> }>(\"wifi.scan\"),\n host.client!.request<NonNullable<typeof host.wifiStatus>>(\"wifi.status\"),\n ]);\n // Use the fresh status (post-scan, signal should now be populated)\n host.wifiStatus = freshStatus;\n // If signal still missing, fill from scan's active network\n if (freshStatus.signal == null && scanResult.networks) {\n const active = scanResult.networks.find((n) => n.active);\n if (active) {\n host.wifiStatus = { ...freshStatus, signal: active.signal };\n }\n }\n } catch {\n // Non-critical — row shows without signal bars\n }\n }\n } catch {\n // Non-critical — row will show \"Checking...\" or be hidden on non-Linux\n }\n}\n\nasync function loadNetworkStatus(host: TaskmasterApp) {\n if (!host.client || !host.connected) return;\n try {\n const result = await host.client.request<{ port: number; hostname: string }>(\"network.status\");\n host.networkPort = result.port;\n host.networkHostname = result.hostname;\n host.networkPortInput = String(result.port);\n host.networkHostnameInput = result.hostname;\n } catch {\n // Non-critical — row will show defaults\n }\n}\n\n// ── Public chat helpers ─────────────────────────────────────────────\n\nconst PUBLIC_COOKIE_NAME = \"taskmaster_public_id\";\n\nfunction getOrCreatePublicCookieId(ttlDays = 30): string {\n const existing = document.cookie\n .split(\";\")\n .map((c) => c.trim())\n .find((c) => c.startsWith(`${PUBLIC_COOKIE_NAME}=`));\n if (existing) return existing.split(\"=\")[1];\n // Generate a random anonymous identifier\n const id = `anon-${crypto.randomUUID?.() ?? Math.random().toString(36).slice(2)}`;\n const expires = new Date(Date.now() + ttlDays * 86400000).toUTCString();\n document.cookie = `${PUBLIC_COOKIE_NAME}=${id}; path=/; expires=${expires}; SameSite=Lax`;\n return id;\n}\n\nasync function resolveAnonymousSession(host: GatewayHost) {\n if (!host.client || !host.connected) return;\n const cookieId = getOrCreatePublicCookieId(host.publicChatConfig?.cookieTtlDays);\n try {\n const accountId = host.publicChatConfig?.accountId;\n const res = (await host.client.request(\"public.session\", { cookieId, accountId })) as {\n sessionKey?: string;\n };\n if (res?.sessionKey) {\n host.publicChatSessionKey = res.sessionKey;\n host.sessionKey = res.sessionKey;\n host.publicChatAuthenticated = true;\n host.publicChatAuthStep = \"ready\";\n // Restore any saved draft for this public chat session\n const acctId = host.publicChatConfig?.accountId ?? \"\";\n (host as unknown as TaskmasterApp).chatMessage = loadDraft(acctId, res.sessionKey);\n void loadChatHistory(host as unknown as TaskmasterApp);\n }\n } catch (err) {\n console.error(\"[public-chat] failed to resolve anonymous session:\", err);\n host.lastError = \"Failed to start chat session\";\n }\n}\n\nexport { resolveAnonymousSession, getOrCreatePublicCookieId };\n","import { html, nothing } from \"lit\";\nimport type { GatewayBrowserClient } from \"../gateway\";\nimport { getOrCreatePublicCookieId } from \"../app-gateway\";\n\nexport type PublicAuthProps = {\n authMode: \"anonymous\" | \"verified\" | \"choice\";\n authStep: \"idle\" | \"phone\" | \"email\" | \"otp\" | \"ready\";\n connected: boolean;\n client: GatewayBrowserClient | null;\n assistantName: string;\n assistantAvatar: string | null;\n accountId?: string;\n cookieTtlDays?: number;\n otpChannels?: string[];\n verifyMethods?: string[];\n onAuthenticated: (sessionKey: string) => void;\n onAuthStepChange: (step: \"idle\" | \"phone\" | \"email\" | \"otp\" | \"ready\") => void;\n /** Trigger a Lit re-render — module-level OTP state isn't reactive. */\n requestUpdate: () => void;\n};\n\nlet otpBusy = false;\nlet otpError: string | null = null;\nlet otpPhone = \"\";\nlet otpEmail = \"\";\nlet otpName = \"\";\n/** Which channel delivered the OTP — set from the server response. */\nlet otpDeliveryChannel = \"\";\n/** Track which identifier type was used for OTP so verify sends the right one. */\nlet otpIdentifierType: \"phone\" | \"email\" = \"phone\";\n/** Visitor's preferred delivery channel — set when they pick WhatsApp or SMS on the choice screen. */\nlet otpPreferredChannel: \"whatsapp\" | \"sms\" | \"\" = \"\";\n\n/** Strip spaces, dashes, and parentheses from a phone number. */\nfunction normalizePhone(raw: string): string {\n return raw.replace(/[\\s\\-()]/g, \"\");\n}\n\nfunction resetOtpState() {\n otpBusy = false;\n otpError = null;\n otpPhone = \"\";\n otpEmail = \"\";\n otpName = \"\";\n otpDeliveryChannel = \"\";\n otpIdentifierType = \"phone\";\n otpPreferredChannel = \"\";\n}\n\nasync function startAnonymousSession(props: PublicAuthProps) {\n if (!props.client || !props.connected) return;\n const cookieId = getOrCreatePublicCookieId(props.cookieTtlDays);\n try {\n const res = (await props.client.request(\"public.session\", { cookieId, accountId: props.accountId })) as {\n sessionKey?: string;\n };\n if (res?.sessionKey) {\n props.onAuthenticated(res.sessionKey);\n }\n } catch (err) {\n otpError = err instanceof Error ? err.message : \"Failed to start session\";\n props.requestUpdate();\n }\n}\n\nasync function requestOtp(props: PublicAuthProps) {\n if (!props.client || otpBusy) return;\n const phone = normalizePhone(otpPhone);\n if (!phone) {\n otpError = \"Please enter your phone number\";\n props.requestUpdate();\n return;\n }\n otpBusy = true;\n otpError = null;\n props.requestUpdate();\n try {\n const res = (await props.client.request(\"public.otp.request\", {\n phone,\n name: otpName.trim() || undefined,\n accountId: props.accountId,\n channel: otpPreferredChannel || undefined,\n })) as { ok?: boolean; channel?: string; error?: string };\n if (res?.ok) {\n otpDeliveryChannel = res.channel ?? \"\";\n otpIdentifierType = \"phone\";\n props.onAuthStepChange(\"otp\");\n } else {\n otpError = res?.error ?? \"Failed to send verification code\";\n }\n } catch (err) {\n otpError = err instanceof Error ? err.message : \"Failed to send verification code\";\n } finally {\n otpBusy = false;\n props.requestUpdate();\n }\n}\n\nasync function requestEmailOtp(props: PublicAuthProps) {\n if (!props.client || otpBusy) return;\n const email = otpEmail.trim().toLowerCase();\n if (!email || !email.includes(\"@\")) {\n otpError = \"Please enter a valid email address\";\n props.requestUpdate();\n return;\n }\n otpBusy = true;\n otpError = null;\n props.requestUpdate();\n try {\n const res = (await props.client.request(\"public.otp.request\", {\n identifier: email,\n accountId: props.accountId,\n })) as { ok?: boolean; channel?: string; error?: string };\n if (res?.ok) {\n otpDeliveryChannel = res.channel ?? \"email\";\n otpIdentifierType = \"email\";\n props.onAuthStepChange(\"otp\");\n } else {\n otpError = res?.error ?? \"Failed to send verification code\";\n }\n } catch (err) {\n otpError = err instanceof Error ? err.message : \"Failed to send verification code\";\n } finally {\n otpBusy = false;\n props.requestUpdate();\n }\n}\n\nasync function verifyOtp(props: PublicAuthProps, code: string) {\n if (!props.client || otpBusy) return;\n if (!code.trim()) {\n otpError = \"Please enter the verification code\";\n props.requestUpdate();\n return;\n }\n otpBusy = true;\n otpError = null;\n props.requestUpdate();\n try {\n const identifier = otpIdentifierType === \"email\" ? otpEmail.trim().toLowerCase() : normalizePhone(otpPhone);\n const res = (await props.client.request(\"public.otp.verify\", {\n identifier,\n code: code.trim(),\n accountId: props.accountId,\n })) as { ok?: boolean; sessionKey?: string; error?: string };\n if (res?.ok && res.sessionKey) {\n resetOtpState();\n props.onAuthenticated(res.sessionKey);\n } else {\n otpError = res?.error ?? \"Invalid verification code\";\n }\n } catch (err) {\n otpError = err instanceof Error ? err.message : \"Verification failed\";\n } finally {\n otpBusy = false;\n props.requestUpdate();\n }\n}\n\nfunction renderAvatar(_props: PublicAuthProps) {\n // Avatar is not shown — no upload feature exists for the public agent,\n // so the value is always a single-letter fallback that renders as a broken <img>.\n return nothing;\n}\n\nfunction renderPhoneForm(props: PublicAuthProps) {\n return html`\n <div class=\"public-auth__form\">\n <label class=\"field public-auth__field\">\n <span>Your name (optional)</span>\n <input\n type=\"text\"\n .value=${otpName}\n @input=${(e: Event) => { otpName = (e.target as HTMLInputElement).value; }}\n placeholder=\"Name\"\n />\n </label>\n <label class=\"field public-auth__field\">\n <span>Phone number</span>\n <input\n type=\"tel\"\n .value=${otpPhone}\n @input=${(e: Event) => { otpPhone = (e.target as HTMLInputElement).value; }}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") { e.preventDefault(); void requestOtp(props); }\n }}\n placeholder=\"+44 7123 456789\"\n required\n />\n </label>\n ${otpError ? html`<div class=\"public-auth__error\">${otpError}</div>` : nothing}\n <button\n class=\"btn primary public-auth__btn\"\n ?disabled=${otpBusy}\n @click=${() => void requestOtp(props)}\n >\n ${otpBusy ? \"Sending...\" : \"Send verification code\"}\n </button>\n </div>\n `;\n}\n\nfunction renderEmailForm(props: PublicAuthProps) {\n return html`\n <div class=\"public-auth__form\">\n <label class=\"field public-auth__field\">\n <span>Your name (optional)</span>\n <input\n type=\"text\"\n .value=${otpName}\n @input=${(e: Event) => { otpName = (e.target as HTMLInputElement).value; }}\n placeholder=\"Name\"\n />\n </label>\n <label class=\"field public-auth__field\">\n <span>Email address</span>\n <input\n type=\"email\"\n .value=${otpEmail}\n @input=${(e: Event) => { otpEmail = (e.target as HTMLInputElement).value; }}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") { e.preventDefault(); void requestEmailOtp(props); }\n }}\n placeholder=\"you@example.com\"\n required\n />\n </label>\n ${otpError ? html`<div class=\"public-auth__error\">${otpError}</div>` : nothing}\n <button\n class=\"btn primary public-auth__btn\"\n ?disabled=${otpBusy}\n @click=${() => void requestEmailOtp(props)}\n >\n ${otpBusy ? \"Sending...\" : \"Send verification code\"}\n </button>\n </div>\n `;\n}\n\nfunction renderOtpForm(props: PublicAuthProps) {\n let otpCode = \"\";\n const isEmailOtp = otpIdentifierType === \"email\";\n const channelLabel = isEmailOtp ? \"email\" : otpDeliveryChannel === \"sms\" ? \"SMS\" : \"WhatsApp\";\n const displayIdentifier = isEmailOtp ? otpEmail : otpPhone;\n const backStep: \"phone\" | \"email\" = isEmailOtp ? \"email\" : \"phone\";\n return html`\n <div class=\"public-auth__form\">\n <p class=\"public-auth__hint\">\n We sent a verification code to <strong>${displayIdentifier}</strong> via ${channelLabel}.\n </p>\n <label class=\"field public-auth__field\">\n <span>Verification code</span>\n <input\n type=\"text\"\n inputmode=\"numeric\"\n maxlength=\"6\"\n @input=${(e: Event) => { otpCode = (e.target as HTMLInputElement).value; }}\n @keydown=${(e: KeyboardEvent) => {\n if (e.key === \"Enter\") { e.preventDefault(); void verifyOtp(props, otpCode); }\n }}\n placeholder=\"123456\"\n required\n />\n </label>\n ${otpError ? html`<div class=\"public-auth__error\">${otpError}</div>` : nothing}\n <button\n class=\"btn primary public-auth__btn\"\n ?disabled=${otpBusy}\n @click=${() => void verifyOtp(props, otpCode)}\n >\n ${otpBusy ? \"Verifying...\" : \"Verify\"}\n </button>\n <button\n class=\"btn public-auth__btn public-auth__btn--link\"\n @click=${() => { otpError = null; props.onAuthStepChange(backStep); }}\n >\n ${isEmailOtp ? \"Use a different email\" : \"Use a different number\"}\n </button>\n </div>\n `;\n}\n\nexport function renderPublicAuth(props: PublicAuthProps) {\n const { authMode, authStep } = props;\n const otpAvailable = !props.otpChannels || props.otpChannels.length > 0;\n\n // \"anonymous\" mode: auto-enter immediately (no screen shown — handled by gateway onHello).\n // If we reach here it means the session hasn't resolved yet.\n if (authMode === \"anonymous\") {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Starting chat...</p>\n </div>\n </div>\n `;\n }\n\n // \"verified\" mode: identity verification required before chat\n if (authMode === \"verified\") {\n const methods = props.verifyMethods ?? [\"whatsapp\", \"sms\"];\n const hasPhone = methods.includes(\"whatsapp\") || methods.includes(\"sms\") || methods.includes(\"phone\");\n const hasEmail = methods.includes(\"email\");\n\n if (!otpAvailable && !hasEmail) {\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">Verification is not available right now.</p>\n </div>\n </div>\n `;\n }\n\n if (authStep === \"otp\") {\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n ${renderOtpForm(props)}\n </div>\n </div>\n `;\n }\n\n if (authStep === \"email\") {\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">Verify your email address to get started.</p>\n ${renderEmailForm(props)}\n ${hasPhone ? html`\n <button class=\"btn public-auth__btn public-auth__btn--link\"\n @click=${() => { resetOtpState(); props.onAuthStepChange(\"phone\"); }}>\n Use phone number instead\n </button>\n ` : nothing}\n </div>\n </div>\n `;\n }\n\n if (authStep === \"phone\") {\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">Verify your phone number to get started.</p>\n ${renderPhoneForm(props)}\n ${hasEmail ? html`\n <button class=\"btn public-auth__btn public-auth__btn--link\"\n @click=${() => { resetOtpState(); props.onAuthStepChange(\"email\"); }}>\n Use email instead\n </button>\n ` : nothing}\n </div>\n </div>\n `;\n }\n\n // Default (idle): auto-navigate to the appropriate form.\n // When both methods are available, default to phone with an email toggle.\n if (hasPhone && hasEmail) {\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">Authenticate to get started.</p>\n ${renderPhoneForm(props)}\n <button class=\"btn public-auth__btn public-auth__btn--link\"\n @click=${() => { resetOtpState(); props.onAuthStepChange(\"email\"); }}>\n Use email instead\n </button>\n </div>\n </div>\n `;\n }\n if (hasEmail) {\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">Verify your email address to get started.</p>\n ${renderEmailForm(props)}\n </div>\n </div>\n `;\n }\n // Phone only (original behaviour)\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">Verify your phone number to get started.</p>\n ${renderPhoneForm(props)}\n </div>\n </div>\n `;\n }\n\n // \"choice\" mode: user picks anonymous or verified\n const methods = props.verifyMethods ?? [\"whatsapp\", \"sms\"];\n const hasWhatsApp = methods.includes(\"whatsapp\") && (!props.otpChannels || props.otpChannels.includes(\"whatsapp\"));\n const hasSms = methods.includes(\"sms\");\n const hasEmail = methods.includes(\"email\");\n const hasPhone = hasWhatsApp || hasSms || methods.includes(\"phone\");\n const verifyAvailable = hasPhone || hasEmail;\n\n if (authStep === \"phone\" || authStep === \"email\" || authStep === \"otp\") {\n const isEmailContext = authStep === \"email\" || (authStep === \"otp\" && otpIdentifierType === \"email\");\n const channelName = isEmailContext ? \"email\" : otpPreferredChannel === \"sms\" ? \"SMS\" : \"WhatsApp\";\n const subtitle = isEmailContext\n ? \"Verify your email address to continue your conversation across devices.\"\n : `Verify your phone number to receive a code via ${channelName}.`;\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">${subtitle}</p>\n ${authStep === \"otp\"\n ? renderOtpForm(props)\n : authStep === \"email\"\n ? renderEmailForm(props)\n : renderPhoneForm(props)}\n ${authStep !== \"otp\" ? html`\n <button class=\"btn public-auth__btn public-auth__btn--link\"\n @click=${() => { resetOtpState(); props.onAuthStepChange(\"idle\"); }}>\n Back\n </button>\n ` : nothing}\n </div>\n </div>\n `;\n }\n\n // Default: choice screen — one button per available channel\n return html`\n <div class=\"setup-container\">\n <div class=\"public-auth\">\n ${renderAvatar(props)}\n <h2 class=\"public-auth__title\">Chat with ${props.assistantName}</h2>\n <p class=\"public-auth__subtitle\">How would you like to get started?</p>\n <div class=\"public-auth__choices\">\n <button\n class=\"btn primary public-auth__btn\"\n @click=${() => void startAnonymousSession(props)}\n >\n Chat now\n </button>\n ${hasWhatsApp\n ? html`\n <button\n class=\"btn public-auth__btn\"\n @click=${() => { resetOtpState(); otpPreferredChannel = \"whatsapp\"; props.onAuthStepChange(\"phone\"); }}\n >\n Authenticate with WhatsApp\n </button>\n `\n : nothing}\n ${hasSms\n ? html`\n <button\n class=\"btn public-auth__btn\"\n @click=${() => { resetOtpState(); otpPreferredChannel = \"sms\"; props.onAuthStepChange(\"phone\"); }}\n >\n Authenticate with SMS\n </button>\n `\n : nothing}\n ${hasEmail\n ? html`\n <button\n class=\"btn public-auth__btn\"\n @click=${() => { resetOtpState(); props.onAuthStepChange(\"email\"); }}\n >\n Authenticate with email\n </button>\n `\n : nothing}\n </div>\n ${verifyAvailable\n ? html`\n <p class=\"public-auth__hint\">\n Authenticating lets you continue your conversation across devices.\n </p>\n `\n : nothing}\n </div>\n </div>\n `;\n}\n","import type { GatewayBrowserClient } from \"../gateway.js\";\nimport type { ConfigSnapshot } from \"../types.js\";\n\n/* ── Form state ── */\n\nexport type OpeningHoursFormState = {\n enabled: boolean;\n publicAgentEnabled: boolean;\n days: {\n [key: string]: { start: string; end: string; closed: boolean };\n };\n closedDates: string[];\n};\n\n/* ── Controller state ── */\n\nexport type OpeningHoursState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n openingHoursLoading: boolean;\n openingHoursError: string | null;\n openingHoursBusy: boolean;\n openingHoursForm: OpeningHoursFormState;\n};\n\n/* ── Defaults ── */\n\nexport function defaultOpeningHoursForm(): OpeningHoursFormState {\n return {\n enabled: false,\n publicAgentEnabled: true,\n days: {\n monday: { start: \"09:00\", end: \"17:00\", closed: false },\n tuesday: { start: \"09:00\", end: \"17:00\", closed: false },\n wednesday: { start: \"09:00\", end: \"17:00\", closed: false },\n thursday: { start: \"09:00\", end: \"17:00\", closed: false },\n friday: { start: \"09:00\", end: \"17:00\", closed: false },\n saturday: { start: \"09:00\", end: \"17:00\", closed: true },\n sunday: { start: \"09:00\", end: \"17:00\", closed: true },\n },\n closedDates: [],\n };\n}\n\n/* ── Load ── */\n\ntype GetResponse = {\n openingHours: {\n enabled: boolean;\n timezone?: string;\n schedule: Record<string, { start: string; end: string } | null>;\n closedDates?: string[];\n } | null;\n publicAgentEnabled: boolean;\n currentlyOpen: boolean;\n reason: string;\n};\n\nconst DAY_KEYS = [\"monday\", \"tuesday\", \"wednesday\", \"thursday\", \"friday\", \"saturday\", \"sunday\"];\n\n/**\n * Full load — fetches server state and replaces the form.\n * Called on initial tab load and after saving.\n */\nexport async function loadOpeningHours(state: OpeningHoursState) {\n if (!state.client || !state.connected) return;\n if (state.openingHoursLoading) return;\n state.openingHoursLoading = true;\n state.openingHoursError = null;\n try {\n const res = (await state.client.request(\"business.openingHours.get\", {})) as GetResponse;\n\n if (res.openingHours) {\n const oh = res.openingHours;\n const days: OpeningHoursFormState[\"days\"] = {};\n for (const day of DAY_KEYS) {\n const sched = oh.schedule[day];\n if (sched === null || sched === undefined) {\n days[day] = { start: \"09:00\", end: \"17:00\", closed: true };\n } else {\n days[day] = { start: sched.start, end: sched.end, closed: false };\n }\n }\n state.openingHoursForm = {\n enabled: oh.enabled,\n publicAgentEnabled: res.publicAgentEnabled,\n days,\n closedDates: [...(oh.closedDates ?? [])].sort(),\n };\n } else {\n const form = defaultOpeningHoursForm();\n form.publicAgentEnabled = res.publicAgentEnabled;\n state.openingHoursForm = form;\n }\n } catch (err) {\n state.openingHoursError = String(err);\n } finally {\n state.openingHoursLoading = false;\n }\n}\n\n/* ── Save ── */\n\nexport async function saveOpeningHours(state: OpeningHoursState) {\n if (!state.client || !state.connected || state.openingHoursBusy) return;\n state.openingHoursBusy = true;\n state.openingHoursError = null;\n try {\n const form = state.openingHoursForm;\n const schedule: Record<string, { start: string; end: string } | null> = {};\n for (const day of DAY_KEYS) {\n const d = form.days[day];\n schedule[day] = d?.closed ? null : { start: d.start, end: d.end };\n }\n\n const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n const openingHours = {\n enabled: form.enabled,\n timezone,\n schedule,\n closedDates: form.closedDates.length > 0 ? [...form.closedDates].sort() : undefined,\n };\n\n const snapshot = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n await state.client.request(\"config.patch\", {\n raw: JSON.stringify({\n business: { openingHours, publicAgentEnabled: form.publicAgentEnabled },\n }),\n baseHash: snapshot.hash,\n note: \"Opening hours updated\",\n });\n\n // Reload to pick up persisted state and fresh open/closed status\n await loadOpeningHours(state);\n } catch (err) {\n state.openingHoursError = String(err);\n } finally {\n state.openingHoursBusy = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { ConfigSnapshot } from \"../types\";\nimport { cloneConfigObject, serializeConfigForm, setPathValue } from \"./config/form-utils\";\nimport type { AdminPhoneEntry } from \"../types.admins\";\n\nexport type AdminsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n adminsLoading: boolean;\n adminPhones: AdminPhoneEntry[];\n adminsError: string | null;\n adminsSaving: boolean;\n configSnapshot: ConfigSnapshot | null;\n configForm: Record<string, unknown> | null;\n configFormDirty: boolean;\n};\n\ntype AgentBinding = {\n agentId: string;\n match: {\n channel: string;\n accountId?: string;\n peer?: { kind: string; id: string };\n guildId?: string;\n teamId?: string;\n };\n meta?: {\n paired?: boolean;\n };\n};\n\n/**\n * Extract admin phone entries from config bindings.\n * Admin phones are bindings where agentId matches the target and match.peer.kind is \"dm\".\n * Returns entries with paired status from binding metadata.\n */\nfunction extractAdminPhones(config: Record<string, unknown> | null, targetAgentId = \"admin\"): AdminPhoneEntry[] {\n if (!config) return [];\n const bindings = config.bindings as AgentBinding[] | undefined;\n if (!Array.isArray(bindings)) return [];\n\n const entries: AdminPhoneEntry[] = [];\n for (const binding of bindings) {\n if (!binding || typeof binding !== \"object\") continue;\n // Accept both the target agent ID and legacy \"management\" alias\n if (binding.agentId !== targetAgentId && binding.agentId !== \"management\") continue;\n const match = binding.match;\n if (!match || typeof match !== \"object\") continue;\n const channel = (match.channel ?? \"\").toLowerCase();\n if (channel !== \"whatsapp\") continue;\n const peer = match.peer;\n if (!peer || typeof peer !== \"object\") continue;\n if (peer.kind !== \"dm\") continue;\n const id = peer.id ?? \"\";\n if (id) {\n entries.push({\n phone: id,\n paired: binding.meta?.paired === true,\n });\n }\n }\n // Sort so paired phone appears first\n entries.sort((a, b) => {\n if (a.paired && !b.paired) return -1;\n if (!a.paired && b.paired) return 1;\n return 0;\n });\n return entries;\n}\n\n/**\n * Build updated bindings array with admin phones added/removed.\n * Preserves paired metadata for existing bindings.\n */\nfunction buildBindingsWithAdmins(\n existingBindings: AgentBinding[],\n phones: AdminPhoneEntry[],\n targetAgentId = \"admin\",\n accountId?: string,\n): AgentBinding[] {\n const isAdminAgent = (id: string) => id === targetAgentId || id === \"management\";\n\n // Build maps of existing admin whatsapp dm bindings to preserve metadata and accountId\n const existingMetaMap = new Map<string, AgentBinding[\"meta\"]>();\n const existingAccountIdMap = new Map<string, string>();\n for (const binding of existingBindings) {\n if (!binding || typeof binding !== \"object\") continue;\n if (!isAdminAgent(binding.agentId)) continue;\n const match = binding.match;\n if (!match || typeof match !== \"object\") continue;\n const channel = (match.channel ?? \"\").toLowerCase();\n if (channel !== \"whatsapp\") continue;\n const peer = match.peer;\n if (!peer || typeof peer !== \"object\") continue;\n if (peer.kind !== \"dm\") continue;\n const id = peer.id ?? \"\";\n if (id) {\n if (binding.meta) existingMetaMap.set(id, binding.meta);\n if (match.accountId) existingAccountIdMap.set(id, match.accountId);\n }\n }\n\n // Remove existing admin whatsapp dm bindings for this agent\n const filtered = existingBindings.filter((binding) => {\n if (!binding || typeof binding !== \"object\") return true;\n if (!isAdminAgent(binding.agentId)) return true;\n const match = binding.match;\n if (!match || typeof match !== \"object\") return true;\n const channel = (match.channel ?? \"\").toLowerCase();\n if (channel !== \"whatsapp\") return true;\n const peer = match.peer;\n if (!peer || typeof peer !== \"object\") return true;\n return peer.kind !== \"dm\";\n });\n\n // Add new admin bindings for each phone, preserving metadata\n const newBindings: AgentBinding[] = phones.map((entry) => {\n // Use explicit accountId: caller-provided > preserved from existing > omit\n const resolvedAccountId = accountId ?? existingAccountIdMap.get(entry.phone);\n const matchObj: AgentBinding[\"match\"] = {\n channel: \"whatsapp\",\n peer: { kind: \"dm\", id: entry.phone },\n };\n if (resolvedAccountId) matchObj.accountId = resolvedAccountId;\n const binding: AgentBinding = { agentId: targetAgentId, match: matchObj };\n // Preserve existing metadata or use entry's paired status\n const existingMeta = existingMetaMap.get(entry.phone);\n if (existingMeta) {\n binding.meta = existingMeta;\n } else if (entry.paired) {\n binding.meta = { paired: true };\n }\n return binding;\n });\n\n return [...filtered, ...newBindings];\n}\n\nexport async function loadAdmins(state: AdminsState, adminAgentId?: string) {\n if (!state.client || !state.connected) return;\n if (!adminAgentId) {\n // No workspace context yet — clear data and wait for workspace selection\n state.adminPhones = [];\n return;\n }\n if (state.adminsLoading) return;\n state.adminsLoading = true;\n state.adminsError = null;\n const agentId = adminAgentId;\n try {\n const res = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n state.configSnapshot = res;\n const config = res.config as Record<string, unknown> | null;\n state.configForm = cloneConfigObject(config ?? {});\n state.adminPhones = extractAdminPhones(config, agentId);\n state.configFormDirty = false;\n } catch (err) {\n state.adminsError = String(err);\n } finally {\n state.adminsLoading = false;\n }\n}\n\nexport async function addAdmin(state: AdminsState, phone: string, adminAgentId?: string, accountId?: string) {\n if (!state.client || !state.connected) return;\n if (!adminAgentId) {\n state.adminsError = \"No business selected.\";\n return;\n }\n if (state.adminsSaving) return;\n const agentId = adminAgentId;\n\n // Normalize phone number (ensure E.164 format)\n let normalized = phone.replace(/[\\s\\-\\(\\)]/g, \"\");\n if (!normalized) {\n state.adminsError = \"Phone number is required\";\n return;\n }\n // Add + if missing\n if (!normalized.startsWith(\"+\")) {\n normalized = \"+\" + normalized;\n }\n // Validate basic phone format\n if (!/^\\+[1-9]\\d{6,14}$/.test(normalized)) {\n state.adminsError = \"Invalid phone number. Use international format (e.g., +44 7504 472444)\";\n return;\n }\n\n // Check if already exists\n if (state.adminPhones.some((entry) => entry.phone === normalized)) {\n state.adminsError = \"Phone number already exists\";\n return;\n }\n\n state.adminsSaving = true;\n state.adminsError = null;\n try {\n const config = cloneConfigObject(\n state.configForm ?? state.configSnapshot?.config ?? {},\n );\n const existingBindings = (config.bindings as AgentBinding[]) ?? [];\n const newPhones: AdminPhoneEntry[] = [...state.adminPhones, { phone: normalized }];\n const updatedBindings = buildBindingsWithAdmins(existingBindings, newPhones, agentId, accountId);\n setPathValue(config, [\"bindings\"], updatedBindings);\n\n const baseHash = state.configSnapshot?.hash;\n if (!baseHash) {\n state.adminsError = \"Config hash missing; reload and retry.\";\n return;\n }\n const raw = serializeConfigForm(config);\n await state.client.request(\"config.set\", { raw, baseHash });\n\n // Reload to get fresh state\n await loadAdmins(state, adminAgentId);\n } catch (err) {\n state.adminsError = String(err);\n } finally {\n state.adminsSaving = false;\n }\n}\n\nexport async function removeAdmin(state: AdminsState, phone: string, adminAgentId?: string, accountId?: string) {\n if (!state.client || !state.connected) return;\n if (!adminAgentId) {\n state.adminsError = \"No business selected.\";\n return;\n }\n if (state.adminsSaving) return;\n const agentId = adminAgentId;\n\n // Prevent removing paired phone\n const entry = state.adminPhones.find((e) => e.phone === phone);\n if (entry?.paired) {\n state.adminsError = \"Cannot remove the paired phone. Unlink WhatsApp first.\";\n return;\n }\n\n state.adminsSaving = true;\n state.adminsError = null;\n try {\n const config = cloneConfigObject(\n state.configForm ?? state.configSnapshot?.config ?? {},\n );\n const existingBindings = (config.bindings as AgentBinding[]) ?? [];\n const newPhones = state.adminPhones.filter((e) => e.phone !== phone);\n const updatedBindings = buildBindingsWithAdmins(existingBindings, newPhones, agentId, accountId);\n setPathValue(config, [\"bindings\"], updatedBindings);\n\n const baseHash = state.configSnapshot?.hash;\n if (!baseHash) {\n state.adminsError = \"Config hash missing; reload and retry.\";\n return;\n }\n const raw = serializeConfigForm(config);\n await state.client.request(\"config.set\", { raw, baseHash });\n\n // Reload to get fresh state\n await loadAdmins(state, adminAgentId);\n } catch (err) {\n state.adminsError = String(err);\n } finally {\n state.adminsSaving = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\n\nexport type ContactRecord = {\n id: string;\n name: string;\n createdAt: string;\n updatedAt: string;\n fields: Record<string, string>;\n};\n\nexport type ContactsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n contactsLoading: boolean;\n contactsSaving: boolean;\n contactsRecords: ContactRecord[];\n contactsError: string | null;\n contactsSearchQuery: string;\n contactsEditingId: string | null;\n contactsShowAddForm: boolean;\n contactsNewPhone: string;\n contactsNewName: string;\n};\n\nexport async function loadContacts(state: ContactsState, workspace?: string) {\n if (!state.client || !state.connected) return;\n if (!workspace) {\n // No workspace context yet — clear data and wait for workspace selection\n state.contactsRecords = [];\n return;\n }\n if (state.contactsLoading) return;\n state.contactsLoading = true;\n state.contactsError = null;\n try {\n const query = state.contactsSearchQuery.trim();\n const res = query\n ? (await state.client.request(\"records.search\", { query, workspace })) as { records: ContactRecord[] }\n : (await state.client.request(\"records.list\", { workspace })) as { records: ContactRecord[] };\n state.contactsRecords = res.records ?? [];\n } catch (err) {\n state.contactsError = String(err);\n } finally {\n state.contactsLoading = false;\n }\n}\n\nexport async function addContact(state: ContactsState, phone: string, name: string, workspace?: string) {\n if (!state.client || !state.connected) return;\n if (state.contactsSaving) return;\n\n let normalizedPhone = phone.replace(/[\\s\\-\\(\\)]/g, \"\");\n const trimmedName = name.trim();\n if (!normalizedPhone) {\n state.contactsError = \"Phone number is required\";\n return;\n }\n if (!trimmedName) {\n state.contactsError = \"Name is required\";\n return;\n }\n if (!normalizedPhone.startsWith(\"+\")) {\n normalizedPhone = \"+\" + normalizedPhone;\n }\n if (!/^\\+[1-9]\\d{6,14}$/.test(normalizedPhone)) {\n state.contactsError = \"Invalid phone number. Use international format (e.g., +44 7490 553305)\";\n return;\n }\n\n state.contactsSaving = true;\n state.contactsError = null;\n try {\n await state.client.request(\"records.set\", {\n id: normalizedPhone,\n name: trimmedName,\n fields: {},\n workspace,\n });\n state.contactsShowAddForm = false;\n state.contactsNewPhone = \"\";\n state.contactsNewName = \"\";\n await loadContacts(state, workspace);\n } catch (err) {\n state.contactsError = String(err);\n } finally {\n state.contactsSaving = false;\n }\n}\n\nexport async function deleteContact(state: ContactsState, id: string, workspace?: string) {\n if (!state.client || !state.connected) return;\n if (state.contactsSaving) return;\n state.contactsSaving = true;\n state.contactsError = null;\n try {\n await state.client.request(\"records.delete\", { id });\n if (state.contactsEditingId === id) state.contactsEditingId = null;\n await loadContacts(state, workspace);\n } catch (err) {\n state.contactsError = String(err);\n } finally {\n state.contactsSaving = false;\n }\n}\n\nexport async function setContactField(\n state: ContactsState,\n id: string,\n key: string,\n value: string,\n workspace?: string,\n) {\n if (!state.client || !state.connected) return;\n if (state.contactsSaving) return;\n state.contactsSaving = true;\n state.contactsError = null;\n try {\n await state.client.request(\"records.setField\", { id, key, value });\n await loadContacts(state, workspace);\n } catch (err) {\n state.contactsError = String(err);\n } finally {\n state.contactsSaving = false;\n }\n}\n\nexport async function deleteContactField(state: ContactsState, id: string, key: string, workspace?: string) {\n if (!state.client || !state.connected) return;\n if (state.contactsSaving) return;\n state.contactsSaving = true;\n state.contactsError = null;\n try {\n await state.client.request(\"records.deleteField\", { id, key });\n await loadContacts(state, workspace);\n } catch (err) {\n state.contactsError = String(err);\n } finally {\n state.contactsSaving = false;\n }\n}\n","import { html, nothing } from \"lit\";\n\nimport type { GatewayBrowserClient, GatewayHelloOk } from \"./gateway\";\nimport type { AppViewState } from \"./app-view-state\";\nimport { parseAgentSessionKey } from \"../../../src/routing/session-key.js\";\nimport { resolveBrand, applyWorkspaceBrand, getWorkspaceBrands } from \"./brand\";\nimport {\n pathForTab,\n type Tab,\n} from \"./navigation\";\nimport { icons } from \"./icons\";\nimport { scheduleDraftSave, flushDraftSave, saveDraft, loadDraft, clearDraft, type UiSettings } from \"./storage\";\nimport type { ThemeMode } from \"./theme\";\nimport type { ThemeTransitionContext } from \"./theme-transition\";\nimport type {\n ConfigSnapshot,\n CronJob,\n CronRunLogEntry,\n CronStatus,\n HealthSnapshot,\n LogEntry,\n LogLevel,\n PresenceEntry,\n ChannelsStatusSnapshot,\n SessionsListResult,\n SessionTranscriptEntry,\n SessionLogType,\n SkillStatusReport,\n StatusSummary,\n} from \"./types\";\nimport type { ChatQueueItem, CronFormState } from \"./ui-types\";\nimport { refreshChatAvatar } from \"./app-chat\";\nimport { renderBrowserViewer } from \"./views/browser-viewer\";\nimport { renderFiles } from \"./views/files\";\nimport { renderSetup } from \"./views/setup\";\nimport { renderAdminsPage } from \"./views/admins\";\nimport { renderContactsPage } from \"./views/contacts\";\nimport { renderChatPage, type ChatPageTab } from \"./views/chat-page\";\nimport type { WhatsAppTabProps } from \"./views/whatsapp-tab\";\nimport {\n loadConversations,\n selectConversation,\n setGroupActivation,\n type WhatsAppTabState,\n} from \"./controllers/whatsapp\";\nimport { renderAdvancedPage, type AdvancedTab } from \"./views/advanced\";\nimport { renderLoginOverlay } from \"./views/login\";\nimport { renderPublicChatPage } from \"./views/public-chat-page\";\nimport { renderPublicAuth } from \"./views/public-auth\";\nimport { setAccountPin } from \"./controllers/access\";\nimport { loadApiKeyProviders as loadApiKeys, saveApiKey, removeApiKey, disableApiKey } from \"./controllers/apikeys\";\nimport type { WorkspaceNavProps } from \"./views/page-nav\";\nimport type { WorkspaceInfo } from \"./controllers/workspaces\";\nimport { loadChannels } from \"./controllers/channels\";\nimport {\n startScreencast as startBrowserScreencast,\n stopScreencast as stopBrowserScreencast,\n sendMouseInput,\n sendKeyInput,\n completeHandoff,\n toggleInputMode,\n toggleFullscreen,\n getCanvasRenderer,\n} from \"./controllers/browser-viewer\";\nimport {\n bulkDownloadFiles,\n createFolder,\n deleteFile,\n downloadFile,\n loadFileTree,\n loadMemoryStatus,\n moveFileToDir,\n clearSearch,\n reindexMemory,\n searchMemory,\n selectFile,\n toggleDirectory,\n toggleSelectFile,\n uploadFiles,\n} from \"./controllers/files\";\nimport {\n closeAddSkillModal,\n closeSkillDetail,\n deleteDraft,\n deleteSkill,\n editDetailSkill,\n editSkill,\n importDraft,\n installDraft,\n installSkill,\n setEditTab,\n loadSkills,\n openAddSkillModal,\n saveNewSkill,\n saveSkillApiKey,\n setSkillDetailTab,\n toggleAlwaysActive,\n updateFormReference,\n updateSkillAgents,\n updateSkillEdit,\n updateSkillEnabled,\n viewSkillDetail,\n type SkillMessage,\n} from \"./controllers/skills\";\nimport { loadChatHistory, CHAT_PAGE_SIZE } from \"./controllers/chat\";\nimport {\n loadConfig,\n updateConfigFormValue,\n} from \"./controllers/config\";\nimport { loadCronRuns, toggleCronJob, runCronJob, removeCronJob, addCronJob, updateCronJob, cronJobToFormState } from \"./controllers/cron\";\nimport { loadOpeningHours, saveOpeningHours, defaultOpeningHoursForm } from \"./controllers/opening-hours\";\nimport { loadLogs } from \"./controllers/logs\";\nimport { loadSessionLogs } from \"./controllers/session-logs\";\nimport { startLogsPolling, stopLogsPolling, startSessionLogsPolling, stopSessionLogsPolling } from \"./app-polling\";\nimport { loadAdmins, addAdmin, removeAdmin } from \"./controllers/admins\";\nimport {\n loadContacts,\n addContact,\n deleteContact,\n setContactField,\n deleteContactField,\n} from \"./controllers/contacts\";\n\n// ── Tailscale connect progress (module-scoped to survive re-renders) ──\nlet _tsProgressInterval: ReturnType<typeof setInterval> | null = null;\nlet _tsPollInterval: ReturnType<typeof setInterval> | null = null;\nlet _tsPollTimeout: ReturnType<typeof setTimeout> | null = null;\n\nconst TS_PROGRESS_MESSAGES: [number, string][] = [\n [0, \"Checking Tailscale service...\"],\n [5, \"Starting login...\"],\n [15, \"Requesting authentication link...\"],\n [40, \"Setting up secure connection...\"],\n [70, \"Almost ready...\"],\n];\n\nfunction clearTailscaleTimers() {\n if (_tsProgressInterval) { clearInterval(_tsProgressInterval); _tsProgressInterval = null; }\n if (_tsPollInterval) { clearInterval(_tsPollInterval); _tsPollInterval = null; }\n if (_tsPollTimeout) { clearTimeout(_tsPollTimeout); _tsPollTimeout = null; }\n}\n\nfunction buildWorkspaceNavProps(state: AppViewState): WorkspaceNavProps | undefined {\n if (state.workspaces.length === 0) return undefined;\n return {\n workspaces: state.workspaces,\n selectedWorkspace: state.selectedWorkspace,\n onWorkspaceSelect: (name: string) => state.handleWorkspaceSelect(name),\n hasPins: state.accessState.hasPins,\n isMaster: state.accessState.master,\n onLogout: () => state.handleLogout(),\n auditCount: state.auditEntries.length,\n onAuditClick: () => { state.auditModalOpen = true; },\n onRestartGateway: () => state.handleGatewayRestart(),\n };\n}\n\n/** Setup page variant: \"Add Account\" opens the add form instead of navigating */\nfunction buildSetupWorkspaceNavProps(state: AppViewState): WorkspaceNavProps | undefined {\n if (state.workspaces.length === 0) return undefined;\n return {\n workspaces: state.workspaces,\n selectedWorkspace: state.selectedWorkspace,\n onWorkspaceSelect: (name: string) => state.handleWorkspaceSelect(name),\n onAddAccount: () => { state.addingWorkspace = true; },\n hasPins: state.accessState.hasPins,\n isMaster: state.accessState.master,\n onLogout: () => state.handleLogout(),\n auditCount: state.auditEntries.length,\n onAuditClick: () => { state.auditModalOpen = true; },\n onRestartGateway: () => state.handleGatewayRestart(),\n };\n}\n\nfunction resolveAdminAgentId(state: AppViewState): string | undefined {\n const ws = getSelectedWorkspaceInfo(state);\n if (!ws) return undefined;\n const adminAgent = ws.agents.find((a) => a.id.endsWith(\"-admin\") || a.id === \"admin\");\n return adminAgent?.id;\n}\n\nfunction resolveWhatsAppAccountId(state: AppViewState): string | undefined {\n const ws = getSelectedWorkspaceInfo(state);\n return ws?.whatsappAccountId ?? undefined;\n}\n\nfunction resolveFilesAgentId(state: AppViewState): string | undefined {\n const ws = getSelectedWorkspaceInfo(state);\n if (!ws) return undefined;\n // Use the admin agent — it has the most complete workspace view\n // (all shared symlinks + its own physical admin/ memory folder).\n const adminAgent = ws.agents.find((a) => a.id.endsWith(\"-admin\") || a.id === \"admin\");\n return adminAgent?.id ?? ws.agents[0]?.id;\n}\n\nfunction resolveWorkspaceName(state: AppViewState): string | undefined {\n return state.selectedWorkspace ?? undefined;\n}\n\nfunction getSelectedWorkspaceInfo(state: AppViewState): WorkspaceInfo | null {\n if (!state.selectedWorkspace) return null;\n return state.workspaces.find((ws) => ws.name === state.selectedWorkspace) ?? null;\n}\n\nconst AVATAR_DATA_RE = /^data:/i;\nconst AVATAR_HTTP_RE = /^https?:\\/\\//i;\n\nfunction resolveAssistantAvatarUrl(state: AppViewState): string | undefined {\n const list = state.agentsList?.agents ?? [];\n const parsed = parseAgentSessionKey(state.sessionKey);\n const agentId =\n parsed?.agentId ??\n state.agentsList?.defaultId ??\n \"main\";\n const agent = list.find((entry) => entry.id === agentId);\n const identity = agent?.identity;\n const candidate = identity?.avatarUrl ?? identity?.avatar;\n if (!candidate) return undefined;\n if (AVATAR_DATA_RE.test(candidate) || AVATAR_HTTP_RE.test(candidate)) return candidate;\n return identity?.avatarUrl;\n}\n\n// Extract WhatsApp channel status from channelsSnapshot\nfunction extractWhatsAppStatus(\n snapshot: ChannelsStatusSnapshot | null,\n): { running: boolean; connected: boolean; linked: boolean; lastError?: string | null } | null {\n if (!snapshot) return null;\n const accounts = snapshot.channelAccounts?.whatsapp;\n if (!accounts || accounts.length === 0) return null;\n const account = accounts[0];\n return {\n running: account.running ?? false,\n connected: account.connected ?? false,\n linked: account.linked ?? false,\n lastError: account.lastError,\n };\n}\n\n// Extract iMessage channel status from channelsSnapshot\nfunction extractIMessageStatus(snapshot: ChannelsStatusSnapshot | null): {\n configured: boolean;\n running: boolean;\n connected: boolean;\n lastError: string | null;\n selfChatMode: boolean;\n dmPolicy: string | null;\n cliPath: string | null;\n} {\n if (!snapshot) return { configured: false, running: false, connected: false, lastError: null, selfChatMode: false, dmPolicy: null, cliPath: null };\n const accounts = snapshot.channelAccounts?.imessage;\n if (!accounts || accounts.length === 0) {\n return { configured: false, running: false, connected: false, lastError: null, selfChatMode: false, dmPolicy: null, cliPath: null };\n }\n const account = accounts[0];\n const running = account.running ?? false;\n // Derive \"connected\" from probe result when available, fall back to running state.\n // The iMessage snapshot doesn't include a `connected` field — the probe\n // (which runs `imsg rpc` → `chats.list`) is the authoritative connectivity check.\n const probe = account.probe as { ok?: boolean } | undefined;\n const connected = probe != null ? (probe.ok === true) : running;\n return {\n configured: account.configured ?? false,\n running,\n connected,\n lastError: account.lastError ?? null,\n selfChatMode: account.mode === \"self-chat\" || Boolean((account as Record<string, unknown>).selfChatMode),\n dmPolicy: account.dmPolicy ?? null,\n cliPath: account.cliPath ?? null,\n };\n}\n\n/**\n * Determine which workspace owns iMessage by inspecting bindings.\n * Looks for any binding with `match.channel === \"imessage\"` and `meta.imessageOwner`.\n * The agentId tells us the workspace: \"tradesupport-admin\" → \"tradesupport\", \"admin\" → default.\n */\nfunction resolveIMessageOwnerWorkspace(state: AppViewState): string | null {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n if (!config) return null;\n const bindings = config.bindings as Array<{\n agentId: string;\n match: { channel?: string };\n meta?: { imessageOwner?: boolean };\n }> | undefined;\n if (!Array.isArray(bindings)) return null;\n const imsgBinding = bindings.find(\n (b) => b.match?.channel === \"imessage\" && b.meta?.imessageOwner,\n );\n if (!imsgBinding) return null;\n const agentId = imsgBinding.agentId;\n // Map agentId back to workspace name\n for (const ws of state.workspaces) {\n if (ws.agents.some((a) => a.id === agentId)) return ws.name;\n }\n // Fallback: derive from agent naming convention\n if (agentId === \"admin\" || agentId === \"public\") {\n const defaultWs = state.workspaces.find((ws) => ws.isDefault);\n return defaultWs?.name ?? null;\n }\n const prefix = agentId.replace(/-(admin|public)$/, \"\");\n if (prefix !== agentId) {\n const ws = state.workspaces.find((ws) => ws.name === prefix);\n return ws?.name ?? null;\n }\n return null;\n}\n\n/**\n * Build a mutable WhatsAppTabState that reads from and writes to the app state.\n * Controller functions mutate the state object in place; after each async\n * operation, call state.requestUpdate() to trigger a re-render.\n */\nfunction buildWhatsAppState(state: AppViewState): WhatsAppTabState {\n // Return a proxy-like plain object whose properties point at the app state.\n // The controller functions (loadConversations, selectConversation, etc.)\n // mutate the object in place, so we use property accessors.\n const proxy: WhatsAppTabState = Object.create(null);\n Object.defineProperties(proxy, {\n client: { get: () => state.client, set: () => {} },\n connected: { get: () => state.connected, set: () => {} },\n conversations: { get: () => state.waConversations, set: (v) => { state.waConversations = v; } },\n selectedJid: { get: () => state.waSelectedJid, set: (v) => { state.waSelectedJid = v; } },\n messages: { get: () => state.waMessages, set: (v) => { state.waMessages = v; } },\n groupInfo: { get: () => state.waGroupInfo, set: (v) => { state.waGroupInfo = v; } },\n loading: { get: () => state.waLoading, set: (v) => { state.waLoading = v; } },\n messagesLoading: { get: () => state.waMessagesLoading, set: (v) => { state.waMessagesLoading = v; } },\n searchQuery: { get: () => state.waSearchQuery, set: (v) => { state.waSearchQuery = v; } },\n composeDraft: { get: () => state.waComposeDraft, set: (v) => { state.waComposeDraft = v; } },\n sending: { get: () => state.waSending, set: (v) => { state.waSending = v; } },\n lastError: { get: () => state.waLastError, set: (v) => { state.waLastError = v; } },\n accountId: { get: () => resolveWhatsAppAccountId(state), set: () => {} },\n });\n return proxy;\n}\n\nfunction scrollWhatsAppMessagesToBottom(): void {\n requestAnimationFrame(() => {\n const el = document.querySelector(\".wa-messages\");\n if (el) el.scrollTop = el.scrollHeight;\n });\n}\n\nfunction buildWhatsAppProps(state: AppViewState): WhatsAppTabProps {\n return {\n client: state.client,\n connected: state.connected,\n conversations: state.waConversations ?? [],\n selectedJid: state.waSelectedJid ?? null,\n messages: state.waMessages ?? [],\n groupInfo: state.waGroupInfo ?? null,\n loading: state.waLoading ?? false,\n messagesLoading: state.waMessagesLoading ?? false,\n searchQuery: state.waSearchQuery ?? \"\",\n composeDraft: state.waComposeDraft ?? \"\",\n sending: state.waSending ?? false,\n lastError: state.waLastError ?? null,\n accountId: resolveWhatsAppAccountId(state),\n onSelectConversation: (jid) => {\n const waState = buildWhatsAppState(state);\n void selectConversation(waState, jid).then(() => {\n state.requestUpdate();\n scrollWhatsAppMessagesToBottom();\n });\n },\n onBack: () => {\n state.waSelectedJid = null;\n state.waMessages = [];\n state.waGroupInfo = null;\n state.requestUpdate();\n },\n onSearchChange: (query) => {\n state.waSearchQuery = query;\n state.requestUpdate();\n },\n onActivationChange: (jid, activation) => {\n const waState = buildWhatsAppState(state);\n void setGroupActivation(waState, jid, activation).then(() => state.requestUpdate());\n },\n onRefresh: () => {\n const waState = buildWhatsAppState(state);\n void loadConversations(waState).then(() => state.requestUpdate());\n },\n requestUpdate: () => state.requestUpdate(),\n };\n}\n\nexport function renderApp(state: AppViewState) {\n // ── Embedding model download overlay ──\n // Blocks ALL navigation while the embedding model is downloading.\n // This runs before any page routing so no other UI is accessible.\n if (state.embeddingDownloading && !state.publicChat) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\" style=\"text-align:center; max-width:420px;\">\n <div class=\"setup-spinner\"></div>\n <h2 style=\"margin:16px 0 8px; font-size:1.1rem; font-weight:600; color:#fff;\">Downloading embedding model</h2>\n <p style=\"margin:0; color:rgba(255,255,255,0.6); font-size:0.85rem; line-height:1.4;\">\n This is a one-time download after install or upgrade.\n It may take a few minutes depending on your connection.\n </p>\n <p style=\"margin:12px 0 0; color:rgba(255,255,255,0.4); font-size:0.75rem;\">\n Memory search will be available when the download completes.\n </p>\n </div>\n </div>\n `;\n }\n\n // ── Public chat mode ──\n // Bypasses all admin UI (PIN auth, nav, workspaces). Routes directly to\n // the public auth screen or the public chat page.\n if (state.publicChat) {\n if (!state.connected) {\n return html`\n <div class=\"setup-container\">\n <div class=\"setup-card\">\n <div class=\"setup-spinner\"></div>\n <p>Connecting...</p>\n </div>\n </div>\n `;\n }\n if (!state.publicChatAuthenticated) {\n return renderPublicAuth({\n authMode: (state.publicChatConfig.auth ?? \"anonymous\") as \"anonymous\" | \"verified\" | \"choice\",\n authStep: state.publicChatAuthStep,\n connected: state.connected,\n client: state.client,\n assistantName: state.assistantName,\n assistantAvatar: state.assistantAvatar,\n accountId: state.publicChatConfig.accountId,\n cookieTtlDays: state.publicChatConfig.cookieTtlDays,\n otpChannels: state.publicChatConfig.otpChannels,\n verifyMethods: state.publicChatConfig.verifyMethods,\n onAuthenticated: (sessionKey: string) => {\n state.publicChatSessionKey = sessionKey;\n state.sessionKey = sessionKey;\n state.publicChatAuthenticated = true;\n state.publicChatAuthStep = \"ready\";\n // Restore any saved draft for this public chat session\n const acctId = state.publicChatConfig?.accountId ?? \"\";\n state.chatMessage = loadDraft(acctId, sessionKey);\n void import(\"./controllers/chat\").then(({ loadChatHistory }) => {\n loadChatHistory(state as unknown as import(\"./app\").TaskmasterApp);\n });\n },\n onAuthStepChange: (step: \"idle\" | \"phone\" | \"email\" | \"otp\" | \"ready\") => {\n state.publicChatAuthStep = step;\n },\n requestUpdate: () => { state.requestUpdate(); },\n });\n }\n // Always prepend the synthetic assistant greeting as the first message\n const greeting = (state.publicChatConfig as { greeting?: string } | undefined)?.greeting;\n const realMessages = state.chatMessages;\n const chatMessages = (!state.chatLoading && greeting)\n ? [{ role: \"assistant\", content: [{ type: \"text\", text: greeting }], timestamp: 0 }, ...(Array.isArray(realMessages) ? realMessages : [])]\n : realMessages;\n\n return renderPublicChatPage({\n connected: state.connected,\n sessionKey: state.sessionKey,\n loading: state.chatLoading,\n sending: state.chatSending,\n messages: chatMessages,\n toolMessages: state.chatToolMessages,\n stream: state.chatStream,\n streamStartedAt: (state as unknown as { chatStreamStartedAt: number | null }).chatStreamStartedAt,\n interimText: (state as unknown as { chatInterimText: string | null }).chatInterimText,\n assistantAvatarUrl: state.chatAvatarUrl ?? resolveAssistantAvatarUrl(state) ?? null,\n draft: state.chatMessage,\n queue: state.chatQueue,\n canSend: state.connected,\n canAbort: Boolean(state.chatRunId),\n disabledReason: state.connected ? null : \"Disconnected.\",\n error: state.lastError,\n assistantName: state.assistantName,\n assistantAvatar: state.assistantAvatar,\n suggestions: (state as unknown as { chatSuggestions: string[] }).chatSuggestions,\n onSuggestionClick: (text: string) => {\n state.chatMessage = text;\n (state as unknown as { chatSuggestions: string[] }).chatSuggestions = [];\n void (state as unknown as { handleSendChat: () => Promise<void> }).handleSendChat();\n },\n onRefresh: () => {\n (state as unknown as { resetToolStream: () => void }).resetToolStream();\n return import(\"./controllers/chat\").then(({ loadChatHistory }) => {\n loadChatHistory(state as unknown as import(\"./app\").TaskmasterApp);\n });\n },\n onDraftChange: (next) => {\n state.chatMessage = next;\n const acctId = state.publicChatConfig?.accountId ?? \"\";\n scheduleDraftSave(acctId, state.sessionKey, next);\n },\n requestUpdate: () => state.requestUpdate(),\n attachments: state.chatAttachments,\n onAttachmentsChange: (next) => (state.chatAttachments = next),\n onSend: () => (state as unknown as { handleSendChat: () => Promise<void> }).handleSendChat(),\n onAbort: () => void (state as unknown as { handleAbortChat: () => Promise<void> }).handleAbortChat(),\n onQueueRemove: (id) => (state as unknown as { removeQueuedMessage: (id: string) => void }).removeQueuedMessage(id),\n onChatScroll: (event) => (state as unknown as { handleChatScroll: (e: Event) => void }).handleChatScroll(event),\n nearBottom: state.chatUserNearBottom,\n hasMore: (state as unknown as { chatHistoryHasMore: boolean }).chatHistoryHasMore,\n loadingOlder: (state as unknown as { chatLoadingOlder: boolean }).chatLoadingOlder,\n onLoadOlder: () => void (state as unknown as { handleLoadOlderChat: () => Promise<void> }).handleLoadOlderChat(),\n });\n }\n\n // ── Access (PIN) gating ──\n // Wait for gateway connection + access check before rendering anything\n if (state.connected && state.accessState.checked) {\n const { accessState } = state;\n\n // PINs exist but session is not authenticated → show login overlay\n if (accessState.hasPins && !accessState.authenticated) {\n return renderLoginOverlay({\n show: true,\n isFirstTime: false,\n accounts: accessState.accounts,\n error: accessState.error,\n busy: accessState.busy,\n onSubmit: (accountOrPin: string, pin?: string) => {\n if (pin != null) state.handlePinSubmit(accountOrPin, pin);\n },\n changePinMode: state.loginChangePinMode,\n onToggleChangePinMode: () => state.toggleChangePinMode(),\n changePinBusy: state.changePinBusy,\n changePinError: state.changePinError,\n changePinSuccess: state.changePinSuccess,\n onChangePin: (account, oldPin, newPin) => state.handleChangePin(account, oldPin, newPin),\n });\n }\n\n // No master PIN yet + on Setup page + not authenticated → show first-time PIN setup overlay\n // (The !authenticated check prevents this from firing on fallback when access.status fails)\n if (!accessState.hasMasterPin && !accessState.authenticated && state.setup) {\n return renderLoginOverlay({\n show: true,\n isFirstTime: true,\n accounts: [],\n error: accessState.error,\n busy: accessState.busy,\n onSubmit: (pin: string) => state.handleSetMasterPin(pin),\n });\n }\n\n // No master PIN + not authenticated + NOT on Setup → redirect to Setup to set one\n if (!accessState.hasMasterPin && !accessState.authenticated && !state.setup) {\n window.location.href = \"/setup\";\n return nothing;\n }\n }\n\n // Setup mode: render multi-step setup view (auth + WhatsApp)\n if (state.setup) {\n const whatsappChannelStatus = extractWhatsAppStatus(state.channelsSnapshot);\n const whatsappAccounts = state.channelsSnapshot?.channelAccounts?.whatsapp ?? [];\n const imsg = extractIMessageStatus(state.channelsSnapshot);\n const imessageOwnerWorkspace = resolveIMessageOwnerWorkspace(state);\n const refreshTailscaleStatus = async () => {\n state.tailscaleStatus = await state.client!.request<NonNullable<typeof state.tailscaleStatus>>(\"tailscale.status\");\n state.remoteAccessQrDataUrl = null;\n state.publicChatQrDataUrl = null;\n };\n const startTailscaleProgress = () => {\n const startTime = Date.now();\n state.tailscaleConnectProgress = 0;\n state.tailscaleConnectMessage = TS_PROGRESS_MESSAGES[0][1];\n state.tailscaleConnectSuccess = false;\n state.tailscaleError = null;\n clearTailscaleTimers();\n _tsProgressInterval = setInterval(() => {\n const elapsed = (Date.now() - startTime) / 1000;\n // Progress 0-95% over ~90 seconds (ease out)\n const progress = Math.min(95, 95 * (1 - Math.exp(-elapsed / 30)));\n state.tailscaleConnectProgress = Math.round(progress);\n // Rotate messages based on elapsed time\n let msg = TS_PROGRESS_MESSAGES[0][1];\n for (const [threshold, text] of TS_PROGRESS_MESSAGES) {\n if (elapsed >= threshold) msg = text;\n }\n state.tailscaleConnectMessage = msg;\n }, 500);\n };\n return renderSetup({\n connected: state.connected,\n serverPlatform: state.hello?.server?.platform ?? null,\n assistantName: state.assistantName,\n currentStep: state.setupStep,\n // License state\n licenseKey: state.licenseKey,\n licenseBusy: state.licenseBusy,\n licenseValid: state.licenseValid,\n licenseMessage: state.licenseMessage,\n licenseTier: state.licenseTier,\n licenseDeviceId: state.licenseDeviceId,\n licenseStoredKey: state.licenseStoredKey,\n onLicenseKeyChange: (key: string) => state.handleLicenseKeyChange(key),\n onLicenseActivate: () => state.handleLicenseActivate(),\n onLicenseRemove: async () => { await state.handleLicenseRemove(); state.licenseRemoveConfirm = false; },\n licenseRemoveConfirm: state.licenseRemoveConfirm,\n onLicenseRemoveConfirm: () => { state.licenseRemoveConfirm = true; },\n onLicenseRemoveCancel: () => { state.licenseRemoveConfirm = false; },\n // Auth state\n authConnected: state.authConnected,\n authBusy: state.authBusy,\n authMessage: state.authMessage,\n authUrl: state.authUrl,\n authCodeInput: state.authCodeInput,\n authExpiresIn: state.authExpiresIn,\n authRefreshToken: state.authRefreshToken,\n claudeAuthModalOpen: state.claudeAuthModalOpen,\n authRefreshTokenInput: state.authRefreshTokenInput,\n authRefreshTokenBusy: state.authRefreshTokenBusy,\n authRefreshTokenError: state.authRefreshTokenError,\n onClaudeAuthModalOpen: () => state.handleClaudeAuthModalOpen(),\n onClaudeAuthModalClose: () => state.handleClaudeAuthModalClose(),\n onRefreshTokenInputChange: (v: string) => { state.authRefreshTokenInput = v; },\n onImportRefreshToken: () => state.handleImportRefreshToken(),\n // WhatsApp login flow state\n whatsappBusy: state.whatsappBusy,\n whatsappLoginMessage: state.whatsappLoginMessage,\n whatsappLoginQrDataUrl: state.whatsappLoginQrDataUrl,\n whatsappLoginConnected: state.whatsappLoginConnected,\n // Real WhatsApp channel status\n whatsappChannelStatus,\n // Multi-account WhatsApp\n whatsappAccounts,\n whatsappActiveQrAccountId: state.whatsappActiveQrAccountId,\n whatsappAccountSaving: state.whatsappAccountSaving,\n // Gateway status\n gatewayHealthy: state.gatewayHealthy,\n gatewayHealthLoading: state.gatewayHealthLoading,\n gatewayHealthMessage: state.gatewayHealthMessage,\n gatewayRestartBusy: state.gatewayRestartBusy,\n // Software update\n updateAvailable: state.updateAvailable,\n currentVersion: state.currentVersion,\n latestVersion: state.latestVersion,\n updateChecking: state.updateChecking,\n updateRunning: state.updateRunning,\n updateMessage: state.updateMessage,\n updateProgressSteps: state.updateProgressSteps,\n updateLastResult: state.updateLastResult,\n onUpdateCheck: () => state.handleUpdateCheck(),\n onUpdateRun: () => state.handleUpdateRun(),\n onUpdateDismissResult: () => state.handleUpdateDismissResult(),\n // Uninstall\n uninstallConfirm: state.uninstallConfirm,\n uninstallBusy: state.uninstallBusy,\n uninstallDone: state.uninstallDone,\n uninstallError: state.uninstallError,\n uninstallConfirmText: state.uninstallConfirmText,\n onUninstallConfirm: () => state.handleUninstallConfirm(),\n onUninstallCancel: () => state.handleUninstallCancel(),\n onUninstallConfirmTextChange: (text: string) => state.handleUninstallConfirmTextChange(text),\n onUninstallRun: () => state.handleUninstallRun(),\n onUninstallDismiss: () => state.handleUninstallDismiss(),\n // Callbacks\n onStartAuth: () => state.handleAuthStart(),\n onSubmitAuthCode: (code: string) => state.handleAuthSubmitCode(code),\n onAuthCodeChange: (code: string) => state.handleAuthCodeChange(code),\n onWhatsAppRelink: async (accountId?: string) => {\n await state.handleWhatsAppStart(true, accountId);\n // Automatically wait for scan after showing QR\n if (state.whatsappLoginQrDataUrl) {\n await state.handleWhatsAppWait(accountId);\n // Refresh status after connection completes\n await loadChannels(state, true);\n state.requestUpdate();\n }\n },\n onWhatsAppUnlink: async (accountId?: string) => {\n await state.handleWhatsAppLogout(accountId);\n },\n onWhatsAppReset: async (accountId?: string) => {\n // Logout first to clear all state, then start fresh\n await state.handleWhatsAppLogout(accountId);\n await state.handleWhatsAppStart(true, accountId);\n // Automatically wait for scan after showing QR\n if (state.whatsappLoginQrDataUrl) {\n await state.handleWhatsAppWait(accountId);\n // Refresh status after connection completes\n await loadChannels(state, true);\n state.requestUpdate();\n }\n },\n onRefreshStatus: async () => {\n await loadChannels(state, true);\n await state.handleGatewayHealthCheck();\n },\n onRefreshGatewayStatus: () => state.handleGatewayHealthCheck(),\n onRefreshWhatsAppStatus: () => loadChannels(state, true),\n onWhatsAppBack: () => {\n // Clear the QR code to go back to status dashboard\n state.whatsappLoginQrDataUrl = null;\n state.whatsappLoginMessage = null;\n state.whatsappLoginConnected = null;\n state.whatsappActiveQrAccountId = null;\n state.requestUpdate();\n loadChannels(state, true);\n },\n onRestartGateway: () => state.handleGatewayRestart(),\n onRemoveWhatsAppAccount: (accountId) => state.handleRemoveWhatsAppAccount(accountId),\n // Workspaces\n workspaces: state.workspaces,\n workspacesLoading: state.workspacesLoading,\n workspacesError: state.workspacesError,\n addingWorkspace: state.addingWorkspace,\n newWorkspaceName: state.newWorkspaceName,\n newWorkspacePath: state.newWorkspacePath,\n workspaceSaving: state.workspaceSaving,\n workspaceRemoveConfirm: state.workspaceRemoveConfirm,\n newWorkspacePin: state.newWorkspacePin,\n onSetNewWorkspacePin: (pin: string) => { state.newWorkspacePin = pin; },\n onWorkspaceCreate: async (name, workspacePath) => {\n const pin = state.newWorkspacePin;\n await state.handleWorkspaceCreate(name, workspacePath);\n // Set the account PIN after workspace creation\n if (pin.match(/^\\d{4,6}$/)) {\n await setAccountPin(state, name, pin);\n state.newWorkspacePin = \"\";\n }\n },\n onWorkspaceRemove: (name) => state.handleWorkspaceRemove(name),\n onSetAddingWorkspace: (adding) => { state.addingWorkspace = adding; },\n onSetNewWorkspaceName: (name) => { state.newWorkspaceName = name; },\n onSetNewWorkspacePath: (path) => { state.newWorkspacePath = path; },\n onSetWorkspaceRemoveConfirm: (name) => { state.workspaceRemoveConfirm = name; },\n // Workspace rename\n renamingWorkspace: state.renamingWorkspace,\n renameWorkspaceName: state.renameWorkspaceName,\n onWorkspaceRenameStart: () => state.handleWorkspaceRenameStart(),\n onWorkspaceRenameCancel: () => state.handleWorkspaceRenameCancel(),\n onWorkspaceRename: (name: string, displayName: string) => state.handleWorkspaceRename(name, displayName),\n // WhatsApp DM policy — read from the selected workspace's account\n whatsappDmPolicy: (() => {\n const ws = getSelectedWorkspaceInfo(state);\n const id = ws?.whatsappAccountId;\n const acct = id ? whatsappAccounts.find((a) => a.accountId === id) : whatsappAccounts[0];\n return acct?.dmPolicy ?? null;\n })(),\n onWhatsAppDmToggle: async () => {\n const ws = getSelectedWorkspaceInfo(state);\n const id = ws?.whatsappAccountId;\n const account = id ? whatsappAccounts.find((a) => a.accountId === id) : whatsappAccounts[0];\n if (!account) return;\n const isEnabled = account.dmPolicy != null && account.dmPolicy !== \"disabled\";\n const newPolicy = isEnabled ? \"disabled\" : \"open\";\n // \"open\" requires allowFrom: [\"*\"] per schema validation\n const policyFields = newPolicy === \"open\"\n ? { dmPolicy: newPolicy, allowFrom: [\"*\"] }\n : { dmPolicy: newPolicy };\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const wa = (cfg?.channels as Record<string, unknown>)?.whatsapp as Record<string, unknown> | undefined;\n const accts = (wa?.accounts ?? {}) as Record<string, Record<string, unknown>>;\n // Write to per-account path if it exists, otherwise root\n const patch = accts[account.accountId]\n ? { channels: { whatsapp: { accounts: { [account.accountId]: policyFields } } } }\n : { channels: { whatsapp: policyFields } };\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify(patch),\n baseHash: snapshot.hash,\n note: `WhatsApp DM policy → ${newPolicy}`,\n skipRestart: true,\n });\n // Refresh channel status to pick up the new dmPolicy\n await loadChannels(state, false);\n } catch (err) {\n console.error(\"DM toggle failed:\", err);\n }\n },\n // WhatsApp group chat — read from config snapshot\n whatsappGroupPolicy: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const wa = (config?.channels as Record<string, unknown>)?.whatsapp as Record<string, unknown> | undefined;\n const ws = getSelectedWorkspaceInfo(state);\n const accountId = ws?.whatsappAccountId;\n const accts = (wa?.accounts ?? {}) as Record<string, Record<string, unknown>>;\n const acctCfg = accountId ? accts[accountId] : undefined;\n const policy = (acctCfg?.groupPolicy ?? wa?.groupPolicy ?? \"allowlist\") as string;\n return policy as \"open\" | \"disabled\" | \"allowlist\";\n })(),\n whatsappGroupRequireMention: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const wa = (config?.channels as Record<string, unknown>)?.whatsapp as Record<string, unknown> | undefined;\n const ws = getSelectedWorkspaceInfo(state);\n const accountId = ws?.whatsappAccountId;\n const accts = (wa?.accounts ?? {}) as Record<string, Record<string, unknown>>;\n const acctCfg = accountId ? accts[accountId] : undefined;\n const groups = (acctCfg?.groups ?? wa?.groups ?? {}) as Record<string, Record<string, unknown>>;\n const wildcard = groups[\"*\"];\n return wildcard?.requireMention !== false;\n })(),\n onWhatsAppGroupToggle: async () => {\n const ws = getSelectedWorkspaceInfo(state);\n const accountId = ws?.whatsappAccountId;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const wa = ((cfg?.channels as Record<string, unknown>)?.whatsapp ?? {}) as Record<string, unknown>;\n const accts = (wa.accounts ?? {}) as Record<string, Record<string, unknown>>;\n const acctCfg = accountId ? accts[accountId] : undefined;\n const currentPolicy = (acctCfg?.groupPolicy ?? wa.groupPolicy ?? \"allowlist\") as string;\n const enabling = currentPolicy === \"disabled\" || currentPolicy === \"allowlist\";\n const newPolicy = enabling ? \"open\" : \"disabled\";\n // When enabling, ensure wildcard groups entry exists so all groups are allowed\n const groupsPatch = enabling ? { \"*\": {} } : undefined;\n const policyFields: Record<string, unknown> = { groupPolicy: newPolicy };\n if (groupsPatch) policyFields.groups = groupsPatch;\n const patch = acctCfg\n ? { channels: { whatsapp: { accounts: { [accountId!]: policyFields } } } }\n : { channels: { whatsapp: policyFields } };\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify(patch),\n baseHash: snapshot.hash,\n note: `WhatsApp groups → ${newPolicy}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Group toggle failed:\", err);\n }\n },\n onWhatsAppGroupMentionChange: async (requireMention: boolean) => {\n const ws = getSelectedWorkspaceInfo(state);\n const accountId = ws?.whatsappAccountId;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const wa = ((cfg?.channels as Record<string, unknown>)?.whatsapp ?? {}) as Record<string, unknown>;\n const accts = (wa.accounts ?? {}) as Record<string, Record<string, unknown>>;\n const acctCfg = accountId ? accts[accountId] : undefined;\n const groupsField = { \"*\": { requireMention } };\n const patch = acctCfg\n ? { channels: { whatsapp: { accounts: { [accountId!]: { groups: groupsField } } } } }\n : { channels: { whatsapp: { groups: groupsField } } };\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify(patch),\n baseHash: snapshot.hash,\n note: `WhatsApp group mention → ${requireMention ? \"when mentioned\" : \"always\"}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Group mention change failed:\", err);\n }\n },\n // WhatsApp settings modal\n whatsappSettingsOpen: state.whatsappSettingsOpen ?? false,\n onWhatsAppSettingsOpen: () => { state.whatsappSettingsOpen = true; },\n onWhatsAppSettingsClose: () => { state.whatsappSettingsOpen = false; },\n // iMessage state\n imessageConfigured: imsg.configured,\n imessageRunning: imsg.running,\n imessageConnected: imsg.connected,\n imessageLastError: imsg.lastError,\n imessageSelfChatMode: imsg.selfChatMode,\n imessageCliPath: imsg.cliPath,\n imessageEnabling: state.imessageEnabling,\n imessageEnableConfirm: state.imessageEnableConfirm,\n imessageOwnerWorkspace,\n onIMessageEnable: () => { state.imessageEnableConfirm = true; },\n onIMessageEnableConfirm: async () => {\n state.imessageEnabling = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const config = snapshot.config as Record<string, unknown> | null;\n const existingBindings = (config?.bindings ?? []) as Array<{\n agentId: string;\n match: { channel?: string; peer?: { kind: string; id: string }; accountId?: string };\n meta?: Record<string, unknown>;\n }>;\n\n // Resolve the selected workspace's agent IDs\n const ws = getSelectedWorkspaceInfo(state);\n const adminAgent = ws?.agents.find((a) => a.id.endsWith(\"-admin\") || a.id === \"admin\");\n const adminAgentId = adminAgent?.id ?? \"admin\";\n\n // Strip ALL existing iMessage bindings (only one business owns iMessage)\n const nonImessageBindings = existingBindings.filter(\n (b) => b.match?.channel !== \"imessage\",\n );\n\n // Create iMessage binding: self-chat → admin agent only.\n // No public agent binding — iMessage is self-chat only, no third-party DMs.\n const imessageBindings = [\n {\n agentId: adminAgentId,\n match: { channel: \"imessage\", peer: { kind: \"dm\", id: \"__self__\" } },\n meta: { imessageOwner: true },\n },\n ];\n\n const updatedBindings = [...nonImessageBindings, ...imessageBindings];\n\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({\n channels: {\n imessage: {\n selfChatMode: true,\n dmPolicy: \"disabled\",\n allowFrom: [\"*\"],\n },\n },\n bindings: updatedBindings,\n }),\n baseHash: snapshot.hash,\n note: \"Enable iMessage (self-chat) for \" + (ws?.name ?? \"default\"),\n });\n state.imessageEnableConfirm = false;\n // Gateway will restart after config.patch; wait then refresh\n setTimeout(() => {\n void Promise.all([loadChannels(state, true), loadConfig(state)]).then(() => {\n state.imessageEnabling = false;\n });\n }, 3000);\n } catch {\n state.imessageEnabling = false;\n }\n },\n onIMessageEnableCancel: () => { state.imessageEnableConfirm = false; },\n onIMessageProbe: async () => {\n state.imessageEnabling = true;\n state.requestUpdate();\n try {\n await loadChannels(state, true);\n } finally {\n state.imessageEnabling = false;\n }\n },\n onIMessageDisconnect: async () => {\n state.imessageEnabling = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const config = snapshot.config as Record<string, unknown> | null;\n const existingBindings = (config?.bindings ?? []) as Array<{\n agentId: string;\n match: { channel?: string; peer?: { kind: string; id: string }; accountId?: string };\n meta?: Record<string, unknown>;\n }>;\n // Remove all iMessage bindings\n const nonImessageBindings = existingBindings.filter(\n (b) => b.match?.channel !== \"imessage\",\n );\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({\n channels: {\n imessage: {\n selfChatMode: false,\n dmPolicy: \"disabled\",\n },\n },\n bindings: nonImessageBindings,\n }),\n baseHash: snapshot.hash,\n note: \"Disconnect iMessage\",\n });\n state.imessageEnableConfirm = false;\n setTimeout(() => {\n void Promise.all([loadChannels(state, true), loadConfig(state)]).then(() => {\n state.imessageEnabling = false;\n });\n }, 3000);\n } catch {\n state.imessageEnabling = false;\n }\n },\n onIMessageReassign: async () => {\n // Same as enable but explicitly for reassigning to current workspace\n state.imessageEnabling = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const config = snapshot.config as Record<string, unknown> | null;\n const existingBindings = (config?.bindings ?? []) as Array<{\n agentId: string;\n match: { channel?: string; peer?: { kind: string; id: string }; accountId?: string };\n meta?: Record<string, unknown>;\n }>;\n const ws = getSelectedWorkspaceInfo(state);\n const adminAgent = ws?.agents.find((a) => a.id.endsWith(\"-admin\") || a.id === \"admin\");\n const adminAgentId = adminAgent?.id ?? \"admin\";\n const nonImessageBindings = existingBindings.filter(\n (b) => b.match?.channel !== \"imessage\",\n );\n const imessageBindings = [\n {\n agentId: adminAgentId,\n match: { channel: \"imessage\", peer: { kind: \"dm\", id: \"__self__\" } },\n meta: { imessageOwner: true },\n },\n ];\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({\n channels: {\n imessage: {\n selfChatMode: true,\n dmPolicy: \"disabled\",\n allowFrom: [\"*\"],\n },\n },\n bindings: [...nonImessageBindings, ...imessageBindings],\n }),\n baseHash: snapshot.hash,\n note: \"Reassign iMessage to \" + (ws?.name ?? \"default\"),\n });\n state.imessageEnableConfirm = false;\n setTimeout(() => {\n void Promise.all([loadChannels(state, true), loadConfig(state)]).then(() => {\n state.imessageEnabling = false;\n });\n }, 3000);\n } catch {\n state.imessageEnabling = false;\n }\n },\n // Info modals\n infoModalOpen: state.infoModalOpen,\n onInfoModalOpen: (id: string) => {\n state.infoModalOpen = id;\n if (id === \"remote-access\") {\n const url = state.tailscaleStatus?.tailnetUrl ?? (state.tailscaleStatus?.hostname ? `https://${state.tailscaleStatus.hostname}` : null);\n if (url && !state.remoteAccessQrDataUrl) {\n state.client!.request<{ dataUrl: string }>(\"qr.generate\", { url }).then((res) => {\n state.remoteAccessQrDataUrl = res?.dataUrl ?? null;\n }).catch(() => {});\n }\n } else if (id === \"public-chat\") {\n const baseUrl = state.tailscaleStatus?.publicUrl ?? state.tailscaleStatus?.tailnetUrl ?? null;\n const accountId = state.selectedWorkspace ?? null;\n if (baseUrl && accountId) {\n const fullUrl = `${baseUrl}/public/chat/${encodeURIComponent(accountId)}`;\n if (!state.publicChatQrDataUrl) {\n state.client!.request<{ dataUrl: string }>(\"qr.generate\", { url: fullUrl }).then((res) => {\n state.publicChatQrDataUrl = res?.dataUrl ?? null;\n }).catch(() => {});\n }\n }\n }\n },\n onInfoModalClose: () => { state.infoModalOpen = null; },\n remoteAccessQrDataUrl: state.remoteAccessQrDataUrl ?? null,\n publicChatQrDataUrl: state.publicChatQrDataUrl ?? null,\n publicChatFullUrl: (() => {\n const baseUrl = state.tailscaleStatus?.publicUrl ?? state.tailscaleStatus?.tailnetUrl ?? null;\n const accountId = state.selectedWorkspace ?? null;\n if (!baseUrl || !accountId) return null;\n return `${baseUrl}/public/chat/${encodeURIComponent(accountId)}`;\n })(),\n // API Keys management (global, admin-only)\n isMaster: state.accessState.master,\n apiKeyProviders: state.apiKeyProviders,\n apiKeyModalOpen: state.apiKeyModalOpen,\n apiKeyBusy: state.apiKeyBusy,\n apiKeyError: state.apiKeyError,\n apiKeySuccess: state.apiKeySuccess,\n apiKeySavingProvider: state.apiKeySavingProvider,\n onApiKeyModalOpen: () => { state.apiKeyModalOpen = true; state.apiKeyError = null; state.apiKeySuccess = null; state.apiKeySavingProvider = null; },\n onApiKeyModalClose: () => { state.apiKeyModalOpen = false; state.apiKeyError = null; state.apiKeySuccess = null; state.apiKeySavingProvider = null; },\n onApiKeySave: async (provider: string, apiKey: string) => {\n state.apiKeySavingProvider = provider;\n state.apiKeyBusy = true;\n state.apiKeyError = null;\n state.apiKeySuccess = null;\n try {\n await saveApiKey(state.client!, provider, apiKey);\n const successMsg = `${provider} key saved`;\n state.apiKeySuccess = successMsg;\n state.apiKeySavingProvider = null;\n try { state.apiKeyProviders = await loadApiKeys(state.client!); } catch { /* ignore */ }\n if (provider === \"anthropic\") {\n await state.handleAuthStatusCheck();\n }\n setTimeout(() => { if (state.apiKeySuccess === successMsg) state.apiKeySuccess = null; }, 2500);\n } catch (err) {\n state.apiKeyError = err instanceof Error ? err.message : \"Failed to save key\";\n state.apiKeySavingProvider = null;\n } finally {\n state.apiKeyBusy = false;\n }\n },\n onApiKeyRemove: async (provider: string) => {\n state.apiKeySavingProvider = provider;\n state.apiKeyBusy = true;\n state.apiKeyError = null;\n state.apiKeySuccess = null;\n try {\n await removeApiKey(state.client!, provider);\n const successMsg = `${provider} key removed`;\n state.apiKeySuccess = successMsg;\n state.apiKeySavingProvider = null;\n try { state.apiKeyProviders = await loadApiKeys(state.client!); } catch { /* ignore */ }\n setTimeout(() => { if (state.apiKeySuccess === successMsg) state.apiKeySuccess = null; }, 2500);\n } catch (err) {\n state.apiKeyError = err instanceof Error ? err.message : \"Failed to remove key\";\n state.apiKeySavingProvider = null;\n } finally {\n state.apiKeyBusy = false;\n }\n },\n onApiKeyDisable: async (provider: string, disabled: boolean) => {\n state.apiKeySavingProvider = provider;\n state.apiKeyBusy = true;\n state.apiKeyError = null;\n state.apiKeySuccess = null;\n try {\n await disableApiKey(state.client!, provider, disabled);\n const successMsg = `${provider} ${disabled ? \"disabled\" : \"enabled\"}`;\n state.apiKeySuccess = successMsg;\n state.apiKeySavingProvider = null;\n try { state.apiKeyProviders = await loadApiKeys(state.client!); } catch { /* ignore */ }\n setTimeout(() => { if (state.apiKeySuccess === successMsg) state.apiKeySuccess = null; }, 2500);\n } catch (err) {\n state.apiKeyError = err instanceof Error ? err.message : `Failed to ${disabled ? \"disable\" : \"enable\"} key`;\n state.apiKeySavingProvider = null;\n } finally {\n state.apiKeyBusy = false;\n }\n },\n // Auth step API key fallback\n authApiKeyMode: state.authApiKeyMode,\n authApiKeyInput: state.authApiKeyInput,\n authApiKeyBusy: state.authApiKeyBusy,\n authApiKeyError: state.authApiKeyError,\n onAuthApiKeyToggle: () => { state.authApiKeyMode = !state.authApiKeyMode; state.authApiKeyError = null; },\n onAuthApiKeyChange: (key: string) => { state.authApiKeyInput = key; },\n onAuthApiKeySubmit: async () => {\n const key = state.authApiKeyInput.trim();\n if (!key) return;\n state.authApiKeyBusy = true;\n state.authApiKeyError = null;\n try {\n await saveApiKey(state.client!, \"anthropic\", key);\n await state.handleAuthStatusCheck();\n state.authApiKeyMode = false;\n state.authApiKeyInput = \"\";\n } catch (err) {\n state.authApiKeyError = err instanceof Error ? err.message : \"Failed to save API key\";\n } finally {\n state.authApiKeyBusy = false;\n }\n },\n // Account PIN management\n accountHasPin: (() => {\n const ws = state.selectedWorkspace ?? state.workspaces[0]?.name;\n return ws ? state.accessState.accounts.some((a) => a.id === ws) : false;\n })(),\n accountPinModalOpen: state.accountPinModalOpen,\n accountPinBusy: state.accountPinBusy,\n accountPinError: state.accountPinError,\n accountPinSuccess: state.accountPinSuccess,\n onAccountPinModalOpen: () => { state.accountPinModalOpen = true; state.accountPinError = null; state.accountPinSuccess = null; },\n onAccountPinModalClose: () => { state.accountPinModalOpen = false; state.accountPinError = null; state.accountPinSuccess = null; },\n onAccountPinSave: (oldPin: string | null, newPin: string) => {\n const ws = state.selectedWorkspace ?? state.workspaces[0]?.name;\n if (ws) state.handleAccountPinSave(ws, oldPin, newPin);\n },\n // Public Chat settings modal + widget snippet\n publicChatAccountId: state.selectedWorkspace ?? null,\n publicChatSettingsOpen: state.publicChatSettingsOpen,\n onPublicChatSettingsOpen: () => { state.publicChatSettingsOpen = true; },\n onPublicChatSettingsClose: () => { state.publicChatSettingsOpen = false; },\n publicChatWidgetModalOpen: state.publicChatWidgetModalOpen,\n onPublicChatWidgetModalOpen: () => { state.publicChatWidgetModalOpen = true; },\n onPublicChatWidgetModalClose: () => { state.publicChatWidgetModalOpen = false; },\n publicChatEnabled: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const pc = config?.publicChat as Record<string, unknown> | undefined;\n return pc?.enabled === true;\n })(),\n publicChatAuthMode: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const pc = config?.publicChat as Record<string, unknown> | undefined;\n const ws = state.selectedWorkspace ?? \"\";\n const accountSettings = pc?.accountSettings as Record<string, Record<string, unknown>> | undefined;\n const mode = (accountSettings?.[ws]?.auth ?? pc?.auth) as string | undefined;\n return (mode === \"verified\" || mode === \"choice\") ? mode : \"anonymous\";\n })(),\n publicChatGreeting: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const pc = config?.publicChat as Record<string, unknown> | undefined;\n const greetings = pc?.greetings as Record<string, string> | undefined;\n const ws = state.selectedWorkspace ?? \"\";\n return (ws && greetings?.[ws]) ?? \"\";\n })(),\n publicChatGreetingBusy: state.publicChatGreetingBusy,\n onPublicChatGreetingToggle: async () => {\n if (state.publicChatGreetingBusy) return;\n const ws = state.selectedWorkspace ?? \"\";\n if (!ws) return;\n state.publicChatGreetingBusy = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const greetings = (cfg?.publicChat as Record<string, unknown>)?.greetings as Record<string, string> | undefined;\n const current = greetings?.[ws];\n if (current) {\n // Disable greeting for this account — set to null to remove\n const patch = { publicChat: { greetings: { [ws]: null } } };\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify(patch),\n baseHash: snapshot.hash,\n note: `Public chat greeting → disabled (${ws})`,\n skipRestart: true,\n });\n } else {\n // Generate greeting via LLM then save to config\n const result = await state.client!.request(\"public.greeting.generate\", { accountId: ws }) as { ok?: boolean; greeting?: string };\n if (result?.ok && result.greeting) {\n const freshSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ publicChat: { greetings: { [ws]: result.greeting } } }),\n baseHash: freshSnapshot.hash,\n note: `Public chat greeting → enabled (${ws})`,\n skipRestart: true,\n });\n }\n }\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Public chat greeting toggle failed:\", err);\n } finally {\n state.publicChatGreetingBusy = false;\n }\n },\n onPublicChatGreetingSave: async (text: string) => {\n const ws = state.selectedWorkspace ?? \"\";\n if (!ws) return;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ publicChat: { greetings: { [ws]: text } } }),\n baseHash: snapshot.hash,\n note: `Public chat greeting text updated (${ws})`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Public chat greeting save failed:\", err);\n }\n },\n onPublicChatGreetingRegenerate: async () => {\n if (state.publicChatGreetingBusy) return;\n const ws = state.selectedWorkspace ?? \"\";\n if (!ws) return;\n state.publicChatGreetingBusy = true;\n try {\n const result = await state.client!.request(\"public.greeting.generate\", { accountId: ws }) as { ok?: boolean; greeting?: string };\n if (result?.ok && result.greeting) {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ publicChat: { greetings: { [ws]: result.greeting } } }),\n baseHash: snapshot.hash,\n note: `Public chat greeting regenerated (${ws})`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n }\n } catch (err) {\n console.error(\"Public chat greeting regeneration failed:\", err);\n } finally {\n state.publicChatGreetingBusy = false;\n }\n },\n publicChatBusy: state.publicChatToggleBusy,\n onPublicChatToggle: async () => {\n if (state.publicChatToggleBusy) return;\n state.publicChatToggleBusy = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const current = (cfg?.publicChat as Record<string, unknown>)?.enabled === true;\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ publicChat: { enabled: !current } }),\n baseHash: snapshot.hash,\n note: `Public chat → ${!current ? \"enabled\" : \"disabled\"}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n state.publicChatQrDataUrl = null;\n } catch (err) {\n console.error(\"Public chat toggle failed:\", err);\n } finally {\n state.publicChatToggleBusy = false;\n }\n },\n onPublicChatAuthModeChange: async (mode: \"anonymous\" | \"verified\" | \"choice\") => {\n if (state.publicChatToggleBusy) return;\n const ws = state.selectedWorkspace ?? \"\";\n if (!ws) return;\n state.publicChatToggleBusy = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ publicChat: { accountSettings: { [ws]: { auth: mode } } } }),\n baseHash: snapshot.hash,\n note: `Public chat auth → ${mode}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Public chat auth mode change failed:\", err);\n } finally {\n state.publicChatToggleBusy = false;\n }\n },\n // Public Chat email verification — from address + verify methods\n publicChatEmailFrom: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const email = (config?.publicChat as Record<string, unknown> | undefined)?.email as Record<string, unknown> | undefined;\n return (email?.from as string) ?? \"\";\n })(),\n publicChatEmailBusy: state.publicChatEmailBusy,\n publicChatVerifyMethods: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const pc = config?.publicChat as Record<string, unknown> | undefined;\n const ws = state.selectedWorkspace ?? \"\";\n const accountSettings = pc?.accountSettings as Record<string, Record<string, unknown>> | undefined;\n const methods = (accountSettings?.[ws]?.verifyMethods ?? pc?.verifyMethods) as string[] | undefined;\n return Array.isArray(methods) ? methods : [\"whatsapp\", \"sms\"];\n })(),\n onPublicChatEmailSave: async (fromAddr: string, verifyMethods: string[]) => {\n if (state.publicChatEmailBusy) return;\n const ws = state.selectedWorkspace ?? \"\";\n if (!ws) return;\n state.publicChatEmailBusy = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({\n publicChat: {\n email: {\n from: fromAddr || undefined,\n },\n accountSettings: { [ws]: { verifyMethods } },\n },\n }),\n baseHash: snapshot.hash,\n note: \"Update email verification settings for public chat\",\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Email verification save failed:\", err);\n } finally {\n state.publicChatEmailBusy = false;\n }\n },\n // Branding (per-workspace)\n brandAccentColor: (() => {\n const ws = state.selectedWorkspace;\n if (!ws) return \"\";\n const brands = getWorkspaceBrands();\n return brands[ws]?.accentColor ?? \"\";\n })(),\n brandBackgroundColor: (() => {\n const ws = state.selectedWorkspace;\n if (!ws) return \"\";\n const brands = getWorkspaceBrands();\n return brands[ws]?.backgroundColor ?? \"\";\n })(),\n brandHasLogo: (() => {\n const ws = state.selectedWorkspace;\n if (!ws) return false;\n const brands = getWorkspaceBrands();\n return Boolean(brands[ws]?.logoUrl);\n })(),\n // Agent Settings — per-agent model + thinking\n agentSettingsOpen: (state as unknown as { agentSettingsOpen: boolean }).agentSettingsOpen,\n agentSettingsAgents: (() => {\n const ws = getSelectedWorkspaceInfo(state);\n if (!ws) return [];\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const agentsList = (config?.agents as Record<string, unknown>)?.list as\n | Array<{ id: string; name?: string; model?: string | { primary?: string }; thinkingLevel?: string }>\n | undefined;\n return ws.agents.map((a) => {\n const cfgEntry = Array.isArray(agentsList) ? agentsList.find((c) => c.id === a.id) : undefined;\n const modelRaw = cfgEntry?.model;\n const model = typeof modelRaw === \"string\" ? modelRaw : (modelRaw as { primary?: string })?.primary ?? null;\n const isAdmin = a.id.endsWith(\"-admin\") || a.id === \"admin\";\n return {\n id: a.id,\n label: isAdmin ? \"Admin\" : \"Public\",\n model: model?.trim() || null,\n thinkingLevel: cfgEntry?.thinkingLevel?.trim() || null,\n };\n });\n })(),\n agentSettingsModelCatalog: (state as unknown as { chatModelCatalog: Array<{ id: string; name: string; provider: string; reasoning?: boolean }> }).chatModelCatalog ?? [],\n memoryProvider: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const memSearch = ((config?.agents as Record<string, unknown>)?.defaults as Record<string, unknown>)?.memorySearch as Record<string, unknown> | undefined;\n return (typeof memSearch?.provider === \"string\" && memSearch.provider) ? memSearch.provider : \"local\";\n })(),\n memoryFallback: (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const memSearch = ((config?.agents as Record<string, unknown>)?.defaults as Record<string, unknown>)?.memorySearch as Record<string, unknown> | undefined;\n return (typeof memSearch?.fallback === \"string\" && memSearch.fallback) ? memSearch.fallback : \"none\";\n })(),\n onAgentSettingsToggle: () => {\n (state as unknown as { agentSettingsOpen: boolean }).agentSettingsOpen =\n !(state as unknown as { agentSettingsOpen: boolean }).agentSettingsOpen;\n },\n onAgentModelChange: async (agentId: string, modelRef: string) => {\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const agents = (cfg?.agents ?? {}) as Record<string, unknown>;\n const list = (Array.isArray(agents.list) ? [...agents.list] : []) as Array<Record<string, unknown>>;\n\n const idx = list.findIndex((a) => a.id === agentId);\n if (modelRef) {\n if (idx >= 0) {\n list[idx] = { ...list[idx], model: modelRef };\n } else {\n list.push({ id: agentId, model: modelRef });\n }\n } else {\n if (idx >= 0) {\n const { model: _, ...rest } = list[idx];\n if (Object.keys(rest).length <= 1) list.splice(idx, 1);\n else list[idx] = rest;\n }\n }\n\n const patch = list.length > 0 ? { agents: { list } } : { agents: { list: null } };\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify(patch),\n baseHash: snapshot.hash,\n note: `Agent ${agentId} model → ${modelRef || \"default\"}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Agent model change failed:\", err);\n }\n },\n onAgentThinkingChange: async (agentId: string, level: string) => {\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const agents = (cfg?.agents ?? {}) as Record<string, unknown>;\n const list = (Array.isArray(agents.list) ? [...agents.list] : []) as Array<Record<string, unknown>>;\n\n const idx = list.findIndex((a) => a.id === agentId);\n const effectiveLevel = level === \"off\" ? undefined : level;\n if (effectiveLevel) {\n if (idx >= 0) {\n list[idx] = { ...list[idx], thinkingLevel: effectiveLevel };\n } else {\n list.push({ id: agentId, thinkingLevel: effectiveLevel });\n }\n } else {\n if (idx >= 0) {\n const { thinkingLevel: _, ...rest } = list[idx];\n if (Object.keys(rest).length <= 1) list.splice(idx, 1);\n else list[idx] = rest;\n }\n }\n\n const patch = list.length > 0 ? { agents: { list } } : { agents: { list: null } };\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify(patch),\n baseHash: snapshot.hash,\n note: `Agent ${agentId} thinking → ${effectiveLevel || \"default\"}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Agent thinking change failed:\", err);\n }\n },\n onMemoryProviderChange: async (provider: string) => {\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ agents: { defaults: { memorySearch: { provider } } } }),\n baseHash: snapshot.hash,\n note: `Memory search provider → ${provider}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Memory provider change failed:\", err);\n }\n },\n onMemoryFallbackChange: async (fallback: string) => {\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ agents: { defaults: { memorySearch: { fallback } } } }),\n baseHash: snapshot.hash,\n note: `Memory search fallback → ${fallback}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n } catch (err) {\n console.error(\"Memory fallback change failed:\", err);\n }\n },\n brandingBusy: state.brandingBusy,\n brandingExpanded: state.brandingExpanded,\n onBrandingToggle: () => {\n state.brandingExpanded = !state.brandingExpanded;\n },\n onBrandAccentColorChange: async (color: string) => {\n const ws = state.selectedWorkspace;\n if (!ws || state.brandingBusy) return;\n state.brandingBusy = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const existing = ((cfg?.workspaces as Record<string, unknown>)?.[ws] as Record<string, unknown>) ?? {};\n const existingBrand = (existing.brand as Record<string, unknown>) ?? {};\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ workspaces: { [ws]: { ...existing, brand: { ...existingBrand, accentColor: color } } } }),\n baseHash: snapshot.hash,\n note: `Brand accent → ${color}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n // Update injected brands map so the UI reflects immediately\n const brands = getWorkspaceBrands();\n if (!brands[ws]) brands[ws] = {};\n brands[ws].accentColor = color;\n applyWorkspaceBrand(ws);\n } catch (err) {\n console.error(\"Brand accent change failed:\", err);\n } finally {\n state.brandingBusy = false;\n }\n },\n onBrandBackgroundColorChange: async (color: string) => {\n const ws = state.selectedWorkspace;\n if (!ws || state.brandingBusy) return;\n state.brandingBusy = true;\n try {\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const existing = ((cfg?.workspaces as Record<string, unknown>)?.[ws] as Record<string, unknown>) ?? {};\n const existingBrand = (existing.brand as Record<string, unknown>) ?? {};\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ workspaces: { [ws]: { ...existing, brand: { ...existingBrand, backgroundColor: color } } } }),\n baseHash: snapshot.hash,\n note: `Brand background → ${color}`,\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const brands = getWorkspaceBrands();\n if (!brands[ws]) brands[ws] = {};\n brands[ws].backgroundColor = color;\n applyWorkspaceBrand(ws);\n } catch (err) {\n console.error(\"Brand background change failed:\", err);\n } finally {\n state.brandingBusy = false;\n }\n },\n onBrandLogoUpload: async (file: File) => {\n const ws = state.selectedWorkspace;\n if (!ws || state.brandingBusy) return;\n state.brandingBusy = true;\n try {\n const buffer = await file.arrayBuffer();\n const bytes = new Uint8Array(buffer);\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n const base64 = btoa(binary);\n await state.client!.request(\"brand.uploadLogo\", {\n workspace: ws,\n data: base64,\n mimeType: file.type,\n });\n // Update injected brands map\n const brands = getWorkspaceBrands();\n if (!brands[ws]) brands[ws] = {};\n brands[ws].logoUrl = `/brand-logo/${encodeURIComponent(ws)}`;\n } catch (err) {\n console.error(\"Brand logo upload failed:\", err);\n } finally {\n state.brandingBusy = false;\n }\n },\n onBrandLogoRemove: async () => {\n const ws = state.selectedWorkspace;\n if (!ws || state.brandingBusy) return;\n state.brandingBusy = true;\n try {\n await state.client!.request(\"brand.removeLogo\", { workspace: ws });\n const brands = getWorkspaceBrands();\n if (brands[ws]) delete brands[ws].logoUrl;\n } catch (err) {\n console.error(\"Brand logo remove failed:\", err);\n } finally {\n state.brandingBusy = false;\n }\n },\n onBrandReset: async () => {\n const ws = state.selectedWorkspace;\n if (!ws || state.brandingBusy) return;\n state.brandingBusy = true;\n try {\n // Clear brand colours from config\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n const cfg = snapshot.config as Record<string, unknown>;\n const existing = ((cfg?.workspaces as Record<string, unknown>)?.[ws] as Record<string, unknown>) ?? {};\n const { brand: _removed, ...rest } = existing;\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify({ workspaces: { [ws]: { ...rest, brand: null } } }),\n baseHash: snapshot.hash,\n note: \"Brand reset to defaults\",\n skipRestart: true,\n });\n state.configSnapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n // Remove logo file\n try {\n await state.client!.request(\"brand.removeLogo\", { workspace: ws });\n } catch { /* ignore if no logo */ }\n // Clear injected brands\n const brands = getWorkspaceBrands();\n delete brands[ws];\n applyWorkspaceBrand(ws);\n } catch (err) {\n console.error(\"Brand reset failed:\", err);\n } finally {\n state.brandingBusy = false;\n }\n },\n // Tailscale / Remote Access (admin-only)\n tailscaleStatus: state.tailscaleStatus,\n tailscaleBusy: state.tailscaleBusy,\n tailscaleAuthUrl: state.tailscaleAuthUrl,\n tailscaleError: state.tailscaleError,\n tailscaleServeEnableUrl: state.tailscaleServeEnableUrl,\n tailscaleFunnelEnableUrl: state.tailscaleFunnelEnableUrl,\n tailscaleDisableConfirm: state.tailscaleDisableConfirm,\n tailscaleConnectProgress: state.tailscaleConnectProgress,\n tailscaleConnectMessage: state.tailscaleConnectMessage,\n tailscaleConnectSuccess: state.tailscaleConnectSuccess,\n onTailscaleEnable: async () => {\n if (state.tailscaleBusy) return;\n state.tailscaleBusy = true;\n state.tailscaleAuthUrl = null;\n startTailscaleProgress();\n try {\n const result = await state.client!.request<{ authUrl?: string; alreadyLoggedIn?: boolean }>(\"tailscale.enable\");\n if (result.authUrl) {\n // Auth phase — stop progress animation, jump to 100, show QR\n if (_tsProgressInterval) { clearInterval(_tsProgressInterval); _tsProgressInterval = null; }\n state.tailscaleConnectProgress = 100;\n state.tailscaleConnectMessage = \"Waiting for authentication...\";\n state.tailscaleAuthUrl = result.authUrl;\n // Poll tailscale.status every 3s until loggedIn\n _tsPollInterval = setInterval(async () => {\n try {\n const status = await state.client!.request<NonNullable<typeof state.tailscaleStatus>>(\"tailscale.status\");\n state.tailscaleStatus = status;\n state.remoteAccessQrDataUrl = null;\n state.publicChatQrDataUrl = null;\n if (status.loggedIn) {\n clearTailscaleTimers();\n // Success phase — brief message, then auto-close\n state.tailscaleAuthUrl = null;\n state.tailscaleConnectSuccess = true;\n state.tailscaleConnectMessage = \"Connected!\";\n setTimeout(() => {\n state.tailscaleConnectSuccess = false;\n state.tailscaleConnectProgress = 0;\n state.tailscaleConnectMessage = \"\";\n state.tailscaleBusy = false;\n }, 1500);\n }\n } catch {\n // keep polling\n }\n }, 3000);\n // Stop polling after 5 minutes\n _tsPollTimeout = setTimeout(() => {\n clearTailscaleTimers();\n if (state.tailscaleBusy) {\n state.tailscaleConnectProgress = 0;\n state.tailscaleConnectMessage = \"\";\n state.tailscaleBusy = false;\n }\n }, 300_000);\n } else if (result.alreadyLoggedIn) {\n clearTailscaleTimers();\n state.tailscaleStatus = await state.client!.request<NonNullable<typeof state.tailscaleStatus>>(\"tailscale.status\");\n state.remoteAccessQrDataUrl = null;\n state.publicChatQrDataUrl = null;\n state.tailscaleConnectProgress = 0;\n state.tailscaleConnectMessage = \"\";\n state.tailscaleBusy = false;\n } else {\n clearTailscaleTimers();\n state.tailscaleConnectProgress = 0;\n state.tailscaleConnectMessage = \"\";\n state.tailscaleBusy = false;\n }\n } catch (err) {\n console.error(\"Tailscale enable failed:\", err);\n clearTailscaleTimers();\n state.tailscaleError = (err as Error).message || \"Failed to enable Remote Access\";\n state.tailscaleConnectProgress = 0;\n state.tailscaleConnectMessage = \"\";\n state.tailscaleBusy = false;\n }\n },\n onTailscaleErrorDismiss: () => {\n state.tailscaleError = null;\n },\n onTailscaleServeEnable: async () => {\n if (state.tailscaleBusy) return;\n state.tailscaleBusy = true;\n state.tailscaleError = null;\n state.tailscaleServeEnableUrl = null;\n try {\n await state.client!.request(\"tailscale.serve.enable\");\n await refreshTailscaleStatus();\n } catch (err) {\n console.error(\"Tailscale serve enable failed:\", err);\n const rpcErr = err as Error & { payload?: { enableUrl?: string } };\n if (rpcErr.payload?.enableUrl) {\n state.tailscaleServeEnableUrl = rpcErr.payload.enableUrl;\n }\n state.tailscaleError = rpcErr.message || \"Failed to enable Remote Access\";\n } finally {\n state.tailscaleBusy = false;\n }\n },\n onTailscaleServeDisable: async () => {\n if (state.tailscaleBusy) return;\n state.tailscaleBusy = true;\n try {\n await state.client!.request(\"tailscale.serve.disable\");\n await refreshTailscaleStatus();\n } catch (err) {\n console.error(\"Tailscale serve disable failed:\", err);\n } finally {\n state.tailscaleBusy = false;\n }\n },\n onTailscaleFunnelEnable: async () => {\n if (state.tailscaleBusy) return;\n state.tailscaleBusy = true;\n state.tailscaleError = null;\n state.tailscaleFunnelEnableUrl = null;\n try {\n await state.client!.request(\"tailscale.funnel.enable\");\n await refreshTailscaleStatus();\n } catch (err) {\n console.error(\"Tailscale funnel enable failed:\", err);\n const rpcErr = err as Error & { payload?: { enableUrl?: string } };\n if (rpcErr.payload?.enableUrl) {\n state.tailscaleFunnelEnableUrl = rpcErr.payload.enableUrl;\n }\n state.tailscaleError = rpcErr.message || \"Failed to enable Funnel\";\n } finally {\n state.tailscaleBusy = false;\n }\n },\n onTailscaleFunnelDisable: async () => {\n if (state.tailscaleBusy) return;\n state.tailscaleBusy = true;\n try {\n await state.client!.request(\"tailscale.funnel.disable\");\n await refreshTailscaleStatus();\n } catch (err) {\n console.error(\"Tailscale funnel disable failed:\", err);\n } finally {\n state.tailscaleBusy = false;\n }\n },\n onTailscaleDisableConfirmToggle: () => {\n state.tailscaleDisableConfirm = !state.tailscaleDisableConfirm;\n },\n // WiFi management (Linux only, modal pattern)\n wifiModalOpen: state.wifiModalOpen,\n onWifiModalToggle: () => {\n state.wifiModalOpen = !state.wifiModalOpen;\n // Reset selection state when closing\n if (!state.wifiModalOpen) {\n state.wifiNetworks = [];\n state.wifiSelectedSsid = null;\n state.wifiPassword = \"\";\n state.wifiError = null;\n }\n },\n wifiStatus: state.wifiStatus,\n wifiNetworks: state.wifiNetworks,\n wifiBusy: state.wifiBusy,\n wifiError: state.wifiError,\n wifiPassword: state.wifiPassword,\n wifiSelectedSsid: state.wifiSelectedSsid,\n onWifiScan: async () => {\n if (state.wifiBusy) return;\n state.wifiBusy = true;\n state.wifiError = null;\n try {\n // Refresh both scan results and connection status\n const [scanResult, statusResult] = await Promise.all([\n state.client!.request<{ networks: NonNullable<typeof state.wifiNetworks> }>(\"wifi.scan\"),\n state.client!.request<NonNullable<typeof state.wifiStatus>>(\"wifi.status\"),\n ]);\n state.wifiNetworks = scanResult.networks;\n // wifi.status often returns null signal (stale nmcli cache) — fill from scan\n if (statusResult.connected && statusResult.signal == null && scanResult.networks?.length) {\n const match = scanResult.networks.find((n) => n.active)\n || scanResult.networks.find((n) => n.ssid === statusResult.ssid);\n if (match) statusResult.signal = match.signal;\n }\n state.wifiStatus = statusResult;\n } catch (err) {\n console.error(\"WiFi scan failed:\", err);\n state.wifiError = (err as Error).message || \"Failed to scan networks\";\n } finally {\n state.wifiBusy = false;\n }\n },\n onWifiConnect: async () => {\n if (state.wifiBusy || !state.wifiSelectedSsid) return;\n const connectingSsid = state.wifiSelectedSsid;\n state.wifiBusy = true;\n state.wifiError = null;\n try {\n const result = await state.client!.request<{ connected: boolean; ssid: string; ip: string | null }>(\"wifi.connect\", {\n ssid: connectingSsid,\n password: state.wifiPassword,\n });\n state.wifiPassword = \"\";\n state.wifiSelectedSsid = null;\n state.wifiNetworks = [];\n // Optimistically set connected state from response\n state.wifiStatus = {\n available: true,\n connected: result.connected,\n ssid: result.ssid,\n signal: null,\n ip: result.ip,\n savedSsid: result.ssid,\n autoconnect: true,\n };\n state.wifiBusy = false;\n // Refresh full status + scan in background for signal strength\n try {\n const [scanResult, status] = await Promise.all([\n state.client!.request<{ networks: NonNullable<typeof state.wifiNetworks> }>(\"wifi.scan\"),\n state.client!.request<NonNullable<typeof state.wifiStatus>>(\"wifi.status\"),\n ]);\n if (status.connected && status.signal == null && scanResult.networks?.length) {\n const match = scanResult.networks.find((n) => n.active)\n || scanResult.networks.find((n) => n.ssid === status.ssid);\n if (match) status.signal = match.signal;\n }\n state.wifiStatus = status;\n } catch { /* non-critical */ }\n } catch (err) {\n console.error(\"WiFi connect failed:\", err);\n state.wifiError = (err as Error).message || \"Failed to connect\";\n state.wifiBusy = false;\n }\n },\n onWifiDisconnect: async () => {\n if (state.wifiBusy) return;\n state.wifiBusy = true;\n state.wifiError = null;\n try {\n await state.client!.request(\"wifi.disconnect\");\n state.wifiNetworks = [];\n state.wifiSelectedSsid = null;\n state.wifiPassword = \"\";\n const status = await state.client!.request<NonNullable<typeof state.wifiStatus>>(\"wifi.status\");\n state.wifiStatus = status;\n } catch (err) {\n console.error(\"WiFi disconnect failed:\", err);\n state.wifiError = (err as Error).message || \"Failed to disconnect\";\n } finally {\n state.wifiBusy = false;\n }\n },\n onWifiForget: async () => {\n if (state.wifiBusy) return;\n state.wifiBusy = true;\n state.wifiError = null;\n try {\n await state.client!.request(\"wifi.forget\");\n state.wifiNetworks = [];\n state.wifiSelectedSsid = null;\n state.wifiPassword = \"\";\n const status = await state.client!.request<NonNullable<typeof state.wifiStatus>>(\"wifi.status\");\n state.wifiStatus = status;\n } catch (err) {\n console.error(\"WiFi forget failed:\", err);\n state.wifiError = (err as Error).message || \"Failed to forget network\";\n } finally {\n state.wifiBusy = false;\n }\n },\n onWifiDismiss: () => {\n state.wifiNetworks = [];\n state.wifiSelectedSsid = null;\n state.wifiPassword = \"\";\n state.wifiError = null;\n },\n onWifiSelectSsid: (ssid: string | null) => {\n state.wifiSelectedSsid = ssid;\n state.wifiPassword = \"\";\n state.wifiError = null;\n },\n onWifiPasswordChange: (password: string) => {\n state.wifiPassword = password;\n },\n // Network settings (port + hostname, modal pattern)\n networkPort: state.networkPort,\n networkHostname: state.networkHostname,\n networkPortInput: state.networkPortInput,\n networkHostnameInput: state.networkHostnameInput,\n networkModalOpen: state.networkModalOpen,\n networkBusy: state.networkBusy,\n networkError: state.networkError,\n networkSuccess: state.networkSuccess,\n onNetworkModalToggle: () => {\n state.networkModalOpen = !state.networkModalOpen;\n // Reset inputs to current values when opening\n if (state.networkModalOpen) {\n state.networkPortInput = String(state.networkPort ?? \"\");\n state.networkHostnameInput = state.networkHostname;\n state.networkError = null;\n state.networkSuccess = null;\n }\n },\n onNetworkPortChange: (port: string) => {\n state.networkPortInput = port;\n state.networkError = null;\n state.networkSuccess = null;\n },\n onNetworkHostnameChange: (hostname: string) => {\n state.networkHostnameInput = hostname;\n state.networkError = null;\n state.networkSuccess = null;\n },\n onNetworkSave: async () => {\n if (state.networkBusy) return;\n state.networkBusy = true;\n state.networkError = null;\n state.networkSuccess = null;\n\n const portStr = state.networkPortInput.trim();\n const portNum = Number.parseInt(portStr, 10);\n const newHostname = state.networkHostnameInput.trim();\n\n // Validate port\n if (!portStr || !Number.isFinite(portNum) || portNum < 1024 || portNum > 65535) {\n state.networkError = \"Port must be a number between 1024 and 65535\";\n state.networkBusy = false;\n return;\n }\n\n const portChanged = portNum !== state.networkPort;\n const hostnameChanged = newHostname !== state.networkHostname;\n\n if (!portChanged && !hostnameChanged) {\n state.networkBusy = false;\n return;\n }\n\n try {\n // Step 1: If hostname changed, update system hostname first\n if (hostnameChanged) {\n await state.client!.request(\"network.setHostname\", { hostname: newHostname });\n }\n\n // Step 2: Build config patch for changed values\n const patch: Record<string, unknown> = {};\n if (portChanged) {\n patch.gateway = { port: portNum };\n }\n if (hostnameChanged) {\n patch.discovery = { bonjourHostname: newHostname };\n }\n\n // Step 3: Fetch fresh config hash and apply patch with delayed restart\n const snapshot = await state.client!.request<ConfigSnapshot>(\"config.get\");\n await state.client!.request(\"config.patch\", {\n raw: JSON.stringify(patch),\n baseHash: snapshot.hash,\n note: [\n portChanged ? `Port → ${portNum}` : null,\n hostnameChanged ? `Hostname → ${newHostname}` : null,\n ].filter(Boolean).join(\", \"),\n restartDelayMs: 2000,\n });\n\n // Step 4: Show success and redirect to new URL\n state.networkSuccess = \"Saved — redirecting...\";\n\n const currentProtocol = window.location.protocol;\n const newHost = hostnameChanged ? `${newHostname}.local` : window.location.hostname;\n const newPort = portChanged ? portNum : state.networkPort;\n const newUrl = `${currentProtocol}//${newHost}:${newPort}/setup`;\n\n // Redirect after a brief delay to let the user see the success message\n setTimeout(() => {\n window.location.href = newUrl;\n }, 1500);\n } catch (err) {\n console.error(\"Network save failed:\", err);\n state.networkError = (err as Error).message || \"Failed to save network settings\";\n state.networkBusy = false;\n }\n },\n // Workspace selector in the nav bar\n wsProps: buildSetupWorkspaceNavProps(state),\n });\n }\n\n // Files page: standalone dark page (same style as setup)\n if (state.filesPage) {\n const filesAgentId = resolveFilesAgentId(state);\n return renderFiles({\n connected: state.connected,\n wsProps: buildWorkspaceNavProps(state),\n loading: state.filesLoading,\n tree: state.filesTree,\n root: state.filesRoot,\n error: state.filesError,\n selectedPath: state.filesSelectedPath,\n selectedPaths: state.filesSelectedPaths,\n previewContent: state.filesPreviewContent,\n previewLoading: state.filesPreviewLoading,\n previewBinary: state.filesPreviewBinary,\n previewSize: state.filesPreviewSize,\n expandedDirs: state.filesExpandedDirs,\n currentDir: state.filesCurrentDir,\n message: state.filesMessage,\n uploadBusy: state.filesUploadBusy,\n reindexBusy: state.filesReindexBusy,\n memoryStatus: state.filesMemoryStatus,\n onRefresh: () => { void loadFileTree(state, filesAgentId); void loadMemoryStatus(state, filesAgentId); },\n onReindex: () => reindexMemory(state, filesAgentId),\n onSelectFile: (path) => { state.filesPendingDeletePath = null; selectFile(state, path, filesAgentId); },\n onToggleSelectFile: (path) => toggleSelectFile(state, path, filesAgentId),\n onToggleDir: (path) => toggleDirectory(state, path),\n onUpload: (dirPath, files) => uploadFiles(state, dirPath, files, filesAgentId),\n onNewFolder: (parentDir, name) => createFolder(state, parentDir, name, filesAgentId),\n onDownload: (path) => downloadFile(state, path, filesAgentId),\n onBulkDownload: () => bulkDownloadFiles(state, filesAgentId),\n onDelete: (path) => { state.filesPendingDeletePath = null; deleteFile(state, path, filesAgentId); },\n pendingDeletePath: state.filesPendingDeletePath,\n onArmDelete: (path) => { state.filesPendingDeletePath = path || null; },\n onMoveToDir: (filePath, targetDir) => moveFileToDir(state, filePath, targetDir, filesAgentId),\n searchQuery: state.filesSearchQuery,\n searchResults: state.filesSearchResults,\n searchLoading: state.filesSearchLoading,\n searchAgentId: state.filesSearchAgentId,\n agentIds: state.workspaceAgentIds ?? [],\n onSearch: (query) => {\n const searchAgent = state.filesSearchAgentId ?? filesAgentId;\n searchMemory(state, query, searchAgent);\n },\n onSearchAgentChange: (agentId) => {\n state.filesSearchAgentId = agentId;\n },\n onSearchClear: () => {\n clearSearch(state);\n },\n onSearchQueryChange: (query) => {\n state.filesSearchQuery = query;\n },\n });\n }\n\n // Browser page: standalone dark page (same style as setup)\n if (state.browserPage) {\n return renderBrowserViewer({\n connected: state.connected,\n active: state.browserScreencastActive,\n loading: state.browserLoading,\n error: state.browserError,\n inputMode: state.browserInputMode,\n fullscreen: state.browserFullscreen,\n handoffPending: state.browserHandoffPending,\n handoffReason: state.browserHandoffReason,\n onStart: () => startBrowserScreencast(state),\n onStop: () => stopBrowserScreencast(state),\n onToggleInput: () => toggleInputMode(state),\n onToggleFullscreen: () => toggleFullscreen(state),\n onCompleteHandoff: () => completeHandoff(state),\n onCanvasMouseDown: (e: MouseEvent) => {\n const canvas = e.target as HTMLCanvasElement;\n const rect = canvas.getBoundingClientRect();\n const renderer = getCanvasRenderer();\n const coords = renderer.translateCoordinates(e.clientX - rect.left, e.clientY - rect.top);\n sendMouseInput(state, \"mousePressed\", coords.x, coords.y,\n e.button === 2 ? \"right\" : e.button === 1 ? \"middle\" : \"left\");\n },\n onCanvasMouseUp: (e: MouseEvent) => {\n const canvas = e.target as HTMLCanvasElement;\n const rect = canvas.getBoundingClientRect();\n const renderer = getCanvasRenderer();\n const coords = renderer.translateCoordinates(e.clientX - rect.left, e.clientY - rect.top);\n sendMouseInput(state, \"mouseReleased\", coords.x, coords.y);\n },\n onCanvasMouseMove: (e: MouseEvent) => {\n const renderer = getCanvasRenderer();\n if (renderer.shouldThrottleMouseMove()) return;\n const canvas = e.target as HTMLCanvasElement;\n const rect = canvas.getBoundingClientRect();\n const coords = renderer.translateCoordinates(e.clientX - rect.left, e.clientY - rect.top);\n sendMouseInput(state, \"mouseMoved\", coords.x, coords.y);\n },\n onCanvasKeyDown: (e: KeyboardEvent) => {\n let modifiers = 0;\n if (e.altKey) modifiers |= 1;\n if (e.ctrlKey) modifiers |= 2;\n if (e.metaKey) modifiers |= 4;\n if (e.shiftKey) modifiers |= 8;\n sendKeyInput(state, \"keyDown\", e.key, { code: e.code, modifiers: modifiers || undefined });\n if (e.key.length === 1) sendKeyInput(state, \"char\", e.key, { text: e.key });\n },\n onCanvasKeyUp: (e: KeyboardEvent) => {\n sendKeyInput(state, \"keyUp\", e.key, { code: e.code });\n },\n });\n }\n\n // Admins page: standalone dark page (same style as setup)\n if (state.adminsPage) {\n const adminAgentId = resolveAdminAgentId(state);\n const waAccountId = resolveWhatsAppAccountId(state);\n return renderAdminsPage({\n connected: state.connected,\n wsProps: buildWorkspaceNavProps(state),\n loading: state.adminsLoading,\n saving: state.adminsSaving,\n phones: state.adminPhones,\n error: state.adminsError,\n newPhone: state.adminsNewPhone,\n onRefresh: () => loadAdmins(state, adminAgentId),\n onAdd: (phone) => {\n void addAdmin(state, phone, adminAgentId, waAccountId).then(() => {\n if (!state.adminsError) state.adminsNewPhone = \"\";\n });\n },\n onRemove: (phone) => removeAdmin(state, phone, adminAgentId, waAccountId),\n onNewPhoneChange: (value) => state.handleAdminsNewPhoneChange(value),\n });\n }\n\n // Contacts page: standalone dark page (same style as admins)\n if (state.contactsPage) {\n const wsName = resolveWorkspaceName(state);\n return renderContactsPage({\n connected: state.connected,\n wsProps: buildWorkspaceNavProps(state),\n loading: state.contactsLoading,\n saving: state.contactsSaving,\n records: state.contactsRecords,\n error: state.contactsError,\n searchQuery: state.contactsSearchQuery,\n editingId: state.contactsEditingId,\n showAddForm: state.contactsShowAddForm,\n newRecordPhone: state.contactsNewPhone,\n newRecordName: state.contactsNewName,\n deleteConfirmId: state.contactsDeleteConfirmId,\n addFieldForId: state.contactsAddFieldForId,\n addFieldKey: state.contactsAddFieldKey,\n addFieldValue: state.contactsAddFieldValue,\n onSearch: (query) => (state.contactsSearchQuery = query),\n onSearchSubmit: () => loadContacts(state, wsName),\n onAdd: (phone, name) => addContact(state, phone, name, wsName),\n onDelete: (id) => deleteContact(state, id, wsName),\n onSetField: (id, key, value) => setContactField(state, id, key, value, wsName),\n onDeleteField: (id, key) => deleteContactField(state, id, key, wsName),\n onToggleExpand: (id) => {\n state.contactsEditingId = state.contactsEditingId === id ? null : id;\n },\n onShowAddForm: () => (state.contactsShowAddForm = true),\n onCancelAddForm: () => {\n state.contactsShowAddForm = false;\n state.contactsNewPhone = \"\";\n state.contactsNewName = \"\";\n },\n onNewRecordPhoneChange: (value) => state.handleContactsNewPhoneChange(value),\n onNewRecordNameChange: (value) => state.handleContactsNewNameChange(value),\n onRefresh: () => loadContacts(state, wsName),\n onDeleteConfirmOpen: (id) => (state.contactsDeleteConfirmId = id),\n onDeleteConfirmClose: () => (state.contactsDeleteConfirmId = null),\n onAddFieldOpen: (id) => {\n state.contactsAddFieldForId = id;\n state.contactsAddFieldKey = \"\";\n state.contactsAddFieldValue = \"\";\n },\n onAddFieldClose: () => {\n state.contactsAddFieldForId = null;\n state.contactsAddFieldKey = \"\";\n state.contactsAddFieldValue = \"\";\n },\n onAddFieldKeyChange: (value) => (state.contactsAddFieldKey = value),\n onAddFieldValueChange: (value) => (state.contactsAddFieldValue = value),\n onAddFieldSubmit: () => {\n const id = state.contactsAddFieldForId;\n const key = state.contactsAddFieldKey.trim();\n if (!id || !key) return;\n setContactField(state, id, key, state.contactsAddFieldValue, wsName);\n state.contactsAddFieldForId = null;\n state.contactsAddFieldKey = \"\";\n state.contactsAddFieldValue = \"\";\n },\n });\n }\n\n // Chat page: standalone dark page\n if (state.chatPage) {\n const chatDisabledReason = state.connected ? null : \"Disconnected from gateway.\";\n const assistantAvatarUrl = resolveAssistantAvatarUrl(state);\n const chatAvatarUrl = state.chatAvatarUrl ?? assistantAvatarUrl ?? null;\n const publicChatOn = (() => {\n const config = state.configSnapshot?.config as Record<string, unknown> | null;\n const pc = config?.publicChat as Record<string, unknown> | undefined;\n return pc?.enabled === true;\n })();\n return renderChatPage({\n connected: state.connected,\n wsProps: buildWorkspaceNavProps(state),\n publicChatEnabled: publicChatOn,\n publicChatAccountId: state.selectedWorkspace ?? undefined,\n chatPageTab: state.chatPageTab ?? \"chat\",\n onChatPageTabChange: (tab: ChatPageTab) => {\n state.chatPageTab = tab;\n if (tab === \"whatsapp\" && !state.waLoading && state.waConversations.length === 0) {\n const waState = buildWhatsAppState(state);\n void loadConversations(waState).then(() => state.requestUpdate());\n }\n },\n whatsappProps: buildWhatsAppProps(state),\n sessionKey: state.sessionKey,\n onSessionKeyChange: (next) => {\n // Persist current session's draft before switching\n const ws = state.selectedWorkspace ?? \"\";\n flushDraftSave();\n saveDraft(ws, state.sessionKey, state.chatMessage);\n state.sessionKey = next;\n state.chatMessage = loadDraft(ws, next);\n state.chatAttachments = [];\n state.chatStream = null;\n (state as unknown as { chatInterimText: string | null }).chatInterimText = null;\n (state as unknown as { chatSuggestions: string[] }).chatSuggestions = [];\n (state as unknown as { chatStreamStartedAt: number | null }).chatStreamStartedAt = null;\n state.chatRunId = null;\n state.chatQueue = [];\n (state as unknown as { resetToolStream: () => void }).resetToolStream();\n (state as unknown as { resetChatScroll: () => void }).resetChatScroll();\n state.applySettings({\n ...state.settings,\n sessionKey: next,\n lastActiveSessionKey: next,\n });\n void state.loadAssistantIdentity();\n void loadChatHistory(state);\n void refreshChatAvatar(state);\n },\n showThinking: state.settings.chatShowThinking ?? false,\n verboseLevel: (state as unknown as { chatVerboseLevel: string | null }).chatVerboseLevel,\n suggestions: (state as unknown as { chatSuggestions: string[] }).chatSuggestions,\n onSuggestionClick: (text: string) => {\n state.chatMessage = text;\n (state as unknown as { chatSuggestions: string[] }).chatSuggestions = [];\n void (state as unknown as { handleSendChat: () => Promise<void> }).handleSendChat();\n },\n loading: state.chatLoading,\n sending: state.chatSending,\n compactionStatus: (state as unknown as { compactionStatus: unknown }).compactionStatus as import(\"./views/chat\").CompactionIndicatorStatus | null,\n assistantAvatarUrl: chatAvatarUrl,\n messages: state.chatMessages,\n toolMessages: state.chatToolMessages,\n stream: state.chatStream,\n streamStartedAt: (state as unknown as { chatStreamStartedAt: number | null }).chatStreamStartedAt,\n interimText: (state as unknown as { chatInterimText: string | null }).chatInterimText,\n draft: state.chatMessage,\n queue: state.chatQueue,\n canSend: state.connected,\n disabledReason: chatDisabledReason,\n error: state.lastError,\n sessions: state.sessionsResult,\n focusMode: false,\n onRefresh: () => {\n (state as unknown as { resetToolStream: () => void }).resetToolStream();\n const lim = Math.max(state.chatMessages.length + 10, CHAT_PAGE_SIZE);\n return Promise.all([loadChatHistory(state, { limit: lim }), refreshChatAvatar(state)]);\n },\n onToggleFocusMode: () => {},\n onChatScroll: (event) => (state as unknown as { handleChatScroll: (e: Event) => void }).handleChatScroll(event),\n nearBottom: state.chatUserNearBottom,\n hasMore: (state as unknown as { chatHistoryHasMore: boolean }).chatHistoryHasMore,\n loadingOlder: (state as unknown as { chatLoadingOlder: boolean }).chatLoadingOlder,\n onLoadOlder: () => void (state as unknown as { handleLoadOlderChat: () => Promise<void> }).handleLoadOlderChat(),\n onDraftChange: (next) => {\n state.chatMessage = next;\n scheduleDraftSave(state.selectedWorkspace ?? \"\", state.sessionKey, next);\n },\n requestUpdate: () => state.requestUpdate(),\n attachments: state.chatAttachments,\n onAttachmentsChange: (next) => (state.chatAttachments = next),\n onSend: () => (state as unknown as { handleSendChat: () => Promise<void> }).handleSendChat(),\n canAbort: Boolean(state.chatRunId),\n onAbort: () => void (state as unknown as { handleAbortChat: () => Promise<void> }).handleAbortChat(),\n onQueueRemove: (id) => (state as unknown as { removeQueuedMessage: (id: string) => void }).removeQueuedMessage(id),\n onNewSession: () =>\n (state as unknown as { handleSendChat: (msg?: string, opts?: { restoreDraft?: boolean }) => Promise<void> }).handleSendChat(\"/new\", { restoreDraft: true }),\n sidebarOpen: (state as unknown as { sidebarOpen: boolean }).sidebarOpen,\n sidebarContent: (state as unknown as { sidebarContent: string | null }).sidebarContent,\n sidebarError: (state as unknown as { sidebarError: string | null }).sidebarError,\n splitRatio: (state as unknown as { splitRatio: number }).splitRatio,\n onOpenSidebar: (content: string) => (state as unknown as { handleOpenSidebar: (c: string) => void }).handleOpenSidebar(content),\n onCloseSidebar: () => (state as unknown as { handleCloseSidebar: () => void }).handleCloseSidebar(),\n onSplitRatioChange: (ratio: number) => (state as unknown as { handleSplitRatioChange: (r: number) => void }).handleSplitRatioChange(ratio),\n assistantName: state.assistantName,\n assistantAvatar: state.assistantAvatar,\n });\n }\n\n // Advanced page: standalone dark page with tabs\n if (state.advancedPage) {\n return renderAdvancedPage({\n connected: state.connected,\n wsProps: buildWorkspaceNavProps(state),\n activeTab: state.advancedTab as AdvancedTab,\n onTabChange: (tab) => {\n (state as unknown as { advancedTab: string }).advancedTab = tab;\n // Trigger data load for newly selected tab\n if (tab === \"cron\") void state.loadCron();\n if (tab === \"skills\") void loadSkills(state, { clearMessages: true });\n if (tab === \"opening-hours\") void loadOpeningHours(state);\n if (tab === \"logs\") {\n const subTab = (state as unknown as { logsSubTab: string }).logsSubTab;\n if (subTab === \"session\") {\n void loadSessionLogs(state as unknown as Parameters<typeof loadSessionLogs>[0], { reset: true });\n } else {\n void loadLogs(state, { reset: true });\n }\n }\n },\n cronProps: {\n loading: state.cronLoading,\n status: state.cronStatus,\n jobs: state.cronJobs,\n error: state.cronError,\n busy: state.cronBusy,\n form: state.cronForm,\n channels: state.channelsSnapshot?.channelMeta?.length\n ? state.channelsSnapshot.channelMeta.map((entry) => entry.id)\n : state.channelsSnapshot?.channelOrder ?? [],\n channelLabels: state.channelsSnapshot?.channelLabels ?? {},\n channelMeta: state.channelsSnapshot?.channelMeta ?? [],\n agentIds: (() => {\n const ws = getSelectedWorkspaceInfo(state);\n return ws?.agents?.map((a) => a.id) ?? [];\n })(),\n runsJobId: state.cronRunsJobId,\n runs: state.cronRuns,\n newEventModalOpen: state.cronNewEventModal,\n onNewEventModalOpen: () => { state.cronNewEventModal = true; },\n onNewEventModalClose: () => { state.cronNewEventModal = false; state.cronEditJobId = null; },\n detailJobId: state.cronDetailJobId,\n editJobId: state.cronEditJobId,\n onDetailOpen: (job) => { state.cronDetailJobId = job.id; loadCronRuns(state, job.id); },\n onDetailClose: () => { state.cronDetailJobId = null; },\n onEdit: (job) => {\n state.cronForm = cronJobToFormState(job);\n state.cronEditJobId = job.id;\n state.cronDetailJobId = null;\n },\n onEditSave: () => {\n const jobId = state.cronEditJobId;\n if (!jobId) return;\n void updateCronJob(state, jobId).then(() => {\n state.cronEditJobId = null;\n });\n },\n onFormChange: (patch) => (state.cronForm = { ...state.cronForm, ...patch }),\n onRefresh: () => state.loadCron(),\n onAdd: () => { void addCronJob(state).then(() => { state.cronNewEventModal = false; }); },\n onToggle: (job, enabled) => toggleCronJob(state, job, enabled),\n onRun: (job) => runCronJob(state, job),\n onRemove: (job) => { state.cronPendingDeleteId = null; removeCronJob(state, job); },\n pendingDeleteId: state.cronPendingDeleteId,\n onArmDelete: (jobId) => { state.cronPendingDeleteId = jobId || null; },\n onLoadRuns: (jobId) => loadCronRuns(state, jobId),\n runModalJobId: state.cronRunModalJobId,\n runModalJobName: state.cronRunModalJobName,\n runResult: state.cronRunResult,\n onRunModalClose: () => { state.cronRunModalJobId = null; state.cronRunModalJobName = \"\"; state.cronRunResult = null; },\n },\n skillsProps: {\n loading: state.skillsLoading,\n report: state.skillsReport,\n error: state.skillsError,\n filter: state.skillsFilter,\n typeFilter: state.skillsTypeFilter,\n edits: state.skillEdits,\n messages: state.skillMessages,\n busyKey: state.skillsBusyKey,\n detail: state.skillDetail,\n detailTab: state.skillDetailTab,\n addModal: state.skillAddModal,\n addForm: state.skillAddForm,\n formSource: state.skillAddFormSource,\n editTab: state.skillEditTab,\n drafts: state.skillDrafts,\n onFilterChange: (next) => (state.skillsFilter = next),\n onTypeFilterChange: (next) => (state.skillsTypeFilter = next),\n onRefresh: () => loadSkills(state, { clearMessages: true }),\n onToggle: (key, enabled) => updateSkillEnabled(state, key, enabled),\n onEdit: (key, value) => updateSkillEdit(state, key, value),\n onSaveKey: (key) => saveSkillApiKey(state, key),\n onInstall: (skillKey, name, installId) =>\n installSkill(state, skillKey, name, installId),\n onViewDetail: (name) => viewSkillDetail(state, name),\n onDetailClose: () => closeSkillDetail(state),\n onDetailTab: (tab) => setSkillDetailTab(state, tab),\n onAddOpen: () => openAddSkillModal(state),\n onAddClose: () => closeAddSkillModal(state),\n onImportDraft: (draft) => importDraft(state, draft),\n onInstallDraft: (draft) => installDraft(state, draft),\n onDeleteDraft: (name) => deleteDraft(state, name),\n onAddSave: () => saveNewSkill(state),\n onAddFormUpdate: (field, value) => {\n state.skillAddForm = { ...state.skillAddForm, [field]: value };\n },\n onAlwaysActiveToggle: (name, alwaysActive) => toggleAlwaysActive(state, name, alwaysActive),\n onDelete: (name) => deleteSkill(state, name),\n onEditSkill: (name) => editSkill(state, name),\n onEditDetail: (activeTab) => editDetailSkill(state, activeTab),\n onRefUpdate: (refName, content) => updateFormReference(state, refName, content),\n onEditTab: (tab) => setEditTab(state, tab),\n agentFilter: state.skillsAgentFilter,\n onAgentFilterChange: (next) => (state.skillsAgentFilter = next),\n onAgentsChange: (skillKey, agents) => updateSkillAgents(state, skillKey, agents),\n },\n logsProps: {\n logsSubTab: (state as unknown as { logsSubTab: \"system\" | \"session\" }).logsSubTab,\n isAdmin: state.accessState.master || !state.accessState.hasPins,\n onSubTabChange: (tab) => {\n (state as unknown as { logsSubTab: \"system\" | \"session\" }).logsSubTab = tab;\n if (tab === \"session\") {\n void loadSessionLogs(state as unknown as Parameters<typeof loadSessionLogs>[0], { reset: true });\n } else {\n void loadLogs(state, { reset: true });\n }\n },\n sessionLogsProps: {\n loading: (state as unknown as { sessionLogsLoading: boolean }).sessionLogsLoading,\n error: (state as unknown as { sessionLogsError: string | null }).sessionLogsError,\n entries: (state as unknown as { sessionLogsEntries: SessionTranscriptEntry[] }).sessionLogsEntries,\n agents: (state as unknown as { sessionLogsAgents: string[] }).sessionLogsAgents,\n filterText: (state as unknown as { sessionLogsFilterText: string }).sessionLogsFilterText,\n typeFilters: (state as unknown as { sessionLogsTypeFilters: Record<SessionLogType, boolean> }).sessionLogsTypeFilters,\n agentFilters: (state as unknown as { sessionLogsAgentFilters: Record<string, boolean> }).sessionLogsAgentFilters,\n autoFollow: (state as unknown as { sessionLogsAutoFollow: boolean }).sessionLogsAutoFollow,\n chipsExpanded: (state as unknown as { sessionLogsChipsExpanded: boolean }).sessionLogsChipsExpanded,\n expandedIds: (state as unknown as { sessionLogsExpandedIds: Set<string> }).sessionLogsExpandedIds,\n onFilterTextChange: (next) => ((state as unknown as { sessionLogsFilterText: string }).sessionLogsFilterText = next),\n onTypeToggle: (type, enabled) => {\n const s = state as unknown as { sessionLogsTypeFilters: Record<string, boolean> };\n s.sessionLogsTypeFilters = { ...s.sessionLogsTypeFilters, [type]: enabled };\n },\n onAgentToggle: (agent, enabled) => {\n const s = state as unknown as { sessionLogsAgentFilters: Record<string, boolean> };\n s.sessionLogsAgentFilters = { ...s.sessionLogsAgentFilters, [agent]: enabled };\n },\n onToggleAutoFollow: (next) => ((state as unknown as { sessionLogsAutoFollow: boolean }).sessionLogsAutoFollow = next),\n onToggleChips: () => {\n const s = state as unknown as { sessionLogsChipsExpanded: boolean };\n s.sessionLogsChipsExpanded = !s.sessionLogsChipsExpanded;\n },\n onToggleExpand: (id) => {\n const s = state as unknown as { sessionLogsExpandedIds: Set<string>; requestUpdate: () => void };\n const next = new Set(s.sessionLogsExpandedIds);\n if (next.has(id)) next.delete(id); else next.add(id);\n s.sessionLogsExpandedIds = next;\n s.requestUpdate();\n },\n onRefresh: () => void loadSessionLogs(state as unknown as Parameters<typeof loadSessionLogs>[0], { reset: true }),\n onExport: (lines, label) => (state as unknown as { exportSessionLogs: (l: string[], lb: string) => void }).exportSessionLogs(lines, label),\n onScroll: (event) => (state as unknown as { handleSessionLogsScroll: (e: Event) => void }).handleSessionLogsScroll(event),\n },\n loading: state.logsLoading,\n error: state.logsError,\n file: state.logsFile,\n entries: state.logsEntries,\n filterText: state.logsFilterText,\n levelFilters: state.logsLevelFilters,\n autoFollow: state.logsAutoFollow,\n chipsExpanded: (state as unknown as { logsChipsExpanded: boolean }).logsChipsExpanded,\n truncated: state.logsTruncated,\n selectedDate: state.logsDate,\n availableDates: state.logsAvailableDates,\n onDateChange: (date: string | null) => {\n state.logsDate = date;\n void loadLogs(state, { reset: true });\n },\n onFilterTextChange: (next) => (state.logsFilterText = next),\n onLevelToggle: (level, enabled) => {\n state.logsLevelFilters = { ...state.logsLevelFilters, [level]: enabled };\n },\n onToggleAutoFollow: (next) => (state.logsAutoFollow = next),\n onToggleChips: () => {\n const s = state as unknown as { logsChipsExpanded: boolean };\n s.logsChipsExpanded = !s.logsChipsExpanded;\n },\n onRefresh: () => loadLogs(state, { reset: true }),\n onExport: (lines, label) => (state as unknown as { exportSessionLogs: (l: string[], lb: string) => void }).exportSessionLogs(lines, label),\n onScroll: (event) => (state as unknown as { handleLogsScroll: (e: Event) => void }).handleLogsScroll(event),\n },\n openingHoursProps: {\n loading: (state as unknown as { openingHoursLoading: boolean }).openingHoursLoading,\n error: (state as unknown as { openingHoursError: string | null }).openingHoursError,\n busy: (state as unknown as { openingHoursBusy: boolean }).openingHoursBusy,\n form: (state as unknown as { openingHoursForm: import(\"./controllers/opening-hours\").OpeningHoursFormState }).openingHoursForm,\n onFormChange: (patch) => {\n const s = state as unknown as { openingHoursForm: import(\"./controllers/opening-hours\").OpeningHoursFormState };\n s.openingHoursForm = { ...s.openingHoursForm, ...patch };\n },\n onDayChange: (day, field, value) => {\n const s = state as unknown as { openingHoursForm: import(\"./controllers/opening-hours\").OpeningHoursFormState };\n const days = { ...s.openingHoursForm.days };\n days[day] = { ...days[day], [field]: value };\n s.openingHoursForm = { ...s.openingHoursForm, days };\n },\n onAddClosedDate: (date) => {\n const s = state as unknown as { openingHoursForm: import(\"./controllers/opening-hours\").OpeningHoursFormState };\n if (!s.openingHoursForm.closedDates.includes(date)) {\n s.openingHoursForm = {\n ...s.openingHoursForm,\n closedDates: [...s.openingHoursForm.closedDates, date].sort(),\n };\n }\n },\n onRemoveClosedDate: (date) => {\n const s = state as unknown as { openingHoursForm: import(\"./controllers/opening-hours\").OpeningHoursFormState };\n s.openingHoursForm = {\n ...s.openingHoursForm,\n closedDates: s.openingHoursForm.closedDates.filter((d) => d !== date),\n };\n },\n onSave: () => void saveOpeningHours(state as unknown as Parameters<typeof saveOpeningHours>[0]),\n },\n });\n }\n\n // No matching standalone page — redirect to /chat\n window.location.replace(\"/chat\");\n return html``;\n}\n","import { html } from \"lit\";\nimport type { AuditEntry } from \"../controllers/audit\";\n\nfunction formatTimestamp(ts: number): string {\n const d = new Date(ts);\n const date = d.toLocaleDateString(\"en-GB\", { day: \"2-digit\", month: \"short\" });\n const time = d.toLocaleTimeString(\"en-GB\", { hour: \"2-digit\", minute: \"2-digit\" });\n return `${date} ${time}`;\n}\n\nfunction folderLabel(path: string): string {\n if (path.startsWith(\"memory/public/\")) return \"public\";\n if (path.startsWith(\"memory/shared/\")) return \"shared\";\n return \"other\";\n}\n\nexport function renderAuditModal(\n entries: AuditEntry[],\n onClear: () => void,\n onClose: () => void,\n) {\n const handleOverlayClick = (e: Event) => {\n if ((e.target as HTMLElement).classList.contains(\"audit-modal-overlay\")) {\n onClose();\n }\n };\n\n return html`\n <div class=\"audit-modal-overlay\" @click=${handleOverlayClick}>\n <div class=\"audit-modal-card\">\n <div class=\"audit-modal-header\">\n <h3>Memory Writes to Review</h3>\n <button class=\"audit-modal-close\" @click=${onClose}>&times;</button>\n </div>\n <p class=\"audit-modal-desc\">\n These files were written to shared or public folders by the agent.\n Review to ensure no sensitive data was misplaced.\n </p>\n ${entries.length === 0\n ? html`<p class=\"audit-modal-empty\">No unreviewed writes.</p>`\n : html`\n <div class=\"audit-modal-list\">\n ${entries.map((entry) => html`\n <div class=\"audit-modal-entry\">\n <div class=\"audit-modal-entry-path\">\n <span class=\"audit-modal-folder audit-modal-folder--${folderLabel(entry.path)}\">${folderLabel(entry.path)}</span>\n <a href=\"/files\" class=\"audit-modal-path-link\">${entry.path}</a>\n </div>\n <div class=\"audit-modal-entry-meta\">\n ${formatTimestamp(entry.timestamp)}\n <span class=\"audit-modal-agent\">${entry.agentId}</span>\n </div>\n </div>\n `)}\n </div>\n <button class=\"setup-button audit-modal-clear\" @click=${onClear}>\n Mark All Reviewed\n </button>\n `}\n </div>\n </div>\n `;\n}\n","import type { LogLevel } from \"./types\";\nimport type { CronFormState } from \"./ui-types\";\n\nexport const DEFAULT_LOG_LEVEL_FILTERS: Record<LogLevel, boolean> = {\n trace: false,\n debug: false,\n info: true,\n warn: true,\n error: true,\n fatal: true,\n};\n\nexport const DEFAULT_CRON_FORM: CronFormState = {\n name: \"\",\n description: \"\",\n agentId: \"\",\n enabled: true,\n scheduleKind: \"every\",\n scheduleAt: \"\",\n everyAmount: \"30\",\n everyUnit: \"minutes\",\n cronExpr: \"0 7 * * *\",\n cronTz: \"\",\n sessionTarget: \"main\",\n wakeMode: \"next-heartbeat\",\n payloadKind: \"systemEvent\",\n payloadText: \"\",\n deliver: false,\n channel: \"last\",\n recipients: [],\n toAdmins: false,\n timeoutSeconds: \"\",\n postToMainPrefix: \"\",\n};\n","import type { Tab } from \"./navigation\";\nimport { connectGateway } from \"./app-gateway\";\nimport {\n applySettingsFromUrl,\n attachThemeListener,\n detachThemeListener,\n inferBasePath,\n syncTabWithLocation,\n syncThemeWithSettings,\n} from \"./app-settings\";\nimport { observeTopbar, scheduleChatScroll, scheduleLogsScroll } from \"./app-scroll\";\nimport {\n startLogsPolling,\n startNodesPolling,\n stopLogsPolling,\n stopNodesPolling,\n startDebugPolling,\n stopDebugPolling,\n startSessionLogsPolling,\n stopSessionLogsPolling,\n startAuditPolling,\n stopAuditPolling,\n startMemoryStatusPolling,\n stopMemoryStatusPolling,\n} from \"./app-polling\";\nimport { resolveBrand, applyBrandAccentColor, applyBrandBackgroundColor } from \"./brand\";\n\ntype LifecycleHost = {\n basePath: string;\n tab: Tab;\n chatHasAutoScrolled: boolean;\n chatLoading: boolean;\n chatMessages: unknown[];\n chatToolMessages: unknown[];\n chatStream: string;\n logsAutoFollow: boolean;\n logsAtBottom: boolean;\n logsEntries: unknown[];\n sessionLogsAutoFollow?: boolean;\n sessionLogsEntries?: unknown[];\n popStateHandler: () => void;\n topbarObserver: ResizeObserver | null;\n // Standalone page mode fields\n setup?: boolean;\n filesPage?: boolean;\n browserPage?: boolean;\n adminsPage?: boolean;\n contactsPage?: boolean;\n chatPage?: boolean;\n advancedPage?: boolean;\n publicChat?: boolean;\n connected?: boolean;\n whatsappBusy?: boolean;\n whatsappLoginQrDataUrl?: string | null;\n whatsappLoginConnected?: boolean | null;\n whatsappLoginMessage?: string | null;\n handleWhatsAppStart?: (force: boolean) => Promise<void>;\n handleWhatsAppWait?: () => Promise<void>;\n // License setup fields\n licenseValid?: boolean | null;\n licenseBusy?: boolean;\n handleLicenseStatusCheck?: () => Promise<void>;\n // Auth setup fields\n setupStep?: \"license\" | \"auth\" | \"setup\";\n authConnected?: boolean | null;\n authBusy?: boolean;\n handleAuthStatusCheck?: () => Promise<void>;\n // Channel status\n channelsLoading?: boolean;\n channelsSnapshot?: {\n channelAccounts?: {\n whatsapp?: Array<{\n running?: boolean | null;\n connected?: boolean | null;\n linked?: boolean | null;\n }>;\n };\n } | null;\n client?: {\n request: (method: string, params: Record<string, unknown>) => Promise<unknown>;\n } | null;\n // Audit polling\n auditPollInterval: number | null;\n // Files page callback\n handleFilesLoad?: () => void;\n // Admins page callback\n handleAdminsLoad?: () => void;\n // Contacts page callback\n handleContactsLoad?: () => void;\n // Chat page callback\n handleChatLoad?: () => void;\n // Advanced page callback\n handleAdvancedLoad?: () => void;\n // Software update callback\n handleUpdateCheck?: () => Promise<void>;\n};\n\nexport function handleConnected(host: LifecycleHost) {\n host.basePath = inferBasePath();\n\n // Apply brand colours and favicon before any rendering\n const brand = resolveBrand();\n applyBrandAccentColor(brand.accentColor);\n applyBrandBackgroundColor(brand.backgroundColor);\n const faviconLink = document.querySelector<HTMLLinkElement>('link[rel=\"icon\"]');\n if (faviconLink) faviconLink.href = brand.iconUrl;\n\n // Scroll to top on page load (standalone pages are full navigations)\n window.scrollTo(0, 0);\n\n // Audit polling runs on every page — the shield icon is in the header\n startAuditPolling(host as unknown as Parameters<typeof startAuditPolling>[0]);\n\n // Public chat: minimal lifecycle — just connect, no admin polling\n if (host.publicChat) {\n const cfg = window.__TASKMASTER_PUBLIC_CHAT_CONFIG__;\n const acct = cfg?.accountId ?? \"\";\n const name = acct ? acct.charAt(0).toUpperCase() + acct.slice(1) : \"Assistant\";\n document.title = `Chat with ${name}`;\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n return;\n }\n\n // Setup mode: set page title and skip normal navigation\n if (host.setup) {\n document.title = `${brand.name} Setup`;\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n return;\n }\n\n // Files page: standalone mode\n if (host.filesPage) {\n document.title = `${brand.name} Files`;\n startMemoryStatusPolling(host as unknown as Parameters<typeof startMemoryStatusPolling>[0]);\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n return;\n }\n\n // Browser page: standalone mode\n if (host.browserPage) {\n document.title = `${brand.name} Browser`;\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n return;\n }\n\n // Admins page: standalone mode\n if (host.adminsPage) {\n document.title = `${brand.name} Admins`;\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n return;\n }\n\n // Contacts page: standalone mode\n if (host.contactsPage) {\n document.title = `${brand.name} Contacts`;\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n return;\n }\n\n // Chat page: standalone mode\n if (host.chatPage) {\n document.title = `${brand.name} Chat`;\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n return;\n }\n\n // Advanced page: standalone mode\n if (host.advancedPage) {\n document.title = `${brand.name} Advanced`;\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n // Start log polling — the interval self-gates on advancedTab/logsSubTab each tick\n startSessionLogsPolling(host as unknown as Parameters<typeof startSessionLogsPolling>[0]);\n startLogsPolling(host as unknown as Parameters<typeof startLogsPolling>[0]);\n return;\n }\n\n syncTabWithLocation(\n host as unknown as Parameters<typeof syncTabWithLocation>[0],\n true,\n );\n syncThemeWithSettings(\n host as unknown as Parameters<typeof syncThemeWithSettings>[0],\n );\n attachThemeListener(\n host as unknown as Parameters<typeof attachThemeListener>[0],\n );\n window.addEventListener(\"popstate\", host.popStateHandler);\n applySettingsFromUrl(\n host as unknown as Parameters<typeof applySettingsFromUrl>[0],\n );\n connectGateway(host as unknown as Parameters<typeof connectGateway>[0]);\n startNodesPolling(host as unknown as Parameters<typeof startNodesPolling>[0]);\n if (host.tab === \"logs\") {\n const subTab = (host as unknown as { logsSubTab?: string }).logsSubTab;\n if (subTab === \"session\") {\n startSessionLogsPolling(host as unknown as Parameters<typeof startSessionLogsPolling>[0]);\n } else {\n startLogsPolling(host as unknown as Parameters<typeof startLogsPolling>[0]);\n }\n }\n if (host.tab === \"debug\") {\n startDebugPolling(host as unknown as Parameters<typeof startDebugPolling>[0]);\n }\n}\n\nexport function handleFirstUpdated(host: LifecycleHost) {\n observeTopbar(host as unknown as Parameters<typeof observeTopbar>[0]);\n}\n\nexport function handleDisconnected(host: LifecycleHost) {\n window.removeEventListener(\"popstate\", host.popStateHandler);\n stopNodesPolling(host as unknown as Parameters<typeof stopNodesPolling>[0]);\n stopLogsPolling(host as unknown as Parameters<typeof stopLogsPolling>[0]);\n stopSessionLogsPolling(host as unknown as Parameters<typeof stopSessionLogsPolling>[0]);\n stopDebugPolling(host as unknown as Parameters<typeof stopDebugPolling>[0]);\n stopAuditPolling(host as unknown as Parameters<typeof stopAuditPolling>[0]);\n stopMemoryStatusPolling(host as unknown as Parameters<typeof stopMemoryStatusPolling>[0]);\n detachThemeListener(\n host as unknown as Parameters<typeof detachThemeListener>[0],\n );\n host.topbarObserver?.disconnect();\n host.topbarObserver = null;\n}\n\nexport function handleUpdated(\n host: LifecycleHost,\n changed: Map<PropertyKey, unknown>,\n) {\n // Public chat: no admin-level lifecycle updates\n if (host.publicChat) return;\n\n // Files page: auto-load file tree when first connected\n if (host.filesPage && host.connected) {\n const justConnected = changed.has(\"connected\") && changed.get(\"connected\") === false;\n if (justConnected && host.handleFilesLoad) {\n host.handleFilesLoad();\n }\n }\n\n // Admins page: auto-load admin phones when first connected\n if (host.adminsPage && host.connected) {\n const justConnected = changed.has(\"connected\") && changed.get(\"connected\") === false;\n if (justConnected && host.handleAdminsLoad) {\n host.handleAdminsLoad();\n }\n }\n\n // Contacts page: auto-load contact records when first connected\n if (host.contactsPage && host.connected) {\n const justConnected = changed.has(\"connected\") && changed.get(\"connected\") === false;\n if (justConnected && host.handleContactsLoad) {\n host.handleContactsLoad();\n }\n }\n\n // Chat page: auto-load chat history when first connected\n if (host.chatPage && host.connected) {\n const justConnected = changed.has(\"connected\") && changed.get(\"connected\") === false;\n if (justConnected && host.handleChatLoad) {\n host.handleChatLoad();\n }\n }\n\n // Advanced page: auto-load default tab data when first connected\n if (host.advancedPage && host.connected) {\n const justConnected = changed.has(\"connected\") && changed.get(\"connected\") === false;\n if (justConnected && host.handleAdvancedLoad) {\n host.handleAdvancedLoad();\n }\n }\n\n // Setup mode: check license → auth → WhatsApp\n if (host.setup && host.connected) {\n const justConnected = changed.has(\"connected\") && changed.get(\"connected\") === false;\n\n // Step 0: Check license status when first connected\n if (justConnected && host.handleLicenseStatusCheck && host.licenseValid === null && !host.licenseBusy) {\n host.handleLicenseStatusCheck();\n }\n\n // Auto-check for software updates on connect\n if (justConnected && host.handleUpdateCheck) {\n host.handleUpdateCheck();\n }\n\n // Step 1: Check auth status when entering auth or setup step\n const justEnteredAuth = changed.has(\"setupStep\") && host.setupStep === \"auth\";\n const justEnteredSetup = changed.has(\"setupStep\") && host.setupStep === \"setup\";\n if (justConnected || justEnteredAuth || justEnteredSetup) {\n if (host.handleAuthStatusCheck && host.authConnected === null && !host.authBusy) {\n host.handleAuthStatusCheck();\n }\n }\n\n // Step 2: Load channels status when moving to WhatsApp step (don't auto-login)\n if (host.setupStep === \"setup\") {\n const stepJustChanged = changed.has(\"setupStep\");\n\n // Load channels status when entering WhatsApp step to show real status\n if (stepJustChanged && host.client && !host.channelsLoading) {\n host.channelsLoading = true;\n host.client.request(\"channels.status\", { probe: true, timeoutMs: 8000 })\n .then((res) => {\n host.channelsSnapshot = res as typeof host.channelsSnapshot;\n host.channelsLoading = false;\n })\n .catch(() => {\n host.channelsLoading = false;\n });\n }\n }\n\n // After WhatsApp login completes (QR scan), refresh channel status\n if (changed.has(\"whatsappLoginConnected\") && host.whatsappLoginConnected === true) {\n if (host.client && !host.channelsLoading) {\n host.channelsLoading = true;\n host.client.request(\"channels.status\", { probe: true, timeoutMs: 8000 })\n .then((res) => {\n host.channelsSnapshot = res as typeof host.channelsSnapshot;\n host.channelsLoading = false;\n })\n .catch(() => {\n host.channelsLoading = false;\n });\n }\n }\n }\n\n if (\n host.tab === \"chat\" &&\n !host.advancedPage &&\n (changed.has(\"chatMessages\") ||\n changed.has(\"chatToolMessages\") ||\n changed.has(\"chatStream\") ||\n changed.has(\"chatLoading\") ||\n changed.has(\"tab\"))\n ) {\n const forcedByTab = changed.has(\"tab\");\n const forcedByLoad =\n changed.has(\"chatLoading\") &&\n changed.get(\"chatLoading\") === true &&\n host.chatLoading === false;\n scheduleChatScroll(\n host as unknown as Parameters<typeof scheduleChatScroll>[0],\n forcedByTab || forcedByLoad || !host.chatHasAutoScrolled,\n );\n }\n // System logs auto-scroll (dashboard only — system logs sub-tab)\n if (\n host.tab === \"logs\" &&\n !host.advancedPage &&\n (changed.has(\"logsEntries\") || changed.has(\"logsAutoFollow\") || changed.has(\"tab\"))\n ) {\n if (host.logsAutoFollow && host.logsAtBottom) {\n scheduleLogsScroll(\n host as unknown as Parameters<typeof scheduleLogsScroll>[0],\n changed.has(\"tab\") || changed.has(\"logsAutoFollow\"),\n );\n }\n }\n // Session logs auto-scroll (both dashboard and Advanced page)\n if (\n changed.has(\"sessionLogsEntries\") || changed.has(\"sessionLogsAutoFollow\")\n ) {\n if (host.sessionLogsAutoFollow && host.logsAtBottom) {\n scheduleLogsScroll(\n host as unknown as Parameters<typeof scheduleLogsScroll>[0],\n changed.has(\"sessionLogsAutoFollow\"),\n );\n }\n }\n}\n","/**\n * Nostr Profile Edit Form\n *\n * Provides UI for editing and publishing Nostr profile (kind:0).\n */\n\nimport { html, nothing, type TemplateResult } from \"lit\";\n\nimport type { NostrProfile as NostrProfileType } from \"../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface NostrProfileFormState {\n /** Current form values */\n values: NostrProfileType;\n /** Original values for dirty detection */\n original: NostrProfileType;\n /** Whether the form is currently submitting */\n saving: boolean;\n /** Whether import is in progress */\n importing: boolean;\n /** Last error message */\n error: string | null;\n /** Last success message */\n success: string | null;\n /** Validation errors per field */\n fieldErrors: Record<string, string>;\n /** Whether to show advanced fields */\n showAdvanced: boolean;\n}\n\nexport interface NostrProfileFormCallbacks {\n /** Called when a field value changes */\n onFieldChange: (field: keyof NostrProfileType, value: string) => void;\n /** Called when save is clicked */\n onSave: () => void;\n /** Called when import is clicked */\n onImport: () => void;\n /** Called when cancel is clicked */\n onCancel: () => void;\n /** Called when toggle advanced is clicked */\n onToggleAdvanced: () => void;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction isFormDirty(state: NostrProfileFormState): boolean {\n const { values, original } = state;\n return (\n values.name !== original.name ||\n values.displayName !== original.displayName ||\n values.about !== original.about ||\n values.picture !== original.picture ||\n values.banner !== original.banner ||\n values.website !== original.website ||\n values.nip05 !== original.nip05 ||\n values.lud16 !== original.lud16\n );\n}\n\n// ============================================================================\n// Form Rendering\n// ============================================================================\n\nexport function renderNostrProfileForm(params: {\n state: NostrProfileFormState;\n callbacks: NostrProfileFormCallbacks;\n accountId: string;\n}): TemplateResult {\n const { state, callbacks, accountId } = params;\n const isDirty = isFormDirty(state);\n\n const renderField = (\n field: keyof NostrProfileType,\n label: string,\n opts: {\n type?: \"text\" | \"url\" | \"textarea\";\n placeholder?: string;\n maxLength?: number;\n help?: string;\n } = {}\n ) => {\n const { type = \"text\", placeholder, maxLength, help } = opts;\n const value = state.values[field] ?? \"\";\n const error = state.fieldErrors[field];\n\n const inputId = `nostr-profile-${field}`;\n\n if (type === \"textarea\") {\n return html`\n <div class=\"form-field\" style=\"margin-bottom: 12px;\">\n <label for=\"${inputId}\" style=\"display: block; margin-bottom: 4px; font-weight: 500;\">\n ${label}\n </label>\n <textarea\n id=\"${inputId}\"\n .value=${value}\n placeholder=${placeholder ?? \"\"}\n maxlength=${maxLength ?? 2000}\n rows=\"3\"\n style=\"width: 100%; padding: 8px; border: 1px solid var(--border-color); border-radius: 4px; resize: vertical; font-family: inherit;\"\n @input=${(e: InputEvent) => {\n const target = e.target as HTMLTextAreaElement;\n callbacks.onFieldChange(field, target.value);\n }}\n ?disabled=${state.saving}\n ></textarea>\n ${help ? html`<div style=\"font-size: 12px; color: var(--text-muted); margin-top: 2px;\">${help}</div>` : nothing}\n ${error ? html`<div style=\"font-size: 12px; color: var(--danger-color); margin-top: 2px;\">${error}</div>` : nothing}\n </div>\n `;\n }\n\n return html`\n <div class=\"form-field\" style=\"margin-bottom: 12px;\">\n <label for=\"${inputId}\" style=\"display: block; margin-bottom: 4px; font-weight: 500;\">\n ${label}\n </label>\n <input\n id=\"${inputId}\"\n type=${type}\n .value=${value}\n placeholder=${placeholder ?? \"\"}\n maxlength=${maxLength ?? 256}\n style=\"width: 100%; padding: 8px; border: 1px solid var(--border-color); border-radius: 4px;\"\n @input=${(e: InputEvent) => {\n const target = e.target as HTMLInputElement;\n callbacks.onFieldChange(field, target.value);\n }}\n ?disabled=${state.saving}\n />\n ${help ? html`<div style=\"font-size: 12px; color: var(--text-muted); margin-top: 2px;\">${help}</div>` : nothing}\n ${error ? html`<div style=\"font-size: 12px; color: var(--danger-color); margin-top: 2px;\">${error}</div>` : nothing}\n </div>\n `;\n };\n\n const renderPicturePreview = () => {\n const picture = state.values.picture;\n if (!picture) return nothing;\n\n return html`\n <div style=\"margin-bottom: 12px;\">\n <img\n src=${picture}\n alt=\"Profile picture preview\"\n style=\"max-width: 80px; max-height: 80px; border-radius: 50%; object-fit: cover; border: 2px solid var(--border-color);\"\n @error=${(e: Event) => {\n const img = e.target as HTMLImageElement;\n img.style.display = \"none\";\n }}\n @load=${(e: Event) => {\n const img = e.target as HTMLImageElement;\n img.style.display = \"block\";\n }}\n />\n </div>\n `;\n };\n\n return html`\n <div class=\"nostr-profile-form\" style=\"padding: 16px; background: var(--bg-secondary); border-radius: 8px; margin-top: 12px;\">\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;\">\n <div style=\"font-weight: 600; font-size: 16px;\">Edit Profile</div>\n <div style=\"font-size: 12px; color: var(--text-muted);\">Account: ${accountId}</div>\n </div>\n\n ${state.error\n ? html`<div class=\"callout danger\" style=\"margin-bottom: 12px;\">${state.error}</div>`\n : nothing}\n\n ${state.success\n ? html`<div class=\"callout success\" style=\"margin-bottom: 12px;\">${state.success}</div>`\n : nothing}\n\n ${renderPicturePreview()}\n\n ${renderField(\"name\", \"Username\", {\n placeholder: \"satoshi\",\n maxLength: 256,\n help: \"Short username (e.g., satoshi)\",\n })}\n\n ${renderField(\"displayName\", \"Display Name\", {\n placeholder: \"Satoshi Nakamoto\",\n maxLength: 256,\n help: \"Your full display name\",\n })}\n\n ${renderField(\"about\", \"Bio\", {\n type: \"textarea\",\n placeholder: \"Tell people about yourself...\",\n maxLength: 2000,\n help: \"A brief bio or description\",\n })}\n\n ${renderField(\"picture\", \"Avatar URL\", {\n type: \"url\",\n placeholder: \"https://example.com/avatar.jpg\",\n help: \"HTTPS URL to your profile picture\",\n })}\n\n ${state.showAdvanced\n ? html`\n <div style=\"border-top: 1px solid var(--border-color); padding-top: 12px; margin-top: 12px;\">\n <div style=\"font-weight: 500; margin-bottom: 12px; color: var(--text-muted);\">Advanced</div>\n\n ${renderField(\"banner\", \"Banner URL\", {\n type: \"url\",\n placeholder: \"https://example.com/banner.jpg\",\n help: \"HTTPS URL to a banner image\",\n })}\n\n ${renderField(\"website\", \"Website\", {\n type: \"url\",\n placeholder: \"https://example.com\",\n help: \"Your personal website\",\n })}\n\n ${renderField(\"nip05\", \"NIP-05 Identifier\", {\n placeholder: \"you@example.com\",\n help: \"Verifiable identifier (e.g., you@domain.com)\",\n })}\n\n ${renderField(\"lud16\", \"Lightning Address\", {\n placeholder: \"you@getalby.com\",\n help: \"Lightning address for tips (LUD-16)\",\n })}\n </div>\n `\n : nothing}\n\n <div style=\"display: flex; gap: 8px; margin-top: 16px; flex-wrap: wrap;\">\n <button\n class=\"btn primary\"\n @click=${callbacks.onSave}\n ?disabled=${state.saving || !isDirty}\n >\n ${state.saving ? \"Saving...\" : \"Save & Publish\"}\n </button>\n\n <button\n class=\"btn\"\n @click=${callbacks.onImport}\n ?disabled=${state.importing || state.saving}\n >\n ${state.importing ? \"Importing...\" : \"Import from Relays\"}\n </button>\n\n <button\n class=\"btn\"\n @click=${callbacks.onToggleAdvanced}\n >\n ${state.showAdvanced ? \"Hide Advanced\" : \"Show Advanced\"}\n </button>\n\n <button\n class=\"btn\"\n @click=${callbacks.onCancel}\n ?disabled=${state.saving}\n >\n Cancel\n </button>\n </div>\n\n ${isDirty\n ? html`<div style=\"font-size: 12px; color: var(--warning-color); margin-top: 8px;\">\n You have unsaved changes\n </div>`\n : nothing}\n </div>\n `;\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create initial form state from existing profile\n */\nexport function createNostrProfileFormState(\n profile: NostrProfileType | undefined\n): NostrProfileFormState {\n const values: NostrProfileType = {\n name: profile?.name ?? \"\",\n displayName: profile?.displayName ?? \"\",\n about: profile?.about ?? \"\",\n picture: profile?.picture ?? \"\",\n banner: profile?.banner ?? \"\",\n website: profile?.website ?? \"\",\n nip05: profile?.nip05 ?? \"\",\n lud16: profile?.lud16 ?? \"\",\n };\n\n return {\n values,\n original: { ...values },\n saving: false,\n importing: false,\n error: null,\n success: null,\n fieldErrors: {},\n showAdvanced: Boolean(\n profile?.banner || profile?.website || profile?.nip05 || profile?.lud16\n ),\n };\n}\n","import {\n addWhatsAppAccount,\n loadChannels,\n logoutWhatsApp,\n removeWhatsAppAccount,\n startWhatsAppLogin,\n waitWhatsAppLogin,\n} from \"./controllers/channels\";\nimport { loadConfig, saveConfig } from \"./controllers/config\";\nimport type { TaskmasterApp } from \"./app\";\nimport type { NostrProfile } from \"./types\";\nimport { createNostrProfileFormState } from \"./views/channels.nostr-profile-form\";\n\nexport async function handleWhatsAppStart(host: TaskmasterApp, force: boolean, accountId?: string) {\n await startWhatsAppLogin(host, force, accountId);\n await loadChannels(host, true);\n}\n\nexport async function handleWhatsAppWait(host: TaskmasterApp, accountId?: string) {\n await waitWhatsAppLogin(host, accountId);\n await loadChannels(host, true);\n}\n\nexport async function handleWhatsAppLogout(host: TaskmasterApp, accountId?: string) {\n await logoutWhatsApp(host, accountId);\n await loadChannels(host, true);\n}\n\nexport async function handleAddWhatsAppAccount(host: TaskmasterApp, name: string) {\n await addWhatsAppAccount(host, name);\n}\n\nexport async function handleRemoveWhatsAppAccount(host: TaskmasterApp, accountId: string) {\n await removeWhatsAppAccount(host, accountId);\n}\n\nexport async function handleChannelConfigSave(host: TaskmasterApp) {\n await saveConfig(host);\n await loadConfig(host);\n await loadChannels(host, true);\n}\n\nexport async function handleChannelConfigReload(host: TaskmasterApp) {\n await loadConfig(host);\n await loadChannels(host, true);\n}\n\nfunction parseValidationErrors(details: unknown): Record<string, string> {\n if (!Array.isArray(details)) return {};\n const errors: Record<string, string> = {};\n for (const entry of details) {\n if (typeof entry !== \"string\") continue;\n const [rawField, ...rest] = entry.split(\":\");\n if (!rawField || rest.length === 0) continue;\n const field = rawField.trim();\n const message = rest.join(\":\").trim();\n if (field && message) errors[field] = message;\n }\n return errors;\n}\n\nfunction resolveNostrAccountId(host: TaskmasterApp): string {\n const accounts = host.channelsSnapshot?.channelAccounts?.nostr ?? [];\n return accounts[0]?.accountId ?? host.nostrProfileAccountId ?? \"default\";\n}\n\nfunction buildNostrProfileUrl(accountId: string, suffix = \"\"): string {\n return `/api/channels/nostr/${encodeURIComponent(accountId)}/profile${suffix}`;\n}\n\nexport function handleNostrProfileEdit(\n host: TaskmasterApp,\n accountId: string,\n profile: NostrProfile | null,\n) {\n host.nostrProfileAccountId = accountId;\n host.nostrProfileFormState = createNostrProfileFormState(profile ?? undefined);\n}\n\nexport function handleNostrProfileCancel(host: TaskmasterApp) {\n host.nostrProfileFormState = null;\n host.nostrProfileAccountId = null;\n}\n\nexport function handleNostrProfileFieldChange(\n host: TaskmasterApp,\n field: keyof NostrProfile,\n value: string,\n) {\n const state = host.nostrProfileFormState;\n if (!state) return;\n host.nostrProfileFormState = {\n ...state,\n values: {\n ...state.values,\n [field]: value,\n },\n fieldErrors: {\n ...state.fieldErrors,\n [field]: \"\",\n },\n };\n}\n\nexport function handleNostrProfileToggleAdvanced(host: TaskmasterApp) {\n const state = host.nostrProfileFormState;\n if (!state) return;\n host.nostrProfileFormState = {\n ...state,\n showAdvanced: !state.showAdvanced,\n };\n}\n\nexport async function handleNostrProfileSave(host: TaskmasterApp) {\n const state = host.nostrProfileFormState;\n if (!state || state.saving) return;\n const accountId = resolveNostrAccountId(host);\n\n host.nostrProfileFormState = {\n ...state,\n saving: true,\n error: null,\n success: null,\n fieldErrors: {},\n };\n\n try {\n const response = await fetch(buildNostrProfileUrl(accountId), {\n method: \"PUT\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(state.values),\n });\n const data = (await response.json().catch(() => null)) as\n | { ok?: boolean; error?: string; details?: unknown; persisted?: boolean }\n | null;\n\n if (!response.ok || data?.ok === false || !data) {\n const errorMessage = data?.error ?? `Profile update failed (${response.status})`;\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: errorMessage,\n success: null,\n fieldErrors: parseValidationErrors(data?.details),\n };\n return;\n }\n\n if (!data.persisted) {\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: \"Profile publish failed on all relays.\",\n success: null,\n };\n return;\n }\n\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: null,\n success: \"Profile published to relays.\",\n fieldErrors: {},\n original: { ...state.values },\n };\n await loadChannels(host, true);\n } catch (err) {\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: `Profile update failed: ${String(err)}`,\n success: null,\n };\n }\n}\n\nexport async function handleNostrProfileImport(host: TaskmasterApp) {\n const state = host.nostrProfileFormState;\n if (!state || state.importing) return;\n const accountId = resolveNostrAccountId(host);\n\n host.nostrProfileFormState = {\n ...state,\n importing: true,\n error: null,\n success: null,\n };\n\n try {\n const response = await fetch(buildNostrProfileUrl(accountId, \"/import\"), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ autoMerge: true }),\n });\n const data = (await response.json().catch(() => null)) as\n | { ok?: boolean; error?: string; imported?: NostrProfile; merged?: NostrProfile; saved?: boolean }\n | null;\n\n if (!response.ok || data?.ok === false || !data) {\n const errorMessage = data?.error ?? `Profile import failed (${response.status})`;\n host.nostrProfileFormState = {\n ...state,\n importing: false,\n error: errorMessage,\n success: null,\n };\n return;\n }\n\n const merged = data.merged ?? data.imported ?? null;\n const nextValues = merged ? { ...state.values, ...merged } : state.values;\n const showAdvanced = Boolean(\n nextValues.banner || nextValues.website || nextValues.nip05 || nextValues.lud16,\n );\n\n host.nostrProfileFormState = {\n ...state,\n importing: false,\n values: nextValues,\n error: null,\n success: data.saved\n ? \"Profile imported from relays. Review and publish.\"\n : \"Profile imported. Review and publish.\",\n showAdvanced,\n };\n\n if (data.saved) {\n await loadChannels(host, true);\n }\n } catch (err) {\n host.nostrProfileFormState = {\n ...state,\n importing: false,\n error: `Profile import failed: ${String(err)}`,\n success: null,\n };\n }\n}\n","/**\n * Auth controller for setup flow\n *\n * Handles Claude OAuth authentication via the Control UI\n */\n\nimport type { GatewayBrowserClient } from \"../gateway\";\n\nexport type AuthState = {\n authConnected: boolean | null;\n authBusy: boolean;\n authMessage: string | null;\n authUrl: string | null;\n authCodeInput: string;\n authExpiresIn: number | null;\n authRefreshToken: string | null;\n setupStep: \"license\" | \"auth\" | \"setup\";\n client: GatewayBrowserClient | null;\n};\n\nexport type AuthStatusResponse = {\n connected: boolean;\n provider: string;\n email?: string;\n expiresIn?: number;\n expiresAt?: number;\n message?: string;\n refreshToken?: string;\n};\n\nexport type AuthStartResponse = {\n authUrl: string;\n message?: string;\n};\n\nexport type AuthCodeResponse = {\n message?: string;\n};\n\nexport type AuthWaitResponse = {\n connected: boolean;\n email?: string;\n message?: string;\n};\n\nexport type RefreshTokenImportState = {\n authRefreshTokenInput: string;\n authRefreshTokenBusy: boolean;\n authRefreshTokenError: string | null;\n authConnected: boolean | null;\n authMessage: string | null;\n authExpiresIn: number | null;\n authRefreshToken: string | null;\n claudeAuthModalOpen: boolean;\n client: GatewayBrowserClient | null;\n};\n\n/**\n * Import a refresh token from another device\n */\nexport async function importRefreshToken(state: RefreshTokenImportState): Promise<void> {\n if (!state.client) return;\n const token = state.authRefreshTokenInput.trim();\n if (!token) return;\n\n state.authRefreshTokenBusy = true;\n state.authRefreshTokenError = null;\n\n try {\n const res = (await state.client.request(\"auth.importRefreshToken\", {\n refreshToken: token,\n })) as AuthStatusResponse;\n\n state.authConnected = res.connected;\n state.authExpiresIn = res.expiresIn ?? null;\n state.authMessage = res.message ?? null;\n state.authRefreshToken = token;\n state.authRefreshTokenInput = \"\";\n state.claudeAuthModalOpen = false;\n } catch (err) {\n state.authRefreshTokenError = err instanceof Error ? err.message : \"Failed to import token\";\n } finally {\n state.authRefreshTokenBusy = false;\n }\n}\n\n/**\n * Check current auth status\n */\nexport async function checkAuthStatus(state: AuthState): Promise<void> {\n if (!state.client) return;\n\n state.authBusy = true;\n state.authMessage = null;\n\n try {\n const res = (await state.client.request(\"auth.status\", {})) as AuthStatusResponse;\n\n state.authConnected = res.connected;\n state.authExpiresIn = res.expiresIn ?? null;\n state.authMessage = res.message ?? null;\n state.authRefreshToken = res.refreshToken ?? null;\n\n // Auth status populates dashboard state only — no navigation side-effect.\n // The dashboard is reached directly from the license step.\n } catch (err) {\n state.authConnected = false;\n state.authMessage = err instanceof Error ? err.message : \"Failed to check auth status\";\n } finally {\n state.authBusy = false;\n }\n}\n\n/**\n * Start OAuth flow\n */\nexport async function startAuth(state: AuthState): Promise<void> {\n if (!state.client) return;\n\n state.authBusy = true;\n state.authMessage = null;\n state.authUrl = null;\n state.authConnected = null;\n\n try {\n const res = (await state.client.request(\"auth.oauth.start\", {\n provider: \"anthropic\",\n })) as AuthStartResponse;\n\n state.authUrl = res.authUrl;\n state.authMessage = res.message ?? \"Sign in with your Claude Pro account\";\n } catch (err) {\n state.authConnected = false;\n state.authMessage = err instanceof Error ? err.message : \"Failed to start auth flow\";\n } finally {\n state.authBusy = false;\n }\n}\n\n/**\n * Submit authorization code\n */\nexport async function submitAuthCode(state: AuthState, code: string): Promise<void> {\n if (!state.client) return;\n\n state.authBusy = true;\n state.authMessage = \"Verifying code...\";\n\n try {\n // Submit the code\n await state.client.request(\"auth.oauth.code\", { code });\n\n // Wait for completion\n const res = (await state.client.request(\"auth.oauth.wait\", {\n timeoutMs: 30000,\n })) as AuthWaitResponse;\n\n if (res.connected) {\n state.authConnected = true;\n state.authMessage = res.message ?? \"Connected to Claude!\";\n state.authUrl = null;\n state.authCodeInput = \"\";\n // Stay on auth step — success screen shows \"Continue to Chat\".\n } else {\n state.authMessage = res.message ?? \"Still waiting for authorization...\";\n }\n } catch (err) {\n state.authConnected = false;\n state.authMessage = err instanceof Error ? err.message : \"Verification failed\";\n } finally {\n state.authBusy = false;\n }\n}\n\n/**\n * Update code input\n */\nexport function updateAuthCodeInput(state: AuthState, code: string): void {\n state.authCodeInput = code;\n}\n\n/**\n * Initialize auth state\n */\nexport function initAuthState(): Partial<AuthState> {\n return {\n authConnected: null,\n authBusy: false,\n authMessage: null,\n authUrl: null,\n authCodeInput: \"\",\n authExpiresIn: null,\n authRefreshToken: null,\n setupStep: \"license\",\n };\n}\n","/**\n * License controller for setup flow\n *\n * Handles license key activation via the Setup UI.\n */\n\nimport type { GatewayBrowserClient } from \"../gateway\";\n\nexport type LicenseState = {\n licenseKey: string;\n licenseBusy: boolean;\n licenseValid: boolean | null;\n licenseMessage: string | null;\n licenseTier: string | null;\n licenseDeviceId: string | null;\n licenseStoredKey: string | null;\n setupStep: \"license\" | \"auth\" | \"setup\";\n client: GatewayBrowserClient | null;\n};\n\nexport type LicenseStatusResponse = {\n licensed: boolean;\n deviceId?: string;\n tier?: string;\n expiresAt?: string;\n key?: string;\n};\n\nexport type LicenseActivateResponse = {\n valid: boolean;\n message?: string;\n tier?: string;\n expiresAt?: string;\n};\n\n/**\n * Check current license status.\n * If already licensed, skip to the setup dashboard.\n */\nexport async function checkLicenseStatus(state: LicenseState): Promise<void> {\n if (!state.client) return;\n\n state.licenseBusy = true;\n state.licenseMessage = null;\n\n try {\n const res = (await state.client.request(\"license.status\", {})) as LicenseStatusResponse;\n\n state.licenseDeviceId = res.deviceId ?? null;\n state.licenseStoredKey = res.key ?? null;\n\n if (res.licensed) {\n state.licenseValid = true;\n state.licenseTier = res.tier ?? null;\n state.setupStep = \"setup\";\n } else {\n state.licenseValid = null;\n state.setupStep = \"license\";\n }\n } catch (err) {\n // If the method is unknown (older gateway), skip the license step\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes(\"unknown method\")) {\n state.licenseValid = true;\n state.setupStep = \"setup\";\n } else {\n state.licenseValid = null;\n state.licenseMessage = msg;\n state.setupStep = \"license\";\n }\n } finally {\n state.licenseBusy = false;\n }\n}\n\n/**\n * Activate a license key via the gateway.\n */\nexport async function activateLicense(state: LicenseState): Promise<void> {\n if (!state.client) return;\n if (!state.licenseKey.trim()) return;\n\n state.licenseBusy = true;\n state.licenseMessage = null;\n state.licenseValid = null;\n\n try {\n const res = (await state.client.request(\"license.activate\", {\n key: state.licenseKey.trim(),\n })) as LicenseActivateResponse;\n\n if (res.valid) {\n state.licenseValid = true;\n state.licenseMessage = res.message ?? \"License activated\";\n state.licenseTier = res.tier ?? null;\n // Move to setup dashboard after a brief delay\n setTimeout(() => {\n state.setupStep = \"setup\";\n }, 1500);\n } else {\n state.licenseValid = false;\n state.licenseMessage = res.message ?? \"Invalid license key\";\n }\n } catch (err) {\n state.licenseValid = false;\n state.licenseMessage = err instanceof Error ? err.message : \"Activation failed\";\n } finally {\n state.licenseBusy = false;\n }\n}\n\n/**\n * Remove the stored license. Drops back to the license step.\n */\nexport async function removeLicense(state: LicenseState): Promise<void> {\n if (!state.client) return;\n\n state.licenseBusy = true;\n try {\n await state.client.request(\"license.remove\", {});\n state.licenseValid = null;\n state.licenseKey = \"\";\n state.licenseTier = null;\n state.licenseMessage = null;\n state.setupStep = \"license\";\n } catch (err) {\n state.licenseMessage = err instanceof Error ? err.message : \"Failed to remove license\";\n } finally {\n state.licenseBusy = false;\n }\n}\n\n/**\n * Update the license key input.\n */\nexport function updateLicenseKey(state: LicenseState, key: string): void {\n state.licenseKey = key;\n}\n\n/**\n * Initialize license state.\n */\nexport function initLicenseState(): Partial<LicenseState> {\n return {\n licenseKey: \"\",\n licenseBusy: false,\n licenseValid: null,\n licenseMessage: null,\n licenseTier: null,\n licenseDeviceId: null,\n licenseStoredKey: null,\n setupStep: \"license\",\n };\n}\n","/**\n * Gateway status and restart controller for setup page\n */\n\nexport interface GatewayState {\n client: { request: (method: string, params: unknown) => Promise<unknown> } | null;\n connected: boolean;\n gatewayHealthy: boolean | null;\n gatewayHealthLoading: boolean;\n gatewayHealthMessage: string | null;\n gatewayRestartBusy: boolean;\n requestUpdate?: () => void;\n}\n\ninterface HealthResponse {\n ok: boolean;\n durationMs?: number;\n}\n\ninterface RestartResponse {\n ok: boolean;\n restart?: {\n ok: boolean;\n delayMs?: number;\n };\n}\n\nexport async function loadGatewayHealth(state: GatewayState): Promise<void> {\n if (!state.client || !state.connected) return;\n if (state.gatewayHealthLoading) return;\n\n state.gatewayHealthLoading = true;\n state.requestUpdate?.();\n\n try {\n const res = (await state.client.request(\"health\", {\n probe: true,\n })) as HealthResponse;\n\n state.gatewayHealthy = res.ok === true;\n state.gatewayHealthMessage = res.ok\n ? `Healthy${res.durationMs ? ` (${res.durationMs}ms)` : \"\"}`\n : \"Unhealthy\";\n } catch (err) {\n state.gatewayHealthy = false;\n state.gatewayHealthMessage = `Error: ${String(err)}`;\n } finally {\n state.gatewayHealthLoading = false;\n state.requestUpdate?.();\n }\n}\n\nexport async function restartGateway(state: GatewayState): Promise<void> {\n if (!state.client || state.gatewayRestartBusy) return;\n\n state.gatewayRestartBusy = true;\n state.gatewayHealthMessage = \"Restarting...\";\n state.requestUpdate?.();\n\n try {\n const res = (await state.client.request(\"gateway.restart\", {\n reason: \"Manual restart from setup page\",\n delayMs: 1000,\n })) as RestartResponse;\n\n if (res.ok && res.restart?.ok) {\n state.gatewayHealthMessage = \"Restarting...\";\n // The gateway will restart and we'll lose connection\n // Wait a bit then reload the page\n setTimeout(() => {\n window.location.reload();\n }, 3000);\n } else {\n throw new Error(\"Restart not scheduled\");\n }\n } catch (err) {\n state.gatewayHealthMessage = `Restart failed: ${String(err)}`;\n state.gatewayRestartBusy = false;\n state.requestUpdate?.();\n }\n}\n","import { LitElement, html, nothing } from \"lit\";\nimport { customElement, state } from \"lit/decorators.js\";\n\nimport type { GatewayBrowserClient, GatewayHelloOk } from \"./gateway\";\nimport { resolveInjectedAssistantIdentity } from \"./assistant-identity\";\nimport { applyWorkspaceBrand } from \"./brand\";\nimport { loadSettings, setActiveWorkspace, saveDraft, loadDraft, clearDraft, flushDraftSave, type UiSettings } from \"./storage\";\nimport { renderApp } from \"./app-render\";\nimport { renderAuditModal } from \"./views/audit-modal\";\nimport type { Tab } from \"./navigation\";\nimport type { ResolvedTheme, ThemeMode } from \"./theme\";\nimport type {\n AgentsListResult,\n ConfigSnapshot,\n ConfigUiHints,\n CronJob,\n CronRunLogEntry,\n CronStatus,\n HealthSnapshot,\n LogEntry,\n LogLevel,\n PresenceEntry,\n ChannelsStatusSnapshot,\n SessionsListResult,\n SessionTranscriptEntry,\n SessionLogType,\n SkillStatusReport,\n StatusSummary,\n NostrProfile,\n} from \"./types\";\nimport { type ChatAttachment, type ChatQueueItem, type CronFormState } from \"./ui-types\";\nimport type { AppViewState } from \"./app-view-state\";\nimport type { EventLogEntry } from \"./app-events\";\nimport { DEFAULT_CRON_FORM, DEFAULT_LOG_LEVEL_FILTERS } from \"./app-defaults\";\nimport { defaultOpeningHoursForm as defaultOpeningHoursFormFn } from \"./controllers/opening-hours\";\nimport type {\n ExecApprovalsFile,\n ExecApprovalsSnapshot,\n} from \"./controllers/exec-approvals\";\nimport type { DevicePairingList } from \"./controllers/devices\";\nimport type { ExecApprovalRequest } from \"./controllers/exec-approval\";\nimport type { AdminPhoneEntry } from \"./types.admins\";\nimport {\n resetToolStream as resetToolStreamInternal,\n type ToolStreamEntry,\n} from \"./app-tool-stream\";\nimport {\n exportLogs as exportLogsInternal,\n exportSessionLogs as exportSessionLogsInternal,\n handleChatScroll as handleChatScrollInternal,\n handleLogsScroll as handleLogsScrollInternal,\n handleSessionLogsScroll as handleSessionLogsScrollInternal,\n resetChatScroll as resetChatScrollInternal,\n scheduleChatScroll as scheduleChatScrollInternal,\n captureScrollForPrepend,\n} from \"./app-scroll\";\nimport { connectGateway as connectGatewayInternal } from \"./app-gateway\";\nimport {\n handleConnected,\n handleDisconnected,\n handleFirstUpdated,\n handleUpdated,\n} from \"./app-lifecycle\";\nimport {\n applySettings as applySettingsInternal,\n loadCron as loadCronInternal,\n loadOverview as loadOverviewInternal,\n setTab as setTabInternal,\n setTheme as setThemeInternal,\n onPopState as onPopStateInternal,\n} from \"./app-settings\";\nimport {\n handleAbortChat as handleAbortChatInternal,\n handleSendChat as handleSendChatInternal,\n removeQueuedMessage as removeQueuedMessageInternal,\n} from \"./app-chat\";\nimport {\n handleChannelConfigReload as handleChannelConfigReloadInternal,\n handleChannelConfigSave as handleChannelConfigSaveInternal,\n handleNostrProfileCancel as handleNostrProfileCancelInternal,\n handleNostrProfileEdit as handleNostrProfileEditInternal,\n handleNostrProfileFieldChange as handleNostrProfileFieldChangeInternal,\n handleNostrProfileImport as handleNostrProfileImportInternal,\n handleNostrProfileSave as handleNostrProfileSaveInternal,\n handleNostrProfileToggleAdvanced as handleNostrProfileToggleAdvancedInternal,\n handleAddWhatsAppAccount as handleAddWhatsAppAccountInternal,\n handleRemoveWhatsAppAccount as handleRemoveWhatsAppAccountInternal,\n handleWhatsAppLogout as handleWhatsAppLogoutInternal,\n handleWhatsAppStart as handleWhatsAppStartInternal,\n handleWhatsAppWait as handleWhatsAppWaitInternal,\n} from \"./app-channels\";\nimport type { NostrProfileFormState } from \"./views/channels.nostr-profile-form\";\nimport { loadAssistantIdentity as loadAssistantIdentityInternal } from \"./controllers/assistant-identity\";\nimport {\n checkAuthStatus as checkAuthStatusInternal,\n startAuth as startAuthInternal,\n submitAuthCode as submitAuthCodeInternal,\n updateAuthCodeInput as updateAuthCodeInputInternal,\n importRefreshToken as importRefreshTokenInternal,\n} from \"./controllers/auth\";\nimport {\n checkLicenseStatus as checkLicenseStatusInternal,\n activateLicense as activateLicenseInternal,\n removeLicense as removeLicenseInternal,\n updateLicenseKey as updateLicenseKeyInternal,\n} from \"./controllers/license\";\nimport {\n loadGatewayHealth as loadGatewayHealthInternal,\n restartGateway as restartGatewayInternal,\n} from \"./controllers/gateway\";\nimport {\n checkForUpdates as checkForUpdatesInternal,\n runUpdate as runUpdateInternal,\n handleUpdateProgress as handleUpdateProgressInternal,\n fetchLastUpdateResult as fetchLastUpdateResultInternal,\n dismissUpdateResult as dismissUpdateResultInternal,\n type UpdateProgressStep,\n type UpdateLastResult,\n} from \"./controllers/update\";\nimport { loadFileTree as loadFileTreeInternal, loadMemoryStatus as loadMemoryStatusInternal } from \"./controllers/files\";\nimport { loadAuditEntries as loadAuditEntriesInternal, clearAudit as clearAuditInternal, type AuditEntry } from \"./controllers/audit\";\nimport {\n type AccessState,\n DEFAULT_ACCESS_STATE,\n checkAccessStatus as checkAccessStatusInternal,\n verifyPin as verifyPinInternal,\n setMasterPin as setMasterPinInternal,\n logout as logoutInternal,\n} from \"./controllers/access\";\n\ndeclare global {\n interface Window {\n __TASKMASTER_CONTROL_UI_BASE_PATH__?: string;\n __TASKMASTER_PUBLIC_CHAT__?: boolean;\n __TASKMASTER_PUBLIC_CHAT_CONFIG__?: { accountId?: string; auth?: string; cookieTtlDays?: number; otpChannels?: string[]; verifyMethods?: string[] };\n }\n}\n\nconst injectedAssistantIdentity = resolveInjectedAssistantIdentity();\n\nfunction resolveOnboardingMode(): boolean {\n if (!window.location.search) return false;\n const params = new URLSearchParams(window.location.search);\n const raw = params.get(\"onboarding\");\n if (!raw) return false;\n const normalized = raw.trim().toLowerCase();\n return normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nfunction resolveSetupMode(): boolean {\n // Check for /setup path\n const pathname = window.location.pathname;\n if (pathname === \"/setup\" || pathname.endsWith(\"/setup\")) {\n return true;\n }\n // Check for ?setup= query parameter\n if (!window.location.search) return false;\n const params = new URLSearchParams(window.location.search);\n const raw = params.get(\"setup\");\n if (!raw) return false;\n const normalized = raw.trim().toLowerCase();\n return normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\nfunction resolveFilesPageMode(): boolean {\n const pathname = window.location.pathname;\n return pathname === \"/files\" || pathname.endsWith(\"/files\");\n}\n\nfunction resolveBrowserPageMode(): boolean {\n const pathname = window.location.pathname;\n return pathname === \"/browser\" || pathname.endsWith(\"/browser\");\n}\n\nfunction resolveAdminsPageMode(): boolean {\n const pathname = window.location.pathname;\n return pathname === \"/admins\" || pathname.endsWith(\"/admins\");\n}\n\nfunction resolveContactsPageMode(): boolean {\n const pathname = window.location.pathname;\n return pathname === \"/contacts\" || pathname.endsWith(\"/contacts\");\n}\n\nfunction resolveChatPageMode(): boolean {\n const pathname = window.location.pathname;\n return pathname === \"/chat\" || pathname.endsWith(\"/chat\");\n}\n\nfunction resolveAdvancedPageMode(): boolean {\n const pathname = window.location.pathname;\n return pathname === \"/advanced\" || pathname.endsWith(\"/advanced\");\n}\n\n@customElement(\"taskmaster-app\")\nexport class TaskmasterApp extends LitElement {\n @state() settings: UiSettings = loadSettings();\n @state() password = \"\";\n @state() tab: Tab = \"chat\";\n @state() onboarding = resolveOnboardingMode();\n @state() setup = resolveSetupMode();\n @state() filesPage = resolveFilesPageMode();\n @state() browserPage = resolveBrowserPageMode();\n @state() adminsPage = resolveAdminsPageMode();\n @state() contactsPage = resolveContactsPageMode();\n @state() chatPage = resolveChatPageMode();\n @state() advancedPage = resolveAdvancedPageMode();\n @state() advancedTab: \"cron\" | \"skills\" | \"logs\" | \"opening-hours\" = \"cron\";\n // Public chat mode — set by injected window globals at /public/chat\n @state() publicChat = Boolean(window.__TASKMASTER_PUBLIC_CHAT__);\n @state() publicChatConfig = window.__TASKMASTER_PUBLIC_CHAT_CONFIG__ ?? {};\n @state() publicChatSessionKey: string | null = null;\n @state() publicChatAuthenticated = false;\n @state() publicChatAuthStep: \"idle\" | \"phone\" | \"email\" | \"otp\" | \"ready\" = \"idle\";\n @state() connected = false;\n @state() accessState: AccessState = DEFAULT_ACCESS_STATE;\n @state() theme: ThemeMode = this.settings.theme ?? \"system\";\n @state() themeResolved: ResolvedTheme = \"dark\";\n @state() hello: GatewayHelloOk | null = null;\n @state() lastError: string | null = null;\n @state() eventLog: EventLogEntry[] = [];\n private eventLogBuffer: EventLogEntry[] = [];\n private toolStreamSyncTimer: number | null = null;\n private sidebarCloseTimer: number | null = null;\n\n @state() assistantName = injectedAssistantIdentity.name;\n @state() assistantAvatar = injectedAssistantIdentity.avatar;\n @state() assistantAgentId = injectedAssistantIdentity.agentId ?? null;\n\n @state() sessionKey = this.settings.sessionKey;\n @state() chatLoading = false;\n @state() chatSending = false;\n @state() chatMessage = \"\";\n @state() chatMessages: unknown[] = [];\n @state() chatHistoryTotal = 0;\n @state() chatHistoryHasMore = false;\n @state() chatLoadingOlder = false;\n @state() chatToolMessages: unknown[] = [];\n @state() chatStream: string | null = null;\n @state() chatInterimText: string | null = null;\n @state() chatSuggestions: string[] = [];\n @state() chatStreamStartedAt: number | null = null;\n @state() chatRunId: string | null = null;\n @state() compactionStatus: import(\"./app-tool-stream\").CompactionStatus | null = null;\n @state() chatAvatarUrl: string | null = null;\n @state() chatModelCatalog: Array<{ id: string; name: string; provider: string; reasoning?: boolean }> = [];\n @state() chatVerboseLevel: string | null = null;\n @state() chatQueue: ChatQueueItem[] = [];\n @state() chatAttachments: ChatAttachment[] = [];\n // Sidebar state for tool output viewing\n @state() sidebarOpen = false;\n @state() sidebarContent: string | null = null;\n @state() sidebarError: string | null = null;\n @state() splitRatio = this.settings.splitRatio;\n\n @state() nodesLoading = false;\n @state() nodes: Array<Record<string, unknown>> = [];\n @state() devicesLoading = false;\n @state() devicesError: string | null = null;\n @state() devicesList: DevicePairingList | null = null;\n @state() execApprovalsLoading = false;\n @state() execApprovalsSaving = false;\n @state() execApprovalsDirty = false;\n @state() execApprovalsSnapshot: ExecApprovalsSnapshot | null = null;\n @state() execApprovalsForm: ExecApprovalsFile | null = null;\n @state() execApprovalsSelectedAgent: string | null = null;\n @state() execApprovalsTarget: \"gateway\" | \"node\" = \"gateway\";\n @state() execApprovalsTargetNodeId: string | null = null;\n @state() execApprovalQueue: ExecApprovalRequest[] = [];\n @state() execApprovalBusy = false;\n @state() execApprovalError: string | null = null;\n\n @state() configLoading = false;\n @state() configRaw = \"{\\n}\\n\";\n @state() configRawOriginal = \"\";\n @state() configValid: boolean | null = null;\n @state() configIssues: unknown[] = [];\n @state() configSaving = false;\n @state() configApplying = false;\n @state() updateRunning = false;\n @state() applySessionKey = this.settings.lastActiveSessionKey;\n @state() configSnapshot: ConfigSnapshot | null = null;\n @state() configSchema: unknown | null = null;\n @state() configSchemaVersion: string | null = null;\n @state() configSchemaLoading = false;\n @state() configUiHints: ConfigUiHints = {};\n @state() configForm: Record<string, unknown> | null = null;\n @state() configFormOriginal: Record<string, unknown> | null = null;\n @state() configFormDirty = false;\n @state() configFormMode: \"form\" | \"raw\" = \"form\";\n @state() configSearchQuery = \"\";\n @state() configActiveSection: string | null = null;\n @state() configActiveSubsection: string | null = null;\n\n @state() channelsLoading = false;\n @state() channelsSnapshot: ChannelsStatusSnapshot | null = null;\n @state() channelsError: string | null = null;\n @state() channelsLastSuccess: number | null = null;\n @state() whatsappLoginMessage: string | null = null;\n @state() whatsappLoginQrDataUrl: string | null = null;\n @state() whatsappLoginConnected: boolean | null = null;\n @state() whatsappBusy = false;\n @state() whatsappActiveQrAccountId: string | null = null;\n @state() whatsappPairedPhone: string | null = null;\n @state() addingWhatsAppAccount = false;\n @state() newWhatsAppAccountName = \"\";\n @state() whatsappAccountError: string | null = null;\n @state() whatsappAccountSaving = false;\n @state() whatsappSettingsOpen = false;\n @state() publicChatToggleBusy = false;\n @state() publicChatGreetingBusy = false;\n @state() publicChatEmailBusy = false;\n @state() publicChatSettingsOpen = false;\n @state() publicChatWidgetModalOpen = false;\n // Branding\n @state() brandingBusy = false;\n @state() agentSettingsOpen = false;\n @state() brandingExpanded = false;\n // Tailscale / Remote Access\n @state() tailscaleStatus: AppViewState[\"tailscaleStatus\"] = null;\n @state() tailscaleBusy = false;\n @state() tailscaleAuthUrl: string | null = null;\n @state() tailscaleError: string | null = null;\n @state() tailscaleServeEnableUrl: string | null = null;\n @state() tailscaleFunnelEnableUrl: string | null = null;\n @state() tailscaleDisableConfirm = false;\n @state() tailscaleConnectProgress = 0;\n @state() tailscaleConnectMessage = \"\";\n @state() tailscaleConnectSuccess = false;\n // WiFi management (Linux only)\n @state() wifiStatus: AppViewState[\"wifiStatus\"] = null;\n @state() wifiNetworks: AppViewState[\"wifiNetworks\"] = [];\n @state() wifiBusy = false;\n @state() wifiError: string | null = null;\n @state() wifiPassword = \"\";\n @state() wifiSelectedSsid: string | null = null;\n // Network settings (port + hostname)\n @state() networkPort: AppViewState[\"networkPort\"] = null;\n @state() networkHostname = \"\";\n @state() networkPortInput = \"\";\n @state() networkHostnameInput = \"\";\n @state() networkModalOpen = false;\n @state() networkBusy = false;\n @state() networkError: string | null = null;\n @state() networkSuccess: string | null = null;\n // WiFi modal\n @state() wifiModalOpen = false;\n // License state for setup flow\n @state() licenseKey = \"\";\n @state() licenseBusy = false;\n @state() licenseValid: boolean | null = null;\n @state() licenseMessage: string | null = null;\n @state() licenseTier: string | null = null;\n @state() licenseDeviceId: string | null = null;\n @state() licenseStoredKey: string | null = null;\n @state() licenseRemoveConfirm = false;\n // Auth state for setup flow\n @state() authConnected: boolean | null = null;\n @state() authBusy = false;\n @state() authMessage: string | null = null;\n @state() authUrl: string | null = null;\n @state() authCodeInput = \"\";\n @state() authExpiresIn: number | null = null;\n @state() authRefreshToken: string | null = null;\n @state() claudeAuthModalOpen = false;\n @state() authRefreshTokenInput = \"\";\n @state() authRefreshTokenBusy = false;\n @state() authRefreshTokenError: string | null = null;\n @state() setupStep: \"license\" | \"auth\" | \"setup\" = \"license\";\n // Gateway status for setup page\n @state() gatewayHealthy: boolean | null = null;\n @state() gatewayHealthLoading = false;\n @state() gatewayHealthMessage: string | null = null;\n @state() gatewayRestartBusy = false;\n // Software update state\n @state() updateAvailable: boolean | null = null;\n @state() currentVersion: string | null = null;\n @state() latestVersion: string | null = null;\n @state() updateChecking = false;\n // updateRunning is declared above (shared with config controller)\n @state() updateMessage: string | null = null;\n @state() updateProgressSteps: UpdateProgressStep[] = [];\n @state() updateLastResult: UpdateLastResult | null = null;\n // Uninstall state\n @state() uninstallConfirm = false;\n @state() uninstallBusy = false;\n @state() uninstallDone = false;\n @state() uninstallError: string | null = null;\n @state() uninstallConfirmText = \"\";\n @state() nostrProfileFormState: NostrProfileFormState | null = null;\n @state() nostrProfileAccountId: string | null = null;\n\n @state() presenceLoading = false;\n @state() presenceEntries: PresenceEntry[] = [];\n @state() presenceError: string | null = null;\n @state() presenceStatus: string | null = null;\n\n @state() agentsLoading = false;\n @state() agentsList: AgentsListResult | null = null;\n @state() agentsError: string | null = null;\n\n @state() sessionsLoading = false;\n @state() sessionsResult: SessionsListResult | null = null;\n @state() sessionsError: string | null = null;\n\n @state() cronLoading = false;\n @state() cronJobs: CronJob[] = [];\n @state() cronStatus: CronStatus | null = null;\n @state() cronError: string | null = null;\n @state() cronForm: CronFormState = { ...DEFAULT_CRON_FORM };\n @state() cronRunsJobId: string | null = null;\n @state() cronRuns: CronRunLogEntry[] = [];\n @state() cronBusy = false;\n @state() cronNewEventModal = false;\n @state() cronDetailJobId: string | null = null;\n @state() cronEditJobId: string | null = null;\n @state() cronPendingDeleteId: string | null = null;\n @state() cronRunModalJobId: string | null = null;\n @state() cronRunModalJobName = \"\";\n @state() cronRunResult: { status: string; durationMs?: number; summary?: string; error?: string } | null = null;\n workspaceAgentIds?: string[];\n accountId?: string;\n\n @state() openingHoursLoading = false;\n @state() openingHoursError: string | null = null;\n @state() openingHoursBusy = false;\n @state() openingHoursForm = defaultOpeningHoursFormFn();\n\n @state() browserScreencastActive = false;\n @state() browserScreencastFrame: string | null = null;\n @state() browserScreencastMetadata: { deviceWidth?: number; deviceHeight?: number } | null = null;\n @state() browserHandoffPending = false;\n @state() browserHandoffReason: string | null = null;\n @state() browserHandoffId: string | null = null;\n @state() browserInputMode = false;\n @state() browserFullscreen = false;\n @state() browserLoading = false;\n @state() browserError: string | null = null;\n\n @state() filesLoading = false;\n @state() filesTree: Array<import(\"./controllers/files\").FileTreeEntry> = [];\n @state() filesRoot = \"\";\n @state() filesError: string | null = null;\n @state() filesSelectedPath: string | null = null;\n @state() filesSelectedPaths: Set<string> = new Set();\n @state() filesPreviewContent: string | null = null;\n @state() filesPreviewLoading = false;\n @state() filesPreviewBinary = false;\n @state() filesPreviewSize: number | null = null;\n @state() filesExpandedDirs: Set<string> = new Set();\n @state() filesCurrentDir = \".\";\n @state() filesPendingDeletePath: string | null = null;\n @state() filesMessage: { kind: \"success\" | \"error\"; text: string } | null = null;\n @state() filesUploadBusy = false;\n @state() filesReindexBusy = false;\n @state() filesMemoryStatus: { dirty: boolean; files: number; chunks: number; model?: string; embeddingState?: \"idle\" | \"downloading\" | \"ready\" | \"error\" } | null = null;\n // Embedding model download overlay — blocks all navigation while model downloads\n @state() embeddingDownloading = false;\n private embeddingPollTimer: number | null = null;\n @state() filesSearchQuery = \"\";\n @state() filesSearchResults: Array<import(\"./controllers/files\").MemorySearchHit> | null = null;\n @state() filesSearchLoading = false;\n @state() filesSearchAgentId: string | null = null;\n /** Resolved agent ID used for file tree, memory status, and reindex. Set by handleFilesLoad. */\n filesResolvedAgentId: string | undefined = undefined;\n\n // Memory write audit\n @state() auditEntries: AuditEntry[] = [];\n @state() auditLoading = false;\n @state() auditModalOpen = false;\n\n @state() skillsLoading = false;\n @state() skillsReport: SkillStatusReport | null = null;\n @state() skillsError: string | null = null;\n @state() skillsFilter = \"\";\n @state() skillsTypeFilter: \"all\" | \"preloaded\" | \"user\" = \"all\";\n @state() skillsAgentFilter: \"all\" | \"admin\" | \"public\" = \"all\";\n @state() skillEdits: Record<string, string> = {};\n @state() skillsBusyKey: string | null = null;\n @state() skillMessages: Record<string, SkillMessage> = {};\n @state() skillDetail: import(\"./controllers/skills\").SkillDetailData | null = null;\n @state() skillDetailTab = \"\";\n @state() skillAddModal = false;\n @state() skillAddForm: import(\"./controllers/skills\").AddSkillForm = { name: \"\", skillContent: \"\", references: [] };\n @state() skillAddFormSource: import(\"./controllers/skills\").SkillFormSource = \"draft\";\n @state() skillEditTab = \"SKILL.md\";\n @state() skillDrafts: import(\"./controllers/skills\").SkillDraft[] = [];\n\n @state() adminsLoading = false;\n @state() adminPhones: AdminPhoneEntry[] = [];\n @state() adminsError: string | null = null;\n @state() adminsSaving = false;\n @state() adminsNewPhone = \"\";\n\n @state() contactsLoading = false;\n @state() contactsSaving = false;\n @state() contactsRecords: Array<import(\"./controllers/contacts\").ContactRecord> = [];\n @state() contactsError: string | null = null;\n @state() contactsSearchQuery = \"\";\n @state() contactsEditingId: string | null = null;\n @state() contactsShowAddForm = false;\n @state() contactsNewPhone = \"\";\n @state() contactsNewName = \"\";\n @state() contactsDeleteConfirmId: string | null = null;\n @state() contactsAddFieldForId: string | null = null;\n @state() contactsAddFieldKey = \"\";\n @state() contactsAddFieldValue = \"\";\n\n // Workspaces state\n // iMessage UI state\n @state() imessageEnableConfirm = false;\n @state() imessageEnabling = false;\n // WhatsApp conversation browser tab\n @state() chatPageTab: \"chat\" | \"whatsapp\" = \"chat\";\n @state() waConversations: import(\"./controllers/whatsapp\").WhatsAppConversation[] = [];\n @state() waSelectedJid: string | null = null;\n @state() waMessages: import(\"./controllers/whatsapp\").WhatsAppMessage[] = [];\n @state() waGroupInfo: import(\"./controllers/whatsapp\").WhatsAppGroupInfo | null = null;\n @state() waLoading = false;\n @state() waMessagesLoading = false;\n @state() waSearchQuery = \"\";\n @state() waComposeDraft = \"\";\n @state() waSending = false;\n @state() waLastError: string | null = null;\n // Info modal\n @state() infoModalOpen: string | null = null;\n @state() remoteAccessQrDataUrl: string | null = null;\n @state() publicChatQrDataUrl: string | null = null;\n\n @state() workspaces: import(\"./controllers/workspaces\").WorkspaceInfo[] = [];\n @state() workspacesLoading = false;\n @state() workspacesError: string | null = null;\n @state() selectedWorkspace: string | null = null;\n @state() addingWorkspace = false;\n @state() newWorkspaceName = \"\";\n @state() newWorkspacePath = \"\";\n @state() newWorkspacePin = \"\";\n @state() accountPinModalOpen = false;\n @state() accountPinBusy = false;\n @state() accountPinError: string | null = null;\n @state() accountPinSuccess: string | null = null;\n // API Keys management\n @state() apiKeyProviders: import(\"./controllers/apikeys\").ApiKeyProvider[] = [];\n @state() apiKeyModalOpen = false;\n @state() apiKeyBusy = false;\n @state() apiKeyError: string | null = null;\n @state() apiKeySuccess: string | null = null;\n @state() apiKeySavingProvider: string | null = null;\n @state() authApiKeyMode = false;\n @state() authApiKeyInput = \"\";\n @state() authApiKeyBusy = false;\n @state() authApiKeyError: string | null = null;\n @state() pinChanging: \"master\" | \"account\" | null = null;\n @state() pinChangeBusy = false;\n @state() pinChangeError: string | null = null;\n @state() loginChangePinMode = false;\n @state() changePinBusy = false;\n @state() changePinError: string | null = null;\n @state() changePinSuccess: string | null = null;\n @state() workspaceSaving = false;\n @state() workspaceRemoveConfirm: string | null = null;\n @state() renamingWorkspace = false;\n @state() renameWorkspaceName = \"\";\n\n @state() debugLoading = false;\n @state() debugStatus: StatusSummary | null = null;\n @state() debugHealth: HealthSnapshot | null = null;\n @state() debugModels: unknown[] = [];\n @state() debugHeartbeat: unknown | null = null;\n @state() debugCallMethod = \"\";\n @state() debugCallParams = \"{}\";\n @state() debugCallResult: string | null = null;\n @state() debugCallError: string | null = null;\n\n @state() logsLoading = false;\n @state() logsError: string | null = null;\n @state() logsFile: string | null = null;\n @state() logsEntries: LogEntry[] = [];\n @state() logsFilterText = \"\";\n @state() logsLevelFilters: Record<LogLevel, boolean> = {\n ...DEFAULT_LOG_LEVEL_FILTERS,\n };\n @state() logsAutoFollow = true;\n @state() logsTruncated = false;\n @state() logsCursor: number | null = null;\n @state() logsLastFetchAt: number | null = null;\n @state() logsLimit = 500;\n @state() logsMaxBytes = 250_000;\n @state() logsAtBottom = true;\n @state() logsDate: string | null = null;\n @state() logsAvailableDates: string[] = [];\n\n @state() logsSubTab: \"system\" | \"session\" = \"session\";\n @state() logsChipsExpanded = false;\n @state() sessionLogsLoading = false;\n @state() sessionLogsError: string | null = null;\n @state() sessionLogsEntries: SessionTranscriptEntry[] = [];\n @state() sessionLogsFilterText = \"\";\n @state() sessionLogsTypeFilters: Record<SessionLogType, boolean> = {\n user: true,\n assistant: true,\n tool: true,\n tool_call: true,\n tool_result: true,\n thinking: true,\n error: true,\n system: true,\n };\n @state() sessionLogsAgentFilters: Record<string, boolean> = {};\n @state() sessionLogsAgents: string[] = [];\n @state() sessionLogsAutoFollow = true;\n @state() sessionLogsChipsExpanded = false;\n sessionLogsExpandedIds: Set<string> = new Set();\n @state() sessionLogsCursors: Record<string, number> = {};\n @state() sessionLogsLastFetchAt: number | null = null;\n @state() sessionLogsAtBottom = true;\n\n client: GatewayBrowserClient | null = null;\n private chatScrollFrame: number | null = null;\n private chatScrollTimeout: number | null = null;\n private chatHasAutoScrolled = false;\n @state() chatUserNearBottom = true;\n onLoadOlder: (() => void) | null = () => this.handleLoadOlderChat();\n private nodesPollInterval: number | null = null;\n private logsPollInterval: number | null = null;\n private sessionLogsPollInterval: number | null = null;\n private debugPollInterval: number | null = null;\n private auditPollInterval: number | null = null;\n private logsScrollFrame: number | null = null;\n private toolStreamById = new Map<string, ToolStreamEntry>();\n private toolStreamOrder: string[] = [];\n basePath = \"\";\n private popStateHandler = () =>\n onPopStateInternal(\n this as unknown as Parameters<typeof onPopStateInternal>[0],\n );\n private themeMedia: MediaQueryList | null = null;\n private themeMediaHandler: ((event: MediaQueryListEvent) => void) | null = null;\n private topbarObserver: ResizeObserver | null = null;\n\n createRenderRoot() {\n return this;\n }\n\n private _beforeUnloadHandler = () => {\n flushDraftSave();\n const ws = this.selectedWorkspace ?? (this as unknown as { publicChatConfig?: { accountId?: string } }).publicChatConfig?.accountId ?? \"\";\n if (ws) saveDraft(ws, this.sessionKey, this.chatMessage);\n };\n\n connectedCallback() {\n super.connectedCallback();\n handleConnected(this as unknown as Parameters<typeof handleConnected>[0]);\n window.addEventListener(\"beforeunload\", this._beforeUnloadHandler);\n }\n\n protected firstUpdated() {\n handleFirstUpdated(this as unknown as Parameters<typeof handleFirstUpdated>[0]);\n }\n\n disconnectedCallback() {\n window.removeEventListener(\"beforeunload\", this._beforeUnloadHandler);\n this.stopEmbeddingPoll();\n handleDisconnected(this as unknown as Parameters<typeof handleDisconnected>[0]);\n super.disconnectedCallback();\n }\n\n /** Poll memory.status for embedding download state. Blocks UI while downloading. */\n startEmbeddingPoll() {\n if (this.embeddingPollTimer != null) return;\n const poll = async () => {\n if (!this.client || !this.connected) return;\n try {\n const res = (await this.client.request(\"memory.status\", {})) as {\n ok?: boolean;\n embeddingState?: \"idle\" | \"downloading\" | \"ready\" | \"error\";\n } | undefined;\n const state = res?.embeddingState;\n if (state === \"downloading\") {\n this.embeddingDownloading = true;\n } else {\n // Download finished (or never started) — dismiss overlay and stop polling\n if (this.embeddingDownloading) {\n this.embeddingDownloading = false;\n }\n this.stopEmbeddingPoll();\n return;\n }\n } catch {\n // memory.status failed — stop polling, don't block UI\n this.embeddingDownloading = false;\n this.stopEmbeddingPoll();\n return;\n }\n // Continue polling every 3 seconds while downloading\n this.embeddingPollTimer = window.setTimeout(poll, 3000);\n };\n void poll();\n }\n\n stopEmbeddingPoll() {\n if (this.embeddingPollTimer != null) {\n window.clearTimeout(this.embeddingPollTimer);\n this.embeddingPollTimer = null;\n }\n }\n\n protected updated(changed: Map<PropertyKey, unknown>) {\n handleUpdated(\n this as unknown as Parameters<typeof handleUpdated>[0],\n changed,\n );\n }\n\n connect() {\n connectGatewayInternal(\n this as unknown as Parameters<typeof connectGatewayInternal>[0],\n );\n }\n\n handleChatScroll(event: Event) {\n handleChatScrollInternal(\n this as unknown as Parameters<typeof handleChatScrollInternal>[0],\n event,\n );\n }\n\n handleLogsScroll(event: Event) {\n handleLogsScrollInternal(\n this as unknown as Parameters<typeof handleLogsScrollInternal>[0],\n event,\n );\n }\n\n handleSessionLogsScroll(event: Event) {\n handleSessionLogsScrollInternal(\n this as unknown as Parameters<typeof handleSessionLogsScrollInternal>[0],\n event,\n );\n }\n\n exportLogs(lines: string[], label: string) {\n exportLogsInternal(lines, label);\n }\n\n exportSessionLogs(lines: string[], label: string) {\n exportSessionLogsInternal(lines, label);\n }\n\n resetToolStream() {\n resetToolStreamInternal(\n this as unknown as Parameters<typeof resetToolStreamInternal>[0],\n );\n }\n\n resetChatScroll() {\n resetChatScrollInternal(\n this as unknown as Parameters<typeof resetChatScrollInternal>[0],\n );\n }\n\n async loadAssistantIdentity() {\n await loadAssistantIdentityInternal(this);\n }\n\n applySettings(next: UiSettings) {\n applySettingsInternal(\n this as unknown as Parameters<typeof applySettingsInternal>[0],\n next,\n );\n }\n\n setTab(next: Tab) {\n setTabInternal(this as unknown as Parameters<typeof setTabInternal>[0], next);\n }\n\n setTheme(next: ThemeMode, context?: Parameters<typeof setThemeInternal>[2]) {\n setThemeInternal(\n this as unknown as Parameters<typeof setThemeInternal>[0],\n next,\n context,\n );\n }\n\n async loadOverview() {\n await loadOverviewInternal(\n this as unknown as Parameters<typeof loadOverviewInternal>[0],\n );\n }\n\n async loadCron() {\n const wsInfo = this.getSelectedWorkspaceInfo();\n this.workspaceAgentIds = wsInfo?.agents?.map((a) => a.id) ?? undefined;\n this.accountId = this.selectedWorkspace ?? undefined;\n this.cronForm = {\n ...this.cronForm,\n accountId: this.selectedWorkspace ?? undefined,\n };\n await loadCronInternal(\n this as unknown as Parameters<typeof loadCronInternal>[0],\n );\n }\n\n async handleAbortChat() {\n await handleAbortChatInternal(\n this as unknown as Parameters<typeof handleAbortChatInternal>[0],\n );\n }\n\n removeQueuedMessage(id: string) {\n removeQueuedMessageInternal(\n this as unknown as Parameters<typeof removeQueuedMessageInternal>[0],\n id,\n );\n }\n\n async handleSendChat(\n messageOverride?: string,\n opts?: Parameters<typeof handleSendChatInternal>[2],\n ) {\n await handleSendChatInternal(\n this as unknown as Parameters<typeof handleSendChatInternal>[0],\n messageOverride,\n opts,\n );\n }\n\n async handleWhatsAppStart(force: boolean, accountId?: string) {\n await handleWhatsAppStartInternal(this, force, accountId);\n }\n\n async handleWhatsAppWait(accountId?: string) {\n await handleWhatsAppWaitInternal(this, accountId);\n }\n\n async handleWhatsAppLogout(accountId?: string) {\n await handleWhatsAppLogoutInternal(this, accountId);\n }\n\n async handleAddWhatsAppAccount(name: string) {\n await handleAddWhatsAppAccountInternal(this, name);\n }\n\n async handleRemoveWhatsAppAccount(accountId: string) {\n await handleRemoveWhatsAppAccountInternal(this, accountId);\n }\n\n // Access (PIN) handlers\n async handleAccessCheck() {\n await checkAccessStatusInternal(this);\n }\n\n async handlePinSubmit(account: string, pin: string) {\n await verifyPinInternal(this, account, pin);\n // Auto-scope to workspace if this is an account-level PIN (not master)\n if (this.accessState.authenticated && this.accessState.workspace) {\n this.handleWorkspaceSelect(this.accessState.workspace);\n }\n }\n\n async handleSetMasterPin(pin: string) {\n await setMasterPinInternal(this, pin);\n }\n\n async handleLogout() {\n await logoutInternal(this);\n }\n\n toggleChangePinMode() {\n this.loginChangePinMode = !this.loginChangePinMode;\n this.changePinError = null;\n this.changePinSuccess = null;\n }\n\n async handleChangePin(account: string, oldPin: string, newPin: string) {\n if (!this.client) return;\n this.changePinBusy = true;\n this.changePinError = null;\n this.changePinSuccess = null;\n try {\n // Step 1: Verify the current PIN\n const verifyResult = (await this.client.request(\"access.verify\", { account, pin: oldPin })) as {\n ok: boolean;\n message?: string;\n };\n if (!verifyResult.ok) {\n this.changePinError = verifyResult.message ?? \"Incorrect current PIN\";\n this.changePinBusy = false;\n return;\n }\n // Step 2: Set the new PIN\n if (account === \"__master__\") {\n await this.client.request(\"access.setMasterPin\", { pin: newPin });\n } else {\n await this.client.request(\"access.setAccountPin\", { workspace: account, pin: newPin });\n }\n this.changePinSuccess = \"PIN changed successfully\";\n this.changePinBusy = false;\n // Return to login mode after a short delay\n setTimeout(() => {\n this.loginChangePinMode = false;\n this.changePinSuccess = null;\n }, 2000);\n } catch {\n this.changePinError = \"Failed to change PIN\";\n this.changePinBusy = false;\n }\n }\n\n async handleAccountPinSave(workspace: string, oldPin: string | null, newPin: string) {\n if (!this.client) return;\n this.accountPinBusy = true;\n this.accountPinError = null;\n this.accountPinSuccess = null;\n try {\n // If changing existing PIN, verify the old one first\n if (oldPin !== null) {\n const verifyResult = (await this.client.request(\"access.verify\", { account: workspace, pin: oldPin })) as {\n ok: boolean; message?: string;\n };\n if (!verifyResult.ok) {\n this.accountPinError = verifyResult.message ?? \"Incorrect current PIN\";\n this.accountPinBusy = false;\n return;\n }\n }\n // Set the new PIN\n await this.client.request(\"access.setAccountPin\", { workspace, pin: newPin });\n this.accountPinSuccess = \"PIN saved\";\n this.accountPinBusy = false;\n // Refresh access state so the accounts list updates\n await checkAccessStatusInternal(this);\n // Close modal after a short delay\n setTimeout(() => {\n this.accountPinModalOpen = false;\n this.accountPinSuccess = null;\n this.accountPinError = null;\n }, 1500);\n } catch {\n this.accountPinError = \"Failed to save PIN\";\n this.accountPinBusy = false;\n }\n }\n\n // License handlers for setup flow\n async handleLicenseStatusCheck() {\n await checkLicenseStatusInternal(this);\n }\n\n async handleLicenseActivate() {\n await activateLicenseInternal(this);\n }\n\n async handleLicenseRemove() {\n await removeLicenseInternal(this);\n }\n\n handleLicenseKeyChange(key: string) {\n updateLicenseKeyInternal(this, key);\n }\n\n // Auth handlers for setup flow\n async handleAuthStatusCheck() {\n await checkAuthStatusInternal(this);\n }\n\n async handleAuthStart() {\n await startAuthInternal(this);\n }\n\n async handleAuthSubmitCode(code: string) {\n await submitAuthCodeInternal(this, code);\n }\n\n handleAuthCodeChange(code: string) {\n updateAuthCodeInputInternal(this, code);\n }\n\n handleClaudeAuthModalOpen() {\n this.claudeAuthModalOpen = true;\n }\n\n handleClaudeAuthModalClose() {\n this.claudeAuthModalOpen = false;\n this.authUrl = null;\n this.authRefreshTokenInput = \"\";\n this.authRefreshTokenError = null;\n }\n\n async handleImportRefreshToken() {\n await importRefreshTokenInternal(this);\n }\n\n // Gateway handlers for setup page\n async handleGatewayHealthCheck() {\n await loadGatewayHealthInternal(this);\n }\n\n async handleGatewayRestart() {\n await restartGatewayInternal(this);\n }\n\n // Software update handlers for setup page\n async handleUpdateCheck() {\n await checkForUpdatesInternal(this);\n }\n\n async handleUpdateRun() {\n await runUpdateInternal(this);\n }\n\n handleUpdateDismissResult() {\n dismissUpdateResultInternal(this);\n }\n\n // Uninstall handlers for setup page\n handleUninstallConfirm() {\n this.uninstallConfirm = true;\n this.uninstallConfirmText = \"\";\n }\n\n handleUninstallCancel() {\n this.uninstallConfirm = false;\n this.uninstallConfirmText = \"\";\n this.uninstallError = null;\n }\n\n handleUninstallConfirmTextChange(text: string) {\n this.uninstallConfirmText = text;\n }\n\n async handleUninstallRun() {\n const { runUninstall } = await import(\"./controllers/uninstall.js\");\n await runUninstall(this);\n }\n\n handleUninstallDismiss() {\n import(\"./controllers/uninstall.js\").then(({ clearUninstallDone }) => {\n clearUninstallDone();\n });\n this.uninstallDone = false;\n this.uninstallConfirm = false;\n this.uninstallConfirmText = \"\";\n }\n\n // Memory write audit — loads on every page via header badge\n async loadAuditEntries() {\n await loadAuditEntriesInternal(this);\n }\n\n async clearAudit() {\n await clearAuditInternal(this);\n this.auditModalOpen = false;\n }\n\n // Files page: auto-load file tree on connect\n handleFilesLoad() {\n const wsInfo = this.getSelectedWorkspaceInfo();\n this.workspaceAgentIds = wsInfo?.agents?.map((a) => a.id) ?? undefined;\n const filesAgentId = this.resolveFilesAgentId();\n this.filesResolvedAgentId = filesAgentId;\n void loadFileTreeInternal(this, filesAgentId);\n void loadMemoryStatusInternal(this, filesAgentId);\n }\n\n // Admins page: auto-load admin phones on connect\n handleAdminsLoad() {\n const adminAgentId = this.resolveAdminAgentId();\n void import(\"./controllers/admins\").then(({ loadAdmins }) => {\n loadAdmins(this, adminAgentId);\n });\n }\n\n private resolveAdminAgentId(): string | undefined {\n const ws = this.getSelectedWorkspaceInfo();\n if (!ws) return undefined;\n const adminAgent = ws.agents.find((a) => a.id.endsWith(\"-admin\") || a.id === \"admin\");\n return adminAgent?.id;\n }\n\n private resolveFilesAgentId(): string | undefined {\n const ws = this.getSelectedWorkspaceInfo();\n if (!ws) return undefined;\n // Use the admin agent — it has the most complete workspace view\n // (all shared symlinks + its own physical admin/ memory folder).\n const adminAgent = ws.agents.find((a) => a.id.endsWith(\"-admin\") || a.id === \"admin\");\n return adminAgent?.id ?? ws.agents[0]?.id;\n }\n\n // Chat page: auto-load chat history on connect\n // Derives session key from the selected workspace's admin agent\n // so switching businesses in the header selector routes to the correct agent.\n handleChatLoad() {\n const adminAgentId = this.resolveAdminAgentId();\n if (adminAgentId) {\n const newSessionKey = `agent:${adminAgentId}:main`;\n if (newSessionKey !== this.sessionKey) {\n this.sessionKey = newSessionKey;\n this.chatMessages = [];\n this.chatStream = null;\n this.chatInterimText = null;\n this.chatRunId = null;\n this.chatSuggestions = [];\n // Reset scroll state so the new session gets a fresh forced scroll\n this.resetChatScroll();\n this.applySettings({\n ...this.settings,\n sessionKey: newSessionKey,\n lastActiveSessionKey: newSessionKey,\n });\n void this.loadAssistantIdentity();\n }\n }\n void import(\"./controllers/chat\").then(({ loadChatHistory }) => {\n void loadChatHistory(this).then(() => {\n // Direct scroll after messages load — independent of the handleUpdated\n // reactive pipeline which can miss due to overlapping load cycles\n scheduleChatScrollInternal(\n this as unknown as Parameters<typeof scheduleChatScrollInternal>[0],\n true,\n );\n });\n });\n }\n\n // Lazy-load older chat messages when user scrolls to top\n async handleLoadOlderChat() {\n if (this.chatLoadingOlder || !this.chatHistoryHasMore) return;\n const restoreScroll = captureScrollForPrepend(\n this as unknown as Parameters<typeof captureScrollForPrepend>[0],\n );\n const { loadOlderChatHistory } = await import(\"./controllers/chat\");\n const loaded = await loadOlderChatHistory(this);\n if (loaded && restoreScroll) {\n // Wait for Lit render, then restore scroll position\n await this.updateComplete;\n restoreScroll();\n }\n }\n\n // Advanced page: auto-load default tab data on connect\n handleAdvancedLoad() {\n const wsInfo = this.getSelectedWorkspaceInfo();\n this.workspaceAgentIds = wsInfo?.agents?.map((a) => a.id) ?? undefined;\n // Reset session logs — previous entries/cursors belong to the old account scope\n this.sessionLogsEntries = [];\n this.sessionLogsCursors = {};\n this.sessionLogsAgents = [];\n // Only load cron jobs if workspace is already selected — if selectedWorkspace is null,\n // workspaces haven't loaded yet and we'd fetch without an accountId filter, returning\n // all jobs across all accounts. initWorkspaceSelection() will call handleAdvancedLoad()\n // again once the workspace is known.\n if (this.advancedTab === \"cron\" && this.selectedWorkspace) void this.loadCron();\n if (this.advancedTab === \"opening-hours\") {\n void import(\"./controllers/opening-hours\").then(({ loadOpeningHours }) => {\n loadOpeningHours(this as unknown as Parameters<typeof loadOpeningHours>[0]);\n });\n }\n if (this.advancedTab === \"logs\") {\n if (this.logsSubTab === \"session\") {\n void import(\"./controllers/session-logs\").then(({ loadSessionLogs }) => {\n loadSessionLogs(this as unknown as Parameters<typeof loadSessionLogs>[0], { reset: true });\n });\n } else {\n void import(\"./controllers/logs\").then(({ loadLogs }) => {\n loadLogs(this, { reset: true });\n });\n }\n }\n if (this.advancedTab === \"skills\") {\n void import(\"./controllers/skills\").then(({ loadSkills }) => {\n loadSkills(this, { clearMessages: true });\n });\n }\n }\n\n async handleChannelConfigSave() {\n await handleChannelConfigSaveInternal(this);\n }\n\n async handleChannelConfigReload() {\n await handleChannelConfigReloadInternal(this);\n }\n\n handleNostrProfileEdit(accountId: string, profile: NostrProfile | null) {\n handleNostrProfileEditInternal(this, accountId, profile);\n }\n\n handleNostrProfileCancel() {\n handleNostrProfileCancelInternal(this);\n }\n\n handleNostrProfileFieldChange(field: keyof NostrProfile, value: string) {\n handleNostrProfileFieldChangeInternal(this, field, value);\n }\n\n async handleNostrProfileSave() {\n await handleNostrProfileSaveInternal(this);\n }\n\n async handleNostrProfileImport() {\n await handleNostrProfileImportInternal(this);\n }\n\n handleNostrProfileToggleAdvanced() {\n handleNostrProfileToggleAdvancedInternal(this);\n }\n\n async handleExecApprovalDecision(decision: \"allow-once\" | \"allow-always\" | \"deny\") {\n const active = this.execApprovalQueue[0];\n if (!active || !this.client || this.execApprovalBusy) return;\n this.execApprovalBusy = true;\n this.execApprovalError = null;\n try {\n await this.client.request(\"exec.approval.resolve\", {\n id: active.id,\n decision,\n });\n this.execApprovalQueue = this.execApprovalQueue.filter((entry) => entry.id !== active.id);\n } catch (err) {\n this.execApprovalError = `Exec approval failed: ${String(err)}`;\n } finally {\n this.execApprovalBusy = false;\n }\n }\n\n // Sidebar handlers for tool output viewing\n handleOpenSidebar(content: string) {\n if (this.sidebarCloseTimer != null) {\n window.clearTimeout(this.sidebarCloseTimer);\n this.sidebarCloseTimer = null;\n }\n this.sidebarContent = content;\n this.sidebarError = null;\n this.sidebarOpen = true;\n }\n\n handleCloseSidebar() {\n this.sidebarOpen = false;\n // Clear content after transition\n if (this.sidebarCloseTimer != null) {\n window.clearTimeout(this.sidebarCloseTimer);\n }\n this.sidebarCloseTimer = window.setTimeout(() => {\n if (this.sidebarOpen) return;\n this.sidebarContent = null;\n this.sidebarError = null;\n this.sidebarCloseTimer = null;\n }, 200);\n }\n\n handleSplitRatioChange(ratio: number) {\n const newRatio = Math.max(0.4, Math.min(0.7, ratio));\n this.splitRatio = newRatio;\n this.applySettings({ ...this.settings, splitRatio: newRatio });\n }\n\n // Admins handlers\n handleAdminsNewPhoneChange(value: string) {\n this.adminsNewPhone = value;\n // Clear error when user starts typing\n if (this.adminsError) this.adminsError = null;\n }\n\n // Contacts handlers\n handleContactsLoad() {\n const workspace = this.selectedWorkspace ?? undefined;\n void import(\"./controllers/contacts\").then(({ loadContacts }) => {\n loadContacts(this, workspace);\n });\n }\n\n handleContactsNewPhoneChange(value: string) {\n this.contactsNewPhone = value;\n if (this.contactsError) this.contactsError = null;\n }\n\n handleContactsNewNameChange(value: string) {\n this.contactsNewName = value;\n if (this.contactsError) this.contactsError = null;\n }\n\n // Workspaces handlers\n async handleWorkspacesLoad() {\n const { loadWorkspaces } = await import(\"./controllers/workspaces\");\n await loadWorkspaces(this);\n }\n\n async handleWorkspaceCreate(name: string, workspacePath?: string) {\n const { createWorkspace } = await import(\"./controllers/workspaces\");\n const { loadChannels } = await import(\"./controllers/channels\");\n await createWorkspace(this, {\n name,\n workspacePath,\n onCreated: (res) => {\n if (!res.whatsappAccountId) return;\n const accountId = res.whatsappAccountId;\n // Switch the dropdown to the new business immediately\n this.handleWorkspaceSelect(name);\n // Backend schedules SIGUSR1 restart with ~2s delay.\n // Wait for it, then reload channels and start QR flow.\n setTimeout(async () => {\n try {\n await loadChannels(this, true);\n await this.handleWhatsAppStart(true, accountId);\n if (this.whatsappLoginQrDataUrl) {\n await this.handleWhatsAppWait(accountId);\n await loadChannels(this, true);\n await this.handleWorkspacesLoad();\n }\n } catch {\n // Non-fatal — user can relink manually from the card\n }\n this.requestUpdate();\n }, 3000);\n },\n });\n }\n\n async handleWorkspaceRemove(name: string) {\n const { removeWorkspace } = await import(\"./controllers/workspaces\");\n await removeWorkspace(this, name);\n }\n\n handleWorkspaceRenameStart() {\n const ws = this.getSelectedWorkspaceInfo();\n this.renameWorkspaceName = ws?.displayName ?? ws?.name ?? \"\";\n this.renamingWorkspace = true;\n }\n\n handleWorkspaceRenameCancel() {\n this.renamingWorkspace = false;\n this.renameWorkspaceName = \"\";\n }\n\n async handleWorkspaceRename(name: string, displayName: string) {\n const { renameWorkspace } = await import(\"./controllers/workspaces\");\n await renameWorkspace(this, name, displayName);\n this.renamingWorkspace = false;\n this.renameWorkspaceName = \"\";\n }\n\n handleWorkspaceSelect(name: string) {\n // Persist current workspace's draft before switching\n flushDraftSave();\n if (this.selectedWorkspace) {\n saveDraft(this.selectedWorkspace, this.sessionKey, this.chatMessage);\n }\n this.selectedWorkspace = name;\n this.publicChatQrDataUrl = null;\n localStorage.setItem(\"taskmaster-selected-workspace\", name);\n // Apply workspace brand colours\n applyWorkspaceBrand(name);\n // Switch per-account settings to the new workspace\n setActiveWorkspace(name);\n this.settings = loadSettings();\n // Restore draft for the new workspace + session, or start empty\n this.chatMessage = loadDraft(name, this.settings.sessionKey);\n this.chatAttachments = [];\n this.chatStream = null;\n this.chatInterimText = null;\n this.chatSuggestions = [];\n this.chatStreamStartedAt = null;\n this.chatRunId = null;\n this.chatQueue = [];\n this.lastError = null;\n // Clear WhatsApp state so the new account's data loads fresh\n this.waConversations = [];\n this.waSelectedJid = null;\n this.waMessages = [];\n this.waGroupInfo = null;\n this.waLastError = null;\n this.waSearchQuery = \"\";\n this.waComposeDraft = \"\";\n this.reloadCurrentPageData();\n }\n\n getSelectedWorkspaceInfo(): import(\"./controllers/workspaces\").WorkspaceInfo | null {\n if (!this.selectedWorkspace) return null;\n return this.workspaces.find((ws) => ws.name === this.selectedWorkspace) ?? null;\n }\n\n private reloadCurrentPageData() {\n // Audit entries load globally — the badge is in the header on every page\n void this.loadAuditEntries();\n\n if (this.adminsPage) this.handleAdminsLoad();\n else if (this.contactsPage) this.handleContactsLoad();\n else if (this.filesPage) this.handleFilesLoad();\n else if (this.chatPage) {\n this.handleChatLoad();\n // If on the WhatsApp sub-tab, reload conversations for the new account\n if (this.chatPageTab === \"whatsapp\" && !this.waLoading && this.waConversations.length === 0) {\n void this.reloadWhatsAppConversations();\n }\n } else if (this.advancedPage) this.handleAdvancedLoad();\n }\n\n private async reloadWhatsAppConversations() {\n if (!this.client || !this.connected) return;\n this.waLoading = true;\n this.waLastError = null;\n try {\n const ws = this.getSelectedWorkspaceInfo();\n const accountId = ws?.whatsappAccountId;\n const res = (await this.client.request(\"whatsapp.conversations\", {\n accountId,\n })) as { conversations: import(\"./controllers/whatsapp\").WhatsAppConversation[] };\n this.waConversations = res.conversations;\n } catch (err) {\n this.waLastError = String(err);\n } finally {\n this.waLoading = false;\n }\n }\n\n /** Called after workspaces are loaded to restore or auto-select workspace. */\n initWorkspaceSelection() {\n if (this.workspaces.length === 0) {\n // No workspaces loaded (transient error or race on reconnect).\n // Still reload page data with the existing session key so standalone\n // pages (chat, files, etc.) don't show stale or empty state.\n this.reloadCurrentPageData();\n return;\n }\n const stored = localStorage.getItem(\"taskmaster-selected-workspace\");\n const match = stored ? this.workspaces.find((ws) => ws.name === stored) : null;\n if (match) {\n this.selectedWorkspace = match.name;\n } else {\n // Auto-select default workspace\n const defaultWs = this.workspaces.find((ws) => ws.isDefault) ?? this.workspaces[0];\n this.selectedWorkspace = defaultWs.name;\n localStorage.setItem(\"taskmaster-selected-workspace\", defaultWs.name);\n }\n // Apply workspace brand colours\n applyWorkspaceBrand(this.selectedWorkspace);\n // Activate per-account settings for the selected workspace\n setActiveWorkspace(this.selectedWorkspace);\n this.settings = loadSettings();\n // Restore any saved draft for this workspace + session\n this.chatMessage = loadDraft(this.selectedWorkspace, this.settings.sessionKey);\n // Reload page data now that workspace context is available\n this.reloadCurrentPageData();\n }\n\n render() {\n return html`${renderApp(this)}${this.auditModalOpen ? renderAuditModal(this.auditEntries, () => this.clearAudit(), () => { this.auditModalOpen = false; }) : nothing}`;\n }\n}\n"],"file":"index-B1bLQjxV.js"}