g-comments 0.1.0 → 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/core/storage.ts","../src/core/env.ts","../src/core/counts.ts","../src/types.ts","../src/core/composer.ts","../src/core/emitter.ts","../src/core/http.ts","../src/core/pkce.ts","../src/core/auth.ts","../src/core/log.ts","../src/core/realtime.ts","../src/core/tree.ts","../src/core/thread.ts","../src/core/client.ts","../src/core/registry.ts","../src/messages.ts"],"names":["error","popup","subscribers","toCommentsError","window"],"mappings":";;;AACO,IAAM,YAAA,GAAe;AAIrB,IAAM,iBAAA,GAAoB,iBAAA;AAC1B,IAAM,mBAAA,GAAsB,SAAA;AAC5B,IAAM,oBAAA,GAAuB,UAAA;AAC7B,IAAM,cAAA,GAAiB;AAEvB,IAAM,iBAAA,GAAoB,EAAA;AAC1B,IAAM,kBAAA,GAAqB,EAAA;AAE3B,IAAM,gBAAA,GAAmB,eAAA;;;ACYhC,IAAM,YAAA,uBAAwC,GAAA,CAAuB;AAAA,EACnE,aAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,oBAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,iBAAA;AAAA,EACA,kBAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA,oBAAA;AAAA,EACA,eAAA;AAAA,EACA,kBAAA;AAAA,EACA,qBAAA;AAAA,EACA,oBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGD,IAAM,cAAA,GAA8D;AAAA,EAClE,GAAA,EAAK,oBAAA;AAAA,EACL,GAAA,EAAK,aAAA;AAAA,EACL,GAAA,EAAK,gBAAA;AAAA,EACL,GAAA,EAAK,WAAA;AAAA,EACL,GAAA,EAAK,iBAAA;AAAA,EACL,GAAA,EAAK,oBAAA;AAAA,EACL,GAAA,EAAK;AACP,CAAA;AAYO,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,EACrB,IAAA,GAAO,eAAA;AAAA,EAChB,IAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,MAAA;AAAA,EACA,MAAA;AAAA;AAAA,EAEA,WAAA;AAAA;AAAA,EAEA,IAAA;AAAA;AAAA,EAEA,UAAA;AAAA,EAET,WAAA,CAAY,IAAA,EAAyB,OAAA,EAAiB,OAAA,GAAgC,EAAC,EAAG;AACxF,IAAA,KAAA,CAAM,OAAA,EAAS,QAAQ,KAAA,KAAU,MAAA,GAAY,SAAY,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,CAAA;AACjF,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,MAAA,IAAU,CAAA;AAChC,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA,KAAW,UAAU,CAAC,OAAO,IAAI,EAAC,CAAA;AACxD,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AACtB,IAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,WAAA;AAC3B,IAAA,IAAA,CAAK,OAAO,OAAA,CAAQ,IAAA;AACpB,IAAA,IAAA,CAAK,aAAa,OAAA,CAAQ,UAAA;AAAA,EAC5B;AACF;AAEO,SAAS,gBAAgB,KAAA,EAAwC;AACtE,EAAA,OAAO,KAAA,YAAiB,aAAA;AAC1B;AAEO,SAAS,iBAAA,CACd,MAAA,EACA,IAAA,EACA,OAAA,EACe;AACf,EAAA,MAAM,aAAa,OAAO,IAAA,EAAM,UAAA,KAAe,QAAA,GAAW,KAAK,UAAA,GAAa,MAAA;AAC5E,EAAA,MAAM,IAAA,GACJ,cAAc,YAAA,CAAa,GAAA,CAAI,UAAU,CAAA,GACpC,UAAA,GACA,cAAA,CAAe,MAAM,CAAA,IAAK,SAAA;AACjC,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,GACrC,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,CAAA,KAAM,QAAQ,IAC5D,EAAC;AACL,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,IAAU,OAAO,KAAK,MAAA,KAAW,QAAA,GAAW,KAAK,MAAA,GAAS,MAAA;AAE/E,EAAA,OAAO,IAAI,cAAc,IAAA,EAAM,MAAA,CAAO,CAAC,CAAA,IAAK,CAAA,2BAAA,EAA8B,MAAM,CAAA,CAAA,EAAI;AAAA,IAClF,MAAA;AAAA,IACA,MAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,aAAa,IAAA,KAAS,YAAA,GAAe,eAAA,CAAgB,MAAA,EAAQ,OAAO,CAAA,GAAI;AAAA,GACzE,CAAA;AACH;AAEA,SAAS,eAAA,CACP,QACA,OAAA,EACoB;AACpB,EAAA,OAAO,OAAA,CAAQ,QAAQ,YAAY,CAAA,IAAK,QAAQ,OAAA,EAAS,GAAA,CAAI,aAAa,CAAC,CAAA;AAC7E;AAGA,SAAS,QAAQ,KAAA,EAAoC;AACnD,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,OAAO,QAAA,CAAS,KAAK,CAAA,IAAK,KAAA,IAAS,IAAI,KAAA,GAAQ,MAAA;AAAA,EACxD;AACA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,qBAAA,CAAsB,IAAA,CAAK,KAAK,CAAA,EAAG;AAClE,IAAA,OAAO,OAAO,KAAK,CAAA;AAAA,EACrB;AACA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,gBAAA,CAAiB,KAAA,EAAe,MAAA,EAA4B,KAAA,EAAgB;AAC1F,EAAA,MAAM,IAAA,GAAO,MAAA,GAAS,CAAA,oBAAA,EAAuB,MAAM,CAAA,CAAA,CAAA,GAAM,oBAAA;AACzD,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,CAAA,EAAG,YAAY,CAAA,iBAAA,EAAoB,KAAK,CAAA,kBAAA,CAAA;AAAA,IACxC,KAAK,IAAI,CAAA,+IAAA,CAAA;AAAA,IACT,kIAAA;AAAA,IACA,2EAAA;AAAA,IACA;AAAA,GACF,CAAE,KAAK,IAAI,CAAA;AAEX,EAAA,OAAO,IAAI,aAAA,CAAc,aAAA,EAAe,CAAA,gBAAA,EAAmB,KAAK,CAAA,CAAA,EAAI;AAAA,IAClE,MAAA,EAAQ,CAAA;AAAA,IACR,QAAQ,EAAC;AAAA,IACT,IAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;;;AC9IO,SAAS,aAAA,GAA6B;AAC3C,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAoB;AACtC,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,KAAA;AAAA,IACT,SAAS,CAAC,GAAA,KAAQ,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,IAAK,IAAA;AAAA,IACpC,OAAA,EAAS,CAAC,GAAA,EAAK,KAAA,KAAU,KAAK,KAAA,CAAM,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,IAClD,YAAY,CAAC,GAAA,KAAQ,KAAK,KAAA,CAAM,OAAO,GAAG;AAAA,GAC5C;AACF;AAOO,SAAS,cAAc,OAAA,EAA0C;AACtE,EAAA,IAAI,OAAA,CAAQ,YAAY,KAAA,EAAO;AAC7B,IAAA,OAAO,OAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,UAAA,CAAW,cAAA;AAC3B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,KAAA,GAAQ,UAAA;AACd,MAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,KAAK,CAAA;AAC5B,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,OAAA,CAAQ,KAAK,CAAA,KAAM,KAAA;AAC5C,MAAA,OAAA,CAAQ,WAAW,KAAK,CAAA;AACxB,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,OAAO,OAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,cAAA,GAAoE;AAClF,EAAA,IAAI;AACF,IAAA,MAAM,UAAU,UAAA,CAAW,YAAA;AAC3B,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,MAAM,KAAA,GAAQ,UAAA;AACd,MAAA,OAAA,CAAQ,OAAA,CAAQ,OAAO,KAAK,CAAA;AAC5B,MAAA,OAAA,CAAQ,WAAW,KAAK,CAAA;AACxB,MAAA,OAAO,EAAE,OAAA,EAAS,cAAA,EAAgB,IAAA,EAAK;AAAA,IACzC;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,aAAA,EAAc,EAAG,gBAAgB,KAAA,EAAM;AAC3D;AAGO,SAAS,eAAe,OAAA,EAA+B;AAC5D,EAAA,IAAI;AACF,IAAA,OAAO,YAAY,UAAA,CAAW,YAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEO,SAAS,QAAA,CAAY,SAAsB,GAAA,EAAuB;AACvE,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AAC/B,IAAA,OAAO,GAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA,GAAU,IAAA;AAAA,EACxC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,SAAA,CAAU,OAAA,EAAsB,GAAA,EAAa,KAAA,EAAsB;AACjF,EAAA,IAAI;AACF,IAAA,OAAA,CAAQ,OAAA,CAAQ,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EAC5C,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEO,SAAS,UAAA,CAAW,SAAsB,GAAA,EAAmB;AAClE,EAAA,IAAI;AACF,IAAA,OAAA,CAAQ,WAAW,GAAG,CAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;;AC9FO,SAAS,SAAA,GAAgC;AAC9C,EAAA,OAAO,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,GAAY,MAAA;AACrD;AAEO,SAAS,WAAA,GAAoC;AAClD,EAAA,OAAO,OAAO,QAAA,KAAa,WAAA,GAAc,MAAA,GAAY,QAAA;AACvD;AAEO,SAAS,UAAA,GAAiC;AAC/C,EAAA,OAAO,SAAA,IAAa,QAAA,CAAS,MAAA;AAC/B;AAGO,SAAS,cAAA,GAAqC;AACnD,EAAA,MAAM,SAAA,GAAY,WAAA,EAAY,EAAG,aAAA,CAA+B,uBAAuB,CAAA;AACvF,EAAA,IAAI,WAAW,IAAA,EAAM;AACnB,IAAA,OAAO,SAAA,CAAU,IAAA;AAAA,EACnB;AACA,EAAA,OAAO,SAAA,IAAa,QAAA,CAAS,IAAA;AAC/B;AAEO,SAAS,gBAAA,GAAuC;AACrD,EAAA,OAAO,WAAA,IAAe,KAAA,IAAS,MAAA;AACjC;AAGO,SAAS,qBAAA,GAA4C;AAC1D,EAAA,MAAM,QAAA,GAAW,WAAU,EAAG,QAAA;AAC9B,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA;AACnC;AAEO,SAAS,gBAAA,GAA4B;AAC1C,EAAA,OAAO,WAAA,IAAe,MAAA,KAAW,IAAA;AACnC;AAEO,SAAS,mBAAmB,QAAA,EAAkC;AACnE,EAAA,MAAM,MAAM,WAAA,EAAY;AACxB,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,OAAO,MAAM;AAAA,IAAC,CAAA;AAAA,EAChB;AACA,EAAA,GAAA,CAAI,gBAAA,CAAiB,oBAAoB,QAAQ,CAAA;AACjD,EAAA,OAAO,MAAM,GAAA,CAAI,mBAAA,CAAoB,kBAAA,EAAoB,QAAQ,CAAA;AACnE;;;ACrCO,SAAS,UAAU,GAAA,EAAuB;AAC/C,EAAA,IAAI,aAAa,GAAA,EAAK;AACpB,IAAA,OAAO,CAAA,EAAA,EAAK,IAAI,OAAO,CAAA,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,gBAAgB,GAAA,EAAK;AACvB,IAAA,MAAM,IAAA,GAAO,GAAA,CAAI,IAAA,IAAQ,SAAA,IAAa,QAAA,CAAS,IAAA;AAC/C,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,UAAU,iEAAiE,CAAA;AAAA,IACvF;AACA,IAAA,OAAO,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA,EAAI,GAAA,CAAI,UAAU,CAAA,CAAA;AAAA,EACrC;AACA,EAAA,OAAO,CAAA,IAAA,EAAO,IAAI,GAAG,CAAA,CAAA;AACvB;AAGA,IAAM,gBAAA,GAAmB,GAAA;AAclB,IAAM,gBAAN,MAAoB;AAAA,EACzB,KAAA;AAAA,EACA,WAAqB,EAAC;AAAA,EACtB,UAAA,GAAa,KAAA;AAAA,EAEb,YAAY,IAAA,EAAY;AACtB,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,EACf;AAAA,EAEA,QAAQ,IAAA,EAA4C;AAClD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,MAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,EAAE,CAAA;AAAA,IAC3B;AACA,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,IAAA,CAAK,SAAS,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,QAAQ,CAAA;AAC5C,MAAA,IAAI,CAAC,KAAK,UAAA,EAAY;AACpB,QAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,QAAA,UAAA,CAAW,MAAM,KAAK,IAAA,CAAK,MAAA,IAAU,CAAC,CAAA;AAAA,MACxC;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,MAAA,GAAwB;AAC5B,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AACrB,IAAA,IAAA,CAAK,WAAW,EAAC;AACjB,IAAA,IAAA,CAAK,UAAA,GAAa,KAAA;AAElB,IAAA,MAAM,MAAA,GAAS,CAAC,GAAG,IAAI,GAAA,CAAI,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAC,CAAA;AAC1D,IAAA,MAAM,UAAsB,EAAC;AAC7B,IAAA,IAAI,UAAoB,EAAC;AACzB,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,KAAA,MAAW,OAAO,MAAA,EAAQ;AACxB,MAAA,MAAM,IAAA,GAAO,kBAAA,CAAmB,GAAG,CAAA,CAAE,SAAS,UAAA,CAAW,MAAA;AACzD,MAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,KAAM,OAAA,CAAQ,UAAU,iBAAA,IAAqB,MAAA,GAAS,OAAO,gBAAA,CAAA,EAAmB;AACnG,QAAA,OAAA,CAAQ,KAAK,OAAO,CAAA;AACpB,QAAA,OAAA,GAAU,EAAC;AACX,QAAA,MAAA,GAAS,CAAA;AAAA,MACX;AACA,MAAA,OAAA,CAAQ,KAAK,GAAG,CAAA;AAChB,MAAA,MAAA,IAAU,IAAA;AAAA,IACZ;AACA,IAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,MAAA,OAAA,CAAQ,KAAK,OAAO,CAAA;AAAA,IACtB;AAEA,IAAA,MAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,IAAA,MAAM,QAAA,uBAAe,GAAA,EAAqB;AAC1C,IAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,MACZ,OAAA,CAAQ,GAAA,CAAI,OAAO,KAAA,KAAU;AAC3B,QAAA,IAAI;AACF,UAAA,MAAM,WAAW,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,CAAwB,OAAO,SAAA,EAAW;AAAA,YAC1E,KAAA,EAAO,EAAE,IAAA,EAAM,KAAA,EAAM;AAAA,YACrB,SAAA,EAAW;AAAA,WACZ,CAAA;AACD,UAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACvB,YAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,MAAA,CAAO,QAAA,CAAS,SAAS,GAAG,CAAA,IAAK,CAAC,CAAC,CAAA;AAAA,UACtD;AAAA,QACF,SAAS,KAAA,EAAO;AACd,UAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACvB,YAAA,QAAA,CAAS,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,UACzB;AAAA,QACF;AAAA,MACF,CAAC;AAAA,KACH;AAEA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,MAAA,GAAS,OAAO,IAAA,CAAK,IAAA,CAAK,CAAC,GAAA,KAAQ,QAAA,CAAS,GAAA,CAAI,GAAG,CAAC,CAAA;AAC1D,MAAA,IAAI,WAAW,MAAA,EAAW;AACxB,QAAA,MAAA,CAAO,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,MAAM,CAAC,CAAA;AAClC,QAAA;AAAA,MACF;AACA,MAAA,MAAM,SAAiB,EAAC;AACxB,MAAA,KAAA,MAAW,GAAA,IAAO,OAAO,IAAA,EAAM;AAC7B,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,IAAK,CAAA;AAAA,MACpC;AACA,MAAA,MAAA,CAAO,QAAQ,MAAM,CAAA;AAAA,IACvB;AAAA,EACF;AACF,CAAA;;;ACFO,SAAS,gBAAgB,MAAA,EAA4C;AAC1E,EAAA,OAAO,OAAO,QAAA,KAAa,IAAA;AAC7B;;;AChGA,IAAM,gBAAA,GAAmB,GAAA;AAElB,SAAS,mBAAA,CAAoB,GAAA,GAAoB,IAAA,CAAK,GAAA,EAAoB;AAC/E,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,IAAI,YAAA,GAAe,CAAA,QAAA;AAEnB,EAAA,MAAM,UAAU,OAAuB;AAAA,IACrC,mBAAA,EAAqB,QAAA;AAAA,IACrB,yBAAA,EAA2B,aAAa,IAAA,GAAO,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,GAAA,EAAI,GAAI,QAAQ;AAAA,GACjF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,IAAI,OAAA,GAAU;AACZ,MAAA,OAAO,QAAA,KAAa,IAAA;AAAA,IACtB,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,QAAA,KAAa,GAAA,EAAI;AAAA,IACnB,CAAA;AAAA,IACA,MAAA,GAAS;AACP,MAAA,QAAA,KAAa,GAAA,EAAI;AACjB,MAAA,MAAM,KAAK,GAAA,EAAI;AACf,MAAA,IAAI,EAAA,GAAK,gBAAgB,gBAAA,EAAkB;AACzC,QAAA,QAAA,IAAY,gBAAA;AACZ,QAAA,YAAA,GAAe,EAAA;AAAA,MACjB;AAAA,IACF,CAAA;AAAA,IACA,OAAA;AAAA,IACA,IAAA,GAAO;AACL,MAAA,MAAM,SAAS,OAAA,EAAQ;AACvB,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,QAAA,GAAW,CAAA;AACX,MAAA,YAAA,GAAe,CAAA,QAAA;AACf,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,GACF;AACF;;;ACxDO,IAAM,UAAN,MAAiB;AAAA,EACtB,UAAA,uBAAiB,GAAA,EAAiB;AAAA,EAElC,IAAI,IAAA,GAAe;AACjB,IAAA,OAAO,KAAK,UAAA,CAAW,IAAA;AAAA,EACzB;AAAA,EAEA,GAAG,QAAA,EAAmC;AACpC,IAAA,IAAA,CAAK,UAAA,CAAW,IAAI,QAAQ,CAAA;AAC5B,IAAA,OAAO,MAAM;AACX,MAAA,IAAA,CAAK,UAAA,CAAW,OAAO,QAAQ,CAAA;AAAA,IACjC,CAAA;AAAA,EACF;AAAA,EAEA,KAAK,KAAA,EAAgB;AACnB,IAAA,KAAA,MAAW,QAAA,IAAY,CAAC,GAAG,IAAA,CAAK,UAAU,CAAA,EAAG;AAC3C,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,KAAK,CAAA;AAAA,MAChB,SAAS,KAAA,EAAO;AAEd,QAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,WAAW,KAAA,EAAM;AAAA,EACxB;AACF,CAAA;;;ACwBO,SAAS,eAAe,KAAA,EAA8B;AAC3D,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAI,IAAI,KAAK,CAAA;AAAA,EACrB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,SAAA,CAAU,CAAA,EAAG,YAAY,CAAA,wCAAA,EAA2C,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,EACxF;AACA,EAAA,IAAI,GAAA,CAAI,QAAA,KAAa,QAAA,IAAY,GAAA,CAAI,aAAa,OAAA,EAAS;AACzD,IAAA,MAAM,IAAI,SAAA,CAAU,CAAA,EAAG,YAAY,CAAA,uCAAA,EAA0C,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,EACvF;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,EAAQ,IAAA,EAAM,GAAA,CAAI,MAAA,GAAS,GAAA,CAAI,QAAA,CAAS,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,EAAE;AACnF;AAEO,SAAS,WAAW,KAAA,EAAuD;AAChF,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,EAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAChD,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,kBAAA,CAAmB,GAAG,CAAC,CAAA,GAAA,EAAM,kBAAA,CAAmB,MAAA,CAAO,IAAI,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,MAC/E;AAAA,IACF,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,kBAAA,CAAmB,GAAG,CAAC,CAAA,CAAA,EAAI,kBAAA,CAAmB,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IAC9E;AAAA,EACF;AACA,EAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AACvB;AAGO,SAAS,WAAW,QAAA,EAA0B;AACnD,EAAA,OAAO,YAAY,kBAAA,CAAmB,QAAQ,EAAE,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAC,CAAA,CAAA;AACvE;AAEO,SAAS,aAAa,KAAA,EAAyB;AACpD,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,IAAA,IACT,MAA6B,IAAA,KAAS,YAAA;AAE3C;AAEO,IAAM,OAAN,MAAW;AAAA,EACP,KAAA;AAAA,EACT,QAAA;AAAA,EACA,MAAA;AAAA,EAEA,YAAY,OAAA,EAAsB;AAChC,IAAA,IAAA,CAAK,QAAQ,OAAA,CAAQ,KAAA;AACrB,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAGhB,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,KAAA,KAAU,CAAC,OAAO,IAAA,KAAS,UAAA,CAAW,KAAA,CAAM,KAAA,EAAO,IAAI,CAAA,CAAA;AAAA,EAC/E;AAAA,EAEA,IAAI,KAAA,GAAmB;AACrB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,GAAA,CAAI,MAAc,KAAA,EAA4C;AAC5D,IAAA,MAAM,EAAA,GAAK,WAAW,KAAK,CAAA;AAC3B,IAAA,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAI,YAAY,IAAI,CAAA,CAAA;AAC9C,IAAA,OAAO,EAAA,GAAK,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA,GAAK,GAAA;AAAA,EAC/B;AAAA,EAEA,MAAM,OAAA,CAAW,MAAA,EAAgB,IAAA,EAAc,OAAA,GAA0B,EAAC,EAAe;AACvF,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,MAAA,EAAQ,kBAAA;AAAA,MACR,GAAG,KAAK,QAAA,CAAS;AAAA,KACnB;AACA,IAAA,MAAM,QAAA,GAAW,cAAA,CAAe,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AACpD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAA,CAAQ,iBAAiB,CAAA,GAAI,QAAA;AAAA,IAC/B;AAEA,IAAA,IAAI,IAAA;AACJ,IAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAW;AAC9B,MAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAC1B,MAAA,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAAA,IACpC,CAAA,MAAA,IAAW,QAAQ,IAAA,EAAM;AACvB,MAAA,IAAA,GAAO,OAAA,CAAQ,IAAA;AAAA,IACjB;AAEA,IAAA,MAAM,WAAA,GAAc,QAAQ,SAAA,GACxB,IAAA,GACC,QAAQ,WAAA,IAAe,IAAA,CAAK,SAAS,WAAA,EAAY;AACtD,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,OAAA,CAAQ,cAAc,IAAI,WAAA,CAAY,GAAA;AACtC,MAAA,OAAA,CAAQ,oBAAoB,IAAI,WAAA,CAAY,QAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,QAAQ,KAAK,CAAA;AACxC,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,GAAW,MAAA,GAAY,KAAK,QAAA,CAAS,QAAA;AAC9D,IAAA,IAAI,UAAU,OAAA,EAAS;AACrB,MAAA,MAAM,IAAI,YAAA,CAAa,kCAAA,EAAoC,YAAY,CAAA;AAAA,IACzE;AACA,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA;AACtD,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,MAAA,EAAQ,GAAG,CAAA;AAE7B,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,MAAM,IAAA,CAAK,MAAA,CAAO,GAAA,EAAK;AAAA,QAChC,MAAA;AAAA,QACA,OAAA;AAAA,QACA,IAAA;AAAA,QACA,WAAA,EAAa,MAAA;AAAA,QACb,IAAA,EAAM,MAAA;AAAA,QACN;AAAA,OACD,CAAA;AAAA,IACH,SAASA,MAAAA,EAAO;AACd,MAAA,IAAI,MAAA,EAAQ,OAAA,IAAW,YAAA,CAAaA,MAAK,CAAA,EAAG;AAC1C,QAAA,MAAMA,MAAAA;AAAA,MACR;AACA,MAAA,MAAM,iBAAiB,IAAA,CAAK,KAAA,CAAM,IAAA,EAAM,UAAA,IAAcA,MAAK,CAAA;AAAA,IAC7D;AAEA,IAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,MAAA,OAAO,MAAA;AAAA,IACT;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,MAAM,IAAA,GAAO,UAAU,IAAI,CAAA;AAE3B,IAAA,IAAI,SAAS,EAAA,EAAI;AACf,MAAA,IAAI,SAAS,MAAA,EAAW;AACtB,QAAA,MAAM,IAAI,aAAA,CAAc,SAAA,EAAW,wCAAA,EAA0C;AAAA,UAC3E,QAAQ,QAAA,CAAS;AAAA,SAClB,CAAA;AAAA,MACH;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,IAAI,CAAA,GAAK,IAAA,GAAyB,IAAA;AAC7D,IAAA,MAAM,QAAQ,iBAAA,CAAkB,QAAA,CAAS,MAAA,EAAQ,SAAA,EAAW,SAAS,OAAO,CAAA;AAC5E,IAAA,IACE,QAAA,CAAS,WAAW,GAAA,IACpB,KAAA,CAAM,eAAe,aAAA,IACrB,WAAA,IACA,SAAA,EAAW,QAAA,KAAa,IAAA,EACxB;AACA,MAAA,IAAA,CAAK,QAAA,CAAS,YAAA,CAAa,WAAA,CAAY,GAAG,CAAA;AAAA,IAC5C;AACA,IAAA,MAAM,KAAA;AAAA,EACR;AACF,CAAA;AAOO,SAAS,eAAe,MAAA,EAAgD;AAC7E,EAAA,MAAM,KAAA,GAAQ,MAAA,EAAQ,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAA;AACvC,EAAA,OAAO,KAAA,IAAS,wBAAA,CAAyB,IAAA,CAAK,KAAK,IAAI,KAAA,GAAQ,MAAA;AACjE;AAEA,SAAS,cAAA,CACP,GACA,CAAA,EACyB;AACzB,EAAA,IAAI,CAAC,CAAA,IAAK,CAAC,CAAA,EAAG;AACZ,IAAA,OAAO,CAAA,IAAK,CAAA;AAAA,EACd;AACA,EAAA,IAAI,OAAO,WAAA,CAAY,GAAA,KAAQ,UAAA,EAAY;AACzC,IAAA,OAAO,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,EAC/B;AACA,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,KAAA,GAAQ,MAAM,UAAA,CAAW,KAAA,EAAM;AACrC,EAAA,IAAI,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,EAAS;AAC1B,IAAA,KAAA,EAAM;AAAA,EACR;AACA,EAAA,CAAA,CAAE,iBAAiB,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AACjD,EAAA,CAAA,CAAE,iBAAiB,OAAA,EAAS,KAAA,EAAO,EAAE,IAAA,EAAM,MAAM,CAAA;AACjD,EAAA,OAAO,UAAA,CAAW,MAAA;AACpB;AAEA,SAAS,UAAU,IAAA,EAAuB;AACxC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAEA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;;;ACvPO,SAAS,UAAU,KAAA,EAA2B;AACnD,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAA,IAAU,MAAA,CAAO,aAAa,IAAI,CAAA;AAAA,EACpC;AACA,EAAA,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC/E;AAGO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAW,KAAK,CAAA;AACnC,EAAA,UAAA,CAAW,MAAA,CAAO,gBAAgB,MAAM,CAAA;AACxC,EAAA,OAAO,UAAU,MAAM,CAAA;AACzB;AAGA,eAAsB,cAAc,QAAA,EAAmC;AACrE,EAAA,MAAM,MAAA,GAAS,WAAW,MAAA,EAAQ,MAAA;AAClC,EAAA,IAAI,CAAC,MAAA,EAAQ;AAGX,IAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,EAC9E;AACA,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,QAAQ,CAAC,CAAA;AAChF,EAAA,OAAO,SAAA,CAAU,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA;AACzC;;;ACmEA,IAAM,iBAAiB,EAAA,GAAK,GAAA;AAC5B,IAAM,UAAA,GAAa,SAAA;AACnB,IAAM,WAAA,GAAc,GAAA;AACpB,IAAM,YAAA,GAAe,GAAA;AACrB,IAAM,eAAA,GAAkB,GAAA;AACxB,IAAM,eAAA,GAAkB,GAAA;AAEjB,IAAM,iBAAN,MAA6C;AAAA,EACzC,QAAA;AAAA,EACT,QAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,GAAW,IAAI,OAAA,EAAmB;AAAA,EAClC,QAAA,GAA2B,IAAA;AAAA,EAC3B,SAAA,GAA8C,IAAA;AAAA,EAC9C,SAAA,GAAiC,IAAA;AAAA;AAAA,EAEjC,WAAA,GAAc,CAAA;AAAA,EAEd,YAAY,OAAA,EAAgC;AAC1C,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,MAAM,SAAS,CAAA,EAAG,cAAc,CAAA,CAAA,EAAI,OAAA,CAAQ,MAAM,IAAI,CAAA,CAAA;AACtD,IAAA,IAAA,CAAK,KAAA,GAAQ;AAAA,MACX,IAAA,EAAM,GAAG,MAAM,CAAA,KAAA,CAAA;AAAA,MACf,QAAA,EAAU,GAAG,MAAM,CAAA,UAAA,CAAA;AAAA,MACnB,OAAA,EAAS,GAAG,MAAM,CAAA,QAAA;AAAA,KACpB;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,gBAAA,CAAiB,OAAA,CAAQ,QAAQ,CAAA;AACtD,IAAA,IAAA,CAAK,OAAA,GAAU,KAAK,WAAA,EAAY;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,OAAO,MAAA,CAAO;AAAA,MAC1B,MAAA,EAAQ,IAAA,CAAK,OAAA,GAAU,WAAA,GAAc,WAAA;AAAA,MACrC,IAAA,EAAM,IAAA,CAAK,OAAA,EAAS,IAAA,IAAQ,IAAA;AAAA,MAC5B,QAAA,EAAU,KAAA;AAAA,MACV,KAAA,EAAO;AAAA,KACR,CAAA;AAED,IAAA,MAAM,MAAM,SAAA,EAAU;AACtB,IAAA,IAAI,OAAA,CAAQ,kBAAkB,GAAA,EAAK;AACjC,MAAA,GAAA,CAAI,gBAAA,CAAiB,SAAA,EAAW,IAAA,CAAK,UAAU,CAAA;AAC/C,MAAA,IAAA,CAAK,YAAY,MAAM,GAAA,CAAI,mBAAA,CAAoB,SAAA,EAAW,KAAK,UAAU,CAAA;AAAA,IAC3E;AAAA,EACF;AAAA,EAEA,IAAI,MAAA,GAAqB;AACvB,IAAA,OAAO,KAAK,MAAA,CAAO,MAAA;AAAA,EACrB;AAAA,EAEA,IAAI,IAAA,GAAyB;AAC3B,IAAA,OAAO,KAAK,MAAA,CAAO,IAAA;AAAA,EACrB;AAAA,EAEA,IAAI,SAAA,GAAqC;AACvC,IAAA,OAAO,IAAA,CAAK,SAAS,SAAA,EAAU;AAAA,EACjC;AAAA,EAEA,KAAA,GAAmB;AACjB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,SAAS,QAAA,EAAkD;AACzD,IAAA,OAAO,IAAA,CAAK,QAAA,CAAS,EAAA,CAAG,QAAQ,CAAA;AAAA,EAClC;AAAA;AAAA,EAGA,WAAA,GAAkC;AAChC,IAAA,OAAO,IAAA,CAAK,OAAA,GAAU,EAAE,GAAA,EAAK,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,QAAA,EAAU,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAU,GAAI,IAAA;AAAA,EACtF;AAAA,EAEA,MAAA,CAAO,OAAA,GAAyB,EAAC,EAA8B;AAC7D,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA,MAAMC,MAAAA,GAAQ,KAAK,QAAA,CAAS,KAAA;AAC5B,MAAA,IAAIA,MAAAA,IAAS,CAACA,MAAAA,CAAM,MAAA,EAAQ;AAC1B,QAAAA,OAAM,KAAA,EAAM;AACZ,QAAA,OAAO,KAAK,QAAA,CAAS,OAAA;AAAA,MACvB;AACA,MAAA,IAAA,CAAK,SAAS,MAAA,CAAO,IAAI,aAAA,CAAc,WAAA,EAAa,uBAAuB,CAAC,CAAA;AAAA,IAC9E;AAEA,IAAA,MAAM,MAAM,SAAA,EAAU;AACtB,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO,QAAQ,MAAA,CAAO,IAAI,aAAA,CAAc,SAAA,EAAW,mCAAmC,CAAC,CAAA;AAAA,IACzF;AAIA,IAAA,MAAM,QAAA,GAAW,KAAK,YAAA,EAAa;AACnC,IAAA,MAAM,KAAA,GAAQ,QAAA,EAAU,KAAA,IAAS,WAAA,CAAY,EAAE,CAAA;AAC/C,IAAA,MAAM,QAAA,GAAW,QAAA,EAAU,QAAA,IAAY,WAAA,CAAY,EAAE,CAAA;AAGrD,IAAA,MAAM,UAAU,OAAA,CAAQ,IAAA,IAAQ,aAAa,OAAA,GAAU,SAAA,CAAU,GAAG,CAAA,GAAI,IAAA;AAExE,IAAA,MAAM,KAAA,GAAQ,MAAA,IAAU,CAAC,MAAA,CAAO,SAAS,MAAA,GAAS,IAAA;AAClD,IAAA,IAAI,cAAA,GAAiB,KAAA;AAErB,IAAA,IAAI,aAAA,GAAsC,IAAA;AAC1C,IAAA,IAAI,kBAAkD,MAAM;AAAA,IAAC,CAAA;AAC7D,IAAA,MAAM,SAAA,GAAY,IAAI,OAAA,CAAe,CAAC,GAAG,MAAA,KAAW;AAClD,MAAA,eAAA,GAAkB,MAAA;AAAA,IACpB,CAAC,CAAA;AACD,IAAA,SAAA,CAAU,MAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AACxB,IAAA,IAAI,YAAY,MAAM;AAAA,IAAC,CAAA;AAEvB,IAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KACpB,IAAA,CAAK,QAAA,CAAS,cAAA,IACd,SAAA,CAAU,IAAA,CAAK,QAAA,CAAS,cAAA,EAAgB,IAAA,CAAK,KAAA,CAAM,OAAA,EAAS;AAAA,MAC1D,KAAA;AAAA,MACA,QAAA;AAAA,MACA,IAAA;AAAA,MACA,UAAA,EAAY,QAAA,EAAU,UAAA,IAAc,IAAA,CAAK,GAAA;AAAI,KACrB,CAAA;AAE5B,IAAA,MAAM,MAAM,YAAuC;AACjD,MAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc,QAAQ,CAAA;AAC9C,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,MAAM,aAAA;AAAA,MACR;AACA,MAAA,MAAM,MAAM,IAAA,CAAK,SAAA,CAAU,KAAA,EAAO,SAAA,EAAW,QAAQ,QAAQ,CAAA;AAE7D,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,IAAI,MAAM,MAAA,EAAQ;AAChB,UAAA,MAAM,IAAI,aAAA,CAAc,WAAA,EAAa,+BAA+B,CAAA;AAAA,QACtE;AAEA,QAAA,YAAA,CAAa,OAAO,CAAA;AACpB,QAAA,cAAA,GAAiB,aAAA,CAAc,OAAO,GAAG,CAAA;AAAA,MAC3C;AACA,MAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,QAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,cAAA,EAAgB;AACjC,UAAA,MAAM,IAAI,aAAA;AAAA,YACR,qBAAA;AAAA,YACA;AAAA,WACF;AAAA,QACF;AACA,QAAA,YAAA,CAAa,UAAU,CAAA;AACvB,QAAA,IAAA,CAAK,QAAA,CAAS,IAAI,gCAAgC,CAAA;AAGlD,QAAA,GAAA,CAAI,gBAAA,CAAiB,UAAA,EAAY,IAAA,CAAK,WAAW,CAAA;AACjD,QAAA,CAAC,IAAA,CAAK,QAAA,CAAS,QAAA,KAAa,CAAC,MAAA,KAAW,IAAI,QAAA,CAAS,MAAA,CAAO,MAAM,CAAA,CAAA,EAAI,GAAG,CAAA;AACzE,QAAA,OAAO,IAAA;AAAA,MACT;AAEA,MAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,aAAA,CAAc,KAAK,KAAA,EAAQ,KAAA,EAAO,CAAC,IAAA,KAAS;AACrE,QAAA,SAAA,GAAY,IAAA;AAAA,MACd,CAAC,CAAA;AACD,MAAA,IAAI,OAAA,CAAQ,SAAS,MAAA,EAAQ;AAC3B,QAAA,OAAO,OAAA,CAAQ,IAAA;AAAA,MACjB;AACA,MAAA,OAAO,KAAK,SAAA,CAAU,OAAA,CAAQ,MAAM,QAAA,EAAU,KAAA,EAAO,MAAM,aAAa,CAAA;AAAA,IAC1E,CAAA;AAEA,IAAA,IAAA,CAAK,KAAK,EAAE,MAAA,EAAQ,YAAA,EAAc,KAAA,EAAO,MAAM,CAAA;AAE/C,IAAA,MAAM,OAAA,GAAmB;AAAA,MACvB,KAAA;AAAA,MACA,MAAA,EAAQ,CAAC,KAAA,KAAU;AACjB,QAAA,aAAA,GAAgB,KAAA;AAChB,QAAA,SAAA,EAAU;AACV,QAAA,eAAA,CAAgB,KAAK,CAAA;AAAA,MACvB,CAAA;AAAA,MACA,OAAA,EAAS,QAAQ,IAAA,CAAK,CAAC,KAAI,EAAG,SAAS,CAAC,CAAA,CAAE,IAAA;AAAA,QACxC,CAAC,IAAA,KAAS;AACR,UAAA,IAAI,IAAA,CAAK,aAAa,OAAA,EAAS;AAC7B,YAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,UAClB;AACA,UAAA,OAAO,IAAA;AAAA,QACT,CAAA;AAAA,QACA,CAAC,KAAA,KAAmB;AAClB,UAAA,MAAM,OAAA,GAAU,gBAAgB,KAAK,CAAA;AACrC,UAAA,IAAI,KAAA,IAAS,CAAC,cAAA,IAAkB,CAAC,MAAM,MAAA,EAAQ;AAC7C,YAAA,KAAA,CAAM,KAAA,EAAM;AAAA,UACd;AAEA,UAAA,IAAI,IAAA,CAAK,aAAa,OAAA,EAAS;AAC7B,YAAA,MAAM,OAAA;AAAA,UACR;AACA,UAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAGhB,UAAA,IAAI,OAAA,CAAQ,SAAS,WAAA,EAAa;AAChC,YAAA,IAAA,CAAK,cAAA,EAAe;AAAA,UACtB;AACA,UAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAA,CAAK,UAAU,WAAA,GAAc,WAAA,EAAa,KAAA,EAAO,OAAA,EAAS,CAAA;AAC9E,UAAA,MAAM,OAAA;AAAA,QACR;AAAA;AACF,KACF;AACA,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAChB,IAAA,OAAO,OAAA,CAAQ,OAAA;AAAA,EACjB;AAAA,EAEA,YAAA,GAAqB;AACnB,IAAA,IAAA,CAAK,UAAU,MAAA,CAAO,IAAI,aAAA,CAAc,WAAA,EAAa,uBAAuB,CAAC,CAAA;AAAA,EAC/E;AAAA,EAEA,MAAM,OAAA,GAAyB;AAG7B,IAAA,IAAA,CAAK,WAAA,EAAA;AACL,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,IAAA,CAAK,cAAA,EAAe;AACpB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,OAAA,CAAQ,QAAQ,cAAc,CAAA;AAAA,MACzD,SAAS,KAAA,EAAO;AAGd,QAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,eAAA,EAAiB,KAAK,CAAA;AAAA,MAC1C;AAAA,IACF;AACA,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,WAAA,EAAa,IAAA,EAAM,MAAM,QAAA,EAAU,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,CAAA;AAAA,EAC7E;AAAA,EAEA,cAAA,GAA4C;AAC1C,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,MAAA,IAAA,CAAK,SAAA,GAAY,KAAK,gBAAA,EAAiB;AACvC,MAAA,IAAA,CAAK,SAAA,CAAU,MAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IAC/B;AACA,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA;AAAA,EAGA,WAAW,OAAA,EAAuB;AAChC,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,OAAA,CAAQ,QAAQ,OAAA,EAAS;AACjD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,KAAK,WAAA,EAAY;AAChC,IAAA,IAAI,MAAA,IAAU,MAAA,CAAO,GAAA,KAAQ,OAAA,EAAS;AACpC,MAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,WAAA,EAAa,MAAM,MAAA,CAAO,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,CAAA;AACjE,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,MAAA,EAAQ,IAAA,CAAK,QAAA,GAAW,YAAA,GAAe,WAAA;AAAA,MACvC,IAAA,EAAM,IAAA;AAAA,MACN,QAAA,EAAU,KAAA;AAAA,MACV,KAAA,EAAO,IAAI,aAAA,CAAc,aAAA,EAAe,iDAAA,EAAmD;AAAA,QACzF,MAAA,EAAQ;AAAA,OACT;AAAA,KACF,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,YAAY,MAAA,EAAsB;AAChC,IAAA,IAAI,IAAA,CAAK,OAAA,IAAW,MAAA,CAAO,YAAA,EAAc;AACvC,MAAA,IAAA,CAAK,UAAU,EAAE,GAAG,KAAK,OAAA,EAAS,IAAA,EAAM,OAAO,YAAA,EAAa;AAC5D,MAAA,SAAA,CAAU,KAAK,QAAA,CAAS,OAAA,EAAS,KAAK,KAAA,CAAM,IAAA,EAAM,KAAK,OAAO,CAAA;AAAA,IAChE;AACA,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,MAAA,CAAO,QAAA,KAAa,IAAA,EAAM,IAAA,EAAM,IAAA,CAAK,OAAA,EAAS,IAAA,IAAQ,IAAA,EAAM,CAAA;AAAA,EACpF;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAA,CAAK,WAAA,EAAA;AACL,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,SAAA,EAAU,EAAG,mBAAA,CAAoB,UAAA,EAAY,IAAA,CAAK,WAAW,CAAA;AAC7D,IAAA,IAAA,CAAK,SAAA,IAAY;AACjB,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,EACtB;AAAA,EAEA,MAAM,gBAAA,GAA8C;AAClD,IAAA,MAAM,MAAM,SAAA,EAAU;AACtB,IAAA,MAAM,IAAA,GAAO,GAAA,EAAK,QAAA,CAAS,IAAA,IAAQ,EAAA;AACnC,IAAA,IAAI,CAAC,OAAO,CAAC,IAAA,CAAK,SAAS,CAAA,EAAG,mBAAmB,GAAG,CAAA,EAAG;AACrD,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,SAAS,IAAI,eAAA,CAAgB,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAChD,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,GAAA,CAAI,mBAAmB,CAAA;AAC3C,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,oBAAoB,CAAA;AAG7C,IAAA,MAAM,OAAA,GAAU,KAAK,YAAA,EAAa;AAClC,IAAA,IAAI,CAAC,QAAQ,CAAC,KAAA,IAAS,CAAC,OAAA,IAAW,OAAA,CAAQ,UAAU,KAAA,EAAO;AAC1D,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,GAAA,CAAI,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,EAAA,EAAI,GAAA,CAAI,QAAA,CAAS,QAAA,GAAW,GAAA,CAAI,QAAA,CAAS,MAAM,CAAA;AAE3F,IAAA,IAAA,CAAK,KAAK,EAAE,MAAA,EAAQ,YAAA,EAAc,KAAA,EAAO,MAAM,CAAA;AAC/C,IAAA,IAAI;AACF,MAAA,MAAM,OAAO,MAAM,IAAA,CAAK,UAAU,IAAA,EAAM,OAAA,CAAQ,UAAU,KAAK,CAAA;AAC/D,MAAA,IAAI,OAAA,CAAQ,SAAS,OAAA,EAAS;AAG5B,QAAA,GAAA,CAAI,KAAA,EAAM;AAAA,MACZ;AACA,MAAA,OAAO,IAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,OAAA,GAAU,gBAAgB,KAAK,CAAA;AACrC,MAAA,IAAI,OAAA,CAAQ,SAAS,WAAA,EAAa;AAChC,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB;AACA,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAA,CAAK,UAAU,WAAA,GAAc,WAAA,EAAa,KAAA,EAAO,OAAA,EAAS,CAAA;AAC9E,MAAA,MAAM,OAAA;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,SAAA,CACJ,IAAA,EACA,UACA,KAAA,EACA,SAAA,GAAwC,MAAM,IAAA,EAC1B;AACpB,IAAA,MAAM,aAAa,IAAA,CAAK,WAAA;AACxB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,YAAA,EAAa,EAAG,KAAA,KAAU,KAAA;AAC/C,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,SAAS,IAAA,CAAK,OAAA,CAA0B,QAAQ,gBAAA,EAAkB;AAAA,MAC5F,MAAM,EAAE,IAAA,EAAM,WAAW,IAAA,CAAK,QAAA,EAAU,eAAe,QAAA,EAAS;AAAA,MAChE,SAAA,EAAW,IAAA;AAAA,MACX,QAAA,EAAU;AAAA,KACX,CAAA;AACD,IAAA,MAAM,YAAA,GACJ,SAAA,EAAU,KACT,UAAA,KAAe,IAAA,CAAK,cACjB,IAAI,aAAA,CAAc,WAAA,EAAa,6BAA6B,CAAA,GAC5D,IAAA,CAAA;AAAA,KAEH,OAAA,IAAW,IAAA,CAAK,YAAA,EAAa,EAAG,KAAA,KAAU,QACvC,IAAI,aAAA,CAAc,WAAA,EAAa,2BAA2B,CAAA,GAC1D,IAAA,CAAA;AACN,IAAA,IAAI,YAAA,EAAc;AAEhB,MAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CACX,OAAA,CAAQ,MAAA,EAAQ,cAAA,EAAgB;AAAA,QAC/B,WAAA,EAAa,EAAE,GAAA,EAAK,QAAA,CAAS,KAAK,QAAA,EAAU,QAAA,CAAS,SAAA,IAAa,IAAA,CAAK,QAAA,EAAS;AAAA,QAChF,QAAA,EAAU;AAAA,OACX,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AACjB,MAAA,MAAM,YAAA;AAAA,IACR;AACA,IAAA,MAAM,MAAA,GAAqB;AAAA,MACzB,KAAK,QAAA,CAAS,GAAA;AAAA,MACd,SAAA,EAAW,QAAA,CAAS,SAAA,IAAa,IAAA,CAAK,QAAA;AAAA,MACtC,UAAA,EAAY,SAAS,UAAA,IAAc,IAAA;AAAA,MACnC,MAAM,QAAA,CAAS;AAAA,KACjB;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,SAAA,CAAU,KAAK,QAAA,CAAS,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,MAAM,MAAM,CAAA;AACxD,IAAA,IAAA,CAAK,cAAA,EAAe;AACpB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,WAAA,EAAa,IAAA,EAAM,MAAA,CAAO,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,CAAA;AAClF,IAAA,OAAO,MAAA,CAAO,IAAA;AAAA,EAChB;AAAA,EAEA,aAAA,CACE,GAAA,EACA,KAAA,EACA,KAAA,EACA,YAAA,EACuB;AACvB,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,MAAA,IAAI,WAAA,GAA6B,IAAA;AAEjC,MAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAwB;AACzC,QAAA,IAAI,KAAA,CAAM,WAAW,IAAA,CAAK,QAAA,CAAS,MAAM,MAAA,IAAU,KAAA,CAAM,WAAW,KAAA,EAAO;AACzE,UAAA;AAAA,QACF;AACA,QAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,QAAA,IACE,CAAC,IAAA,IACD,OAAO,IAAA,KAAS,YAChB,IAAA,CAAK,IAAA,KAAS,iBAAA,IACd,IAAA,CAAK,KAAA,KAAU,KAAA,IACf,OAAO,IAAA,CAAK,SAAS,QAAA,EACrB;AACA,UAAA;AAAA,QACF;AACA,QAAA,IAAA,EAAK;AACL,QAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,MAAM,CAAA;AAAA,MAC3C,CAAA;AAIA,MAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAwB;AACzC,QAAA,IAAI,MAAM,GAAA,KAAQ,IAAA,CAAK,MAAM,IAAA,IAAQ,CAAC,MAAM,QAAA,EAAU;AACpD,UAAA;AAAA,QACF;AACA,QAAA,MAAM,MAAA,GAAS,KAAK,WAAA,EAAY;AAChC,QAAA,IAAI,MAAA,EAAQ;AACV,UAAA,IAAA,EAAK;AACL,UAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,CAAO,MAAM,CAAA;AAAA,QAC7C;AAAA,MACF,CAAA;AAIA,MAAA,MAAM,WAAA,GAAc,YAAY,MAAM;AACpC,QAAA,IAAI,CAAC,KAAA,CAAM,MAAA,IAAU,CAAC,WAAA,EAAY,EAAG,UAAS,EAAG;AAC/C,UAAA,WAAA,GAAc,IAAA;AACd,UAAA;AAAA,QACF;AACA,QAAA,WAAA,KAAgB,KAAK,GAAA,EAAI;AACzB,QAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,WAAA,IAAe,eAAA,EAAiB;AAC/C,UAAA,IAAA,EAAK;AACL,UAAA,MAAA,CAAO,IAAI,aAAA,CAAc,WAAA,EAAa,+BAA+B,CAAC,CAAA;AAAA,QACxE;AAAA,MACF,GAAG,eAAe,CAAA;AAElB,MAAA,MAAM,OAAA,GAAU,WAAW,MAAM;AAC/B,QAAA,IAAA,EAAK;AACL,QAAA,MAAA,CAAO,IAAI,aAAA,CAAc,WAAA,EAAa,mBAAmB,CAAC,CAAA;AAAA,MAC5D,GAAG,cAAc,CAAA;AAEjB,MAAA,MAAM,OAAO,MAAM;AACjB,QAAA,GAAA,CAAI,mBAAA,CAAoB,WAAW,SAAS,CAAA;AAC5C,QAAA,GAAA,CAAI,mBAAA,CAAoB,WAAW,SAAS,CAAA;AAC5C,QAAA,aAAA,CAAc,WAAW,CAAA;AACzB,QAAA,YAAA,CAAa,OAAO,CAAA;AAAA,MACtB,CAAA;AAEA,MAAA,GAAA,CAAI,gBAAA,CAAiB,WAAW,SAAS,CAAA;AACzC,MAAA,IAAI,IAAA,CAAK,SAAS,cAAA,EAAgB;AAChC,QAAA,GAAA,CAAI,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAAA,MAC3C;AACA,MAAA,YAAA,CAAa,IAAI,CAAA;AAAA,IACnB,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,SAAA,CAAU,KAAA,EAAe,SAAA,EAAmB,QAAA,EAAsC;AAChF,IAAA,MAAM,QAAQ,UAAA,CAAW;AAAA,MACvB,MAAA,EAAQ,SAAA,EAAU,EAAG,QAAA,CAAS,MAAA;AAAA,MAC9B,WAAW,IAAA,CAAK,QAAA;AAAA,MAChB,KAAA;AAAA,MACA,cAAA,EAAgB,SAAA;AAAA,MAChB,WAAW,qBAAA,EAAsB;AAAA,MACjC;AAAA,KACD,CAAA;AACD,IAAA,OAAO,GAAG,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,IAAI,wBAAwB,KAAK,CAAA,CAAA;AAAA,EACjE;AAAA,EAEA,WAAA,GAAc,CAAC,KAAA,KAAqC;AAClD,IAAA,IAAI,CAAC,MAAM,SAAA,EAAW;AACpB,MAAA;AAAA,IACF;AACA,IAAA,SAAA,EAAU,EAAG,mBAAA,CAAoB,UAAA,EAAY,IAAA,CAAK,WAAW,CAAA;AAC7D,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,MAAA,CAAO,WAAW,YAAA,EAAc;AACzD,MAAA,IAAA,CAAK,KAAK,EAAE,MAAA,EAAQ,KAAK,OAAA,GAAU,WAAA,GAAc,aAAa,CAAA;AAAA,IAChE;AAAA,EACF,CAAA;AAAA,EAEA,cAAA,GAAuB;AACrB,IAAA,IAAI,IAAA,CAAK,SAAS,cAAA,EAAgB;AAChC,MAAA,UAAA,CAAW,IAAA,CAAK,QAAA,CAAS,cAAA,EAAgB,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,YAAA,GAAsC;AACpC,IAAA,MAAM,OAAA,GAAU,KAAK,QAAA,CAAS,cAAA;AAC9B,IAAA,MAAM,UAAU,OAAA,GAAU,QAAA,CAAyB,SAAS,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA,GAAI,IAAA;AAClF,IAAA,IACE,CAAC,OAAA,IACD,OAAO,QAAQ,KAAA,KAAU,QAAA,IACzB,OAAO,OAAA,CAAQ,QAAA,KAAa,YAC5B,OAAO,OAAA,CAAQ,eAAe,QAAA,IAC9B,IAAA,CAAK,KAAI,GAAI,OAAA,CAAQ,aAAa,cAAA,EAClC;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,UAAA,GAAa,CAAC,KAAA,KAA8B;AAC1C,IAAA,IAAI,MAAM,GAAA,KAAQ,IAAA,IAAQ,MAAM,GAAA,KAAQ,IAAA,CAAK,MAAM,IAAA,EAAM;AACvD,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,WAAA,EAAY;AAChC,IAAA,IAAI,MAAA,EAAQ,GAAA,KAAQ,IAAA,CAAK,OAAA,EAAS,GAAA,EAAK;AACrC,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,MAAA,EAAQ,MAAA,GAAS,WAAA,GAAc,IAAA,CAAK,WAAW,YAAA,GAAe,WAAA;AAAA,MAC9D,IAAA,EAAM,QAAQ,IAAA,IAAQ,IAAA;AAAA,MACtB,QAAA,EAAU,KAAA;AAAA,MACV,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH,CAAA;AAAA,EAEA,iBAAiB,QAAA,EAAsC;AACrD,IAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,MAAA,IAAI,CAAC,gBAAA,CAAiB,IAAA,CAAK,QAAQ,CAAA,EAAG;AACpC,QAAA,MAAM,IAAI,SAAA,CAAU,CAAA,EAAG,YAAY,CAAA,wBAAA,EAA2B,gBAAgB,CAAA,CAAE,CAAA;AAAA,MAClF;AACA,MAAA,OAAO,QAAA;AAAA,IACT;AACA,IAAA,MAAM,EAAE,OAAA,EAAQ,GAAI,IAAA,CAAK,QAAA;AACzB,IAAA,IAAI,MAAA,GAAwB,IAAA;AAC5B,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA;AAAA,IAC9C,CAAA,CAAA,MAAQ;AACN,MAAA,MAAA,GAAS,IAAA;AAAA,IACX;AACA,IAAA,IAAI,MAAA,IAAU,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA,EAAG;AAC3C,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,MAAM,SAAA,GAAY,YAAY,EAAE,CAAA;AAChC,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,QAAA,EAAU,SAAS,CAAA;AAAA,IAChD,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,OAAO,SAAA;AAAA,EACT;AAAA,EAEA,WAAA,GAAiC;AAC/B,IAAA,MAAM,SAAS,QAAA,CAAqB,IAAA,CAAK,SAAS,OAAA,EAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAC1E,IAAA,IACE,CAAC,MAAA,IACD,OAAO,MAAA,CAAO,GAAA,KAAQ,YACtB,OAAO,MAAA,CAAO,SAAA,KAAc,QAAA,IAC5B,CAAC,MAAA,CAAO,IAAA,IACR,OAAO,MAAA,CAAO,SAAS,QAAA,EACvB;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI,MAAA,CAAO,cAAc,IAAA,CAAK,KAAA,CAAM,OAAO,UAAU,CAAA,IAAK,IAAA,CAAK,GAAA,EAAI,EAAG;AACpE,MAAA,UAAA,CAAW,IAAA,CAAK,QAAA,CAAS,OAAA,EAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AACjD,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,YAAA,GAAqB;AACnB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,UAAA,CAAW,IAAA,CAAK,QAAA,CAAS,OAAA,EAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,EACnD;AAAA,EAEA,KAAK,KAAA,EAAiC;AACpC,IAAA,MAAM,OAAkB,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,GAAG,KAAA,EAAM;AACnD,IAAA,IACE,IAAA,CAAK,WAAW,IAAA,CAAK,MAAA,CAAO,UAC5B,IAAA,CAAK,QAAA,KAAa,KAAK,MAAA,CAAO,QAAA,IAC9B,KAAK,KAAA,KAAU,IAAA,CAAK,OAAO,KAAA,IAC3B,QAAA,CAAS,KAAK,IAAA,EAAM,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,EACpC;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,IAAI,CAAA;AAChC,IAAA,IAAA,CAAK,QAAA,CAAS,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA;AAAA,EAChC;AACF,CAAA;AAEA,SAAS,UAAU,GAAA,EAA4B;AAC7C,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAA,CAAI,GAAA,CAAI,UAAA,GAAa,WAAA,IAAe,CAAC,CAAC,CAAA;AACrF,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAA,CAAI,GAAA,CAAI,WAAA,GAAc,YAAA,IAAgB,CAAC,CAAC,CAAA;AACtF,EAAA,IAAI;AACF,IAAA,OAAO,GAAA,CAAI,IAAA;AAAA,MACT,EAAA;AAAA,MACA,UAAA;AAAA,MACA,mBAAmB,WAAW,CAAA,QAAA,EAAW,YAAY,CAAA,MAAA,EAAS,IAAI,QAAQ,GAAG,CAAA;AAAA,KAC/E;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,aAAA,CAAc,OAAe,GAAA,EAAsB;AAC1D,EAAA,IAAI;AACF,IAAA,KAAA,CAAM,QAAA,CAAS,QAAQ,GAAG,CAAA;AAC1B,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,QAAA,CAAS,GAAqB,CAAA,EAA8B;AACnE,EAAA,IAAI,MAAM,CAAA,EAAG;AACX,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI,CAAC,CAAA,IAAK,CAAC,CAAA,EAAG;AACZ,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAK,SAAA,CAAU,CAAC,CAAA,KAAM,IAAA,CAAK,UAAU,CAAC,CAAA;AAC/C;AAEA,SAAS,gBAAgB,KAAA,EAA+B;AACtD,EAAA,IAAI,eAAA,CAAgB,KAAK,CAAA,EAAG;AAC1B,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAI,cAAc,SAAA,EAAW,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA,EAAG;AAAA,IAC1F,KAAA,EAAO;AAAA,GACR,CAAA;AACH;;;AClqBO,SAAS,aAAa,KAAA,EAAoC;AAC/D,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAO,MAAM;AAAA,IAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,CAAA,GAAI,SAAS,OAAA,CAAQ,KAAA,CAAM,IAAI,YAAY,CAAA,CAAA,CAAA,EAAK,GAAG,IAAI,CAAA;AAChE;;;ACkDA,IAAM,cAAA,GAAiB,WAAA;AACvB,IAAM,eAAA,GAAkB,WAAA;AACxB,IAAM,iBAAA,GAAoB,eAAA;AAG1B,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,sBAAA,GAAyB,IAAA;AAC/B,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,cAAA,GAAiB,GAAA;AAGvB,SAAS,WAAW,QAAA,EAA0B;AAC5C,EAAA,MAAM,UAAU,IAAA,CAAK,GAAA,CAAI,iBAAiB,CAAA,KAAM,QAAA,GAAW,IAAI,cAAc,CAAA;AAC7E,EAAA,OAAO,OAAA,GAAU,CAAA,GAAI,IAAA,CAAK,MAAA,MAAY,OAAA,GAAU,CAAA,CAAA;AAClD;AASO,IAAM,mBAAN,MAAoD;AAAA,EAChD,QAAA,GAAW,YAAY,EAAE,CAAA;AAAA,EAClC,QAAA;AAAA,EACA,SAAA,uBAAgB,GAAA,EAAyB;AAAA,EACzC,cAAA,GAAiB,IAAI,OAAA,EAAwB;AAAA,EAC7C,OAAA,GAA0B,MAAA;AAAA,EAC1B,WAAA,GAAsC,IAAA;AAAA,EACtC,KAAA,GAA6B,IAAA;AAAA,EAC7B,QAAA,GAAW,KAAA;AAAA,EACX,QAAA,GAAW,KAAA;AAAA,EACX,SAAA,GAAY,CAAA;AAAA,EACZ,IAAA,GAAO,CAAA;AAAA,EAEP,YAAY,OAAA,EAAkC;AAC5C,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA;AAAA,EAClB;AAAA,EAEA,IAAI,MAAA,GAAyB;AAC3B,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAI,GAAA,GAAc;AAChB,IAAA,OAAO,GAAG,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,aAAA,EAAgB,KAAK,QAAQ,CAAA,KAAA,CAAA;AAAA,EAC3D;AAAA,EAEA,SAAA,CAAU,OAAA,EAAiB,MAAA,EAAgB,QAAA,EAA6C;AACtF,IAAA,IAAI,WAAA,GAAc,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,WAAA,GAAc,QAAA,CAAS,WAAW,CAAA,GAAI,MAAA;AACrD,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,WAAA,uBAAkB,GAAA,EAAI;AACtB,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAA,EAAS,WAAW,CAAA;AAAA,IACzC;AACA,IAAA,WAAA,CAAY,GAAA,CAAI,UAAU,MAAM,CAAA;AAGhC,IAAA,IAAI,MAAA,KAAW,MAAA,IAAa,MAAA,GAAS,MAAA,EAAQ;AAC3C,MAAA,IAAA,CAAK,QAAA,EAAS;AAAA,IAChB;AAEA,IAAA,OAAO;AAAA,MACL,OAAA;AAAA,MACA,SAAA,EAAW,CAAC,EAAA,KAAO;AACjB,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AAC1C,QAAA,MAAM,MAAA,GAAS,OAAA,EAAS,GAAA,CAAI,QAAQ,CAAA;AACpC,QAAA,IAAI,OAAA,IAAW,MAAA,KAAW,MAAA,IAAa,EAAA,GAAK,MAAA,EAAQ;AAClD,UAAA,OAAA,CAAQ,GAAA,CAAI,UAAU,EAAE,CAAA;AAAA,QAC1B;AAAA,MACF,CAAA;AAAA,MACA,aAAa,MAAM;AACjB,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AAC1C,QAAA,IAAI,CAAC,OAAA,EAAS,MAAA,CAAO,QAAQ,CAAA,EAAG;AAC9B,UAAA;AAAA,QACF;AACA,QAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,UAAA,IAAA,CAAK,SAAA,CAAU,OAAO,OAAO,CAAA;AAC7B,UAAA,IAAA,CAAK,QAAA,EAAS;AAAA,QAChB;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA,EAEA,SAAS,QAAA,EAAwD;AAC/D,IAAA,OAAO,IAAA,CAAK,cAAA,CAAe,EAAA,CAAG,QAAQ,CAAA;AAAA,EACxC;AAAA;AAAA,EAGA,OAAO,OAAA,EAAqC;AAC1C,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AAC9C,IAAA,OAAO,WAAA,GAAc,QAAA,CAAS,WAAW,CAAA,GAAI,MAAA;AAAA,EAC/C;AAAA,EAEA,IAAA,GAAa;AACX,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AACrB,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AACxB,IAAA,IAAA,CAAK,KAAA,IAAQ;AACb,IAAA,IAAA,CAAK,WAAW,MAAM,CAAA;AAAA,EACxB;AAAA,EAEA,QAAA,GAAiB;AACf,IAAA,IAAI,KAAK,QAAA,EAAU;AACjB,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AACxB,IAAA,IAAA,CAAK,KAAA,IAAQ;AACb,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,IAAA,KAAS,CAAA,EAAG;AAC7B,MAAA,IAAA,CAAK,WAAW,MAAM,CAAA;AACtB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,KAAK,KAAK,KAAA,EAAM;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAI;AACF,MAAA,OAAO,CAAC,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,SAAA,CAAU,OAAO,CAAA,EAAG;AAChD,QAAA,IAAI,IAAA,CAAK,YAAY,MAAA,EAAQ;AAC3B,UAAA,IAAA,CAAK,WAAW,YAAY,CAAA;AAAA,QAC9B;AACA,QAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,QAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,QAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,QAAA,IAAI,QAAA,GAAW,CAAA;AAEf,QAAA,IAAI;AACF,UAAA,MAAM,WAAW,MAAM,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,KAAK,GAAA,EAAK;AAAA,YACnD,MAAA,EAAQ,MAAA;AAAA,YACR,OAAA,EAAS,EAAE,cAAA,EAAgB,mCAAA,EAAoC;AAAA,YAC/D,IAAA,EAAM,KAAK,KAAA,EAAM;AAAA,YACjB,WAAA,EAAa,MAAA;AAAA,YACb,IAAA,EAAM,MAAA;AAAA,YACN,QAAQ,UAAA,CAAW;AAAA,WACpB,CAAA;AACD,UAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,YAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mCAAA,EAAsC,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,UACzE;AACA,UAAA,MAAM,sBAAA,CAAuB,QAAA,EAAU,CAAC,QAAA,KAAa;AACnD,YAAA,QAAA,IAAY,QAAA,CAAS,MAAA;AACrB,YAAA,IAAA,CAAK,SAAS,QAAQ,CAAA;AAAA,UACxB,CAAC,CAAA;AAAA,QACH,SAAS,KAAA,EAAO;AACd,UAAA,IAAI,UAAA,CAAW,OAAO,OAAA,EAAS;AAC7B,YAAA;AAAA,UACF;AACA,UAAA,IAAA,CAAK,SAAA,EAAA;AACL,UAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,yBAAA,EAA2B,KAAK,CAAA;AAClD,UAAA,IAAI,IAAA,CAAK,SAAA,KAAc,IAAA,CAAK,QAAA,CAAS,oBAAoB,CAAA,CAAA,EAAI;AAC3D,YAAA,IAAA,CAAK,WAAW,QAAQ,CAAA;AAAA,UAC1B;AACA,UAAA,MAAM,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,SAAS,CAAC,CAAA;AAC5C,UAAA;AAAA,QACF,CAAA,SAAE;AACA,UAAA,IAAI,IAAA,CAAK,gBAAgB,UAAA,EAAY;AACnC,YAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,UACrB;AAAA,QACF;AAEA,QAAA,IAAA,CAAK,SAAA,GAAY,CAAA;AACjB,QAAA,IAAA,CAAK,WAAW,WAAW,CAAA;AAC3B,QAAA,IAAI,aAAa,CAAA,IAAK,IAAA,CAAK,GAAA,EAAI,GAAI,YAAY,iBAAA,EAAmB;AAChE,UAAA,MAAM,IAAA,CAAK,OAAO,sBAAsB,CAAA;AAAA,QAC1C;AAAA,MACF;AAAA,IACF,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,KAAA,GAAgB;AACd,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,KAAA,MAAW,CAAC,OAAA,EAAS,WAAW,CAAA,IAAK,KAAK,SAAA,EAAW;AACnD,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,kBAAA,CAAmB,OAAO,CAAA,CAAE,OAAA,CAAQ,OAAA,EAAS,GAAG,CAAC,CAAA,CAAA,EAAI,QAAA,CAAS,WAAW,CAAC,CAAA,CAAE,CAAA;AAAA,IAC5F;AACA,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,MAAA,EAAS,EAAE,IAAA,CAAK,IAAI,CAAA,CAAE,CAAA;AACjC,IAAA,OAAO,KAAA,CAAM,KAAK,GAAG,CAAA;AAAA,EACvB;AAAA,EAEA,SAAS,QAAA,EAA2B;AAClC,IAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC1B,MAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AACnC,QAAA;AAAA,MACF;AACA,MAAA,MAAM,OAAA,GAAU,GAAA;AAChB,MAAA,IAAI,OAAA,CAAQ,YAAY,cAAA,EAAgB;AACtC,QAAA,MAAM,SAAA,GAAa,OAAA,CAAQ,IAAA,IAAQ,EAAC;AACpC,QAAA,KAAA,MAAW,CAAC,OAAA,EAAS,EAAE,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACrD,UAAA,MAAMC,YAAAA,GAAc,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AAC9C,UAAA,IAAIA,YAAAA,IAAe,OAAO,EAAA,KAAO,QAAA,EAAU;AACzC,YAAA,IAAA,CAAK,YAAA,CAAaA,cAAa,EAAE,CAAA;AAAA,UACnC;AAAA,QACF;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,QAAQ,OAAO,CAAA;AACtD,MAAA,IAAI,CAAC,WAAA,IAAe,OAAO,OAAA,CAAQ,eAAe,QAAA,EAAU;AAC1D,QAAA;AAAA,MACF;AACA,MAAA,KAAA,MAAW,CAAC,QAAA,EAAU,MAAM,KAAK,CAAC,GAAG,WAAW,CAAA,EAAG;AAGjD,QAAA,IAAI,MAAA,IAAU,CAAA,IAAK,OAAA,CAAQ,UAAA,IAAc,MAAA,EAAQ;AAC/C,UAAA;AAAA,QACF;AACA,QAAA,WAAA,CAAY,GAAA,CAAI,QAAA,EAAU,OAAA,CAAQ,UAAU,CAAA;AAC5C,QAAA,MAAA,CAAO,QAAA,EAAU,EAAE,IAAA,EAAM,SAAA,EAAW,MAAM,OAAA,CAAQ,IAAA,EAAM,SAAS,CAAA;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAA,CAAa,aAA0B,EAAA,EAAkB;AACvD,IAAA,KAAA,MAAW,CAAC,QAAA,EAAU,MAAM,KAAK,CAAC,GAAG,WAAW,CAAA,EAAG;AACjD,MAAA,WAAA,CAAY,GAAA,CAAI,UAAU,EAAE,CAAA;AAE5B,MAAA,IAAI,MAAA,KAAW,EAAA,IAAM,EAAA,KAAO,MAAA,EAAQ;AAClC,QAAA;AAAA,MACF;AACA,MAAA,IAAI,KAAK,MAAA,EAAQ;AACf,QAAA,MAAA,CAAO,UAAU,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,IAAI,CAAA;AAAA,MAC/C,CAAA,MAAA,IAAW,UAAU,CAAA,EAAG;AACtB,QAAA,MAAA,CAAO,UAAU,EAAE,IAAA,EAAM,KAAA,EAAO,MAAA,EAAQ,IAAI,CAAA;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,EAAA,EAA2B;AAChC,IAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,MAAA,MAAM,OAAO,MAAM;AACjB,QAAA,YAAA,CAAa,KAAK,CAAA;AAClB,QAAA,IAAI,IAAA,CAAK,UAAU,IAAA,EAAM;AACvB,UAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,QACf;AACA,QAAA,OAAA,EAAQ;AAAA,MACV,CAAA;AACA,MAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,EAAM,EAAE,CAAA;AACjC,MAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AAAA,IACf,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,WAAW,MAAA,EAA8B;AACvC,IAAA,IAAI,MAAA,KAAW,KAAK,OAAA,EAAS;AAC3B,MAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,MAAA,IAAA,CAAK,cAAA,CAAe,KAAK,MAAM,CAAA;AAAA,IACjC;AAAA,EACF;AACF,CAAA;AAEA,SAAS,SAAS,WAAA,EAAkC;AAClD,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,CAAY,QAAQ,CAAA;AACzC;AAEA,SAAS,MAAA,CAAO,UAAuB,KAAA,EAAuB;AAC5D,EAAA,IAAI;AACF,IAAA,QAAA,CAAS,KAAK,CAAA;AAAA,EAChB,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,EACrB;AACF;AAOA,eAAsB,sBAAA,CACpB,UACA,OAAA,EACe;AACf,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAAkB;AAC9B,IAAA,MAAM,OAAO,KAAA,CAAM,OAAA,CAAQ,iBAAA,EAAmB,eAAe,EAAE,IAAA,EAAK;AACpE,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC9B,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,EAAG;AACzB,MAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,IAChB;AAAA,EACF,CAAA;AACA,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,KAAmB;AAChC,IAAA,IAAI,KAAA;AACJ,IAAA,OAAA,CAAQ,KAAA,GAAQ,MAAA,CAAO,OAAA,CAAQ,eAAe,OAAO,EAAA,EAAI;AACvD,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA;AACnC,MAAA,MAAA,GAAS,MAAA,CAAO,KAAA,CAAM,KAAA,GAAQ,eAAA,CAAgB,MAAM,CAAA;AACpD,MAAA,IAAA,CAAK,KAAK,CAAA;AAAA,IACZ;AACA,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,IAAA,CAAK,MAAM,CAAA;AACX,MAAA,MAAA,GAAS,EAAA;AAAA,IACX;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAA,EAAM,SAAA,EAAU;AACxC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAA,GAAS,MAAM,SAAS,IAAA,EAAK;AAC7B,IAAA,KAAA,CAAM,IAAI,CAAA;AACV,IAAA;AAAA,EACF;AACA,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,WAAS;AACP,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,IAAA,IAAI,IAAA,EAAM;AACR,MAAA;AAAA,IACF;AACA,IAAA,MAAA,IAAU,QAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAM,CAAA;AAChD,IAAA,KAAA,CAAM,KAAK,CAAA;AAAA,EACb;AACA,EAAA,MAAA,IAAU,QAAQ,MAAA,EAAO;AACzB,EAAA,KAAA,CAAM,IAAI,CAAA;AACZ;AAYO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,KAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,GAAkC,IAAA;AAAA,EAClC,OAAA,GAAU,KAAA;AAAA,EACV,UAAA,GAAa,CAAA;AAAA,EACb,cAAA,GAAsC,IAAA;AAAA,EAEtC,WAAA,CAAY,IAAA,EAA8B,OAAA,GAAoC,EAAC,EAAG;AAChF,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,MAAA,IAAU,GAAA;AACjC,IAAA,IAAA,CAAK,MAAA,GAAS,QAAQ,KAAA,IAAS,IAAA;AAC/B,IAAA,IAAA,CAAK,cAAc,IAAA,CAAK,OAAA;AAAA,EAC1B;AAAA,EAEA,IAAI,MAAA,GAAkB;AACpB,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA,EAEA,IAAI,UAAA,GAAqB;AACvB,IAAA,OAAO,IAAA,CAAK,WAAA;AAAA,EACd;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAA,CAAK,cAAc,IAAA,CAAK,OAAA;AACxB,IAAA,IAAA,CAAK,UAAA,GAAa,KAAK,GAAA,EAAI;AAC3B,IAAA,IAAA,CAAK,cAAA,GAAiB,kBAAA,CAAmB,IAAA,CAAK,mBAAmB,CAAA;AACjE,IAAA,IAAA,CAAK,SAAA,EAAU;AAAA,EACjB;AAAA,EAEA,IAAA,GAAa;AACX,IAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AACf,IAAA,YAAA,CAAa,KAAK,MAAM,CAAA;AACxB,IAAA,IAAA,CAAK,cAAA,IAAiB;AACtB,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,EACxB;AAAA,EAEA,MAAA,GAAwB;AACtB,IAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,IAAA,EAAK,CAAE,QAAQ,MAAM;AACzC,QAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,QAAA,IAAA,CAAK,SAAA,EAAU;AAAA,MACjB,CAAC,CAAA;AAAA,IACH;AACA,IAAA,OAAO,IAAA,CAAK,SAAA;AAAA,EACd;AAAA,EAEA,MAAM,IAAA,GAAsB;AAC1B,IAAA,YAAA,CAAa,KAAK,MAAM,CAAA;AACxB,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,IAAI;AACF,MAAA,OAAA,GAAU,MAAM,KAAK,KAAA,EAAM;AAAA,IAC7B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAA,GAAU,KAAA;AAAA,IACZ;AACA,IAAA,IAAA,CAAK,UAAA,GAAa,KAAK,GAAA,EAAI;AAC3B,IAAA,IAAA,CAAK,WAAA,GAAc,OAAA,GAAU,IAAA,CAAK,OAAA,GAAU,IAAA,CAAK,IAAI,IAAA,CAAK,WAAA,GAAc,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA;AAAA,EACxF;AAAA,EAEA,SAAA,GAAkB;AAChB,IAAA,YAAA,CAAa,KAAK,MAAM,CAAA;AACxB,IAAA,IAAI,CAAC,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,SAAA,IAAa,kBAAiB,EAAG;AACzD,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,WAAW,MAAM,KAAK,KAAK,MAAA,EAAO,EAAG,KAAK,WAAW,CAAA;AAAA,EACrE;AAAA,EAEA,sBAAsB,MAAY;AAChC,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,kBAAiB,EAAG;AACtB,MAAA,YAAA,CAAa,KAAK,MAAM,CAAA;AAAA,IAC1B,WAAW,IAAA,CAAK,GAAA,KAAQ,IAAA,CAAK,UAAA,IAAc,KAAK,WAAA,EAAa;AAC3D,MAAA,KAAK,KAAK,MAAA,EAAO;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,SAAA,EAAU;AAAA,IACjB;AAAA,EACF,CAAA;AACF,CAAA;;;ACzcO,SAAS,WAAA,CAAY,OAA2B,EAAA,EAAoC;AACzF,EAAA,OAAO,IAAA,CAAK,OAAO,CAAC,CAAA,KAAM,EAAE,EAAA,KAAO,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA;AAC9C;AAEO,SAAS,YAAA,CAAa,OAA2B,MAAA,EAAwC;AAC9F,EAAA,OAAO,IAAA,CAAK,OAAO,CAAC,CAAA,KAAM,EAAE,MAAA,KAAW,MAAA,EAAQ,CAAA,EAAG,EAAE,CAAA;AACtD;AAEA,SAAS,IAAA,CACP,KAAA,EACA,KAAA,EACA,KAAA,EACA,IAAA,EACwB;AACxB,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,QAAA,GAAW,CAAC,GAAG,IAAA,EAAM,KAAK,EAAE,CAAA;AAClC,IAAA,IAAI,KAAA,CAAM,IAAI,CAAA,EAAG;AACf,MAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,QAAA,EAAS;AAAA,IACvC;AACA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC5B,MAAA,MAAM,QAAQ,IAAA,CAAK,IAAA,CAAK,UAAU,KAAA,EAAO,KAAA,GAAQ,GAAG,QAAQ,CAAA;AAC5D,MAAA,IAAI,KAAA,EAAO;AACT,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAUO,SAAS,aAAA,CACd,KAAA,EACA,EAAA,EACA,MAAA,EACoB;AACpB,EAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,EAAA,EAAI,MAAM,CAAA,IAAK,KAAA;AACvC;AAEA,SAAS,OAAA,CACP,KAAA,EACA,EAAA,EACA,MAAA,EACkB;AAClB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,IAAA,IAAI,IAAA,CAAK,OAAO,EAAA,EAAI;AAClB,MAAA,MAAM,IAAA,GAAO,OAAO,IAAI,CAAA;AACxB,MAAA,IAAI,SAAS,IAAA,EAAM;AACjB,QAAA,OAAO,IAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,EAAM;AACzB,MAAA,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA;AACV,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC5B,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,QAAA,EAAU,IAAI,MAAM,CAAA;AAClD,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,MAAM,IAAA,GAAO,MAAM,KAAA,EAAM;AACzB,QAAA,IAAA,CAAK,CAAC,CAAA,GAAI,EAAE,GAAG,MAAM,QAAA,EAAS;AAC9B,QAAA,OAAO,IAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAMO,SAAS,YAAA,CAAa,OAAgB,QAAA,EAA4B;AACvE,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,KAAA,CAAM,QAAA,EAAU,SAAS,QAAQ,CAAA;AAEhE,EAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,CAAM,QAAA,CAAS,UAAU,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,UAAU,CAAA;AAC3E,EAAA,IAAI,KAAA,IAAS,UAAA,CAAW,KAAA,EAAO,QAAQ,CAAA,EAAG;AACxC,IAAA,OAAO,aAAa,KAAA,CAAM,QAAA,GAAW,QAAQ,EAAE,GAAG,OAAO,QAAA,EAAS;AAAA,EACpE;AACA,EAAA,OAAO,EAAE,GAAG,QAAA,EAAU,QAAA,EAAS;AACjC;AAEA,SAAS,aAAA,CAAc,OAAkB,QAAA,EAAgC;AACvE,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AACrD,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM;AACjC,IAAA,MAAM,QAAA,GAAW,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AACnC,IAAA,OAAO,QAAA,GAAW,YAAA,CAAa,QAAA,EAAU,CAAC,CAAA,GAAI,CAAA;AAAA,EAChD,CAAC,CAAA;AACD,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAC9C,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,EAAG;AACnB,MAAA,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IACf;AAAA,EACF;AACA,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,KAAW,KAAA,CAAM,MAAA,IAAU,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,KAAM,KAAA,CAAM,CAAC,CAAC,CAAA;AACzF,EAAA,OAAO,YAAY,KAAA,GAAQ,MAAA;AAC7B;AAEA,SAAS,UAAA,CAAW,GAAY,CAAA,EAAqB;AACnD,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,EAA2B;AACxD,IAAA,IAAI,QAAQ,UAAA,EAAY;AACtB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAO,EAAE,GAAG,CAAA;AAClB,IAAA,MAAM,KAAA,GAAQ,EAAE,GAAG,CAAA;AACnB,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA;AAAA,IACF;AACA,IAAA,IACE,OAAO,IAAA,KAAS,QAAA,IAChB,OAAO,KAAA,KAAU,QAAA,IACjB,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,EAC7C;AACA,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,YAAA,CAAa,OAA2B,QAAA,EAAuC;AAC7F,EAAA,OAAO,aAAA,CAAc,OAAO,QAAA,CAAS,EAAA,EAAI,CAAC,KAAA,KAAU,YAAA,CAAa,KAAA,EAAO,QAAQ,CAAC,CAAA;AACnF;AAEO,SAAS,UAAU,OAAA,EAA2B;AACnD,EAAA,IAAI,QAAQ,OAAA,IAAW,OAAA,CAAQ,SAAS,EAAA,IAAM,OAAA,CAAQ,WAAW,IAAA,EAAM;AACrE,IAAA,OAAO,OAAA;AAAA,EACT;AACA,EAAA,OAAO;AAAA,IACL,GAAG,OAAA;AAAA,IACH,OAAA,EAAS,IAAA;AAAA,IACT,IAAA,EAAM,EAAA;AAAA,IACN,MAAA,EAAQ,IAAA;AAAA,IACR,OAAO,EAAE,GAAG,OAAA,CAAQ,KAAA,EAAO,UAAU,KAAA,EAAM;AAAA,IAC3C,GAAA,EAAK,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAK,MAAM,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,IAAA,EAAM,KAAA;AAAM,GACjE;AACF;AAEO,SAAS,gBAAA,CAAiB,OAA2B,EAAA,EAAgC;AAC1F,EAAA,OAAO,aAAA,CAAc,KAAA,EAAO,EAAA,EAAI,SAAS,CAAA;AAC3C;AAGO,SAAS,UAAA,CACd,KAAA,EACA,OAAA,EACA,QAAA,EACoB;AACpB,EAAA,IAAI,WAAA,CAAY,KAAA,EAAO,OAAA,CAAQ,EAAE,CAAA,EAAG;AAClC,IAAA,OAAO,YAAA,CAAa,OAAO,OAAO,CAAA;AAAA,EACpC;AACA,EAAA,IAAI,aAAa,KAAA,EAAO;AACtB,IAAA,OAAO,CAAC,GAAG,KAAA,EAAO,OAAO,CAAA;AAAA,EAC3B;AAEA,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,OAAO,QAAQ,KAAA,CAAM,MAAA,IAAU,KAAA,CAAM,KAAK,EAAG,MAAA,EAAQ;AACnD,IAAA,KAAA,EAAA;AAAA,EACF;AACA,EAAA,OAAO,CAAC,GAAG,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,EAAG,OAAA,EAAS,GAAG,KAAA,CAAM,KAAA,CAAM,KAAK,CAAC,CAAA;AAClE;AAOO,SAAS,YACd,KAAA,EACA,QAAA,EACA,SACA,QAAA,EACA,EAAE,YAAW,EACc;AAC3B,EAAA,IAAI,WAAA,CAAY,KAAA,EAAO,OAAA,CAAQ,EAAE,CAAA,EAAG;AAClC,IAAA,OAAO,YAAA,CAAa,OAAO,OAAO,CAAA;AAAA,EACpC;AACA,EAAA,MAAM,QAAA,GAAW,WAAA,CAAY,KAAA,EAAO,QAAQ,CAAA;AAC5C,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,QAAA,CAAS,IAAI,CAAA;AACvC,EAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,SAAA,EAAW,CAAC,IAAA,KAAS;AACzC,IAAA,MAAM,QAAA,GAAW,KAAK,EAAA,KAAO,QAAA;AAC7B,IAAA,MAAM,WAAW,QAAA,GACb,QAAA,KAAa,OAAA,GACX,CAAC,SAAS,GAAG,IAAA,CAAK,QAAQ,CAAA,GAC1B,CAAC,GAAG,IAAA,CAAK,QAAA,EAAU,OAAO,IAC5B,IAAA,CAAK,QAAA;AACT,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,QAAA,EAAS;AAAA,IAC7B;AACA,IAAA,OAAO;AAAA,MACL,GAAG,IAAA;AAAA,MACH,QAAA;AAAA,MACA,kBAAA,EAAoB,QAAA,GAAW,IAAA,CAAK,kBAAA,GAAqB,IAAI,IAAA,CAAK,kBAAA;AAAA,MAClE,sBAAA,EAAwB,KAAK,sBAAA,GAAyB;AAAA,KACxD;AAAA,EACF,CAAC,CAAA;AACH;AAGA,SAAS,OAAA,CACP,KAAA,EACA,GAAA,EACA,MAAA,EACW;AACX,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS;AACzB,IAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AACrB,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA,CAAS,KAAK,CAAC,CAAA,KAAM,IAAI,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,IACpD,OAAA,CAAQ,IAAA,CAAK,UAAU,GAAA,EAAK,MAAM,IAClC,IAAA,CAAK,QAAA;AACT,IAAA,OAAO,MAAA,CAAO,aAAa,IAAA,CAAK,QAAA,GAAW,OAAO,EAAE,GAAG,IAAA,EAAM,QAAA,EAAU,CAAA;AAAA,EACzE,CAAC,CAAA;AACH;AAkBO,SAAS,aAAA,CACd,KAAA,EACA,QAAA,EACA,IAAA,EACW;AACX,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,EAAA,EAAI,CAAC,CAAC,CAAC,CAAA;AACnD,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM;AAC9B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AAC1B,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,CAAA;AAAA,IACT;AACA,IAAA,MAAM,MAAA,GAAS,YAAA,CAAa,CAAA,EAAG,IAAI,CAAA;AACnC,IAAA,OAAA,KAAY,MAAA,KAAW,CAAA;AACvB,IAAA,OAAO,MAAA;AAAA,EACT,CAAC,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAC/C,EAAA,MAAM,QAAQ,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,QAAA,CAAS,GAAA,CAAI,CAAA,CAAE,EAAE,KAAK,CAAC,WAAA,CAAY,IAAA,EAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AACpF,EAAA,IAAI,CAAC,OAAA,IAAW,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAClC,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,CAAC,GAAG,MAAA,EAAQ,GAAG,KAAK,CAAA;AAC7B;AAGO,SAAS,WAAW,KAAA,EAAqC;AAC9D,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,MAAM,IAAA,GAAO,CAAC,KAAA,KAA8B;AAC1C,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,MAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,QAAA,GAAA,CAAI,IAAA,CAAK,KAAK,EAAE,CAAA;AAAA,MAClB;AACA,MAAA,IAAA,CAAK,KAAK,QAAQ,CAAA;AAAA,IACpB;AAAA,EACF,CAAA;AACA,EAAA,IAAA,CAAK,KAAK,CAAA;AACV,EAAA,OAAO,GAAA;AACT;AAGO,SAAS,UAAU,KAAA,EAAmC;AAC3D,EAAA,IAAI,GAAA,GAAM,CAAA;AACV,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,GAAA,GAAM,IAAA,CAAK,IAAI,GAAA,EAAK,IAAA,CAAK,QAAQ,SAAA,CAAU,IAAA,CAAK,QAAQ,CAAC,CAAA;AAAA,EAC3D;AACA,EAAA,OAAO,GAAA;AACT;AAEO,SAAS,SAAA,CAAU,OAA2B,SAAA,EAAyC;AAC5F,EAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,SAAS,CAAA;AAChC,EAAA,MAAM,UAAU,KAAA,CAAM,GAAA;AAAA,IAAI,CAAC,CAAA,KACzB,CAAA,CAAE,WAAW,MAAA,CAAO,GAAA,CAAI,EAAE,EAAE,CAAA,GAAI,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,MAAA,EAAQ,OAAO,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA;AAAE,GACvE;AACA,EAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,SAAA,CAAU,GAAA,CAAI,CAAC,EAAA,EAAI,KAAA,KAAU,CAAC,EAAA,EAAI,KAAK,CAAC,CAAC,CAAA;AAC/D,EAAA,MAAM,QAAA,GAAW,QACd,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAM,CAAA,CACtB,IAAA,CAAK,CAAC,CAAA,EAAG,OAAO,KAAA,CAAM,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,IAAK,CAAA,KAAM,MAAM,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,IAAK,CAAA,CAAE,CAAA;AACjE,EAAA,OAAO,CAAC,GAAG,QAAA,EAAU,GAAG,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,MAAM,CAAC,CAAA;AAC1D;AAEO,SAAS,aAAa,IAAA,EAA4B;AACvD,EAAA,OAAO,IAAA,KAAS,WAAW,KAAA,GAAQ,OAAA;AACrC;AAEO,SAAS,cAAc,IAAA,EAA4B;AACxD,EAAA,OAAO,IAAA,KAAS,WAAW,OAAA,GAAU,KAAA;AACvC;;;ACtIA,IAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAM,mBAAA,GAAsB,CAAA;AAC5B,IAAM,yBAAA,GAA4B,CAAA;AAClC,IAAM,aAAA,GAAgB,CAAA;AAEf,IAAM,gBAAN,MAA4C;AAAA,EACxC,WAA0B,mBAAA,EAAoB;AAAA,EACvD,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA,GAAU,IAAI,OAAA,EAAqB;AAAA;AAAA,EAEnC,YAAgC,EAAC;AAAA,EACjC,iBAAA,GAAoB,CAAA;AAAA;AAAA,EAEpB,WAAA,GAAc,CAAA;AAAA,EACd,eAAA,GAA0C,IAAA;AAAA,EAC1C,WAA2B,EAAC;AAAA;AAAA,EAE5B,IAAA,GAAO,CAAA;AAAA;AAAA,EAEP,UAAA,uBAAiB,GAAA,EAAoB;AAAA,EACrC,MAAA,uBAAa,GAAA,EAAwB;AAAA,EACrC,YAAA,GAA8B,IAAA;AAAA,EAC9B,aAAA,GAA6C,IAAA;AAAA,EAC7C,WAAA,GAAmC,IAAA;AAAA,EACnC,UAAA;AAAA;AAAA,EAEA,SAAA,GAA2B,IAAA;AAAA,EAC3B,gBAAA,GAAmB,CAAA;AAAA,EACnB,QAAA,uBAAe,GAAA,EAAqB;AAAA,EACpC,iBAAA,GAAoB,KAAA;AAAA,EACpB,aAAA,GAA+B,QAAQ,OAAA,EAAQ;AAAA,EAC/C,gBAAA,GAAmB,CAAA;AAAA,EACnB,aAAA;AAAA,EACA,UAAA,GAAmC,IAAA;AAAA,EACnC,gBAAA,GAAmB,CAAA;AAAA,EACnB,aAAA;AAAA,EACA,SAAA,GAAY,KAAA;AAAA,EAEZ,WAAA,CAAY,MAAA,EAAmB,IAAA,EAAkB,IAAA,EAAa;AAC5D,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAA;AACb,IAAA,IAAA,CAAK,MAAA,GAAS,OAAO,MAAA,CAAO;AAAA,MAC1B,MAAA;AAAA,MACA,OAAA,EAAS,gBAAgB,MAAM,CAAA;AAAA,MAC/B,UAAU,EAAC;AAAA,MACX,IAAA,EAAM,QAAQ,MAAA,CAAO,IAAA;AAAA,MACrB,MAAA,EAAQ,MAAA;AAAA,MACR,KAAA,EAAO,IAAA;AAAA,MACP,IAAA,EAAM,CAAA;AAAA,MACN,OAAA,EAAS,KAAA;AAAA,MACT,WAAA,EAAa,KAAA;AAAA,MACb,UAAA,EAAY,CAAA;AAAA,MACZ,UAAU,EAAC;AAAA,MACX,kBAAkB,EAAC;AAAA,MACnB,UAAA,EAAY;AAAA,KACY,CAAA;AAC1B,IAAA,IAAA,CAAK,aAAa,IAAI,iBAAA,CAAkB,MAAM,IAAA,CAAK,cAAc,CAAA;AAAA,EACnE;AAAA,EAEA,IAAI,EAAA,GAAa;AACf,IAAA,OAAO,IAAA,CAAK,OAAO,MAAA,CAAO,EAAA;AAAA,EAC5B;AAAA,EAEA,QAAA,GAA2B;AACzB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,UAAU,QAAA,EAAoD;AAC5D,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,QAAQ,CAAA;AAAA,EACjC;AAAA,EAEA,MAAM,IAAA,GAAsB;AAC1B,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,IAAI,eAAA,CAAgB,MAAM,CAAA,EAAG;AAC3B,MAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,OAAA,EAAS;AAGlC,QAAA,MAAM,KAAK,UAAA,EAAW;AACtB,QAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,OAAA,EAAS;AACxB,UAAA;AAAA,QACF;AAAA,MACF;AACA,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,OAAA,EAAS,QAAA,EAAU,EAAC,EAAG,OAAA,EAAS,KAAA,EAAO,IAAA,EAAM,CAAA,EAAG,CAAA;AACpE,MAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,EAAE,IAAA,CAAK,WAAA;AAC1B,IAAA,IAAA,CAAK,iBAAiB,KAAA,EAAM;AAC5B,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,IAAA,CAAK,eAAA,GAAkB,UAAA;AACvB,IAAA,IAAA,CAAK,WAAW,EAAC;AACjB,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,IAAA;AACzB,IAAA,IAAA,CAAK,KAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAO,MAAM,CAAA;AAE5C,IAAA,IAAI;AAGF,MAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,MAAA,IAAI,MAAA,CAAO,QAAA,KAAa,MAAA,IAAU,IAAA,KAAS,QAAA,EAAU;AACnD,QAAA,QAAA,GAAW,MAAM,IAAA,CAAK,aAAA,CAAc,MAAA,CAAO,EAAA,EAAI,WAAW,MAAM,CAAA;AAAA,MAClE;AACA,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,QAA2B,KAAA,EAAO,UAAA,CAAW,MAAA,CAAO,EAAE,CAAA,EAAG;AAAA,QAC9F,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA,EAAE;AAAA,QACvB,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AACD,MAAA,IAAI,eAAe,IAAA,CAAK,WAAA,IAAe,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,MAAM,CAAC,CAAA;AACvE,MAAA,MAAM,aAAA,GAAgB,SAAS,IAAA,IAAQ,IAAA;AACvC,MAAA,MAAM,KAAA,GAAQ,aAAA,KAAkB,QAAA,IAAY,CAAC,QAAA,CAAS,QAAA;AACtD,MAAA,IAAA,CAAK,SAAA,GACH,QAAA,KAAa,IAAA,GACT,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,SAAA,CAAU,QAAQ,CAAC,CAAA,GACtC,KAAA,GACE,SAAA,CAAU,QAAQ,CAAA,GAClB,IAAA;AAGR,MAAA,IAAA,CAAK,YACH,IAAA,CAAK,iBAAA,KAAsB,MAAA,CAAO,QAAA,GAC9B,KAAK,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,WAAA,CAAY,QAAA,EAAU,EAAE,EAAE,CAAC,IACzD,EAAC;AACP,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACR,QAAQ,QAAA,CAAS,MAAA;AAAA,QACjB,QAAA;AAAA,QACA,IAAA,EAAM,aAAA;AAAA,QACN,IAAA,EAAM,SAAS,IAAA,IAAQ,CAAA;AAAA,QACvB,SAAS,QAAA,CAAS,QAAA;AAAA,QAClB,WAAA,EAAa,KAAA;AAAA,QACb,UAAU,EAAC;AAAA,QACX,UAAA,EAAY,KAAK,SAAA,CAAU,MAAA;AAAA,QAC3B,MAAA,EAAQ,OAAA;AAAA,QACR,KAAA,EAAO;AAAA,OACR,CAAA;AAGD,MAAA,IAAA,CAAK,aAAA,EAAe,SAAA,CAAU,QAAA,CAAS,MAAA,CAAO,mBAAmB,CAAA;AACjE,MAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AACvB,MAAA,IAAA,CAAK,cAAA,EAAe;AACpB,MAAA,IAAA,CAAK,eAAA,EAAgB;AAAA,IACvB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,UAAA,KAAe,IAAA,CAAK,WAAA,IAAe,YAAA,CAAa,KAAK,CAAA,EAAG;AAC1D,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,WAAW,EAAC;AACjB,MAAA,MAAM,OAAA,GAAUC,iBAAgB,KAAK,CAAA;AACrC,MAAA,IAAA,CAAK,KAAK,EAAE,MAAA,EAAQ,OAAA,EAAS,KAAA,EAAO,SAAS,CAAA;AAC7C,MAAA,MAAM,OAAA;AAAA,IACR,CAAA,SAAE;AACA,MAAA,IAAI,IAAA,CAAK,oBAAoB,UAAA,EAAY;AACvC,QAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAA,GAA0B;AAC9B,IAAA,MAAM,QAAQ,IAAA,CAAK,MAAA;AACnB,IAAA,IAAI,KAAA,CAAM,WAAW,CAAC,KAAA,CAAM,WAAW,KAAA,CAAM,WAAA,IAAe,KAAA,CAAM,MAAA,KAAW,OAAA,EAAS;AACpF,MAAA;AAAA,IACF;AACA,IAAA,MAAM,aAAa,IAAA,CAAK,WAAA;AACxB,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,WAAA,EAAa,IAAA,EAAM,CAAA;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,QACrC,KAAA;AAAA,QACA,UAAA,CAAW,KAAA,CAAM,MAAA,CAAO,EAAE,CAAA;AAAA,QAC1B,EAAE,KAAA,EAAO,EAAE,IAAA,EAAM,KAAA,CAAM,MAAM,IAAA,EAAM,KAAA,CAAM,IAAA,GAAO,CAAA,EAAE;AAAE,OACtD;AACA,MAAA,IAAI,eAAe,IAAA,CAAK,WAAA,IAAe,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC7D,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,MAAM,CAAC,CAAA;AACnE,MAAA,IAAI,QAAA,GAAW,KAAK,MAAA,CAAO,QAAA;AAC3B,MAAA,MAAM,QAAmB,EAAC;AAC1B,MAAA,KAAA,MAAW,WAAW,IAAA,EAAM;AAC1B,QAAA,IAAI,WAAA,CAAY,QAAA,EAAU,OAAA,CAAQ,EAAE,CAAA,EAAG;AACrC,UAAA,QAAA,GAAW,YAAA,CAAa,UAAU,OAAO,CAAA;AAAA,QAC3C,CAAA,MAAO;AACL,UAAA,KAAA,CAAM,KAAK,OAAO,CAAA;AAAA,QACpB;AAAA,MACF;AACA,MAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,IAAA,CAAK,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AACzC,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,GAAA,CAAI,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAA;AAC5D,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACR,QAAA,EAAU,MAAM,MAAA,GAAS,CAAA,GAAI,CAAC,GAAG,QAAA,EAAU,GAAG,KAAK,CAAA,GAAI,QAAA;AAAA,QACvD,IAAA,EAAM,QAAA,CAAS,IAAA,IAAQ,KAAA,CAAM,IAAA,GAAO,CAAA;AAAA,QACpC,SAAS,QAAA,CAAS,QAAA;AAAA,QAClB,WAAA,EAAa,KAAA;AAAA,QACb,UAAA,EAAY,KAAK,SAAA,CAAU;AAAA,OAC5B,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,UAAA,KAAe,KAAK,WAAA,EAAa;AACnC,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,WAAA,EAAa,KAAA,EAAO,CAAA;AAAA,MAClC;AACA,MAAA,MAAMA,iBAAgB,KAAK,CAAA;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,SAAA,EAAkC;AAClD,IAAA,MAAM,QAAA,GAAW,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,UAAU,SAAS,CAAA;AAC5D,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,YAAY,SAAS,CAAA;AAAA,IAC7B;AACA,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA;AAC7C,IAAA,IAAI,QAAQ,OAAA,EAAS;AACnB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,IAAA,GAAA,CAAQ,MAAA,EAAQ,IAAA,IAAQ,EAAA,IAAM,CAAA;AACpC,IAAA,MAAM,aAAa,IAAA,CAAK,WAAA;AACxB,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,IAAA,CAAK,WAAW,SAAA,EAAW;AAAA,MACzB,IAAA,EAAM,QAAQ,IAAA,IAAQ,EAAA;AAAA,MACtB,OAAA,EAAS,IAAA;AAAA,MACT,OAAA,EAAS,QAAQ,OAAA,IAAW;AAAA,KAC7B,CAAA;AAED,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,QACrC,KAAA;AAAA,QACA,CAAA,EAAG,WAAW,IAAA,CAAK,EAAE,CAAC,CAAA,UAAA,EAAa,QAAA,CAAS,KAAK,MAAM,CAAA,CAAA;AAAA,QACvD,EAAE,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,CAAK,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,KAAA,EAAO,QAAA,CAAS,KAAA,GAAQ,CAAA,EAAE;AAAE,OACvE;AACA,MAAA,IAAI,eAAe,IAAA,CAAK,WAAA,IAAe,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC7D,QAAA;AAAA,MACF;AACA,MAAA,MAAM,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,MAAM,CAAC,CAAA;AACvE,MAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,QAAA;AACzB,MAAA,IAAI,QAAA,GAAW,aAAA,CAAc,IAAA,EAAM,SAAA,EAAW,CAAC,IAAA,KAAS;AACtD,QAAA,MAAM,MAAA,GAAS,aAAA,CAAc,IAAA,CAAK,QAAA,EAAU,UAAU,IAAI,CAAA;AAC1D,QAAA,OAAO,MAAA,KAAW,KAAK,QAAA,GAAW,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,UAAU,MAAA,EAAO;AAAA,MACvE,CAAC,CAAA;AAED,MAAA,KAAA,MAAW,SAAS,QAAA,EAAU;AAC5B,QAAA,MAAM,SAAA,GAAY,WAAA,CAAY,QAAA,EAAU,KAAA,CAAM,EAAE,CAAA;AAChD,QAAA,IAAI,aAAa,SAAA,CAAU,IAAA,CAAK,EAAA,CAAG,CAAA,CAAE,MAAM,SAAA,EAAW;AACpD,UAAA,QAAA,GAAW,YAAA,CAAa,UAAU,KAAK,CAAA;AAAA,QACzC;AAAA,MACF;AACA,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,CAAA;AACtB,MAAA,IAAA,CAAK,WAAW,SAAA,EAAW;AAAA,QACzB,IAAA,EAAM,SAAS,IAAA,IAAQ,IAAA;AAAA,QACvB,OAAA,EAAS,KAAA;AAAA,QACT,SAAS,QAAA,CAAS;AAAA,OACnB,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,UAAA,KAAe,KAAK,WAAA,EAAa;AACnC,QAAA,IAAA,CAAK,WAAW,SAAA,EAAW;AAAA,UACzB,IAAA,EAAM,QAAQ,IAAA,IAAQ,EAAA;AAAA,UACtB,OAAA,EAAS,KAAA;AAAA,UACT,OAAA,EAAS,QAAQ,OAAA,IAAW;AAAA,SAC7B,CAAA;AAAA,MACH;AACA,MAAA,MAAMA,iBAAgB,KAAK,CAAA;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,IAAA,EAA2B;AACvC,IAAA,IAAI,SAAS,IAAA,CAAK,MAAA,CAAO,QAAQ,IAAA,CAAK,MAAA,CAAO,WAAW,OAAA,EAAS;AAC/D,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,IAAA,EAAM,CAAA;AAClB,IAAA,MAAM,KAAK,IAAA,EAAK;AAAA,EAClB;AAAA,EAEA,MAAM,KAAK,OAAA,EAA2C;AACpD,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,QAAA,IAAY,IAAA,CAAK,QAAA;AACvC,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,EAAQ;AAC/B,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,IAAA,GAAgC;AAAA,MACpC,KAAK,OAAA,CAAQ,IAAA;AAAA,MACb,aAAa,OAAA,CAAQ,OAAA;AAAA,MACrB,qBAAA,EAAuB,OAAA,CAAQ,mBAAA,IAAuB,QAAA,CAAS,mBAAA;AAAA,MAC/D,4BAAA,EACE,OAAA,CAAQ,yBAAA,IAA6B,QAAA,CAAS;AAAA,KAClD;AACA,IAAA,IAAI,eAAA,CAAgB,MAAM,CAAA,EAAG;AAC3B,MAAA,MAAM,EAAE,GAAA,EAAK,KAAA,EAAO,UAAA,EAAW,GAAI,KAAK,KAAA,CAAM,IAAA;AAC9C,MAAA,IAAA,CAAK,IAAA,GAAO,EAAE,GAAA,EAAK,KAAA,EAAO,UAAA,EAAW;AAAA,IACvC;AAEA,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,MACrC,MAAA;AAAA,MACA,CAAA,EAAG,UAAA,CAAW,MAAA,CAAO,EAAE,CAAC,CAAA,SAAA,CAAA;AAAA,MACxB,EAAE,IAAA;AAAK,KACT;AACA,IAAA,KAAA,CAAM,IAAA,EAAK;AACX,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AAEpC,IAAA,IAAI,aAAa,QAAA,EAAU;AACzB,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,IAAA,CAAK,IAAA,CAAK,EAAE,gBAAA,EAAkB,CAAC,GAAG,IAAA,CAAK,MAAA,CAAO,gBAAA,EAAkB,QAAA,CAAS,OAAO,CAAA,EAAG,CAAA;AACnF,QAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,mBAAmB,OAAA,EAAS,QAAA,CAAS,SAAS,CAAA;AAAA,MAC1E;AACA,MAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,SAAS,OAAA,EAAQ;AAAA,IACtD;AAEA,IAAA,MAAM,EAAE,SAAQ,GAAI,QAAA;AAEpB,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAQ;AAAA,IACpC;AACA,IAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,OAAA;AAC/B,IAAA,IAAI,UAAA,EAAY;AACd,MAAA,IAAA,CAAK,MAAA,CAAO,SAAS,MAAM,CAAA;AAAA,IAC7B,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,MAAM,CAAA;AAAA,IACvC;AACA,IAAA,IAAA,CAAK,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAS,MAAM,CAAA;AAChD,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,gBAAA,EAAkB,SAAS,CAAA;AACrD,IAAA,IAAI,UAAA,IAAc,QAAA,CAAS,MAAA,CAAO,KAAA,GAAQ,CAAA,EAAG;AAE3C,MAAA,KAAK,IAAA,CAAK,IAAA,EAAK,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACjC;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAQ;AAAA,EACpC;AAAA,EAEA,MAAM,IAAA,CAAK,SAAA,EAAmB,IAAA,EAAgC;AAC5D,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,MACrC,OAAA;AAAA,MACA,IAAA,CAAK,aAAa,SAAS,CAAA;AAAA,MAC3B,EAAE,IAAA,EAAM,EAAE,GAAA,EAAK,MAAK;AAAE,KACxB;AACA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,MAAA,IAAA,CAAK,eAAe,CAAC,QAAA,CAAS,OAAO,CAAA,EAAG,MAAA,EAAQ,MAAM,KAAK,CAAA;AAC3D,MAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,kBAAkB,OAAA,EAAS,QAAA,CAAS,SAAS,CAAA;AAAA,IACzE;AACA,IAAA,OAAO,QAAA,CAAS,OAAA;AAAA,EAClB;AAAA,EAEA,MAAM,OAAO,SAAA,EAAkC;AAC7C,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,IAAA,CAAK,MAAM,IAAA,CAAK,OAAA,CAAc,UAAU,IAAA,CAAK,YAAA,CAAa,SAAS,CAAC,CAAA;AAC1E,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC1B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,aAAa,SAAS,CAAA;AAG3B,IAAA,MAAM,KAAA,GAAQ,KAAK,OAAA,EAAQ;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAA,CAAW,MAAM,IAAA,CAAK,WAAA,CAAY,CAAC,SAAS,CAAC,CAAA,EAAG,QAAA,CAAS,CAAC,CAAA;AAChE,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,IAAA,CAAK,eAAe,CAAC,OAAO,CAAA,EAAG,KAAA,EAAO,MAAM,KAAK,CAAA;AAAA,MACnD;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,EAAE,MAAM,iBAAA,EAAmB,EAAA,EAAI,WAAW,CAAA;AAAA,EAC9D;AAAA,EAEA,KAAK,SAAA,EAAqC;AACxC,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,SAAA,EAAW,IAAI,CAAA;AAAA,EACzC;AAAA,EAEA,OAAO,SAAA,EAAqC;AAC1C,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,SAAA,EAAW,KAAK,CAAA;AAAA,EAC1C;AAAA,EAEA,MAAM,IAAA,CAAK,SAAA,EAAmB,OAAA,EAAqC;AACjE,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA,CAAc,MAAA,EAAQ,GAAG,IAAA,CAAK,YAAA,CAAa,SAAS,CAAC,CAAA,KAAA,CAAA,EAAS;AAAA,MAClF,MAAM,EAAE,SAAA,EAAW,QAAQ,IAAA,EAAM,OAAA,EAAS,QAAQ,OAAA;AAAQ,KAC3D,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,IAAI,SAAA,EAAkC;AAC1C,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,KAAK,CAAA;AAAA,EACrC;AAAA,EAEA,MAAM,MAAM,SAAA,EAAkC;AAC5C,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,QAAQ,CAAA;AAAA,EACxC;AAAA,EAEA,MAAM,IAAI,SAAA,EAAoC;AAC5C,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,MACrC,KAAA;AAAA,MACA,CAAA,EAAG,IAAA,CAAK,YAAA,CAAa,SAAS,CAAC,CAAA,IAAA;AAAA,KACjC;AACA,IAAA,IAAA,CAAK,eAAe,MAAM,CAAA;AAC1B,IAAA,OAAO,QAAA,CAAS,GAAA;AAAA,EAClB;AAAA,EAEA,WAAA,GAAoB;AAClB,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG;AAC/B,MAAA;AAAA,IACF;AACA,IAAA,IAAI,QAAA,GAAW,KAAK,MAAA,CAAO,QAAA;AAC3B,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA;AAC9C,IAAA,KAAA,MAAW,OAAA,IAAW,KAAK,SAAA,EAAW;AACpC,MAAA,QAAA,GAAW,UAAA,CAAW,QAAA,EAAU,OAAA,EAAS,QAAQ,CAAA;AAAA,IACnD;AACA,IAAA,IAAA,CAAK,YAAY,EAAC;AAClB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,UAAA,EAAY,GAAG,CAAA;AAAA,EACvC;AAAA,EAEA,MAAM,QAAQ,SAAA,EAA4C;AACxD,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,IAAI,SAAS,WAAA,CAAY,IAAA,CAAK,OAAO,QAAA,EAAU,SAAS,GAAG,IAAA,CAAK,MAAA;AAChE,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,MAAA,GAAA,CAAU,MAAM,KAAK,WAAA,CAAY,CAAC,SAAS,CAAC,CAAA,EAAG,QAAA,CAAS,CAAC,CAAA,EAAG,MAAA;AAC5D,MAAA,IAAA,CAAK,eAAe,MAAM,CAAA;AAAA,IAC5B;AACA,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,MAAM,YAAY,SAAS,CAAA;AAAA,IAC7B;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,MACrC,KAAA;AAAA,MACA,GAAG,UAAA,CAAW,IAAA,CAAK,EAAE,CAAC,YAAY,MAAM,CAAA,CAAA;AAAA,MACxC,EAAE,KAAA,EAAO,EAAE,MAAM,IAAA,CAAK,MAAA,CAAO,MAAK;AAAE,KACtC;AACA,IAAA,IAAA,CAAK,eAAe,MAAM,CAAA;AAE1B,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,SAAA,CAAU,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,MAAM,CAAC,CAAA;AACzE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,SAAS,MAAM,CAAA;AACtD,IAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,SAAA,EAAW,MAAM,CAAA;AACnC,IAAA,IAAI,QAAA,GAAW,KAAK,MAAA,CAAO,QAAA;AAC3B,IAAA,MAAM,CAAC,GAAA,EAAK,GAAG,IAAI,CAAA,GAAI,KAAA;AACvB,IAAA,IAAI,OAAO,CAAC,WAAA,CAAY,QAAA,EAAU,GAAA,CAAI,EAAE,CAAA,EAAG;AACzC,MAAA,QAAA,GAAW,UAAA,CAAW,QAAA,EAAU,GAAA,EAAK,OAAO,CAAA;AAAA,IAC9C;AACA,IAAA,IAAI,WAAW,GAAA,EAAK,EAAA;AACpB,IAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,MAAA,IAAI,aAAa,MAAA,IAAa,CAAC,YAAY,QAAA,EAAU,IAAA,CAAK,EAAE,CAAA,EAAG;AAC7D,QAAA,QAAA,GAAW,WAAA,CAAY,UAAU,QAAA,EAAU,IAAA,EAAM,SAAS,EAAE,UAAA,EAAY,KAAA,EAAO,CAAA,IAAK,QAAA;AAAA,MACtF;AACA,MAAA,QAAA,GAAW,IAAA,CAAK,EAAA;AAAA,IAClB;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,CAAA,CAAE,EAAE,CAAC,CAAA;AAC/E,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,YAAY,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AAEzD,IAAA,OAAO;AAAA,MACL,SAAA;AAAA,MACA,oBAAoB,QAAA,CAAS,mBAAA;AAAA,MAC7B,OAAA,EAAS;AAAA,KACX;AAAA,EACF;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,IAAA,CAAK,WAAA,EAAA;AACL,IAAA,IAAA,CAAK,iBAAiB,KAAA,EAAM;AAC5B,IAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAC/B,IAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAC/B,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AACnB,IAAA,IAAA,CAAK,MAAM,SAAA,EAAU;AAAA,EACvB;AAAA;AAAA,EAIA,gBAAgB,MAAA,EAA2B;AACzC,IAAA,OAAO,eAAA,CAAgB,MAAM,CAAA,GACzB,CAAA,QAAA,EAAW,MAAA,CAAO,eAAe,CAAA,CAAA,GACjC,CAAA,EAAG,MAAA,CAAO,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,QAAQ,CAAA,CAAA;AAAA,EAC3C;AAAA;AAAA,EAGA,eAAA,GAAwB;AACtB,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,eAAA,CAAgB,MAAM,CAAA;AACvC,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,YAAA,KAAiB,GAAA,EAAK;AAC/C,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,aAAA,EAAc;AACnB,IAAA,IAAA,CAAK,YAAA,GAAe,GAAA;AACpB,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,IAAA,CAAK,KAAA;AAE1B,IAAA,IAAI,eAAA,CAAgB,MAAM,CAAA,EAAG;AAK3B,MAAA,IAAA,CAAK,gBAAgB,QAAA,CAAS,SAAA,CAAU,MAAA,CAAO,eAAA,EAAiB,IAAI,MAAM;AACxE,QAAA,KAAK,KAAK,UAAA,EAAW;AAAA,MACvB,CAAC,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,MAAA,CAAO,QAAA,KAAa,MAAA,EAAQ;AACrC,MAAA,IAAA,CAAK,gBAAgB,QAAA,CAAS,SAAA;AAAA,QAC5B,CAAA,OAAA,EAAU,OAAO,QAAQ,CAAA,CAAA;AAAA,QACzB,MAAA,CAAO,mBAAA;AAAA,QACP,CAAC,KAAA,KAAU,IAAA,CAAK,aAAA,CAAc,KAAK;AAAA,OACrC;AAAA,IACF,CAAA,MAAO;AAEL,MAAA,IAAA,CAAK,eAAe,KAAK,CAAA;AACzB,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,WAAA,GAAc,SAAS,QAAA,CAAS,CAAC,WAAW,IAAA,CAAK,kBAAA,CAAmB,MAAM,CAAC,CAAA;AAChF,IAAA,IAAA,CAAK,kBAAA,CAAmB,SAAS,MAAM,CAAA;AAAA,EACzC;AAAA;AAAA,EAGA,eAAe,SAAA,EAA0B;AACvC,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,UAAA,EAAY,UAAA,EAAY,CAAA;AACpC,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAQ;AAC1B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,WAAW,KAAA,EAAM;AACtB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,KAAK,IAAA,CAAK,WAAW,MAAA,EAAO;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,aAAA,GAAsB;AACpB,IAAA,IAAA,CAAK,eAAe,WAAA,EAAY;AAChC,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,IAAA,IAAA,CAAK,WAAA,IAAc;AACnB,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,IAAA,IAAA,CAAK,WAAW,IAAA,EAAK;AACrB,IAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AACpB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,UAAA,EAAY,KAAA,EAAO,CAAA;AAAA,EACjC;AAAA,EAEA,mBAAmB,MAAA,EAA8B;AAC/C,IAAA,IAAI,WAAW,QAAA,EAAU;AACvB,MAAA,IAAA,CAAK,eAAe,IAAI,CAAA;AACxB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAA,GAAa,KAAK,UAAA,CAAW,MAAA;AACnC,IAAA,IAAA,CAAK,WAAW,IAAA,EAAK;AACrB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,UAAA,EAAY,MAAA,EAAQ,CAAA;AAChC,IAAA,IAAI,UAAA,IAAc,WAAW,WAAA,EAAa;AAExC,MAAA,KAAK,IAAA,CAAK,WAAW,MAAA,EAAO;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,cAAc,KAAA,EAAuB;AACnC,IAAA,IAAI,KAAA,CAAM,SAAS,KAAA,EAAO;AAGxB,MAAA,KAAK,IAAA,CAAK,WAAW,MAAA,EAAO;AAC5B,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,CAAM,SAAS,SAAA,EAAW;AAC5B,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAU,KAAA,CAAM,IAAA;AACtB,IAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,KAAY,QAAA,EAAU;AAC3C,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAK,OAAO,OAAA,CAAQ,EAAA,KAAO,QAAA,GAAW,QAAQ,EAAA,GAAK,IAAA;AACzD,IAAA,QAAQ,QAAQ,IAAA;AAAM,MACpB,KAAK,SAAA;AACH,QAAA,IAAI,OAAO,IAAA,EAAM;AACf,UAAA,IAAA,CAAK,aAAA,CAAc,IAAI,IAAI,CAAA;AAAA,QAC7B;AACA,QAAA;AAAA,MACF,KAAK,WAAA;AACH,QAAA,IAAI,OAAO,IAAA,EAAM;AACf,UAAA,IAAA,CAAK,UAAA,CAAW,OAAO,EAAE,CAAA;AACzB,UAAA,IAAA,CAAK,MAAA,EAAO;AACZ,UAAA,IAAA,CAAK,aAAA,CAAc,IAAI,IAAI,CAAA;AAAA,QAC7B;AACA,QAAA;AAAA,MACF,KAAK,SAAA;AAAA,MACL,KAAK,SAAA;AAAA,MACL,KAAK,OAAA;AAAA,MACL,KAAK,SAAA;AAGH,QAAA,IAAI,EAAA,KAAO,IAAA,IAAQ,IAAA,CAAK,MAAA,CAAO,EAAE,CAAA,EAAG;AAClC,UAAA,IAAA,CAAK,aAAA,CAAc,IAAI,KAAK,CAAA;AAAA,QAC9B;AACA,QAAA;AAAA,MACF,KAAK,SAAA;AAAA,MACL,KAAK,WAAA;AACH,QAAA,IAAI,OAAO,IAAA,EAAM;AACf,UAAA,IAAA,CAAK,aAAa,EAAE,CAAA;AAAA,QACtB;AACA,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,IAAI,OAAO,QAAQ,WAAA,KAAgB,QAAA,IAAY,CAAC,eAAA,CAAgB,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,EAAG;AACnF,UAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,WAAA,GAAc,GAAG,CAAC,CAAA;AACjD,UAAA,IAAI,KAAA,KAAU,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,KAAA,EAAO;AACtC,YAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,EAAE,GAAG,KAAK,MAAA,CAAO,MAAA,EAAQ,KAAA,EAAM,EAAG,CAAA;AAAA,UACxD;AAAA,QACF;AACA,QAAA;AAAA;AACJ,EACF;AAAA,EAEA,OAAO,EAAA,EAAqB;AAC1B,IAAA,OACE,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,QAAA,EAAU,EAAE,CAAA,KAAM,IAAA,IAAQ,WAAA,CAAY,IAAA,CAAK,SAAA,EAAW,EAAE,CAAA,KAAM,IAAA;AAAA,EAE1F;AAAA,EAEA,aAAA,CAAc,IAAY,WAAA,EAA4B;AACpD,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,EAAA,EAAA,CAAK,IAAA,CAAK,SAAS,GAAA,CAAI,EAAE,CAAA,IAAK,KAAA,KAAU,WAAW,CAAA;AAErE,IAAA,IAAI,IAAA,CAAK,kBAAkB,MAAA,EAAW;AACpC,MAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,gBAAA,GAAyB;AACvB,IAAA,IAAI,KAAK,iBAAA,EAAmB;AAC1B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,iBAAA,GAAoB,IAAA;AAEzB,IAAA,cAAA,CAAe,MAAM;AACnB,MAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK,aAAA,CAAc,KAAK,MAAM,IAAA,CAAK,eAAe,CAAA;AAAA,IACzE,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,aAAA,GAA+B;AACnC,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,IAAA,CAAK,QAAQ,CAAA;AACrC,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AACpB,IAAA,IAAA,CAAK,iBAAA,GAAoB,KAAA;AACzB,IAAA,IAAI,IAAA,CAAK,aAAa,eAAA,CAAgB,IAAA,CAAK,OAAO,MAAM,CAAA,IAAK,OAAA,CAAQ,IAAA,KAAS,CAAA,EAAG;AAC/E,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,GAAA,GAAM,CAAC,GAAG,OAAA,CAAQ,MAAM,CAAA;AAC9B,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,KAAK,kBAAA,EAAoB;AACvD,MAAA,IAAI;AACF,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,WAAA,CAAY,IAAI,KAAA,CAAM,CAAA,EAAG,CAAA,GAAI,kBAAkB,CAAC,CAAA;AAC5E,QAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAE1B,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,gBAAA,GAAmB,CAAA;AACxB,QAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,MAAM,CAAA;AACrC,QAAA,IAAA,CAAK,cAAA,CAAe,QAAA,CAAS,QAAA,EAAU,MAAA,EAAQ,CAAC,CAAA,KAAM,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAE,EAAE,CAAA,KAAM,IAAI,CAAA;AAAA,MAClF,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,IAAA,CAAK,SAAA,IAAa,YAAA,CAAa,KAAK,CAAA,EAAG;AACzC,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,gBAAA,EAAkB,KAAK,CAAA;AACtC,QAAA,KAAA,MAAW,EAAA,IAAM,GAAA,CAAI,KAAA,CAAM,CAAC,CAAA,EAAG;AAC7B,UAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAA,EAAA,CAAK,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA,IAAK,KAAA,KAAU,OAAA,CAAQ,GAAA,CAAI,EAAE,MAAM,IAAI,CAAA;AAAA,QACpF;AACA,QAAA,IAAA,CAAK,cAAc,KAAK,CAAA;AACxB,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,cAAc,KAAA,EAAsB;AAClC,IAAA,IAAA,CAAK,gBAAA,EAAA;AACL,IAAA,IAAI,IAAA,CAAK,mBAAmB,mBAAA,EAAqB;AAC/C,MAAA,IAAA,CAAK,gBAAA,GAAmB,CAAA;AACxB,MAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AACpB,MAAA,KAAK,IAAA,CAAK,WAAW,MAAA,EAAO;AAC5B,MAAA;AAAA,IACF;AACA,IAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,KAAK,CAAA,GAAI,MAAM,WAAA,GAAc,MAAA;AACjE,IAAA,MAAM,KAAA,GACJ,WAAA,KAAgB,MAAA,GACZ,WAAA,GAAc,GAAA,GACd,IAAA,CAAK,GAAA,CAAI,GAAA,GAAQ,CAAA,IAAK,IAAA,CAAK,gBAAA,EAAkB,GAAM,CAAA;AACzD,IAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAC/B,IAAA,IAAA,CAAK,aAAA,GAAgB,WAAW,MAAM;AACpC,MAAA,IAAA,CAAK,aAAA,GAAgB,MAAA;AACrB,MAAA,IAAA,CAAK,gBAAA,EAAiB;AAAA,IACxB,GAAG,KAAK,CAAA;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAA,GAAiC;AACrC,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,IAAI,eAAA,CAAgB,MAAM,CAAA,EAAG;AAC3B,MAAA,MAAM,KAAK,UAAA,EAAW;AACtB,MAAA,OAAO,CAAC,KAAK,MAAA,CAAO,OAAA;AAAA,IACtB;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,aAAa,IAAA,CAAK,WAAA;AACxB,IAAA,MAAM,KAAA,GAAQ,MAAM,UAAA,KAAe,IAAA,CAAK,eAAe,CAAC,IAAA,CAAK,SAAS,MAAM,CAAA;AAC5E,IAAA,MAAM,cAAc,MAAA,CAAO,KAAA;AAC3B,IAAA,IAAI,OAAA,GAAU,KAAA;AAEd,IAAA,IAAI,IAAA,CAAK,cAAc,IAAA,EAAM;AAI3B,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,aAAA,CAAc,OAAO,EAAE,CAAA;AACnD,MAAA,IAAI,OAAM,EAAG;AACX,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,SAAA,CAAU,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,EAAG,SAAA,CAAU,IAAA,CAAK,SAAS,CAAC,CAAA;AAC9F,MAAA,OAAA,GAAU,IAAA;AAAA,IACZ,CAAA,MAAO;AACL,MAAA,MAAM,WAAW,IAAA,CAAK,SAAA;AACtB,MAAA,IAAI,OAAA,GAAU,QAAA;AACd,MAAA,MAAM,QAAmB,EAAC;AAC1B,MAAA,KAAA,IAAS,IAAA,GAAO,CAAA,EAAG,IAAA,GAAO,aAAA,EAAe,IAAA,EAAA,EAAQ;AAC/C,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,QAA2B,KAAA,EAAO,UAAA,CAAW,MAAA,CAAO,EAAE,CAAA,EAAG;AAAA,UAC9F,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA;AAAK,SAC/B,CAAA;AACD,QAAA,IAAI,OAAM,EAAG;AACX,UAAA,OAAO,KAAA;AAAA,QACT;AACA,QAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,MAAM,CAAA;AACrC,QAAA,KAAA,CAAM,IAAA,CAAK,GAAG,QAAA,CAAS,QAAQ,CAAA;AAC/B,QAAA,OAAA,GAAU,KAAK,GAAA,CAAI,OAAA,EAAS,SAAA,CAAU,QAAA,CAAS,QAAQ,CAAC,CAAA;AACxD,QAAA,IAAI,CAAC,QAAA,CAAS,QAAA,IAAY,QAAA,CAAS,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,IAAU,QAAQ,CAAA,EAAG;AAC7E,UAAA;AAAA,QACF;AAAA,MACF;AACA,MAAA,IAAA,CAAK,SAAA,GAAY,OAAA;AACjB,MAAA,OAAA,GAAU,IAAA,CAAK,eAAe,KAAA,EAAO,MAAA,EAAQ,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,QAAQ,CAAA;AAAA,IACzE;AAEA,IAAA,OAAA,GAAW,MAAM,IAAA,CAAK,gBAAA,CAAiB,MAAA,EAAQ,KAAK,CAAA,IAAM,OAAA;AAC1D,IAAA,OAAO,OAAA,IAAW,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,KAAA,KAAU,WAAA;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,gBAAA,CAAiB,MAAA,EAAgB,KAAA,EAAwC;AAC7E,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA;AAC3C,IAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACpB,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,gBAAA,GAAmB,GAAA,CAAI,MAAA;AAC1C,IAAA,MAAMC,OAAAA,GAAS,CAAC,GAAG,GAAA,CAAI,KAAA,CAAM,KAAK,CAAA,EAAG,GAAG,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,KAAK,CAAC,CAAA,CAAE,KAAA;AAAA,MAC3D,CAAA;AAAA,MACA,kBAAA,GAAqB;AAAA,KACvB;AACA,IAAA,IAAA,CAAK,gBAAA,GAAmB,QAAQA,OAAAA,CAAO,MAAA;AAEvC,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAIA,OAAAA,CAAO,MAAA,EAAQ,KAAK,kBAAA,EAAoB;AAC1D,MAAA,MAAM,KAAA,GAAQA,OAAAA,CAAO,KAAA,CAAM,CAAA,EAAG,IAAI,kBAAkB,CAAA;AACpD,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,WAAA,CAAY,KAAK,CAAA;AAC7C,MAAA,IAAI,OAAM,EAAG;AACX,QAAA,OAAO,OAAA;AAAA,MACT;AACA,MAAA,IAAA,CAAK,gBAAA,CAAiB,SAAS,MAAM,CAAA;AACrC,MAAA,OAAA,GAAU,KAAK,cAAA,CAAe,QAAA,CAAS,UAAU,MAAA,EAAQ,MAAM,KAAK,CAAA,IAAK,OAAA;AACzE,MAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAI,QAAA,CAAS,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAC3D,MAAA,KAAA,MAAW,MAAM,KAAA,EAAO;AACtB,QAAA,IAAI,CAAC,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA,IAAK,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,QAAA,EAAU,EAAE,CAAA,EAAG,IAAA,CAAK,YAAY,KAAA,EAAO;AACtF,UAAA,IAAA,CAAK,aAAa,EAAE,CAAA;AACpB,UAAA,OAAA,GAAU,IAAA;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEA,MAAM,aAAA,CAAc,QAAA,EAAkB,MAAA,EAAuC;AAC3E,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,OAAA,CAA2B,KAAA,EAAO,UAAA,CAAW,QAAQ,CAAA,EAAG;AAAA,MAC7F,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA,EAAE;AAAA,MACjC;AAAA,KACD,CAAA;AACD,IAAA,OAAO,SAAA,CAAU,SAAS,QAAQ,CAAA;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAA,GAA4B;AAC1B,IAAA,IAAA,CAAK,gBAAgB,YAAY;AAC/B,MAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,KAAA,CAAM,OAAA,EAAQ;AACxC,QAAA,IAAI,IAAA,CAAK,SAAA,IAAa,CAAC,IAAA,CAAK,OAAO,OAAA,EAAS;AAC1C,UAAA;AAAA,QACF;AACA,QAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAE1B,UAAA,cAAA,CAAe,MAAM,KAAK,IAAA,CAAK,UAAA,EAAY,CAAA;AAC3C,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,gBAAA,GAAmB,CAAA;AACxB,QAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAC/B,QAAA,IAAI,eAAA,CAAgB,MAAM,CAAA,EAAG;AAC3B,UAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,QAAA,CAAS,QAAQ,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,GAAI,KAAK,MAAA,CAAO,MAAA,GAAS,MAAA,EAAQ,KAAA,EAAO,MAAM,CAAA;AACrG,UAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,OAAO,MAAM,CAAA;AAClB,QAAA,MAAM,KAAK,IAAA,EAAK;AAAA,MAClB,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,IAAA,CAAK,SAAA,IAAa,YAAA,CAAa,KAAK,CAAA,EAAG;AACzC,UAAA;AAAA,QACF;AACA,QAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,gCAAA,EAAkC,KAAK,CAAA;AACtD,QAAA,IAAA,CAAK,KAAK,EAAE,KAAA,EAAOD,gBAAAA,CAAgB,KAAK,GAAG,CAAA;AAC3C,QAAA,IAAA,CAAK,qBAAA,EAAsB;AAAA,MAC7B,CAAA,SAAE;AACA,QAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,MACpB;AAAA,IACF,CAAA,GAAG;AACH,IAAA,OAAO,IAAA,CAAK,UAAA;AAAA,EACd;AAAA,EAEA,qBAAA,GAA8B;AAC5B,IAAA,IAAA,CAAK,gBAAA,EAAA;AACL,IAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAC/B,IAAA,IAAI,IAAA,CAAK,mBAAmB,mBAAA,EAAqB;AAC/C,MAAA,IAAA,CAAK,gBAAA,GAAmB,CAAA;AACxB,MAAA,IAAA,CAAK,eAAe,KAAK,CAAA;AACzB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,aAAA,GAAgB,UAAA;AAAA,MACnB,MAAM,KAAK,IAAA,CAAK,UAAA,EAAW;AAAA,MAC3B,KAAK,GAAA,CAAI,GAAA,GAAQ,MAAM,IAAA,CAAK,gBAAA,GAAmB,IAAI,GAAM;AAAA,KAC3D;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,MAAA,EAAsB;AAC3B,IAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAC/B,IAAA,IAAA,CAAK,gBAAA,GAAmB,CAAA;AACxB,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,OAAA,EAAS,OAAO,MAAA,EAAQ,OAAA,EAAS,KAAA,EAAO,IAAA,EAAM,CAAA;AAClE,IAAA,IAAA,CAAK,eAAA,EAAgB;AACrB,IAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,EAAE,IAAA,EAAM,gBAAA,EAAkB,QAAQ,CAAA;AAAA,EACtD;AAAA;AAAA,EAIA,OAAA,GAAkB;AAChB,IAAA,OAAO,EAAE,KAAK,IAAA,CAAK,IAAA,EAAM,UAAU,IAAA,CAAK,KAAA,CAAM,UAAS,EAAE;AAAA,EAC3D;AAAA,EAEA,MAAA,GAAiB;AACf,IAAA,OAAO,EAAE,IAAA,CAAK,IAAA;AAAA,EAChB;AAAA;AAAA,EAGA,SAAS,MAAA,EAAyB;AAChC,IAAA,OAAO,CAAC,IAAA,CAAK,SAAA,IAAa,OAAO,QAAA,KAAa,IAAA,CAAK,MAAM,QAAA,EAAS;AAAA,EACpE;AAAA,EAEA,eAAe,MAAA,EAAsB;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,aAAA,CAAc,WAAA,EAAa,mDAAmD,CAAA;AAAA,IAC1F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAA,CAAU,SAAkB,MAAA,EAAyB;AACnD,IAAA,IAAI,IAAA,GAAO,OAAA;AACX,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,KAAK,EAAE,CAAA;AAC7C,IAAA,IAAI,cAAc,MAAA,IAAa,SAAA,GAAY,OAAO,GAAA,IAAO,CAAC,KAAK,OAAA,EAAS;AACtE,MAAA,IAAA,GAAO,UAAU,IAAI,CAAA;AAAA,IACvB;AACA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG;AAC5B,MAAA,MAAM,KAAA,GAAQ,YAAY,IAAA,CAAK,MAAA,CAAO,UAAU,IAAA,CAAK,EAAE,GAAG,IAAA,CAAK,KAAA;AAC/D,MAAA,IAAI,SAAS,CAAC,QAAA,CAAS,KAAA,EAAO,IAAA,CAAK,KAAK,CAAA,EAAG;AACzC,QAAA,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,KAAA,EAAO,KAAA,EAAM;AAAA,MACjC;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC5B,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAC,UAAU,IAAA,CAAK,SAAA,CAAU,KAAA,EAAO,MAAM,CAAC,CAAA;AAC3E,MAAA,IAAI,QAAA,CAAS,IAAA,CAAK,CAAC,KAAA,EAAO,KAAA,KAAU,UAAU,IAAA,CAAK,QAAA,CAAS,KAAK,CAAC,CAAA,EAAG;AACnE,QAAA,IAAA,GAAO,EAAE,GAAG,IAAA,EAAM,QAAA,EAAS;AAAA,MAC7B;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGA,cAAA,CACE,QAAA,EACA,MAAA,EACA,UAAA,EACS;AACT,IAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,IAAK,QAAA,CAAS,WAAW,CAAA,EAAG;AACnD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,SAAA,GAAY,SAAS,GAAA,CAAI,CAAC,MAAM,IAAA,CAAK,SAAA,CAAU,CAAA,EAAG,MAAM,CAAC,CAAA;AAC/D,IAAA,IAAA,CAAK,OAAA,CAAQ;AAAA,MACX,IAAA,EAAM,UAAA;AAAA,MACN,QAAA,EAAU,SAAA;AAAA,MACV,UAAA,EAAY,IAAI,GAAA,CAAI,SAAA,CAAU,MAAA,CAAO,UAAU,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAC,CAAA;AAAA,MACjE;AAAA,KACD,CAAA;AAED,IAAA,IAAI,IAAA,GAAO,KAAK,MAAA,CAAO,QAAA;AACvB,IAAA,IAAI,WAAW,IAAA,CAAK,SAAA;AACpB,IAAA,MAAM,WAA2D,EAAC;AAClE,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,aAAA,EAAc;AACpC,IAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,IAAA;AAEzB,IAAA,KAAA,MAAW,WAAW,SAAA,EAAW;AAC/B,MAAA,IAAI,WAAA,CAAY,IAAA,EAAM,OAAA,CAAQ,EAAE,CAAA,EAAG;AACjC,QAAA,IAAA,GAAO,YAAA,CAAa,MAAM,OAAO,CAAA;AACjC,QAAA;AAAA,MACF;AACA,MAAA,IAAI,WAAA,CAAY,QAAA,EAAU,OAAA,CAAQ,EAAE,CAAA,EAAG;AACrC,QAAA,QAAA,GAAW,YAAA,CAAa,UAAU,OAAO,CAAA;AACzC,QAAA;AAAA,MACF;AACA,MAAA,IAAI,CAAC,WAAW,OAAO,CAAA,IAAK,KAAK,UAAA,CAAW,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AAC3D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,YAAA,GAAe,QAAQ,QAAA,EAAU,MAAA;AACvC,MAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,QAAA,IAAI,EAAA,KAAO,IAAA,IAAQ,OAAA,CAAQ,MAAA,EAAQ,OAAO,EAAA,EAAI;AAC5C,UAAA,IAAA,GAAO,UAAA,CAAW,IAAA,EAAM,OAAA,EAAS,YAAA,CAAa,IAAI,CAAC,CAAA;AACnD,UAAA,QAAA,CAAS,IAAA,CAAK,EAAE,OAAA,EAAS,QAAA,EAAU,OAAO,CAAA;AAAA,QAC5C,CAAA,MAAO;AACL,UAAA,QAAA,GAAW,CAAC,GAAG,QAAA,EAAU,OAAO,CAAA;AAChC,UAAA,QAAA,CAAS,IAAA,CAAK,EAAE,OAAA,EAAS,QAAA,EAAU,MAAM,CAAA;AAAA,QAC3C;AACA,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,cAAc,IAAI,CAAA;AACnC,MAAA,MAAM,YAAA,GAAe,YAAA,CAAa,IAAA,EAAM,YAAY,CAAA;AACpD,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,IAAA,GACE,WAAA,CAAY,IAAA,EAAM,YAAA,CAAa,IAAA,CAAK,EAAA,EAAI,OAAA,EAAS,QAAA,EAAU,EAAE,UAAA,EAAY,IAAA,EAAM,CAAA,IAAK,IAAA;AACtF,QAAA,QAAA,CAAS,IAAA,CAAK,EAAE,OAAA,EAAS,QAAA,EAAU,OAAO,CAAA;AAC1C,QAAA;AAAA,MACF;AACA,MAAA,MAAM,gBAAA,GAAmB,YAAA,CAAa,QAAA,EAAU,YAAY,CAAA;AAC5D,MAAA,IAAI,gBAAA,EAAkB;AACpB,QAAA,QAAA,GACE,YAAY,QAAA,EAAU,gBAAA,CAAiB,IAAA,CAAK,EAAA,EAAI,SAAS,QAAA,EAAU;AAAA,UACjE,UAAA,EAAY;AAAA,SACb,CAAA,IAAK,QAAA;AAAA,MACV;AAAA,IACF;AAEA,IAAA,MAAM,UAAU,IAAA,KAAS,IAAA,CAAK,MAAA,CAAO,QAAA,IAAY,aAAa,IAAA,CAAK,SAAA;AACnE,IAAA,IAAI,QAAA,KAAa,KAAK,SAAA,EAAW;AAC/B,MAAA,IAAA,CAAK,oBAAoB,MAAA,CAAO,QAAA;AAAA,IAClC;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,QAAA;AACjB,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,MAAM,UAAA,EAAY,QAAA,CAAS,QAAQ,CAAA;AACzD,IAAA,KAAA,MAAW,SAAS,QAAA,EAAU;AAC5B,MAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,EAAE,MAAM,kBAAA,EAAoB,GAAG,OAAO,CAAA;AAAA,IAC1D;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,EAAA,EAAkB;AAC7B,IAAA,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,EAAA,EAAI,IAAA,CAAK,QAAQ,CAAA;AACrC,IAAA,IAAA,CAAK,OAAA,CAAQ,EAAE,IAAA,EAAM,WAAA,EAAa,IAAI,CAAA;AACtC,IAAA,IAAA,CAAK,gBAAgB,EAAE,CAAA;AAAA,EACzB;AAAA,EAEA,gBAAgB,EAAA,EAAkB;AAGhC,IAAA,IAAA,CAAK,SAAA,GAAY,gBAAA;AAAA,MACf,KAAK,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAAA,MACxC;AAAA,KACF;AACA,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,QAAA,EAAU,gBAAA,CAAiB,IAAA,CAAK,MAAA,CAAO,UAAU,EAAE,CAAA;AAAA,MACnD,UAAA,EAAY,KAAK,SAAA,CAAU;AAAA,KAC5B,CAAA;AAAA,EACH;AAAA,EAEA,QAAQ,KAAA,EAA2B;AACjC,IAAA,IAAI,KAAK,eAAA,EAAiB;AACxB,MAAA,IAAA,CAAK,QAAA,CAAS,KAAK,KAAK,CAAA;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA,EAGA,cAAA,GAAuB;AACrB,IAAA,MAAM,UAAU,IAAA,CAAK,QAAA;AACrB,IAAA,IAAA,CAAK,WAAW,EAAC;AACjB,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,KAAA,CAAM,SAAS,WAAA,EAAa;AAC9B,QAAA,IAAA,CAAK,eAAA,CAAgB,MAAM,EAAE,CAAA;AAAA,MAC/B,CAAA,MAAA,IAAW,KAAA,CAAM,IAAA,KAAS,MAAA,EAAQ;AAChC,QAAA,IAAI,KAAA,CAAM,QAAA,KAAa,IAAA,CAAK,KAAA,CAAM,UAAS,EAAG;AAC5C,UAAA,IAAA,CAAK,UAAA,CAAW,MAAM,GAAG,CAAA;AAAA,QAC3B;AAAA,MACF,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,cAAA,CAAe,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,MAAA,EAAQ,CAAC,CAAA,KAAM,KAAA,CAAM,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAA;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAIA,UAAA,CAAW,OAAA,EAAkB,OAAA,EAA6B,MAAA,EAAsB;AAC9E,IAAA,IAAA,CAAK,QAAQ,EAAE,IAAA,EAAM,UAAA,EAAY,QAAA,EAAU,CAAC,OAAO,CAAA,EAAG,UAAA,kBAAY,IAAI,IAAI,CAAC,OAAA,CAAQ,EAAE,CAAC,CAAA,EAAG,QAAQ,CAAA;AACjG,IAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,IAAA;AACzB,IAAA,IAAI,QAAA,GAAW,KAAK,MAAA,CAAO,QAAA;AAC3B,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,QAAA,GACE,WAAA,CAAY,QAAA,EAAU,OAAA,EAAS,OAAA,EAAS,aAAA,CAAc,IAAI,CAAA,EAAG,EAAE,UAAA,EAAY,IAAA,EAAM,CAAA,IACjF,QAAA;AAAA,IACJ,CAAA,MAAO;AACL,MAAA,QAAA,GAAW,UAAA,CAAW,QAAA,EAAU,OAAA,EAAS,YAAA,CAAa,IAAI,CAAC,CAAA;AAAA,IAC7D;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,KAAK,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,OAAA,CAAQ,EAAE,CAAA;AACjE,IAAA,IAAA,CAAK,KAAK,EAAE,QAAA,EAAU,YAAY,IAAA,CAAK,SAAA,CAAU,QAAQ,CAAA;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAA,CAAY,SAAA,EAAmB,KAAA,EAAkC;AACrE,IAAA,MAAM,OAAO,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,QAAA,EAAU,SAAS,CAAA,EAAG,IAAA;AAC3D,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,YAAY,SAAS,CAAA;AAAA,IAC7B;AACA,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,GAAA,GAAM,KAAK,MAAA,EAAO;AACxB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,SAAS,CAAA,IAAK;AAAA,MAC3C,GAAA;AAAA,MACA,WAAW,IAAA,CAAK,KAAA;AAAA,MAChB,KAAA,EAAO,QAAQ,OAAA;AAAQ,KACzB;AACA,IAAA,MAAA,CAAO,GAAA,GAAM,GAAA;AACb,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,MAAM,CAAA;AACjC,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,KAAA,KAAU,KAAA,EAAO;AAC9B,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACR,UAAU,aAAA,CAAc,IAAA,CAAK,OAAO,QAAA,EAAU,SAAA,EAAW,CAAC,CAAA,MAAO;AAAA,UAC/D,GAAG,CAAA;AAAA,UACH,OAAO,EAAE,GAAG,CAAA,CAAE,KAAA,EAAO,OAAO,KAAA,EAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAE,KAAA,CAAM,KAAA,IAAS,KAAA,GAAQ,CAAA,GAAI,GAAG,CAAA;AAAE,SACnF,CAAE;AAAA,OACH,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,CACpB,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA,CACd,IAAA;AAAA,MAAK,MACJ,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,QACd,QAAQ,KAAA,GAAQ,QAAA;AAAA,QAChB,CAAA,EAAG,IAAA,CAAK,YAAA,CAAa,SAAS,CAAC,CAAA,KAAA;AAAA;AACjC,KACF;AACF,IAAA,MAAA,CAAO,KAAA,GAAQ,OAAA;AAEf,IAAA,IAAI;AACF,MAAA,MAAM,WAAW,MAAM,OAAA;AACvB,MAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AAC1B,QAAA,OAAO,QAAA,CAAS,OAAA;AAAA,MAClB;AACA,MAAA,MAAA,CAAO,SAAA,GAAY,SAAS,OAAA,CAAQ,KAAA;AACpC,MAAA,IAAI,MAAA,CAAO,QAAQ,GAAA,EAAK;AACtB,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,SAAS,CAAA;AAAA,MAC9B;AACA,MAAA,IAAA,CAAK,eAAe,CAAC,QAAA,CAAS,OAAO,CAAA,EAAG,MAAA,EAAQ,MAAM,KAAK,CAAA;AAC3D,MAAA,OAAO,QAAA,CAAS,OAAA;AAAA,IAClB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,KAAK,QAAA,CAAS,MAAM,CAAA,IAAK,MAAA,CAAO,QAAQ,GAAA,EAAK;AAC/C,QAAA,IAAA,CAAK,MAAA,CAAO,OAAO,SAAS,CAAA;AAC5B,QAAA,IAAA,CAAK,IAAA,CAAK;AAAA,UACR,QAAA,EAAU,aAAA;AAAA,YAAc,KAAK,MAAA,CAAO,QAAA;AAAA,YAAU,SAAA;AAAA,YAAW,CAAC,CAAA,KACxD,QAAA,CAAS,CAAA,CAAE,OAAO,MAAA,CAAO,SAAS,CAAA,GAAI,CAAA,GAAI,EAAE,GAAG,CAAA,EAAG,KAAA,EAAO,OAAO,SAAA;AAAU;AAC5E,SACD,CAAA;AAAA,MACH;AACA,MAAA,MAAMA,iBAAgB,KAAK,CAAA;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,OAAA,CAAQ,SAAA,EAAmB,MAAA,EAAyC;AACxE,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,EAAQ;AAC5B,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAA;AAAA,MACrC,MAAA;AAAA,MACA,CAAA,EAAG,IAAA,CAAK,YAAA,CAAa,SAAS,CAAC,CAAA,IAAA;AAAA,KACjC;AACA,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA,EAAG;AACzB,MAAA,IAAA,CAAK,OAAA,CAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,GAAA,EAAK,SAAS,UAAA,EAAY,QAAA,EAAU,MAAA,CAAO,QAAA,EAAU,CAAA;AAClF,MAAA,IAAA,CAAK,UAAA,CAAW,SAAS,UAAU,CAAA;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,WAAW,SAAA,EAA2B;AACpC,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,IAAI,eAAA,CAAgB,MAAM,CAAA,EAAG;AAC3B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,IAAA,CAAK;AAAA,MACR,MAAA,EAAQ,QAAA,CAAS,MAAA,CAAO,UAAA,EAAY,SAAS,CAAA,GAAI,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,UAAA,EAAY,SAAA,EAAU;AAAA,MAC7F,QAAA,EAAU,SAAA,CAAU,IAAA,CAAK,MAAA,CAAO,UAAU,SAAS;AAAA,KACpD,CAAA;AAAA,EACH;AAAA,EAEA,iBAAiB,MAAA,EAAsB;AACrC,IAAA,MAAM,OAAA,GAAU,KAAK,MAAA,CAAO,MAAA;AAC5B,IAAA,IAAI,gBAAgB,OAAO,CAAA,IAAK,OAAA,CAAQ,EAAA,KAAO,OAAO,EAAA,EAAI;AACxD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,EAAE,GAAG,MAAA,EAAQ,MAAM,OAAA,CAAQ,IAAA,EAAM,mBAAA,EAAqB,OAAA,CAAQ,mBAAA,EAAoB;AAC/F,IAAA,IAAI,CAAC,QAAA,CAAS,IAAA,EAAM,OAAO,CAAA,EAAG;AAC5B,MAAA,IAAA,CAAK,IAAA,CAAK,EAAE,MAAA,EAAQ,IAAA,EAAM,CAAA;AAC1B,MAAA,IAAI,KAAK,YAAA,KAAiB,IAAA,IAAQ,IAAA,CAAK,QAAA,KAAa,QAAQ,QAAA,EAAU;AACpE,QAAA,IAAA,CAAK,eAAA,EAAgB;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY,GAAA,EAA+C;AACzD,IAAA,OAAO,IAAA,CAAK,MAAM,IAAA,CAAK,OAAA,CAA+B,OAAO,UAAA,CAAW,IAAA,CAAK,EAAE,CAAA,EAAG;AAAA,MAChF,OAAO,EAAE,GAAA,EAAK,IAAA,EAAM,IAAA,CAAK,OAAO,IAAA;AAAK,KACtC,CAAA;AAAA,EACH;AAAA,EAEA,aAAa,SAAA,EAA2B;AACtC,IAAA,OAAO,GAAG,UAAA,CAAW,IAAA,CAAK,EAAE,CAAC,aAAa,SAAS,CAAA,CAAA;AAAA,EACrD;AAAA,EAEA,UAAA,CAAW,WAAmB,MAAA,EAA2B;AACvD,IAAA,IAAA,CAAK,IAAA,CAAK,EAAE,QAAA,EAAU,EAAE,GAAG,IAAA,CAAK,MAAA,CAAO,QAAA,EAAU,CAAC,SAAS,GAAG,MAAA,IAAU,CAAA;AAAA,EAC1E;AAAA,EAEA,KAAK,KAAA,EAAsC;AACzC,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,KAAK,CAAA,EAAkC;AACnE,MAAA,IAAI,MAAM,GAAG,CAAA,KAAM,IAAA,CAAK,MAAA,CAAO,GAAG,CAAA,EAAG;AACnC,QAAA,OAAA,GAAU,IAAA;AACV,QAAA;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,CAAC,OAAA,IAAW,IAAA,CAAK,SAAA,EAAW;AAC9B,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,MAAA,GAAS,OAAO,MAAA,CAAO,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,GAAG,KAAA,EAAO,CAAA;AACxD,IAAA,IAAA,CAAK,OAAA,CAAQ,KAAK,EAAE,IAAA,EAAM,UAAU,QAAA,EAAU,IAAA,CAAK,QAAQ,CAAA;AAAA,EAC7D;AACF,CAAA;AAEA,SAAS,QAAA,CAAS,GAAY,CAAA,EAAqB;AACjD,EAAA,OAAO,CAAA,KAAM,KAAK,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,KAAM,IAAA,CAAK,UAAU,CAAC,CAAA;AAC1D;AAEA,SAAS,YAAY,SAAA,EAAkC;AACrD,EAAA,OAAO,IAAI,aAAA,CAAc,WAAA,EAAa,CAAA,QAAA,EAAW,SAAS,CAAA,6BAAA,CAAA,EAAiC;AAAA,IACzF,MAAA,EAAQ;AAAA,GACT,CAAA;AACH;AAEA,SAASA,iBAAgB,KAAA,EAA+B;AACtD,EAAA,IAAI,eAAA,CAAgB,KAAK,CAAA,EAAG;AAC1B,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,OAAO,IAAI,cAAc,SAAA,EAAW,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA,EAAG;AAAA,IAC1F,KAAA,EAAO;AAAA,GACR,CAAA;AACH;;;AChzCA,IAAM,mBAAA,GAAsB,GAAA;AAC5B,IAAM,0BAA0B,EAAA,GAAK,GAAA;AACrC,IAAM,mBAAA,GAAsB,CAAA;AAsErB,SAAS,aAAa,OAAA,EAA8C;AACzE,EAAA,OAAO,yBAAA,CAA0B,OAAA,EAAS,EAAE,CAAA;AAC9C;AAEO,SAAS,yBAAA,CACd,SACA,SAAA,EACgB;AAChB,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,OAAA,CAAQ,KAAK,CAAA;AAC1C,EAAA,MAAM,GAAA,GAAM,YAAA,CAAa,OAAA,CAAQ,KAAK,CAAA;AACtC,EAAA,MAAM,EAAE,OAAA,EAAS,cAAA,EAAe,GAAI,OAAA,CAAQ,UACxC,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAS,gBAAgB,cAAA,CAAe,OAAA,CAAQ,OAAO,CAAA,MACzE,MAAM;AACL,IAAA,MAAM,WAAW,cAAA,EAAe;AAChC,IAAA,OAAO,EAAE,OAAA,EAAS,QAAA,CAAS,OAAA,EAAS,cAAA,EAAgB,SAAS,cAAA,EAAe;AAAA,EAC9E,CAAA,GAAG;AAEP,EAAA,IAAI,YAAA,GAA8B,IAAA;AAClC,EAAA,IAAI,aAAA,GAAwC,IAAA;AAC5C,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAmB;AAEvC,EAAA,MAAM,QAAA,GAAW,IAAI,eAAA,EAAgB;AACrC,EAAA,MAAM,aAAA,GAAgB,MAAM,IAAI,aAAA,CAAc,aAAa,kCAAkC,CAAA;AAG7F,EAAA,IAAI,IAAA;AACJ,EAAA,MAAM,IAAA,GAAO,IAAI,IAAA,CAAK;AAAA,IACpB,KAAA;AAAA,IACA,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,WAAA,EAAa,MAAM,IAAA,CAAK,WAAA,EAAY;AAAA,IACpC,YAAA,EAAc,CAAC,GAAA,KAAQ,IAAA,CAAK,WAAW,GAAG,CAAA;AAAA,IAC1C,GAAA;AAAA,IACA,UAAU,QAAA,CAAS;AAAA,GACpB,CAAA;AACD,EAAA,IAAA,GAAO,IAAI,cAAA,CAAe;AAAA,IACxB,IAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA,cAAA,EAAgB,cAAc,OAAO,CAAA;AAAA,IACrC,cAAA;AAAA,IACA,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,GAAA;AAAA,IACA,SAAA,EAAW,MAAM,YAAA,EAAc,cAAA,IAAkB,EAAC;AAAA,IAClD,UAAU,SAAA,CAAU;AAAA,GACrB,CAAA;AACD,EAAA,MAAM,QAAA,GAAW,SAAA,CAAU,QAAA,IAAY,IAAI,gBAAA,CAAiB,EAAE,IAAA,EAAM,KAAA,CAAM,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,KAAA,EAAO,KAAK,CAAA;AACxG,EAAA,MAAM,OAAA,GAAU,IAAI,aAAA,CAAc,IAAI,CAAA;AAEtC,EAAA,IAAI,gBAAA,GAAmB,CAAA;AACvB,EAAA,IAAI,YAAA,GAA2C,IAAA;AAC/C,EAAA,IAAI,eAAA;AACJ,EAAA,IAAI,cAAA,GAAiB,CAAA;AAErB,EAAA,SAAS,MAAA,GAA0B;AACjC,IAAA,IAAI,QAAA,CAAS,OAAO,OAAA,EAAS;AAC3B,MAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,aAAA,EAAe,CAAA;AAAA,IACvC;AACA,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,MAAM,UAAA,GAAa,gBAAA;AACnB,MAAA,aAAA,GAAgB,IAAA,CAAK,OAAA,CAAgB,KAAA,EAAO,SAAS,CAAA,CAAE,IAAA;AAAA,QACrD,CAAC,MAAA,KAAqC;AACpC,UAAA,IAAI,QAAA,CAAS,OAAO,OAAA,EAAS;AAC3B,YAAA,MAAM,aAAA,EAAc;AAAA,UACtB;AAEA,UAAA,IAAI,eAAe,gBAAA,EAAkB;AACnC,YAAA,OAAO,MAAA,EAAO;AAAA,UAChB;AACA,UAAA,YAAA,GAAe,MAAA;AACf,UAAA,IAAA,CAAK,YAAY,MAAM,CAAA;AACvB,UAAA,YAAA,CAAa,eAAe,CAAA;AAC5B,UAAA,IAAI,OAAO,QAAA,EAAU;AACnB,YAAA,uBAAA,EAAwB;AAAA,UAC1B,CAAA,MAAO;AACL,YAAA,cAAA,GAAiB,CAAA;AAAA,UACnB;AACA,UAAA,OAAO,MAAA;AAAA,QACT,CAAA;AAAA,QACA,CAAC,KAAA,KAAmB;AAClB,UAAA,IAAI,eAAe,gBAAA,EAAkB;AACnC,YAAA,aAAA,GAAgB,IAAA;AAAA,UAClB;AACA,UAAA,MAAM,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,aAAA;AAAA,EACT;AAGA,EAAA,SAAS,uBAAA,GAAgC;AACvC,IAAA,IAAI,QAAA,CAAS,MAAA,CAAO,OAAA,IAAW,cAAA,IAAkB,mBAAA,EAAqB;AACpE,MAAA;AAAA,IACF;AACA,IAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,mBAAA,GAAsB,CAAA,IAAK,gBAAgB,uBAAuB,CAAA;AACzF,IAAA,cAAA,EAAA;AACA,IAAA,YAAA,CAAa,eAAe,CAAA;AAC5B,IAAA,eAAA,GAAkB,WAAW,MAAM;AACjC,MAAA,aAAA,GAAgB,IAAA;AAEhB,MAAA,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM,uBAAA,EAAyB,CAAA;AAAA,IAChD,GAAG,KAAK,CAAA;AAAA,EACV;AAEA,EAAA,IAAI,UAAA,GAAa,IAAA,CAAK,IAAA,EAAM,EAAA,IAAM,IAAA;AAGlC,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,QAAA,CAAS,CAAC,KAAA,KAAU;AAChD,IAAA,IAAI,KAAA,CAAM,WAAW,YAAA,EAAc;AACjC,MAAA;AAAA,IACF;AACA,IAAA,MAAM,SAAS,KAAA,CAAM,MAAA,KAAW,cAAe,KAAA,CAAM,IAAA,EAAM,MAAM,IAAA,GAAQ,IAAA;AACzE,IAAA,IAAI,WAAW,UAAA,EAAY;AACzB,MAAA;AAAA,IACF;AACA,IAAA,UAAA,GAAa,MAAA;AACb,IAAA,QAAA,EAAA;AAEA,IAAA,MAAM,YAAY,aAAA,KAAkB,IAAA;AACpC,IAAA,gBAAA,EAAA;AACA,IAAA,aAAA,GAAgB,IAAA;AAChB,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,KAAK,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IAC9B;AACA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,KAAK,MAAA,CAAO,IAAA,EAAK,CAAE,KAAA,CAAM,MAAM;AAAA,MAAC,CAAC,CAAA;AAAA,IACnC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,eAAe,IAAA,CAAK,WAAA,GAAiC,EAAC,EAA0B;AAC9E,IAAA,IAAI,QAAA,CAAS,OAAO,OAAA,EAAS;AAC3B,MAAA,MAAM,aAAA,EAAc;AAAA,IACtB;AACA,IAAA,MAAM,GAAA,GAAM,WAAA,CAAY,GAAA,IAAO,cAAA,EAAe;AAC9C,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,MAAM,IAAI,aAAA,CAAc,aAAA,EAAe,6CAA6C,CAAA;AAAA,IACtF;AACA,IAAA,MAAM,IAAA,GAAgB;AAAA,MACpB,GAAA;AAAA,MACA,KAAA,EAAO,WAAA,CAAY,KAAA,IAAS,gBAAA,EAAiB;AAAA,MAC7C,YAAY,WAAA,CAAY;AAAA,KAC1B;AACA,IAAA,MAAM,OAAA,GAAU,YAAA,CACb,MAAM,IAAA,CAAK,OAAA,CAAwB,MAAA,EAAQ,UAAA,EAAY,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA,EAAG,MAAA;AAE3E,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,EAAQ;AAC7B,IAAA,IAAI,QAAA,CAAS,OAAO,OAAA,EAAS;AAC3B,MAAA,MAAM,aAAA,EAAc;AAAA,IACtB;AACA,IAAA,MAAM,SAAwB,IAAI,aAAA;AAAA,MAChC,MAAA;AAAA,MACA;AAAA,QACE,IAAA;AAAA,QACA,QAAA;AAAA,QACA,aAAA,EAAe,MAAM,IAAA,CAAK,IAAA,EAAM,EAAA,IAAM,IAAA;AAAA,QACtC,UAAU,MAAM,QAAA;AAAA,QAChB,IAAA;AAAA,QACA,OAAA;AAAA,QACA,GAAA;AAAA,QACA,SAAA,EAAW,MAAM,OAAA,CAAQ,MAAA,CAAO,MAAM;AAAA,OACxC;AAAA,MACA,WAAA,CAAY;AAAA,KACd;AACA,IAAA,OAAA,CAAQ,IAAI,MAAM,CAAA;AAElB,IAAA,MAAM,MAAA,CAAO,IAAA,EAAK,CAAE,KAAA,CAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAClC,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,eAAe,MAAA,CAAO,QAAA,EAAkB,IAAA,EAAY,aAAA,GAA+B,EAAC,EAAG;AACrF,IAAA,MAAM,IAAA,GAAO,IAAI,QAAA,EAAS;AAC1B,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,QAAA,IAAa,IAAA,CAAuB,IAAA,IAAQ,QAAA;AACvE,IAAA,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,IAAA,EAAM,IAAI,CAAA;AAC9B,IAAA,IAAI,cAAc,MAAA,EAAQ;AACxB,MAAA,IAAA,CAAK,MAAA,CAAO,UAAU,MAAM,CAAA;AAAA,IAC9B;AACA,IAAA,OAAO,IAAA,CAAK,OAAA,CAAgB,MAAA,EAAQ,CAAA,EAAG,UAAA,CAAW,QAAQ,CAAC,CAAA,YAAA,CAAA,EAAgB,EAAE,IAAA,EAAM,CAAA;AAAA,EACrF;AAEA,EAAA,SAAS,KAAA,GAA6B;AACpC,IAAA,IAAI,QAAA,CAAS,OAAO,OAAA,EAAS;AAC3B,MAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,aAAA,EAAe,CAAA;AAAA,IACvC;AACA,IAAA,YAAA,KAAiB,KAAK,OAAA,CAAoB,KAAA,EAAO,QAAQ,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAmB;AACnF,MAAA,YAAA,GAAe,IAAA;AACf,MAAA,MAAM,KAAA;AAAA,IACR,CAAC,CAAA;AACD,IAAA,OAAO,YAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAA,GAAyB;AAAA,IAC7B,OAAO,KAAA,CAAM,IAAA;AAAA,IACb,aAAa,KAAA,CAAM,MAAA;AAAA,IACnB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,IAAA;AAAA,IACA,OAAA,EAAS,EAAE,IAAA,EAAK;AAAA,IAChB,WAAA,EAAa,EAAE,MAAA,EAAO;AAAA,IACtB,MAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA,EAAQ,CAAC,IAAA,KAAS,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAAA,IACtC,KAAA,EAAO,OAAO,GAAA,KAAA,CAAS,MAAM,OAAA,CAAQ,OAAA,CAAQ,CAAC,GAAG,CAAC,CAAA,EAAG,SAAA,CAAU,GAAG,CAAC,CAAA,IAAK,CAAA;AAAA,IACxE,OAAA,EAAS,OAAO,IAAA,KAAA,CACb,MAAM,KAAK,OAAA,CAAyB,MAAA,EAAQ,UAAA,EAAY,EAAE,MAAM,EAAE,GAAA,EAAK,IAAA,EAAK,EAAG,CAAA,EAAG,IAAA;AAAA,IACrF,QAAA,EAAU,OAAO,KAAA,EAAO,QAAA,KAAA,CAEpB,MAAM,IAAA,CAAK,OAAA,CAA0B,OAAO,WAAA,EAAa;AAAA,MACvD,KAAA,EAAO,EAAE,CAAA,EAAG,KAAA,EAAO,QAAQ,QAAA;AAAS,KACrC,CAAA,EACD,KAAA;AAAA,IACJ,OAAA,GAAU;AACR,MAAA,IAAI,QAAA,CAAS,OAAO,OAAA,EAAS;AAC3B,QAAA;AAAA,MACF;AACA,MAAA,QAAA,CAAS,KAAA,EAAM;AACf,MAAA,KAAA,MAAW,MAAA,IAAU,CAAC,GAAG,OAAO,CAAA,EAAG;AACjC,QAAA,MAAA,CAAO,OAAA,EAAQ;AAAA,MACjB;AACA,MAAA,QAAA,CAAS,IAAA,EAAK;AACd,MAAA,YAAA,CAAa,eAAe,CAAA;AAC5B,MAAA,gBAAA,EAAiB;AACjB,MAAA,IAAA,CAAK,OAAA,EAAQ;AAAA,IACf;AAAA,GACF;AAEA,EAAA,IAAI,WAAU,EAAG;AACf,IAAA,KAAK,KAAK,cAAA,EAAe;AAAA,EAC3B;AAEA,EAAA,OAAO,MAAA;AACT;;;AClTO,SAAS,oBAAA,CACd,SAA2D,YAAA,EAC3C;AAChB,EAAA,MAAM,OAAA,uBAAc,GAAA,EAA4B;AAEhD,EAAA,OAAO;AAAA,IACL,QAAQ,OAAA,EAAS;AACf,MAAA,MAAM,GAAA,GAAM,cAAA,CAAe,OAAA,CAAQ,KAAK,CAAA,CAAE,IAAA;AAC1C,MAAA,IAAI,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAC5B,MAAA,IAAI,CAAC,MAAA,EAAQ;AACX,QAAA,MAAA,GAAS,OAAO,OAAO,CAAA;AACvB,QAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,MAAM,CAAA;AAAA,MACzB;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA,IAAI,KAAA,EAAO;AACT,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,cAAA,CAAe,KAAK,EAAE,IAAI,CAAA;AAAA,IAC/C,CAAA;AAAA,IACA,MAAM,KAAA,EAAO;AACX,MAAA,MAAM,IAAA,GAAO,KAAA,KAAU,MAAA,GAAY,CAAC,GAAG,OAAA,CAAQ,IAAA,EAAM,CAAA,GAAI,CAAC,cAAA,CAAe,KAAK,EAAE,IAAI,CAAA;AACpF,MAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,QAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,EAAG,OAAA,EAAQ;AAC1B,QAAA,OAAA,CAAQ,OAAO,GAAG,CAAA;AAAA,MACpB;AAAA,IACF;AAAA,GACF;AACF;AAGO,IAAM,iBAAiC,oBAAA;;;ACnCvC,IAAM,EAAA,GAAK;AAAA,EAChB,MAAA,EAAQ,SAAA;AAAA,EACR,UAAA,EAAY,0BAAA;AAAA,EACZ,OAAA,EAAS,UAAA;AAAA,EACT,SAAA,EAAW,8CAAA;AAAA,EACX,YAAA,EAAc,QAAA;AAAA,EACd,cAAA,EAAgB,iDAAA;AAAA,EAChB,gBAAA,EAAkB,uBAAA;AAAA,EAClB,oBAAA,EAAsB,+CAAA;AAAA,EACtB,mBAAA,EAAqB,qBAAA;AAAA,EACrB,IAAA,EAAM,MAAA;AAAA,EACN,OAAA,EAAS,eAAA;AAAA,EACT,KAAA,EAAO,OAAA;AAAA,EACP,UAAA,EAAY,yBAAA;AAAA,EACZ,MAAA,EAAQ,QAAA;AAAA,EACR,IAAA,EAAM,MAAA;AAAA,EACN,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,MAAA,EAAQ,QAAA;AAAA,EACR,aAAA,EAAe,sBAAA;AAAA,EACf,OAAA,EAAS,2BAAA;AAAA,EACT,MAAA,EAAQ,2DAAA;AAAA,EACR,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ,aAAA;AAAA,EACR,WAAW,EAAE,IAAA,EAAM,YAAY,GAAA,EAAK,cAAA,EAAgB,OAAO,eAAA,EAAgB;AAAA,EAC3E,MAAA,EAAQ,QAAA;AAAA,EACR,WAAA,EAAa,qCAAA;AAAA,EACb,kBAAA,EAAoB,WAAA;AAAA,EACpB,sBAAA,EAAwB,eAAA;AAAA,EACxB,aAAA,EAAe,MAAA;AAAA,EACf,gBAAA,EAAkB,SAAA;AAAA,EAClB,0BAAA,EAA4B,gBAAA;AAAA,EAC5B,wBAAA,EAA0B,qCAAA;AAAA,EAC1B,UAAA,EAAY,0CAAA;AAAA,EACZ,GAAA,EAAK,SAAA;AAAA,EACL,KAAA,EAAO,WAAA;AAAA,EACP,MAAA,EAAQ,UAAA;AAAA,EACR,OAAA,EAAS,sDAAA;AAAA,EACT,QAAA,EAAU,oBAAA;AAAA,EACV,WAAA,EAAa,EAAE,GAAA,EAAK,oBAAA,EAAsB,OAAO,sBAAA,EAAuB;AAAA,EACxE,cAAA,EAAgB,sBAAA;AAAA,EAChB,WAAA,EAAa,EAAE,GAAA,EAAK,qBAAA,EAAuB,OAAO,sBAAA,EAAuB;AAAA,EACzE,cAAc,EAAE,IAAA,EAAM,mBAAmB,GAAA,EAAK,iBAAA,EAAmB,OAAO,kBAAA,EAAmB;AAAA,EAC3F,MAAA,EAAQ,SAAA;AAAA,EACR,WAAA,EAAa,MAAA;AAAA,EACb,UAAA,EAAY,KAAA;AAAA,EACZ,aAAA,EAAe,QAAA;AAAA,EACf,aAAA,EAAe,QAAA;AAAA,EACf,MAAA,EAAQ,sBAAA;AAAA,EACR,QAAA,EAAU,mCAAA;AAAA,EACV,UAAA,EAAY,sBAAA;AAAA,EACZ,OAAA,EAAS,SAAA;AAAA,EACT,KAAA,EAAO,OAAA;AAAA,EACP,WAAA,EAAa,qCAAA;AAAA,EACb,KAAA,EAAO,WAAA;AAAA,EACP,WAAA,EAAa;AAAA,IACX,GAAA,EAAK,2DAAA;AAAA,IACL,KAAA,EAAO;AAAA,GACT;AAAA,EACA,YAAA,EAAc,yCAAA;AAAA,EACd,QAAA,EAAU,WAAA;AAAA,EACV,UAAA,EAAY,aAAA;AAAA,EACZ,WAAA,EAAa,iBAAA;AAAA,EACb,KAAA,EAAO,OAAA;AAAA,EACP,MAAA,EAAQ,cAAA;AAAA,EACR,SAAA,EAAW,iBAAA;AAAA,EACX,QAAA,EAAU,UAAA;AAAA,EACV,UAAA,EAAY,yBAAA;AAAA,EACZ,eAAA,EAAiB,EAAE,GAAA,EAAK,yBAAA,EAA2B,OAAO,2BAAA,EAA4B;AAAA,EACtF,SAAA,EAAW,sBAAA;AAAA,EACX,kBAAA,EAAoB,qCAAA;AAAA,EACpB,WAAA,EAAa,cAAA;AAAA,EACb,SAAA,EAAW,mBAAA;AAAA,EACX,cAAA,EAAgB,iBAAA;AAAA,EAChB,SAAA,EAAW,mBAAA;AAAA,EACX,gBAAA,EAAkB,qBAAA;AAAA,EAClB,OAAA,EAAS,sBAAA;AAAA,EACT,QAAA,EAAU,0CAAA;AAAA,EACV,OAAA,EAAS,6CAAA;AAAA,EACT,UAAA,EAAY,YAAA;AAAA,EACZ,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,UAAA,EAAY,aAAA;AAAA,EACZ,IAAA,EAAM,MAAA;AAAA,EACN,KAAA,EAAO,OAAA;AAAA,EACP,kBAAA,EAAoB,qBAAA;AAAA,EACpB,YAAA,EAAc,yBAAA;AAAA,EACd,OAAA,EAAS,eAAA;AAAA,EACT,aAAA,EAAe,iCAAA;AAAA,EACf,qBAAA,EAAuB,kCAAA;AAAA,EACvB,KAAA,EAAO;AACT;AASO,IAAM,IAAA,GAAiB;AAAA,EAC5B,MAAA,EAAQ,QAAA;AAAA,EACR,UAAA,EAAY,0BAAA;AAAA,EACZ,OAAA,EAAS,MAAA;AAAA,EACT,SAAA,EAAW,2CAAA;AAAA,EACX,YAAA,EAAc,UAAA;AAAA,EACd,cAAA,EAAgB,uDAAA;AAAA,EAChB,gBAAA,EAAkB,uBAAA;AAAA,EAClB,oBAAA,EAAsB,+CAAA;AAAA,EACtB,mBAAA,EAAqB,gCAAA;AAAA,EACrB,IAAA,EAAM,UAAA;AAAA,EACN,OAAA,EAAS,kBAAA;AAAA,EACT,KAAA,EAAO,WAAA;AAAA,EACP,UAAA,EAAY,2BAAA;AAAA,EACZ,MAAA,EAAQ,UAAA;AAAA,EACR,IAAA,EAAM,QAAA;AAAA,EACN,IAAA,EAAM,QAAA;AAAA,EACN,MAAA,EAAQ,SAAA;AAAA,EACR,MAAA,EAAQ,SAAA;AAAA,EACR,aAAA,EAAe,6BAAA;AAAA,EACf,OAAA,EAAS,qCAAA;AAAA,EACT,MAAA,EAAQ,qEAAA;AAAA,EACR,IAAA,EAAM,QAAA;AAAA,EACN,MAAA,EAAQ,WAAA;AAAA,EACR,WAAW,EAAE,IAAA,EAAM,mBAAmB,GAAA,EAAK,iBAAA,EAAmB,OAAO,kBAAA,EAAmB;AAAA,EACxF,MAAA,EAAQ,WAAA;AAAA,EACR,WAAA,EAAa,yDAAA;AAAA,EACb,kBAAA,EAAoB,iBAAA;AAAA,EACpB,sBAAA,EAAwB,cAAA;AAAA,EACxB,aAAA,EAAe,MAAA;AAAA,EACf,gBAAA,EAAkB,QAAA;AAAA,EAClB,0BAAA,EAA4B,cAAA;AAAA,EAC5B,wBAAA,EAA0B,uCAAA;AAAA,EAC1B,UAAA,EAAY,2CAAA;AAAA,EACZ,GAAA,EAAK,UAAA;AAAA,EACL,KAAA,EAAO,kBAAA;AAAA,EACP,MAAA,EAAQ,aAAA;AAAA,EACR,OAAA,EAAS,0DAAA;AAAA,EACT,QAAA,EAAU,8BAAA;AAAA,EACV,WAAA,EAAa,EAAE,GAAA,EAAK,sBAAA,EAAwB,OAAO,uBAAA,EAAwB;AAAA,EAC3E,cAAA,EAAgB,yBAAA;AAAA,EAChB,WAAA,EAAa,EAAE,GAAA,EAAK,4BAAA,EAA2B,OAAO,8BAAA,EAA4B;AAAA,EAClF,YAAA,EAAc;AAAA,IACZ,IAAA,EAAM,4BAAA;AAAA,IACN,GAAA,EAAK,uBAAA;AAAA,IACL,KAAA,EAAO;AAAA,GACT;AAAA,EACA,MAAA,EAAQ,aAAA;AAAA,EACR,WAAA,EAAa,UAAA;AAAA,EACb,UAAA,EAAY,SAAA;AAAA,EACZ,aAAA,EAAe,eAAA;AAAA,EACf,aAAA,EAAe,cAAA;AAAA,EACf,MAAA,EAAQ,wCAAA;AAAA,EACR,QAAA,EAAU,wDAAA;AAAA,EACV,UAAA,EAAY,0BAAA;AAAA,EACZ,OAAA,EAAS,mBAAA;AAAA,EACT,KAAA,EAAO,UAAA;AAAA,EACP,WAAA,EAAa,yDAAA;AAAA,EACb,KAAA,EAAO,kBAAA;AAAA,EACP,WAAA,EAAa;AAAA,IACX,GAAA,EAAK,2FAAA;AAAA,IACL,KAAA,EAAO;AAAA,GACT;AAAA,EACA,YAAA,EAAc,mCAAA;AAAA,EACd,QAAA,EAAU,aAAA;AAAA,EACV,UAAA,EAAY,cAAA;AAAA,EACZ,WAAA,EAAa,gBAAA;AAAA,EACb,KAAA,EAAO,QAAA;AAAA,EACP,MAAA,EAAQ,eAAA;AAAA,EACR,SAAA,EAAW,gBAAA;AAAA,EACX,QAAA,EAAU,gBAAA;AAAA,EACV,UAAA,EAAY,2BAAA;AAAA,EACZ,eAAA,EAAiB,EAAE,GAAA,EAAK,2BAAA,EAA6B,OAAO,4BAAA,EAA6B;AAAA,EACzF,SAAA,EAAW,qCAAA;AAAA,EACX,kBAAA,EAAoB,sDAAA;AAAA,EACpB,WAAA,EAAa,kBAAA;AAAA,EACb,SAAA,EAAW,yBAAA;AAAA,EACX,cAAA,EAAgB,2BAAA;AAAA,EAChB,SAAA,EAAW,oBAAA;AAAA,EACX,gBAAA,EAAkB,4BAAA;AAAA,EAClB,OAAA,EAAS,4BAAA;AAAA,EACT,QAAA,EAAU,0DAAA;AAAA,EACV,OAAA,EAAS,yDAAA;AAAA,EACT,UAAA,EAAY,kBAAA;AAAA,EACZ,IAAA,EAAM,SAAA;AAAA,EACN,MAAA,EAAQ,YAAA;AAAA,EACR,UAAA,EAAY,cAAA;AAAA,EACZ,IAAA,EAAM,WAAA;AAAA,EACN,KAAA,EAAO,eAAA;AAAA,EACP,kBAAA,EAAoB,8BAAA;AAAA,EACpB,YAAA,EAAc,oCAAA;AAAA,EACd,OAAA,EAAS,kBAAA;AAAA,EACT,aAAA,EAAe,+CAAA;AAAA,EACf,qBAAA,EAAuB,6CAAA;AAAA,EACvB,KAAA,EAAO;AACT;AAEO,IAAM,OAAA,GAAU,EAAE,EAAA,EAAoB,OAAA,EAAS,IAAA;AAS/C,SAAS,cAAc,MAAA,EAA6C;AACzE,EAAA,OAAO,QAAQ,WAAA,EAAY,CAAE,UAAA,CAAW,IAAI,IAAI,OAAA,GAAU,IAAA;AAC5D;AAEO,SAAS,gBAAA,CACd,MAAA,EACA,SAAA,GAA+B,EAAC,EACpB;AACZ,EAAA,MAAM,QAAA,GAAW,cAAc,MAAM,CAAA;AACrC,EAAA,MAAM,QAAkB,EAAE,GAAG,QAAQ,QAAQ,CAAA,EAAG,GAAG,SAAA,EAAU;AAC7D,EAAA,MAAM,KAAA,GAAQ,IAAI,IAAA,CAAK,WAAA,CAAY,QAAQ,CAAA;AAE3C,EAAA,OAAO,CAAC,KAAK,IAAA,KAAS;AACpB,IAAA,MAAM,KAAA,GAAsB,MAAM,GAAG,CAAA;AACrC,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,QAAA,GAAW,KAAA;AAAA,IACb,CAAA,MAAO;AACL,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,EAAM,KAAA,IAAS,CAAC,CAAA;AACrC,MAAA,MAAM,QAAA,GAAW,KAAA,CAAM,MAAA,CAAO,KAAK,CAAA;AACnC,MAAA,QAAA,GAAA,CAAY,KAAA,KAAU,IAAI,KAAA,CAAM,IAAA,GAAO,WAAc,KAAA,CAAM,QAAQ,KAAK,KAAA,CAAM,KAAA;AAAA,IAChF;AACA,IAAA,OAAO,QAAA,CAAS,OAAA;AAAA,MAAQ,YAAA;AAAA,MAAc,CAAC,KAAA,EAAO,IAAA,KAC5C,IAAA,IAAQ,IAAA,IAAQ,OAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,GAAI;AAAA,KAC9C;AAAA,EACF,CAAA;AACF","file":"chunk-IBNNENCZ.cjs","sourcesContent":["/** The published package name. Renaming the package changes this line and package.json only. */\nexport const PACKAGE_NAME = \"g-comments\";\n\n// Wire-protocol identifiers shared with the forum plugin. They stay fixed\n// across package renames because the plugin hard-codes them.\nexport const AUTH_MESSAGE_TYPE = \"g-comments:auth\";\nexport const REDIRECT_CODE_PARAM = \"gc_code\";\nexport const REDIRECT_NONCE_PARAM = \"gc_nonce\";\nexport const STORAGE_PREFIX = \"gc\";\n\nexport const COUNTS_BATCH_SIZE = 50;\nexport const REFETCH_BATCH_SIZE = 50;\n\nexport const CLIENT_ID_FORMAT = /^[\\w-]{8,64}$/;\n","import { PACKAGE_NAME } from \"./constants\";\nimport type { ErrorResponse } from \"./types\";\n\nexport type CommentsErrorType =\n | \"invalid_key\"\n | \"not_logged_in\"\n | \"invalid_access\"\n | \"invalid_parameters\"\n | \"not_found\"\n | \"rate_limit\"\n | \"thread_conflict\"\n | \"page_not_allowed\"\n | \"invalid_url\"\n | \"no_category\"\n | \"thread_not_created\"\n | \"invalid_grant\"\n | \"user_not_allowed\"\n | \"submission_rejected\"\n | \"not_a_root_comment\"\n | \"pin_limit_reached\"\n | \"cancelled\"\n | \"storage_unavailable\"\n | \"unreachable\"\n | \"unknown\";\n\nconst SERVER_TYPES: ReadonlySet<string> = new Set<CommentsErrorType>([\n \"invalid_key\",\n \"not_logged_in\",\n \"invalid_access\",\n \"invalid_parameters\",\n \"not_found\",\n \"rate_limit\",\n \"thread_conflict\",\n \"page_not_allowed\",\n \"invalid_url\",\n \"no_category\",\n \"thread_not_created\",\n \"invalid_grant\",\n \"user_not_allowed\",\n \"submission_rejected\",\n \"not_a_root_comment\",\n \"pin_limit_reached\",\n]);\n\n// Some core errors (validation failures, like/flag outcomes) carry no error_type.\nconst TYPE_BY_STATUS: Readonly<Record<number, CommentsErrorType>> = {\n 400: \"invalid_parameters\",\n 401: \"invalid_key\",\n 403: \"invalid_access\",\n 404: \"not_found\",\n 409: \"thread_conflict\",\n 422: \"invalid_parameters\",\n 429: \"rate_limit\",\n};\n\nexport interface CommentsErrorOptions {\n status?: number;\n errors?: string[];\n extras?: Record<string, unknown>;\n waitSeconds?: number;\n hint?: string;\n serverType?: string;\n cause?: unknown;\n}\n\nexport class CommentsError extends Error {\n override readonly name = \"CommentsError\";\n readonly type: CommentsErrorType;\n /** HTTP status, or 0 when no response was received. */\n readonly status: number;\n /** Human-readable messages from the server, safe to show inline. */\n readonly errors: string[];\n readonly extras: Record<string, unknown> | undefined;\n /** Seconds until a rate-limited action may be retried. */\n readonly waitSeconds: number | undefined;\n /** Developer-facing explanation of the probable cause (setup problems). */\n readonly hint: string | undefined;\n /** The raw `error_type` from the server, if it sent one. */\n readonly serverType: string | undefined;\n\n constructor(type: CommentsErrorType, message: string, options: CommentsErrorOptions = {}) {\n super(message, options.cause === undefined ? undefined : { cause: options.cause });\n this.type = type;\n this.status = options.status ?? 0;\n this.errors = options.errors ?? (message ? [message] : []);\n this.extras = options.extras;\n this.waitSeconds = options.waitSeconds;\n this.hint = options.hint;\n this.serverType = options.serverType;\n }\n}\n\nexport function isCommentsError(error: unknown): error is CommentsError {\n return error instanceof CommentsError;\n}\n\nexport function errorFromResponse(\n status: number,\n body: ErrorResponse | null,\n headers?: Headers,\n): CommentsError {\n const serverType = typeof body?.error_type === \"string\" ? body.error_type : undefined;\n const type: CommentsErrorType =\n serverType && SERVER_TYPES.has(serverType)\n ? (serverType as CommentsErrorType)\n : (TYPE_BY_STATUS[status] ?? \"unknown\");\n const errors = Array.isArray(body?.errors)\n ? body.errors.filter((e): e is string => typeof e === \"string\")\n : [];\n const extras = body?.extras && typeof body.extras === \"object\" ? body.extras : undefined;\n\n return new CommentsError(type, errors[0] ?? `Request failed with status ${status}`, {\n status,\n errors,\n extras,\n serverType,\n waitSeconds: type === \"rate_limit\" ? waitSecondsFrom(extras, headers) : undefined,\n });\n}\n\nfunction waitSecondsFrom(\n extras: Record<string, unknown> | undefined,\n headers: Headers | undefined,\n): number | undefined {\n return seconds(extras?.wait_seconds) ?? seconds(headers?.get(\"Retry-After\"));\n}\n\n/** A non-negative number of seconds, or `undefined` for missing/empty/non-numeric values. */\nfunction seconds(value: unknown): number | undefined {\n if (typeof value === \"number\") {\n return Number.isFinite(value) && value >= 0 ? value : undefined;\n }\n if (typeof value === \"string\" && /^\\s*\\d+(\\.\\d+)?\\s*$/.test(value)) {\n return Number(value);\n }\n return undefined;\n}\n\nexport function unreachableError(forum: string, origin: string | undefined, cause: unknown) {\n const from = origin ? `this page's origin (${origin})` : \"this page's origin\";\n const hint = [\n `${PACKAGE_NAME} could not reach ${forum}. Probable causes:`,\n `- ${from} is not allowed: add the host under Admin → Customize → Embedding on the forum, or to the discourse_comments_allowed_origins setting;`,\n \"- the forum is behind HTTP basic auth, which rejects CORS preflight (OPTIONS) requests: let OPTIONS through without credentials;\",\n \"- the discourse-comments plugin is disabled (discourse_comments_enabled);\",\n \"- the forum URL is wrong or the forum is offline.\",\n ].join(\"\\n\");\n\n return new CommentsError(\"unreachable\", `Could not reach ${forum}`, {\n status: 0,\n errors: [],\n hint,\n cause,\n });\n}\n","/** The subset of the Web Storage API the client needs. */\nexport interface StorageLike {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n removeItem(key: string): void;\n /**\n * `false` when values do not survive a page navigation (memory). Redirect\n * sign-in needs storage that does; anything else is assumed durable.\n */\n readonly durable?: boolean;\n}\n\nexport function memoryStorage(): StorageLike {\n const items = new Map<string, string>();\n return {\n durable: false,\n getItem: (key) => items.get(key) ?? null,\n setItem: (key, value) => void items.set(key, value),\n removeItem: (key) => void items.delete(key),\n };\n}\n\n/**\n * Where a sign-in in progress keeps its nonce and PKCE verifier: the client's\n * storage when it survives a navigation, else `sessionStorage` (same tab only),\n * else nothing, in which case redirect sign-in is unavailable.\n */\nexport function signInStorage(storage: StorageLike): StorageLike | null {\n if (storage.durable !== false) {\n return storage;\n }\n try {\n const session = globalThis.sessionStorage;\n if (session) {\n const probe = \"gc:probe\";\n session.setItem(probe, probe);\n const readable = session.getItem(probe) === probe;\n session.removeItem(probe);\n if (readable) {\n return session;\n }\n }\n } catch {\n // fall through\n }\n return null;\n}\n\n/** `localStorage` when usable (it throws in some privacy modes), otherwise memory. */\nexport function browserStorage(): { storage: StorageLike; isLocalStorage: boolean } {\n try {\n const storage = globalThis.localStorage;\n if (storage) {\n const probe = \"gc:probe\";\n storage.setItem(probe, probe);\n storage.removeItem(probe);\n return { storage, isLocalStorage: true };\n }\n } catch {\n // fall through\n }\n return { storage: memoryStorage(), isLocalStorage: false };\n}\n\n/** Only `localStorage` fires cross-tab `storage` events. */\nexport function isLocalStorage(storage: StorageLike): boolean {\n try {\n return storage === globalThis.localStorage;\n } catch {\n return false;\n }\n}\n\nexport function readJson<T>(storage: StorageLike, key: string): T | null {\n try {\n const raw = storage.getItem(key);\n return raw ? (JSON.parse(raw) as T) : null;\n } catch {\n return null;\n }\n}\n\nexport function writeJson(storage: StorageLike, key: string, value: unknown): void {\n try {\n storage.setItem(key, JSON.stringify(value));\n } catch {\n // Quota or privacy-mode failures leave the state in memory only.\n }\n}\n\nexport function removeItem(storage: StorageLike, key: string): void {\n try {\n storage.removeItem(key);\n } catch {\n // ignore\n }\n}\n","// Every browser global is read lazily so the module can be imported during SSR.\n\nexport function getWindow(): Window | undefined {\n return typeof window === \"undefined\" ? undefined : window;\n}\n\nexport function getDocument(): Document | undefined {\n return typeof document === \"undefined\" ? undefined : document;\n}\n\nexport function pageOrigin(): string | undefined {\n return getWindow()?.location.origin;\n}\n\n/** `<link rel=\"canonical\">` when present, else the current location. */\nexport function defaultPageUrl(): string | undefined {\n const canonical = getDocument()?.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\n if (canonical?.href) {\n return canonical.href;\n }\n return getWindow()?.location.href;\n}\n\nexport function defaultPageTitle(): string | undefined {\n return getDocument()?.title || undefined;\n}\n\n/** The current URL without its fragment; the auth `return_to`. */\nexport function currentUrlWithoutHash(): string | undefined {\n const location = getWindow()?.location;\n if (!location) {\n return undefined;\n }\n return location.href.split(\"#\")[0];\n}\n\nexport function isDocumentHidden(): boolean {\n return getDocument()?.hidden === true;\n}\n\nexport function onVisibilityChange(listener: () => void): () => void {\n const doc = getDocument();\n if (!doc) {\n return () => {};\n }\n doc.addEventListener(\"visibilitychange\", listener);\n return () => doc.removeEventListener(\"visibilitychange\", listener);\n}\n","import { COUNTS_BATCH_SIZE } from \"../constants\";\nimport type { CountRef, Counts, CountsResponse } from \"../types\";\nimport { getWindow } from \"./env\";\nimport type { Http } from \"./http\";\n\n/**\n * Encodes a ref the way `GET /comments/counts` keys it: `url:<url>`,\n * `id:<host>/<identifier>` (host defaults to the current page's host) or\n * `t:<topic_id>`.\n */\nexport function encodeRef(ref: CountRef): string {\n if (\"topicId\" in ref) {\n return `t:${ref.topicId}`;\n }\n if (\"identifier\" in ref) {\n const host = ref.host ?? getWindow()?.location.host;\n if (!host) {\n throw new TypeError(\"A count ref with an identifier needs a host outside the browser\");\n }\n return `id:${host}/${ref.identifier}`;\n }\n return `url:${ref.url}`;\n}\n\n// Long page URLs would push 50 refs past common proxy request-line limits (8 KB).\nconst MAX_QUERY_LENGTH = 4_000;\n\ninterface Waiter {\n keys: string[];\n resolve: (counts: Counts) => void;\n reject: (error: unknown) => void;\n}\n\n/**\n * Collects count lookups made in the same task into requests of at most 50\n * refs (and ~4 KB). The window is a zero-delay timer rather than a microtask\n * so counts rendered by separate roots (one custom element each) still share\n * one request.\n */\nexport class CountsBatcher {\n #http: Http;\n #waiters: Waiter[] = [];\n #scheduled = false;\n\n constructor(http: Http) {\n this.#http = http;\n }\n\n request(refs: readonly CountRef[]): Promise<Counts> {\n const keys = refs.map(encodeRef);\n if (keys.length === 0) {\n return Promise.resolve({});\n }\n return new Promise((resolve, reject) => {\n this.#waiters.push({ keys, resolve, reject });\n if (!this.#scheduled) {\n this.#scheduled = true;\n setTimeout(() => void this.#flush(), 0);\n }\n });\n }\n\n async #flush(): Promise<void> {\n const waiters = this.#waiters;\n this.#waiters = [];\n this.#scheduled = false;\n\n const unique = [...new Set(waiters.flatMap((w) => w.keys))];\n const batches: string[][] = [];\n let current: string[] = [];\n let length = 0;\n for (const key of unique) {\n const cost = encodeURIComponent(key).length + \"&refs[]=\".length;\n if (current.length > 0 && (current.length >= COUNTS_BATCH_SIZE || length + cost > MAX_QUERY_LENGTH)) {\n batches.push(current);\n current = [];\n length = 0;\n }\n current.push(key);\n length += cost;\n }\n if (current.length > 0) {\n batches.push(current);\n }\n\n const results = new Map<string, number>();\n const failures = new Map<string, unknown>();\n await Promise.all(\n batches.map(async (batch) => {\n try {\n const response = await this.#http.request<CountsResponse>(\"GET\", \"/counts\", {\n query: { refs: batch },\n anonymous: true,\n });\n for (const key of batch) {\n results.set(key, Number(response.counts?.[key] ?? 0));\n }\n } catch (error) {\n for (const key of batch) {\n failures.set(key, error);\n }\n }\n }),\n );\n\n for (const waiter of waiters) {\n const failed = waiter.keys.find((key) => failures.has(key));\n if (failed !== undefined) {\n waiter.reject(failures.get(failed));\n continue;\n }\n const counts: Counts = {};\n for (const key of waiter.keys) {\n counts[key] = results.get(key) ?? 0;\n }\n waiter.resolve(counts);\n }\n }\n}\n","// Shapes returned by the discourse-comments plugin. Each interface mirrors a\n// serializer or controller response in the plugin; field names stay\n// snake_case so fixtures captured from the server type-check unchanged.\n\n/** Public sort names (`DiscourseComments::Sort`). */\nexport type Sort = \"best\" | \"hot\" | \"newest\" | \"oldest\";\n\n/** Report reasons accepted by `POST …/comments/:id/flag` (`Comment::Flag::FLAG_TYPES`). */\nexport type FlagType = \"off_topic\" | \"inappropriate\" | \"spam\" | \"illegal\" | \"notify_moderators\";\n\n/** `discourse_comments_thread_creation` setting values. */\nexport type ThreadCreation = \"first_view\" | \"first_comment\";\n\n/** `CommenterSerializer`: the signed-in reader, mention results, exchange/me responses. */\nexport interface Commenter {\n id: number;\n username: string;\n name: string | null;\n avatar_url: string;\n title: string | null;\n staff: boolean;\n}\n\n/** `ClientConfig#auth_providers` entry. */\nexport interface AuthProvider {\n name: string;\n title: string;\n}\n\nexport interface ForumInfo {\n name: string;\n base_url: string;\n locale: string;\n}\n\nexport interface Features {\n nested: boolean;\n hot_sort: boolean;\n mentions: boolean;\n uploads: boolean;\n /** `null` when the reactions plugin is not installed. */\n reactions: boolean | null;\n}\n\nexport interface Limits {\n min_post_length: number;\n max_post_length: number;\n roots_per_page: number;\n children_per_page: number;\n max_image_size_kb: number;\n /** Pipe-separated list, as stored in the `authorized_extensions` site setting. */\n authorized_extensions: string;\n}\n\n/** `ConfigSerializer` (`GET /comments/config`). */\nexport interface Config {\n forum: ForumInfo;\n features: Features;\n limits: Limits;\n auth_providers: AuthProvider[];\n sorts: Sort[];\n default_sort: Sort;\n thread_creation: ThreadCreation;\n guidelines_url: string | null;\n scope_version: number;\n /** Present only when the request carried a valid user API key. */\n current_user?: Commenter;\n /** Set when the forum served the request anonymously under load; the key is still valid. */\n degraded?: true;\n}\n\n/** `ThreadSerializer`: a page's thread once its topic exists. */\nexport interface Thread {\n /** Opaque handle; the topic id as a string. */\n id: string;\n topic_id: number;\n key: string;\n url: string;\n title: string | null;\n count: number;\n closed: boolean;\n listed: boolean;\n can_comment: boolean;\n nested: boolean;\n sorts: Sort[];\n sort: Sort;\n pinned_ids: number[];\n realtime: \"live\" | \"poll\";\n message_bus_last_id: number;\n forum_url: string;\n}\n\n/** `VirtualThreadSerializer`: a page whose topic does not exist yet. */\nexport interface VirtualThread {\n id: `v:${string}`;\n topic_id: null;\n key: string;\n url: string;\n title: string;\n count: 0;\n closed: false;\n listed: false;\n can_comment: boolean;\n nested: boolean;\n sorts: Sort[];\n sort: Sort;\n pinned_ids: [];\n realtime: \"pending\";\n /** MessageBus channel where the forum announces `{ topic_id }` on creation. */\n pending_channel: string;\n message_bus_last_id: null;\n forum_url: null;\n}\n\nexport type AnyThread = Thread | VirtualThread;\n\nexport function isVirtualThread(thread: AnyThread): thread is VirtualThread {\n return thread.topic_id === null;\n}\n\n/** `CommentSerializer#author`; `null` on deleted placeholders. */\nexport interface CommentAuthor {\n id: number | null;\n username: string | null;\n name: string | null;\n avatar_url: string | null;\n title: string | null;\n staff: boolean;\n}\n\nexport interface CommentReplyTo {\n number: number;\n username: string | null;\n}\n\nexport interface CommentLikes {\n count: number;\n liked: boolean;\n can_like: boolean;\n}\n\nexport interface CommentPermissions {\n edit: boolean;\n delete: boolean;\n flag: boolean;\n pin: boolean;\n}\n\n/** `CommentSerializer`. Treat as immutable: the SDK replaces nodes instead of mutating them. */\nexport interface Comment {\n id: number;\n number: number;\n author: CommentAuthor | null;\n /** Server-sanitized cooked HTML with absolute links; `\"\"` for deleted placeholders. */\n html: string;\n created_at: string;\n updated_at: string;\n edited: boolean;\n /** `null` for top-level comments. Carries the parent's post number, not its id. */\n reply_to: CommentReplyTo | null;\n children: Comment[];\n direct_reply_count: number;\n total_descendant_count: number;\n pinned: boolean;\n likes: CommentLikes;\n can: CommentPermissions;\n pending: boolean;\n deleted: boolean;\n hidden: boolean;\n url: string | null;\n}\n\n/** `{ pending }` from `POST …/comments` when the comment went to the review queue. */\nexport interface Pending {\n reviewable_id: number | null;\n message: string | null;\n pending_count: number | null;\n}\n\n/** `UploadSerializer` as returned by `POST …/attachments`. */\nexport interface Upload {\n id: number;\n url: string;\n original_filename: string;\n filesize: number;\n width: number | null;\n height: number | null;\n thumbnail_width: number | null;\n thumbnail_height: number | null;\n extension: string;\n short_url: string;\n short_path: string;\n retain_hours: number | null;\n human_filesize: string;\n dominant_color: string | null;\n}\n\n/** Comment counts keyed by encoded ref (`url:…`, `id:<host>/<identifier>`, `t:<topic_id>`). */\nexport type Counts = Record<string, number>;\n\nexport type CountRef = { url: string } | { identifier: string; host?: string } | { topicId: number };\n\n// Response envelopes, one per route.\n\nexport interface ThreadResponse {\n thread: AnyThread;\n}\n\nexport interface RootsPageResponse {\n thread: Thread;\n comments: Comment[];\n has_more: boolean;\n page: number;\n sort: Sort;\n}\n\nexport interface CommentsByIdsResponse {\n thread: Thread;\n comments: Comment[];\n}\n\nexport interface ChildrenPageResponse {\n comments: Comment[];\n has_more: boolean;\n page: number;\n}\n\nexport interface CommentContextResponse {\n ancestors: Comment[];\n ancestors_truncated: boolean;\n comment: Comment;\n}\n\nexport type CreateCommentResponse = { comment: Comment; thread: Thread } | { pending: Pending };\n\nexport interface CommentResponse {\n comment: Comment;\n}\n\nexport interface PinsResponse {\n pinned_ids: number[];\n}\n\nexport interface RawResponse {\n id: number;\n raw: string;\n}\n\nexport interface CountsResponse {\n counts: Counts;\n}\n\nexport interface MentionsResponse {\n users: Commenter[];\n}\n\nexport interface PreviewResponse {\n html: string;\n}\n\nexport interface ExchangeResponse {\n key: string;\n client_id: string;\n expires_at: string | null;\n user: Commenter;\n}\n\n/** Server error body (`create_errors_json`). */\nexport interface ErrorResponse {\n errors?: string[];\n error_type?: string;\n extras?: Record<string, unknown>;\n degraded?: boolean;\n}\n\n/** One palette of a theme (`ForumTheme#scheme_payload`). */\nexport interface ForumColorScheme {\n id: number;\n name: string;\n type: \"light\" | \"dark\";\n /**\n * Every custom property the forum's colour definitions emit, without the\n * `--` prefix and with references already resolved: `primary`, `secondary`,\n * `tertiary`, `primary-low`, `primary-medium`, `danger`, …\n */\n colors: Record<string, string>;\n}\n\n/** A `@font-face` source the forum serves. */\nexport interface ForumFontFace {\n family: string;\n /** A CSS `src` value, e.g. `url(\"https://forum/fonts/x.woff2\") format(\"woff2\")`. */\n src: string;\n weight: number | string;\n}\n\nexport interface ForumFont {\n key: string;\n name: string;\n /** A CSS `font-family` value. */\n stack: string;\n /** Empty for fonts the forum expects to be installed. */\n faces: ForumFontFace[];\n}\n\n/** `GET /comments/theme`: the forum's look as data. */\nexport interface ForumTheme {\n theme: { id: number; name: string } | null;\n schemes: {\n light: ForumColorScheme;\n /** Present when the theme has a dark palette. */\n dark: ForumColorScheme | null;\n };\n fonts: {\n body: ForumFont | null;\n heading: ForumFont | null;\n monospace: ForumFont | null;\n };\n /** The theme's \"Embedded CSS\" stylesheets, absolute URLs. */\n stylesheets: string[];\n /** Changes whenever any of the above changes. */\n version: string;\n}\n","export interface ComposerTiming {\n typingDurationMsecs: number;\n composerOpenDurationMsecs: number;\n}\n\n/**\n * Measures what the forum's fast-typer check needs (`typing_duration_msecs`,\n * `composer_open_duration_msecs`). Without it, a new account's first comments\n * land in the review queue.\n */\nexport interface ComposerTimer {\n readonly started: boolean;\n /** Call when the composer opens or gains focus; repeated calls are no-ops. */\n start(): void;\n /** Call on every input event. */\n typing(): void;\n measure(): ComposerTiming;\n /** Returns the measurement and resets the timer. */\n stop(): ComposerTiming;\n}\n\n// Mirrors the forum composer: each keystroke window of 100 ms counts once.\nconst TYPING_WINDOW_MS = 100;\n\nexport function createComposerTimer(now: () => number = Date.now): ComposerTimer {\n let openedAt: number | null = null;\n let typingMs = 0;\n let lastTypingAt = -Infinity;\n\n const measure = (): ComposerTiming => ({\n typingDurationMsecs: typingMs,\n composerOpenDurationMsecs: openedAt === null ? 0 : Math.max(0, now() - openedAt),\n });\n\n return {\n get started() {\n return openedAt !== null;\n },\n start() {\n openedAt ??= now();\n },\n typing() {\n openedAt ??= now();\n const at = now();\n if (at - lastTypingAt >= TYPING_WINDOW_MS) {\n typingMs += TYPING_WINDOW_MS;\n lastTypingAt = at;\n }\n },\n measure,\n stop() {\n const timing = measure();\n openedAt = null;\n typingMs = 0;\n lastTypingAt = -Infinity;\n return timing;\n },\n };\n}\n","export type Listener<T> = (value: T) => void;\n\nexport class Emitter<T> {\n #listeners = new Set<Listener<T>>();\n\n get size(): number {\n return this.#listeners.size;\n }\n\n on(listener: Listener<T>): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n emit(value: T): void {\n for (const listener of [...this.#listeners]) {\n try {\n listener(value);\n } catch (error) {\n // One broken subscriber must not stop the others from updating.\n console.error(error);\n }\n }\n }\n\n clear(): void {\n this.#listeners.clear();\n }\n}\n","import { PACKAGE_NAME } from \"../constants\";\nimport { CommentsError, errorFromResponse, unreachableError } from \"../errors\";\nimport type { ErrorResponse } from \"../types\";\nimport { pageOrigin } from \"./env\";\nimport type { Logger } from \"./log\";\n\nexport type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;\n\nexport interface ForumLocation {\n /** Origin plus any subfolder, without a trailing slash. */\n base: string;\n origin: string;\n}\n\nexport interface Credentials {\n key: string;\n clientId: string;\n}\n\nexport type Method = \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n\nexport type QueryValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | ReadonlyArray<string | number>;\n\nexport interface RequestOptions {\n query?: Record<string, QueryValue>;\n json?: unknown;\n form?: FormData;\n signal?: AbortSignal;\n /** Skip the user API key headers (exchange, counts). */\n anonymous?: boolean;\n /** Use these key headers instead of the stored ones. */\n credentials?: Credentials;\n /** Keep running after the client is disposed (to revoke a key minted meanwhile). */\n detached?: boolean;\n}\n\nexport interface HttpOptions {\n forum: ForumLocation;\n fetch?: FetchLike | undefined;\n headers?: Record<string, string> | undefined;\n locale?: string | undefined;\n credentials: () => Credentials | null;\n onInvalidKey: (key: string) => void;\n log: Logger;\n /** Aborted when the client is disposed; cancels every request still running. */\n lifetime?: AbortSignal;\n}\n\nexport function normalizeForum(forum: string): ForumLocation {\n let url: URL;\n try {\n url = new URL(forum);\n } catch {\n throw new TypeError(`${PACKAGE_NAME}: \"forum\" must be an absolute URL, got \"${forum}\"`);\n }\n if (url.protocol !== \"https:\" && url.protocol !== \"http:\") {\n throw new TypeError(`${PACKAGE_NAME}: \"forum\" must be an http(s) URL, got \"${forum}\"`);\n }\n return { origin: url.origin, base: url.origin + url.pathname.replace(/\\/+$/, \"\") };\n}\n\nexport function buildQuery(query: Record<string, QueryValue> | undefined): string {\n if (!query) {\n return \"\";\n }\n const parts: string[] = [];\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n parts.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(String(item))}`);\n }\n } else {\n parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);\n }\n }\n return parts.join(\"&\");\n}\n\n/** Thread handles look like `123` or `v:<sha1>`; keep the colon readable. */\nexport function threadPath(threadId: string): string {\n return `/threads/${encodeURIComponent(threadId).replace(/%3A/gi, \":\")}`;\n}\n\nexport function isAbortError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as { name?: unknown }).name === \"AbortError\"\n );\n}\n\nexport class Http {\n readonly forum: ForumLocation;\n #options: HttpOptions;\n #fetch: FetchLike;\n\n constructor(options: HttpOptions) {\n this.forum = options.forum;\n this.#options = options;\n // Resolved per call so a fetch stubbed after construction is honoured,\n // and never invoked as a method (native fetch throws on a foreign `this`).\n this.#fetch = options.fetch ?? ((input, init) => globalThis.fetch(input, init));\n }\n\n get fetch(): FetchLike {\n return this.#fetch;\n }\n\n url(path: string, query?: Record<string, QueryValue>): string {\n const qs = buildQuery(query);\n const url = `${this.forum.base}/comments${path}`;\n return qs ? `${url}?${qs}` : url;\n }\n\n async request<T>(method: Method, path: string, options: RequestOptions = {}): Promise<T> {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n ...this.#options.headers,\n };\n const language = acceptLanguage(this.#options.locale);\n if (language) {\n headers[\"Accept-Language\"] = language;\n }\n\n let body: BodyInit | undefined;\n if (options.json !== undefined) {\n headers[\"Content-Type\"] = \"application/json\";\n body = JSON.stringify(options.json);\n } else if (options.form) {\n body = options.form;\n }\n\n const credentials = options.anonymous\n ? null\n : (options.credentials ?? this.#options.credentials());\n if (credentials) {\n headers[\"User-Api-Key\"] = credentials.key;\n headers[\"User-Api-Client-Id\"] = credentials.clientId;\n }\n\n const url = this.url(path, options.query);\n const lifetime = options.detached ? undefined : this.#options.lifetime;\n if (lifetime?.aborted) {\n throw new DOMException(\"The comments client was disposed\", \"AbortError\");\n }\n const signal = combineSignals(options.signal, lifetime);\n this.#options.log(method, url);\n\n let response: Response;\n try {\n response = await this.#fetch(url, {\n method,\n headers,\n body,\n credentials: \"omit\",\n mode: \"cors\",\n signal,\n });\n } catch (error) {\n if (signal?.aborted || isAbortError(error)) {\n throw error;\n }\n throw unreachableError(this.forum.base, pageOrigin(), error);\n }\n\n if (response.status === 204) {\n return undefined as T;\n }\n\n const text = await response.text();\n const data = parseJson(text);\n\n if (response.ok) {\n if (data === undefined) {\n throw new CommentsError(\"unknown\", \"The forum returned a non-JSON response\", {\n status: response.status,\n });\n }\n return data as T;\n }\n\n const errorBody = isObject(data) ? (data as ErrorResponse) : null;\n const error = errorFromResponse(response.status, errorBody, response.headers);\n if (\n response.status === 401 &&\n error.serverType === \"invalid_key\" &&\n credentials &&\n errorBody?.degraded !== true\n ) {\n this.#options.onInvalidKey(credentials.key);\n }\n throw error;\n }\n}\n\n/**\n * `Accept-Language` skips the CORS preflight allow-list only while it stays\n * within the safelisted characters, so Discourse-style `pt_BR` becomes `pt-BR`\n * and anything else is not sent.\n */\nexport function acceptLanguage(locale: string | undefined): string | undefined {\n const value = locale?.replace(/_/g, \"-\");\n return value && /^[0-9A-Za-z *,\\-.;=]+$/.test(value) ? value : undefined;\n}\n\nfunction combineSignals(\n a: AbortSignal | undefined,\n b: AbortSignal | undefined,\n): AbortSignal | undefined {\n if (!a || !b) {\n return a ?? b;\n }\n if (typeof AbortSignal.any === \"function\") {\n return AbortSignal.any([a, b]);\n }\n const controller = new AbortController();\n const abort = () => controller.abort();\n if (a.aborted || b.aborted) {\n abort();\n }\n a.addEventListener(\"abort\", abort, { once: true });\n b.addEventListener(\"abort\", abort, { once: true });\n return controller.signal;\n}\n\nfunction parseJson(text: string): unknown {\n if (!text) {\n return null;\n }\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","export function base64url(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n\n/** URL-safe random token; `bytes` 16 → 22 chars, 32 → 43 chars. */\nexport function randomToken(bytes: number): string {\n const buffer = new Uint8Array(bytes);\n globalThis.crypto.getRandomValues(buffer);\n return base64url(buffer);\n}\n\n/** PKCE S256 challenge: base64url(sha256(verifier)), no padding. */\nexport async function codeChallenge(verifier: string): Promise<string> {\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n // WebCrypto is only exposed on secure contexts; the forum also rejects\n // non-https origins other than localhost, so this is a setup error.\n throw new Error(\"Signing in requires a secure context (https or localhost).\");\n }\n const digest = await subtle.digest(\"SHA-256\", new TextEncoder().encode(verifier));\n return base64url(new Uint8Array(digest));\n}\n","import {\n AUTH_MESSAGE_TYPE,\n CLIENT_ID_FORMAT,\n PACKAGE_NAME,\n REDIRECT_CODE_PARAM,\n REDIRECT_NONCE_PARAM,\n STORAGE_PREFIX,\n} from \"../constants\";\nimport { CommentsError, isCommentsError } from \"../errors\";\nimport type { AuthProvider, Commenter, Config, ExchangeResponse } from \"../types\";\nimport { Emitter } from \"./emitter\";\nimport { currentUrlWithoutHash, getDocument, getWindow } from \"./env\";\nimport { buildQuery, type Credentials, type ForumLocation, type Http } from \"./http\";\nimport type { Logger } from \"./log\";\nimport { codeChallenge, randomToken } from \"./pkce\";\nimport { readJson, removeItem, type StorageLike, writeJson } from \"./storage\";\n\nexport type AuthStatus = \"anonymous\" | \"signing-in\" | \"signed-in\";\n\nexport interface AuthState {\n readonly status: AuthStatus;\n readonly user: Commenter | null;\n /** The forum served a request anonymously under load. The key is kept; treat the UI as read-only. */\n readonly degraded: boolean;\n /** Why the last sign-in failed or the session ended (`invalid_key` means it expired). */\n readonly error: CommentsError | null;\n}\n\n/** What is persisted under `gc:<forum>:auth`. */\nexport interface StoredAuth {\n key: string;\n client_id: string;\n expires_at: string | null;\n user: Commenter;\n}\n\nexport interface SignInOptions {\n /** An `auth_providers[].name` to go straight to that provider. */\n provider?: string;\n /** Defaults to `popup`; a blocked popup falls back to `redirect`. */\n mode?: \"popup\" | \"redirect\";\n}\n\nexport interface CommentsAuth {\n readonly status: AuthStatus;\n readonly user: Commenter | null;\n /** From `config().auth_providers`; empty until the config has loaded. */\n readonly providers: readonly AuthProvider[];\n /** Per-browser id the forum's user API key is bound to. */\n readonly clientId: string;\n /** Immutable, referentially stable while nothing changes. */\n state(): AuthState;\n onChange(listener: (state: AuthState) => void): () => void;\n /** Resolves with the user (popup) or `null` once a redirect has started. */\n signIn(options?: SignInOptions): Promise<Commenter | null>;\n /** Abandons a pending popup sign-in. */\n cancelSignIn(): void;\n signOut(): Promise<void>;\n /** Completes a redirect sign-in from `#gc_code=…&gc_nonce=…`; runs once per page load. */\n handleRedirect(): Promise<Commenter | null>;\n}\n\ninterface PendingAttempt {\n nonce: string;\n verifier: string;\n mode: \"popup\" | \"redirect\";\n created_at: number;\n}\n\ntype PopupOutcome = { kind: \"code\"; code: string } | { kind: \"user\"; user: Commenter };\n\ninterface Attempt {\n promise: Promise<Commenter | null>;\n popup: Window | null;\n cancel: (error: CommentsError) => void;\n}\n\nexport interface AuthControllerOptions {\n http: Http;\n forum: ForumLocation;\n storage: StorageLike;\n /** Durable storage for a sign-in in progress (`signInStorage`); `null` disables redirects. */\n pendingStorage: StorageLike | null;\n /** Listen to `storage` events (only meaningful when `storage` is `localStorage`). */\n syncAcrossTabs: boolean;\n clientId?: string | undefined;\n log: Logger;\n providers: () => readonly AuthProvider[];\n navigate?: ((url: string) => void) | undefined;\n}\n\n// A pending attempt (nonce + PKCE verifier) outlives a redirect, but not by much.\nconst PENDING_TTL_MS = 15 * 60_000;\nconst POPUP_NAME = \"gc-auth\";\nconst POPUP_WIDTH = 520;\nconst POPUP_HEIGHT = 680;\nconst CLOSED_CHECK_MS = 500;\nconst CLOSED_GRACE_MS = 1_000;\n\nexport class AuthController implements CommentsAuth {\n readonly clientId: string;\n #options: AuthControllerOptions;\n #keys: { auth: string; clientId: string; pending: string };\n #stored: StoredAuth | null;\n #state: AuthState;\n #emitter = new Emitter<AuthState>();\n #attempt: Attempt | null = null;\n #redirect: Promise<Commenter | null> | null = null;\n #stopSync: (() => void) | null = null;\n /** Bumped on sign-out and dispose; an exchange started earlier must not sign anyone in. */\n #generation = 0;\n\n constructor(options: AuthControllerOptions) {\n this.#options = options;\n const prefix = `${STORAGE_PREFIX}:${options.forum.base}`;\n this.#keys = {\n auth: `${prefix}:auth`,\n clientId: `${prefix}:client_id`,\n pending: `${prefix}:pending`,\n };\n this.clientId = this.#resolveClientId(options.clientId);\n this.#stored = this.#readStored();\n this.#state = Object.freeze({\n status: this.#stored ? \"signed-in\" : \"anonymous\",\n user: this.#stored?.user ?? null,\n degraded: false,\n error: null,\n });\n\n const win = getWindow();\n if (options.syncAcrossTabs && win) {\n win.addEventListener(\"storage\", this.#onStorage);\n this.#stopSync = () => win.removeEventListener(\"storage\", this.#onStorage);\n }\n }\n\n get status(): AuthStatus {\n return this.#state.status;\n }\n\n get user(): Commenter | null {\n return this.#state.user;\n }\n\n get providers(): readonly AuthProvider[] {\n return this.#options.providers();\n }\n\n state(): AuthState {\n return this.#state;\n }\n\n onChange(listener: (state: AuthState) => void): () => void {\n return this.#emitter.on(listener);\n }\n\n /** Headers for the current key; the client id is the one that minted it. */\n credentials(): Credentials | null {\n return this.#stored ? { key: this.#stored.key, clientId: this.#stored.client_id } : null;\n }\n\n signIn(options: SignInOptions = {}): Promise<Commenter | null> {\n if (this.#attempt) {\n const popup = this.#attempt.popup;\n if (popup && !popup.closed) {\n popup.focus();\n return this.#attempt.promise;\n }\n this.#attempt.cancel(new CommentsError(\"cancelled\", \"Sign-in was restarted\"));\n }\n\n const win = getWindow();\n if (!win) {\n return Promise.reject(new CommentsError(\"unknown\", \"Signing in needs a browser window\"));\n }\n\n // A recent unfinished attempt keeps its nonce and verifier, so a popup the\n // reader left open can still complete after they click \"Sign in\" again.\n const previous = this.#readPending();\n const nonce = previous?.nonce ?? randomToken(16);\n const verifier = previous?.verifier ?? randomToken(32);\n // Opened before any await so it stays inside the click's user activation;\n // it is pointed at the forum once the PKCE challenge is ready.\n const opened = (options.mode ?? \"popup\") === \"popup\" ? openPopup(win) : null;\n // Some blockers hand back a window that is already closed.\n const popup = opened && !opened.closed ? opened : null;\n let popupNavigated = false;\n\n let cancelledWith: CommentsError | null = null;\n let rejectCancelled: (error: CommentsError) => void = () => {};\n const cancelled = new Promise<never>((_, reject) => {\n rejectCancelled = reject;\n });\n cancelled.catch(() => {});\n let stopPopup = () => {};\n\n const writePending = (mode: PendingAttempt[\"mode\"]) =>\n this.#options.pendingStorage &&\n writeJson(this.#options.pendingStorage, this.#keys.pending, {\n nonce,\n verifier,\n mode,\n created_at: previous?.created_at ?? Date.now(),\n } satisfies PendingAttempt);\n\n const run = async (): Promise<Commenter | null> => {\n const challenge = await codeChallenge(verifier);\n if (cancelledWith) {\n throw cancelledWith;\n }\n const url = this.#startUrl(nonce, challenge, options.provider);\n\n if (popup) {\n if (popup.closed) {\n throw new CommentsError(\"cancelled\", \"The sign-in window was closed\");\n }\n // Stored before the popup leaves, in case it completes on this site.\n writePending(\"popup\");\n popupNavigated = navigatePopup(popup, url);\n }\n if (!popupNavigated) {\n if (!this.#options.pendingStorage) {\n throw new CommentsError(\n \"storage_unavailable\",\n \"Signing in needs a popup or browser storage, and this page has neither. Allow popups for this site, or enable site data (localStorage/sessionStorage).\",\n );\n }\n writePending(\"redirect\");\n this.#options.log(\"popup unavailable, redirecting\");\n // Coming back via the back button restores this page from bfcache\n // mid-\"signing-in\"; settle the state again when that happens.\n win.addEventListener(\"pageshow\", this.#onPageShow);\n (this.#options.navigate ?? ((target) => win.location.assign(target)))(url);\n return null;\n }\n\n const outcome = await this.#waitForPopup(win, popup!, nonce, (stop) => {\n stopPopup = stop;\n });\n if (outcome.kind === \"user\") {\n return outcome.user;\n }\n return this.#exchange(outcome.code, verifier, nonce, () => cancelledWith);\n };\n\n this.#set({ status: \"signing-in\", error: null });\n\n const attempt: Attempt = {\n popup,\n cancel: (error) => {\n cancelledWith = error;\n stopPopup();\n rejectCancelled(error);\n },\n promise: Promise.race([run(), cancelled]).then(\n (user) => {\n if (this.#attempt === attempt) {\n this.#attempt = null;\n }\n return user;\n },\n (error: unknown) => {\n const failure = toCommentsError(error);\n if (popup && !popupNavigated && !popup.closed) {\n popup.close();\n }\n // A newer attempt owns the state and the pending entry now.\n if (this.#attempt !== attempt) {\n throw failure;\n }\n this.#attempt = null;\n // A cancelled popup may still finish later in its own window, so the\n // pending verifier stays until it expires or is replaced.\n if (failure.type !== \"cancelled\") {\n this.#removePending();\n }\n this.#set({ status: this.#stored ? \"signed-in\" : \"anonymous\", error: failure });\n throw failure;\n },\n ),\n };\n this.#attempt = attempt;\n return attempt.promise;\n }\n\n cancelSignIn(): void {\n this.#attempt?.cancel(new CommentsError(\"cancelled\", \"Sign-in was cancelled\"));\n }\n\n async signOut(): Promise<void> {\n // Exchanges still in flight (popup, redirect, or a popup finishing on this\n // site in another window) must not sign the reader back in.\n this.#generation++;\n this.cancelSignIn();\n this.#removePending();\n if (this.#stored) {\n try {\n await this.#options.http.request(\"POST\", \"/auth/revoke\");\n } catch (error) {\n // The key is dropped locally either way; an unreachable forum must not\n // keep the reader signed in.\n this.#options.log(\"revoke failed\", error);\n }\n }\n this.#clearStored();\n this.#set({ status: \"anonymous\", user: null, degraded: false, error: null });\n }\n\n handleRedirect(): Promise<Commenter | null> {\n if (!this.#redirect) {\n this.#redirect = this.#consumeRedirect();\n this.#redirect.catch(() => {});\n }\n return this.#redirect;\n }\n\n /** Called by the HTTP layer on 401 `invalid_key` for the key it sent. */\n invalidate(sentKey: string): void {\n if (!this.#stored || this.#stored.key !== sentKey) {\n return;\n }\n // Another tab may have stored a fresh key before its storage event got here.\n const latest = this.#readStored();\n if (latest && latest.key !== sentKey) {\n this.#stored = latest;\n this.#set({ status: \"signed-in\", user: latest.user, error: null });\n return;\n }\n this.#clearStored();\n this.#set({\n status: this.#attempt ? \"signing-in\" : \"anonymous\",\n user: null,\n degraded: false,\n error: new CommentsError(\"invalid_key\", \"Your session has expired. Please sign in again.\", {\n status: 401,\n }),\n });\n }\n\n /** Folds `/comments/config` into the auth state. */\n applyConfig(config: Config): void {\n if (this.#stored && config.current_user) {\n this.#stored = { ...this.#stored, user: config.current_user };\n writeJson(this.#options.storage, this.#keys.auth, this.#stored);\n }\n this.#set({ degraded: config.degraded === true, user: this.#stored?.user ?? null });\n }\n\n dispose(): void {\n this.#generation++;\n this.cancelSignIn();\n getWindow()?.removeEventListener(\"pageshow\", this.#onPageShow);\n this.#stopSync?.();\n this.#stopSync = null;\n this.#emitter.clear();\n }\n\n async #consumeRedirect(): Promise<Commenter | null> {\n const win = getWindow();\n const hash = win?.location.hash ?? \"\";\n if (!win || !hash.includes(`${REDIRECT_CODE_PARAM}=`)) {\n return null;\n }\n\n const params = new URLSearchParams(hash.slice(1));\n const code = params.get(REDIRECT_CODE_PARAM);\n const nonce = params.get(REDIRECT_NONCE_PARAM);\n // Only claim a fragment for a sign-in this client started: another\n // client on the page (a different forum) may own it.\n const pending = this.#readPending();\n if (!code || !nonce || !pending || pending.nonce !== nonce) {\n return null;\n }\n // The fragment never reached a server; drop it from the address bar and history now.\n win.history.replaceState(win.history.state, \"\", win.location.pathname + win.location.search);\n\n this.#set({ status: \"signing-in\", error: null });\n try {\n const user = await this.#exchange(code, pending.verifier, nonce);\n if (pending.mode === \"popup\") {\n // This is the sign-in popup whose opener link was cut (forum COOP);\n // the opener picks the key up through the storage event.\n win.close();\n }\n return user;\n } catch (error) {\n const failure = toCommentsError(error);\n if (failure.type !== \"cancelled\") {\n this.#removePending();\n }\n this.#set({ status: this.#stored ? \"signed-in\" : \"anonymous\", error: failure });\n throw failure;\n }\n }\n\n async #exchange(\n code: string,\n verifier: string,\n nonce: string,\n cancelled: () => CommentsError | null = () => null,\n ): Promise<Commenter> {\n const generation = this.#generation;\n const tracked = this.#readPending()?.nonce === nonce;\n const response = await this.#options.http.request<ExchangeResponse>(\"POST\", \"/auth/exchange\", {\n json: { code, client_id: this.clientId, code_verifier: verifier },\n anonymous: true,\n detached: true,\n });\n const cancellation =\n cancelled() ??\n (generation !== this.#generation\n ? new CommentsError(\"cancelled\", \"Signed out while signing in\")\n : null) ??\n // Sign-out in another tab removes the shared pending entry.\n (tracked && this.#readPending()?.nonce !== nonce\n ? new CommentsError(\"cancelled\", \"The sign-in was abandoned\")\n : null);\n if (cancellation) {\n // Never keep a key minted for a sign-in that no longer applies.\n this.#options.http\n .request(\"POST\", \"/auth/revoke\", {\n credentials: { key: response.key, clientId: response.client_id || this.clientId },\n detached: true,\n })\n .catch(() => {});\n throw cancellation;\n }\n const stored: StoredAuth = {\n key: response.key,\n client_id: response.client_id || this.clientId,\n expires_at: response.expires_at ?? null,\n user: response.user,\n };\n this.#stored = stored;\n writeJson(this.#options.storage, this.#keys.auth, stored);\n this.#removePending();\n this.#set({ status: \"signed-in\", user: stored.user, degraded: false, error: null });\n return stored.user;\n }\n\n #waitForPopup(\n win: Window,\n popup: Window,\n nonce: string,\n registerStop: (stop: () => void) => void,\n ): Promise<PopupOutcome> {\n return new Promise((resolve, reject) => {\n let closedSince: number | null = null;\n\n const onMessage = (event: MessageEvent) => {\n if (event.origin !== this.#options.forum.origin || event.source !== popup) {\n return;\n }\n const data = event.data as Record<string, unknown> | null;\n if (\n !data ||\n typeof data !== \"object\" ||\n data.type !== AUTH_MESSAGE_TYPE ||\n data.nonce !== nonce ||\n typeof data.code !== \"string\"\n ) {\n return;\n }\n stop();\n resolve({ kind: \"code\", code: data.code });\n };\n\n // The forum's default COOP cuts the opener link, so the popup finishes on\n // this site (`#gc_code`), exchanges there and hands the key over via storage.\n const onStorage = (event: StorageEvent) => {\n if (event.key !== this.#keys.auth || !event.newValue) {\n return;\n }\n const stored = this.#readStored();\n if (stored) {\n stop();\n resolve({ kind: \"user\", user: stored.user });\n }\n };\n\n // A closed popup is ambiguous for the same reason: only give up once this\n // window has focus again and no hand-over arrived shortly after.\n const checkClosed = setInterval(() => {\n if (!popup.closed || !getDocument()?.hasFocus()) {\n closedSince = null;\n return;\n }\n closedSince ??= Date.now();\n if (Date.now() - closedSince >= CLOSED_GRACE_MS) {\n stop();\n reject(new CommentsError(\"cancelled\", \"The sign-in window was closed\"));\n }\n }, CLOSED_CHECK_MS);\n\n const timeout = setTimeout(() => {\n stop();\n reject(new CommentsError(\"cancelled\", \"Sign-in timed out\"));\n }, PENDING_TTL_MS);\n\n const stop = () => {\n win.removeEventListener(\"message\", onMessage);\n win.removeEventListener(\"storage\", onStorage);\n clearInterval(checkClosed);\n clearTimeout(timeout);\n };\n\n win.addEventListener(\"message\", onMessage);\n if (this.#options.syncAcrossTabs) {\n win.addEventListener(\"storage\", onStorage);\n }\n registerStop(stop);\n });\n }\n\n #startUrl(nonce: string, challenge: string, provider: string | undefined): string {\n const query = buildQuery({\n origin: getWindow()?.location.origin,\n client_id: this.clientId,\n nonce,\n code_challenge: challenge,\n return_to: currentUrlWithoutHash(),\n provider,\n });\n return `${this.#options.forum.base}/comments/auth/start?${query}`;\n }\n\n #onPageShow = (event: PageTransitionEvent): void => {\n if (!event.persisted) {\n return;\n }\n getWindow()?.removeEventListener(\"pageshow\", this.#onPageShow);\n if (!this.#attempt && this.#state.status === \"signing-in\") {\n this.#set({ status: this.#stored ? \"signed-in\" : \"anonymous\" });\n }\n };\n\n #removePending(): void {\n if (this.#options.pendingStorage) {\n removeItem(this.#options.pendingStorage, this.#keys.pending);\n }\n }\n\n #readPending(): PendingAttempt | null {\n const storage = this.#options.pendingStorage;\n const pending = storage ? readJson<PendingAttempt>(storage, this.#keys.pending) : null;\n if (\n !pending ||\n typeof pending.nonce !== \"string\" ||\n typeof pending.verifier !== \"string\" ||\n typeof pending.created_at !== \"number\" ||\n Date.now() - pending.created_at > PENDING_TTL_MS\n ) {\n return null;\n }\n return pending;\n }\n\n #onStorage = (event: StorageEvent): void => {\n if (event.key !== null && event.key !== this.#keys.auth) {\n return;\n }\n const stored = this.#readStored();\n if (stored?.key === this.#stored?.key) {\n return;\n }\n this.#stored = stored;\n this.#set({\n status: stored ? \"signed-in\" : this.#attempt ? \"signing-in\" : \"anonymous\",\n user: stored?.user ?? null,\n degraded: false,\n error: null,\n });\n };\n\n #resolveClientId(explicit: string | undefined): string {\n if (explicit !== undefined) {\n if (!CLIENT_ID_FORMAT.test(explicit)) {\n throw new TypeError(`${PACKAGE_NAME}: \"clientId\" must match ${CLIENT_ID_FORMAT}`);\n }\n return explicit;\n }\n const { storage } = this.#options;\n let stored: string | null = null;\n try {\n stored = storage.getItem(this.#keys.clientId);\n } catch {\n stored = null;\n }\n if (stored && CLIENT_ID_FORMAT.test(stored)) {\n return stored;\n }\n const generated = randomToken(24);\n try {\n storage.setItem(this.#keys.clientId, generated);\n } catch {\n // A per-page client id still works; the forum just sees a new device.\n }\n return generated;\n }\n\n #readStored(): StoredAuth | null {\n const stored = readJson<StoredAuth>(this.#options.storage, this.#keys.auth);\n if (\n !stored ||\n typeof stored.key !== \"string\" ||\n typeof stored.client_id !== \"string\" ||\n !stored.user ||\n typeof stored.user !== \"object\"\n ) {\n return null;\n }\n if (stored.expires_at && Date.parse(stored.expires_at) <= Date.now()) {\n removeItem(this.#options.storage, this.#keys.auth);\n return null;\n }\n return stored;\n }\n\n #clearStored(): void {\n this.#stored = null;\n removeItem(this.#options.storage, this.#keys.auth);\n }\n\n #set(patch: Partial<AuthState>): void {\n const next: AuthState = { ...this.#state, ...patch };\n if (\n next.status === this.#state.status &&\n next.degraded === this.#state.degraded &&\n next.error === this.#state.error &&\n sameUser(next.user, this.#state.user)\n ) {\n return;\n }\n this.#state = Object.freeze(next);\n this.#emitter.emit(this.#state);\n }\n}\n\nfunction openPopup(win: Window): Window | null {\n const left = Math.round(win.screenX + Math.max(0, (win.outerWidth - POPUP_WIDTH) / 2));\n const top = Math.round(win.screenY + Math.max(0, (win.outerHeight - POPUP_HEIGHT) / 2));\n try {\n return win.open(\n \"\",\n POPUP_NAME,\n `popup=yes,width=${POPUP_WIDTH},height=${POPUP_HEIGHT},left=${left},top=${top}`,\n );\n } catch {\n return null;\n }\n}\n\nfunction navigatePopup(popup: Window, url: string): boolean {\n try {\n popup.location.replace(url);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction sameUser(a: Commenter | null, b: Commenter | null): boolean {\n if (a === b) {\n return true;\n }\n if (!a || !b) {\n return false;\n }\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\nfunction toCommentsError(error: unknown): CommentsError {\n if (isCommentsError(error)) {\n return error;\n }\n return new CommentsError(\"unknown\", error instanceof Error ? error.message : String(error), {\n cause: error,\n });\n}\n","import { PACKAGE_NAME } from \"../constants\";\n\nexport type Logger = (...args: unknown[]) => void;\n\nexport function createLogger(debug: boolean | undefined): Logger {\n if (!debug) {\n return () => {};\n }\n return (...args) => console.debug(`[${PACKAGE_NAME}]`, ...args);\n}\n","import { Emitter } from \"./emitter\";\nimport { isDocumentHidden, onVisibilityChange } from \"./env\";\nimport type { FetchLike } from \"./http\";\nimport type { Logger } from \"./log\";\nimport { randomToken } from \"./pkce\";\n\nexport type RealtimeStatus = \"idle\" | \"connecting\" | \"connected\" | \"failed\";\n\n/** One entry of the MessageBus poll response array. */\nexport interface BusMessage {\n global_id: number;\n message_id: number;\n channel: string;\n data: unknown;\n}\n\n/**\n * What a subscriber hears about its channel:\n * - `message`: a message newer than the subscriber's cursor;\n * - `bump`: the cursor moved past messages this anonymous poll may not read\n * (group-scoped publishes);\n * - `gap`: the server's position is behind the subscriber's (ids were reset),\n * so messages may have been lost and the subscriber should reconcile.\n */\nexport type BusEvent =\n | { kind: \"message\"; data: unknown; message: BusMessage }\n | { kind: \"bump\"; lastId: number }\n | { kind: \"gap\"; lastId: number };\n\nexport type BusListener = (event: BusEvent) => void;\n\nexport interface RealtimeSubscription {\n readonly channel: string;\n /** Moves this subscriber's cursor forward; never backwards. */\n advanceTo(lastId: number): void;\n unsubscribe(): void;\n}\n\n/** What threads need from a realtime connection; the MessageBus poller is the default. */\nexport interface RealtimeTransport {\n readonly status: RealtimeStatus;\n /**\n * Subscribes from `lastId` (`-2` replays the channel's last message). Each\n * subscriber keeps its own cursor; the poll asks from the oldest of them.\n */\n subscribe(channel: string, lastId: number, listener: BusListener): RealtimeSubscription;\n onStatus(listener: (status: RealtimeStatus) => void): () => void;\n stop(): void;\n}\n\nexport interface MessageBusPollerOptions {\n /** Forum base URL (origin plus subfolder). */\n base: string;\n fetch: FetchLike;\n log: Logger;\n /** Consecutive failures before the transport reports `failed`. */\n failureThreshold?: number;\n}\n\nconst STATUS_CHANNEL = \"/__status\";\nconst CHUNK_SEPARATOR = \"\\r\\n|\\r\\n\";\nconst ESCAPED_SEPARATOR = /\\r\\n\\|\\|\\r\\n/g;\n// A poll that returns empty this fast means the server is not holding\n// connections open (long polling off or saturated); slow down.\nconst QUICK_RESPONSE_MS = 1_000;\nconst SHORT_POLL_INTERVAL_MS = 15_000;\nconst MIN_BACKOFF_MS = 5_000;\nconst MAX_BACKOFF_MS = 60_000;\n\n/** 5 s doubling to 60 s, with jitter so readers do not reconnect in lockstep after a deploy. */\nfunction retryDelay(failures: number): number {\n const ceiling = Math.min(MIN_BACKOFF_MS * 2 ** (failures - 1), MAX_BACKOFF_MS);\n return ceiling / 2 + Math.random() * (ceiling / 2);\n}\n\n/** Subscriber cursors of one channel. */\ntype Subscribers = Map<BusListener, number>;\n\n/**\n * Anonymous MessageBus long-poll over a CORS *simple request*: form-encoded\n * body, no custom headers, no credentials, so no preflight is ever needed.\n */\nexport class MessageBusPoller implements RealtimeTransport {\n readonly clientId = randomToken(16);\n #options: MessageBusPollerOptions;\n #channels = new Map<string, Subscribers>();\n #statusEmitter = new Emitter<RealtimeStatus>();\n #status: RealtimeStatus = \"idle\";\n #controller: AbortController | null = null;\n #wake: (() => void) | null = null;\n #running = false;\n #stopped = false;\n #failures = 0;\n #seq = 0;\n\n constructor(options: MessageBusPollerOptions) {\n this.#options = options;\n }\n\n get status(): RealtimeStatus {\n return this.#status;\n }\n\n get url(): string {\n return `${this.#options.base}/message-bus/${this.clientId}/poll`;\n }\n\n subscribe(channel: string, lastId: number, listener: BusListener): RealtimeSubscription {\n let subscribers = this.#channels.get(channel);\n const before = subscribers ? cursorOf(subscribers) : undefined;\n if (!subscribers) {\n subscribers = new Map();\n this.#channels.set(channel, subscribers);\n }\n subscribers.set(listener, lastId);\n // A new channel, or a subscriber further behind than the poll, needs the\n // server to send the backlog from the older position.\n if (before === undefined || lastId < before) {\n this.#restart();\n }\n\n return {\n channel,\n advanceTo: (id) => {\n const current = this.#channels.get(channel);\n const cursor = current?.get(listener);\n if (current && cursor !== undefined && id > cursor) {\n current.set(listener, id);\n }\n },\n unsubscribe: () => {\n const current = this.#channels.get(channel);\n if (!current?.delete(listener)) {\n return;\n }\n if (current.size === 0) {\n this.#channels.delete(channel);\n this.#restart();\n }\n },\n };\n }\n\n onStatus(listener: (status: RealtimeStatus) => void): () => void {\n return this.#statusEmitter.on(listener);\n }\n\n /** The position the poll asks a channel from (the oldest subscriber cursor). */\n cursor(channel: string): number | undefined {\n const subscribers = this.#channels.get(channel);\n return subscribers ? cursorOf(subscribers) : undefined;\n }\n\n stop(): void {\n this.#stopped = true;\n this.#channels.clear();\n this.#controller?.abort();\n this.#wake?.();\n this.#setStatus(\"idle\");\n }\n\n #restart(): void {\n if (this.#stopped) {\n return;\n }\n // The in-flight poll carries the old channel set; abort and re-post.\n this.#controller?.abort();\n this.#wake?.();\n if (this.#channels.size === 0) {\n this.#setStatus(\"idle\");\n return;\n }\n if (!this.#running) {\n void this.#loop();\n }\n }\n\n async #loop(): Promise<void> {\n this.#running = true;\n try {\n while (!this.#stopped && this.#channels.size > 0) {\n if (this.#status === \"idle\") {\n this.#setStatus(\"connecting\");\n }\n const controller = new AbortController();\n this.#controller = controller;\n const startedAt = Date.now();\n let received = 0;\n\n try {\n const response = await this.#options.fetch(this.url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: this.#body(),\n credentials: \"omit\",\n mode: \"cors\",\n signal: controller.signal,\n });\n if (!response.ok) {\n throw new Error(`MessageBus poll failed with status ${response.status}`);\n }\n await readMessageBusResponse(response, (messages) => {\n received += messages.length;\n this.#deliver(messages);\n });\n } catch (error) {\n if (controller.signal.aborted) {\n continue;\n }\n this.#failures++;\n this.#options.log(\"message-bus poll failed\", error);\n if (this.#failures >= (this.#options.failureThreshold ?? 2)) {\n this.#setStatus(\"failed\");\n }\n await this.#sleep(retryDelay(this.#failures));\n continue;\n } finally {\n if (this.#controller === controller) {\n this.#controller = null;\n }\n }\n\n this.#failures = 0;\n this.#setStatus(\"connected\");\n if (received === 0 && Date.now() - startedAt < QUICK_RESPONSE_MS) {\n await this.#sleep(SHORT_POLL_INTERVAL_MS);\n }\n }\n } finally {\n this.#running = false;\n }\n }\n\n #body(): string {\n const parts: string[] = [];\n for (const [channel, subscribers] of this.#channels) {\n parts.push(`${encodeURIComponent(channel).replace(/%2F/gi, \"/\")}=${cursorOf(subscribers)}`);\n }\n parts.push(`__seq=${++this.#seq}`);\n return parts.join(\"&\");\n }\n\n #deliver(messages: unknown[]): void {\n for (const raw of messages) {\n if (!raw || typeof raw !== \"object\") {\n continue;\n }\n const message = raw as BusMessage;\n if (message.channel === STATUS_CHANNEL) {\n const positions = (message.data ?? {}) as Record<string, unknown>;\n for (const [channel, id] of Object.entries(positions)) {\n const subscribers = this.#channels.get(channel);\n if (subscribers && typeof id === \"number\") {\n this.#applyStatus(subscribers, id);\n }\n }\n continue;\n }\n\n const subscribers = this.#channels.get(message.channel);\n if (!subscribers || typeof message.message_id !== \"number\") {\n continue;\n }\n for (const [listener, cursor] of [...subscribers]) {\n // Another subscriber's older cursor makes the server resend messages\n // this one has already handled.\n if (cursor >= 0 && message.message_id <= cursor) {\n continue;\n }\n subscribers.set(listener, message.message_id);\n notify(listener, { kind: \"message\", data: message.data, message });\n }\n }\n }\n\n #applyStatus(subscribers: Subscribers, id: number): void {\n for (const [listener, cursor] of [...subscribers]) {\n subscribers.set(listener, id);\n // A -1 subscription's first status is only its starting position.\n if (cursor === -1 || id === cursor) {\n continue;\n }\n if (id > cursor) {\n notify(listener, { kind: \"bump\", lastId: id });\n } else if (cursor >= 0) {\n notify(listener, { kind: \"gap\", lastId: id });\n }\n }\n }\n\n #sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n if (this.#wake === done) {\n this.#wake = null;\n }\n resolve();\n };\n const timer = setTimeout(done, ms);\n this.#wake = done;\n });\n }\n\n #setStatus(status: RealtimeStatus): void {\n if (status !== this.#status) {\n this.#status = status;\n this.#statusEmitter.emit(status);\n }\n }\n}\n\nfunction cursorOf(subscribers: Subscribers): number {\n return Math.min(...subscribers.values());\n}\n\nfunction notify(listener: BusListener, event: BusEvent): void {\n try {\n listener(event);\n } catch (error) {\n console.error(error);\n }\n}\n\n/**\n * Reads a poll response. With chunked encoding the server streams JSON arrays\n * separated by `\\r\\n|\\r\\n` and keeps the connection open, so batches are\n * delivered as they arrive; otherwise the body is one JSON array.\n */\nexport async function readMessageBusResponse(\n response: Response,\n onBatch: (messages: unknown[]) => void,\n): Promise<void> {\n let buffer = \"\";\n const emit = (chunk: string) => {\n const text = chunk.replace(ESCAPED_SEPARATOR, CHUNK_SEPARATOR).trim();\n if (!text) {\n return;\n }\n const parsed = JSON.parse(text) as unknown;\n if (Array.isArray(parsed)) {\n onBatch(parsed);\n }\n };\n const drain = (final: boolean) => {\n let index: number;\n while ((index = buffer.indexOf(CHUNK_SEPARATOR)) !== -1) {\n const chunk = buffer.slice(0, index);\n buffer = buffer.slice(index + CHUNK_SEPARATOR.length);\n emit(chunk);\n }\n if (final) {\n emit(buffer);\n buffer = \"\";\n }\n };\n\n const reader = response.body?.getReader();\n if (!reader) {\n buffer = await response.text();\n drain(true);\n return;\n }\n const decoder = new TextDecoder();\n for (;;) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n buffer += decoder.decode(value, { stream: true });\n drain(false);\n }\n buffer += decoder.decode();\n drain(true);\n}\n\nexport interface IntervalRefresherOptions {\n baseMs?: number;\n maxMs?: number;\n}\n\n/**\n * Fallback when live updates are unavailable: runs `task` every 30 s, doubling\n * up to 2 min while nothing changes, paused while the tab is hidden. Calls are\n * coalesced, so at most one refresh is ever in flight.\n */\nexport class IntervalRefresher {\n #task: () => Promise<boolean>;\n #baseMs: number;\n #maxMs: number;\n #intervalMs: number;\n #timer: ReturnType<typeof setTimeout> | undefined;\n #inFlight: Promise<void> | null = null;\n #active = false;\n #lastRunAt = 0;\n #stopListening: (() => void) | null = null;\n\n constructor(task: () => Promise<boolean>, options: IntervalRefresherOptions = {}) {\n this.#task = task;\n this.#baseMs = options.baseMs ?? 30_000;\n this.#maxMs = options.maxMs ?? 120_000;\n this.#intervalMs = this.#baseMs;\n }\n\n get active(): boolean {\n return this.#active;\n }\n\n get intervalMs(): number {\n return this.#intervalMs;\n }\n\n start(): void {\n if (this.#active) {\n return;\n }\n this.#active = true;\n this.#intervalMs = this.#baseMs;\n this.#lastRunAt = Date.now();\n this.#stopListening = onVisibilityChange(this.#onVisibilityChange);\n this.#schedule();\n }\n\n stop(): void {\n this.#active = false;\n clearTimeout(this.#timer);\n this.#stopListening?.();\n this.#stopListening = null;\n }\n\n runNow(): Promise<void> {\n if (!this.#inFlight) {\n this.#inFlight = this.#run().finally(() => {\n this.#inFlight = null;\n this.#schedule();\n });\n }\n return this.#inFlight;\n }\n\n async #run(): Promise<void> {\n clearTimeout(this.#timer);\n let changed = false;\n try {\n changed = await this.#task();\n } catch {\n changed = false;\n }\n this.#lastRunAt = Date.now();\n this.#intervalMs = changed ? this.#baseMs : Math.min(this.#intervalMs * 2, this.#maxMs);\n }\n\n #schedule(): void {\n clearTimeout(this.#timer);\n if (!this.#active || this.#inFlight || isDocumentHidden()) {\n return;\n }\n this.#timer = setTimeout(() => void this.runNow(), this.#intervalMs);\n }\n\n #onVisibilityChange = (): void => {\n if (!this.#active) {\n return;\n }\n if (isDocumentHidden()) {\n clearTimeout(this.#timer);\n } else if (Date.now() - this.#lastRunAt >= this.#intervalMs) {\n void this.runNow();\n } else {\n this.#schedule();\n }\n };\n}\n","// Pure, structurally-shared operations on the comment tree. Every function\n// returns the input array unchanged (same reference) when nothing changed, so\n// snapshots stay referentially stable for UI stores.\nimport type { Comment, Sort } from \"../types\";\n\nexport interface CommentLocation {\n node: Comment;\n /** 0 for top-level comments. */\n depth: number;\n /** Ids from the root down to (and including) the node. */\n path: number[];\n}\n\nexport type InsertPosition = \"start\" | \"end\";\n\nexport function findComment(roots: readonly Comment[], id: number): CommentLocation | null {\n return find(roots, (c) => c.id === id, 0, []);\n}\n\nexport function findByNumber(roots: readonly Comment[], number: number): CommentLocation | null {\n return find(roots, (c) => c.number === number, 0, []);\n}\n\nfunction find(\n nodes: readonly Comment[],\n match: (c: Comment) => boolean,\n depth: number,\n path: number[],\n): CommentLocation | null {\n for (const node of nodes) {\n const nodePath = [...path, node.id];\n if (match(node)) {\n return { node, depth, path: nodePath };\n }\n if (node.children.length > 0) {\n const found = find(node.children, match, depth + 1, nodePath);\n if (found) {\n return found;\n }\n }\n }\n return null;\n}\n\nexport function countComments(roots: readonly Comment[]): number {\n let total = 0;\n for (const node of roots) {\n total += 1 + countComments(node.children);\n }\n return total;\n}\n\nexport function updateComment(\n roots: readonly Comment[],\n id: number,\n update: (comment: Comment) => Comment,\n): readonly Comment[] {\n return mapNode(roots, id, update) ?? roots;\n}\n\nfunction mapNode(\n nodes: readonly Comment[],\n id: number,\n update: (comment: Comment) => Comment,\n): Comment[] | null {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!;\n if (node.id === id) {\n const next = update(node);\n if (next === node) {\n return null;\n }\n const copy = nodes.slice();\n copy[i] = next;\n return copy;\n }\n if (node.children.length > 0) {\n const children = mapNode(node.children, id, update);\n if (children) {\n const copy = nodes.slice();\n copy[i] = { ...node, children };\n return copy;\n }\n }\n }\n return null;\n}\n\n/**\n * Server data wins for the node itself unless it is older; locally loaded\n * children survive. Returns `local` itself when nothing changed.\n */\nexport function mergeComment(local: Comment, incoming: Comment): Comment {\n const children = mergeChildren(local.children, incoming.children);\n // A response that was in flight across a newer one must not roll it back.\n const stale = Date.parse(incoming.updated_at) < Date.parse(local.updated_at);\n if (stale || sameFields(local, incoming)) {\n return children === local.children ? local : { ...local, children };\n }\n return { ...incoming, children };\n}\n\nfunction mergeChildren(local: Comment[], incoming: Comment[]): Comment[] {\n if (incoming.length === 0) {\n return local;\n }\n const localById = new Map(local.map((c) => [c.id, c]));\n const merged = incoming.map((c) => {\n const existing = localById.get(c.id);\n return existing ? mergeComment(existing, c) : c;\n });\n const seen = new Set(incoming.map((c) => c.id));\n for (const c of local) {\n if (!seen.has(c.id)) {\n merged.push(c);\n }\n }\n const unchanged = merged.length === local.length && merged.every((c, i) => c === local[i]);\n return unchanged ? local : merged;\n}\n\nfunction sameFields(a: Comment, b: Comment): boolean {\n for (const key of Object.keys(b) as Array<keyof Comment>) {\n if (key === \"children\") {\n continue;\n }\n const left = a[key];\n const right = b[key];\n if (left === right) {\n continue;\n }\n if (\n typeof left !== \"object\" ||\n typeof right !== \"object\" ||\n JSON.stringify(left) !== JSON.stringify(right)\n ) {\n return false;\n }\n }\n return true;\n}\n\nexport function patchComment(roots: readonly Comment[], incoming: Comment): readonly Comment[] {\n return updateComment(roots, incoming.id, (local) => mergeComment(local, incoming));\n}\n\nexport function tombstone(comment: Comment): Comment {\n if (comment.deleted && comment.html === \"\" && comment.author === null) {\n return comment;\n }\n return {\n ...comment,\n deleted: true,\n html: \"\",\n author: null,\n likes: { ...comment.likes, can_like: false },\n can: { ...comment.can, edit: false, delete: false, flag: false },\n };\n}\n\nexport function tombstoneComment(roots: readonly Comment[], id: number): readonly Comment[] {\n return updateComment(roots, id, tombstone);\n}\n\n/** Inserts (or patches, if already present anywhere) a top-level comment. */\nexport function insertRoot(\n roots: readonly Comment[],\n comment: Comment,\n position: InsertPosition,\n): readonly Comment[] {\n if (findComment(roots, comment.id)) {\n return patchComment(roots, comment);\n }\n if (position === \"end\") {\n return [...roots, comment];\n }\n // New comments go below featured (pinned) ones.\n let index = 0;\n while (index < roots.length && roots[index]!.pinned) {\n index++;\n }\n return [...roots.slice(0, index), comment, ...roots.slice(index)];\n}\n\n/**\n * Inserts a reply under `parentId`. With `bumpCounts`, the parent's\n * `direct_reply_count` and every ancestor's `total_descendant_count` grow by one.\n * Returns `null` when the parent is not in the tree.\n */\nexport function insertReply(\n roots: readonly Comment[],\n parentId: number,\n comment: Comment,\n position: InsertPosition,\n { bumpCounts }: { bumpCounts: boolean },\n): readonly Comment[] | null {\n if (findComment(roots, comment.id)) {\n return patchComment(roots, comment);\n }\n const location = findComment(roots, parentId);\n if (!location) {\n return null;\n }\n const ancestors = new Set(location.path);\n return mapPath(roots, ancestors, (node) => {\n const isParent = node.id === parentId;\n const children = isParent\n ? position === \"start\"\n ? [comment, ...node.children]\n : [...node.children, comment]\n : node.children;\n if (!bumpCounts) {\n return { ...node, children };\n }\n return {\n ...node,\n children,\n direct_reply_count: isParent ? node.direct_reply_count + 1 : node.direct_reply_count,\n total_descendant_count: node.total_descendant_count + 1,\n };\n });\n}\n\n/** Rewrites every node whose id is in `ids` (an ancestor path), deepest first. */\nfunction mapPath(\n nodes: readonly Comment[],\n ids: Set<number>,\n update: (node: Comment) => Comment,\n): Comment[] {\n return nodes.map((node) => {\n if (!ids.has(node.id)) {\n return node;\n }\n const children = node.children.some((c) => ids.has(c.id))\n ? mapPath(node.children, ids, update)\n : node.children;\n return update(children === node.children ? node : { ...node, children });\n });\n}\n\n/** Appends children/roots that are not in the tree yet (paging dedupe). */\nexport function appendUnique(\n existing: readonly Comment[],\n more: readonly Comment[],\n tree: readonly Comment[] = existing,\n): Comment[] {\n const fresh = more.filter((c) => !findComment(tree, c.id));\n // Same reference when nothing is new, so callers can detect \"unchanged\".\n return fresh.length === 0 ? (existing as Comment[]) : [...existing, ...fresh];\n}\n\n/**\n * Merges a page of children into the ones already shown: known siblings are\n * updated in place (their subtrees merged), new ones are appended in server\n * order. Ids that already sit elsewhere in `tree` are not duplicated.\n */\nexport function mergeSiblings(\n local: Comment[],\n incoming: readonly Comment[],\n tree: readonly Comment[],\n): Comment[] {\n const byId = new Map(incoming.map((c) => [c.id, c]));\n let changed = false;\n const merged = local.map((c) => {\n const next = byId.get(c.id);\n if (!next) {\n return c;\n }\n const result = mergeComment(c, next);\n changed ||= result !== c;\n return result;\n });\n const localIds = new Set(local.map((c) => c.id));\n const fresh = incoming.filter((c) => !localIds.has(c.id) && !findComment(tree, c.id));\n if (!changed && fresh.length === 0) {\n return local;\n }\n return [...merged, ...fresh];\n}\n\n/** Ids of every comment in the tree that is not a deleted placeholder. */\nexport function collectIds(roots: readonly Comment[]): number[] {\n const ids: number[] = [];\n const walk = (nodes: readonly Comment[]) => {\n for (const node of nodes) {\n if (!node.deleted) {\n ids.push(node.id);\n }\n walk(node.children);\n }\n };\n walk(roots);\n return ids;\n}\n\n/** Highest post number anywhere in the tree (0 when empty). */\nexport function maxNumber(roots: readonly Comment[]): number {\n let max = 0;\n for (const node of roots) {\n max = Math.max(max, node.number, maxNumber(node.children));\n }\n return max;\n}\n\nexport function applyPins(roots: readonly Comment[], pinnedIds: readonly number[]): Comment[] {\n const pinned = new Set(pinnedIds);\n const flagged = roots.map((c) =>\n c.pinned === pinned.has(c.id) ? c : { ...c, pinned: pinned.has(c.id) },\n );\n const order = new Map(pinnedIds.map((id, index) => [id, index]));\n const featured = flagged\n .filter((c) => c.pinned)\n .sort((a, b) => (order.get(a.id) ?? 0) - (order.get(b.id) ?? 0));\n return [...featured, ...flagged.filter((c) => !c.pinned)];\n}\n\nexport function rootPosition(sort: Sort): InsertPosition {\n return sort === \"oldest\" ? \"end\" : \"start\";\n}\n\nexport function replyPosition(sort: Sort): InsertPosition {\n return sort === \"newest\" ? \"start\" : \"end\";\n}\n","import { REFETCH_BATCH_SIZE } from \"../constants\";\nimport { CommentsError, isCommentsError } from \"../errors\";\nimport {\n type AnyThread,\n type ChildrenPageResponse,\n type Comment,\n type CommentLikes,\n type CommentContextResponse,\n type CommentResponse,\n type CommentsByIdsResponse,\n type CreateCommentResponse,\n type FlagType,\n isVirtualThread,\n type Pending,\n type PinsResponse,\n type RawResponse,\n type RootsPageResponse,\n type Sort,\n type Thread,\n} from \"../types\";\nimport { type ComposerTimer, createComposerTimer } from \"./composer\";\nimport { Emitter } from \"./emitter\";\nimport { type Http, isAbortError, threadPath } from \"./http\";\nimport type { Logger } from \"./log\";\nimport {\n type BusEvent,\n IntervalRefresher,\n type RealtimeStatus,\n type RealtimeSubscription,\n type RealtimeTransport,\n} from \"./realtime\";\nimport {\n applyPins,\n collectIds,\n findByNumber,\n findComment,\n insertReply,\n insertRoot,\n maxNumber,\n mergeSiblings,\n patchComment,\n replyPosition,\n rootPosition,\n tombstone,\n tombstoneComment,\n updateComment,\n} from \"./tree\";\n\nexport type ThreadStatus = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\n/** How updates arrive: MessageBus, the interval fallback, or not at all. */\nexport type ConnectionMode = \"live\" | \"interval\" | \"off\";\n\nexport interface BranchState {\n /** Last children page loaded for this comment (-1 = only the preloaded ones). */\n readonly page: number;\n readonly loading: boolean;\n readonly hasMore: boolean;\n}\n\nexport interface ThreadSnapshot {\n readonly thread: AnyThread;\n /** True until the page's topic exists (`thread.id` starts with `v:`). */\n readonly virtual: boolean;\n /** Top-level comments with their loaded replies nested in `children`. */\n readonly comments: readonly Comment[];\n readonly sort: Sort;\n readonly status: ThreadStatus;\n readonly error: CommentsError | null;\n readonly page: number;\n readonly hasMore: boolean;\n readonly loadingMore: boolean;\n /** Top-level comments that arrived live and wait for `showPending()`. */\n readonly pendingNew: number;\n readonly branches: Readonly<Record<number, BranchState>>;\n /** The reader's own comments that went to the review queue. */\n readonly awaitingApproval: readonly Pending[];\n readonly connection: ConnectionMode;\n}\n\nexport type ThreadEvent =\n | { type: \"change\"; snapshot: ThreadSnapshot }\n | { type: \"comment.posted\"; comment: Comment }\n | { type: \"comment.pending\"; pending: Pending }\n | { type: \"comment.edited\"; comment: Comment }\n | { type: \"comment.removed\"; id: number }\n | { type: \"comment.received\"; comment: Comment; buffered: boolean }\n | { type: \"thread.created\"; thread: Thread };\n\nexport interface PostOptions {\n body: string;\n /** Id of the comment being replied to (never a post number). */\n replyTo?: number;\n typingDurationMsecs?: number;\n composerOpenDurationMsecs?: number;\n /** Timer to read when the durations are not passed; defaults to `thread.composer`. */\n composer?: ComposerTimer;\n}\n\nexport type PostResult =\n | { type: \"created\"; comment: Comment }\n | { type: \"pending\"; pending: Pending };\n\nexport interface FlagOptions {\n type: FlagType;\n message?: string;\n}\n\nexport interface CommentContext {\n ancestors: Comment[];\n ancestorsTruncated: boolean;\n comment: Comment;\n}\n\nexport interface ThreadHandle {\n /** Current handle; changes from `v:…` to the topic id once the thread is created. */\n readonly id: string;\n /** Default timer for the thread's main composer. */\n readonly composer: ComposerTimer;\n /** Immutable; the same object is returned until something changes. */\n snapshot(): ThreadSnapshot;\n subscribe(listener: (event: ThreadEvent) => void): () => void;\n load(): Promise<void>;\n loadMore(): Promise<void>;\n loadReplies(commentId: number): Promise<void>;\n setSort(sort: Sort): Promise<void>;\n post(options: PostOptions): Promise<PostResult>;\n edit(commentId: number, body: string): Promise<Comment>;\n remove(commentId: number): Promise<void>;\n like(commentId: number): Promise<Comment>;\n unlike(commentId: number): Promise<Comment>;\n flag(commentId: number, options: FlagOptions): Promise<void>;\n pin(commentId: number): Promise<void>;\n unpin(commentId: number): Promise<void>;\n /** Markdown source, for editing. */\n raw(commentId: number): Promise<string>;\n /** Moves live-arrived top-level comments into `comments`. */\n showPending(): void;\n /** Loads a comment with its ancestors into the tree (deep links). */\n context(commentId: number): Promise<CommentContext>;\n dispose(): void;\n}\n\nexport interface PageRef {\n url: string;\n title?: string | undefined;\n identifier?: string | undefined;\n}\n\nexport interface ThreadDeps {\n http: Http;\n realtime: RealtimeTransport;\n currentUserId: () => number | null;\n /** Bumped by the client whenever the signed-in reader changes. */\n identity: () => number;\n page: PageRef;\n /** Re-runs `POST /comments/threads` for this page. */\n resolve: () => Promise<AnyThread>;\n log: Logger;\n onDispose: () => void;\n}\n\ntype TopicMessage = { type?: unknown; id?: unknown; posts_count?: unknown };\n\n/**\n * When a request started: `seq` orders it against local events (deletions,\n * like intents), `identity` against sign-in changes.\n */\ninterface Ticket {\n seq: number;\n identity: number;\n}\n\n/** Server facts applied while a reload is in flight, re-applied on its result. */\ntype JournalEntry =\n | { kind: \"comments\"; comments: readonly Comment[]; insertable: ReadonlySet<number>; ticket: Ticket }\n | { kind: \"tombstone\"; id: number }\n | { kind: \"pins\"; ids: number[]; identity: number };\n\ninterface LikeIntent {\n /** Event seq of the latest like/unlike for the comment. */\n seq: number;\n /** Server state after the last completed request (what a failure rolls back to). */\n confirmed: CommentLikes;\n /** Requests for one comment go out one at a time, in click order. */\n chain: Promise<unknown>;\n}\n\nconst MAX_REFETCH_RETRIES = 4;\nconst MAX_RESOLVE_RETRIES = 5;\nconst RECONCILE_BATCHES_PER_RUN = 4;\nconst MAX_GAP_PAGES = 5;\n\nexport class CommentThread implements ThreadHandle {\n readonly composer: ComposerTimer = createComposerTimer();\n #deps: ThreadDeps;\n #state: ThreadSnapshot;\n #events = new Emitter<ThreadEvent>();\n /** Live-arrived roots, oldest first, not yet shown. */\n #incoming: readonly Comment[] = [];\n #incomingIdentity = 0;\n /** Bumped by every reload; page and branch responses from an older one are dropped. */\n #generation = 0;\n #loadController: AbortController | null = null;\n #journal: JournalEntry[] = [];\n /** Local event counter (see `Ticket`). */\n #seq = 0;\n /** Event seq at which each comment was seen deleted; older responses cannot revive it. */\n #deletedAt = new Map<number, number>();\n #likes = new Map<number, LikeIntent>();\n #realtimeKey: string | null = null;\n #subscription: RealtimeSubscription | null = null;\n #stopStatus: (() => void) | null = null;\n #refresher: IntervalRefresher;\n /** Highest top-level post number known to exist; `null` until known exactly. */\n #baseline: number | null = null;\n #reconcileOffset = 0;\n #refetch = new Map<number, boolean>();\n #refetchScheduled = false;\n #refetchChain: Promise<void> = Promise.resolve();\n #refetchAttempts = 0;\n #refetchTimer: ReturnType<typeof setTimeout> | undefined;\n #resolving: Promise<void> | null = null;\n #resolveAttempts = 0;\n #resolveTimer: ReturnType<typeof setTimeout> | undefined;\n #disposed = false;\n\n constructor(thread: AnyThread, deps: ThreadDeps, sort?: Sort) {\n this.#deps = deps;\n this.#state = Object.freeze({\n thread,\n virtual: isVirtualThread(thread),\n comments: [],\n sort: sort ?? thread.sort,\n status: \"idle\",\n error: null,\n page: 0,\n hasMore: false,\n loadingMore: false,\n pendingNew: 0,\n branches: {},\n awaitingApproval: [],\n connection: \"off\",\n } satisfies ThreadSnapshot);\n this.#refresher = new IntervalRefresher(() => this.#refreshOnce());\n }\n\n get id(): string {\n return this.#state.thread.id;\n }\n\n snapshot(): ThreadSnapshot {\n return this.#state;\n }\n\n subscribe(listener: (event: ThreadEvent) => void): () => void {\n return this.#events.on(listener);\n }\n\n async load(): Promise<void> {\n if (this.#disposed) {\n return;\n }\n const thread = this.#state.thread;\n if (isVirtualThread(thread)) {\n if (this.#state.status === \"ready\") {\n // Reloads (e.g. after signing in) refresh `can_comment` and catch a\n // topic created in the meantime.\n await this.#reresolve();\n if (!this.#state.virtual) {\n return;\n }\n }\n this.#set({ status: \"ready\", comments: [], hasMore: false, page: 0 });\n this.#ensureRealtime();\n return;\n }\n\n const generation = ++this.#generation;\n this.#loadController?.abort();\n const controller = new AbortController();\n this.#loadController = controller;\n this.#journal = [];\n const ticket = this.#ticket();\n const sort = this.#state.sort;\n this.#set({ status: \"loading\", error: null });\n\n try {\n // Poll-mode threads find new comments by post number. Reading the\n // newest root before the snapshot leaves no window in which one is missed.\n let baseline: number | null = null;\n if (thread.realtime === \"poll\" && sort !== \"newest\") {\n baseline = await this.#readBaseline(thread.id, controller.signal);\n }\n const response = await this.#deps.http.request<RootsPageResponse>(\"GET\", threadPath(thread.id), {\n query: { sort, page: 0 },\n signal: controller.signal,\n });\n if (generation !== this.#generation || !this.#current(ticket)) {\n return;\n }\n\n const comments = response.comments.map((c) => this.#sanitize(c, ticket));\n const effectiveSort = response.sort ?? sort;\n const exact = effectiveSort === \"newest\" || !response.has_more;\n this.#baseline =\n baseline !== null\n ? Math.max(baseline, maxNumber(comments))\n : exact\n ? maxNumber(comments)\n : null;\n // Live arrivals not shown yet stay pending unless the snapshot has them;\n // ones fetched for a different reader are dropped.\n this.#incoming =\n this.#incomingIdentity === ticket.identity\n ? this.#incoming.filter((c) => !findComment(comments, c.id))\n : [];\n this.#set({\n thread: response.thread,\n comments,\n sort: effectiveSort,\n page: response.page ?? 0,\n hasMore: response.has_more,\n loadingMore: false,\n branches: {},\n pendingNew: this.#incoming.length,\n status: \"ready\",\n error: null,\n });\n // The server captured this id before reading the snapshot, so nothing\n // published while it loaded is skipped.\n this.#subscription?.advanceTo(response.thread.message_bus_last_id);\n this.#loadController = null;\n this.#replayJournal();\n this.#ensureRealtime();\n } catch (error) {\n if (generation !== this.#generation || isAbortError(error)) {\n return;\n }\n this.#journal = [];\n const failure = toCommentsError(error);\n this.#set({ status: \"error\", error: failure });\n throw failure;\n } finally {\n if (this.#loadController === controller) {\n this.#loadController = null;\n }\n }\n }\n\n async loadMore(): Promise<void> {\n const state = this.#state;\n if (state.virtual || !state.hasMore || state.loadingMore || state.status !== \"ready\") {\n return;\n }\n const generation = this.#generation;\n const ticket = this.#ticket();\n this.#set({ loadingMore: true });\n try {\n const response = await this.#deps.http.request<RootsPageResponse>(\n \"GET\",\n threadPath(state.thread.id),\n { query: { sort: state.sort, page: state.page + 1 } },\n );\n if (generation !== this.#generation || !this.#current(ticket)) {\n return;\n }\n const page = response.comments.map((c) => this.#sanitize(c, ticket));\n let comments = this.#state.comments;\n const fresh: Comment[] = [];\n for (const comment of page) {\n if (findComment(comments, comment.id)) {\n comments = patchComment(comments, comment);\n } else {\n fresh.push(comment);\n }\n }\n const ids = new Set(page.map((c) => c.id));\n this.#incoming = this.#incoming.filter((c) => !ids.has(c.id));\n this.#set({\n comments: fresh.length > 0 ? [...comments, ...fresh] : comments,\n page: response.page ?? state.page + 1,\n hasMore: response.has_more,\n loadingMore: false,\n pendingNew: this.#incoming.length,\n });\n } catch (error) {\n if (generation === this.#generation) {\n this.#set({ loadingMore: false });\n }\n throw toCommentsError(error);\n }\n }\n\n async loadReplies(commentId: number): Promise<void> {\n const location = findComment(this.#state.comments, commentId);\n if (!location) {\n throw notInThread(commentId);\n }\n const branch = this.#state.branches[commentId];\n if (branch?.loading) {\n return;\n }\n const page = (branch?.page ?? -1) + 1;\n const generation = this.#generation;\n const ticket = this.#ticket();\n this.#setBranch(commentId, {\n page: branch?.page ?? -1,\n loading: true,\n hasMore: branch?.hasMore ?? true,\n });\n\n try {\n const response = await this.#deps.http.request<ChildrenPageResponse>(\n \"GET\",\n `${threadPath(this.id)}/children/${location.node.number}`,\n { query: { sort: this.#state.sort, page, depth: location.depth + 1 } },\n );\n if (generation !== this.#generation || !this.#current(ticket)) {\n return;\n }\n const children = response.comments.map((c) => this.#sanitize(c, ticket));\n const tree = this.#state.comments;\n let comments = updateComment(tree, commentId, (node) => {\n const merged = mergeSiblings(node.children, children, tree);\n return merged === node.children ? node : { ...node, children: merged };\n });\n // A child that already sits elsewhere (e.g. a deep link) is updated in place.\n for (const child of children) {\n const elsewhere = findComment(comments, child.id);\n if (elsewhere && elsewhere.path.at(-2) !== commentId) {\n comments = patchComment(comments, child);\n }\n }\n this.#set({ comments });\n this.#setBranch(commentId, {\n page: response.page ?? page,\n loading: false,\n hasMore: response.has_more,\n });\n } catch (error) {\n if (generation === this.#generation) {\n this.#setBranch(commentId, {\n page: branch?.page ?? -1,\n loading: false,\n hasMore: branch?.hasMore ?? true,\n });\n }\n throw toCommentsError(error);\n }\n }\n\n async setSort(sort: Sort): Promise<void> {\n if (sort === this.#state.sort && this.#state.status === \"ready\") {\n return;\n }\n this.#set({ sort });\n await this.load();\n }\n\n async post(options: PostOptions): Promise<PostResult> {\n const timer = options.composer ?? this.composer;\n const measured = timer.measure();\n const thread = this.#state.thread;\n const json: Record<string, unknown> = {\n raw: options.body,\n reply_to_id: options.replyTo,\n typing_duration_msecs: options.typingDurationMsecs ?? measured.typingDurationMsecs,\n composer_open_duration_msecs:\n options.composerOpenDurationMsecs ?? measured.composerOpenDurationMsecs,\n };\n if (isVirtualThread(thread)) {\n const { url, title, identifier } = this.#deps.page;\n json.page = { url, title, identifier };\n }\n\n const ticket = this.#ticket();\n const response = await this.#deps.http.request<CreateCommentResponse>(\n \"POST\",\n `${threadPath(thread.id)}/comments`,\n { json },\n );\n timer.stop();\n const current = this.#current(ticket);\n\n if (\"pending\" in response) {\n if (current) {\n this.#set({ awaitingApproval: [...this.#state.awaitingApproval, response.pending] });\n this.#events.emit({ type: \"comment.pending\", pending: response.pending });\n }\n return { type: \"pending\", pending: response.pending };\n }\n\n const { comment } = response;\n // Posted as a reader who has since signed out: the reload shows the result.\n if (!current) {\n return { type: \"created\", comment };\n }\n const wasVirtual = this.#state.virtual;\n if (wasVirtual) {\n this.#adopt(response.thread);\n } else {\n this.#mergeThreadMeta(response.thread);\n }\n this.#insertOwn(comment, options.replyTo, ticket);\n this.#events.emit({ type: \"comment.posted\", comment });\n if (wasVirtual && response.thread.count > 1) {\n // Someone else created the topic first; fetch their comments too.\n void this.load().catch(() => {});\n }\n return { type: \"created\", comment };\n }\n\n async edit(commentId: number, body: string): Promise<Comment> {\n const ticket = this.#ticket();\n const response = await this.#deps.http.request<CommentResponse>(\n \"PATCH\",\n this.#commentPath(commentId),\n { json: { raw: body } },\n );\n if (this.#current(ticket)) {\n this.#applyComments([response.comment], ticket, () => false);\n this.#events.emit({ type: \"comment.edited\", comment: response.comment });\n }\n return response.comment;\n }\n\n async remove(commentId: number): Promise<void> {\n const ticket = this.#ticket();\n await this.#deps.http.request<void>(\"DELETE\", this.#commentPath(commentId));\n if (!this.#current(ticket)) {\n return;\n }\n this.#markDeleted(commentId);\n // Authors' deletions are soft (revised text) and staff deletions leave a\n // placeholder; ask the server what the comment looks like now.\n const after = this.#ticket();\n try {\n const current = (await this.#fetchByIds([commentId])).comments[0];\n if (current) {\n this.#applyComments([current], after, () => false);\n }\n } catch {\n // The tombstone stays.\n }\n this.#events.emit({ type: \"comment.removed\", id: commentId });\n }\n\n like(commentId: number): Promise<Comment> {\n return this.#toggleLike(commentId, true);\n }\n\n unlike(commentId: number): Promise<Comment> {\n return this.#toggleLike(commentId, false);\n }\n\n async flag(commentId: number, options: FlagOptions): Promise<void> {\n await this.#deps.http.request<void>(\"POST\", `${this.#commentPath(commentId)}/flag`, {\n json: { flag_type: options.type, message: options.message },\n });\n }\n\n async pin(commentId: number): Promise<void> {\n await this.#setPin(commentId, \"PUT\");\n }\n\n async unpin(commentId: number): Promise<void> {\n await this.#setPin(commentId, \"DELETE\");\n }\n\n async raw(commentId: number): Promise<string> {\n const ticket = this.#ticket();\n const response = await this.#deps.http.request<RawResponse>(\n \"GET\",\n `${this.#commentPath(commentId)}/raw`,\n );\n this.#assertCurrent(ticket);\n return response.raw;\n }\n\n showPending(): void {\n if (this.#incoming.length === 0) {\n return;\n }\n let comments = this.#state.comments;\n const position = rootPosition(this.#state.sort);\n for (const comment of this.#incoming) {\n comments = insertRoot(comments, comment, position);\n }\n this.#incoming = [];\n this.#set({ comments, pendingNew: 0 });\n }\n\n async context(commentId: number): Promise<CommentContext> {\n const ticket = this.#ticket();\n let number = findComment(this.#state.comments, commentId)?.node.number;\n if (number === undefined) {\n number = (await this.#fetchByIds([commentId])).comments[0]?.number;\n this.#assertCurrent(ticket);\n }\n if (number === undefined) {\n throw notInThread(commentId);\n }\n\n const response = await this.#deps.http.request<CommentContextResponse>(\n \"GET\",\n `${threadPath(this.id)}/context/${number}`,\n { query: { sort: this.#state.sort } },\n );\n this.#assertCurrent(ticket);\n\n const ancestors = response.ancestors.map((c) => this.#sanitize(c, ticket));\n const target = this.#sanitize(response.comment, ticket);\n const chain = [...ancestors, target];\n let comments = this.#state.comments;\n const [top, ...rest] = chain;\n if (top && !findComment(comments, top.id)) {\n comments = insertRoot(comments, top, \"start\");\n }\n let parentId = top?.id;\n for (const node of rest) {\n if (parentId !== undefined && !findComment(comments, node.id)) {\n comments = insertReply(comments, parentId, node, \"start\", { bumpCounts: false }) ?? comments;\n }\n parentId = node.id;\n }\n this.#incoming = this.#incoming.filter((c) => !chain.some((n) => n.id === c.id));\n this.#set({ comments, pendingNew: this.#incoming.length });\n\n return {\n ancestors,\n ancestorsTruncated: response.ancestors_truncated,\n comment: target,\n };\n }\n\n dispose(): void {\n if (this.#disposed) {\n return;\n }\n this.#disposed = true;\n this.#generation++;\n this.#loadController?.abort();\n clearTimeout(this.#refetchTimer);\n clearTimeout(this.#resolveTimer);\n this.#stopRealtime();\n this.#events.clear();\n this.#deps.onDispose();\n }\n\n // Realtime\n\n #realtimeKeyFor(thread: AnyThread): string {\n return isVirtualThread(thread)\n ? `pending:${thread.pending_channel}`\n : `${thread.realtime}:${thread.topic_id}`;\n }\n\n /** (Re)connects whenever the thread, its channel or its realtime mode changes. */\n #ensureRealtime(): void {\n const thread = this.#state.thread;\n const key = this.#realtimeKeyFor(thread);\n if (this.#disposed || this.#realtimeKey === key) {\n return;\n }\n this.#stopRealtime();\n this.#realtimeKey = key;\n const { realtime } = this.#deps;\n\n if (isVirtualThread(thread)) {\n // -2 replays the channel's last message, covering a creation announced\n // between the snapshot and this subscription. Any activity counts: in\n // read-restricted categories the announcement is group-scoped, so\n // anonymous polls only see the cursor move.\n this.#subscription = realtime.subscribe(thread.pending_channel, -2, () => {\n void this.#reresolve();\n });\n } else if (thread.realtime === \"live\") {\n this.#subscription = realtime.subscribe(\n `/topic/${thread.topic_id}`,\n thread.message_bus_last_id,\n (event) => this.#onTopicEvent(event),\n );\n } else {\n // Poll mode: the load just read everything, so the first refresh can wait.\n this.#startFallback(false);\n return;\n }\n\n this.#stopStatus = realtime.onStatus((status) => this.#onTransportStatus(status));\n this.#onTransportStatus(realtime.status);\n }\n\n /** Interval refreshes; `immediate` also runs one now (catching up after a failure). */\n #startFallback(immediate: boolean): void {\n this.#set({ connection: \"interval\" });\n if (this.#refresher.active) {\n return;\n }\n this.#refresher.start();\n if (immediate) {\n void this.#refresher.runNow();\n }\n }\n\n #stopRealtime(): void {\n this.#subscription?.unsubscribe();\n this.#subscription = null;\n this.#stopStatus?.();\n this.#stopStatus = null;\n this.#refresher.stop();\n this.#realtimeKey = null;\n this.#set({ connection: \"off\" });\n }\n\n #onTransportStatus(status: RealtimeStatus): void {\n if (status === \"failed\") {\n this.#startFallback(true);\n return;\n }\n const recovering = this.#refresher.active;\n this.#refresher.stop();\n this.#set({ connection: \"live\" });\n if (recovering && status === \"connected\") {\n // Catch up on anything the MessageBus backlog may no longer hold.\n void this.#refresher.runNow();\n }\n }\n\n #onTopicEvent(event: BusEvent): void {\n if (event.kind === \"gap\") {\n // The server's position went backwards: messages may be lost, so\n // reconcile what is loaded and look for new comments.\n void this.#refresher.runNow();\n return;\n }\n if (event.kind !== \"message\") {\n return;\n }\n const message = event.data as TopicMessage;\n if (!message || typeof message !== \"object\") {\n return;\n }\n const id = typeof message.id === \"number\" ? message.id : null;\n switch (message.type) {\n case \"created\":\n if (id !== null) {\n this.#queueRefetch(id, true);\n }\n break;\n case \"recovered\":\n if (id !== null) {\n this.#deletedAt.delete(id);\n this.#event();\n this.#queueRefetch(id, true);\n }\n break;\n case \"revised\":\n case \"rebaked\":\n case \"liked\":\n case \"unliked\":\n // Unknown ids are comments not loaded here; fetching them would turn an\n // edit of an old comment into a \"new comment\".\n if (id !== null && this.#knows(id)) {\n this.#queueRefetch(id, false);\n }\n break;\n case \"deleted\":\n case \"destroyed\":\n if (id !== null) {\n this.#markDeleted(id);\n }\n break;\n case \"stats\":\n if (typeof message.posts_count === \"number\" && !isVirtualThread(this.#state.thread)) {\n const count = Math.max(message.posts_count - 1, 0);\n if (count !== this.#state.thread.count) {\n this.#set({ thread: { ...this.#state.thread, count } });\n }\n }\n break;\n }\n }\n\n #knows(id: number): boolean {\n return (\n findComment(this.#state.comments, id) !== null || findComment(this.#incoming, id) !== null\n );\n }\n\n #queueRefetch(id: number, allowInsert: boolean): void {\n this.#refetch.set(id, (this.#refetch.get(id) ?? false) || allowInsert);\n // While a retry is waiting (e.g. on a rate limit) the timer flushes everything.\n if (this.#refetchTimer === undefined) {\n this.#scheduleRefetch();\n }\n }\n\n #scheduleRefetch(): void {\n if (this.#refetchScheduled) {\n return;\n }\n this.#refetchScheduled = true;\n // One flush at a time, so responses are applied in request order.\n queueMicrotask(() => {\n this.#refetchChain = this.#refetchChain.then(() => this.#flushRefetch());\n });\n }\n\n async #flushRefetch(): Promise<void> {\n const pending = new Map(this.#refetch);\n this.#refetch.clear();\n this.#refetchScheduled = false;\n if (this.#disposed || isVirtualThread(this.#state.thread) || pending.size === 0) {\n return;\n }\n const ticket = this.#ticket();\n const ids = [...pending.keys()];\n for (let i = 0; i < ids.length; i += REFETCH_BATCH_SIZE) {\n try {\n const response = await this.#fetchByIds(ids.slice(i, i + REFETCH_BATCH_SIZE));\n if (!this.#current(ticket)) {\n // The reload for the new reader covers these.\n return;\n }\n this.#refetchAttempts = 0;\n this.#mergeThreadMeta(response.thread);\n this.#applyComments(response.comments, ticket, (c) => pending.get(c.id) === true);\n } catch (error) {\n if (this.#disposed || isAbortError(error)) {\n return;\n }\n this.#deps.log(\"refetch failed\", error);\n for (const id of ids.slice(i)) {\n this.#refetch.set(id, (this.#refetch.get(id) ?? false) || pending.get(id) === true);\n }\n this.#retryRefetch(error);\n return;\n }\n }\n }\n\n /** Retries failed hydration with backoff (honouring rate limits), then reconciles. */\n #retryRefetch(error: unknown): void {\n this.#refetchAttempts++;\n if (this.#refetchAttempts > MAX_REFETCH_RETRIES) {\n this.#refetchAttempts = 0;\n this.#refetch.clear();\n void this.#refresher.runNow();\n return;\n }\n const waitSeconds = isCommentsError(error) ? error.waitSeconds : undefined;\n const delay =\n waitSeconds !== undefined\n ? waitSeconds * 1_000\n : Math.min(1_000 * 2 ** this.#refetchAttempts, 30_000);\n clearTimeout(this.#refetchTimer);\n this.#refetchTimer = setTimeout(() => {\n this.#refetchTimer = undefined;\n this.#scheduleRefetch();\n }, delay);\n }\n\n /**\n * One fallback refresh; resolves `true` when anything changed. Discovers new\n * top-level comments by post number (whatever the display sort), then\n * re-reads the loaded ones so edits, likes and deletions show up.\n */\n async #refreshOnce(): Promise<boolean> {\n const thread = this.#state.thread;\n if (isVirtualThread(thread)) {\n await this.#reresolve();\n return !this.#state.virtual;\n }\n const ticket = this.#ticket();\n const generation = this.#generation;\n const stale = () => generation !== this.#generation || !this.#current(ticket);\n const countBefore = thread.count;\n let changed = false;\n\n if (this.#baseline === null) {\n // Only reachable when live updates failed on a paged, non-newest view:\n // start from now, and let the MessageBus backlog fill the gap if it\n // comes back. Keep the short interval after this run.\n const baseline = await this.#readBaseline(thread.id);\n if (stale()) {\n return false;\n }\n this.#baseline = Math.max(baseline, maxNumber(this.#state.comments), maxNumber(this.#incoming));\n changed = true;\n } else {\n const baseline = this.#baseline;\n let highest = baseline;\n const found: Comment[] = [];\n for (let page = 0; page < MAX_GAP_PAGES; page++) {\n const response = await this.#deps.http.request<RootsPageResponse>(\"GET\", threadPath(thread.id), {\n query: { sort: \"newest\", page },\n });\n if (stale()) {\n return false;\n }\n this.#mergeThreadMeta(response.thread);\n found.push(...response.comments);\n highest = Math.max(highest, maxNumber(response.comments));\n if (!response.has_more || response.comments.some((c) => c.number <= baseline)) {\n break;\n }\n }\n this.#baseline = highest;\n changed = this.#applyComments(found, ticket, (c) => c.number > baseline);\n }\n\n changed = (await this.#reconcileLoaded(ticket, stale)) || changed;\n return changed || this.#state.thread.count !== countBefore;\n }\n\n /** Re-reads a rotating window of loaded comments; missing ones are gone for this reader. */\n async #reconcileLoaded(ticket: Ticket, stale: () => boolean): Promise<boolean> {\n const ids = collectIds(this.#state.comments);\n if (ids.length === 0) {\n return false;\n }\n const start = this.#reconcileOffset % ids.length;\n const window = [...ids.slice(start), ...ids.slice(0, start)].slice(\n 0,\n REFETCH_BATCH_SIZE * RECONCILE_BATCHES_PER_RUN,\n );\n this.#reconcileOffset = start + window.length;\n\n let changed = false;\n for (let i = 0; i < window.length; i += REFETCH_BATCH_SIZE) {\n const batch = window.slice(i, i + REFETCH_BATCH_SIZE);\n const response = await this.#fetchByIds(batch);\n if (stale()) {\n return changed;\n }\n this.#mergeThreadMeta(response.thread);\n changed = this.#applyComments(response.comments, ticket, () => false) || changed;\n const returned = new Set(response.comments.map((c) => c.id));\n for (const id of batch) {\n if (!returned.has(id) && findComment(this.#state.comments, id)?.node.deleted === false) {\n this.#markDeleted(id);\n changed = true;\n }\n }\n }\n return changed;\n }\n\n async #readBaseline(threadId: string, signal?: AbortSignal): Promise<number> {\n const response = await this.#deps.http.request<RootsPageResponse>(\"GET\", threadPath(threadId), {\n query: { sort: \"newest\", page: 0 },\n signal,\n });\n return maxNumber(response.comments);\n }\n\n /**\n * Re-resolves a virtual thread (did its topic appear? did permissions\n * change?). Failures surface on `snapshot().error` and retry with backoff,\n * then on the slow interval until the topic exists or the handle is disposed.\n */\n #reresolve(): Promise<void> {\n this.#resolving ??= (async () => {\n const ticket = this.#ticket();\n try {\n const thread = await this.#deps.resolve();\n if (this.#disposed || !this.#state.virtual) {\n return;\n }\n if (!this.#current(ticket)) {\n // Resolved for the previous reader; ask again for the current one.\n queueMicrotask(() => void this.#reresolve());\n return;\n }\n this.#resolveAttempts = 0;\n clearTimeout(this.#resolveTimer);\n if (isVirtualThread(thread)) {\n this.#set({ thread: sameJson(thread, this.#state.thread) ? this.#state.thread : thread, error: null });\n this.#ensureRealtime();\n return;\n }\n this.#adopt(thread);\n await this.load();\n } catch (error) {\n if (this.#disposed || isAbortError(error)) {\n return;\n }\n this.#deps.log(\"re-resolving the thread failed\", error);\n this.#set({ error: toCommentsError(error) });\n this.#scheduleResolveRetry();\n } finally {\n this.#resolving = null;\n }\n })();\n return this.#resolving;\n }\n\n #scheduleResolveRetry(): void {\n this.#resolveAttempts++;\n clearTimeout(this.#resolveTimer);\n if (this.#resolveAttempts > MAX_RESOLVE_RETRIES) {\n this.#resolveAttempts = 0;\n this.#startFallback(false);\n return;\n }\n this.#resolveTimer = setTimeout(\n () => void this.#reresolve(),\n Math.min(2_000 * 2 ** (this.#resolveAttempts - 1), 30_000),\n );\n }\n\n /** Switches a virtual thread to its newly created topic. */\n #adopt(thread: Thread): void {\n clearTimeout(this.#resolveTimer);\n this.#resolveAttempts = 0;\n this.#set({ thread, virtual: false, status: \"ready\", error: null });\n this.#ensureRealtime();\n this.#events.emit({ type: \"thread.created\", thread });\n }\n\n // Applying server data\n\n #ticket(): Ticket {\n return { seq: this.#seq, identity: this.#deps.identity() };\n }\n\n #event(): number {\n return ++this.#seq;\n }\n\n /** The response belongs to this handle's current reader. */\n #current(ticket: Ticket): boolean {\n return !this.#disposed && ticket.identity === this.#deps.identity();\n }\n\n #assertCurrent(ticket: Ticket): void {\n if (!this.#current(ticket)) {\n throw new CommentsError(\"cancelled\", \"The reader changed while this request was running\");\n }\n }\n\n /**\n * Adjusts a server comment (recursively) for what happened locally after the\n * request started: deletions win, and a like in flight keeps showing the\n * reader's latest intent.\n */\n #sanitize(comment: Comment, ticket: Ticket): Comment {\n let node = comment;\n const deletedAt = this.#deletedAt.get(node.id);\n if (deletedAt !== undefined && deletedAt > ticket.seq && !node.deleted) {\n node = tombstone(node);\n }\n if (this.#likes.has(node.id)) {\n const shown = findComment(this.#state.comments, node.id)?.node.likes;\n if (shown && !sameJson(shown, node.likes)) {\n node = { ...node, likes: shown };\n }\n }\n if (node.children.length > 0) {\n const children = node.children.map((child) => this.#sanitize(child, ticket));\n if (children.some((child, index) => child !== node.children[index])) {\n node = { ...node, children };\n }\n }\n return node;\n }\n\n /** Folds server comments in: patch known ones, place insertable new ones. */\n #applyComments(\n comments: readonly Comment[],\n ticket: Ticket,\n insertable: (comment: Comment) => boolean,\n ): boolean {\n if (!this.#current(ticket) || comments.length === 0) {\n return false;\n }\n const sanitized = comments.map((c) => this.#sanitize(c, ticket));\n this.#record({\n kind: \"comments\",\n comments: sanitized,\n insertable: new Set(sanitized.filter(insertable).map((c) => c.id)),\n ticket,\n });\n\n let tree = this.#state.comments;\n let incoming = this.#incoming;\n const received: Array<{ comment: Comment; buffered: boolean }> = [];\n const me = this.#deps.currentUserId();\n const sort = this.#state.sort;\n\n for (const comment of sanitized) {\n if (findComment(tree, comment.id)) {\n tree = patchComment(tree, comment);\n continue;\n }\n if (findComment(incoming, comment.id)) {\n incoming = patchComment(incoming, comment);\n continue;\n }\n if (!insertable(comment) || this.#deletedAt.has(comment.id)) {\n continue;\n }\n\n const parentNumber = comment.reply_to?.number;\n if (parentNumber === undefined) {\n if (me !== null && comment.author?.id === me) {\n tree = insertRoot(tree, comment, rootPosition(sort));\n received.push({ comment, buffered: false });\n } else {\n incoming = [...incoming, comment];\n received.push({ comment, buffered: true });\n }\n continue;\n }\n\n const position = replyPosition(sort);\n const parentInTree = findByNumber(tree, parentNumber);\n if (parentInTree) {\n tree =\n insertReply(tree, parentInTree.node.id, comment, position, { bumpCounts: true }) ?? tree;\n received.push({ comment, buffered: false });\n continue;\n }\n const parentInIncoming = findByNumber(incoming, parentNumber);\n if (parentInIncoming) {\n incoming =\n insertReply(incoming, parentInIncoming.node.id, comment, position, {\n bumpCounts: true,\n }) ?? incoming;\n }\n }\n\n const changed = tree !== this.#state.comments || incoming !== this.#incoming;\n if (incoming !== this.#incoming) {\n this.#incomingIdentity = ticket.identity;\n }\n this.#incoming = incoming;\n this.#set({ comments: tree, pendingNew: incoming.length });\n for (const entry of received) {\n this.#events.emit({ type: \"comment.received\", ...entry });\n }\n return changed;\n }\n\n /** Records a deletion (barrier for older responses) and tombstones it everywhere. */\n #markDeleted(id: number): void {\n this.#deletedAt.set(id, this.#event());\n this.#record({ kind: \"tombstone\", id });\n this.#applyTombstone(id);\n }\n\n #applyTombstone(id: number): void {\n // A deleted root that was never shown simply goes away; nested ones are\n // tombstoned in the buffer too.\n this.#incoming = tombstoneComment(\n this.#incoming.filter((c) => c.id !== id),\n id,\n );\n this.#set({\n comments: tombstoneComment(this.#state.comments, id),\n pendingNew: this.#incoming.length,\n });\n }\n\n #record(entry: JournalEntry): void {\n if (this.#loadController) {\n this.#journal.push(entry);\n }\n }\n\n /** Re-applies facts that the just-loaded snapshot may predate. */\n #replayJournal(): void {\n const journal = this.#journal;\n this.#journal = [];\n for (const entry of journal) {\n if (entry.kind === \"tombstone\") {\n this.#applyTombstone(entry.id);\n } else if (entry.kind === \"pins\") {\n if (entry.identity === this.#deps.identity()) {\n this.#applyPins(entry.ids);\n }\n } else {\n this.#applyComments(entry.comments, entry.ticket, (c) => entry.insertable.has(c.id));\n }\n }\n }\n\n // Helpers\n\n #insertOwn(comment: Comment, replyTo: number | undefined, ticket: Ticket): void {\n this.#record({ kind: \"comments\", comments: [comment], insertable: new Set([comment.id]), ticket });\n const sort = this.#state.sort;\n let comments = this.#state.comments;\n if (replyTo !== undefined) {\n comments =\n insertReply(comments, replyTo, comment, replyPosition(sort), { bumpCounts: true }) ??\n comments;\n } else {\n comments = insertRoot(comments, comment, rootPosition(sort));\n }\n this.#incoming = this.#incoming.filter((c) => c.id !== comment.id);\n this.#set({ comments, pendingNew: this.#incoming.length });\n }\n\n /**\n * Likes are optimistic. Requests for one comment are sent in order and only\n * the latest intent's outcome (or rollback) touches what is shown.\n */\n async #toggleLike(commentId: number, liked: boolean): Promise<Comment> {\n const node = findComment(this.#state.comments, commentId)?.node;\n if (!node) {\n throw notInThread(commentId);\n }\n const ticket = this.#ticket();\n const seq = this.#event();\n const intent = this.#likes.get(commentId) ?? {\n seq,\n confirmed: node.likes,\n chain: Promise.resolve(),\n };\n intent.seq = seq;\n this.#likes.set(commentId, intent);\n if (node.likes.liked !== liked) {\n this.#set({\n comments: updateComment(this.#state.comments, commentId, (c) => ({\n ...c,\n likes: { ...c.likes, liked, count: Math.max(0, c.likes.count + (liked ? 1 : -1)) },\n })),\n });\n }\n\n const request = intent.chain\n .catch(() => {})\n .then(() =>\n this.#deps.http.request<CommentResponse>(\n liked ? \"PUT\" : \"DELETE\",\n `${this.#commentPath(commentId)}/like`,\n ),\n );\n intent.chain = request;\n\n try {\n const response = await request;\n if (!this.#current(ticket)) {\n return response.comment;\n }\n intent.confirmed = response.comment.likes;\n if (intent.seq === seq) {\n this.#likes.delete(commentId);\n }\n this.#applyComments([response.comment], ticket, () => false);\n return response.comment;\n } catch (error) {\n if (this.#current(ticket) && intent.seq === seq) {\n this.#likes.delete(commentId);\n this.#set({\n comments: updateComment(this.#state.comments, commentId, (c) =>\n sameJson(c.likes, intent.confirmed) ? c : { ...c, likes: intent.confirmed },\n ),\n });\n }\n throw toCommentsError(error);\n }\n }\n\n async #setPin(commentId: number, method: \"PUT\" | \"DELETE\"): Promise<void> {\n const ticket = this.#ticket();\n const response = await this.#deps.http.request<PinsResponse>(\n method,\n `${this.#commentPath(commentId)}/pin`,\n );\n if (this.#current(ticket)) {\n this.#record({ kind: \"pins\", ids: response.pinned_ids, identity: ticket.identity });\n this.#applyPins(response.pinned_ids);\n }\n }\n\n #applyPins(pinnedIds: number[]): void {\n const thread = this.#state.thread;\n if (isVirtualThread(thread)) {\n return;\n }\n this.#set({\n thread: sameJson(thread.pinned_ids, pinnedIds) ? thread : { ...thread, pinned_ids: pinnedIds },\n comments: applyPins(this.#state.comments, pinnedIds),\n });\n }\n\n #mergeThreadMeta(thread: Thread): void {\n const current = this.#state.thread;\n if (isVirtualThread(current) || current.id !== thread.id) {\n return;\n }\n // The sort and MessageBus position belong to this handle, not the response.\n const next = { ...thread, sort: current.sort, message_bus_last_id: current.message_bus_last_id };\n if (!sameJson(next, current)) {\n this.#set({ thread: next });\n if (this.#realtimeKey !== null && next.realtime !== current.realtime) {\n this.#ensureRealtime();\n }\n }\n }\n\n #fetchByIds(ids: number[]): Promise<CommentsByIdsResponse> {\n return this.#deps.http.request<CommentsByIdsResponse>(\"GET\", threadPath(this.id), {\n query: { ids, sort: this.#state.sort },\n });\n }\n\n #commentPath(commentId: number): string {\n return `${threadPath(this.id)}/comments/${commentId}`;\n }\n\n #setBranch(commentId: number, branch: BranchState): void {\n this.#set({ branches: { ...this.#state.branches, [commentId]: branch } });\n }\n\n #set(patch: Partial<ThreadSnapshot>): void {\n let changed = false;\n for (const key of Object.keys(patch) as Array<keyof ThreadSnapshot>) {\n if (patch[key] !== this.#state[key]) {\n changed = true;\n break;\n }\n }\n if (!changed || this.#disposed) {\n return;\n }\n this.#state = Object.freeze({ ...this.#state, ...patch });\n this.#events.emit({ type: \"change\", snapshot: this.#state });\n }\n}\n\nfunction sameJson(a: unknown, b: unknown): boolean {\n return a === b || JSON.stringify(a) === JSON.stringify(b);\n}\n\nfunction notInThread(commentId: number): CommentsError {\n return new CommentsError(\"not_found\", `Comment ${commentId} is not loaded in this thread`, {\n status: 404,\n });\n}\n\nfunction toCommentsError(error: unknown): CommentsError {\n if (isCommentsError(error)) {\n return error;\n }\n return new CommentsError(\"unknown\", error instanceof Error ? error.message : String(error), {\n cause: error,\n });\n}\n","import { CommentsError } from \"../errors\";\nimport type {\n AnyThread,\n Commenter,\n Config,\n CountRef,\n Counts,\n ForumTheme,\n MentionsResponse,\n PreviewResponse,\n Sort,\n ThreadResponse,\n Upload,\n} from \"../types\";\nimport { AuthController, type CommentsAuth } from \"./auth\";\nimport { CountsBatcher, encodeRef } from \"./counts\";\nimport { defaultPageTitle, defaultPageUrl, getWindow } from \"./env\";\nimport { type FetchLike, Http, normalizeForum, threadPath } from \"./http\";\nimport { createLogger } from \"./log\";\nimport { MessageBusPoller, type RealtimeTransport } from \"./realtime\";\nimport { browserStorage, isLocalStorage, signInStorage, type StorageLike } from \"./storage\";\nimport { CommentThread, type PageRef, type ThreadHandle } from \"./thread\";\n\nconst DEGRADED_RECHECK_MS = 60_000;\nconst MAX_DEGRADED_RECHECK_MS = 10 * 60_000;\nconst MAX_DEGRADED_CHECKS = 6;\n\nexport interface CreateClientOptions {\n /** The forum's base URL, e.g. `https://forum.example.com` (a trailing slash is fine). */\n forum: string;\n /** Custom fetch (SSR, tests, proxies). Defaults to the global fetch. */\n fetch?: FetchLike;\n /** Extra headers for comments API requests, e.g. `Authorization` for a forum behind basic auth. */\n headers?: Record<string, string>;\n /** Where the key and client id are kept. Defaults to `localStorage` (memory if unavailable). */\n storage?: StorageLike;\n /** Fixed client id (`[\\w-]{8,64}`) instead of a generated per-browser one. */\n clientId?: string;\n /** Sent as `Accept-Language` so server messages match the widget. */\n locale?: string;\n /** Logs requests and realtime activity to the console. */\n debug?: boolean;\n}\n\nexport interface OpenThreadOptions {\n /** Defaults to `<link rel=\"canonical\">`, else `location.href`. */\n url?: string;\n /** Defaults to `document.title`. */\n title?: string;\n /** Optional stable key, namespaced by the page's canonical host on the forum. */\n identifier?: string;\n /** Initial sort; defaults to the forum's default. */\n sort?: Sort;\n}\n\nexport interface UploadOptions {\n filename?: string;\n /** Marks the file as pasted from the clipboard. */\n pasted?: boolean;\n}\n\nexport interface CommentsClient {\n /** Normalized forum base URL. */\n readonly forum: string;\n readonly forumOrigin: string;\n readonly locale: string | undefined;\n readonly auth: CommentsAuth;\n readonly threads: {\n /** Resolves (or creates) the page's thread and loads its first page of comments. */\n open(options?: OpenThreadOptions): Promise<ThreadHandle>;\n };\n readonly attachments: {\n upload(threadId: string, file: Blob, options?: UploadOptions): Promise<Upload>;\n };\n /** Cached; refetched after sign-in and sign-out. */\n config(): Promise<Config>;\n /** The forum's palettes, fonts and theme stylesheets; cached for the client's lifetime. */\n theme(): Promise<ForumTheme>;\n /** Batched per tick, at most 50 refs per request. Keys are encoded refs (see `encodeRef`). */\n counts(refs: readonly CountRef[]): Promise<Counts>;\n count(ref: CountRef): Promise<number>;\n /** Cooks markdown into sanitized HTML (signed-in only). */\n preview(body: string): Promise<string>;\n /** User search for @mentions (signed-in only). */\n mentions(query: string, threadId?: string): Promise<Commenter[]>;\n /** Stops realtime, timers and listeners for every thread of this client. */\n dispose(): void;\n}\n\n/** Test seams; not part of the public API. */\nexport interface ClientInternals {\n realtime?: RealtimeTransport;\n navigate?: (url: string) => void;\n}\n\nexport function createClient(options: CreateClientOptions): CommentsClient {\n return createClientWithInternals(options, {});\n}\n\nexport function createClientWithInternals(\n options: CreateClientOptions,\n internals: ClientInternals,\n): CommentsClient {\n const forum = normalizeForum(options.forum);\n const log = createLogger(options.debug);\n const { storage, syncAcrossTabs } = options.storage\n ? { storage: options.storage, syncAcrossTabs: isLocalStorage(options.storage) }\n : (() => {\n const resolved = browserStorage();\n return { storage: resolved.storage, syncAcrossTabs: resolved.isLocalStorage };\n })();\n\n let latestConfig: Config | null = null;\n let configPromise: Promise<Config> | null = null;\n const threads = new Set<CommentThread>();\n // Aborted on dispose: cancels requests in flight and fences late responses.\n const lifetime = new AbortController();\n const disposedError = () => new CommentsError(\"cancelled\", \"The comments client was disposed\");\n\n // `auth` and `http` need each other; the closures below run after both exist.\n let auth: AuthController;\n const http = new Http({\n forum,\n fetch: options.fetch,\n headers: options.headers,\n locale: options.locale,\n credentials: () => auth.credentials(),\n onInvalidKey: (key) => auth.invalidate(key),\n log,\n lifetime: lifetime.signal,\n });\n auth = new AuthController({\n http,\n forum,\n storage,\n pendingStorage: signInStorage(storage),\n syncAcrossTabs,\n clientId: options.clientId,\n log,\n providers: () => latestConfig?.auth_providers ?? [],\n navigate: internals.navigate,\n });\n const realtime = internals.realtime ?? new MessageBusPoller({ base: forum.base, fetch: http.fetch, log });\n const batcher = new CountsBatcher(http);\n\n let configGeneration = 0;\n let themePromise: Promise<ForumTheme> | null = null;\n let degradedRecheck: ReturnType<typeof setTimeout> | undefined;\n let degradedChecks = 0;\n\n function config(): Promise<Config> {\n if (lifetime.signal.aborted) {\n return Promise.reject(disposedError());\n }\n if (!configPromise) {\n const generation = configGeneration;\n configPromise = http.request<Config>(\"GET\", \"/config\").then(\n (loaded): Config | Promise<Config> => {\n if (lifetime.signal.aborted) {\n throw disposedError();\n }\n // Fetched for a reader who has since signed in or out.\n if (generation !== configGeneration) {\n return config();\n }\n latestConfig = loaded;\n auth.applyConfig(loaded);\n clearTimeout(degradedRecheck);\n if (loaded.degraded) {\n scheduleDegradedRecheck();\n } else {\n degradedChecks = 0;\n }\n return loaded;\n },\n (error: unknown) => {\n if (generation === configGeneration) {\n configPromise = null;\n }\n throw error;\n },\n );\n }\n return configPromise;\n }\n\n /** Degraded means the forum was under load: look again, a bounded number of times. */\n function scheduleDegradedRecheck(): void {\n if (lifetime.signal.aborted || degradedChecks >= MAX_DEGRADED_CHECKS) {\n return;\n }\n const delay = Math.min(DEGRADED_RECHECK_MS * 2 ** degradedChecks, MAX_DEGRADED_RECHECK_MS);\n degradedChecks++;\n clearTimeout(degradedRecheck);\n degradedRecheck = setTimeout(() => {\n configPromise = null;\n // A failed recheck leaves the reader degraded; try again later.\n config().catch(() => scheduleDegradedRecheck());\n }, delay);\n }\n\n let lastUserId = auth.user?.id ?? null;\n // Bumped whenever the reader changes; thread responses fetched for an\n // earlier reader are discarded instead of mixing permissions.\n let identity = 0;\n const stopAuthListener = auth.onChange((state) => {\n if (state.status === \"signing-in\") {\n return;\n }\n const userId = state.status === \"signed-in\" ? (state.user?.id ?? null) : null;\n if (userId === lastUserId) {\n return;\n }\n lastUserId = userId;\n identity++;\n // Permissions (`can`, `likes.liked`) and `current_user` depend on who is asking.\n const hadConfig = configPromise !== null;\n configGeneration++;\n configPromise = null;\n if (hadConfig) {\n void config().catch(() => {});\n }\n for (const thread of threads) {\n void thread.load().catch(() => {});\n }\n });\n\n async function open(openOptions: OpenThreadOptions = {}): Promise<ThreadHandle> {\n if (lifetime.signal.aborted) {\n throw disposedError();\n }\n const url = openOptions.url ?? defaultPageUrl();\n if (!url) {\n throw new CommentsError(\"invalid_url\", \"No page URL: pass `url` outside the browser\");\n }\n const page: PageRef = {\n url,\n title: openOptions.title ?? defaultPageTitle(),\n identifier: openOptions.identifier,\n };\n const resolve = async (): Promise<AnyThread> =>\n (await http.request<ThreadResponse>(\"POST\", \"/threads\", { json: page })).thread;\n\n const thread = await resolve();\n if (lifetime.signal.aborted) {\n throw disposedError();\n }\n const handle: CommentThread = new CommentThread(\n thread,\n {\n http,\n realtime,\n currentUserId: () => auth.user?.id ?? null,\n identity: () => identity,\n page,\n resolve,\n log,\n onDispose: () => threads.delete(handle),\n },\n openOptions.sort,\n );\n threads.add(handle);\n // A failed first load stays on the handle (`status: \"error\"`) so the UI can retry.\n await handle.load().catch(() => {});\n return handle;\n }\n\n async function upload(threadId: string, file: Blob, uploadOptions: UploadOptions = {}) {\n const form = new FormData();\n const name = uploadOptions.filename ?? (file as Partial<File>).name ?? \"upload\";\n form.append(\"file\", file, name);\n if (uploadOptions.pasted) {\n form.append(\"pasted\", \"true\");\n }\n return http.request<Upload>(\"POST\", `${threadPath(threadId)}/attachments`, { form });\n }\n\n function theme(): Promise<ForumTheme> {\n if (lifetime.signal.aborted) {\n return Promise.reject(disposedError());\n }\n themePromise ??= http.request<ForumTheme>(\"GET\", \"/theme\").catch((error: unknown) => {\n themePromise = null;\n throw error;\n });\n return themePromise;\n }\n\n const client: CommentsClient = {\n forum: forum.base,\n forumOrigin: forum.origin,\n locale: options.locale,\n auth,\n threads: { open },\n attachments: { upload },\n config,\n theme,\n counts: (refs) => batcher.request(refs),\n count: async (ref) => (await batcher.request([ref]))[encodeRef(ref)] ?? 0,\n preview: async (body) =>\n (await http.request<PreviewResponse>(\"POST\", \"/preview\", { json: { raw: body } })).html,\n mentions: async (query, threadId) =>\n (\n await http.request<MentionsResponse>(\"GET\", \"/mentions\", {\n query: { q: query, thread: threadId },\n })\n ).users,\n dispose() {\n if (lifetime.signal.aborted) {\n return;\n }\n lifetime.abort();\n for (const thread of [...threads]) {\n thread.dispose();\n }\n realtime.stop();\n clearTimeout(degradedRecheck);\n stopAuthListener();\n auth.dispose();\n },\n };\n\n if (getWindow()) {\n void auth.handleRedirect();\n }\n\n return client;\n}\n","import { type CommentsClient, createClient, type CreateClientOptions } from \"./client\";\nimport { normalizeForum } from \"./http\";\n\n/**\n * Shares one client per forum per page, so every widget, count and hook that\n * names the same forum reuses one auth state, config cache, counts batcher and\n * realtime connection.\n */\nexport interface ClientRegistry {\n /**\n * The shared client for `options.forum`, created from `options` on first use.\n * Forum URLs are compared after normalization (`https://f.example/` equals\n * `https://F.example`); options passed after the first call are ignored.\n */\n acquire(options: CreateClientOptions): CommentsClient;\n /** The shared client for `forum`, if one has been created. */\n get(forum: string): CommentsClient | undefined;\n /** Disposes and forgets the client for `forum`, or every client when omitted. */\n clear(forum?: string): void;\n}\n\nexport function createClientRegistry(\n create: (options: CreateClientOptions) => CommentsClient = createClient,\n): ClientRegistry {\n const clients = new Map<string, CommentsClient>();\n\n return {\n acquire(options) {\n const key = normalizeForum(options.forum).base;\n let client = clients.get(key);\n if (!client) {\n client = create(options);\n clients.set(key, client);\n }\n return client;\n },\n get(forum) {\n return clients.get(normalizeForum(forum).base);\n },\n clear(forum) {\n const keys = forum === undefined ? [...clients.keys()] : [normalizeForum(forum).base];\n for (const key of keys) {\n clients.get(key)?.dispose();\n clients.delete(key);\n }\n },\n };\n}\n\n/** The page-wide registry used by the React components. */\nexport const clientRegistry: ClientRegistry = createClientRegistry();\n","// UI strings for the React and custom-element layers. The core has no UI;\n// these live here so every layer shares one table and one translator.\n\nexport interface PluralMessage {\n /** Used for a count of exactly 0 when present. */\n zero?: string;\n one: string;\n two?: string;\n few?: string;\n many?: string;\n other: string;\n}\n\nexport type MessageValue = string | PluralMessage;\n\nexport const en = {\n signIn: \"Sign in\",\n signInWith: \"Continue with {provider}\",\n signOut: \"Sign out\",\n signingIn: \"Finish signing in in the window that opened.\",\n signInCancel: \"Cancel\",\n sessionExpired: \"Your session expired. Sign in again to comment.\",\n joinConversation: \"Join the conversation\",\n joinConversationBody: \"Sign in with your {forum} account to comment.\",\n composerPlaceholder: \"Add a comment…\",\n post: \"Post\",\n posting: \"Posting…\",\n reply: \"Reply\",\n replyingTo: \"Replying to @{username}\",\n cancel: \"Cancel\",\n save: \"Save\",\n edit: \"Edit\",\n edited: \"Edited\",\n delete: \"Delete\",\n deleteConfirm: \"Delete this comment?\",\n deleted: \"This comment was deleted.\",\n hidden: \"This comment was hidden after reports from the community.\",\n like: \"Like\",\n unlike: \"Remove like\",\n likeCount: { zero: \"No likes\", one: \"{count} like\", other: \"{count} likes\" },\n report: \"Report\",\n reportTitle: \"Why are you reporting this comment?\",\n \"report.off_topic\": \"Off-topic\",\n \"report.inappropriate\": \"Inappropriate\",\n \"report.spam\": \"Spam\",\n \"report.illegal\": \"Illegal\",\n \"report.notify_moderators\": \"Something else\",\n reportMessagePlaceholder: \"Tell the moderators more (optional)\",\n reportSent: \"Thanks, the moderators will take a look.\",\n pin: \"Feature\",\n unpin: \"Unfeature\",\n pinned: \"Featured\",\n pending: \"Your comment was submitted and is awaiting approval.\",\n loadMore: \"Load more comments\",\n loadReplies: { one: \"View {count} reply\", other: \"View {count} replies\" },\n continueThread: \"Continue this thread\",\n newComments: { one: \"{count} new comment\", other: \"{count} new comments\" },\n commentCount: { zero: \"No comments yet\", one: \"{count} comment\", other: \"{count} comments\" },\n sortBy: \"Sort by\",\n \"sort.best\": \"Best\",\n \"sort.hot\": \"Hot\",\n \"sort.newest\": \"Newest\",\n \"sort.oldest\": \"Oldest\",\n closed: \"Comments are closed.\",\n readOnly: \"Comments are read-only right now.\",\n guidelines: \"Community guidelines\",\n preview: \"Preview\",\n write: \"Write\",\n unavailable: \"Comments are unavailable right now.\",\n retry: \"Try again\",\n rateLimited: {\n one: \"You're doing that too often. Try again in {count} second.\",\n other: \"You're doing that too often. Try again in {count} seconds.\",\n },\n genericError: \"Something went wrong. Please try again.\",\n copyLink: \"Copy link\",\n linkCopied: \"Link copied\",\n viewOnForum: \"View on {forum}\",\n staff: \"Staff\",\n upload: \"Attach image\",\n uploading: \"Uploading…\",\n comments: \"Comments\",\n signedInAs: \"Signed in as {username}\",\n loadMoreReplies: { one: \"View {count} more reply\", other: \"View {count} more replies\" },\n backToAll: \"Back to all comments\",\n ancestorsTruncated: \"Some earlier replies are not shown.\",\n moreActions: \"More actions\",\n commentBy: \"Comment by {name}\",\n deletedComment: \"Deleted comment\",\n repliesTo: \"Replies to {name}\",\n replyPlaceholder: \"Write a reply…\",\n editing: \"Editing your comment\",\n tooShort: \"Comments need at least {min} characters.\",\n tooLong: \"Comments can have at most {max} characters.\",\n formatting: \"Formatting\",\n bold: \"Bold\",\n italic: \"Italic\",\n insertLink: \"Insert link\",\n code: \"Code\",\n quote: \"Quote\",\n mentionSuggestions: \"Mention suggestions\",\n previewEmpty: \"Nothing to preview yet.\",\n loading: \"Loading…\",\n cannotComment: \"You can't comment on this page.\",\n reportMessageRequired: \"Tell the moderators what's wrong\",\n close: \"Close\",\n} as const satisfies Record<string, MessageValue>;\n\nexport type MessageKey = keyof typeof en;\n\n/** A full table: plural entries stay plural in every locale. */\nexport type Messages = {\n [K in MessageKey]: (typeof en)[K] extends string ? string : PluralMessage;\n};\n\nexport const ptBR: Messages = {\n signIn: \"Entrar\",\n signInWith: \"Continuar com {provider}\",\n signOut: \"Sair\",\n signingIn: \"Conclua o login na janela que foi aberta.\",\n signInCancel: \"Cancelar\",\n sessionExpired: \"Sua sessão expirou. Entre novamente para comentar.\",\n joinConversation: \"Participe da conversa\",\n joinConversationBody: \"Entre com sua conta de {forum} para comentar.\",\n composerPlaceholder: \"Escreva um comentário…\",\n post: \"Publicar\",\n posting: \"Publicando…\",\n reply: \"Responder\",\n replyingTo: \"Respondendo a @{username}\",\n cancel: \"Cancelar\",\n save: \"Salvar\",\n edit: \"Editar\",\n edited: \"Editado\",\n delete: \"Excluir\",\n deleteConfirm: \"Excluir este comentário?\",\n deleted: \"Este comentário foi excluído.\",\n hidden: \"Este comentário foi ocultado após denúncias da comunidade.\",\n like: \"Curtir\",\n unlike: \"Descurtir\",\n likeCount: { zero: \"Nenhuma curtida\", one: \"{count} curtida\", other: \"{count} curtidas\" },\n report: \"Denunciar\",\n reportTitle: \"Por que você está denunciando este comentário?\",\n \"report.off_topic\": \"Fora do assunto\",\n \"report.inappropriate\": \"Inapropriado\",\n \"report.spam\": \"Spam\",\n \"report.illegal\": \"Ilegal\",\n \"report.notify_moderators\": \"Outro motivo\",\n reportMessagePlaceholder: \"Conte mais aos moderadores (opcional)\",\n reportSent: \"Obrigado, os moderadores vão analisar.\",\n pin: \"Destacar\",\n unpin: \"Remover destaque\",\n pinned: \"Em destaque\",\n pending: \"Seu comentário foi enviado e aguarda aprovação.\",\n loadMore: \"Carregar mais comentários\",\n loadReplies: { one: \"Ver {count} resposta\", other: \"Ver {count} respostas\" },\n continueThread: \"Continuar esta conversa\",\n newComments: { one: \"{count} novo comentário\", other: \"{count} novos comentários\" },\n commentCount: {\n zero: \"Nenhum comentário ainda\",\n one: \"{count} comentário\",\n other: \"{count} comentários\",\n },\n sortBy: \"Ordenar por\",\n \"sort.best\": \"Melhores\",\n \"sort.hot\": \"Em alta\",\n \"sort.newest\": \"Mais recentes\",\n \"sort.oldest\": \"Mais antigos\",\n closed: \"Os comentários estão encerrados.\",\n readOnly: \"Os comentários estão somente leitura no momento.\",\n guidelines: \"Diretrizes da comunidade\",\n preview: \"Pré-visualizar\",\n write: \"Escrever\",\n unavailable: \"Os comentários estão indisponíveis no momento.\",\n retry: \"Tentar novamente\",\n rateLimited: {\n one: \"Você está fazendo isso com muita frequência. Tente novamente em {count} segundo.\",\n other: \"Você está fazendo isso com muita frequência. Tente novamente em {count} segundos.\",\n },\n genericError: \"Algo deu errado. Tente novamente.\",\n copyLink: \"Copiar link\",\n linkCopied: \"Link copiado\",\n viewOnForum: \"Ver em {forum}\",\n staff: \"Equipe\",\n upload: \"Anexar imagem\",\n uploading: \"Enviando…\",\n comments: \"Comentários\",\n signedInAs: \"Conectado como {username}\",\n loadMoreReplies: { one: \"Ver mais {count} resposta\", other: \"Ver mais {count} respostas\" },\n backToAll: \"Voltar para todos os comentários\",\n ancestorsTruncated: \"Algumas respostas anteriores não são exibidas.\",\n moreActions: \"Mais ações\",\n commentBy: \"Comentário de {name}\",\n deletedComment: \"Comentário excluído\",\n repliesTo: \"Respostas a {name}\",\n replyPlaceholder: \"Escreva uma resposta…\",\n editing: \"Editando seu comentário\",\n tooShort: \"Comentários precisam ter pelo menos {min} caracteres.\",\n tooLong: \"Comentários podem ter no máximo {max} caracteres.\",\n formatting: \"Formatação\",\n bold: \"Negrito\",\n italic: \"Itálico\",\n insertLink: \"Inserir link\",\n code: \"Código\",\n quote: \"Citação\",\n mentionSuggestions: \"Sugestões de menção\",\n previewEmpty: \"Nada para pré-visualizar ainda.\",\n loading: \"Carregando…\",\n cannotComment: \"Você não pode comentar nesta página.\",\n reportMessageRequired: \"Conte aos moderadores o que há de errado\",\n close: \"Fechar\",\n};\n\nexport const locales = { en: en as Messages, \"pt-BR\": ptBR } as const;\n\nexport type SupportedLocale = keyof typeof locales;\n\nexport type MessageVars = Record<string, string | number>;\n\nexport type Translator = (key: MessageKey, vars?: MessageVars) => string;\n\n/** Closest bundled locale: any `pt*` maps to `pt-BR`, everything else to `en`. */\nexport function resolveLocale(locale: string | undefined): SupportedLocale {\n return locale?.toLowerCase().startsWith(\"pt\") ? \"pt-BR\" : \"en\";\n}\n\nexport function createTranslator(\n locale?: string,\n overrides: Partial<Messages> = {},\n): Translator {\n const resolved = resolveLocale(locale);\n const table: Messages = { ...locales[resolved], ...overrides };\n const rules = new Intl.PluralRules(resolved);\n\n return (key, vars) => {\n const value: MessageValue = table[key];\n let template: string;\n if (typeof value === \"string\") {\n template = value;\n } else {\n const count = Number(vars?.count ?? 0);\n const category = rules.select(count) as keyof PluralMessage;\n template = (count === 0 ? value.zero : undefined) ?? value[category] ?? value.other;\n }\n return template.replace(/\\{(\\w+)\\}/g, (match, name: string) =>\n vars && name in vars ? String(vars[name]) : match,\n );\n };\n}\n"]}