@event-timeline/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/layout/byFirstEvent.ts","../src/layout/stableAppend.ts","../src/cluster/strategies.ts","../src/layout/positions.ts","../src/model/diagnostics.ts","../src/model/extent.ts","../src/model/temporalIndex.ts","../src/model/store.ts","../src/cluster/cluster.ts","../src/render/batch.ts","../src/render/riser.ts","../src/render/arrows.ts","../src/render/canvas2d.ts","../src/render/device.ts","../src/render/elementLines.ts","../src/render/iconCache.ts","../src/render/rowBand.ts","../src/render/snap.ts","../src/scale/camera.ts","../src/scale/ticks.ts","../src/render/resolveStyle.ts","../src/interaction/wheel.ts","../src/interaction/pointer.ts","../src/interaction/hitGrid.ts","../src/interaction/geometry.ts","../src/interaction/hitTest.ts","../src/interaction/selection.ts","../src/engine/debounce.ts","../src/engine/emitter.ts","../src/engine/scheduler.ts","../src/engine/theme.ts","../src/engine/timeline.ts","../src/layout/barycenter.ts","../src/layout/explicit.ts","../src/index.ts"],"names":["year","t","pad","distSq","tol","hitId","MS_PER_DAY","key"],"mappings":";;;AAOO,IAAM,YAAA,GAA+B;AAAA,EAC1C,KAAA,CAAM,UAAU,MAAA,EAAkB;AAChC,IAAA,MAAM,cAAA,uBAAqB,GAAA,EAAoB;AAC/C,IAAA,MAAM,IAAA,GAAO,CAAC,EAAA,EAAY,IAAA,KAAiB;AACzC,MAAA,MAAM,OAAA,GAAU,cAAA,CAAe,GAAA,CAAI,EAAE,CAAA;AACrC,MAAA,IAAI,OAAA,KAAY,MAAA,IAAa,IAAA,GAAO,OAAA,EAAS;AAC3C,QAAA,cAAA,CAAe,GAAA,CAAI,IAAI,IAAI,CAAA;AAAA,MAC7B;AAAA,IACF,CAAA;AACA,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAE1B,MAAA,IAAA,CAAK,KAAA,CAAM,QAAA,EAAU,KAAA,CAAM,IAAI,CAAA;AAC/B,MAAA,IAAI,KAAA,CAAM,aAAa,KAAA,CAAM,QAAA,OAAe,KAAA,CAAM,QAAA,EAAU,MAAM,IAAI,CAAA;AAAA,IACxE;AAIA,IAAA,OAAO,QAAA,CACJ,GAAA,CAAI,CAAC,OAAA,EAAS,KAAA,MAAW;AAAA,MACxB,IAAI,OAAA,CAAQ,EAAA;AAAA,MACZ,KAAA;AAAA,MACA,GAAA,EAAK,cAAA,CAAe,GAAA,CAAI,OAAA,CAAQ,EAAE;AAAA,KACpC,CAAE,CAAA,CACD,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM;AACd,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,MAAA,IAAa,CAAA,CAAE,QAAQ,MAAA,EAAW;AAC9C,QAAA,OAAO,CAAA,CAAE,GAAA,KAAQ,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,MAAM,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,KAAA;AAAA,MACvD;AACA,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,MAAA,EAAW,OAAO,EAAA;AAChC,MAAA,IAAI,CAAA,CAAE,GAAA,KAAQ,MAAA,EAAW,OAAO,CAAA;AAChC,MAAA,OAAO,CAAA,CAAE,QAAQ,CAAA,CAAE,KAAA;AAAA,IACrB,CAAC,CAAA,CACA,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,EAAE,CAAA;AAAA,EAC5B;AACF;;;ACxBO,SAAS,YAAA,CACd,YACA,QAAA,EACU;AACV,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,QAAA,CAAS,IAAI,CAAC,OAAA,KAAY,OAAA,CAAQ,EAAE,CAAC,CAAA;AAC7D,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAY;AAC/B,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,MAAM,UAAA,EAAY;AAC3B,IAAA,IAAI,OAAA,CAAQ,IAAI,EAAE,CAAA,IAAK,CAAC,MAAA,CAAO,GAAA,CAAI,EAAE,CAAA,EAAG;AACtC,MAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,MAAA,MAAA,CAAO,IAAI,EAAE,CAAA;AAAA,IACf;AAAA,EACF;AACA,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,IAAI,CAAC,MAAA,CAAO,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AAC3B,MAAA,KAAA,CAAM,IAAA,CAAK,QAAQ,EAAE,CAAA;AACrB,MAAA,MAAA,CAAO,GAAA,CAAI,QAAQ,EAAE,CAAA;AAAA,IACvB;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;;;ACxBA,IAAM,GAAA,GAAM,IAAA;AACZ,IAAM,UAAA,GAAa,KAAA;AAGnB,SAAS,WAAA,CAAY,OAAsB,GAAA,EAA6B;AACtE,EAAA,OAAO,IAAA,CAAK,MAAM,GAAA,CAAI,aAAA,CAAc,MAAM,IAAI,CAAA,GAAI,IAAI,eAAe,CAAA;AACvE;AAGA,SAAS,eAAe,KAAA,EAA8B;AACpD,EAAA,OAAO,GAAG,KAAA,CAAM,QAAQ,GAAG,GAAG,CAAA,EAAG,MAAM,QAAQ,CAAA,CAAA;AACjD;AAGO,IAAM,aAAA,GAAiC;AAAA,EAC5C,GAAA,EAAK,CAAC,KAAA,EAAO,GAAA,KAAQ,OAAO,WAAA,CAAY,KAAA,EAAO,GAAG,CAAC;AACrD;AAGO,IAAM,aAAA,GAAiC;AAAA,EAC5C,GAAA,EAAK,CAAC,KAAA,KAAU,cAAA,CAAe,KAAK;AACtC;AAGO,IAAM,KAAA,GAAyB;AAAA,EACpC,GAAA,EAAK,CAAC,KAAA,KAAU,MAAA,CAAO,KAAK,KAAA,CAAM,KAAA,CAAM,IAAA,GAAO,UAAU,CAAC;AAC5D;AAMO,IAAM,oBAAA,GAAwC;AAAA,EACnD,GAAA,EAAK,CAAC,KAAA,EAAO,GAAA,KACX,GAAG,cAAA,CAAe,KAAK,CAAC,CAAA,EAAG,GAAG,CAAA,EAAG,WAAA,CAAY,KAAA,EAAO,GAAG,CAAC,CAAA;AAC5D;;;AC/BO,SAAS,gBAAA,CACd,YACA,OAAA,EACW;AACX,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAAoB;AAC7C,EAAA,UAAA,CAAW,OAAA,CAAQ,CAAC,EAAA,EAAI,KAAA,KAAU,aAAa,GAAA,CAAI,EAAA,EAAI,KAAK,CAAC,CAAA;AAC7D,EAAA,MAAM,WAAW,UAAA,CAAW,MAAA;AAC5B,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,YAAA;AAAA,IACA,QAAA;AAAA,IACA,aAAA,EAAe,QAAA,IAAY,OAAA,CAAQ,SAAA,GAAY,OAAA,CAAQ,MAAA;AAAA,GACzD;AACF;;;ACLO,SAAS,2BAAA,GAA4C;AAG1D,EAAA,MAAM,GAAA,GACJ,WACA,OAAA,EAAS,GAAA;AACX,EAAA,IAAI,GAAA,EAAK,aAAa,YAAA,EAAc;AAClC,IAAA,OAAO,MAAM;AAAA,IAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,CAAC,CAAA,KAAM;AACZ,IAAA,MAAM,KAAK,CAAA,CAAE,EAAA,KAAO,SAAY,CAAA,EAAA,EAAK,CAAA,CAAE,EAAE,CAAA,CAAA,CAAA,GAAM,EAAA;AAC/C,IAAA,OAAA,CAAQ,IAAA,CAAK,sBAAsB,CAAA,CAAE,IAAI,GAAG,EAAE,CAAA,EAAA,EAAK,CAAA,CAAE,MAAM,CAAA,CAAE,CAAA;AAAA,EAC/D,CAAA;AACF;;;ACtBO,SAAS,WAAA,CAAY,SAA6B,CAAA,EAAiB;AACxE,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,OAAO,EAAE,OAAA,EAAS,CAAA,EAAG,OAAA,EAAS,CAAA,EAAE;AAAA,EAClC;AACA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,CAAA,GAAI,OAAA,CAAQ,OAAA,GAAU,IAAI,OAAA,CAAQ,OAAA;AAAA,IAC3C,OAAA,EAAS,CAAA,GAAI,OAAA,CAAQ,OAAA,GAAU,IAAI,OAAA,CAAQ;AAAA,GAC7C;AACF;AAMO,SAAS,WACd,OAAA,EACe;AACf,EAAA,IAAI,MAAA,GAAwB,IAAA;AAC5B,EAAA,KAAA,MAAW,MAAA,IAAU,OAAA,CAAQ,MAAA,EAAO,EAAG;AACrC,IAAA,MAAA,GACE,MAAA,KAAW,OACP,EAAE,OAAA,EAAS,OAAO,OAAA,EAAS,OAAA,EAAS,MAAA,CAAO,OAAA,EAAQ,GACnD;AAAA,MACE,SAAS,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,OAAO,OAAO,CAAA;AAAA,MAChD,SAAS,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,OAAO,OAAO;AAAA,KAClD;AAAA,EACR;AACA,EAAA,OAAO,MAAA;AACT;;;AC1BO,SAAS,UAAA,CAAW,QAA0B,CAAA,EAAiB;AACpE,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,KAAK,MAAA,CAAO,MAAA;AAChB,EAAA,OAAO,KAAK,EAAA,EAAI;AACd,IAAA,MAAM,GAAA,GAAO,KAAK,EAAA,KAAQ,CAAA;AAC1B,IAAA,IAAK,OAAO,GAAG,CAAA,CAAY,IAAA,GAAO,CAAA,OAAQ,GAAA,GAAM,CAAA;AAAA,SAC3C,EAAA,GAAK,GAAA;AAAA,EACZ;AACA,EAAA,OAAO,EAAA;AACT;AAMO,SAAS,UAAA,CAAW,QAA0B,CAAA,EAAiB;AACpE,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,KAAK,MAAA,CAAO,MAAA;AAChB,EAAA,OAAO,KAAK,EAAA,EAAI;AACd,IAAA,MAAM,GAAA,GAAO,KAAK,EAAA,KAAQ,CAAA;AAC1B,IAAA,IAAK,OAAO,GAAG,CAAA,CAAY,IAAA,IAAQ,CAAA,OAAQ,GAAA,GAAM,CAAA;AAAA,SAC5C,EAAA,GAAK,GAAA;AAAA,EACZ;AACA,EAAA,OAAO,EAAA;AACT;AAOO,SAAS,aACd,MAAA,EACuB;AACvB,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAsB;AAC1C,EAAA,MAAM,GAAA,GAAM,CAAC,EAAA,EAAY,KAAA,KAAkB;AACzC,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA;AAC7B,IAAA,IAAI,WAAW,MAAA,EAAW,OAAA,CAAQ,IAAI,EAAA,EAAI,CAAC,KAAK,CAAC,CAAA;AAAA,SAC5C,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,EACxB,CAAA;AACA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,IAAA,MAAM,KAAA,GAAQ,OAAO,CAAC,CAAA;AACtB,IAAA,GAAA,CAAI,KAAA,CAAM,UAAU,CAAC,CAAA;AACrB,IAAA,IAAI,MAAM,QAAA,KAAa,KAAA,CAAM,UAAU,GAAA,CAAI,KAAA,CAAM,UAAU,CAAC,CAAA;AAAA,EAC9D;AACA,EAAA,OAAO,OAAA;AACT;;;ACnCO,IAAM,YAAN,MAAiC;AAAA,EACrB,YAAA;AAAA,EAET,WAAqC,EAAC;AAAA,EACtC,WAAA,uBAAkB,GAAA,EAAoC;AAAA;AAAA,EAEtD,SAAiC,EAAC;AAAA,EAClC,SAAA,uBAAgB,GAAA,EAAkC;AAAA,EAClD,OAAA,uBAAc,GAAA,EAAoB;AAAA;AAAA,EAElC,qBAAA,uBAA4B,GAAA,EAAsB;AAAA;AAAA,EAElD,GAAA,uBAAU,GAAA,EAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5C,UAAA,GAAa,CAAA;AAAA,EAErB,WAAA,CAAY,OAAA,GAA4B,EAAC,EAAG;AAC1C,IAAA,IAAA,CAAK,YAAA,GAAe,OAAA,CAAQ,YAAA,IAAgB,2BAAA,EAA4B;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,IAAA,EAA6C;AACnD,IAAA,IAAA,CAAK,KAAA,EAAM;AACX,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,OAAA,IAAW,KAAK,QAAA,EAAU;AACnC,MAAA,IAAI,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA,EAAG,KAAA,EAAA;AAAA,IACnC;AACA,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,MAAA,EAAQ;AAC/B,MAAA,IAAI,IAAA,CAAK,WAAA,CAAY,KAAK,CAAA,EAAG,KAAA,EAAA;AAAA,IAC/B;AACA,IAAA,IAAA,CAAK,OAAA,EAAQ;AACb,IAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,EAAE;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,MAAA,EAA2D;AACnE,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,IAAI,IAAA,CAAK,WAAA,CAAY,KAAK,CAAA,EAAG,KAAA,EAAA;AAAA,IAC/B;AACA,IAAA,IAAI,KAAA,GAAQ,CAAA,EAAG,IAAA,CAAK,OAAA,EAAQ;AAC5B,IAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,EAAE;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,QAAA,EAA+D;AACzE,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,MAAA,IAAI,IAAA,CAAK,aAAA,CAAc,OAAO,CAAA,EAAG,KAAA,EAAA;AAAA,IACnC;AACA,IAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,EAAE;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,GAAA,EAA0C;AACrD,IAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AACjC,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,KAAA,MAAW,MAAM,GAAA,EAAK;AACpB,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,EAAE,CAAA;AACnC,MAAA,IAAI,UAAU,MAAA,EAAW;AACzB,MAAA,IAAA,CAAK,SAAA,CAAU,OAAO,EAAE,CAAA;AACxB,MAAA,IAAA,CAAK,GAAA,CAAI,OAAO,KAAK,CAAA;AACrB,MAAA,QAAA,CAAS,GAAA,CAAI,MAAM,QAAQ,CAAA;AAC3B,MAAA,QAAA,CAAS,GAAA,CAAI,MAAM,QAAQ,CAAA;AAC3B,MAAA,OAAA,EAAA;AAAA,IACF;AACA,IAAA,IAAI,OAAA,KAAY,GAAG,OAAO,EAAE,OAAO,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,OAAA,EAAS,CAAA,EAAE;AAE7D,IAAA,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAA;AAChE,IAAA,IAAA,CAAK,OAAA,EAAQ;AACb,IAAA,KAAA,MAAW,EAAA,IAAM,QAAA,EAAU,IAAA,CAAK,kBAAA,CAAmB,EAAE,CAAA;AACrD,IAAA,OAAO,EAAE,KAAA,EAAO,CAAA,EAAG,OAAA,EAAS,SAAS,CAAA,EAAE;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAA,CACE,IACA,KAAA,EACkB;AAClB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,EAAE,CAAA;AACxC,IAAA,IAAI,QAAA,KAAa,QAAW,OAAO,EAAE,OAAO,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,OAAA,EAAS,CAAA,EAAE;AACtE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA;AAG3C,IAAA,IAAI,IAAA,KAAS,IAAI,OAAO,EAAE,OAAO,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,OAAA,EAAS,CAAA,EAAE;AAC3D,IAAA,MAAM,UAAkC,EAAE,GAAG,QAAA,EAAU,GAAG,OAAO,EAAA,EAAG;AACpE,IAAA,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,GAAI,OAAA;AACtB,IAAA,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,EAAA,EAAI,OAAO,CAAA;AAChC,IAAA,OAAO,EAAE,KAAA,EAAO,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,EAAE;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,EAAA,EAAkB;AAC3C,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,qBAAA,CAAsB,GAAA,CAAI,EAAE,CAAA;AACjD,IAAA,IAAI,OAAA,KAAY,MAAA,IAAa,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG;AACjD,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,EAAE,CAAA;AACtB,MAAA;AAAA,IACF;AACA,IAAA,IAAI,MAAA;AACJ,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,KAAK,CAAA;AAC/B,MAAA,MAAA,GAAS,WAAA,CAAY,MAAA,EAAQ,KAAA,CAAM,IAAI,CAAA;AAAA,IACzC;AACA,IAAA,IAAI,WAAW,MAAA,EAAW,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,IAAI,MAAM,CAAA;AAAA,EACvD;AAAA,EAEQ,KAAA,GAAc;AACpB,IAAA,IAAA,CAAK,WAAW,EAAC;AACjB,IAAA,IAAA,CAAK,YAAY,KAAA,EAAM;AACvB,IAAA,IAAA,CAAK,SAAS,EAAC;AACf,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AACrB,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AACnB,IAAA,IAAA,CAAK,sBAAsB,KAAA,EAAM;AACjC,IAAA,IAAA,CAAK,IAAI,KAAA,EAAM;AACf,IAAA,IAAA,CAAK,UAAA,GAAa,CAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,OAAA,GAAgB;AACtB,IAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM;AACzB,MAAA,IAAI,EAAE,IAAA,KAAS,CAAA,CAAE,MAAM,OAAO,CAAA,CAAE,OAAO,CAAA,CAAE,IAAA;AACzC,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,IAAK,MAAM,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,CAAC,CAAA,IAAK,CAAA,CAAA;AAAA,IACtD,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,qBAAA,GAAwB,YAAA,CAAa,IAAA,CAAK,MAAM,CAAA;AAAA,EACvD;AAAA,EAEQ,cAAc,OAAA,EAA0C;AAC9D,IAAA,IAAI,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AACpC,MAAA,IAAA,CAAK,YAAA,CAAa;AAAA,QAChB,IAAA,EAAM,cAAA;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,MAAA,EAAQ;AAAA,OACT,CAAA;AACD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAA,CAAK,QAAA,CAAS,KAAK,OAAO,CAAA;AAC1B,IAAA,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,OAAA,CAAQ,EAAA,EAAI,OAAO,CAAA;AACxC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEQ,YAAY,KAAA,EAAsC;AACxD,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA,EAAG;AAChC,MAAA,IAAA,CAAK,YAAA,CAAa;AAAA,QAChB,IAAA,EAAM,cAAA;AAAA,QACN,IAAA,EAAM,OAAA;AAAA,QACN,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACT,CAAA;AACD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,EAAG;AAChC,MAAA,IAAA,CAAK,YAAA,CAAa;AAAA,QAChB,IAAA,EAAM,cAAA;AAAA,QACN,IAAA,EAAM,OAAA;AAAA,QACN,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACT,CAAA;AACD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IACE,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,QAAQ,CAAA,IACpC,CAAC,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,KAAA,CAAM,QAAQ,CAAA,EACpC;AACA,MAAA,IAAA,CAAK,YAAA,CAAa;AAAA,QAChB,IAAA,EAAM,eAAA;AAAA,QACN,IAAA,EAAM,OAAA;AAAA,QACN,IAAI,KAAA,CAAM,EAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACT,CAAA;AACD,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,KAAA,EAAO,IAAA,CAAK,UAAA,EAAY,CAAA;AACrC,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,KAAK,CAAA;AACtB,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,KAAA,CAAM,EAAA,EAAI,KAAK,CAAA;AAGlC,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA;AAAA,MACX,KAAA,CAAM,QAAA;AAAA,MACN,WAAA,CAAY,KAAK,OAAA,CAAQ,GAAA,CAAI,MAAM,QAAQ,CAAA,EAAG,MAAM,IAAI;AAAA,KAC1D;AACA,IAAA,IAAI,KAAA,CAAM,QAAA,KAAa,KAAA,CAAM,QAAA,EAAU;AACrC,MAAA,IAAA,CAAK,OAAA,CAAQ,GAAA;AAAA,QACX,KAAA,CAAM,QAAA;AAAA,QACN,WAAA,CAAY,KAAK,OAAA,CAAQ,GAAA,CAAI,MAAM,QAAQ,CAAA,EAAG,MAAM,IAAI;AAAA,OAC1D;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,WAAA,GAAiD;AAC/C,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEA,SAAA,GAA6C;AAC3C,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAA,CAAiB,QAAc,IAAA,EAA6C;AAC1E,IAAA,IAAI,IAAA,GAAO,MAAA,EAAQ,OAAO,EAAC;AAC3B,IAAA,MAAM,EAAA,GAAK,UAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,MAAM,CAAA;AACzC,IAAA,MAAM,EAAA,GAAK,UAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,IAAI,CAAA;AACvC,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,0BAA0B,EAAA,EAA+B;AACvD,IAAA,OAAO,IAAA,CAAK,qBAAA,CAAsB,GAAA,CAAI,EAAE,KAAK,EAAC;AAAA,EAChD;AAAA,EAEA,eAAe,EAAA,EAAgD;AAC7D,IAAA,OAAO,IAAA,CAAK,WAAA,CAAY,GAAA,CAAI,EAAE,CAAA;AAAA,EAChC;AAAA,EAEA,UAAU,EAAA,EAAgC;AACxC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA;AAAA,EAC5B;AAAA,EAEA,UAAA,GAA0C;AACxC,IAAA,OAAO,IAAA,CAAK,OAAA;AAAA,EACd;AAAA;AAAA,EAGA,aAAA,GAA+B;AAC7B,IAAA,OAAO,UAAA,CAAW,KAAK,OAAO,CAAA;AAAA,EAChC;AACF,CAAA;;;AC5RO,SAAS,aAAA,CACd,MAAA,EACA,QAAA,EACA,GAAA,EACkB;AAElB,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoC;AACvD,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,GAAA,GAAM,QAAA,CAAS,GAAA,CAAI,KAAA,EAAO,GAAG,CAAA;AACnC,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAC5B,IAAA,IAAI,UAAU,MAAA,EAAW,MAAA,CAAO,IAAI,GAAA,EAAK,CAAC,KAAK,CAAC,CAAA;AAAA,SAC3C,KAAA,CAAM,KAAK,KAAK,CAAA;AAAA,EACvB;AAEA,EAAA,MAAM,WAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,EAAO,EAAG;AAGnC,IAAA,IAAI,MAA8B,EAAC;AACnC,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,KAAA,MAAW,SAAS,KAAA,EAAO;AACzB,MAAA,MAAM,CAAA,GAAI,GAAA,CAAI,aAAA,CAAc,KAAA,CAAM,IAAI,CAAA;AACtC,MAAA,IAAI,IAAI,MAAA,KAAW,CAAA,IAAK,CAAA,GAAI,KAAA,IAAS,IAAI,eAAA,EAAiB;AACxD,QAAA,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,MAChB,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,IAAA,CAAK,EAAE,MAAA,EAAQ,GAAA,EAAK,CAAA;AAC7B,QAAA,GAAA,GAAM,CAAC,KAAK,CAAA;AAAA,MACd;AACA,MAAA,KAAA,GAAQ,CAAA;AAAA,IACV;AACA,IAAA,IAAI,GAAA,CAAI,SAAS,CAAA,EAAG,QAAA,CAAS,KAAK,EAAE,MAAA,EAAQ,KAAK,CAAA;AAAA,EACnD;AACA,EAAA,OAAO,QAAA;AACT;;;AC1CO,SAAS,SAAA,CACd,GAAA,EACA,KAAA,EACA,KAAA,EACU;AACV,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA;AAC7B,EAAA,IAAI,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACvB,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,KAAA,GAAQ,EAAE,KAAA,EAAO,KAAA,EAAO,QAAA,EAAU,EAAC,EAAE;AACrC,IAAA,GAAA,CAAI,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EACpB;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,SAAA,CACd,GAAA,EACA,KAAA,EACA,MAAA,EACU;AACV,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AAC9B,EAAA,IAAI,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACvB,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,KAAA,GAAQ,EAAE,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,EAAC,EAAE;AACnC,IAAA,GAAA,CAAI,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EACpB;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,cAAA,CACd,GAAA,EACA,KAAA,EACA,IAAA,EACe;AACf,EAAA,MAAM,GAAA,GAAM,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAC5B,EAAA,IAAI,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACvB,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,KAAA,GAAQ,EAAE,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,EAAC,EAAE;AACjC,IAAA,GAAA,CAAI,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EACpB;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,WACd,GAAA,EACA,KAAA,EACA,MACA,KAAA,GAA4B,MAAA,EAC5B,WAAkC,QAAA,EACvB;AAGX,EAAA,MAAM,GAAA,GAAM,GAAG,KAAK,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,KAAK,IAAI,QAAQ,CAAA,CAAA;AACjD,EAAA,IAAI,KAAA,GAAQ,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA;AACvB,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,KAAA,GAAQ,EAAE,KAAA,EAAO,IAAA,EAAM,UAAU,KAAA,EAAO,KAAA,EAAO,EAAC,EAAE;AAClD,IAAA,GAAA,CAAI,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EACpB;AACA,EAAA,OAAO,KAAA;AACT;;;AClDA,IAAM,aAAA,GAAgB,CAAA;AAQf,SAAS,kBAAA,CACd,CAAA,EACA,KAAA,EACA,GAAA,EACA,WACA,SAAA,EACe;AACf,EAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,IAAK,SAAA,IAAa,CAAA,EAAG;AAC5C,IAAA,OAAO,CAAC,EAAE,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,OAAO,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,GAAA,EAAK,CAAA;AAAA,EAC9C;AAEA,EAAA,MAAM,GAAA,GAAM,GAAA,IAAO,KAAA,GAAQ,CAAA,GAAI,EAAA;AAE/B,EAAA,MAAM,OAAA,GAAU,CAAC,GAAG,SAAS,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,GAAA,IAAO,CAAA,GAAI,CAAA,CAAE,CAAA;AAE3D,EAAA,MAAM,SAAqC,CAAC,EAAE,CAAA,EAAG,CAAA,EAAG,OAAO,CAAA;AAC3D,EAAA,KAAA,MAAW,MAAM,OAAA,EAAS;AACxB,IAAA,MAAM,MAAA,GAAS,KAAK,GAAA,GAAM,SAAA;AAC1B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,GAAM,SAAA;AACzB,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,QAAQ,CAAA;AAE5B,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,aAAA,EAAe,CAAA,EAAA,EAAK;AACtC,MAAA,MAAM,KAAA,GAAS,IAAA,CAAK,EAAA,GAAK,CAAA,GAAK,aAAA;AAC9B,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,CAAA,EAAG,CAAA,GAAI,SAAA,GAAY,IAAA,CAAK,IAAI,KAAK,CAAA;AAAA,QACjC,GAAG,EAAA,GAAK,GAAA,GAAM,SAAA,GAAY,IAAA,CAAK,IAAI,KAAK;AAAA,OACzC,CAAA;AAAA,IACH;AACA,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,OAAO,CAAA;AAAA,EAC7B;AACA,EAAA,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,KAAK,CAAA;AAEzB,EAAA,MAAM,WAA0B,EAAC;AACjC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACtC,IAAA,MAAM,CAAA,GAAI,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA;AACtB,IAAA,MAAM,CAAA,GAAI,OAAO,CAAC,CAAA;AAClB,IAAA,IAAI,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,MAAA,EAAW;AACxC,IAAA,QAAA,CAAS,IAAA,CAAK,EAAE,EAAA,EAAI,CAAA,CAAE,GAAG,EAAA,EAAI,CAAA,CAAE,CAAA,EAAG,EAAA,EAAI,CAAA,CAAE,CAAA,EAAG,EAAA,EAAI,CAAA,CAAE,GAAG,CAAA;AAAA,EACtD;AACA,EAAA,OAAO,QAAA;AACT;;;ACjCA,IAAM,gBAAA,GAAmB,CAAA;AAEzB,IAAM,YAAA,GAAe,CAAA;AAErB,IAAM,kBAAA,GAAqB,CAAA;AAE3B,IAAM,oBAAA,GAAuB,EAAA;AAE7B,IAAM,uBAAA,GAA0B,CAAA;AAEhC,IAAM,aAAA,GAAgB,CAAA;AAEtB,IAAM,iBAAA,GAAoB,EAAA;AAE1B,IAAM,UAAA,GAAa,KAAK,EAAA,GAAK,CAAA;AAC7B,IAAM,QAAA,GAAW,CAAC,IAAA,CAAK,EAAA,GAAK,CAAA;AAOrB,SAAS,cAAc,CAAA,EAAmB;AAC/C,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,YAAY,CAAA,GAAI,gBAAA;AACrC;AAuBO,SAAS,YACd,GAAA,EACqB;AACrB,EAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,GAAA,EAAK,YAAW,GAAI,GAAA;AAE9C,EAAA,MAAM,OAAA,GAA0B;AAAA,IAC9B,KAAA,sBAAW,GAAA,EAAI;AAAA,IACf,KAAA,sBAAW,GAAA,EAAI;AAAA,IACf,UAAA,sBAAgB,GAAA,EAAI;AAAA,IACpB,MAAA,sBAAY,GAAA,EAAI;AAAA,IAChB,SAAS,EAAC;AAAA,IACV,YAAA,sBAAkB,GAAA;AAAI,GACxB;AAKA,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,aAAA,CAAc,CAAC,oBAAoB,CAAA;AACzD,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,aAAA,CAAc,QAAA,CAAS,WAAW,oBAAoB,CAAA;AAC1E,EAAA,MAAM,YAAA,GAAe,GAAA,CAAI,IAAA,CAAK,gBAAA,CAAiB,QAAQ,IAAI,CAAA;AAK3D,EAAA,MAAM,UAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,SAAS,YAAA,EAAc;AAChC,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,EAAK,KAAK,CAAA;AAC/B,IAAA,IAAI,SAAS,IAAA,EAAM;AACnB,IAAA,IAAI,IAAA,CAAK,KAAK,GAAA,CAAI,IAAA,CAAK,YAAY,IAAA,CAAK,EAAA,GAAK,GAAA,CAAI,IAAA,CAAK,OAAA,EAAS;AAC/D,IAAA,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,EACpB;AAEA,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,KAAA,CAAM,OAAA,IAAW,GAAA,CAAI,oBAAA;AAE7C,EAAA,IAAI,WAAW,OAAA,EAAS;AACtB,IAAA,MAAM,UAAA,GAA6B;AAAA,MACjC,iBAAiB,UAAA,CAAW,eAAA;AAAA,MAC5B,aAAA,EAAe,CAAC,CAAA,KAAM,MAAA,CAAO,cAAc,CAAC;AAAA,KAC9C;AACA,IAAA,KAAA,MAAW,OAAA,IAAW,aAAA;AAAA,MACpB,OAAA;AAAA,MACA,UAAA,CAAW,QAAA;AAAA,MACX;AAAA,KACF,EAAG;AACD,MAAA,MAAM,CAAC,KAAK,CAAA,GAAI,OAAA,CAAQ,MAAA;AACxB,MAAA,IAAI,OAAA,CAAQ,MAAA,CAAO,MAAA,KAAW,CAAA,IAAK,UAAU,MAAA,EAAW;AACtD,QAAA,cAAA,CAAe,OAAA,EAAS,GAAA,EAAK,KAAA,EAAO,QAAQ,CAAA;AAAA,MAC9C,CAAA,MAAO;AACL,QAAA,UAAA,CAAW,OAAA,EAAS,GAAA,EAAK,OAAA,CAAQ,MAAM,CAAA;AAAA,MACzC;AAAA,IACF;AAAA,EACF,CAAA,MAAO;AACL,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS,cAAA,CAAe,OAAA,EAAS,GAAA,EAAK,OAAO,QAAQ,CAAA;AAAA,EAC3E;AAEA,EAAA,OAAO;AAAA,IACL,OAAO,CAAC,GAAG,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAA;AAAA,IACjC,OAAO,CAAC,GAAG,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAA;AAAA,IACjC,YAAY,CAAC,GAAG,OAAA,CAAQ,UAAA,CAAW,QAAQ,CAAA;AAAA,IAC3C,QAAQ,CAAC,GAAG,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA;AAAA,IACnC,SAAS,OAAA,CAAQ;AAAA,GACnB;AACF;AAGA,SAAS,OAAA,CACP,KACA,KAAA,EACyE;AACzE,EAAA,MAAM,YAAY,GAAA,CAAI,SAAA,CAAU,YAAA,CAAa,GAAA,CAAI,MAAM,QAAQ,CAAA;AAC/D,EAAA,MAAM,YAAY,GAAA,CAAI,SAAA,CAAU,YAAA,CAAa,GAAA,CAAI,MAAM,QAAQ,CAAA;AAC/D,EAAA,IAAI,SAAA,KAAc,MAAA,IAAa,SAAA,KAAc,MAAA,EAAW,OAAO,IAAA;AAC/D,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,SAAS,CAAA;AAAA,IACjC,EAAA,EAAI,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,SAAS,CAAA;AAAA,IACjC,SAAA;AAAA,IACA;AAAA,GACF;AACF;AAGA,SAAS,cAAA,CACP,OAAA,EACA,GAAA,EACA,KAAA,EACA,QAAA,EACM;AACN,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,EAAK,KAAK,CAAA;AAC/B,EAAA,IAAI,SAAS,IAAA,EAAM;AACnB,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,GAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,MAAM,SAAA,GAAY,CAAA;AAElC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,aAAA,CAAc,KAAA,CAAM,IAAI,CAAA;AAC7C,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC/B,EAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA,IAAK,CAAA;AAC9C,EAAA,OAAA,CAAQ,YAAA,CAAa,GAAA,CAAI,MAAA,EAAQ,CAAA,GAAI,CAAC,CAAA;AACtC,EAAA,MAAM,CAAA,GAAI,KAAA,GAAQ,aAAA,CAAc,CAAC,CAAA;AAGjC,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,iBAAA,CAAkB,KAAK,CAAA;AACzC,EAAA,MAAM,QAAQ,KAAA,CAAM,UAAA;AACpB,EAAA,MAAM,QAAQ,KAAA,CAAM,UAAA;AACpB,EAAA,MAAM,OAAO,KAAA,CAAM,aAAA;AACnB,EAAA,MAAM,SAAS,KAAA,CAAM,UAAA;AACrB,EAAA,MAAM,SAAA,GAAY,QAAA,GAAW,GAAA,CAAI,gBAAA,CAAiB,KAAK,CAAA,GAAI,MAAA;AAE3D,EAAA,IAAI,KAAA,CAAM,QAAA,KAAa,KAAA,CAAM,QAAA,EAAU;AACrC,IAAA,MAAM,CAAA,GAAI,MAAA,CAAO,YAAA,CAAa,IAAA,CAAK,SAAS,CAAA,GAAI,OAAA;AAChD,IAAA,WAAA,CAAY,OAAA,EAAS,EAAE,KAAA,EAAO,KAAA,EAAO,MAAM,MAAA,EAAO,EAAG,CAAA,EAAG,CAAA,EAAG,KAAK,CAAA;AAChE,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,cAAA,CAAe,OAAA,CAAQ,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAO;AAAA,QAC/C,CAAA,EAAG,CAAA,GAAI,IAAA,GAAO,CAAA,GAAI,kBAAA;AAAA,QAClB;AAAA,OACD,CAAA;AAAA,IACH;AACA,IAAA;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,YAAA,CAAa,IAAA,CAAK,SAAS,CAAA,GAAI,OAAA;AACtD,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,YAAA,CAAa,IAAA,CAAK,SAAS,CAAA,GAAI,OAAA;AAC5D,EAAA,MAAM,GAAA,GAAM,aAAA,GAAgB,OAAA,GAAU,CAAA,GAAI,EAAA;AAM1C,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,IAAA,CAAK,cAAA,CAAe,MAAM,QAAQ,CAAA;AACvD,EAAA,MAAM,eAAA,GAAkB,WACpB,GAAA,CAAI,mBAAA,CAAoB,QAAQ,CAAA,CAAE,SAAA,GAClC,MAAM,OAAA,CAAQ,SAAA;AAClB,EAAA,MAAM,QAAA,GAAW,aAAA,GAAgB,GAAA,IAAO,eAAA,GAAkB,CAAA,CAAA;AAC1D,EAAA,MAAM,gBAAA,GAAmB,WAAW,GAAA,GAAM,IAAA;AAG1C,EAAA,MAAM,SAAA,GAAY,qBAAA,CAAsB,GAAA,EAAK,IAAA,EAAM,MAAM,IAAI,CAAA;AAC7D,EAAA,MAAM,QAAA,GAAW,kBAAA;AAAA,IACf,CAAA;AAAA,IACA,OAAA;AAAA,IACA,gBAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,SAAA,CAAU,OAAA,CAAQ,OAAO,KAAA,EAAO,KAAK,EAAE,QAAA,CAAS,IAAA,CAAK,GAAG,QAAQ,CAAA;AAEhE,EAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,OAAA,CAAQ,KAAA,EAAO,OAAO,MAAM,CAAA;AACpD,EAAA,KAAA,CAAM,MAAM,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,SAAS,CAAA;AAClC,EAAA,KAAA,CAAM,MAAM,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,eAAe,CAAA;AACxC,EAAA,cAAA,CAAe,QAAQ,UAAA,EAAY,KAAA,EAAO,IAAI,CAAA,CAAE,MAAM,IAAA,CAAK;AAAA,IACzD,CAAA;AAAA,IACA,CAAA,EAAG,gBAAA;AAAA,IACH,KAAA,EAAO,GAAA,GAAM,CAAA,GAAI,UAAA,GAAa;AAAA,GAC/B,CAAA;AACD,EAAA,OAAA,CAAQ,QAAQ,IAAA,CAAK;AAAA,IACnB,IAAA,EAAM,OAAA;AAAA,IACN,KAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA,EAAW,EAAE,CAAA,EAAG,CAAA,EAAG,gBAAA,EAAiB;AAAA,IACpC,IAAA,EAAM,EAAE,CAAA,EAAG,CAAA,EAAG,OAAA,EAAQ;AAAA,IACtB,UAAA,EAAY,EAAE,CAAA,EAAG,CAAA,EAAG,aAAA,EAAc;AAAA,IAClC,KAAA;AAAA,IACA,aAAA,EAAe;AAAA,GAChB,CAAA;AACD,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,cAAA,CAAe,OAAA,CAAQ,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAO;AAAA,MAC/C,CAAA,EAAG,CAAA,GAAI,KAAA,GAAQ,CAAA,GAAI,kBAAA;AAAA,MACnB,CAAA,EAAA,CAAI,UAAU,aAAA,IAAiB;AAAA,KAChC,CAAA;AAAA,EACH;AACF;AASA,SAAS,qBAAA,CACP,GAAA,EACA,IAAA,EACA,IAAA,EACU;AACV,EAAA,IAAI,IAAA,CAAK,KAAK,IAAA,CAAK,EAAA,IAAM,KAAK,IAAA,CAAK,EAAA,GAAK,KAAK,EAAA,GAAK,iBAAA;AAChD,IAAA,OAAO,EAAC;AACV,EAAA,MAAM,EAAE,SAAA,EAAW,IAAA,EAAM,MAAA,EAAQ,OAAM,GAAI,GAAA;AAC3C,EAAA,MAAM,OAAA,GAAU,MAAM,SAAA,GAAY,CAAA;AAClC,EAAA,MAAM,KAAe,EAAC;AACtB,EAAA,KAAA,IAAS,IAAI,IAAA,CAAK,EAAA,GAAK,GAAG,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAM,EAAA,GAAK,SAAA,CAAU,UAAA,CAAW,CAAC,CAAA;AACjC,IAAA,IAAI,OAAO,MAAA,EAAW;AACtB,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,EAAE,CAAA;AAChC,IAAA,IAAI,WAAW,MAAA,EAAW;AAC1B,IAAA,IAAI,IAAA,GAAO,MAAA,CAAO,OAAA,IAAW,IAAA,GAAO,OAAO,OAAA,EAAS;AACpD,IAAA,EAAA,CAAG,IAAA,CAAK,MAAA,CAAO,YAAA,CAAa,CAAC,IAAI,OAAO,CAAA;AAAA,EAC1C;AACA,EAAA,OAAO,EAAA;AACT;AAOA,SAAS,UAAA,CACP,OAAA,EACA,GAAA,EACA,MAAA,EACM;AACN,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,GAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,MAAM,SAAA,GAAY,CAAA;AAElC,EAAA,IAAI,MAAA,GAAS,QAAA;AACb,EAAA,IAAI,MAAA,GAAS,CAAA,QAAA;AACb,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,EAAK,KAAK,CAAA;AAC/B,IAAA,IAAI,SAAS,IAAA,EAAM;AACnB,IAAA,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,IAAA,CAAK,EAAE,CAAA;AACjC,IAAA,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,IAAA,CAAK,EAAE,CAAA;AACjC,IAAA,IAAA,IAAQ,MAAA,CAAO,aAAA,CAAc,KAAA,CAAM,IAAI,CAAA;AACvC,IAAA,MAAA,IAAU,CAAA;AAAA,EACZ;AACA,EAAA,IAAI,WAAW,CAAA,EAAG;AAIlB,EAAA,MAAM,IAAI,IAAA,GAAO,MAAA;AACjB,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,YAAA,CAAa,MAAM,CAAA,GAAI,OAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,YAAA,CAAa,MAAM,CAAA,GAAI,OAAA;AAC3C,EAAA,MAAM,IAAA,GAAA,CAAQ,OAAO,IAAA,IAAQ,CAAA;AAC7B,EAAA,MAAM,QAAQ,KAAA,CAAM,YAAA;AACpB,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,UAAA;AAC1B,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,KAAA,CAAM,UAAA,GAAa,uBAAA;AAG9C,EAAA,MAAM,QAAA,GAAW,IAAA,KAAS,IAAA,GAAO,CAAC,EAAE,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,IAAA,EAAM,IAAI,CAAA,EAAG,EAAA,EAAI,IAAA,EAAM,IAAI,EAAC;AAC3E,EAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,IAAA,SAAA,CAAU,OAAA,CAAQ,OAAO,KAAA,EAAO,KAAK,EAAE,QAAA,CAAS,IAAA,CAAK,GAAG,QAAQ,CAAA;AAAA,EAClE;AACA,EAAA,SAAA,CAAU,OAAA,CAAQ,KAAA,EAAO,KAAA,EAAO,YAAY,CAAA,CAAE,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,IAAA,EAAM,CAAA;AACvE,EAAA,UAAA,CAAW,OAAA,CAAQ,QAAQ,KAAA,EAAO,KAAA,CAAM,MAAM,SAAS,CAAA,CAAE,MAAM,IAAA,CAAK;AAAA,IAClE,CAAA,EAAG,IAAI,YAAA,GAAe,kBAAA;AAAA,IACtB,CAAA,EAAG,IAAA;AAAA,IACH,IAAA,EAAM,CAAA,IAAA,EAAI,MAAA,CAAO,MAAM,CAAA;AAAA,GACxB,CAAA;AACD,EAAA,OAAA,CAAQ,QAAQ,IAAA,CAAK;AAAA,IACnB,IAAA,EAAM,SAAA;AAAA,IACN,MAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA,EAAQ,EAAE,CAAA,EAAG,CAAA,EAAG,IAAA,EAAK;AAAA,IACrB,UAAA,EAAY,YAAA;AAAA,IACZ;AAAA,GACD,CAAA;AACH;AAMA,SAAS,WAAA,CACP,OAAA,EACA,KAAA,EACA,CAAA,EACA,GACA,KAAA,EACM;AACN,EAAA,MAAM,IAAA,GAAO,MAAM,IAAA,GAAO,CAAA;AAC1B,EAAA,MAAM,MAAM,CAAA,GAAI,IAAA;AAChB,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,EAAE,IAAI,CAAA,EAAG,EAAA,EAAI,GAAG,EAAA,EAAI,CAAA,EAAG,IAAI,GAAA,EAAI;AAAA,IAC/B,EAAE,IAAI,CAAA,EAAG,EAAA,EAAI,KAAK,EAAA,EAAI,CAAA,GAAI,IAAA,EAAM,EAAA,EAAI,GAAA,EAAI;AAAA,IACxC,EAAE,EAAA,EAAI,CAAA,GAAI,IAAA,EAAM,EAAA,EAAI,KAAK,EAAA,EAAI,CAAA,GAAI,IAAA,EAAM,EAAA,EAAI,CAAA;AAAE,GAC/C;AACA,EAAA,SAAA,CAAU,OAAA,CAAQ,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,KAAK,CAAA,CAAE,QAAA,CAAS,IAAA,CAAK,GAAG,QAAQ,CAAA;AAC5E,EAAA,SAAA,CAAU,OAAA,CAAQ,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,MAAM,CAAA,CAAE,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA;AACvE,EAAA,cAAA,CAAe,OAAA,CAAQ,YAAY,KAAA,CAAM,KAAA,EAAO,MAAM,IAAI,CAAA,CAAE,MAAM,IAAA,CAAK;AAAA,IACrE,GAAG,CAAA,GAAI,IAAA;AAAA,IACP,CAAA;AAAA,IACA,KAAA,EAAO;AAAA,GACR,CAAA;AACD,EAAA,OAAA,CAAQ,QAAQ,IAAA,CAAK;AAAA,IACnB,IAAA,EAAM,OAAA;AAAA,IACN,KAAA;AAAA,IACA,QAAA;AAAA,IACA,SAAA,EAAW,EAAE,CAAA,EAAG,CAAA,GAAI,MAAM,CAAA,EAAE;AAAA,IAC5B,IAAA,EAAM,EAAE,CAAA,EAAG,CAAA,EAAE;AAAA,IACb,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,eAAe,KAAA,CAAM;AAAA,GACtB,CAAA;AACH;AAEA,SAAS,cAAA,CACP,MAAA,EACA,IAAA,EACA,KAAA,EACA,EAAA,EACM;AACN,EAAA,UAAA,CAAW,QAAQ,KAAA,CAAM,UAAA,EAAY,MAAM,SAAS,CAAA,CAAE,MAAM,IAAA,CAAK;AAAA,IAC/D,GAAG,EAAA,CAAG,CAAA;AAAA,IACN,GAAG,EAAA,CAAG,CAAA;AAAA,IACN;AAAA,GACD,CAAA;AACH;;;AC1WO,IAAM,mBAAN,MAA2C;AAAA,EAKhD,WAAA,CACmB,UAAA,EACA,aAAA,EACT,UAAA,EACR;AAHiB,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AACT,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAER,IAAA,IAAA,CAAK,OAAA,GAAU,WAAW,UAAU,CAAA;AACpC,IAAA,IAAA,CAAK,UAAA,GAAa,WAAW,aAAa,CAAA;AAC1C,IAAA,IAAA,CAAK,UAAU,IAAA,CAAK,OAAA;AAAA,EACtB;AAAA,EAPmB,UAAA;AAAA,EACA,aAAA;AAAA,EACT,UAAA;AAAA,EAPO,OAAA;AAAA,EACA,UAAA;AAAA,EACT,OAAA;AAAA,EAYR,cAAc,UAAA,EAA0B;AACtC,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AAAA,EAEA,MAAA,CAAO,aAAqB,YAAA,EAA4B;AAEtD,IAAA,IAAA,CAAK,WAAW,KAAA,GAAQ,WAAA;AACxB,IAAA,IAAA,CAAK,WAAW,MAAA,GAAS,YAAA;AACzB,IAAA,IAAA,CAAK,cAAc,KAAA,GAAQ,WAAA;AAC3B,IAAA,IAAA,CAAK,cAAc,MAAA,GAAS,YAAA;AAAA,EAC9B;AAAA,EAEA,WAAW,KAAA,EAAoB;AAC7B,IAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,MAAA,IAAA,CAAK,UAAU,IAAA,CAAK,OAAA;AACpB,MAAA,IAAA,CAAK,OAAA,CAAQ,YAAY,IAAA,CAAK,UAAA;AAC9B,MAAA,IAAA,CAAK,OAAA,CAAQ,QAAA;AAAA,QACX,CAAA;AAAA,QACA,CAAA;AAAA,QACA,KAAK,UAAA,CAAW,KAAA;AAAA,QAChB,KAAK,UAAA,CAAW;AAAA,OAClB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,UAAU,IAAA,CAAK,UAAA;AACpB,MAAA,IAAA,CAAK,UAAA,CAAW,SAAA;AAAA,QACd,CAAA;AAAA,QACA,CAAA;AAAA,QACA,KAAK,aAAA,CAAc,KAAA;AAAA,QACnB,KAAK,aAAA,CAAc;AAAA,OACrB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAA,CACE,CAAA,EACA,CAAA,EACA,KAAA,EACA,QACA,KAAA,EACM;AACN,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,GAAA,CAAI,SAAA,GAAY,KAAA;AAChB,IAAA,GAAA,CAAI,QAAA,CAAS,CAAA,EAAG,CAAA,EAAG,KAAA,EAAO,MAAM,CAAA;AAAA,EAClC;AAAA,EAEA,UAAU,KAAA,EAAwB;AAChC,IAAA,IAAI,KAAA,CAAM,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AACjC,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,GAAA,CAAI,cAAc,KAAA,CAAM,KAAA;AACxB,IAAA,GAAA,CAAI,YAAY,KAAA,CAAM,KAAA;AACtB,IAAA,GAAA,CAAI,SAAA,EAAU;AACd,IAAA,KAAA,MAAW,CAAA,IAAK,MAAM,QAAA,EAAU;AAC9B,MAAA,GAAA,CAAI,MAAA,CAAO,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAA;AACrB,MAAA,GAAA,CAAI,MAAA,CAAO,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAA;AAAA,IACvB;AACA,IAAA,GAAA,CAAI,MAAA,EAAO;AAAA,EACb;AAAA,EAEA,SAAS,KAAA,EAAwB;AAC/B,IAAA,IAAI,KAAA,CAAM,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAC9B,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,GAAA,CAAI,YAAY,KAAA,CAAM,KAAA;AACtB,IAAA,GAAA,CAAI,OAAO,KAAA,CAAM,IAAA;AACjB,IAAA,GAAA,CAAI,eAAe,KAAA,CAAM,QAAA;AACzB,IAAA,GAAA,CAAI,YAAY,KAAA,CAAM,KAAA;AACtB,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,KAAA,EAAO;AAC9B,MAAA,GAAA,CAAI,SAAS,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,CAAA,EAAG,KAAK,CAAC,CAAA;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,WAAA,CAAY,MAAc,IAAA,EAA+B;AACvD,IAAA,IAAA,CAAK,QAAQ,IAAA,GAAO,IAAA;AACpB,IAAA,OAAO,EAAE,KAAA,EAAO,IAAA,CAAK,QAAQ,WAAA,CAAY,IAAI,EAAE,KAAA,EAAM;AAAA,EACvD;AAAA,EAEA,eAAe,KAAA,EAA6B;AAC1C,IAAA,IAAI,KAAA,CAAM,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAC9B,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,IAAA,GAAA,CAAI,YAAY,KAAA,CAAM,KAAA;AAGtB,IAAA,GAAA,CAAI,SAAA,EAAU;AACd,IAAA,KAAA,MAAW,EAAE,CAAA,EAAG,CAAA,EAAG,KAAA,EAAM,IAAK,MAAM,KAAA,EAAO;AACzC,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAC1B,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAC1B,MAAA,MAAM,IAAA,GAAO,IAAI,IAAA,GAAO,GAAA;AACxB,MAAA,MAAM,IAAA,GAAO,IAAI,IAAA,GAAO,GAAA;AAExB,MAAA,MAAM,KAAK,IAAA,GAAO,IAAA;AAClB,MAAA,MAAM,KAAK,GAAA,GAAM,IAAA;AACjB,MAAA,MAAM,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,GAAA,GAAM,EAAA,GAAK,GAAA;AAC/B,MAAA,MAAM,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,GAAA,GAAM,EAAA,GAAK,GAAA;AAC/B,MAAA,MAAM,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,GAAA,GAAM,EAAA,GAAK,GAAA;AAC/B,MAAA,MAAM,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,GAAA,GAAM,EAAA,GAAK,GAAA;AAC/B,MAAA,GAAA,CAAI,MAAA,CAAO,MAAM,IAAI,CAAA;AACrB,MAAA,GAAA,CAAI,MAAA,CAAO,IAAI,EAAE,CAAA;AACjB,MAAA,GAAA,CAAI,MAAA,CAAO,IAAI,EAAE,CAAA;AACjB,MAAA,GAAA,CAAI,SAAA,EAAU;AAAA,IAChB;AACA,IAAA,GAAA,CAAI,IAAA,EAAK;AAAA,EACX;AAAA,EAEA,UAAU,KAAA,EAAwB;AAChC,IAAA,IAAI,KAAA,CAAM,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG;AAC9B,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,GAAA,CAAI,YAAY,KAAA,CAAM,KAAA;AACtB,IAAA,GAAA,CAAI,SAAA,EAAU;AACd,IAAA,KAAA,MAAW,EAAE,CAAA,EAAG,CAAA,EAAE,IAAK,MAAM,KAAA,EAAO;AAElC,MAAA,GAAA,CAAI,MAAA,CAAO,CAAA,GAAI,KAAA,CAAM,MAAA,EAAQ,CAAC,CAAA;AAC9B,MAAA,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,EAAG,KAAA,CAAM,QAAQ,CAAA,EAAG,IAAA,CAAK,KAAK,CAAC,CAAA;AAAA,IAC5C;AACA,IAAA,GAAA,CAAI,IAAA,EAAK;AAAA,EACX;AAAA,EAEA,WAAW,KAAA,EAAyB;AAClC,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,KAAA,MAAW,EAAE,CAAA,EAAG,CAAA,EAAG,MAAM,KAAA,EAAM,IAAK,MAAM,KAAA,EAAO;AAC/C,MAAA,IAAI;AAGF,QAAA,GAAA,CAAI,SAAA,CAAU,KAAA,EAA4B,CAAA,EAAG,CAAA,EAAG,MAAM,IAAI,CAAA;AAAA,MAC5D,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA,EAEA,SAAS,MAAA,EAAqB;AAAA,EAE9B;AACF,CAAA;AAEA,SAAS,WAAW,MAAA,EAAqD;AACvE,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA;AAClC,EAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,IAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,EACpE;AACA,EAAA,OAAO,GAAA;AACT;;;ACxKO,SAAS,UAAA,CAAW,OAAe,GAAA,EAAqB;AAC7D,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,GAAG,CAAA;AAC/B;AAGO,SAAS,eAAe,aAAA,EAA+B;AAC5D,EAAA,OAAO,aAAA,GAAgB,CAAA,KAAM,CAAA,GAAI,GAAA,GAAM,CAAA;AACzC;AAOO,SAAS,iBAAA,CAAkB,MAAc,GAAA,EAAqB;AACnE,EAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IACV,eAAA;AAAA,IACA,CAAC,CAAA,EAAG,IAAA,KAAiB,GAAG,MAAA,CAAO,IAAI,IAAI,GAAG,CAAA,EAAA;AAAA,GAC5C;AACF;;;ACJO,IAAM,gBAAA,GAAmB,EAAA;AAEhC,IAAM,aAAA,GAAgB,CAAA;AAEtB,IAAM,YAAA,GAAe,CAAA;AAErB,IAAM,iBAAA,GAAoB,EAAA;AAQ1B,IAAM,mBAAA,GAAsB,EAAA;AAOrB,SAAS,oBAAoB,KAAA,EAAsB;AACxD,EAAA,MAAM,iBAAiB,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,OAAA,CAAQ,UAAU,mBAAmB,CAAA;AAC3E,EAAA,OAAO,KAAA,CAAM,YAAA,GAAe,cAAA,GAAiB,aAAA,GAAgB,gBAAA;AAC/D;AAKA,SAAS,OAAO,IAAA,EAAsB;AACpC,EAAA,MAAM,KAAA,GAAQ,mBAAA,CAAoB,IAAA,CAAK,IAAI,CAAA;AAC3C,EAAA,OAAO,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,CAAC,CAAC,CAAA,GAAI,iBAAA;AACpC;AAWO,SAAS,kBACd,GAAA,EAC2B;AAC3B,EAAA,MAAM,EAAE,QAAQ,SAAA,EAAW,IAAA,EAAM,UAAU,KAAA,EAAO,IAAA,EAAM,aAAY,GAAI,GAAA;AACxE,EAAA,MAAM,YAAY,KAAA,CAAM,SAAA;AAExB,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAsB;AACxC,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAuB;AAC1C,EAAA,MAAM,KAAA,GAAkB,EAAE,KAAA,EAAO,EAAC,EAAE;AACpC,EAAA,MAAM,UAA8B,EAAC;AAErC,EAAA,KAAA,MAAW,EAAA,IAAM,UAAU,UAAA,EAAY;AACrC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,EAAE,CAAA;AAChC,IAAA,IAAI,WAAW,MAAA,EAAW;AAE1B,IAAA,MAAM,QAAA,GAAW,SAAA,CAAU,YAAA,CAAa,GAAA,CAAI,EAAE,CAAA;AAC9C,IAAA,IAAI,aAAa,MAAA,EAAW;AAC5B,IAAA,IAAI,QAAA,GAAW,IAAA,CAAK,QAAA,IAAY,QAAA,GAAW,KAAK,OAAA,EAAS;AAEzD,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,aAAA,CAAc,MAAA,CAAO,OAAO,CAAA;AACtD,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,aAAA,CAAc,MAAA,CAAO,OAAO,CAAA;AAMpD,IAAA,IAAI,QAAA,IAAY,CAAA,IAAK,UAAA,GAAa,gBAAA,GAAmB,SAAS,QAAA,EAAU;AACtE,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,YAAA,CAAa,QAAQ,IAAI,SAAA,GAAY,CAAA;AAC/D,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,cAAA,CAAe,EAAE,CAAA;AAGtC,IAAA,MAAM,QAAQ,OAAA,GAAU,GAAA,CAAI,mBAAA,CAAoB,OAAO,IAAI,KAAA,CAAM,OAAA;AACjE,IAAA,MAAM,YAAY,KAAA,CAAM,SAAA;AACxB,IAAA,MAAM,YAAY,KAAA,CAAM,SAAA;AACxB,IAAA,MAAM,KAAK,UAAA,GAAa,gBAAA;AACxB,IAAA,SAAA,CAAU,KAAA,EAAO,SAAA,EAAW,SAAS,CAAA,CAAE,SAAS,IAAA,CAAK;AAAA,MACnD,EAAA;AAAA,MACA,EAAA,EAAI,UAAA;AAAA,MACJ,EAAA,EAAI,QAAA;AAAA,MACJ,EAAA,EAAI;AAAA,KACL,CAAA;AACD,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,SAAA;AAAA,QACN,OAAA;AAAA,QACA,CAAA,EAAG,UAAA;AAAA,QACH,EAAA;AAAA,QACA,EAAA,EAAI,QAAA;AAAA,QACJ,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AAOA,IAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AACvB,IAAA,MAAM,OAAO,OAAA,EAAS,IAAA;AACtB,IAAA,MAAM,IAAA,GAAO,OAAA,GAAU,GAAA,CAAI,kBAAA,CAAmB,OAAO,CAAA,GAAI,EAAA;AACzD,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,KAAA,CAAM,SAAS,CAAA;AAEtC,IAAA,IAAI,SAAS,MAAA,EAAW;AACtB,MAAA,MAAM,cAAc,QAAA,GAAW,CAAA;AAC/B,MAAA,MAAM,gBAAgB,IAAA,CAAK,GAAA;AAAA,QACzB,KAAK,aAAA,GAAgB,WAAA;AAAA,QACrB,MAAM,YAAA,GAAe;AAAA,OACvB;AAEA,MAAA,MAAM,MAAA,GAAS,WAAW,YAAA,GAAe,OAAA;AACzC,MAAA,MAAM,GAAA,GAAM,aAAa,MAAA,GAAS,CAAA;AAClC,MAAA,MAAM,WAAA,GAAc,MAAM,QAAA,GAAW,CAAA;AACrC,MAAA,MAAM,MAAA,GAAS,GAAA,GAAM,QAAA,GAAW,YAAA,GAAe,OAAA,GAAU,CAAA;AACzD,MAAA,MAAM,QAAA,GAAW,YAAY,IAAI,CAAA;AACjC,MAAA,IAAI,QAAA,CAAS,SAAS,OAAA,EAAS;AAC7B,QAAA,KAAA,CAAM,MAAM,IAAA,CAAK;AAAA,UACf,CAAA,EAAG,gBAAgB,QAAA,GAAW,CAAA;AAAA,UAC9B,CAAA,EAAG,GAAA;AAAA,UACH,IAAA,EAAM,QAAA;AAAA,UACN,OAAO,QAAA,CAAS;AAAA,SACjB,CAAA;AAAA,MACH,CAAA,MAAA,IAAW,QAAA,CAAS,IAAA,KAAS,MAAA,EAAQ;AAGnC,QAAA,MAAM,QAAA,GAAW,GAAG,QAAQ,CAAA,aAAA,CAAA;AAC5B,QAAA,UAAA,CAAW,QAAQ,KAAA,CAAM,UAAA,EAAY,UAAU,QAAQ,CAAA,CAAE,MAAM,IAAA,CAAK;AAAA,UAClE,CAAA,EAAG,aAAA;AAAA,UACH,CAAA,EAAG,WAAA;AAAA,UACH,MAAM,QAAA,CAAS;AAAA,SAChB,CAAA;AAAA,MACH;AACA,MAAA,UAAA;AAAA,QACE,MAAA;AAAA,QACA,KAAA,CAAM,UAAA;AAAA,QACN,KAAA,CAAM,SAAA;AAAA,QACN;AAAA,OACF,CAAE,MAAM,IAAA,CAAK,EAAE,GAAG,aAAA,EAAe,CAAA,EAAG,MAAA,EAAQ,IAAA,EAAM,CAAA;AAAA,IACpD,CAAA,MAAO;AAIL,MAAA,MAAM,cAAc,EAAA,GAAK,aAAA;AACzB,MAAA,IAAI,WAAA,IAAe,MAAM,YAAA,EAAc;AACrC,QAAA,UAAA;AAAA,UACE,MAAA;AAAA,UACA,KAAA,CAAM,UAAA;AAAA,UACN,KAAA,CAAM,SAAA;AAAA,UACN;AAAA,SACF,CAAE,MAAM,IAAA,CAAK,EAAE,GAAG,WAAA,EAAa,CAAA,EAAG,UAAA,EAAY,IAAA,EAAM,CAAA;AAAA,MACtD,CAAA,MAAO;AACL,QAAA,UAAA;AAAA,UACE,MAAA;AAAA,UACA,KAAA,CAAM,UAAA;AAAA,UACN,KAAA,CAAM,SAAA;AAAA,UACN;AAAA,SACF,CAAE,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,EAAG,MAAM,YAAA,EAAc,CAAA,EAAG,UAAA,EAAY,IAAA,EAAM,CAAA;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,CAAC,GAAG,KAAA,CAAM,QAAQ,CAAA;AAAA,IACzB,MAAA,EAAQ,CAAC,GAAG,MAAA,CAAO,QAAQ,CAAA;AAAA,IAC3B,KAAA;AAAA,IACA;AAAA,GACF;AACF;;;ACrLO,SAAS,UAAU,IAAA,EAAuB;AAC/C,EAAA,OACE,wCAAwC,IAAA,CAAK,IAAI,CAAA,IACjD,2CAAA,CAA4C,KAAK,IAAI,CAAA;AAEzD;AAEO,IAAM,YAAN,MAAgB;AAAA,EAIrB,YAA6B,MAAA,EAAoB;AAApB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAqB;AAAA,EAArB,MAAA;AAAA;AAAA,EAFZ,KAAA,uBAAY,GAAA,EAAqC;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlE,IAAI,GAAA,EAA2C;AAC7C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC9B,IAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,MAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AACb,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,IAAI,GAAA,KAAQ,MAAM,OAAO,MAAA;AACzB,IAAA,OAAO,GAAA,CAAI,QAAA,IAAY,GAAA,CAAI,YAAA,GAAe,IAAI,GAAA,GAAM,MAAA;AAAA,EACtD;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA,EAEQ,KAAK,GAAA,EAAmB;AAE9B,IAAA,IAAI,OAAO,UAAU,WAAA,EAAa;AAChC,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AACxB,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AACxB,IAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,EAAM;AACxB,IAAA,KAAA,CAAM,SAAS,MAAM;AACnB,MAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AACzB,MAAA,IAAA,CAAK,MAAA,EAAO;AAAA,IACd,CAAA;AACA,IAAA,KAAA,CAAM,UAAU,MAAM;AAAA,IAEtB,CAAA;AACA,IAAA,KAAA,CAAM,GAAA,GAAM,GAAA;AAAA,EACd;AACF,CAAA;;;AC7CO,SAAS,cAAA,CACd,MAAA,EACA,QAAA,EACA,QAAA,EACA,YAAA,EACS;AACT,EAAA,IAAI,aAAa,CAAA,EAAG,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,SAAS,EAAA,EAAG;AACtD,EAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,OAAO,YAAA,CAAa,YAAY,CAAC,CAAA,GAAI,CAAA;AAC5D,EAAA,MAAM,MAAA,GAAS,KAAK,IAAA,CAAK,MAAA,CAAO,aAAa,QAAA,CAAS,SAAS,CAAC,CAAA,GAAI,CAAA;AACpE,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,GAAG,CAAA;AAAA,IACzB,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,QAAA,GAAW,GAAG,MAAM;AAAA,GACxC;AACF;;;ACLO,SAAS,SAAA,CAAU,MAAgB,GAAA,EAAwB;AAChE,EAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,WAAW,IAAA,CAAK,KAAA,EAAO,GAAG,CAAC,CAAA;AACrD,EAAA,MAAM,GAAA,GAAM,eAAe,KAAK,CAAA;AAChC,EAAA,OAAO;AAAA,IACL,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,KAAA;AAAA,IACA,QAAA,EAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAClC,EAAA,EAAI,UAAA,CAAW,CAAA,CAAE,EAAA,EAAI,GAAG,CAAA,GAAI,GAAA;AAAA,MAC5B,EAAA,EAAI,UAAA,CAAW,CAAA,CAAE,EAAA,EAAI,GAAG,CAAA,GAAI,GAAA;AAAA,MAC5B,EAAA,EAAI,UAAA,CAAW,CAAA,CAAE,EAAA,EAAI,GAAG,CAAA,GAAI,GAAA;AAAA,MAC5B,EAAA,EAAI,UAAA,CAAW,CAAA,CAAE,EAAA,EAAI,GAAG,CAAA,GAAI;AAAA,KAC9B,CAAE;AAAA,GACJ;AACF;AAEO,SAAS,SAAA,CAAU,MAAgB,GAAA,EAAwB;AAChE,EAAA,OAAO;AAAA,IACL,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,MAAA,EAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,WAAW,IAAA,CAAK,MAAA,EAAQ,GAAG,CAAC,CAAA;AAAA,IAChD,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC5B,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA;AAAA,MACtB,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG;AAAA,KACxB,CAAE;AAAA,GACJ;AACF;AAEO,SAAS,cAAA,CACd,MACA,GAAA,EACgB;AAChB,EAAA,OAAO;AAAA,IACL,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,IAAA,EAAM,KAAK,GAAA,CAAI,CAAA,EAAG,WAAW,IAAA,CAAK,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IAC5C,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC5B,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA;AAAA,MACtB,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA;AAAA,MACtB,OAAO,CAAA,CAAE;AAAA;AAAA,KACX,CAAE;AAAA,GACJ;AACF;AAEO,SAAS,UAAA,CAAW,MAAiB,GAAA,EAAwB;AAClE,EAAA,OAAO;AAAA,IACL,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,IAAA,EAAM,iBAAA,CAAkB,IAAA,CAAK,IAAA,EAAM,GAAG,CAAA;AAAA,IACtC,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC5B,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA;AAAA,MACtB,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA;AAAA,MACtB,MAAM,CAAA,CAAE;AAAA,KACV,CAAE;AAAA,GACJ;AACF;AAEO,SAAS,SAAA,CAAU,MAAgB,GAAA,EAAyB;AACjE,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MAC5B,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA;AAAA,MACtB,CAAA,EAAG,UAAA,CAAW,CAAA,CAAE,CAAA,EAAG,GAAG,CAAA;AAAA,MACtB,IAAA,EAAM,UAAA,CAAW,CAAA,CAAE,IAAA,EAAM,GAAG,CAAA;AAAA,MAC5B,OAAO,CAAA,CAAE;AAAA,KACX,CAAE;AAAA,GACJ;AACF;;;AC7EO,IAAM,MAAA,GAAS,KAAA;AAGf,IAAM,oBAAoB,EAAA,GAAK,MAAA;AAG/B,IAAM,gBAAA,GAAmB,GAAA;AA0ChC,SAAS,cAAA,CAAe,UAAoB,KAAA,EAAyB;AACnE,EAAA,MAAM,IAAA,GAAO,MAAM,IAAA,IAAQ,CAAA;AAC3B,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,CAAA;AAC7B,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,QAAA,CAAS,QAAA,GAAW,OAAO,KAAK,CAAA;AACrD;AAEA,IAAM,aAAA,GAA6B;AAAA,EACjC,UAAA,EAAY,CAAA;AAAA,EACZ,OAAA,EAAS,CAAA;AAAA,EACT,OAAA,EAAS;AACX,CAAA;AAEO,IAAM,SAAN,MAAa;AAAA,EAGlB,WAAA,CACmB,OAAA,EACjB,OAAA,GAAgC,EAAC,EACjC;AAFiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAGjB,IAAA,IAAA,CAAK,MAAA,GAAS,EAAE,GAAG,aAAA,EAAe,GAAG,OAAA,EAAQ;AAAA,EAC/C;AAAA,EAJmB,OAAA;AAAA,EAHX,MAAA;AAAA,EASR,IAAI,KAAA,GAA+B;AACjC,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA,EAIA,cAAc,CAAA,EAAiB;AAC7B,IAAA,OAAA,CAAQ,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,UAAA,IAAc,KAAK,MAAA,CAAO,OAAA;AAAA,EACpD;AAAA,EAEA,cAAc,CAAA,EAAiB;AAC7B,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,UAAA,GAAa,CAAA,GAAI,KAAK,MAAA,CAAO,OAAA;AAAA,EAClD;AAAA,EAEA,aAAa,GAAA,EAAqB;AAChC,IAAA,MAAM,EAAE,YAAA,EAAc,SAAA,EAAW,MAAA,KAAW,IAAA,CAAK,OAAA;AACjD,IAAA,OAAO,YAAA,GAAe,GAAA,IAAO,SAAA,GAAY,MAAA,CAAA,GAAU,KAAK,MAAA,CAAO,OAAA;AAAA,EACjE;AAAA,EAEA,aAAa,CAAA,EAAmB;AAC9B,IAAA,MAAM,EAAE,YAAA,EAAc,SAAA,EAAW,MAAA,KAAW,IAAA,CAAK,OAAA;AACjD,IAAA,OAAA,CAAQ,CAAA,GAAI,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,iBAAiB,SAAA,GAAY,MAAA,CAAA;AAAA,EACjE;AAAA;AAAA,EAIA,cAAc,CAAA,EAAe;AAC3B,IAAA,IAAA,CAAK,OAAO,UAAA,GAAa,CAAA;AAAA,EAC3B;AAAA,EAEA,WAAW,CAAA,EAAiB;AAC1B,IAAA,IAAA,CAAK,OAAO,OAAA,GAAU,CAAA;AAAA,EACxB;AAAA,EAEA,UAAA,CAAW,SAAiB,MAAA,EAA0B;AACpD,IAAA,IAAA,CAAK,MAAA,CAAO,UAAU,IAAA,CAAK,GAAA;AAAA,MACzB,MAAA,CAAO,UAAA;AAAA,MACP,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,UAAA,EAAY,OAAO;AAAA,KACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAAA,CACE,MAAA,EACA,aAAA,EACA,MAAA,EACM;AACN,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,aAAA,CAAc,aAAa,CAAA;AAChD,IAAA,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,QAAQ,MAAM,CAAA;AACpD,IAAA,IAAA,CAAK,MAAA,CAAO,UAAA,GAAa,OAAA,GAAU,aAAA,GAAgB,KAAK,MAAA,CAAO,OAAA;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAA,CAAY,OAAe,KAAA,EAAqB;AAC9C,IAAA,IAAA,CAAK,MAAA,CAAO,UAAA,IAAc,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,OAAA;AAC9C,IAAA,IAAA,CAAK,OAAO,OAAA,IAAW,KAAA;AAAA,EACzB;AAAA;AAAA,EAGA,YAAA,CAAa,eAAuB,QAAA,EAA0B;AAC5D,IAAA,MAAM,WAAA,GAAc,QAAA,CAAS,SAAA,GAAY,IAAA,CAAK,OAAA,CAAQ,YAAA;AACtD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,gBAAgB,WAAW,CAAA;AACnD,IAAA,IAAA,CAAK,MAAA,CAAO,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,EACtE;AACF,CAAA;AAOO,SAAS,eAAA,CAAgB,QAAuB,GAAA,EAAmB;AACxE,EAAA,IAAI,WAAW,IAAA,EAAM;AACnB,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,MAAM,iBAAA,GAAoB,CAAA;AAAA,MACnC,OAAA,EAAS,MAAM,iBAAA,GAAoB;AAAA,KACrC;AAAA,EACF;AACA,EAAA,IAAI,MAAA,CAAO,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,CAAA,EAAG;AACxC,IAAA,MAAM,SAAS,MAAA,CAAO,OAAA;AACtB,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,SAAS,iBAAA,GAAoB,CAAA;AAAA,MACtC,OAAA,EAAS,SAAS,iBAAA,GAAoB;AAAA,KACxC;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,kBACd,MAAA,EACA,QAAA,EACA,GAAA,EACA,KAAA,GAAkB,EAAC,EACP;AACZ,EAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,MAAA,EAAQ,GAAG,CAAA;AACvC,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,OAAA,GAAU,GAAA,CAAI,OAAA;AAC/B,EAAA,MAAM,aAAa,gBAAA,GAAmB,MAAA;AAItC,EAAA,MAAM,UAAA,GAAa,cAAA,CAAe,QAAA,EAAU,KAAK,CAAA,GAAI,IAAA;AACrD,EAAA,OAAO,EAAE,YAAY,UAAA,EAAW;AAClC;AASO,SAAS,IACd,MAAA,EACA,MAAA,EACA,UACA,GAAA,EACA,KAAA,GAAkB,EAAC,EACb;AACN,EAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,MAAA,EAAQ,GAAG,CAAA;AACvC,EAAA,MAAM,IAAA,GAAO,GAAA,CAAI,OAAA,GAAU,GAAA,CAAI,OAAA;AAC/B,EAAA,MAAA,CAAO,UAAA;AAAA,IACL,cAAA,CAAe,QAAA,EAAU,KAAK,CAAA,GAAI,IAAA;AAAA,IAClC,iBAAA,CAAkB,MAAA,EAAQ,QAAA,EAAU,GAAA,EAAK,KAAK;AAAA,GAChD;AAGA,EAAA,MAAM,IAAA,GAAO,MAAM,IAAA,IAAQ,CAAA;AAC3B,EAAA,MAAA,CAAO,cAAc,GAAA,CAAI,OAAA,GAAU,IAAA,GAAO,MAAA,CAAO,MAAM,OAAO,CAAA;AAC9D,EAAA,MAAA,CAAO,WAAW,CAAC,CAAA;AACrB;;;AC1LA,IAAM,KAAA,GAAgB;AAAA,EACpB,EAAE,KAAA,EAAO,KAAA,EAAO,CAAA,EAAG,CAAA,EAAG,UAAU,MAAA,EAAO;AAAA,EACvC,EAAE,KAAA,EAAO,KAAA,EAAO,GAAG,CAAA,EAAG,QAAA,EAAU,IAAI,MAAA,EAAO;AAAA,EAC3C,EAAE,KAAA,EAAO,KAAA,EAAO,GAAG,CAAA,EAAG,QAAA,EAAU,IAAI,MAAA,EAAO;AAAA,EAC3C,EAAE,KAAA,EAAO,KAAA,EAAO,GAAG,EAAA,EAAI,QAAA,EAAU,KAAK,MAAA,EAAO;AAAA,EAC7C,EAAE,KAAA,EAAO,OAAA,EAAS,GAAG,CAAA,EAAG,QAAA,EAAU,KAAK,MAAA,EAAO;AAAA,EAC9C,EAAE,KAAA,EAAO,OAAA,EAAS,GAAG,CAAA,EAAG,QAAA,EAAU,KAAK,MAAA,EAAO;AAAA,EAC9C,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAG,CAAA,EAAG,QAAA,EAAU,MAAM,MAAA,EAAO;AAAA,EAC9C,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAG,CAAA,EAAG,QAAA,EAAU,MAAM,MAAA,EAAO;AAAA,EAC9C,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAG,CAAA,EAAG,QAAA,EAAU,OAAO,MAAA,EAAO;AAAA,EAC/C,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAG,EAAA,EAAI,QAAA,EAAU,OAAO,MAAA;AAC3C,CAAA;AAEA,SAAS,QAAA,CAAS,SAAiB,aAAA,EAA6B;AAC9D,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,IAAA,CAAK,QAAA,GAAW,OAAA,IAAW,aAAA,EAAe,OAAO,IAAA;AAAA,EACvD;AACA,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AAC/B;AAGA,SAAS,YAAY,KAAA,EAAmB;AACtC,EAAA,QAAQ,MAAM,KAAA;AAAO,IACnB,KAAK,KAAA;AACH,MAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,GAAG,CAAA,EAAG,QAAA,EAAU,KAAK,MAAA,EAAO;AAAA,IACvD,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAG,CAAA,EAAG,QAAA,EAAU,MAAM,MAAA,EAAO;AAAA,IACvD,KAAK,MAAA;AACH,MAAA,OAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,CAAA,EAAG,KAAA,CAAM,IAAI,EAAA,EAAI,QAAA,EAAU,KAAA,CAAM,QAAA,GAAW,EAAA,EAAG;AAAA;AAE7E;AAEA,SAAS,QAAQ,CAAA,EAAiB;AAChC,EAAA,OAAO,IAAI,IAAA,CAAK,CAAC,CAAA,CAAE,cAAA,EAAe;AACpC;AACA,SAAS,SAAS,CAAA,EAAiB;AACjC,EAAA,OAAO,IAAI,IAAA,CAAK,CAAC,CAAA,CAAE,WAAA,EAAY;AACjC;AACA,SAAS,cAAA,CAAe,MAAc,KAAA,EAAuB;AAC3D,EAAA,OAAO,IAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,QAAQ,CAAA,EAAG,CAAC,CAAC,CAAA,CAAE,UAAA,EAAW;AAC3D;AAEA,IAAM,cAAA,uBAAqB,GAAA,EAAoC;AAC/D,SAAS,aAAA,CAAc,MAAY,KAAA,EAA0B;AAC3D,EAAA,IAAI,GAAA,GAAM,cAAA,CAAe,GAAA,CAAI,KAAK,CAAA;AAClC,EAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,IAAA,MAAM,OAAA,GACJ,UAAU,MAAA,GACN,EAAE,UAAU,KAAA,EAAO,IAAA,EAAM,SAAA,EAAU,GACnC,KAAA,KAAU,OAAA,GACR,EAAE,QAAA,EAAU,KAAA,EAAO,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,SAAA,KACzC,EAAE,QAAA,EAAU,KAAA,EAAO,GAAA,EAAK,SAAA,EAAU;AAC1C,IAAA,GAAA,GAAM,IAAI,IAAA,CAAK,cAAA,CAAe,OAAA,EAAS,OAAO,CAAA;AAC9C,IAAA,cAAA,CAAe,GAAA,CAAI,OAAO,GAAG,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,GAAA,CAAI,OAAO,IAAI,CAAA;AACxB;AAEA,SAAS,QAAA,CAAS,IAAA,EAAY,KAAA,EAAkB,MAAA,EAA6B;AAC3E,EAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,MAAA,CAAO,IAAI,IAAA,CAAK,IAAI,CAAA,EAAG,KAAK,CAAA,EAAE;AAC7D;AAEA,SAAS,SAAA,CACP,MAAA,EACA,IAAA,EACA,IAAA,EACA,MAAA,EACQ;AACR,EAAA,MAAM,QAAgB,EAAC;AACvB,EAAA,IAAI,IAAA,CAAK,UAAU,KAAA,EAAO;AAGxB,IAAA,IAAI,UAAA,GAAa,KAAK,GAAA,CAAI,OAAA,CAAQ,MAAM,CAAA,EAAG,QAAA,CAAS,MAAM,CAAA,EAAG,CAAC,CAAA;AAC9D,IAAA,OAAO,cAAc,IAAA,EAAM;AACzB,MAAA,MAAMA,KAAAA,GAAO,QAAQ,UAAU,CAAA;AAC/B,MAAA,MAAM,KAAA,GAAQ,SAAS,UAAU,CAAA;AACjC,MAAA,MAAM,GAAA,GAAM,cAAA,CAAeA,KAAAA,EAAM,KAAK,CAAA;AACtC,MAAA,KAAA,IAAS,MAAM,CAAA,EAAG,GAAA,IAAO,GAAA,EAAK,GAAA,IAAO,KAAK,CAAA,EAAG;AAC3C,QAAA,MAAMC,EAAAA,GAAI,IAAA,CAAK,GAAA,CAAID,KAAAA,EAAM,OAAO,GAAG,CAAA;AACnC,QAAA,IAAIC,EAAAA,IAAK,MAAA,IAAUA,EAAAA,IAAK,IAAA,EAAM,KAAA,CAAM,KAAK,QAAA,CAASA,EAAAA,EAAG,KAAA,EAAO,MAAM,CAAC,CAAA;AAAA,MACrE;AACA,MAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAID,KAAAA,EAAM,KAAA,GAAQ,GAAG,CAAC,CAAA;AAAA,IAC1C;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,IAAA,CAAK,UAAU,OAAA,EAAS;AAC1B,IAAA,MAAM,UAAA,GAAa,KAAK,KAAA,CAAM,QAAA,CAAS,MAAM,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,CAAA;AAChE,IAAA,IAAIA,KAAAA,GAAO,QAAQ,MAAM,CAAA;AACzB,IAAA,IAAI,KAAA,GAAQ,UAAA;AACZ,IAAA,IAAIC,EAAAA,GAAI,IAAA,CAAK,GAAA,CAAID,KAAAA,EAAM,OAAO,CAAC,CAAA;AAC/B,IAAA,OAAOC,MAAK,IAAA,EAAM;AAChB,MAAA,IAAIA,EAAAA,IAAK,QAAQ,KAAA,CAAM,IAAA,CAAK,SAASA,EAAAA,EAAG,OAAA,EAAS,MAAM,CAAC,CAAA;AACxD,MAAA,KAAA,IAAS,IAAA,CAAK,CAAA;AACd,MAAAA,EAAAA,GAAI,IAAA,CAAK,GAAA,CAAID,KAAAA,EAAM,OAAO,CAAC,CAAA;AAC3B,MAAAA,KAAAA,GAAO,QAAQC,EAAC,CAAA;AAChB,MAAA,KAAA,GAAQ,SAASA,EAAC,CAAA;AAAA,IACpB;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,GAAO,KAAK,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,CAAA;AACvD,EAAA,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,GAAG,CAAC,CAAA;AAC3B,EAAA,OAAO,KAAK,IAAA,EAAM;AAChB,IAAA,IAAI,CAAA,IAAK,QAAQ,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA,EAAG,MAAA,EAAQ,MAAM,CAAC,CAAA;AACvD,IAAA,IAAA,IAAQ,IAAA,CAAK,CAAA;AACb,IAAA,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,CAAA,EAAG,CAAC,CAAA;AAAA,EACzB;AACA,EAAA,OAAO,KAAA;AACT;AAQA,SAAS,YAAA,CACP,KAAA,EACA,OAAA,EACA,QAAA,EACQ;AACR,EAAA,MAAM,OAAe,EAAC;AACtB,EAAA,IAAI,KAAA,GAAQ,CAAA,QAAA;AACZ,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,CAAA,GAAI,KAAK,IAAA,GAAO,OAAA;AACtB,IAAA,IAAI,CAAA,GAAI,SAAS,QAAA,EAAU;AACzB,MAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AACd,MAAA,KAAA,GAAQ,CAAA;AAAA,IACV;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,cACd,MAAA,EACA,IAAA,EACA,OAAA,EACA,aAAA,EACA,aAA4B,aAAA,EACjB;AACX,EAAA,IAAI,IAAA,IAAQ,UAAU,CAAC,MAAA,CAAO,SAAS,OAAO,CAAA,IAAK,WAAW,CAAA,EAAG;AAC/D,IAAA,OAAO,EAAE,KAAA,EAAO,EAAC,EAAG,KAAA,EAAO,EAAC,EAAE;AAAA,EAChC;AACA,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,OAAA,EAAS,aAAa,CAAA;AAC7C,EAAA,MAAM,KAAA,GAAQ,YAAY,KAAK,CAAA;AAC/B,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,YAAA;AAAA,MACL,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAO,UAAU,CAAA;AAAA,MACzC,OAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,KAAA,EAAO,YAAA;AAAA,MACL,SAAA,CAAU,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAO,UAAU,CAAA;AAAA,MACzC,OAAA;AAAA,MACA;AAAA;AACF,GACF;AACF;;;ACnLO,SAAS,YAAA,CACd,SACG,QAAA,EACA;AACH,EAAA,MAAM,GAAA,GAAM,EAAE,GAAG,IAAA,EAAK;AACtB,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,IAAI,YAAY,MAAA,EAAW;AAC3B,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAqB;AACxD,MAAA,MAAM,KAAA,GAAQ,QAAQ,GAAG,CAAA;AACzB,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA,IACtC;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;;;ACXA,IAAM,uBAAA,GAA0B,GAAA;AAOzB,SAAS,cAAA,CACd,GACA,OAAA,EACa;AACb,EAAA,IAAI,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA,EAAS;AAC1B,IAAA,MAAM,SAAS,IAAA,CAAK,GAAA,CAAI,GAAG,CAAC,CAAA,CAAE,SAAS,uBAAuB,CAAA;AAC9D,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAQ;AAAA,EACzC;AACA,EAAA,IAAI,EAAE,QAAA,EAAU;AACd,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,CAAC,EAAE,MAAA,EAAO;AAAA,EACzC;AACA,EAAA,IAAI,IAAA,CAAK,IAAI,CAAA,CAAE,MAAM,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,MAAM,CAAA,EAAG;AAE3C,IAAA,OAAO,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,CAAC,EAAE,MAAA,EAAO;AAAA,EACzC;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,EAAE,MAAA,EAAO;AAC3C;;;ACbA,IAAM,iBAAA,GAAoB,CAAA;AAInB,IAAM,oBAAN,MAAwB;AAAA,EAQ7B,WAAA,CACmB,QACA,IAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAEjB,IAAA,MAAA,CAAO,gBAAA,CAAiB,aAAA,EAAe,IAAA,CAAK,aAAa,CAAA;AACzD,IAAA,MAAA,CAAO,gBAAA,CAAiB,aAAA,EAAe,IAAA,CAAK,aAAa,CAAA;AACzD,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAA,EAAa,IAAA,CAAK,WAAW,CAAA;AACrD,IAAA,MAAA,CAAO,gBAAA,CAAiB,eAAA,EAAiB,IAAA,CAAK,eAAe,CAAA;AAC7D,IAAA,MAAA,CAAO,gBAAA,CAAiB,cAAA,EAAgB,IAAA,CAAK,cAAc,CAAA;AAE3D,IAAA,MAAA,CAAO,iBAAiB,OAAA,EAAS,IAAA,CAAK,SAAS,EAAE,OAAA,EAAS,OAAO,CAAA;AAAA,EACnE;AAAA,EAVmB,MAAA;AAAA,EACA,IAAA;AAAA,EATX,KAAA,GAAe,MAAA;AAAA,EACf,aAAA,GAA+B,IAAA;AAAA,EAC/B,KAAA,GAAQ,CAAA;AAAA,EACR,KAAA,GAAQ,CAAA;AAAA,EACR,KAAA,GAAQ,CAAA;AAAA,EACR,KAAA,GAAQ,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBR,KAAA,CAAM,SAAiB,OAAA,EAA2C;AACxE,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,MAAA,CAAO,qBAAA,EAAsB;AAC/C,IAAA,OAAO,EAAE,GAAG,OAAA,GAAU,IAAA,CAAK,MAAM,CAAA,EAAG,OAAA,GAAU,KAAK,GAAA,EAAI;AAAA,EACzD;AAAA,EAEiB,aAAA,GAAgB,CAAC,CAAA,KAA0B;AAC1D,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AAC3B,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,IAAA,IAAA,CAAK,gBAAgB,CAAA,CAAE,SAAA;AACvB,IAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,OAAA;AACf,IAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,OAAA;AACf,IAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,OAAA;AACf,IAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,OAAA;AACf,IAAA,IAAA,CAAK,MAAA,CAAO,iBAAA,CAAkB,CAAA,CAAE,SAAS,CAAA;AAAA,EAC3C,CAAA;AAAA,EAEiB,aAAA,GAAgB,CAAC,CAAA,KAA0B;AAC1D,IAAA,IAAI,CAAA,CAAE,SAAA,KAAc,IAAA,CAAK,aAAA,EAAe;AAGtC,MAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzB,QAAA,MAAM,EAAE,GAAG,CAAA,EAAE,GAAI,KAAK,KAAA,CAAM,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,OAAO,CAAA;AAChD,QAAA,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,CAAA,EAAG,CAAC,CAAA;AAAA,MACxB;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzB,MAAA,MAAM,QAAA,GACJ,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,UAAU,IAAA,CAAK,KAAK,CAAA,GAAI,iBAAA,IACnC,KAAK,GAAA,CAAI,CAAA,CAAE,OAAA,GAAU,IAAA,CAAK,KAAK,CAAA,GAAI,iBAAA;AACrC,MAAA,IAAI,CAAC,QAAA,EAAU;AACf,MAAA,IAAA,CAAK,KAAA,GAAQ,SAAA;AAIb,MAAA,IAAA,CAAK,KAAK,KAAA,EAAM;AAAA,IAClB;AAEA,IAAA,IAAI,IAAA,CAAK,UAAU,SAAA,EAAW;AAC5B,MAAA,MAAM,EAAA,GAAK,CAAA,CAAE,OAAA,GAAU,IAAA,CAAK,KAAA;AAC5B,MAAA,MAAM,EAAA,GAAK,CAAA,CAAE,OAAA,GAAU,IAAA,CAAK,KAAA;AAC5B,MAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,OAAA;AACf,MAAA,IAAA,CAAK,QAAQ,CAAA,CAAE,OAAA;AACf,MAAA,IAAI,EAAA,KAAO,KAAK,EAAA,KAAO,CAAA,OAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,EAAE,CAAA;AAAA,IAClD;AAAA,EACF,CAAA;AAAA,EAEiB,WAAA,GAAc,CAAC,CAAA,KAA0B;AACxD,IAAA,IAAI,CAAA,CAAE,SAAA,KAAc,IAAA,CAAK,aAAA,EAAe;AAExC,IAAA,IAAI,IAAA,CAAK,UAAU,MAAA,EAAQ;AACzB,MAAA,MAAM,EAAE,GAAG,CAAA,EAAE,GAAI,KAAK,KAAA,CAAM,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,OAAO,CAAA;AAChD,MAAA,IAAA,CAAK,IAAA,CAAK,OAAA,CAAQ,CAAA,EAAG,CAAA,EAAG;AAAA,QACtB,UAAA,EAAY,CAAA,CAAE,OAAA,IAAW,CAAA,CAAE,OAAA;AAAA,QAC3B,OAAO,CAAA,CAAE;AAAA,OACV,CAAA;AAAA,IACH;AACA,IAAA,IAAA,CAAK,OAAA,CAAQ,EAAE,SAAS,CAAA;AAAA,EAC1B,CAAA;AAAA,EAEiB,eAAA,GAAkB,CAAC,CAAA,KAA0B;AAC5D,IAAA,IAAI,CAAA,CAAE,SAAA,KAAc,IAAA,CAAK,aAAA,EAAe;AACxC,IAAA,IAAA,CAAK,OAAA,CAAQ,EAAE,SAAS,CAAA;AAAA,EAC1B,CAAA;AAAA,EAEiB,iBAAiB,MAAY;AAC5C,IAAA,IAAI,IAAA,CAAK,KAAA,KAAU,MAAA,EAAQ,IAAA,CAAK,KAAK,KAAA,EAAM;AAAA,EAC7C,CAAA;AAAA,EAEiB,OAAA,GAAU,CAAC,CAAA,KAAwB;AAClD,IAAA,MAAM,MAAA,GAAS,cAAA,CAAe,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,EAAE,OAAA,EAAS,CAAA,CAAE,OAAO,CAAA,CAAE,CAAC,CAAA;AACnE,IAAA,QAAQ,OAAO,IAAA;AAAM,MACnB,KAAK,MAAA;AACH,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,MAAA,EAAQ,OAAO,OAAO,CAAA;AAC9C,QAAA;AAAA,MACF,KAAK,KAAA;AACH,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,KAAA,EAAO,CAAC,CAAA;AAC/B,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,KAAK,CAAA;AAC/B,QAAA;AAAA;AACJ,EACF,CAAA;AAAA,EAEQ,QAAQ,SAAA,EAAyB;AACvC,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA;AACb,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AACrB,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,iBAAA,CAAkB,SAAS,CAAA,EAAG;AAC5C,MAAA,IAAA,CAAK,MAAA,CAAO,sBAAsB,SAAS,CAAA;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,CAAoB,aAAA,EAAe,IAAA,CAAK,aAAa,CAAA;AACjE,IAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,CAAoB,aAAA,EAAe,IAAA,CAAK,aAAa,CAAA;AACjE,IAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,CAAoB,WAAA,EAAa,IAAA,CAAK,WAAW,CAAA;AAC7D,IAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,CAAoB,eAAA,EAAiB,IAAA,CAAK,eAAe,CAAA;AACrE,IAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,CAAoB,cAAA,EAAgB,IAAA,CAAK,cAAc,CAAA;AACnE,IAAA,IAAA,CAAK,MAAA,CAAO,mBAAA,CAAoB,OAAA,EAAS,IAAA,CAAK,OAAO,CAAA;AAAA,EACvD;AACF,CAAA;;;AC5JA,IAAM,OAAA,GAAU,EAAA;AAKhB,IAAM,WAAA,GAAc,CAAA;AASpB,SAAS,SAAS,MAAA,EAA2B;AAC3C,EAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,IAAA,MAAMC,IAAAA,GAAM,cAAc,MAAA,CAAO,KAAA;AACjC,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,GAAA,CAAI,OAAO,EAAA,EAAI,MAAA,CAAO,EAAE,CAAA,GAAIA,IAAAA;AAAA,MACvC,MAAM,IAAA,CAAK,GAAA,CAAI,OAAO,EAAA,EAAI,MAAA,CAAO,EAAE,CAAA,GAAIA,IAAAA;AAAA,MACvC,IAAA,EAAM,OAAO,CAAA,GAAIA,IAAAA;AAAA,MACjB,IAAA,EAAM,OAAO,CAAA,GAAIA;AAAA,KACnB;AAAA,EACF;AACA,EAAA,IAAI,IAAA,GAAO,QAAA;AACX,EAAA,IAAI,IAAA,GAAO,QAAA;AACX,EAAA,IAAI,IAAA,GAAO,CAAA,QAAA;AACX,EAAA,IAAI,IAAA,GAAO,CAAA,QAAA;AACX,EAAA,MAAM,OAAA,GAAU,CAAC,CAAA,EAAW,CAAA,KAAc;AACxC,IAAA,IAAI,CAAA,GAAI,MAAM,IAAA,GAAO,CAAA;AACrB,IAAA,IAAI,CAAA,GAAI,MAAM,IAAA,GAAO,CAAA;AACrB,IAAA,IAAI,CAAA,GAAI,MAAM,IAAA,GAAO,CAAA;AACrB,IAAA,IAAI,CAAA,GAAI,MAAM,IAAA,GAAO,CAAA;AAAA,EACvB,CAAA;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,OAAO,QAAA,EAAU;AAC/B,IAAA,OAAA,CAAQ,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAA;AAClB,IAAA,OAAA,CAAQ,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAA;AAAA,EACpB;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,IAAA,OAAA,CAAQ,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,MAAA,CAAO,OAAO,CAAC,CAAA;AACxC,IAAA,MAAMA,OAAM,WAAA,GAAc,IAAA,CAAK,IAAI,MAAA,CAAO,KAAA,EAAO,OAAO,UAAU,CAAA;AAClE,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,GAAOA,IAAAA;AAAA,MACb,MAAM,IAAA,GAAOA,IAAAA;AAAA,MACb,MAAM,IAAA,GAAOA,IAAAA;AAAA,MACb,MAAM,IAAA,GAAOA;AAAA,KACf;AAAA,EACF;AACA,EAAA,IAAI,MAAA,CAAO,WAAW,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAA,EAAG,MAAA,CAAO,UAAU,CAAC,CAAA;AACpE,EAAA,IAAI,MAAA,CAAO,MAAM,OAAA,CAAQ,MAAA,CAAO,KAAK,CAAA,EAAG,MAAA,CAAO,KAAK,CAAC,CAAA;AACrD,EAAA,MAAM,MAAM,WAAA,GAAc,IAAA,CAAK,IAAI,MAAA,CAAO,KAAA,EAAO,OAAO,aAAa,CAAA;AACrE,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,GAAO,GAAA;AAAA,IACb,MAAM,IAAA,GAAO,GAAA;AAAA,IACb,MAAM,IAAA,GAAO,GAAA;AAAA,IACb,MAAM,IAAA,GAAO;AAAA,GACf;AACF;AAEO,IAAM,OAAA,GAAN,MAAM,QAAA,CAAyB;AAAA,EAGpC,WAAA,CAA6B,WAAmB,OAAA,EAAS;AAA5B,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAA6B;AAAA,EAA7B,QAAA;AAAA,EAFZ,KAAA,uBAAY,GAAA,EAAgC;AAAA,EAI7D,OAAe,GAAA,CAAI,EAAA,EAAY,EAAA,EAAoB;AACjD,IAAA,OAAO,CAAA,EAAG,EAAE,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA;AAAA,EACpB;AAAA;AAAA,EAGA,OAAO,MAAA,EAAgC;AACrC,IAAA,MAAM,CAAA,GAAI,SAAS,MAAM,CAAA;AACzB,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAA,GAAO,KAAK,QAAQ,CAAA;AAC7C,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAA,GAAO,KAAK,QAAQ,CAAA;AAC7C,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAA,GAAO,KAAK,QAAQ,CAAA;AAC7C,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,IAAA,GAAO,KAAK,QAAQ,CAAA;AAC7C,IAAA,KAAA,IAAS,EAAA,GAAK,GAAA,EAAK,EAAA,IAAM,GAAA,EAAK,EAAA,EAAA,EAAM;AAClC,MAAA,KAAA,IAAS,EAAA,GAAK,GAAA,EAAK,EAAA,IAAM,GAAA,EAAK,EAAA,EAAA,EAAM;AAClC,QAAA,MAAM,GAAA,GAAM,QAAA,CAAQ,GAAA,CAAI,EAAA,EAAI,EAAE,CAAA;AAC9B,QAAA,IAAI,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC/B,QAAA,IAAI,WAAW,MAAA,EAAW;AACxB,UAAA,MAAA,GAAS,EAAC;AACV,UAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,MAAM,CAAA;AAAA,QAC5B;AACA,QAAA,MAAA,CAAO,KAAK,MAAM,CAAA;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,KAAA,CAAM,GAAW,CAAA,EAAwC;AACvD,IAAA,MAAM,MAAM,QAAA,CAAQ,GAAA;AAAA,MAClB,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA;AAAA,MAC5B,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,IAAA,CAAK,QAAQ;AAAA,KAC9B;AACA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,KAAK,EAAC;AAAA,EACjC;AACF,CAAA;AAGO,SAAS,aACd,OAAA,EACgB;AAChB,EAAA,MAAM,IAAA,GAAO,IAAI,OAAA,EAAe;AAChC,EAAA,KAAA,MAAW,CAAA,IAAK,OAAA,EAAS,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACtC,EAAA,OAAO,IAAA;AACT;;;AC7GO,SAAS,gBACd,EAAA,EACA,EAAA,EACA,EAAA,EACA,EAAA,EACA,IACA,EAAA,EACQ;AACR,EAAA,MAAM,KAAK,EAAA,GAAK,EAAA;AAChB,EAAA,MAAM,KAAK,EAAA,GAAK,EAAA;AAChB,EAAA,MAAM,KAAA,GAAQ,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAE7B,EAAA,MAAM,CAAA,GAAI,UAAU,CAAA,GAAI,CAAA,GAAA,CAAA,CAAM,KAAK,EAAA,IAAM,EAAA,GAAA,CAAM,EAAA,GAAK,EAAA,IAAM,EAAA,IAAM,KAAA;AAChE,EAAA,MAAM,UAAU,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,IAAI,CAAA,GAAI,CAAA;AACxC,EAAA,MAAM,EAAA,GAAK,KAAK,OAAA,GAAU,EAAA;AAC1B,EAAA,MAAM,EAAA,GAAK,KAAK,OAAA,GAAU,EAAA;AAC1B,EAAA,MAAM,KAAK,EAAA,GAAK,EAAA;AAChB,EAAA,MAAM,KAAK,EAAA,GAAK,EAAA;AAChB,EAAA,OAAO,EAAA,GAAK,KAAK,EAAA,GAAK,EAAA;AACxB;AAGO,SAAS,QAAA,CACd,EAAA,EACA,EAAA,EACA,EAAA,EACA,IACA,IAAA,EACS;AACT,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,EAAA,GAAK,EAAE,CAAA,IAAK,QAAQ,IAAA,CAAK,GAAA,CAAI,EAAA,GAAK,EAAE,CAAA,IAAK,IAAA;AAC3D;;;ACtBO,IAAM,gBAAA,GAAmB,CAAA;AAOzB,SAAS,OAAA,CACd,IAAA,EACA,CAAA,EACA,CAAA,EACA,YAAoB,gBAAA,EACK;AAGzB,EAAA,IAAI,OAAA,GAAmC,IAAA;AACvC,EAAA,IAAI,WAAA,GAAuC,IAAA;AAE3C,EAAA,KAAA,MAAW,MAAA,IAAU,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,EAAG;AACrC,IAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,MAAA,MAAMC,OAAAA,GAAS,eAAA;AAAA,QACb,CAAA;AAAA,QACA,CAAA;AAAA,QACA,MAAA,CAAO,EAAA;AAAA,QACP,MAAA,CAAO,CAAA;AAAA,QACP,MAAA,CAAO,EAAA;AAAA,QACP,MAAA,CAAO;AAAA,OACT;AACA,MAAA,MAAMC,IAAAA,GAAM,SAAA,GAAY,MAAA,CAAO,KAAA,GAAQ,CAAA;AACvC,MAAA,IACED,WAAUC,IAAAA,GAAMA,IAAAA,KACf,gBAAgB,IAAA,IAAQD,OAAAA,GAAS,YAAY,MAAA,CAAA,EAC9C;AACA,QAAA,WAAA,GAAc,EAAE,MAAA,EAAQ,MAAA,EAAAA,OAAAA,EAAO;AAAA,MACjC;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,MAAA,GAAS,QAAA;AACb,IAAA,KAAA,MAAW,CAAA,IAAK,OAAO,QAAA,EAAU;AAC/B,MAAA,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,eAAA,CAAgB,GAAG,CAAA,EAAG,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAA,EAAI,CAAA,CAAE,EAAE,CAAC,CAAA;AAAA,IACzE;AACA,IAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAS;AAE3B,MAAA,IACE,MAAA,CAAO,cAAc,MAAA,IACrB,QAAA;AAAA,QACE,CAAA;AAAA,QACA,CAAA;AAAA,QACA,OAAO,SAAA,CAAU,CAAA;AAAA,QACjB,OAAO,SAAA,CAAU,CAAA;AAAA,QACjB,MAAA,CAAO;AAAA,OACT,EACA;AACA,QAAA,MAAA,GAAS,CAAA;AAAA,MACX;AAEA,MAAA,IACE,MAAA,CAAO,eAAe,MAAA,IACtB,QAAA;AAAA,QACE,CAAA;AAAA,QACA,CAAA;AAAA,QACA,OAAO,UAAA,CAAW,CAAA;AAAA,QAClB,OAAO,UAAA,CAAW,CAAA;AAAA,QAClB,MAAA,CAAO;AAAA,OACT,EACA;AACA,QAAA,MAAA,GAAS,CAAA;AAAA,MACX;AAAA,IACF,CAAA,MAAA,IACE,QAAA,CAAS,CAAA,EAAG,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,CAAA,EAAG,MAAA,CAAO,UAAU,CAAA,EAClE;AAEA,MAAA,MAAA,GAAS,CAAA;AAAA,IACX;AACA,IAAA,MAAM,GAAA,GAAM,SAAA,GAAY,MAAA,CAAO,KAAA,GAAQ,CAAA;AACvC,IAAA,IAAI,UAAU,GAAA,GAAM,GAAA,KAAQ,YAAY,IAAA,IAAQ,MAAA,GAAS,QAAQ,MAAA,CAAA,EAAS;AACxE,MAAA,OAAA,GAAU,EAAE,QAAQ,MAAA,EAAO;AAAA,IAC7B;AAAA,EACF;AAEA,EAAA,IAAI,YAAY,IAAA,EAAM;AACpB,IAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,IAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAS,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,MAAA,CAAO,KAAA,EAAM;AACzE,IAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,MAAA,OAAO;AAAA,QACL,IAAA,EAAM,SAAA;AAAA,QACN,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,KAAA,EAAO,OAAO,MAAA,CAAO;AAAA,OACvB;AAAA,IACF;AAAA,EACF;AACA,EAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,WAAA,CAAY,MAAA,CAAO,SAAS,SAAA,EAAW;AACjE,IAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,WAAA,CAAY,OAAO,OAAA,EAAQ;AAAA,EAChE;AACA,EAAA,OAAO,IAAA;AACT;;;ACvFO,SAAS,aAAA,CACd,OAAA,EACAE,MAAAA,EACA,IAAA,EACA,WAAA,EACiB;AACjB,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,OAAO,CAAA;AAE5B,EAAA,IAAI,WAAA,IAAe,KAAK,UAAA,EAAY;AAClC,IAAA,IAAIA,WAAU,IAAA,EAAM;AAElB,MAAA,OAAO,EAAE,GAAA,EAAK,CAAC,GAAG,OAAO,CAAA,EAAG,SAAS,KAAA,EAAM;AAAA,IAC7C;AACA,IAAA,IAAI,KAAK,GAAA,CAAIA,MAAK,CAAA,EAAG,IAAA,CAAK,OAAOA,MAAK,CAAA;AAAA,SACjC,IAAA,CAAK,IAAIA,MAAK,CAAA;AAAA,EACrB,CAAA,MAAO;AACL,IAAA,IAAA,CAAK,KAAA,EAAM;AACX,IAAA,IAAIA,MAAAA,KAAU,IAAA,EAAM,IAAA,CAAK,GAAA,CAAIA,MAAK,CAAA;AAAA,EACpC;AAEA,EAAA,OAAO,EAAE,GAAA,EAAK,CAAC,GAAG,IAAI,CAAA,EAAG,OAAA,EAAS,CAAC,OAAA,CAAQ,OAAA,EAAS,IAAI,CAAA,EAAE;AAC5D;AAGO,SAAS,OAAA,CACd,GACA,CAAA,EACS;AACT,EAAA,IAAI,CAAA,CAAE,IAAA,KAAS,CAAA,CAAE,IAAA,EAAM,OAAO,KAAA;AAC9B,EAAA,KAAA,MAAW,EAAA,IAAM,GAAG,IAAI,CAAC,EAAE,GAAA,CAAI,EAAE,GAAG,OAAO,KAAA;AAC3C,EAAA,OAAO,IAAA;AACT;;;ACxCO,SAAS,QAAA,CACd,IACA,OAAA,EACkB;AAClB,EAAA,IAAI,MAAA,GAA+C,IAAA;AACnD,EAAA,IAAI,WAAA,GAA4B,IAAA;AAEhC,EAAA,MAAM,MAAM,MAAM;AAChB,IAAA,MAAA,GAAS,IAAA;AACT,IAAA,IAAI,gBAAgB,IAAA,EAAM;AAC1B,IAAA,MAAM,IAAA,GAAO,WAAA;AACb,IAAA,WAAA,GAAc,IAAA;AACd,IAAA,EAAA,CAAG,GAAG,IAAI,CAAA;AAAA,EACZ,CAAA;AAEA,EAAA,MAAM,SAAA,IAAa,IAAI,IAAA,KAAgB;AACrC,IAAA,WAAA,GAAc,IAAA;AACd,IAAA,IAAI,MAAA,KAAW,IAAA,EAAM,YAAA,CAAa,MAAM,CAAA;AACxC,IAAA,MAAA,GAAS,UAAA,CAAW,KAAK,OAAO,CAAA;AAAA,EAClC,CAAA,CAAA;AAEA,EAAA,SAAA,CAAU,SAAS,MAAM;AACvB,IAAA,IAAI,WAAW,IAAA,EAAM;AACnB,MAAA,YAAA,CAAa,MAAM,CAAA;AACnB,MAAA,MAAA,GAAS,IAAA;AAAA,IACX;AACA,IAAA,WAAA,GAAc,IAAA;AAAA,EAChB,CAAA;AAEA,EAAA,SAAA,CAAU,QAAQ,MAAM;AACtB,IAAA,IAAI,WAAW,IAAA,EAAM;AACnB,MAAA,YAAA,CAAa,MAAM,CAAA;AACnB,MAAA,GAAA,EAAI;AAAA,IACN;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,SAAA;AACT;;;AC1BO,IAAM,eAAN,MAAsB;AAAA,EACV,SAAA,uBAAgB,GAAA,EAAqC;AAAA,EAEtE,EAAA,CAAsB,KAAQ,EAAA,EAAgC;AAC5D,IAAA,IAAI,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA;AAChC,IAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,MAAA,GAAA,uBAAU,GAAA,EAAI;AACd,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAA,EAAK,GAAG,CAAA;AAAA,IAC7B;AACA,IAAA,GAAA,CAAI,IAAI,EAAuB,CAAA;AAC/B,IAAA,OAAO,MAAM,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,EAAE,CAAA;AAAA,EAC/B;AAAA,EAEA,GAAA,CAAuB,KAAQ,EAAA,EAA0B;AACvD,IAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,EAAuB,CAAA;AAAA,EACzD;AAAA,EAEA,IAAA,CAAwB,KAAQ,OAAA,EAAqB;AACnD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA;AAClC,IAAA,IAAI,QAAQ,MAAA,EAAW;AACvB,IAAA,KAAA,MAAW,EAAA,IAAM,GAAA,EAAM,EAAA,CAAsB,OAAO,CAAA;AAAA,EACtD;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,UAAU,KAAA,EAAM;AAAA,EACvB;AACF,CAAA;;;ACvCO,IAAM,iBAAN,MAAqB;AAAA,EAK1B,YAA6B,MAAA,EAAqC;AAArC,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAAsC;AAAA,EAAtC,MAAA;AAAA,EAJrB,KAAA,GAAoB,EAAE,IAAA,EAAM,KAAA,EAAO,SAAS,KAAA,EAAM;AAAA,EAClD,WAAA,GAA6B,IAAA;AAAA,EAC7B,QAAA,GAAW,KAAA;AAAA,EAInB,UAAU,KAAA,EAAoB;AAC5B,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,GAAI,IAAA;AACpB,IAAA,IAAI,IAAA,CAAK,gBAAgB,IAAA,EAAM;AAC7B,MAAA,IAAA,CAAK,WAAA,GAAc,qBAAA,CAAsB,MAAM,IAAA,CAAK,MAAM,CAAA;AAAA,IAC5D;AAAA,EACF;AAAA,EAEQ,IAAA,GAAa;AACnB,IAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AACnB,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA;AACnB,IAAA,IAAA,CAAK,KAAA,GAAQ,EAAE,IAAA,EAAM,KAAA,EAAO,SAAS,KAAA,EAAM;AAC3C,IAAA,IAAI,KAAA,CAAM,IAAA,IAAQ,KAAA,CAAM,OAAA,EAAS;AAC/B,MAAA,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAI,IAAA,CAAK,gBAAgB,IAAA,EAAM;AAC7B,MAAA,oBAAA,CAAqB,KAAK,WAAW,CAAA;AACrC,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,IACrB;AAAA,EACF;AACF,CAAA;;;ACvCO,IAAM,YAAA,GAAsB;AAAA,EACjC,UAAA,EAAY,SAAA;AAAA,EACZ,aAAA,EAAe,2BAAA;AAAA,EACf,eAAA,EAAiB,SAAA;AAAA,EACjB,UAAA,EAAY,4BAAA;AAAA,EACZ,YAAA,EAAc,EAAA;AAAA,EACd,SAAA,EAAW,EAAA;AAAA,EACX,MAAA,EAAQ,CAAA;AAAA,EACR,YAAA,EAAc,CAAA;AAAA,EACd,UAAA,EAAY,SAAA;AAAA,EACZ,cAAA,EAAgB,SAAA;AAAA,EAChB,YAAA,EAAc,SAAA;AAAA,EACd,OAAA,EAAS;AAAA,IACP,SAAA,EAAW,SAAA;AAAA,IACX,SAAA,EAAW,CAAA;AAAA,IACX,UAAA,EAAY,SAAA;AAAA,IACZ,SAAA,EAAW,4BAAA;AAAA,IACX,QAAA,EAAU;AAAA,GACZ;AAAA,EACA,KAAA,EAAO;AAAA,IACL,UAAA,EAAY,SAAA;AAAA,IACZ,UAAA,EAAY,CAAA;AAAA,IACZ,aAAA,EAAe,CAAA;AAAA,IACf,UAAA,EAAY,SAAA;AAAA,IACZ,SAAA,EAAW,4BAAA;AAAA,IACX,UAAA,EAAY;AAAA;AAEhB;AAOO,SAAS,aAAa,OAAA,EAAiC;AAC5D,EAAA,IAAI,OAAA,KAAY,QAAW,OAAO,YAAA;AAClC,EAAA,OAAO;AAAA,IACL,GAAG,YAAA;AAAA,IACH,GAAG,OAAA;AAAA,IACH,SAAS,EAAE,GAAG,aAAa,OAAA,EAAS,GAAG,QAAQ,OAAA,EAAQ;AAAA,IACvD,OAAO,EAAE,GAAG,aAAa,KAAA,EAAO,GAAG,QAAQ,KAAA;AAAM,GACnD;AACF;;;AC0GA,IAAM,gBAAA,GAAmB,EAAA;AACzB,IAAMC,WAAAA,GAAa,KAAA;AAEnB,IAAM,iCAAA,GAAoC,EAAA;AAE1C,IAAM,kCAAA,GAAqC,EAAA;AAE3C,IAAM,0BAAA,GAA6B,GAAA;AAE5B,IAAM,iBAAN,MAAsC;AAAA,EAC1B,KAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA,GAAU,IAAI,YAAA,EAAsC;AAAA,EACpD,OAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA;AAAA,EAEA,eAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAA;AAAA;AAAA,EAEA,GAAA;AAAA,EACA,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAA;AAAA,EAGA,iBAAA;AAAA,EAGA,kBAAA;AAAA,EAGA,gBAAA;AAAA,EAGA,aAAA;AAAA;AAAA,EAEA,YAAA;AAAA,EACA,YAAY,IAAI,SAAA;AAAA,IAAU,MACzC,IAAA,CAAK,SAAA,CAAU,SAAA,CAAU,MAAM;AAAA,GACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOiB,WAAA,GAA2B,CAAC,IAAA,KAAS;AACpD,IAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC5B,MAAA,OAAO,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,YAAA,GAAe,CAAA,GACxC,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,IAAA,EAAK,GAC7B,EAAE,MAAM,MAAA,EAAO;AAAA,IACrB;AACA,IAAA,IAAI,SAAA,CAAU,IAAI,CAAA,EAAG;AACnB,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AACrC,MAAA,OAAO,KAAA,GAAQ,EAAE,IAAA,EAAM,OAAA,EAAS,OAAM,GAAI,EAAE,MAAM,MAAA,EAAO;AAAA,IAC3D;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAK;AAAA,EACpC,CAAA;AAAA,EAEQ,QAAA,GAAqB,EAAE,QAAA,EAAU,CAAA,EAAG,WAAW,CAAA,EAAE;AAAA,EACjD,GAAA,GAAM,CAAA;AAAA,EACN,SAAA,GAAuB,gBAAA,CAAiB,EAAC,EAAG;AAAA,IAElD,SAAA,EAAW,CAAA;AAAA,IACX,MAAA,EAAQ;AAAA,GACT,CAAA;AAAA,EACO,SAAA,GAAY,KAAA;AAAA,EACZ,QAAA,GAAW,KAAA;AAAA;AAAA;AAAA,EAIX,OAAA,GAAiC,IAAA;AAAA,EACjC,eAAmC,EAAC;AAAA;AAAA,EAEpC,cAAA,GAAkD,IAAA;AAAA,EAClD,OAAA,GAAmC,IAAA;AAAA,EAC1B,WAAA,uBAAkB,GAAA,EAAY;AAAA,EAE/C,WAAA,CACE,UAAA,EACA,aAAA,EACA,OAAA,GAAwC,EAAC,EACzC;AACA,IAAA,IAAA,CAAK,KAAA,GAAQ,YAAA,CAAa,OAAA,CAAQ,KAAK,CAAA;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACb,YAAA,EAAc,KAAK,KAAA,CAAM,YAAA;AAAA,MACzB,SAAA,EAAW,KAAK,KAAA,CAAM,SAAA;AAAA,MACtB,MAAA,EAAQ,KAAK,KAAA,CAAM;AAAA,KACrB;AACA,IAAA,IAAA,CAAK,cAAA,GAAiB,QAAQ,MAAA,IAAU,YAAA;AACxC,IAAA,IAAA,CAAK,eAAA,GAAkB,QAAQ,eAAA,IAAmB,eAAA;AAClD,IAAA,IAAA,CAAK,wBAAA,GAA2B,SAAS,MAAM;AAC7C,MAAA,IAAI,KAAK,QAAA,EAAU;AACnB,MAAA,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAC3B,MAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,MAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,IAC1B,CAAA,EAAG,OAAA,CAAQ,gBAAA,IAAoB,0BAA0B,CAAA;AACzD,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,WAAA,IAAe,KAAA;AAC1C,IAAA,IAAA,CAAK,UAAA,GAAa;AAAA,MAChB,OAAA,EAAS,OAAA,CAAQ,UAAA,EAAY,OAAA,IAAW,IAAA;AAAA,MACxC,QAAA,EAAU,OAAA,CAAQ,UAAA,EAAY,QAAA,IAAY,oBAAA;AAAA,MAC1C,eAAA,EACE,OAAA,CAAQ,UAAA,EAAY,eAAA,IACpB;AAAA,KACJ;AACA,IAAA,IAAA,CAAK,GAAA,GAAM;AAAA,MACT,oBAAA,EACE,OAAA,CAAQ,GAAA,EAAK,oBAAA,IACb,kCAAA,GAAqCA;AAAA,KACzC;AAGA,IAAA,MAAM,eAAA,GAAkB,QAAQ,cAAA,EAAgB,OAAA;AAChD,IAAA,IAAA,CAAK,mBAAA,GAAsB,CAAC,OAAA,KAC1B,YAAA;AAAA,MACE,KAAK,KAAA,CAAM,OAAA;AAAA,MACX,kBAAkB,OAAO,CAAA;AAAA,MACzB,OAAA,CAAQ;AAAA,KACV;AACF,IAAA,MAAM,aAAA,GAAgB,QAAQ,cAAA,EAAgB,KAAA;AAC9C,IAAA,IAAA,CAAK,iBAAA,GAAoB,CAAC,KAAA,KACxB,YAAA,CAAa,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,aAAA,GAAgB,KAAK,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AACpE,IAAA,IAAA,CAAK,kBAAA,GACH,QAAQ,UAAA,EAAY,YAAA,KACnB,CAAC,OAAA,KAAY,OAAA,CAAQ,SAAS,OAAA,CAAQ,EAAA,CAAA;AACzC,IAAA,IAAA,CAAK,mBACH,OAAA,CAAQ,UAAA,EAAY,UAAA,KAAe,CAAC,UAAU,KAAA,CAAM,KAAA,CAAA;AACtD,IAAA,IAAA,CAAK,aAAA,GAAgB,QAAQ,UAAA,EAAY,SAAA;AACzC,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,YAAA;AAC5B,IAAA,IAAA,CAAK,QAAQ,IAAI,SAAA,CAAiB,EAAE,YAAA,EAAc,OAAA,CAAQ,cAAc,CAAA;AACxE,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AACrC,IAAA,IAAA,CAAK,WAAW,IAAI,gBAAA;AAAA,MAClB,UAAA;AAAA,MACA,aAAA;AAAA,MACA,KAAK,KAAA,CAAM;AAAA,KACb;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,cAAA,CAAe,CAAC,UAAU,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAIpE,IAAA,IAAA,CAAK,UAAU,IAAI,iBAAA,CAAkB,aAAA,EAAe,IAAA,CAAK,aAAa,CAAA;AAEtE,IAAA,cAAA,CAAe,MAAM;AACnB,MAAA,IAAI,CAAC,IAAA,CAAK,QAAA,OAAe,OAAA,CAAQ,IAAA,CAAK,SAAS,MAAS,CAAA;AAAA,IAC1D,CAAC,CAAA;AAAA,EACH;AAAA;AAAA,EAIA,QAAQ,IAAA,EAAiC;AACvC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA;AACtC,IAAA,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAC3B,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,MAAM,CAAA;AACtC,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,UAAU,MAAA,EAA+C;AACvD,IAAA,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,MAAM,CAAC,CAAA;AAAA,EACjD;AAAA;AAAA,EAGA,aAAa,GAAA,EAA8B;AACzC,IAAA,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,GAAG,CAAC,CAAA;AAAA,EACjD;AAAA;AAAA,EAGA,YAAY,QAAA,EAAmD;AAC7D,IAAA,IAAA,CAAK,aAAA,CAAc,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,QAAQ,CAAC,CAAA;AAAA,EACrD;AAAA;AAAA,EAGA,aAAA,CAAc,IAAY,KAAA,EAA8C;AACtE,IAAA,IAAA,CAAK,cAAc,IAAA,CAAK,KAAA,CAAM,aAAA,CAAc,EAAA,EAAI,KAAK,CAAC,CAAA;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,cAAc,MAAA,EAAgC;AACpD,IAAA,IAAI,MAAA,CAAO,UAAU,CAAA,IAAK,MAAA,CAAO,YAAY,CAAA,IAAK,MAAA,CAAO,YAAY,CAAA,EAAG;AACtE,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,uBAAA,EAAwB;AAC7B,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,MAAM,CAAA;AACtC,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA,EAEA,MAAA,CAAO,QAAA,EAAkB,SAAA,EAAmB,GAAA,EAAmB;AAC7D,IAAA,IAAA,CAAK,QAAA,GAAW,EAAE,QAAA,EAAU,SAAA,EAAU;AACtC,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,QAAA,CAAS,OAAO,UAAA,CAAW,QAAA,EAAU,GAAG,CAAA,EAAG,UAAA,CAAW,SAAA,EAAW,GAAG,CAAC,CAAA;AAC1E,IAAA,IAAA,CAAK,MAAA,CAAO,WAAW,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,EAAS,IAAA,CAAK,YAAY,CAAA;AACnE,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,IAAA,CAAK,OAAO,YAAA,CAAa,IAAA,CAAK,SAAA,CAAU,aAAA,EAAe,KAAK,QAAQ,CAAA;AACpE,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA,EAEA,GAAA,GAAY;AACV,IAAA,GAAA;AAAA,MACE,IAAA,CAAK,MAAA;AAAA,MACL,IAAA,CAAK,MAAM,aAAA,EAAc;AAAA,MACzB,IAAA,CAAK,QAAA;AAAA,MACL,KAAK,GAAA,EAAI;AAAA,MACT,KAAK,QAAA;AAAS,KAChB;AACA,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA,EAEA,UAAU,CAAA,EAAe;AACvB,IAAA,IAAA,CAAK,MAAA,CAAO,cAAc,CAAC,CAAA;AAC3B,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA;AAAA,EAGA,WAAA,CAAY,OAAa,GAAA,EAAiB;AACxC,IAAA,MAAM,OAAO,GAAA,GAAM,KAAA;AACnB,IAAA,IAAI,EAAE,IAAA,GAAO,CAAA,CAAA,IAAM,IAAA,CAAK,QAAA,CAAS,YAAY,CAAA,EAAG;AAChD,IAAA,IAAA,CAAK,MAAA,CAAO,cAAc,KAAK,CAAA;AAC/B,IAAA,IAAA,CAAK,MAAA,CAAO,WAAW,IAAA,CAAK,QAAA,CAAS,WAAW,IAAA,EAAM,IAAA,CAAK,YAAY,CAAA;AACvE,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,GAAA,EAAqB;AAC1B,IAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,GAAG,CAAA;AACxB,IAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,WAAA,EAAa,IAAI,CAAA,EAAG;AACrC,IAAA,IAAA,CAAK,YAAY,KAAA,EAAM;AACvB,IAAA,KAAA,MAAW,EAAA,IAAM,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,IAAI,EAAE,CAAA;AAC9C,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,iBAAA,EAAmB,EAAE,GAAA,EAAK,CAAC,GAAG,IAAA,CAAK,WAAW,CAAA,EAAG,CAAA;AACnE,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,SAAS,CAAA;AAAA,EACpC;AAAA,EAEA,WAAA,GAAyD;AACvD,IAAA,MAAM,EAAE,OAAA,EAAS,OAAA,EAAQ,GAAI,KAAK,MAAA,CAAO,KAAA;AACzC,IAAA,MAAM,SAAA,GAA8B;AAAA,MAClC,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,CAAC,CAAA;AAAA,MAC3B,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,IAAA,CAAK,SAAS,QAAQ;AAAA,KAClD;AACA,IAAA,MAAM,MAAM,IAAA,CAAK,GAAA;AAAA,MACf,CAAA;AAAA,MACA,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,CAAO,aAAa,IAAA,CAAK,OAAA,CAAQ,YAAY,CAAC;AAAA,KAChE;AACA,IAAA,MAAM,SAAS,IAAA,CAAK,GAAA;AAAA,MAClB,KAAK,SAAA,CAAU,QAAA;AAAA,MACf,IAAA,CAAK,KAAK,IAAA,CAAK,MAAA,CAAO,aAAa,IAAA,CAAK,QAAA,CAAS,SAAS,CAAC;AAAA,KAC7D;AACA,IAAA,OAAO;AAAA,MACL,SAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,iBAAiB,CAAC,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,MAAM,CAAC;AAAA,KAC9C;AAAA,EACF;AAAA,EAEA,EAAA,CACE,KACA,EAAA,EACY;AACZ,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,EAAA,CAAG,GAAA,EAAK,EAAE,CAAA;AAAA,EAChC;AAAA,EAEA,GAAA,CACE,KACA,EAAA,EACM;AACN,IAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,EAAE,CAAA;AAAA,EAC1B;AAAA,EAEA,OAAA,GAAgB;AACd,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAA,CAAK,yBAAyB,MAAA,EAAO;AACrC,IAAA,IAAA,CAAK,UAAU,OAAA,EAAQ;AACvB,IAAA,IAAA,CAAK,QAAQ,OAAA,EAAQ;AACrB,IAAA,IAAA,CAAK,QAAQ,KAAA,EAAM;AAAA,EACrB;AAAA;AAAA,EAIQ,GAAA,GAAY;AAClB,IAAA,OAAO,KAAK,GAAA,EAAI;AAAA,EAClB;AAAA,EAEQ,UAAA,GAAa;AACnB,IAAA,OAAO,iBAAA;AAAA,MACL,IAAA,CAAK,MAAM,aAAA,EAAc;AAAA,MACzB,IAAA,CAAK,QAAA;AAAA,MACL,KAAK,GAAA,EAAI;AAAA,MACT,KAAK,QAAA;AAAS,KAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,QAAA,GAAqB;AAC3B,IAAA,IAAI,KAAK,KAAA,CAAM,WAAA,GAAc,MAAA,KAAW,CAAA,SAAU,EAAC;AACnD,IAAA,OAAO,EAAE,IAAA,EAAM,mBAAA,CAAoB,IAAA,CAAK,KAAK,CAAA,EAAE;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAA,CAAgB,OAAiC,MAAA,EAAc;AACrE,IAAA,MAAM,UAAA,GACJ,IAAA,KAAS,MAAA,GACL,IAAA,CAAK,cAAA,CAAe,KAAA;AAAA,MAClB,IAAA,CAAK,MAAM,WAAA,EAAY;AAAA,MACvB,IAAA,CAAK,MAAM,SAAA;AAAU,KACvB,GACA,aAAa,IAAA,CAAK,SAAA,CAAU,YAAY,IAAA,CAAK,KAAA,CAAM,aAAa,CAAA;AACtE,IAAA,IAAA,CAAK,SAAA,GAAY,gBAAA,CAAiB,UAAA,EAAY,IAAA,CAAK,OAAO,CAAA;AAC1D,IAAA,IAAA,CAAK,OAAO,YAAA,CAAa,IAAA,CAAK,SAAA,CAAU,aAAA,EAAe,KAAK,QAAQ,CAAA;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,uBAAA,GAAgC;AACtC,IAAA,IAAI,IAAA,CAAK,oBAAoB,MAAA,EAAQ;AACnC,MAAA,IAAA,CAAK,wBAAA,EAAyB;AAAA,IAChC,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,gBAAgB,eAAe,CAAA;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,QAAA,GAAiB;AACvB,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,IAAA,CAAK,QAAA,CAAS,YAAY,CAAA,EAAG;AACnD,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,aAAA,EAAc,KAAM,IAAA,EAAM;AACvC,MAAA,IAAA,CAAK,GAAA,EAAI;AACT,MAAA;AAAA,IACF;AACA,IAAA,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,IAAA,EAAM,IAAA,CAAK,QAAA,EAAU,KAAK,GAAA,EAAI,EAAG,IAAA,CAAK,QAAA,EAAU,CAAA;AACjE,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA;AAAA,EAGQ,cAAA,GAAuB;AAC7B,IAAA,IAAA,CAAK,SAAA,CAAU,UAAU,MAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,EAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,WAAA,GAA2B;AACjC,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,CAAC,EAAA,EAAI,EAAA,KAAO;AACjB,QAAA,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,EAAA,EAAI,EAAE,CAAA;AAC9B,QAAA,IAAA,CAAK,OAAO,YAAA,CAAa,IAAA,CAAK,SAAA,CAAU,aAAA,EAAe,KAAK,QAAQ,CAAA;AACpE,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB,CAAA;AAAA,MACA,MAAA,EAAQ,CAAC,MAAA,EAAQ,OAAA,KAAY;AAC3B,QAAA,IAAA,CAAK,OAAO,eAAA,CAAgB,MAAA,EAAQ,OAAA,EAAS,IAAA,CAAK,YAAY,CAAA;AAC9D,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB,CAAA;AAAA,MACA,QAAA,EAAU,CAAC,EAAA,KAAO;AAChB,QAAA,IAAA,CAAK,MAAA,CAAO,WAAA,CAAY,CAAA,EAAG,CAAC,EAAE,CAAA;AAC9B,QAAA,IAAA,CAAK,OAAO,YAAA,CAAa,IAAA,CAAK,SAAA,CAAU,aAAA,EAAe,KAAK,QAAQ,CAAA;AACpE,QAAA,IAAA,CAAK,cAAA,EAAe;AAAA,MACtB,CAAA;AAAA,MACA,OAAA,EAAS,CAAC,CAAA,EAAG,CAAA,KAAM;AAGjB,QAAA,IAAA,CAAK,cAAA,GAAiB,EAAE,CAAA,EAAG,CAAA,EAAE;AAC7B,QAAA,IAAA,CAAK,SAAA,CAAU,UAAU,SAAS,CAAA;AAAA,MACpC,CAAA;AAAA,MACA,OAAA,EAAS,CAAC,CAAA,EAAG,CAAA,EAAG,SAAS,IAAA,CAAK,OAAA,CAAQ,CAAA,EAAG,CAAA,EAAG,IAAI,CAAA;AAAA,MAChD,OAAO,MAAM;AACX,QAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AACtB,QAAA,IAAI,IAAA,CAAK,YAAY,IAAA,EAAM;AACzB,UAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,UAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,IAAI,CAAA;AAC/B,UAAA,IAAA,CAAK,SAAA,CAAU,UAAU,SAAS,CAAA;AAAA,QACpC;AAAA,MACF;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGQ,OAAA,CACN,CAAA,EACA,CAAA,EACA,IAAA,EACM;AACN,IAAA,MAAM,GAAA,GAAM,KAAK,OAAA,GAAU,OAAA,CAAQ,KAAK,OAAA,EAAS,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA;AACzD,IAAA,IAAI,GAAA,KAAQ,IAAA,EAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,SAAS,EAAE,GAAA,EAAK,SAAA,EAAW,IAAA,EAAM,CAAA;AAKrE,IAAA,IAAI,GAAA,EAAK,SAAS,SAAA,EAAW;AAC3B,MAAA,IAAA,CAAK,aAAA,CAAc,IAAI,MAAM,CAAA;AAC7B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,aAAA;AAAA,MACb,IAAA,CAAK,WAAA;AAAA,MACL,GAAA,KAAQ,IAAA,GAAO,KAAA,CAAM,GAAG,CAAA,GAAI,IAAA;AAAA,MAC5B,IAAA;AAAA,MACA,IAAA,CAAK;AAAA,KACP;AACA,IAAA,IAAI,OAAO,OAAA,EAAS;AAClB,MAAA,IAAA,CAAK,YAAY,KAAA,EAAM;AACvB,MAAA,KAAA,MAAW,MAAM,MAAA,CAAO,GAAA,EAAK,IAAA,CAAK,WAAA,CAAY,IAAI,EAAE,CAAA;AACpD,MAAA,IAAA,CAAK,QAAQ,IAAA,CAAK,iBAAA,EAAmB,EAAE,GAAA,EAAK,MAAA,CAAO,KAAK,CAAA;AACxD,MAAA,IAAA,CAAK,SAAA,CAAU,UAAU,SAAS,CAAA;AAAA,IACpC;AAAA,EACF;AAAA;AAAA,EAGQ,cAAc,MAAA,EAAyC;AAC7D,IAAA,IAAI,GAAA,GAAM,QAAA;AACV,IAAA,IAAI,GAAA,GAAM,CAAA,QAAA;AACV,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,IAAI,KAAA,CAAM,IAAA,GAAO,GAAA,EAAK,GAAA,GAAM,KAAA,CAAM,IAAA;AAClC,MAAA,IAAI,KAAA,CAAM,IAAA,GAAO,GAAA,EAAK,GAAA,GAAM,KAAA,CAAM,IAAA;AAAA,IACpC;AAEA,IAAA,IAAI,OAAO,QAAA,CAAS,GAAG,GAAG,IAAA,CAAK,WAAA,CAAY,KAAK,GAAG,CAAA;AAAA,EACrD;AAAA,EAEQ,kBAAA,GAA2B;AACjC,IAAA,IAAI,IAAA,CAAK,SAAS,QAAA,IAAY,CAAA,IAAK,EAAE,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,OAAA,GAAU,CAAA,CAAA,EAAI;AACrE,IAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,gBAAA,EAAkB,IAAA,CAAK,aAAa,CAAA;AAAA,EACxD;AAAA,EAEQ,UAAU,KAAA,EAAyB;AACzC,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,IAAI,MAAM,IAAA,EAAM,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,KAAK,QAAQ,CAAA;AAOhD,IAAA,IAAI,KAAA,CAAM,QAAQ,KAAA,CAAM,OAAA,OAAc,KAAA,CAAM,SAAA,EAAW,KAAK,WAAW,CAAA;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,KAAA,CAAM,OAA2B,IAAA,EAAwB;AAC/D,IAAA,IAAI,IAAA,CAAK,iBAAiB,MAAA,EAAW;AACnC,MAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AACd,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAA,GAAQ,YAAY,GAAA,EAAI;AAC9B,IAAA,IAAA,CAAK,KAAK,IAAI,CAAA;AACd,IAAA,IAAA,CAAK,YAAA,CAAa,EAAE,KAAA,EAAO,UAAA,EAAY,YAAY,GAAA,EAAI,GAAI,OAAO,CAAA;AAAA,EACpE;AAAA,EAEQ,QAAA,GAAiB;AACvB,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,IAAA,CAAK,QAAA;AACrC,IAAA,MAAM,EAAE,YAAA,EAAa,GAAI,IAAA,CAAK,OAAA;AAC9B,IAAA,MAAM,MAAM,IAAA,CAAK,GAAA;AACjB,IAAA,IAAA,CAAK,QAAA,CAAS,WAAW,MAAM,CAAA;AAE/B,IAAA,MAAM,KAAA,GAAQ,aAAA;AAAA,MACZ,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,CAAC,CAAA;AAAA,MAC3B,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,QAAQ,CAAA;AAAA,MAClC,IAAA,CAAK,OAAO,KAAA,CAAM,OAAA;AAAA,MAClB,gBAAA;AAAA,MACA,IAAA,CAAK;AAAA,KACP;AAIA,IAAA,MAAM,YAAY,IAAA,CAAK,GAAA,CAAI,GAAG,UAAA,CAAW,CAAA,EAAG,GAAG,CAAC,CAAA;AAChD,IAAA,MAAM,YAAA,GAA8B,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS;AAC5D,MAAA,MAAM,CAAA,GACJ,UAAA,CAAW,IAAA,CAAK,MAAA,CAAO,aAAA,CAAc,IAAA,CAAK,IAAI,CAAA,EAAG,GAAG,CAAA,GACpD,cAAA,CAAe,SAAS,CAAA;AAC1B,MAAA,OAAO;AAAA,QACL,EAAA,EAAI,CAAA;AAAA,QACJ,EAAA,EAAI,UAAA,CAAW,YAAA,EAAc,GAAG,CAAA;AAAA,QAChC,EAAA,EAAI,CAAA;AAAA,QACJ,EAAA,EAAI,UAAA,CAAW,SAAA,EAAW,GAAG;AAAA,OAC/B;AAAA,IACF,CAAC,CAAA;AACD,IAAA,IAAA,CAAK,SAAS,SAAA,CAAU;AAAA,MACtB,KAAA,EAAO,KAAK,KAAA,CAAM,aAAA;AAAA,MAClB,KAAA,EAAO,SAAA;AAAA,MACP,QAAA,EAAU;AAAA,KACX,CAAA;AAID,IAAA,MAAM,GAAA,GAA2B;AAAA,MAC/B,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,MAAM,IAAA,CAAK,KAAA;AAAA,MACX,UAAU,IAAA,CAAK,QAAA;AAAA,MACf,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,IAAA,EAAM,cAAA;AAAA,QACJ,IAAA,CAAK,MAAA;AAAA,QACL,IAAA,CAAK,QAAA;AAAA,QACL,KAAK,SAAA,CAAU,QAAA;AAAA,QACf;AAAA,OACF;AAAA,MACA,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,KAAK,IAAA,CAAK,GAAA;AAAA,MACV,YAAY,IAAA,CAAK,UAAA;AAAA,MACjB,qBAAqB,IAAA,CAAK,mBAAA;AAAA,MAC1B,mBAAmB,IAAA,CAAK,iBAAA;AAAA,MACxB,oBAAoB,IAAA,CAAK,kBAAA;AAAA,MACzB,kBAAkB,IAAA,CAAK;AAAA,KACzB;AACA,IAAA,MAAM,QAAA,GAAW,kBAAkB,GAAG,CAAA;AACtC,IAAA,MAAM,MAAA,GAAS,YAAY,GAAG,CAAA;AAI9B,IAAA,IAAA,CAAK,eAAe,CAAC,GAAG,SAAS,OAAA,EAAS,GAAG,OAAO,OAAO,CAAA;AAC3D,IAAA,IAAA,CAAK,OAAA,GAAU,YAAA,CAAa,IAAA,CAAK,YAAY,CAAA;AAE7C,IAAA,KAAA,MAAW,IAAA,IAAQ,SAAS,KAAA,EAAO;AACjC,MAAA,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU,SAAA,CAAU,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IAC9C;AACA,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/B,MAAA,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU,SAAA,CAAU,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IAC9C;AACA,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/B,MAAA,IAAA,CAAK,QAAA,CAAS,SAAA,CAAU,SAAA,CAAU,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IAC9C;AACA,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,UAAA,EAAY;AACpC,MAAA,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,cAAA,CAAe,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IACxD;AACA,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAO,MAAA,EAAQ;AAChC,MAAA,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,UAAA,CAAW,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IAC9C;AACA,IAAA,KAAA,MAAW,IAAA,IAAQ,SAAS,MAAA,EAAQ;AAClC,MAAA,IAAA,CAAK,QAAA,CAAS,QAAA,CAAS,UAAA,CAAW,IAAA,EAAM,GAAG,CAAC,CAAA;AAAA,IAC9C;AACA,IAAA,IAAA,CAAK,SAAS,UAAA,CAAW,SAAA,CAAU,QAAA,CAAS,KAAA,EAAO,GAAG,CAAC,CAAA;AAIvD,IAAA,IAAA,CAAK,QAAA,CAAS,QAAA;AAAA,MACZ,CAAA;AAAA,MACA,CAAA;AAAA,MACA,UAAA,CAAW,UAAU,GAAG,CAAA;AAAA,MACxB,UAAA,CAAW,cAAc,GAAG,CAAA;AAAA,MAC5B,KAAK,KAAA,CAAM;AAAA,KACb;AACA,IAAA,MAAM,YAAY,UAAA,CAAW,YAAA,EAAc,GAAG,CAAA,GAAI,eAAe,SAAS,CAAA;AAC1E,IAAA,IAAA,CAAK,SAAS,SAAA,CAAU;AAAA,MACtB,KAAA,EAAO,KAAK,KAAA,CAAM,aAAA;AAAA,MAClB,KAAA,EAAO,SAAA;AAAA,MACP,QAAA,EAAU;AAAA,QACR,EAAE,EAAA,EAAI,CAAA,EAAG,EAAA,EAAI,SAAA,EAAW,EAAA,EAAI,UAAA,CAAW,QAAA,EAAU,GAAG,CAAA,EAAG,EAAA,EAAI,SAAA;AAAU;AACvE,KACD,CAAA;AAED,IAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,IAAA,CAAK,KAAA,CAAM,YAAY,GAAG,CAAA;AAC/D,IAAA,IAAA,CAAK,SAAS,QAAA,CAAS;AAAA,MACrB,KAAA,EAAO,KAAK,KAAA,CAAM,eAAA;AAAA,MAClB,IAAA,EAAM,UAAA;AAAA,MACN,QAAA,EAAU,QAAA;AAAA,MACV,KAAA,EAAO,QAAA;AAAA,MACP,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,QAChC,CAAA,EAAG,WAAW,IAAA,CAAK,MAAA,CAAO,cAAc,IAAA,CAAK,IAAI,GAAG,GAAG,CAAA;AAAA,QACvD,CAAA,EAAG,UAAA,CAAW,YAAA,GAAe,IAAA,EAAM,GAAG,CAAA;AAAA,QACtC,MAAM,IAAA,CAAK;AAAA,OACb,CAAE;AAAA,KACH,CAAA;AACD,IAAA,IAAA,CAAK,SAAS,QAAA,CAAS;AAAA,MACrB,KAAA,EAAO,KAAK,KAAA,CAAM,eAAA;AAAA,MAClB,IAAA,EAAM,UAAA;AAAA,MACN,QAAA,EAAU,QAAA;AAAA,MACV,KAAA,EAAO,QAAA;AAAA,MACP,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,QAChC,CAAA,EAAG,WAAW,IAAA,CAAK,MAAA,CAAO,cAAc,IAAA,CAAK,IAAI,GAAG,GAAG,CAAA;AAAA,QACvD,CAAA,EAAG,UAAA,CAAW,YAAA,GAAe,IAAA,EAAM,GAAG,CAAA;AAAA,QACtC,MAAM,IAAA,CAAK;AAAA,OACb,CAAE;AAAA,KACH,CAAA;AAED,IAAA,IAAA,CAAK,QAAA,CAAS,SAAS,MAAM,CAAA;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,WAAA,GAAoB;AAC1B,IAAA,IAAA,CAAK,YAAA,EAAa;AAClB,IAAA,IAAA,CAAK,QAAA,CAAS,WAAW,SAAS,CAAA;AAElC,IAAA,MAAM,MAAM,IAAA,CAAK,GAAA;AACjB,IAAA,MAAM,aAAa,IAAA,CAAK,OAAA,KAAY,OAAO,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA,GAAI,IAAA;AAGjE,IAAA,MAAM,gBAAA,GACJ,KAAK,OAAA,EAAS,IAAA,KAAS,YAAY,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAA,GAAK,IAAA;AAC/D,IAAA,MAAM,kBAAA,GAAqB,kBAAA,CAAmB,IAAA,CAAK,WAAW,CAAA;AAE9D,IAAA,KAAA,MAAW,MAAA,IAAU,KAAK,YAAA,EAAc;AACtC,MAAA,MAAM,QAAQ,IAAA,CAAK,iBAAA;AAAA,QACjB,MAAA;AAAA,QACA,UAAA;AAAA,QACA,gBAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,IAAI,UAAU,IAAA,EAAM,IAAA,CAAK,aAAA,CAAc,MAAA,EAAQ,OAAO,GAAG,CAAA;AAAA,IAC3D;AAEA,IAAA,IAAA,CAAK,QAAA,CAAS,SAAS,SAAS,CAAA;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,iBAAA,CACN,MAAA,EACA,UAAA,EACA,gBAAA,EACA,kBAAA,EACe;AACf,IAAA,MAAM,GAAA,GAAM,UAAU,MAAM,CAAA;AAC5B,IAAA,MAAM,UACJ,GAAA,KAAQ,UAAA,IACP,qBAAqB,IAAA,IAAQ,cAAA,CAAe,QAAQ,gBAAgB,CAAA;AACvE,IAAA,IAAI,OAAA,EAAS,OAAO,IAAA,CAAK,KAAA,CAAM,UAAA;AAC/B,IAAA,MAAM,QAAA,GACJ,KAAK,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA,IACxB,iBAAA,CAAkB,QAAQ,kBAAkB,CAAA;AAC9C,IAAA,IAAI,QAAA,EAAU,OAAO,IAAA,CAAK,KAAA,CAAM,cAAA;AAChC,IAAA,OAAO,IAAA;AAAA,EACT;AAAA;AAAA,EAGQ,YAAA,GAAqB;AAC3B,IAAA,IAAI,IAAA,CAAK,cAAA,KAAmB,IAAA,IAAQ,IAAA,CAAK,YAAY,IAAA,EAAM;AAC3D,IAAA,MAAM,GAAA,GAAM,OAAA;AAAA,MACV,IAAA,CAAK,OAAA;AAAA,MACL,KAAK,cAAA,CAAe,CAAA;AAAA,MACpB,KAAK,cAAA,CAAe;AAAA,KACtB;AACA,IAAA,MAAM,OAAA,GAAU,GAAA,KAAQ,IAAA,GAAO,KAAA,CAAM,GAAG,CAAA,GAAI,IAAA;AAC5C,IAAA,MAAM,UAAU,IAAA,CAAK,OAAA,KAAY,OAAO,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA,GAAI,IAAA;AAC9D,IAAA,IAAI,YAAY,OAAA,EAAS;AACvB,MAAA,IAAA,CAAK,OAAA,GAAU,GAAA;AACf,MAAA,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,GAAG,CAAA;AAAA,IAChC;AAAA,EACF;AAAA;AAAA,EAGQ,aAAA,CACN,MAAA,EACA,KAAA,EACA,GAAA,EACM;AACN,IAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,MAAA,IAAA,CAAK,QAAA,CAAS,SAAA;AAAA,QACZ,SAAA;AAAA,UACE;AAAA,YACE,KAAA;AAAA,YACA,KAAA,EAAO,OAAO,KAAA,GAAQ,CAAA;AAAA,YACtB,QAAA,EAAU;AAAA,cACR,EAAE,EAAA,EAAI,MAAA,CAAO,EAAA,EAAI,EAAA,EAAI,MAAA,CAAO,CAAA,EAAG,EAAA,EAAI,MAAA,CAAO,EAAA,EAAI,EAAA,EAAI,MAAA,CAAO,CAAA;AAAE;AAC7D,WACF;AAAA,UACA;AAAA;AACF,OACF;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC9B,QAAA,IAAA,CAAK,QAAA,CAAS,SAAA;AAAA,UACZ,SAAA;AAAA,YACE,EAAE,OAAO,KAAA,EAAO,MAAA,CAAO,QAAQ,CAAA,EAAG,QAAA,EAAU,OAAO,QAAA,EAAS;AAAA,YAC5D;AAAA;AACF,SACF;AAAA,MACF;AACA,MAAA,IAAA,CAAK,QAAA,CAAS,SAAA;AAAA,QACZ,SAAA;AAAA,UACE,EAAE,KAAA,EAAO,MAAA,EAAQ,MAAA,CAAO,UAAA,GAAa,GAAG,KAAA,EAAO,CAAC,MAAA,CAAO,MAAM,CAAA,EAAE;AAAA,UAC/D;AAAA;AACF,OACF;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAA,CAAK,QAAA,CAAS,SAAA;AAAA,MACZ,SAAA;AAAA,QACE,EAAE,OAAO,KAAA,EAAO,MAAA,CAAO,QAAQ,CAAA,EAAG,QAAA,EAAU,OAAO,QAAA,EAAS;AAAA,QAC5D;AAAA;AACF,KACF;AACA,IAAA,MAAM,OAAO,CAAC,MAAA,CAAO,IAAA,EAAM,MAAA,CAAO,UAAU,CAAA,CAAE,MAAA;AAAA,MAC5C,CAAC,MAAqC,CAAA,KAAM;AAAA,KAC9C;AACA,IAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,MAAA,IAAA,CAAK,QAAA,CAAS,SAAA;AAAA,QACZ,SAAA;AAAA,UACE,EAAE,OAAO,MAAA,EAAQ,IAAA,CAAK,MAAM,KAAA,CAAM,UAAA,GAAa,CAAA,EAAG,KAAA,EAAO,IAAA,EAAK;AAAA,UAC9D;AAAA;AACF,OACF;AAAA,IACF;AACA,IAAA,IAAI,MAAA,CAAO,cAAc,MAAA,EAAW;AAClC,MAAA,IAAA,CAAK,QAAA,CAAS,cAAA;AAAA,QACZ,cAAA;AAAA,UACE;AAAA,YACE,KAAA;AAAA,YACA,IAAA,EAAM,OAAO,aAAA,GAAgB,CAAA;AAAA,YAC7B,KAAA,EAAO,CAAC,EAAE,GAAG,MAAA,CAAO,WAAW,KAAA,EAAO,cAAA,CAAe,MAAM,CAAA,EAAG;AAAA,WAChE;AAAA,UACA;AAAA;AACF,OACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,MAAM,GAAA,EAAwB;AACrC,EAAA,QAAQ,IAAI,IAAA;AAAM,IAChB,KAAK,SAAA;AACH,MAAA,OAAO,CAAA,QAAA,EAAW,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,CAAA;AAAA,IAClC,KAAK,OAAA;AACH,MAAA,OAAO,CAAA,MAAA,EAAS,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,CAAA;AAAA,IAC9B,KAAK,SAAA;AACH,MAAA,OAAO,CAAA,QAAA,EAAW,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA;AAE7D;AAGA,SAAS,UAAU,MAAA,EAA2B;AAC5C,EAAA,QAAQ,OAAO,IAAA;AAAM,IACnB,KAAK,SAAA;AACH,MAAA,OAAO,CAAA,QAAA,EAAW,MAAA,CAAO,OAAA,CAAQ,EAAE,CAAA,CAAA;AAAA,IACrC,KAAK,OAAA;AACH,MAAA,OAAO,CAAA,MAAA,EAAS,MAAA,CAAO,KAAA,CAAM,EAAE,CAAA,CAAA;AAAA,IACjC,KAAK,SAAA;AACH,MAAA,OAAO,CAAA,QAAA,EAAW,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAAA;AAEhE;AAEA,IAAM,kBAAA,GAAqB,UAAA;AAG3B,SAAS,mBAAmB,IAAA,EAAwC;AAClE,EAAA,MAAM,GAAA,uBAAU,GAAA,EAAY;AAC5B,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,GAAA,CAAI,UAAA,CAAW,kBAAkB,CAAA,EAAG;AACtC,MAAA,GAAA,CAAI,GAAA,CAAI,GAAA,CAAI,KAAA,CAAM,kBAAA,CAAmB,MAAM,CAAC,CAAA;AAAA,IAC9C;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,iBAAiB,MAAA,EAA6B;AACrD,EAAA,QAAQ,OAAO,IAAA;AAAM,IACnB,KAAK,SAAA;AACH,MAAA,OAAO,EAAC;AAAA,IACV,KAAK,OAAA;AACH,MAAA,OAAO,CAAC,MAAA,CAAO,KAAA,CAAM,QAAA,EAAU,MAAA,CAAO,MAAM,QAAQ,CAAA;AAAA,IACtD,KAAK,SAAA;AACH,MAAA,OAAO,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,QAAA,EAAU,CAAA,CAAE,QAAQ,CAAC,CAAA;AAAA;AAElE;AAEA,SAAS,cAAA,CAAe,QAAmB,SAAA,EAA4B;AACrE,EAAA,OAAO,gBAAA,CAAiB,MAAM,CAAA,CAAE,QAAA,CAAS,SAAS,CAAA;AACpD;AAEA,SAAS,iBAAA,CACP,QACA,GAAA,EACS;AACT,EAAA,OAAO,GAAA,CAAI,IAAA,GAAO,CAAA,IAAK,gBAAA,CAAiB,MAAM,CAAA,CAAE,IAAA,CAAK,CAAC,EAAA,KAAO,GAAA,CAAI,GAAA,CAAI,EAAE,CAAC,CAAA;AAC1E;AAGA,SAAS,eAAe,MAAA,EAGb;AACT,EAAA,MAAM,OAAO,MAAA,CAAO,QAAA,CAAS,MAAA,CAAO,QAAA,CAAS,SAAS,CAAC,CAAA;AACvD,EAAA,IAAI,SAAS,MAAA,IAAa,MAAA,CAAO,cAAc,MAAA,EAAW,OAAO,KAAK,EAAA,GAAK,CAAA;AAC3E,EAAA,OAAO,MAAA,CAAO,SAAA,CAAU,CAAA,IAAK,IAAA,CAAK,EAAA,GAAK,KAAK,EAAA,GAAK,CAAA,GAAI,CAAC,IAAA,CAAK,EAAA,GAAK,CAAA;AAClE;;;ACx9BA,IAAM,UAAA,GAAa,CAAA;AAGnB,IAAM,aAAA,uBAAiD,GAAA,EAAI;AAU3D,SAAS,cAAA,CACP,KACA,MAAA,EACW;AACX,EAAA,MAAM,SAAA,uBAA2B,GAAA,EAAI;AACrC,EAAA,KAAA,MAAW,MAAM,GAAA,EAAK,SAAA,CAAU,IAAI,EAAA,kBAAI,IAAI,KAAK,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,EAAW,CAAA,KAAc;AACrC,IAAA,MAAM,UAAA,GAAa,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA;AAClC,IAAA,IAAI,eAAe,MAAA,EAAW;AAC9B,IAAA,UAAA,CAAW,IAAI,CAAA,EAAA,CAAI,UAAA,CAAW,IAAI,CAAC,CAAA,IAAK,KAAK,CAAC,CAAA;AAAA,EAChD,CAAA;AACA,EAAA,KAAA,MAAW,EAAE,QAAA,EAAU,QAAA,EAAS,IAAK,MAAA,EAAQ;AAC3C,IAAA,IAAI,aAAa,QAAA,EAAU;AAC3B,IAAA,IAAA,CAAK,UAAU,QAAQ,CAAA;AACvB,IAAA,IAAA,CAAK,UAAU,QAAQ,CAAA;AAAA,EACzB;AACA,EAAA,OAAO,SAAA;AACT;AAMA,SAAS,YAAA,CACP,YACA,YAAA,EACe;AACf,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,MAAW,CAAC,WAAA,EAAa,CAAC,CAAA,IAAK,UAAA,EAAY;AACzC,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA;AACxC,IAAA,IAAI,QAAQ,MAAA,EAAW;AACvB,IAAA,WAAA,IAAe,GAAA,GAAM,CAAA;AACrB,IAAA,MAAA,IAAU,CAAA;AAAA,EACZ;AACA,EAAA,OAAO,MAAA,KAAW,CAAA,GAAI,IAAA,GAAO,WAAA,GAAc,MAAA;AAC7C;AAWA,SAAS,aAAA,CAAc,OAA0B,SAAA,EAA8B;AAC7E,EAAA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,EAAA,EAAI,KAAA,KAAU,CAAC,EAAA,EAAI,KAAK,CAAC,CAAC,CAAA;AAClE,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,UAAU,CAAA,IAAK,SAAA,EAAW;AACxC,IAAA,MAAM,GAAA,GAAM,YAAA,CAAa,GAAA,CAAI,EAAE,CAAA;AAC/B,IAAA,IAAI,QAAQ,MAAA,EAAW;AACvB,IAAA,KAAA,MAAW,CAAC,WAAA,EAAa,MAAM,CAAA,IAAK,UAAA,EAAY;AAC9C,MAAA,MAAM,YAAA,GAAe,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA;AACjD,MAAA,IAAI,iBAAiB,MAAA,EAAW;AAChC,MAAA,IAAA,IAAQ,IAAA,CAAK,GAAA,CAAI,GAAA,GAAM,YAAY,CAAA,GAAI,MAAA;AAAA,IACzC;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAEO,IAAM,UAAA,GAA6B;AAAA,EACxC,KAAA,CAAM,UAAU,MAAA,EAAkB;AAGhC,IAAA,MAAM,IAAA,GAAO,YAAA,CAAa,KAAA,CAAM,QAAA,EAAU,MAAM,CAAA;AAChD,IAAA,IAAI,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAE5B,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,IAAA,EAAM,MAAM,CAAA;AAU7C,IAAA,IAAI,KAAA,GAAQ,IAAA;AACZ,IAAA,IAAI,IAAA,GAAO,IAAA;AACX,IAAA,IAAI,QAAA,GAAW,aAAA,CAAc,IAAA,EAAM,SAAS,CAAA;AAC5C,IAAA,IAAI,UAAA,GAAa,EAAA;AACjB,IAAA,IAAI,WAAA,GAAc,IAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AAE/B,IAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,UAAA,EAAY,KAAA,EAAA,EAAS;AAC/C,MAAA,MAAM,YAAA,GAAe,IAAI,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,EAAA,EAAI,KAAA,KAAU,CAAC,EAAA,EAAI,KAAK,CAAC,CAAC,CAAA;AAIlE,MAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,CAAC,IAAI,KAAA,KAAU;AACtC,QAAA,MAAMC,IAAAA,GAAM,YAAA;AAAA,UACV,SAAA,CAAU,GAAA,CAAI,EAAE,CAAA,IAAK,aAAA;AAAA,UACrB;AAAA,SACF;AACA,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,GAAA,EAAKA,QAAO,KAAA,EAAM;AAAA,MACxC,CAAC,CAAA;AACD,MAAA,MAAA,CAAO,IAAA;AAAA,QAAK,CAAC,CAAA,EAAG,CAAA,KACd,CAAA,CAAE,GAAA,KAAQ,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,QAAQ,CAAA,CAAE;AAAA,OAChD;AACA,MAAA,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,EAAE,CAAA;AAEtC,MAAA,MAAM,IAAA,GAAO,aAAA,CAAc,KAAA,EAAO,SAAS,CAAA;AAC3C,MAAA,IAAI,OAAO,QAAA,EAAU;AACnB,QAAA,IAAA,GAAO,KAAA;AACP,QAAA,QAAA,GAAW,IAAA;AAAA,MACb;AAIA,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA;AAC1B,MAAA,IAAI,GAAA,KAAQ,WAAA,IAAe,GAAA,KAAQ,UAAA,EAAY;AAC/C,MAAA,UAAA,GAAa,WAAA;AACb,MAAA,WAAA,GAAc,GAAA;AAAA,IAChB;AAEA,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;ACpIO,IAAM,QAAA,GAA2B;AAAA,EACtC,KAAA,CAAM,UAAU,MAAA,EAAkB;AAChC,IAAA,MAAM,SAAyD,EAAC;AAChE,IAAA,MAAM,WAA8B,EAAC;AACrC,IAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,QAAA,CAAS,QAAQ,KAAA,EAAA,EAAS;AACpD,MAAA,MAAM,OAAA,GAAU,SAAS,KAAK,CAAA;AAC9B,MAAA,IAAI,MAAA,CAAO,QAAA,CAAS,OAAA,CAAQ,KAAK,CAAA,EAAG;AAClC,QAAA,MAAA,CAAO,IAAA,CAAK,EAAE,EAAA,EAAI,OAAA,CAAQ,IAAI,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAQ,KAAA,EAAO,CAAA;AAAA,MAC9D,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,KAAK,OAAO,CAAA;AAAA,MACvB;AAAA,IACF;AAEA,IAAA,MAAA,CAAO,IAAA;AAAA,MAAK,CAAC,CAAA,EAAG,CAAA,KACd,CAAA,CAAE,KAAA,KAAU,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,QAAQ,CAAA,CAAE;AAAA,KACxD;AAEA,IAAA,OAAO;AAAA,MACL,GAAG,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU,MAAM,EAAE,CAAA;AAAA,MACjC,GAAG,YAAA,CAAa,KAAA,CAAM,QAAA,EAAU,MAAM;AAAA,KACxC;AAAA,EACF;AACF;;;AC1BO,IAAM,OAAA,GAAU","file":"index.cjs","sourcesContent":["// Default layout: order elements by the time of their first event (DESIGN.md §7).\n//\n// Predictable, stable, cheap. Event-less elements have no first-event key and\n// sort after all elements that have events, in stable input order (§1).\n\nimport type { LayoutStrategy } from './types';\n\nexport const byFirstEvent: LayoutStrategy = {\n order(elements, events): string[] {\n const firstEventTime = new Map<string, number>();\n const note = (id: string, time: number) => {\n const current = firstEventTime.get(id);\n if (current === undefined || time < current) {\n firstEventTime.set(id, time);\n }\n };\n for (const event of events) {\n // An element's first event counts it as either endpoint.\n note(event.sourceId, event.time);\n if (event.targetId !== event.sourceId) note(event.targetId, event.time);\n }\n\n // Stable sort: ties and event-less elements keep input order; the explicit\n // index tiebreak documents that intent.\n return elements\n .map((element, index) => ({\n id: element.id,\n index,\n key: firstEventTime.get(element.id),\n }))\n .sort((a, b) => {\n if (a.key !== undefined && b.key !== undefined) {\n return a.key !== b.key ? a.key - b.key : a.index - b.index;\n }\n if (a.key !== undefined) return -1; // elements with events sort first\n if (b.key !== undefined) return 1;\n return a.index - b.index; // both event-less: stable input order\n })\n .map((entry) => entry.id);\n },\n};\n","// Stable-append ordering for streaming updates (DESIGN.md §7, §10).\n//\n// During streaming the default is *stable append*: existing rows keep their\n// position (no jarring reshuffle) and newly-arrived elements slot in at the end.\n// Unlike a `LayoutStrategy`, this needs the *prior* order, so it lives beside the\n// strategies as an engine helper rather than implementing the pure\n// `order(elements, events)` seam (§7 SRP).\n\nimport type { TimelineElement } from '../model/types';\n\n/**\n * Merge `elements` onto a `priorOrder`: keep the prior ids that still exist in\n * their existing order, then append current ids not already placed, in element\n * input order. Pure — ids vanished from `elements` are dropped. A full re-layout\n * is the opt-in alternative (re-run the configured `LayoutStrategy`).\n */\nexport function stableAppend(\n priorOrder: readonly string[],\n elements: readonly TimelineElement[],\n): string[] {\n const current = new Set(elements.map((element) => element.id));\n const placed = new Set<string>();\n const order: string[] = [];\n for (const id of priorOrder) {\n if (current.has(id) && !placed.has(id)) {\n order.push(id);\n placed.add(id);\n }\n }\n for (const element of elements) {\n if (!placed.has(element.id)) {\n order.push(element.id);\n placed.add(element.id);\n }\n }\n return order;\n}\n","// Built-in cluster strategies (DESIGN.md §6).\n//\n// The default is `bySourceTargetColumn`, composed from the element-pair and\n// pixel-column keys so same-direction events in the same column collapse. Day\n// bucketing uses integer division by the (fixed-length) UTC day, matching the\n// machine-stable UTC arithmetic the tick generator already relies on (§8) — no\n// locale or DST ambiguity, so it is golden-test stable.\n\nimport type { ClusterContext, ClusterStrategy } from './types';\nimport type { TimelineEvent } from '../model/types';\n\n/** Field separator that cannot appear in a key fragment, keeping keys injective. */\nconst SEP = '\u0000';\nconst MS_PER_DAY = 86_400_000;\n\n/** The pixel column an event falls in, binned by `minSeparationPx`. */\nfunction pixelColumn(event: TimelineEvent, ctx: ClusterContext): number {\n return Math.floor(ctx.timeToScreenX(event.time) / ctx.minSeparationPx);\n}\n\n/** `(sourceId, targetId)` — direction-aware element pair. */\nfunction elementPairKey(event: TimelineEvent): string {\n return `${event.sourceId}${SEP}${event.targetId}`;\n}\n\n/** Collapse every event sharing a pixel column, regardless of endpoints. */\nexport const byPixelColumn: ClusterStrategy = {\n key: (event, ctx) => String(pixelColumn(event, ctx)),\n};\n\n/** Collapse events between the same source and target (proximity-gated, §6). */\nexport const byElementPair: ClusterStrategy = {\n key: (event) => elementPairKey(event),\n};\n\n/** Collapse events sharing a UTC calendar day (proximity-gated, §6). */\nexport const byDay: ClusterStrategy = {\n key: (event) => String(Math.floor(event.time / MS_PER_DAY)),\n};\n\n/**\n * Default: `(sourceId, targetId, pixelColumn)` — same-direction events in the\n * same column collapse, so a dense fan-out between two lines reads as one marker.\n */\nexport const bySourceTargetColumn: ClusterStrategy = {\n key: (event, ctx) =>\n `${elementPairKey(event)}${SEP}${pixelColumn(event, ctx)}`,\n};\n","// Map an ordered id list to row indices and report content height (DESIGN.md §7).\n//\n// This is the \"engine maps order to row indices and y\" step kept out of the\n// strategy. Screen-Y for a row comes from Camera.rowToScreenY — never\n// re-derived here — preserving the single source of coordinate truth (§3).\n\nimport type { RowMetrics } from '../scale/camera';\n\nexport interface RowLayout {\n orderedIds: string[];\n rowIndexById: Map<string, number>;\n rowCount: number;\n /** Total stacked height of all rows in CSS px. */\n contentHeight: number;\n}\n\nexport function computeRowLayout(\n orderedIds: string[],\n metrics: RowMetrics,\n): RowLayout {\n const rowIndexById = new Map<string, number>();\n orderedIds.forEach((id, index) => rowIndexById.set(id, index));\n const rowCount = orderedIds.length;\n return {\n orderedIds,\n rowIndexById,\n rowCount,\n contentHeight: rowCount * (metrics.rowHeight + metrics.rowGap),\n };\n}\n","// Diagnostics sink contract + default sink (DESIGN.md §1 validation policy).\n//\n// Validation is lenient: invalid items are dropped, never thrown, and reported\n// through an injectable sink so the core stays decoupled from any logging\n// implementation (DIP) and the behaviour is unit-testable.\n\n/** Why an item was dropped during ingest. */\nexport type DiagnosticCode = 'invalid-time' | 'dangling-edge' | 'duplicate-id';\n\nexport interface Diagnostic {\n code: DiagnosticCode;\n kind: 'element' | 'event';\n /** Id of the offending item, when known. */\n id?: string;\n reason: string;\n}\n\nexport type OnDiagnostic = (d: Diagnostic) => void;\n\n/**\n * The default sink: forwards to `console.warn` in development builds and is a\n * no-op in production (`process.env.NODE_ENV === 'production'`). `process` is\n * accessed guardedly so the core stays SSR/browser-safe.\n */\nexport function createDefaultDiagnosticSink(): OnDiagnostic {\n // Read NODE_ENV via globalThis so the core needs no Node type definitions and\n // stays safe in browser/SSR bundles that have no `process` global.\n const env = (\n globalThis as { process?: { env?: Record<string, string | undefined> } }\n ).process?.env;\n if (env?.NODE_ENV === 'production') {\n return () => {};\n }\n return (d) => {\n const id = d.id !== undefined ? ` (${d.id})` : '';\n console.warn(`[timeline] dropped ${d.kind}${id}: ${d.reason}`);\n };\n}\n","// The single extent computation, reused by layout, rendering, and fit\n// (DESIGN.md §1, §5 \"Extent computation likewise lives in one place\").\n\nimport type { Time } from './types';\n\n/** The time span [minTime, maxTime] covered by an element (or the whole data). */\nexport interface Extent {\n minTime: Time;\n maxTime: Time;\n}\n\n/**\n * Widen an extent to include `t`. An absent extent starts as the single\n * instant `[t, t]`. Pure — returns a new value, never mutates `current`.\n */\nexport function widenExtent(current: Extent | undefined, t: Time): Extent {\n if (current === undefined) {\n return { minTime: t, maxTime: t };\n }\n return {\n minTime: t < current.minTime ? t : current.minTime,\n maxTime: t > current.maxTime ? t : current.maxTime,\n };\n}\n\n/**\n * The overall extent across every element, or `null` when there is no data.\n * Drives the degenerate-extent handling of §3.1 and `fit`.\n */\nexport function dataExtent(\n extents: ReadonlyMap<string, Extent>,\n): Extent | null {\n let result: Extent | null = null;\n for (const extent of extents.values()) {\n result =\n result === null\n ? { minTime: extent.minTime, maxTime: extent.maxTime }\n : {\n minTime: Math.min(result.minTime, extent.minTime),\n maxTime: Math.max(result.maxTime, extent.maxTime),\n };\n }\n return result;\n}\n","// Temporal index helpers for the sorted-by-time event array (DESIGN.md §5).\n//\n// Horizontal culling is \"binary search for [tStart, tEnd] → O(log n + k)\". These\n// pure helpers own that search and the per-element bucket build so the store and\n// its tests share one implementation (DRY); the store composes them in `reindex`.\n\nimport type { Time, TimelineEvent } from './types';\n\n/** Anything with a `time`, so callers can search a slice without copying. */\ninterface Timed {\n time: Time;\n}\n\n/**\n * First index `i` in `[0, events.length]` whose `events[i].time >= t`\n * (the half-open lower bound). `events` must be sorted ascending by `time`.\n */\nexport function lowerBound(events: readonly Timed[], t: Time): number {\n let lo = 0;\n let hi = events.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if ((events[mid] as Timed).time < t) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\n/**\n * First index `i` in `[0, events.length]` whose `events[i].time > t`\n * (the half-open upper bound). `events` must be sorted ascending by `time`.\n */\nexport function upperBound(events: readonly Timed[], t: Time): number {\n let lo = 0;\n let hi = events.length;\n while (lo < hi) {\n const mid = (lo + hi) >>> 1;\n if ((events[mid] as Timed).time <= t) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n}\n\n/**\n * Map each element id to the indices (into the sorted array) of the events that\n * touch it, in time order (§5). An inter-row event is bucketed under both\n * endpoints; a self-event (`sourceId === targetId`) is bucketed once.\n */\nexport function buildBuckets(\n sorted: readonly TimelineEvent[],\n): Map<string, number[]> {\n const buckets = new Map<string, number[]>();\n const add = (id: string, index: number) => {\n const bucket = buckets.get(id);\n if (bucket === undefined) buckets.set(id, [index]);\n else bucket.push(index);\n };\n for (let i = 0; i < sorted.length; i++) {\n const event = sorted[i] as TimelineEvent;\n add(event.sourceId, i);\n if (event.targetId !== event.sourceId) add(event.targetId, i);\n }\n return buckets;\n}\n","// The dataset store: owns the elements, events, and per-element extents, and is\n// the single owner of dataset validation (DESIGN.md §1, §5).\n//\n// The full-rebuild path (`setData`) and any future incremental path share one\n// insert routine: rebuild is \"clear, then apply the whole dataset through the\n// incremental insert routine.\" There is no second, parallel index builder.\n\nimport { createDefaultDiagnosticSink, type OnDiagnostic } from './diagnostics';\nimport { type Extent, dataExtent, widenExtent } from './extent';\nimport { buildBuckets, lowerBound, upperBound } from './temporalIndex';\nimport type {\n Time,\n TimelineData,\n TimelineElement,\n TimelineEvent,\n} from './types';\n\nexport interface DataStoreOptions {\n onDiagnostic?: OnDiagnostic;\n}\n\n/** Counts reported after a mutation (DESIGN.md §9 `dataChange`). */\nexport interface DataChangeCounts {\n added: number;\n removed: number;\n updated: number;\n}\n\nexport class DataStore<TData = unknown> {\n private readonly onDiagnostic: OnDiagnostic;\n\n private elements: TimelineElement<TData>[] = [];\n private elementById = new Map<string, TimelineElement<TData>>();\n /** Events sorted ascending by `time` (DESIGN.md §5); see {@link reindex}. */\n private events: TimelineEvent<TData>[] = [];\n private eventById = new Map<string, TimelineEvent<TData>>();\n private extents = new Map<string, Extent>();\n /** Element id → indices into {@link events}, in time order (§5). */\n private eventIndicesByElement = new Map<string, number[]>();\n /** Per-event insertion order, the stable tiebreak for equal-time events. */\n private seq = new Map<TimelineEvent<TData>, number>();\n /**\n * Monotonic source for {@link seq}. Never reset except by {@link clear}, so\n * an event inserted after a removal still sorts *after* survivors at the same\n * time — using `events.length` would recycle a live seq and corrupt the order.\n */\n private seqCounter = 0;\n\n constructor(options: DataStoreOptions = {}) {\n this.onDiagnostic = options.onDiagnostic ?? createDefaultDiagnosticSink();\n }\n\n /**\n * Full replace: clear, then apply the whole dataset through the same insert\n * routines used by (future) incremental updates (§5). Elements are inserted\n * before events so edges can reference any element in the batch.\n */\n setData(data: TimelineData<TData>): DataChangeCounts {\n this.clear();\n let added = 0;\n for (const element of data.elements) {\n if (this.insertElement(element)) added++;\n }\n for (const event of data.events) {\n if (this.insertEvent(event)) added++;\n }\n this.reindex();\n return { added, removed: 0, updated: 0 };\n }\n\n /**\n * Incrementally insert events (DESIGN.md §10). Each row runs through the same\n * validated {@link insertEvent} as `setData` (lenient: invalid rows drop), then\n * a single {@link reindex} re-sorts and rebuilds buckets. Appending a batch and\n * re-sorting the mostly-sorted array is the §10 \"single merge\" in practice — no\n * parallel index builder (the §5 single-build-path invariant).\n */\n addEvents(events: readonly TimelineEvent<TData>[]): DataChangeCounts {\n let added = 0;\n for (const event of events) {\n if (this.insertEvent(event)) added++;\n }\n if (added > 0) this.reindex();\n return { added, removed: 0, updated: 0 };\n }\n\n /**\n * Incrementally insert elements with stable-append semantics (DESIGN.md §10):\n * appended in input order, existing elements untouched. Duplicates drop\n * leniently. Events are unchanged, so no reindex is needed.\n */\n addElements(elements: readonly TimelineElement<TData>[]): DataChangeCounts {\n let added = 0;\n for (const element of elements) {\n if (this.insertElement(element)) added++;\n }\n return { added, removed: 0, updated: 0 };\n }\n\n /**\n * Remove events by id (DESIGN.md §10). Unknown ids are ignored (lenient).\n * Extents shrink, so the touched elements' extents are recomputed from their\n * surviving events after the buckets are rebuilt by {@link reindex}.\n */\n removeEvents(ids: readonly string[]): DataChangeCounts {\n const affected = new Set<string>();\n let removed = 0;\n for (const id of ids) {\n const event = this.eventById.get(id);\n if (event === undefined) continue;\n this.eventById.delete(id);\n this.seq.delete(event);\n affected.add(event.sourceId);\n affected.add(event.targetId);\n removed++;\n }\n if (removed === 0) return { added: 0, removed: 0, updated: 0 };\n\n this.events = this.events.filter((e) => this.eventById.has(e.id));\n this.reindex();\n for (const id of affected) this.recomputeExtentFor(id);\n return { added: 0, removed, updated: 0 };\n }\n\n /**\n * Patch an element in place (DESIGN.md §10): style/label/icon/order overrides\n * without a full rebuild. The `id` is immutable. Unknown ids are a lenient\n * no-op. Extents are event-derived, so they are unaffected.\n *\n * Note: patching `order` only changes row position under the `explicit`\n * layout with `streamingLayout: 'full'`; the default stable-append streaming\n * layout deliberately never reshuffles existing rows (§7).\n */\n updateElement(\n id: string,\n patch: Partial<TimelineElement<TData>>,\n ): DataChangeCounts {\n const existing = this.elementById.get(id);\n if (existing === undefined) return { added: 0, removed: 0, updated: 0 };\n const slot = this.elements.indexOf(existing);\n // `elementById` and `elements` are kept in sync, so this is always >= 0;\n // guard defensively rather than silently writing an out-of-range index.\n if (slot === -1) return { added: 0, removed: 0, updated: 0 };\n const updated: TimelineElement<TData> = { ...existing, ...patch, id };\n this.elements[slot] = updated;\n this.elementById.set(id, updated);\n return { added: 0, removed: 0, updated: 1 };\n }\n\n /**\n * Recompute one element's extent from its surviving events (§5). Reads the\n * rebuilt bucket; an event-less element has no extent and is removed.\n */\n private recomputeExtentFor(id: string): void {\n const indices = this.eventIndicesByElement.get(id);\n if (indices === undefined || indices.length === 0) {\n this.extents.delete(id);\n return;\n }\n let extent: Extent | undefined;\n for (const index of indices) {\n const event = this.events[index] as TimelineEvent<TData>;\n extent = widenExtent(extent, event.time);\n }\n if (extent !== undefined) this.extents.set(id, extent);\n }\n\n private clear(): void {\n this.elements = [];\n this.elementById.clear();\n this.events = [];\n this.eventById.clear();\n this.extents.clear();\n this.eventIndicesByElement.clear();\n this.seq.clear();\n this.seqCounter = 0;\n }\n\n /**\n * Finalise the derived event indexes from the validated events (§5): sort by\n * `time` (stable on the insertion `seq`, so equal-time order is deterministic\n * across engines), then build the per-element buckets in one pass. This is the\n * single index-build path — the future incremental `addEvents` (§10) re-enters\n * here rather than maintaining a parallel builder.\n */\n private reindex(): void {\n this.events.sort((a, b) => {\n if (a.time !== b.time) return a.time - b.time;\n return (this.seq.get(a) ?? 0) - (this.seq.get(b) ?? 0);\n });\n this.eventIndicesByElement = buildBuckets(this.events);\n }\n\n private insertElement(element: TimelineElement<TData>): boolean {\n if (this.elementById.has(element.id)) {\n this.onDiagnostic({\n code: 'duplicate-id',\n kind: 'element',\n id: element.id,\n reason: 'duplicate element id',\n });\n return false;\n }\n this.elements.push(element);\n this.elementById.set(element.id, element);\n return true;\n }\n\n private insertEvent(event: TimelineEvent<TData>): boolean {\n if (!Number.isFinite(event.time)) {\n this.onDiagnostic({\n code: 'invalid-time',\n kind: 'event',\n id: event.id,\n reason: 'time is not a finite number',\n });\n return false;\n }\n if (this.eventById.has(event.id)) {\n this.onDiagnostic({\n code: 'duplicate-id',\n kind: 'event',\n id: event.id,\n reason: 'duplicate event id',\n });\n return false;\n }\n if (\n !this.elementById.has(event.sourceId) ||\n !this.elementById.has(event.targetId)\n ) {\n this.onDiagnostic({\n code: 'dangling-edge',\n kind: 'event',\n id: event.id,\n reason: 'sourceId or targetId references an unknown element',\n });\n return false;\n }\n\n this.seq.set(event, this.seqCounter++);\n this.events.push(event);\n this.eventById.set(event.id, event);\n // An event widens both endpoints' extents; a self-event (source === target)\n // widens its single element's extent once.\n this.extents.set(\n event.sourceId,\n widenExtent(this.extents.get(event.sourceId), event.time),\n );\n if (event.targetId !== event.sourceId) {\n this.extents.set(\n event.targetId,\n widenExtent(this.extents.get(event.targetId), event.time),\n );\n }\n return true;\n }\n\n getElements(): readonly TimelineElement<TData>[] {\n return this.elements;\n }\n\n getEvents(): readonly TimelineEvent<TData>[] {\n return this.events;\n }\n\n /**\n * The events whose `time` falls in `[tStart, tEnd]` (inclusive), via binary\n * search over the sorted array — O(log n + k) (§5). Used by the renderer for\n * horizontal culling instead of a linear scan.\n */\n getEventsInRange(tStart: Time, tEnd: Time): readonly TimelineEvent<TData>[] {\n if (tEnd < tStart) return [];\n const lo = lowerBound(this.events, tStart);\n const hi = upperBound(this.events, tEnd);\n return this.events.slice(lo, hi);\n }\n\n /**\n * Indices into {@link getEvents} of the events touching `id`, in time order\n * (§5). Empty for an unknown or event-less element.\n */\n getEventIndicesForElement(id: string): readonly number[] {\n return this.eventIndicesByElement.get(id) ?? [];\n }\n\n getElementById(id: string): TimelineElement<TData> | undefined {\n return this.elementById.get(id);\n }\n\n getExtent(id: string): Extent | undefined {\n return this.extents.get(id);\n }\n\n getExtents(): ReadonlyMap<string, Extent> {\n return this.extents;\n }\n\n /** Overall extent across all elements, or `null` when empty (§3.1). */\n getDataExtent(): Extent | null {\n return dataExtent(this.extents);\n }\n}\n","// The per-frame clustering pass (DESIGN.md §6).\n//\n// Pure: groups a *visible* event slice (already time-sorted by the temporal\n// index, §5) by strategy key, then sweeps each group merging consecutive events\n// that render within `minSeparationPx`. No precomputation and no persisted state,\n// so live updates stay cheap and \"expand on zoom-in\" is automatic — zooming in\n// pushes neighbours apart until every group is singletons again. Cost is linear\n// in the visible slice, the accepted O(n) stress case at full zoom-out.\n\nimport type { Cluster, ClusterContext, ClusterStrategy } from './types';\nimport type { TimelineEvent } from '../model/types';\n\n/**\n * Collapse `events` into clusters. Input must be ascending by `time` (the\n * renderer passes the temporal-index slice), which — since `timeToScreenX` is\n * monotonic in time — keeps each group ascending in screen-x for the sweep.\n * Single-event clusters are returned as-is for the renderer's ordinary path.\n */\nexport function clusterEvents<TData>(\n events: readonly TimelineEvent<TData>[],\n strategy: ClusterStrategy,\n ctx: ClusterContext,\n): Cluster<TData>[] {\n // Group by key, preserving the incoming (time) order within each group.\n const groups = new Map<string, TimelineEvent<TData>[]>();\n for (const event of events) {\n const key = strategy.key(event, ctx);\n const group = groups.get(key);\n if (group === undefined) groups.set(key, [event]);\n else group.push(event);\n }\n\n const clusters: Cluster<TData>[] = [];\n for (const group of groups.values()) {\n // Proximity sweep: extend the current run while consecutive events render\n // within minSeparationPx, otherwise flush and start a new run.\n let run: TimelineEvent<TData>[] = [];\n let prevX = 0;\n for (const event of group) {\n const x = ctx.timeToScreenX(event.time);\n if (run.length === 0 || x - prevX <= ctx.minSeparationPx) {\n run.push(event);\n } else {\n clusters.push({ events: run });\n run = [event];\n }\n prevX = x;\n }\n if (run.length > 0) clusters.push({ events: run });\n }\n return clusters;\n}\n","// Style-keyed batch accumulators (DESIGN.md §4 \"batch by style\").\n//\n// Builders group primitives that share a colour/width/font into one spec so the\n// renderer issues a single path/fill per group, minimising context state\n// changes. These helpers are the one place a batch key is formed, keeping the\n// keying consistent across the elementLines and arrows builders (DRY).\n\nimport type { ArrowheadSpec, LabelSpec, LineSpec, NodeSpec } from './specs';\n\nexport function lineBatch(\n map: Map<string, LineSpec>,\n color: string,\n width: number,\n): LineSpec {\n const key = `${color}|${width}`;\n let batch = map.get(key);\n if (batch === undefined) {\n batch = { color, width, segments: [] };\n map.set(key, batch);\n }\n return batch;\n}\n\nexport function nodeBatch(\n map: Map<string, NodeSpec>,\n color: string,\n radius: number,\n): NodeSpec {\n const key = `${color}|${radius}`;\n let batch = map.get(key);\n if (batch === undefined) {\n batch = { color, radius, items: [] };\n map.set(key, batch);\n }\n return batch;\n}\n\nexport function arrowheadBatch(\n map: Map<string, ArrowheadSpec>,\n color: string,\n size: number,\n): ArrowheadSpec {\n const key = `${color}|${size}`;\n let batch = map.get(key);\n if (batch === undefined) {\n batch = { color, size, items: [] };\n map.set(key, batch);\n }\n return batch;\n}\n\nexport function labelBatch(\n map: Map<string, LabelSpec>,\n color: string,\n font: string,\n align: LabelSpec['align'] = 'left',\n baseline: LabelSpec['baseline'] = 'middle',\n): LabelSpec {\n // Alignment is part of the key: centered marker labels (§1) and left-anchored\n // event labels (§9) share a colour/font but must not land in the same path.\n const key = `${color}|${font}|${align}|${baseline}`;\n let batch = map.get(key);\n if (batch === undefined) {\n batch = { color, font, baseline, align, items: [] };\n map.set(key, batch);\n }\n return batch;\n}\n","// Vertical arrow risers with \"hop\" arcs over crossed lines (DESIGN.md §4, §16).\n//\n// An event riser is a vertical line between the source and target rows. Where it\n// crosses an *intermediary* element line (a row strictly between source and\n// target whose line is present at the event's x), it should visibly jump over it\n// — the wire-crossing \"bridge\" notation — to read as passing above the line.\n//\n// The Renderer seam exposes only straight-line batches (§4), so each hop is a\n// small semicircle approximated by a short polyline. This keeps the backend-free\n// seam unchanged: the result is just more `SpecSegment`s drawn via `drawLines`.\n//\n// Pure geometry in CSS pixels; reused for the line batch, the hit-test target,\n// and the overlay highlight from the same coordinates (DRY).\n\nimport type { SpecSegment } from './specs';\n\n/** Polyline segments approximating one hop semicircle. */\nconst HOP_ARC_STEPS = 6;\n\n/**\n * A vertical riser at `x` from `yFrom` to `yTo`, bulging +x by a semicircular hop\n * of radius `hopRadius` at each y in `crossings`. With no crossings it is a single\n * straight segment. Crossings are expected strictly between the endpoints (the\n * caller derives them from intermediary rows), so hops never touch the ends.\n */\nexport function buildRiserSegments(\n x: number,\n yFrom: number,\n yTo: number,\n crossings: readonly number[],\n hopRadius: number,\n): SpecSegment[] {\n if (crossings.length === 0 || hopRadius <= 0) {\n return [{ x1: x, y1: yFrom, x2: x, y2: yTo }];\n }\n\n const dir = yTo >= yFrom ? 1 : -1;\n // Walk the crossings in travel order so the polyline is monotonic along y.\n const ordered = [...crossings].sort((a, b) => dir * (a - b));\n\n const points: { x: number; y: number }[] = [{ x, y: yFrom }];\n for (const cy of ordered) {\n const entryY = cy - dir * hopRadius;\n const exitY = cy + dir * hopRadius;\n points.push({ x, y: entryY });\n // Semicircle centred at (x, cy), bulging +x: theta 0→π maps entry→exit.\n for (let s = 1; s < HOP_ARC_STEPS; s++) {\n const theta = (Math.PI * s) / HOP_ARC_STEPS;\n points.push({\n x: x + hopRadius * Math.sin(theta),\n y: cy - dir * hopRadius * Math.cos(theta),\n });\n }\n points.push({ x, y: exitY });\n }\n points.push({ x, y: yTo });\n\n const segments: SpecSegment[] = [];\n for (let i = 1; i < points.length; i++) {\n const a = points[i - 1];\n const b = points[i];\n if (a === undefined || b === undefined) continue;\n segments.push({ x1: a.x, y1: a.y, x2: b.x, y2: b.y });\n }\n return segments;\n}\n","// Directed event arrows (DESIGN.md §1, §4, §5, §6, §16).\n//\n// Each event is an orthogonal arrow at a single instant: a vertical riser at the\n// event time between the source and target rows, a node dot at the source, and a\n// direction-aware arrowhead at the target. A self-event (source === target) is a\n// small rectangular half-loop on the element's own line. Risers sharing a pixel\n// column are spread a few px (sub-lane offset, §16).\n//\n// Horizontal culling is a binary search over the time-sorted index (§5), not a\n// linear scan: only events whose time falls in the (margin-widened) visible\n// window are considered, then the §5 row-interval test drops those whose riser\n// misses the visible band. Survivors are collapsed by the clustering pass (§6)\n// — dense same-key runs become a single count marker — and per-event labels are\n// suppressed below the label-LOD zoom threshold.\n//\n// Pure: works in CSS pixels and returns specs; the engine snaps to device px.\n\nimport { clusterEvents } from '../cluster/cluster';\nimport type { ClusterContext } from '../cluster/types';\nimport { arrowheadBatch, labelBatch, lineBatch, nodeBatch } from './batch';\nimport { buildRiserSegments } from './riser';\nimport type {\n ArrowheadSpec,\n BuildContext,\n HitTarget,\n LabelSpec,\n LineSpec,\n NodeSpec,\n} from './specs';\nimport type { EventStyle, TimelineEvent } from '../model/types';\n\n/** Horizontal pixels a riser is nudged per event sharing its pixel column. */\nconst SUB_LANE_STEP_PX = 2;\n/** Cap on the sub-lane spread; residual overlap is accepted (§16). */\nconst SUB_LANE_MAX = 4;\n/** Gap between the riser/marker and its label. */\nconst EVENT_LABEL_GAP_PX = 4;\n/** Slack each side for the horizontal cull (arrowhead/node/self-loop extent). */\nconst HORIZONTAL_MARGIN_PX = 48;\n/** Extra radius a cluster marker gets over an ordinary source dot. */\nconst CLUSTER_MARKER_BONUS_PX = 2;\n/** Radius of the semicircular hop a riser makes over a crossed line (§16). */\nconst HOP_RADIUS_PX = 4;\n/** Skip hop computation beyond this row span (perf guard, §13); draw straight. */\nconst MAX_HOP_SPAN_ROWS = 24;\n/** Pointing straight down / up in screen space (y-down); risers are vertical. */\nconst ANGLE_DOWN = Math.PI / 2;\nconst ANGLE_UP = -Math.PI / 2;\n\n/**\n * Deterministic sub-lane nudge for the `k`-th event in a pixel column (§16).\n * Stable because events are scanned in (time, insertion) order; capped to bound\n * fan-out.\n */\nexport function subLaneOffset(k: number): number {\n return Math.min(k, SUB_LANE_MAX) * SUB_LANE_STEP_PX;\n}\n\n/** Mutable per-frame accumulators shared by the single-arrow and cluster paths. */\ninterface Batches<TData> {\n lines: Map<string, LineSpec>;\n nodes: Map<string, NodeSpec>;\n arrowheads: Map<string, ArrowheadSpec>;\n labels: Map<string, LabelSpec>;\n targets: HitTarget<TData>[];\n /** Count of risers already placed per rounded pixel column (sub-lane keying). */\n columnCounts: Map<number, number>;\n}\n\nexport interface ArrowsResult<TData = unknown> {\n /** Risers and self-loop glyphs. */\n lines: LineSpec[];\n nodes: NodeSpec[];\n arrowheads: ArrowheadSpec[];\n labels: LabelSpec[];\n /** Identity-carrying arrow/cluster geometry for hit-testing (§5, §6). */\n targets: HitTarget<TData>[];\n}\n\nexport function buildArrows<TData>(\n ctx: BuildContext<TData>,\n): ArrowsResult<TData> {\n const { camera, viewport, lod, clustering } = ctx;\n\n const batches: Batches<TData> = {\n lines: new Map(),\n nodes: new Map(),\n arrowheads: new Map(),\n labels: new Map(),\n targets: [],\n columnCounts: new Map(),\n };\n\n // Horizontal cull via the temporal index (§5), widened so an arrowhead or\n // self-loop just off either edge is still drawn. The window is derived through\n // the Camera, never raw pxPerMs (§3).\n const tStart = camera.screenXToTime(-HORIZONTAL_MARGIN_PX);\n const tEnd = camera.screenXToTime(viewport.cssWidth + HORIZONTAL_MARGIN_PX);\n const windowEvents = ctx.data.getEventsInRange(tStart, tEnd);\n\n // Vertical cull (§5 row-interval test): keep an arrow unless the rows it spans\n // miss the band entirely, so a riser crossing the band with both endpoints\n // off-screen is retained.\n const visible: TimelineEvent<TData>[] = [];\n for (const event of windowEvents) {\n const rows = rowSpan(ctx, event);\n if (rows === null) continue;\n if (rows.hi < ctx.band.firstRow || rows.lo > ctx.band.lastRow) continue;\n visible.push(event);\n }\n\n const labelsOn = camera.state.pxPerMs >= lod.eventLabelMinPxPerMs;\n\n if (clustering.enabled) {\n const clusterCtx: ClusterContext = {\n minSeparationPx: clustering.minSeparationPx,\n timeToScreenX: (t) => camera.timeToScreenX(t),\n };\n for (const cluster of clusterEvents(\n visible,\n clustering.strategy,\n clusterCtx,\n )) {\n const [first] = cluster.events;\n if (cluster.events.length === 1 && first !== undefined) {\n addSingleArrow(batches, ctx, first, labelsOn);\n } else {\n addCluster(batches, ctx, cluster.events);\n }\n }\n } else {\n for (const event of visible) addSingleArrow(batches, ctx, event, labelsOn);\n }\n\n return {\n lines: [...batches.lines.values()],\n nodes: [...batches.nodes.values()],\n arrowheads: [...batches.arrowheads.values()],\n labels: [...batches.labels.values()],\n targets: batches.targets,\n };\n}\n\n/** The inclusive row interval an event spans, or `null` if an endpoint is unrowed. */\nfunction rowSpan<TData>(\n ctx: BuildContext<TData>,\n event: TimelineEvent<TData>,\n): { lo: number; hi: number; sourceRow: number; targetRow: number } | null {\n const sourceRow = ctx.rowLayout.rowIndexById.get(event.sourceId);\n const targetRow = ctx.rowLayout.rowIndexById.get(event.targetId);\n if (sourceRow === undefined || targetRow === undefined) return null;\n return {\n lo: Math.min(sourceRow, targetRow),\n hi: Math.max(sourceRow, targetRow),\n sourceRow,\n targetRow,\n };\n}\n\n/** Draw one event as an ordinary arrow (riser + node + arrowhead, or self-loop). */\nfunction addSingleArrow<TData>(\n batches: Batches<TData>,\n ctx: BuildContext<TData>,\n event: TimelineEvent<TData>,\n labelsOn: boolean,\n): void {\n const rows = rowSpan(ctx, event);\n if (rows === null) return;\n const { camera, theme } = ctx;\n const halfRow = theme.rowHeight / 2;\n\n const baseX = camera.timeToScreenX(event.time);\n const column = Math.round(baseX);\n const k = batches.columnCounts.get(column) ?? 0;\n batches.columnCounts.set(column, k + 1);\n const x = baseX + subLaneOffset(k);\n\n // Resolve the full §11 style once per event (theme → resolver → .style).\n const style = ctx.resolveEventStyle(event);\n const color = style.arrowColor;\n const width = style.arrowWidth;\n const size = style.arrowheadSize;\n const radius = style.nodeRadius;\n const labelText = labelsOn ? ctx.formatEventLabel(event) : undefined;\n\n if (event.sourceId === event.targetId) {\n const y = camera.rowToScreenY(rows.sourceRow) + halfRow;\n addSelfLoop(batches, { color, width, size, radius }, x, y, event);\n if (labelText) {\n pushEventLabel(batches.labels, labelText, style, {\n x: x + size * 2 + EVENT_LABEL_GAP_PX,\n y,\n });\n }\n return;\n }\n\n const ySource = camera.rowToScreenY(rows.sourceRow) + halfRow;\n const yTargetCenter = camera.rowToScreenY(rows.targetRow) + halfRow;\n const dir = yTargetCenter > ySource ? 1 : -1;\n\n // Land at the near edge of the target line's thickness (§1): resolve the\n // target element's line width so the arrowhead tip stops on the edge, and the\n // riser ends at the arrowhead base rather than piercing the line. A dot then\n // marks the landing point on the target line (mirrors the source dot).\n const targetEl = ctx.data.getElementById(event.targetId);\n const targetLineWidth = targetEl\n ? ctx.resolveElementStyle(targetEl).lineWidth\n : theme.element.lineWidth;\n const nearEdge = yTargetCenter - dir * (targetLineWidth / 2);\n const arrowheadAnchorY = nearEdge - dir * size;\n\n // Hop over any intermediary element lines the riser crosses (§16).\n const crossings = intermediaryCrossings(ctx, rows, event.time);\n const segments = buildRiserSegments(\n x,\n ySource,\n arrowheadAnchorY,\n crossings,\n HOP_RADIUS_PX,\n );\n lineBatch(batches.lines, color, width).segments.push(...segments);\n\n const nodes = nodeBatch(batches.nodes, color, radius);\n nodes.items.push({ x, y: ySource });\n nodes.items.push({ x, y: yTargetCenter });\n arrowheadBatch(batches.arrowheads, color, size).items.push({\n x,\n y: arrowheadAnchorY,\n angle: dir > 0 ? ANGLE_DOWN : ANGLE_UP,\n });\n batches.targets.push({\n kind: 'event',\n event,\n segments,\n arrowhead: { x, y: arrowheadAnchorY },\n node: { x, y: ySource },\n targetNode: { x, y: yTargetCenter },\n width,\n arrowheadSize: size,\n });\n if (labelText) {\n pushEventLabel(batches.labels, labelText, style, {\n x: x + width / 2 + EVENT_LABEL_GAP_PX,\n y: (ySource + yTargetCenter) / 2,\n });\n }\n}\n\n/**\n * Screen-Y of each intermediary element line the riser crosses: rows strictly\n * between source and target whose element line is present at the event's time.\n * Bounded by {@link MAX_HOP_SPAN_ROWS} so a tall riser never scans the whole\n * column (§13). The line's small lead pad is ignored — the extent test is close\n * enough and the hop is cosmetic.\n */\nfunction intermediaryCrossings<TData>(\n ctx: BuildContext<TData>,\n rows: { lo: number; hi: number },\n time: number,\n): number[] {\n if (rows.hi - rows.lo <= 1 || rows.hi - rows.lo > MAX_HOP_SPAN_ROWS)\n return [];\n const { rowLayout, data, camera, theme } = ctx;\n const halfRow = theme.rowHeight / 2;\n const ys: number[] = [];\n for (let r = rows.lo + 1; r < rows.hi; r++) {\n const id = rowLayout.orderedIds[r];\n if (id === undefined) continue;\n const extent = data.getExtent(id);\n if (extent === undefined) continue;\n if (time < extent.minTime || time > extent.maxTime) continue;\n ys.push(camera.rowToScreenY(r) + halfRow);\n }\n return ys;\n}\n\n/**\n * Draw a collapsed cluster (§6): a riser spanning the members' row interval, a\n * count marker at its midpoint, and an \"×N\" label. Direction is ambiguous once\n * many events merge, so no arrowhead is drawn; the marker carries the meaning.\n */\nfunction addCluster<TData>(\n batches: Batches<TData>,\n ctx: BuildContext<TData>,\n events: TimelineEvent<TData>[],\n): void {\n const { camera, theme } = ctx;\n const halfRow = theme.rowHeight / 2;\n\n let minRow = Infinity;\n let maxRow = -Infinity;\n let sumX = 0;\n let placed = 0;\n for (const event of events) {\n const rows = rowSpan(ctx, event);\n if (rows === null) continue;\n minRow = Math.min(minRow, rows.lo);\n maxRow = Math.max(maxRow, rows.hi);\n sumX += camera.timeToScreenX(event.time);\n placed += 1;\n }\n if (placed === 0) return;\n\n // Average only over the events that contributed an x (those with a row pair),\n // so the marker stays centred even if the row-span and cull paths ever desync.\n const x = sumX / placed;\n const yTop = camera.rowToScreenY(minRow) + halfRow;\n const yBot = camera.rowToScreenY(maxRow) + halfRow;\n const yMid = (yTop + yBot) / 2;\n const color = theme.clusterColor;\n const width = theme.event.arrowWidth;\n const markerRadius = theme.event.nodeRadius + CLUSTER_MARKER_BONUS_PX;\n\n // Riser only when the cluster spans more than one row (else it is a point).\n const segments = yTop !== yBot ? [{ x1: x, y1: yTop, x2: x, y2: yBot }] : [];\n if (segments.length > 0) {\n lineBatch(batches.lines, color, width).segments.push(...segments);\n }\n nodeBatch(batches.nodes, color, markerRadius).items.push({ x, y: yMid });\n labelBatch(batches.labels, color, theme.event.labelFont).items.push({\n x: x + markerRadius + EVENT_LABEL_GAP_PX,\n y: yMid,\n text: `×${events.length}`,\n });\n batches.targets.push({\n kind: 'cluster',\n events,\n segments,\n marker: { x, y: yMid },\n markerSize: markerRadius,\n width,\n });\n}\n\n/**\n * A self-directed event: a rectangular half-loop above the line returning to a\n * downward arrowhead, with the source dot on the line. No inter-row riser (§1).\n */\nfunction addSelfLoop<TData>(\n batches: Batches<TData>,\n style: { color: string; width: number; size: number; radius: number },\n x: number,\n y: number,\n event: TimelineEvent<TData>,\n): void {\n const loop = style.size * 2;\n const top = y - loop;\n const segments = [\n { x1: x, y1: y, x2: x, y2: top },\n { x1: x, y1: top, x2: x + loop, y2: top },\n { x1: x + loop, y1: top, x2: x + loop, y2: y },\n ];\n lineBatch(batches.lines, style.color, style.width).segments.push(...segments);\n nodeBatch(batches.nodes, style.color, style.radius).items.push({ x, y });\n arrowheadBatch(batches.arrowheads, style.color, style.size).items.push({\n x: x + loop,\n y,\n angle: ANGLE_DOWN,\n });\n batches.targets.push({\n kind: 'event',\n event,\n segments,\n arrowhead: { x: x + loop, y },\n node: { x, y },\n width: style.width,\n arrowheadSize: style.size,\n });\n}\n\nfunction pushEventLabel(\n labels: Map<string, LabelSpec>,\n text: string,\n style: EventStyle,\n at: { x: number; y: number },\n): void {\n labelBatch(labels, style.labelColor, style.labelFont).items.push({\n x: at.x,\n y: at.y,\n text,\n });\n}\n","// Canvas2D implementation of the Renderer seam (DESIGN.md §3 DPR, §4).\n//\n// This is the only file in the engine allowed to touch a 2D context, and it is\n// not re-exported as a type, so the engine never imports CanvasRenderingContext2D.\n//\n// DPR convention (§3): resize sets the backing store to device pixels and does\n// NOT call ctx.scale; all incoming batch coordinates are already in device\n// pixels. Drawing batches by style minimises context state changes (§4).\n\nimport type {\n ArrowheadBatch,\n ImageBatch,\n Layer,\n LineBatch,\n NodeBatch,\n Renderer,\n TextBatch,\n TextMetricsLite,\n} from './types';\n\nexport class Canvas2DRenderer implements Renderer {\n private readonly baseCtx: CanvasRenderingContext2D;\n private readonly overlayCtx: CanvasRenderingContext2D;\n private current: CanvasRenderingContext2D;\n\n constructor(\n private readonly baseCanvas: HTMLCanvasElement,\n private readonly overlayCanvas: HTMLCanvasElement,\n private background: string,\n ) {\n this.baseCtx = getContext(baseCanvas);\n this.overlayCtx = getContext(overlayCanvas);\n this.current = this.baseCtx;\n }\n\n setBackground(background: string): void {\n this.background = background;\n }\n\n resize(deviceWidth: number, deviceHeight: number): void {\n // Setting width/height resizes the backing store and clears it.\n this.baseCanvas.width = deviceWidth;\n this.baseCanvas.height = deviceHeight;\n this.overlayCanvas.width = deviceWidth;\n this.overlayCanvas.height = deviceHeight;\n }\n\n beginFrame(layer: Layer): void {\n if (layer === 'base') {\n this.current = this.baseCtx;\n this.baseCtx.fillStyle = this.background;\n this.baseCtx.fillRect(\n 0,\n 0,\n this.baseCanvas.width,\n this.baseCanvas.height,\n );\n } else {\n this.current = this.overlayCtx;\n this.overlayCtx.clearRect(\n 0,\n 0,\n this.overlayCanvas.width,\n this.overlayCanvas.height,\n );\n }\n }\n\n fillRect(\n x: number,\n y: number,\n width: number,\n height: number,\n color: string,\n ): void {\n const ctx = this.current;\n ctx.fillStyle = color;\n ctx.fillRect(x, y, width, height);\n }\n\n drawLines(batch: LineBatch): void {\n if (batch.segments.length === 0) return;\n const ctx = this.current;\n ctx.strokeStyle = batch.color;\n ctx.lineWidth = batch.width;\n ctx.beginPath();\n for (const s of batch.segments) {\n ctx.moveTo(s.x1, s.y1);\n ctx.lineTo(s.x2, s.y2);\n }\n ctx.stroke();\n }\n\n drawText(batch: TextBatch): void {\n if (batch.items.length === 0) return;\n const ctx = this.current;\n ctx.fillStyle = batch.color;\n ctx.font = batch.font;\n ctx.textBaseline = batch.baseline;\n ctx.textAlign = batch.align;\n for (const item of batch.items) {\n ctx.fillText(item.text, item.x, item.y);\n }\n }\n\n measureText(text: string, font: string): TextMetricsLite {\n this.baseCtx.font = font;\n return { width: this.baseCtx.measureText(text).width };\n }\n\n drawArrowheads(batch: ArrowheadBatch): void {\n if (batch.items.length === 0) return;\n const ctx = this.current;\n const { size } = batch;\n ctx.fillStyle = batch.color;\n // One path for the whole batch: each item is a triangle pointing +x in local\n // space (tip at +size), rotated by `angle` and translated to (x, y).\n ctx.beginPath();\n for (const { x, y, angle } of batch.items) {\n const cos = Math.cos(angle);\n const sin = Math.sin(angle);\n const tipX = x + size * cos;\n const tipY = y + size * sin;\n // Base corners at local (-0.4·size, ±0.6·size).\n const bx = -0.4 * size;\n const wy = 0.6 * size;\n const x1 = x + bx * cos - wy * sin;\n const y1 = y + bx * sin + wy * cos;\n const x2 = x + bx * cos + wy * sin;\n const y2 = y + bx * sin - wy * cos;\n ctx.moveTo(tipX, tipY);\n ctx.lineTo(x1, y1);\n ctx.lineTo(x2, y2);\n ctx.closePath();\n }\n ctx.fill();\n }\n\n drawNodes(batch: NodeBatch): void {\n if (batch.items.length === 0) return;\n const ctx = this.current;\n ctx.fillStyle = batch.color;\n ctx.beginPath();\n for (const { x, y } of batch.items) {\n // moveTo before each arc so circles are not joined by a connecting line.\n ctx.moveTo(x + batch.radius, y);\n ctx.arc(x, y, batch.radius, 0, Math.PI * 2);\n }\n ctx.fill();\n }\n\n drawImages(batch: ImageBatch): void {\n const ctx = this.current;\n for (const { x, y, size, image } of batch.items) {\n try {\n // The seam carries an opaque RendererImage; Canvas2D narrows it to a\n // CanvasImageSource (§4). Only this backend knows the concrete type.\n ctx.drawImage(image as CanvasImageSource, x, y, size, size);\n } catch {\n // An image that failed to decode throws on draw; skip it this frame.\n }\n }\n }\n\n endFrame(_layer: Layer): void {\n /* Canvas2D is immediate-mode; nothing to flush. */\n }\n}\n\nfunction getContext(canvas: HTMLCanvasElement): CanvasRenderingContext2D {\n const ctx = canvas.getContext('2d');\n if (ctx === null) {\n throw new Error('Canvas2DRenderer: failed to acquire a 2D context');\n }\n return ctx;\n}\n","// CSS-px → device-px helpers for the DPR convention (DESIGN.md §3).\n//\n// The backing store is cssSize * dpr and the context is NOT pre-scaled, so the\n// engine converts coordinates to device pixels and snaps them to integers here;\n// a 0.5px offset keeps odd-width strokes crisp (hairline rule).\n\n/** Convert a CSS-pixel coordinate to an integer device pixel. */\nexport function snapDevice(cssPx: number, dpr: number): number {\n return Math.round(cssPx * dpr);\n}\n\n/** The 0.5px offset that keeps an odd device-width stroke on a pixel centre. */\nexport function hairlineOffset(deviceWidthPx: number): number {\n return deviceWidthPx % 2 === 1 ? 0.5 : 0;\n}\n\n/**\n * Scale the `px` size in a CSS font shorthand by `dpr`. The context is not\n * pre-scaled (§3), so text drawn in device pixels needs its size multiplied to\n * match. e.g. scaleFontToDevice('12px system-ui', 2) → '24px system-ui'.\n */\nexport function scaleFontToDevice(font: string, dpr: number): string {\n return font.replace(\n /(\\d*\\.?\\d+)px/,\n (_, size: string) => `${Number(size) * dpr}px`,\n );\n}\n","// Element lines + their label/icon at the line start (DESIGN.md §1, §4, §7).\n//\n// Each element is a horizontal line spanning from a few px before its first\n// event to its last event, with its label (and optional icon) anchored at the\n// line start in world space so they pan with the content. When the line start\n// scrolls off the left edge while the line is still visible, the label \"sticks\"\n// to the left edge so it stays readable (§1). Vertical culling uses the padded\n// row band (§5, §16); event-less elements have no extent and are not drawn (§1).\n//\n// Pure: works in CSS pixels and returns specs; the engine snaps to device px.\n\nimport type { Theme } from '../model/types';\nimport { labelBatch, lineBatch } from './batch';\nimport type {\n BuildContext,\n HitTarget,\n IconSpec,\n LabelSpec,\n LineSpec,\n} from './specs';\n\n/** CSS px of line drawn before an element's first event — the lead gap (§1). */\nexport const LINE_LEAD_PAD_PX = 12;\n/** Gap between the start marker (icon/label block) and the line's left end. */\nconst MARKER_GAP_PX = 8;\n/** Vertical gap between the stacked icon and the label beneath it. */\nconst STACK_GAP_PX = 2;\n/** Fallback label line height when a font's px size can't be parsed. */\nconst FALLBACK_LABEL_PX = 12;\n\n/**\n * Heuristic label-width budget (CSS px) used only to reserve fit space. The pure\n * builder never measures text (it has no canvas), so `fit` can't know the real\n * label width; this is a reasonable upper bound for typical short labels. Wider\n * labels still render fine — they may just need a manual pan after the initial fit.\n */\nconst FIT_LABEL_BUDGET_PX = 96;\n\n/**\n * CSS px to reserve left of the leftmost line so its start marker (icon + label,\n * §1) isn't clipped by `fit`. Mirrors the marker geometry below: the line's lead\n * gap, the marker gap, the marker content width, and the left padding.\n */\nexport function markerReserveLeftPx(theme: Theme): number {\n const markerContentW = Math.max(theme.element.iconSize, FIT_LABEL_BUDGET_PX);\n return theme.labelPadding + markerContentW + MARKER_GAP_PX + LINE_LEAD_PAD_PX;\n}\n\n// Extract the leading px size from a CSS font shorthand (e.g. \"12px Inter\").\n// Only px-sized fonts are supported (the theme uses them); pt/em/% fall back to\n// FALLBACK_LABEL_PX, which only affects vertical stack centering, never layout.\nfunction fontPx(font: string): number {\n const match = /(\\d+(?:\\.\\d+)?)px/.exec(font);\n return match ? Number(match[1]) : FALLBACK_LABEL_PX;\n}\n\nexport interface ElementLinesResult<TData = unknown> {\n lines: LineSpec[];\n /** Element labels and emoji icons (both anchored left/middle). */\n labels: LabelSpec[];\n icons: IconSpec;\n /** Identity-carrying line geometry for hit-testing (§5). */\n targets: HitTarget<TData>[];\n}\n\nexport function buildElementLines<TData>(\n ctx: BuildContext<TData>,\n): ElementLinesResult<TData> {\n const { camera, rowLayout, data, viewport, theme, band, resolveIcon } = ctx;\n const rowHeight = theme.rowHeight;\n\n const lines = new Map<string, LineSpec>();\n const labels = new Map<string, LabelSpec>();\n const icons: IconSpec = { items: [] };\n const targets: HitTarget<TData>[] = [];\n\n for (const id of rowLayout.orderedIds) {\n const extent = data.getExtent(id);\n if (extent === undefined) continue; // event-less: not drawn (§1)\n\n const rowIndex = rowLayout.rowIndexById.get(id);\n if (rowIndex === undefined) continue;\n if (rowIndex < band.firstRow || rowIndex > band.lastRow) continue; // §5/§16\n\n const lineStartX = camera.timeToScreenX(extent.minTime);\n const lineEndX = camera.timeToScreenX(extent.maxTime);\n // Keep while any part of the line is visible. The left bound is governed by\n // lineEndX (a sticky label is drawn while the line still reaches the\n // viewport), so we must NOT cull on a negative lineStartX. `lineEndX <= 0`\n // means the whole line sits at/left of the edge — nothing visible — so the\n // cull and the `lineEndX > 0` sticky guard below agree on \"visible = > 0\".\n if (lineEndX <= 0 || lineStartX - LINE_LEAD_PAD_PX > viewport.cssWidth) {\n continue;\n }\n\n const rowCenterY = camera.rowToScreenY(rowIndex) + rowHeight / 2;\n const element = data.getElementById(id);\n\n // Resolve the full §11 style once per element (theme → resolver → .style).\n const style = element ? ctx.resolveElementStyle(element) : theme.element;\n const lineColor = style.lineColor;\n const lineWidth = style.lineWidth;\n const x1 = lineStartX - LINE_LEAD_PAD_PX;\n lineBatch(lines, lineColor, lineWidth).segments.push({\n x1,\n y1: rowCenterY,\n x2: lineEndX,\n y2: rowCenterY,\n });\n if (element !== undefined) {\n targets.push({\n kind: 'element',\n element,\n y: rowCenterY,\n x1,\n x2: lineEndX,\n width: lineWidth,\n });\n }\n\n // Start marker (§1): a block to the LEFT of the line's left end. With an\n // icon it's the icon stacked over a centred label; without one it's the\n // label alone, right-aligned so it never spills onto the line. Sticky-left:\n // when the start scrolls past the edge but the line is still visible, pin\n // the marker so it clears `labelPadding` and stays readable.\n const iconSize = style.iconSize;\n const icon = element?.icon;\n const text = element ? ctx.formatElementLabel(element) : id;\n const labelPx = fontPx(style.labelFont);\n\n if (icon !== undefined) {\n const markerHalfW = iconSize / 2;\n const markerCenterX = Math.max(\n x1 - MARKER_GAP_PX - markerHalfW,\n theme.labelPadding + markerHalfW,\n );\n // Centre the icon+label stack vertically on the row centre.\n const totalH = iconSize + STACK_GAP_PX + labelPx;\n const top = rowCenterY - totalH / 2;\n const iconCenterY = top + iconSize / 2;\n const labelY = top + iconSize + STACK_GAP_PX + labelPx / 2;\n const resolved = resolveIcon(icon);\n if (resolved.kind === 'image') {\n icons.items.push({\n x: markerCenterX - iconSize / 2,\n y: top,\n size: iconSize,\n image: resolved.image,\n });\n } else if (resolved.kind === 'text') {\n // Emoji / glyph icon drawn as centred text sized to the icon slot,\n // tinted with the element's resolved label colour for consistency.\n const iconFont = `${iconSize}px sans-serif`;\n labelBatch(labels, style.labelColor, iconFont, 'center').items.push({\n x: markerCenterX,\n y: iconCenterY,\n text: resolved.text,\n });\n }\n labelBatch(\n labels,\n style.labelColor,\n style.labelFont,\n 'center',\n ).items.push({ x: markerCenterX, y: labelY, text });\n } else {\n // No icon: right-align the label so its right edge sits a gap left of the\n // line start — it can never overflow onto the line. When the line start\n // scrolls off-screen, fall back to a left-anchored sticky label.\n const labelRightX = x1 - MARKER_GAP_PX;\n if (labelRightX >= theme.labelPadding) {\n labelBatch(\n labels,\n style.labelColor,\n style.labelFont,\n 'right',\n ).items.push({ x: labelRightX, y: rowCenterY, text });\n } else {\n labelBatch(\n labels,\n style.labelColor,\n style.labelFont,\n 'left',\n ).items.push({ x: theme.labelPadding, y: rowCenterY, text });\n }\n }\n }\n\n return {\n lines: [...lines.values()],\n labels: [...labels.values()],\n icons,\n targets,\n };\n}\n","// Element icon loading + classification (DESIGN.md §1, §11).\n//\n// `element.icon` is a URL, an emoji/glyph string, or a preloaded image. URLs are\n// loaded once and cached by URL; while loading, `get` returns undefined and the\n// frame skips the icon, then the injected `markDirty` callback re-renders when\n// the image arrives (core stays decoupled from any scheduler — DIP). Emoji/glyph\n// strings are not URLs and are drawn as text by the builder instead.\n\n/**\n * Whether an icon string is a URL/path (load as an image) rather than an\n * emoji/glyph (draw as text). Matches a protocol, a path prefix, or a known\n * image extension; anything else is treated as text.\n */\nexport function isIconUrl(icon: string): boolean {\n return (\n /^(https?:|data:|blob:|\\/|\\.\\/|\\.\\.\\/)/.test(icon) ||\n /\\.(png|jpe?g|gif|svg|webp|avif|bmp|ico)$/i.test(icon)\n );\n}\n\nexport class IconCache {\n // `null` = loading or failed; `undefined` (absent) = never requested.\n private readonly cache = new Map<string, HTMLImageElement | null>();\n\n constructor(private readonly onLoad: () => void) {}\n\n /**\n * The ready image for `url`, or `undefined` while it is still loading (or\n * failed). The first request for a URL kicks off the load.\n */\n get(url: string): HTMLImageElement | undefined {\n const hit = this.cache.get(url);\n if (hit === undefined) {\n this.load(url);\n return undefined;\n }\n if (hit === null) return undefined;\n return hit.complete && hit.naturalWidth > 0 ? hit : undefined;\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n private load(url: string): void {\n // SSR / non-DOM guard: no Image constructor means we simply never resolve.\n if (typeof Image === 'undefined') {\n this.cache.set(url, null);\n return;\n }\n this.cache.set(url, null);\n const image = new Image();\n image.onload = () => {\n this.cache.set(url, image);\n this.onLoad();\n };\n image.onerror = () => {\n // Leave as null (failed); do not retry to avoid a load storm.\n };\n image.src = url;\n }\n}\n","// The visible row band for vertical culling (DESIGN.md §5, §16).\n//\n// Phase 1 culled element rows by line-centre Y, which dropped rows whose centre\n// had just scrolled under the header or below the viewport even though part of\n// the row was still visible (§16 note). This computes an inclusive row interval\n// padded by one row each side, so partially-visible edge rows are retained and\n// arrows whose endpoints straddle the band are kept (§5 row-interval test).\n\nimport type { Camera, Viewport } from '../scale/camera';\nimport type { RowBand } from './specs';\n\n/**\n * The inclusive `[firstRow, lastRow]` interval of rows that may be visible,\n * padded by one row on each side and clamped to `[0, rowCount - 1]`. Returns an\n * empty band (`firstRow > lastRow`) when there are no rows.\n */\nexport function visibleRowBand(\n camera: Camera,\n viewport: Viewport,\n rowCount: number,\n headerHeight: number,\n): RowBand {\n if (rowCount === 0) return { firstRow: 0, lastRow: -1 };\n const top = Math.floor(camera.screenYToRow(headerHeight)) - 1;\n const bottom = Math.ceil(camera.screenYToRow(viewport.cssHeight)) + 1;\n return {\n firstRow: Math.max(0, top),\n lastRow: Math.min(rowCount - 1, bottom),\n };\n}\n","// The single CSS-px → device-px pass (DESIGN.md §3, §4).\n//\n// Builders emit specs in CSS pixels; this is the one place the DPR convention is\n// applied — coordinates multiplied by dpr and snapped to integer device pixels,\n// with a 0.5px hairline offset so odd-width strokes stay crisp, and fonts scaled\n// to match the un-prescaled context. Keeping it here means the geometry builders\n// never touch dpr and the snapping rule has a single definition.\n\nimport { hairlineOffset, scaleFontToDevice, snapDevice } from './device';\nimport type {\n ArrowheadSpec,\n IconSpec,\n LabelSpec,\n LineSpec,\n NodeSpec,\n} from './specs';\nimport type {\n ArrowheadBatch,\n ImageBatch,\n LineBatch,\n NodeBatch,\n TextBatch,\n} from './types';\n\nexport function snapLines(spec: LineSpec, dpr: number): LineBatch {\n const width = Math.max(1, snapDevice(spec.width, dpr));\n const off = hairlineOffset(width);\n return {\n color: spec.color,\n width,\n segments: spec.segments.map((s) => ({\n x1: snapDevice(s.x1, dpr) + off,\n y1: snapDevice(s.y1, dpr) + off,\n x2: snapDevice(s.x2, dpr) + off,\n y2: snapDevice(s.y2, dpr) + off,\n })),\n };\n}\n\nexport function snapNodes(spec: NodeSpec, dpr: number): NodeBatch {\n return {\n color: spec.color,\n radius: Math.max(1, snapDevice(spec.radius, dpr)),\n items: spec.items.map((i) => ({\n x: snapDevice(i.x, dpr),\n y: snapDevice(i.y, dpr),\n })),\n };\n}\n\nexport function snapArrowheads(\n spec: ArrowheadSpec,\n dpr: number,\n): ArrowheadBatch {\n return {\n color: spec.color,\n size: Math.max(1, snapDevice(spec.size, dpr)),\n items: spec.items.map((i) => ({\n x: snapDevice(i.x, dpr),\n y: snapDevice(i.y, dpr),\n angle: i.angle, // direction is dpr-invariant\n })),\n };\n}\n\nexport function snapLabels(spec: LabelSpec, dpr: number): TextBatch {\n return {\n color: spec.color,\n font: scaleFontToDevice(spec.font, dpr),\n baseline: spec.baseline,\n align: spec.align,\n items: spec.items.map((i) => ({\n x: snapDevice(i.x, dpr),\n y: snapDevice(i.y, dpr),\n text: i.text,\n })),\n };\n}\n\nexport function snapIcons(spec: IconSpec, dpr: number): ImageBatch {\n return {\n items: spec.items.map((i) => ({\n x: snapDevice(i.x, dpr),\n y: snapDevice(i.y, dpr),\n size: snapDevice(i.size, dpr),\n image: i.image,\n })),\n };\n}\n","// The single source of coordinate truth (DESIGN.md §3, §3.1).\n//\n// Every time↔screen and row↔screen transform lives here; no other module\n// re-derives `(t - originTime) * pxPerMs`. Horizontal pan is anchored in the\n// time domain (`originTime`), never as a pixel offset, so pan and zoom compose\n// cleanly. All math is in CSS pixels; the renderer applies DPR (§3).\n\nimport type { Time } from '../model/types';\nimport type { Extent } from '../model/extent';\n\n/** One day in milliseconds; the unit for day-width-derived zoom limits. */\nexport const DAY_MS = 86_400_000;\n\n/** Default window spanned when the data extent is empty or degenerate (§3.1). */\nexport const DEFAULT_WINDOW_MS = 30 * DAY_MS;\n\n/** Max useful day width (CSS px); drives `maxPxPerMs`. */\nexport const MAX_DAY_WIDTH_PX = 4000;\n\nexport interface CameraState {\n /** Time mapped to the left edge of the viewport (screen x = 0). */\n originTime: Time;\n /** Vertical scroll offset in CSS px. */\n scrollY: number;\n /** Horizontal zoom level: CSS px per millisecond. */\n pxPerMs: number;\n}\n\n/** Viewport size in CSS pixels (DPR is the renderer's concern, §3). */\nexport interface Viewport {\n cssWidth: number;\n cssHeight: number;\n}\n\n/** Fixed vertical metrics for row placement. */\nexport interface RowMetrics {\n headerHeight: number;\n rowHeight: number;\n rowGap: number;\n}\n\nexport interface ZoomBounds {\n minPxPerMs: number;\n maxPxPerMs: number;\n}\n\n/**\n * CSS px reserved at the viewport edges when fitting, so content drawn *outside*\n * the data extent stays on-screen — chiefly the element start markers that sit\n * left of each line's first event (§1). The engine derives these from the theme;\n * the Camera just treats them as a usable-width reduction (it stays the single\n * source of coordinate truth, §3).\n */\nexport interface FitInset {\n left?: number;\n right?: number;\n}\n\n/** Usable horizontal span for fitting, after reserving the edge insets. */\nfunction usableFitWidth(viewport: Viewport, inset: FitInset): number {\n const left = inset.left ?? 0;\n const right = inset.right ?? 0;\n return Math.max(1, viewport.cssWidth - left - right);\n}\n\nconst DEFAULT_STATE: CameraState = {\n originTime: 0,\n scrollY: 0,\n pxPerMs: 1,\n};\n\nexport class Camera {\n private _state: CameraState;\n\n constructor(\n private readonly metrics: RowMetrics,\n initial: Partial<CameraState> = {},\n ) {\n this._state = { ...DEFAULT_STATE, ...initial };\n }\n\n get state(): Readonly<CameraState> {\n return this._state;\n }\n\n // --- Transforms (the only place this arithmetic exists) ---\n\n timeToScreenX(t: Time): number {\n return (t - this._state.originTime) * this._state.pxPerMs;\n }\n\n screenXToTime(x: number): Time {\n return this._state.originTime + x / this._state.pxPerMs;\n }\n\n rowToScreenY(row: number): number {\n const { headerHeight, rowHeight, rowGap } = this.metrics;\n return headerHeight + row * (rowHeight + rowGap) - this._state.scrollY;\n }\n\n screenYToRow(y: number): number {\n const { headerHeight, rowHeight, rowGap } = this.metrics;\n return (y + this._state.scrollY - headerHeight) / (rowHeight + rowGap);\n }\n\n // --- Mutations ---\n\n setOriginTime(t: Time): void {\n this._state.originTime = t;\n }\n\n setScrollY(y: number): void {\n this._state.scrollY = y;\n }\n\n setPxPerMs(pxPerMs: number, bounds: ZoomBounds): void {\n this._state.pxPerMs = Math.min(\n bounds.maxPxPerMs,\n Math.max(bounds.minPxPerMs, pxPerMs),\n );\n }\n\n /**\n * Zoom about the cursor (DESIGN.md §3): scale `pxPerMs` by `factor`, keeping\n * the time under `cursorScreenX` fixed on screen. The cursor time is captured\n * *before* the zoom change, then `originTime` is recomputed afterwards so the\n * same instant lands under the same screen x. Reuses the existing transforms\n * and clamping — no new `pxPerMs` arithmetic leaks out of the Camera.\n */\n zoomAboutCursor(\n factor: number,\n cursorScreenX: number,\n bounds: ZoomBounds,\n ): void {\n const tCursor = this.screenXToTime(cursorScreenX);\n this.setPxPerMs(this._state.pxPerMs * factor, bounds);\n this._state.originTime = tCursor - cursorScreenX / this._state.pxPerMs;\n }\n\n /**\n * Pan by a pixel delta. Dragging right (`dxCss > 0`) reveals earlier time at\n * the left edge, so `originTime` decreases. This is the only place a pixel\n * delta is converted to a time delta (`dxCss / pxPerMs`).\n */\n panByPixels(dxCss: number, dyCss: number): void {\n this._state.originTime -= dxCss / this._state.pxPerMs;\n this._state.scrollY -= dyCss;\n }\n\n /** Clamp `scrollY` so vertical scroll cannot overscroll the content. */\n clampScrollY(contentHeight: number, viewport: Viewport): void {\n const visibleBody = viewport.cssHeight - this.metrics.headerHeight;\n const max = Math.max(0, contentHeight - visibleBody);\n this._state.scrollY = Math.min(max, Math.max(0, this._state.scrollY));\n }\n}\n\n/**\n * Resolve a degenerate data extent to a usable window (DESIGN.md §3.1). This is\n * the only place empty / single-instant extents are widened, so no division by\n * zero ever reaches the scale math.\n */\nexport function effectiveExtent(extent: Extent | null, now: Time): Extent {\n if (extent === null) {\n return {\n minTime: now - DEFAULT_WINDOW_MS / 2,\n maxTime: now + DEFAULT_WINDOW_MS / 2,\n };\n }\n if (extent.maxTime - extent.minTime <= 0) {\n const center = extent.minTime;\n return {\n minTime: center - DEFAULT_WINDOW_MS / 2,\n maxTime: center + DEFAULT_WINDOW_MS / 2,\n };\n }\n return extent;\n}\n\n/**\n * Zoom limits for the current data + viewport. `minPxPerMs` fits the (degenerate\n * -safe) extent to the viewport width; `maxPxPerMs` comes from a max useful day\n * width. `now` resolves empty/single-instant extents (§3.1).\n */\nexport function computeZoomBounds(\n extent: Extent | null,\n viewport: Viewport,\n now: Time,\n inset: FitInset = {},\n): ZoomBounds {\n const eff = effectiveExtent(extent, now);\n const span = eff.maxTime - eff.minTime;\n const maxPxPerMs = MAX_DAY_WIDTH_PX / DAY_MS;\n // The zoom-out limit must permit the inset-aware fit level (below), so it is\n // derived from the usable width, not the full viewport — otherwise a later\n // setPxPerMs would clamp the fitted zoom back up and undo the inset.\n const minPxPerMs = usableFitWidth(viewport, inset) / span;\n return { minPxPerMs, maxPxPerMs };\n}\n\n/**\n * Frame the data extent to the viewport: `pxPerMs` spans the (degenerate-safe)\n * extent across the *usable* width (the viewport minus any `inset`), the extent\n * start sits at the left inset, and `scrollY` resets. Reserving a left inset\n * keeps each line's start marker (icon + label, §1) on-screen instead of clipped\n * at the edge. `now` resolves empty/single-instant extents (§3.1).\n */\nexport function fit(\n camera: Camera,\n extent: Extent | null,\n viewport: Viewport,\n now: Time,\n inset: FitInset = {},\n): void {\n const eff = effectiveExtent(extent, now);\n const span = eff.maxTime - eff.minTime;\n camera.setPxPerMs(\n usableFitWidth(viewport, inset) / span,\n computeZoomBounds(extent, viewport, now, inset),\n );\n // Place the extent start at the left inset using the *clamped* pxPerMs:\n // originTime is the time at screen x=0, so back off the inset's worth of time.\n const left = inset.left ?? 0;\n camera.setOriginTime(eff.minTime - left / camera.state.pxPerMs);\n camera.setScrollY(0);\n}\n","// Adaptive tick generation for the time header (DESIGN.md §8).\n//\n// An adaptive generator chooses tick steps from `pxPerMs` so labels never\n// overlap, picking \"nice\" steps (1/2/5/10 days, months, quarters, years). All\n// calendar boundaries are computed in **UTC** (via native `Date.UTC` + UTC\n// getters) so day/month/year boundaries and labels are identical on every\n// machine and stable for golden tests. (date-fns — the engine's calendar dep —\n// is reserved for the richer interval/duration math of later phases; Phase 1's\n// boundary stepping is pure UTC integer arithmetic, which date-fns cannot do\n// without a UTC wrapper and which guarantees machine-stability here.)\n\nimport type { Time } from '../model/types';\nimport { DAY_MS } from './camera';\n\nexport type TickLevel = 'year' | 'month' | 'day';\n\nexport interface Tick {\n time: Time;\n level: TickLevel;\n label: string;\n}\n\n/** Two header rows: `major` (coarser, drives gridlines) over `minor`. */\nexport interface TickScale {\n major: Tick[];\n minor: Tick[];\n}\n\nexport type TickFormatter = (date: Date, level: TickLevel) => string;\n\ninterface Step {\n level: TickLevel;\n n: number;\n /** Approximate width in ms, used only for step selection. */\n approxMs: number;\n}\n\n// Ascending by approximate width; the first whose pixel width clears the label\n// gap is chosen (so labels never overlap, §8).\nconst STEPS: Step[] = [\n { level: 'day', n: 1, approxMs: DAY_MS },\n { level: 'day', n: 2, approxMs: 2 * DAY_MS },\n { level: 'day', n: 5, approxMs: 5 * DAY_MS },\n { level: 'day', n: 10, approxMs: 10 * DAY_MS },\n { level: 'month', n: 1, approxMs: 30 * DAY_MS },\n { level: 'month', n: 3, approxMs: 91 * DAY_MS },\n { level: 'year', n: 1, approxMs: 365 * DAY_MS },\n { level: 'year', n: 2, approxMs: 730 * DAY_MS },\n { level: 'year', n: 5, approxMs: 1826 * DAY_MS },\n { level: 'year', n: 10, approxMs: 3652 * DAY_MS },\n];\n\nfunction pickStep(pxPerMs: number, minLabelGapPx: number): Step {\n for (const step of STEPS) {\n if (step.approxMs * pxPerMs >= minLabelGapPx) return step;\n }\n return STEPS[STEPS.length - 1] as Step;\n}\n\n/** The next coarser step row drawn above `minor`. */\nfunction coarserStep(minor: Step): Step {\n switch (minor.level) {\n case 'day':\n return { level: 'month', n: 1, approxMs: 30 * DAY_MS };\n case 'month':\n return { level: 'year', n: 1, approxMs: 365 * DAY_MS };\n case 'year':\n return { level: 'year', n: minor.n * 10, approxMs: minor.approxMs * 10 };\n }\n}\n\nfunction utcYear(t: Time): number {\n return new Date(t).getUTCFullYear();\n}\nfunction utcMonth(t: Time): number {\n return new Date(t).getUTCMonth();\n}\nfunction daysInUtcMonth(year: number, month: number): number {\n return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n}\n\nconst formatterCache = new Map<TickLevel, Intl.DateTimeFormat>();\nfunction defaultFormat(date: Date, level: TickLevel): string {\n let fmt = formatterCache.get(level);\n if (fmt === undefined) {\n const options: Intl.DateTimeFormatOptions =\n level === 'year'\n ? { timeZone: 'UTC', year: 'numeric' }\n : level === 'month'\n ? { timeZone: 'UTC', month: 'short', year: 'numeric' }\n : { timeZone: 'UTC', day: 'numeric' };\n fmt = new Intl.DateTimeFormat('en-US', options);\n formatterCache.set(level, fmt);\n }\n return fmt.format(date);\n}\n\nfunction makeTick(time: Time, level: TickLevel, format: TickFormatter): Tick {\n return { time, level, label: format(new Date(time), level) };\n}\n\nfunction enumerate(\n tStart: Time,\n tEnd: Time,\n step: Step,\n format: TickFormatter,\n): Tick[] {\n const ticks: Tick[] = [];\n if (step.level === 'day') {\n // Day ticks restart on the 1st of each month so a tick always lands on the\n // month boundary; within a month they step by `n` days.\n let monthStart = Date.UTC(utcYear(tStart), utcMonth(tStart), 1);\n while (monthStart <= tEnd) {\n const year = utcYear(monthStart);\n const month = utcMonth(monthStart);\n const dim = daysInUtcMonth(year, month);\n for (let day = 1; day <= dim; day += step.n) {\n const t = Date.UTC(year, month, day);\n if (t >= tStart && t <= tEnd) ticks.push(makeTick(t, 'day', format));\n }\n monthStart = Date.UTC(year, month + 1, 1);\n }\n return ticks;\n }\n if (step.level === 'month') {\n const startMonth = Math.floor(utcMonth(tStart) / step.n) * step.n;\n let year = utcYear(tStart);\n let month = startMonth;\n let t = Date.UTC(year, month, 1);\n while (t <= tEnd) {\n if (t >= tStart) ticks.push(makeTick(t, 'month', format));\n month += step.n;\n t = Date.UTC(year, month, 1);\n year = utcYear(t);\n month = utcMonth(t);\n }\n return ticks;\n }\n // year\n let year = Math.floor(utcYear(tStart) / step.n) * step.n;\n let t = Date.UTC(year, 0, 1);\n while (t <= tEnd) {\n if (t >= tStart) ticks.push(makeTick(t, 'year', format));\n year += step.n;\n t = Date.UTC(year, 0, 1);\n }\n return ticks;\n}\n\n/**\n * Drop ticks closer than `minGapPx` to the previously kept one. Day ticks\n * restart on the 1st of each month, so a month boundary can place the prior\n * month's last day a single day from the next month's 1st; thinning keeps those\n * labels from overlapping (the \"31 1\" collision).\n */\nfunction thinByPixels(\n ticks: Tick[],\n pxPerMs: number,\n minGapPx: number,\n): Tick[] {\n const kept: Tick[] = [];\n let lastX = -Infinity;\n for (const tick of ticks) {\n const x = tick.time * pxPerMs;\n if (x - lastX >= minGapPx) {\n kept.push(tick);\n lastX = x;\n }\n }\n return kept;\n}\n\n/**\n * Generate the major/minor ticks visible in `[tStart, tEnd]` at the given zoom.\n * `minLabelGapPx` is the minimum pixel spacing labels need; the smallest \"nice\"\n * step clearing it is chosen, and overlapping boundary ticks are thinned out.\n */\nexport function generateTicks(\n tStart: Time,\n tEnd: Time,\n pxPerMs: number,\n minLabelGapPx: number,\n formatTick: TickFormatter = defaultFormat,\n): TickScale {\n if (tEnd <= tStart || !Number.isFinite(pxPerMs) || pxPerMs <= 0) {\n return { major: [], minor: [] };\n }\n const minor = pickStep(pxPerMs, minLabelGapPx);\n const major = coarserStep(minor);\n return {\n major: thinByPixels(\n enumerate(tStart, tEnd, major, formatTick),\n pxPerMs,\n minLabelGapPx,\n ),\n minor: thinByPixels(\n enumerate(tStart, tEnd, minor, formatTick),\n pxPerMs,\n minLabelGapPx,\n ),\n };\n}\n","// Per-item style resolution (DESIGN.md §11).\n//\n// The §11 resolution order is, most specific wins: per-item `style` → resolver\n// callback → theme default, each visual property resolved independently. This is\n// expressed once here as an `overlayStyle` merge and reused for both element and\n// event styles (DRY), so there is a single definition of \"how a style is layered\"\n// rather than parallel `?? theme` chains scattered through the builders.\n\nimport type {\n ElementStyle,\n EventStyle,\n TimelineElement,\n TimelineEvent,\n} from '../model/types';\n\n/**\n * Overlay `partials` onto a complete `base`, later partials winning. A property\n * set to `undefined` (or absent) in a partial **falls through** to the previous\n * layer, matching the `?? theme.default` semantics each level previously used and\n * keeping per-property independence (§11): a partial only overrides the keys it\n * actually sets.\n */\nexport function overlayStyle<T extends object>(\n base: T,\n ...partials: Array<Partial<T> | undefined>\n): T {\n const out = { ...base } as T;\n for (const partial of partials) {\n if (partial === undefined) continue;\n for (const key of Object.keys(partial) as Array<keyof T>) {\n const value = partial[key];\n if (value !== undefined) out[key] = value as T[keyof T];\n }\n }\n return out;\n}\n\n/** Data-driven element style override (§11); merged between theme and `.style`. */\nexport type ElementStyleResolver<TData = unknown> = (\n element: TimelineElement<TData>,\n) => Partial<ElementStyle>;\n\n/** Data-driven event style override (§11); merged between theme and `.style`. */\nexport type EventStyleResolver<TData = unknown> = (\n event: TimelineEvent<TData>,\n) => Partial<EventStyle>;\n","// Pure wheel-gesture interpretation (DESIGN.md §9).\n//\n// The wheel maps to three intents by modifier: `ctrl`/`⌘` (or a trackpad pinch,\n// which the browser reports as ctrl+wheel) → horizontal zoom about the cursor;\n// `shift`+wheel or a horizontal trackpad swipe (`deltaX`) → horizontal pan;\n// otherwise → vertical scroll. Kept pure over a minimal event shape so it\n// unit-tests in the node env without a DOM, and so the controller does no\n// pxPerMs/zoom-factor arithmetic of its own (the engine/Camera own that).\n\n/** The subset of `WheelEvent` this interpreter reads. */\nexport interface WheelEventLike {\n deltaX: number;\n deltaY: number;\n ctrlKey: boolean;\n metaKey: boolean;\n shiftKey: boolean;\n}\n\nexport type WheelIntent =\n | { kind: 'zoom'; factor: number; cursorX: number }\n | { kind: 'pan'; dxCss: number }\n | { kind: 'scroll'; dyCss: number };\n\n/** Pixels of wheel delta that halve/double the zoom; tuned for a smooth feel. */\nconst ZOOM_DELTA_PER_DOUBLING = 200;\n\n/**\n * Interpret a wheel event at canvas-local `cursorX` (CSS px). Zoom factor grows\n * exponentially in `deltaY` so repeated ticks compose multiplicatively and the\n * gesture is symmetric in/out: scrolling up (`deltaY < 0`) zooms in (factor > 1).\n */\nexport function interpretWheel(\n e: WheelEventLike,\n cursorX: number,\n): WheelIntent {\n if (e.ctrlKey || e.metaKey) {\n const factor = Math.pow(2, -e.deltaY / ZOOM_DELTA_PER_DOUBLING);\n return { kind: 'zoom', factor, cursorX };\n }\n if (e.shiftKey) {\n return { kind: 'pan', dxCss: -e.deltaY };\n }\n if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) {\n // Trackpad horizontal swipe: pan so that swiping left reveals later time.\n return { kind: 'pan', dxCss: -e.deltaX };\n }\n return { kind: 'scroll', dyCss: e.deltaY };\n}\n","// Pointer + wheel state machine (DESIGN.md §9).\n//\n// A pure input translator: it turns raw DOM pointer/wheel events into the\n// high-level intents of §9 (pan, zoom, scroll, hover, click) and forwards them\n// to an injected `PointerHost`. It performs NO coordinate or zoom arithmetic of\n// its own — pixel deltas and canvas-local screen coords go to the host, and the\n// engine/Camera own the math (single source of coordinate truth, §3). A small\n// drag threshold separates a click from a pan so selection and panning don't\n// fight. Hover positions are forwarded raw; the engine coalesces them to one\n// hit-test per animation frame (§9).\n\nimport { interpretWheel } from './wheel';\n\n/** Semantic intents the controller emits; the engine applies them. */\nexport interface PointerHost {\n /** Drag by a pixel delta (horizontal time pan + vertical scroll). */\n panBy(dxCss: number, dyCss: number): void;\n /** Zoom about the cursor by a multiplicative factor (§3). */\n zoomBy(factor: number, cursorX: number): void;\n /** Vertical scroll by a pixel delta. */\n scrollBy(dyCss: number): void;\n /** Pointer moved while not dragging — request a (coalesced) hit-test. */\n hoverAt(x: number, y: number): void;\n /** A click (press+release without a drag) at a point, with modifiers. */\n clickAt(\n x: number,\n y: number,\n mods: { ctrlOrMeta: boolean; shift: boolean },\n ): void;\n /** The pointer left the canvas — clear any hover. */\n leave(): void;\n}\n\n/** CSS px the pointer must move before a press becomes a pan rather than a click. */\nconst DRAG_THRESHOLD_PX = 4;\n\ntype State = 'idle' | 'down' | 'panning';\n\nexport class PointerController {\n private state: State = 'idle';\n private activePointer: number | null = null;\n private lastX = 0;\n private lastY = 0;\n private downX = 0;\n private downY = 0;\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly host: PointerHost,\n ) {\n canvas.addEventListener('pointerdown', this.onPointerDown);\n canvas.addEventListener('pointermove', this.onPointerMove);\n canvas.addEventListener('pointerup', this.onPointerUp);\n canvas.addEventListener('pointercancel', this.onPointerCancel);\n canvas.addEventListener('pointerleave', this.onPointerLeave);\n // `passive: false` so wheel zoom/pan can preventDefault the page scroll.\n canvas.addEventListener('wheel', this.onWheel, { passive: false });\n }\n\n /**\n * Convert a client position to canvas-local CSS px. Reads the bounding rect\n * once per call (one layout flush) — hover runs on every move, so the two\n * coords must not each force a separate reflow.\n */\n private local(clientX: number, clientY: number): { x: number; y: number } {\n const rect = this.canvas.getBoundingClientRect();\n return { x: clientX - rect.left, y: clientY - rect.top };\n }\n\n private readonly onPointerDown = (e: PointerEvent): void => {\n if (this.state !== 'idle') return;\n this.state = 'down';\n this.activePointer = e.pointerId;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n this.downX = e.clientX;\n this.downY = e.clientY;\n this.canvas.setPointerCapture(e.pointerId);\n };\n\n private readonly onPointerMove = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointer) {\n // Not dragging: a hover move. (When a drag is active, all moves belong to\n // it via pointer capture, so this branch only runs for true hovers.)\n if (this.state === 'idle') {\n const { x, y } = this.local(e.clientX, e.clientY);\n this.host.hoverAt(x, y);\n }\n return;\n }\n\n if (this.state === 'down') {\n const movedFar =\n Math.abs(e.clientX - this.downX) > DRAG_THRESHOLD_PX ||\n Math.abs(e.clientY - this.downY) > DRAG_THRESHOLD_PX;\n if (!movedFar) return;\n this.state = 'panning';\n // A drag has begun: drop any hover so the highlight/tooltip doesn't linger\n // at the stale press position while the content pans under it. (Wheel\n // zoom/scroll keep hover live — the cursor stays put there.)\n this.host.leave();\n }\n\n if (this.state === 'panning') {\n const dx = e.clientX - this.lastX;\n const dy = e.clientY - this.lastY;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n if (dx !== 0 || dy !== 0) this.host.panBy(dx, dy);\n }\n };\n\n private readonly onPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointer) return;\n // A press that never crossed the drag threshold is a click → hit-test.\n if (this.state === 'down') {\n const { x, y } = this.local(e.clientX, e.clientY);\n this.host.clickAt(x, y, {\n ctrlOrMeta: e.ctrlKey || e.metaKey,\n shift: e.shiftKey,\n });\n }\n this.release(e.pointerId);\n };\n\n private readonly onPointerCancel = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointer) return;\n this.release(e.pointerId);\n };\n\n private readonly onPointerLeave = (): void => {\n if (this.state === 'idle') this.host.leave();\n };\n\n private readonly onWheel = (e: WheelEvent): void => {\n const intent = interpretWheel(e, this.local(e.clientX, e.clientY).x);\n switch (intent.kind) {\n case 'zoom':\n e.preventDefault();\n this.host.zoomBy(intent.factor, intent.cursorX);\n break;\n case 'pan':\n e.preventDefault();\n this.host.panBy(intent.dxCss, 0);\n break;\n case 'scroll':\n e.preventDefault();\n this.host.scrollBy(intent.dyCss);\n break;\n }\n };\n\n private release(pointerId: number): void {\n this.state = 'idle';\n this.activePointer = null;\n if (this.canvas.hasPointerCapture(pointerId)) {\n this.canvas.releasePointerCapture(pointerId);\n }\n }\n\n dispose(): void {\n this.canvas.removeEventListener('pointerdown', this.onPointerDown);\n this.canvas.removeEventListener('pointermove', this.onPointerMove);\n this.canvas.removeEventListener('pointerup', this.onPointerUp);\n this.canvas.removeEventListener('pointercancel', this.onPointerCancel);\n this.canvas.removeEventListener('pointerleave', this.onPointerLeave);\n this.canvas.removeEventListener('wheel', this.onWheel);\n }\n}\n","// Screen-space hit-test grid (DESIGN.md §5).\n//\n// A uniform grid of fixed CSS-px cells mapping cell → the visible primitives\n// whose bounding box overlaps it. Built once per base redraw from the frame's\n// `HitTarget`s (camera/data change), then reused unchanged during pure hover so\n// a `pointermove` only tests the few candidates in the cursor's cell. The grid\n// stores no coordinate math of its own — targets arrive already in CSS px from\n// the builders.\n\nimport type { HitTarget } from '../render/specs';\n\n/** Cell size in CSS px (§5). */\nconst CELL_PX = 64;\n/**\n * Bounding-box padding so a target is registered in every cell its hit\n * tolerance can reach, even when its geometry only grazes a cell edge.\n */\nconst BBOX_PAD_PX = 6;\n\ninterface Bounds {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nfunction boundsOf(target: HitTarget): Bounds {\n if (target.kind === 'element') {\n const pad = BBOX_PAD_PX + target.width;\n return {\n minX: Math.min(target.x1, target.x2) - pad,\n maxX: Math.max(target.x1, target.x2) + pad,\n minY: target.y - pad,\n maxY: target.y + pad,\n };\n }\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n const consume = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n };\n for (const s of target.segments) {\n consume(s.x1, s.y1);\n consume(s.x2, s.y2);\n }\n if (target.kind === 'cluster') {\n consume(target.marker.x, target.marker.y);\n const pad = BBOX_PAD_PX + Math.max(target.width, target.markerSize);\n return {\n minX: minX - pad,\n minY: minY - pad,\n maxX: maxX + pad,\n maxY: maxY + pad,\n };\n }\n if (target.arrowhead) consume(target.arrowhead.x, target.arrowhead.y);\n if (target.node) consume(target.node.x, target.node.y);\n const pad = BBOX_PAD_PX + Math.max(target.width, target.arrowheadSize);\n return {\n minX: minX - pad,\n minY: minY - pad,\n maxX: maxX + pad,\n maxY: maxY + pad,\n };\n}\n\nexport class HitGrid<TData = unknown> {\n private readonly cells = new Map<string, HitTarget<TData>[]>();\n\n constructor(private readonly cellSize: number = CELL_PX) {}\n\n private static key(cx: number, cy: number): string {\n return `${cx},${cy}`;\n }\n\n /** Register a target in every cell its padded bounding box overlaps. */\n insert(target: HitTarget<TData>): void {\n const b = boundsOf(target);\n const cx0 = Math.floor(b.minX / this.cellSize);\n const cx1 = Math.floor(b.maxX / this.cellSize);\n const cy0 = Math.floor(b.minY / this.cellSize);\n const cy1 = Math.floor(b.maxY / this.cellSize);\n for (let cx = cx0; cx <= cx1; cx++) {\n for (let cy = cy0; cy <= cy1; cy++) {\n const key = HitGrid.key(cx, cy);\n let bucket = this.cells.get(key);\n if (bucket === undefined) {\n bucket = [];\n this.cells.set(key, bucket);\n }\n bucket.push(target);\n }\n }\n }\n\n /** Candidates whose cell contains the screen point (x,y), in insertion order. */\n query(x: number, y: number): readonly HitTarget<TData>[] {\n const key = HitGrid.key(\n Math.floor(x / this.cellSize),\n Math.floor(y / this.cellSize),\n );\n return this.cells.get(key) ?? [];\n }\n}\n\n/** Build a grid from a frame's targets (the one place targets are indexed). */\nexport function buildHitGrid<TData>(\n targets: readonly HitTarget<TData>[],\n): HitGrid<TData> {\n const grid = new HitGrid<TData>();\n for (const t of targets) grid.insert(t);\n return grid;\n}\n","// Pure 2-D geometry helpers for hit-testing (DESIGN.md §5).\n//\n// Hit-testing reduces to \"how far is the cursor from this primitive\": distance\n// to an arrow's orthogonal segment, distance to an element's horizontal line, or\n// containment in an arrowhead/marker box. These helpers work in CSS pixels and\n// have no dependency on the camera or the renderer, so they unit-test directly.\n\n/** Squared distance from point (px,py) to the segment (x1,y1)-(x2,y2). */\nexport function distSqToSegment(\n px: number,\n py: number,\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): number {\n const dx = x2 - x1;\n const dy = y2 - y1;\n const lenSq = dx * dx + dy * dy;\n // Degenerate segment (a point): distance to that point.\n const t = lenSq === 0 ? 0 : ((px - x1) * dx + (py - y1) * dy) / lenSq;\n const clamped = t < 0 ? 0 : t > 1 ? 1 : t;\n const cx = x1 + clamped * dx;\n const cy = y1 + clamped * dy;\n const ex = px - cx;\n const ey = py - cy;\n return ex * ex + ey * ey;\n}\n\n/** Whether (px,py) lies within `half` CSS px of the centre (cx,cy) on each axis. */\nexport function inSquare(\n px: number,\n py: number,\n cx: number,\n cy: number,\n half: number,\n): boolean {\n return Math.abs(px - cx) <= half && Math.abs(py - cy) <= half;\n}\n","// Resolve a screen point to a primitive (DESIGN.md §5, §9).\n//\n// Queries the per-frame hit grid for the few candidates near the cursor, then\n// does precise distance tests in CSS px: an arrow hit is proximity to its riser\n// segments or its arrowhead box; an element hit is proximity to its horizontal\n// line. Arrows draw on top of element lines, so an event hit wins over an\n// element hit at the same point. Returns the nearest match within tolerance, or\n// null. All geometry is pure (`geometry.ts`); the camera is not consulted here —\n// the grid already holds screen-space CSS px.\n\nimport { distSqToSegment, inSquare } from './geometry';\nimport type { HitGrid } from './hitGrid';\nimport type { HitResult } from './hit';\nimport type { HitTarget } from '../render/specs';\n\n/** Base pointer tolerance in CSS px, widened by each primitive's own width. */\nexport const HIT_TOLERANCE_PX = 5;\n\ninterface Candidate<TData> {\n target: HitTarget<TData>;\n distSq: number;\n}\n\nexport function hitTest<TData>(\n grid: HitGrid<TData>,\n x: number,\n y: number,\n tolerance: number = HIT_TOLERANCE_PX,\n): HitResult<TData> | null {\n // Arrows and cluster markers share the top draw layer; element lines sit\n // beneath. So `bestTop` (event or cluster) wins over `bestElement` at a point.\n let bestTop: Candidate<TData> | null = null;\n let bestElement: Candidate<TData> | null = null;\n\n for (const target of grid.query(x, y)) {\n if (target.kind === 'element') {\n const distSq = distSqToSegment(\n x,\n y,\n target.x1,\n target.y,\n target.x2,\n target.y,\n );\n const tol = tolerance + target.width / 2;\n if (\n distSq <= tol * tol &&\n (bestElement === null || distSq < bestElement.distSq)\n ) {\n bestElement = { target, distSq };\n }\n continue;\n }\n\n let distSq = Infinity;\n for (const s of target.segments) {\n distSq = Math.min(distSq, distSqToSegment(x, y, s.x1, s.y1, s.x2, s.y2));\n }\n if (target.kind === 'event') {\n // The arrowhead is a filled triangle; treat its bounding box as solid.\n if (\n target.arrowhead !== undefined &&\n inSquare(\n x,\n y,\n target.arrowhead.x,\n target.arrowhead.y,\n target.arrowheadSize,\n )\n ) {\n distSq = 0;\n }\n // The target dot sits on the target line, just past the arrowhead tip.\n if (\n target.targetNode !== undefined &&\n inSquare(\n x,\n y,\n target.targetNode.x,\n target.targetNode.y,\n target.arrowheadSize,\n )\n ) {\n distSq = 0;\n }\n } else if (\n inSquare(x, y, target.marker.x, target.marker.y, target.markerSize)\n ) {\n // Cluster: its count marker is a solid box around the riser midpoint.\n distSq = 0;\n }\n const tol = tolerance + target.width / 2;\n if (distSq <= tol * tol && (bestTop === null || distSq < bestTop.distSq)) {\n bestTop = { target, distSq };\n }\n }\n\n if (bestTop !== null) {\n const target = bestTop.target;\n if (target.kind === 'event') return { kind: 'event', event: target.event };\n if (target.kind === 'cluster') {\n return {\n kind: 'cluster',\n events: target.events,\n count: target.events.length,\n };\n }\n }\n if (bestElement !== null && bestElement.target.kind === 'element') {\n return { kind: 'element', element: bestElement.target.element };\n }\n return null;\n}\n","// Pure selection-state transition (DESIGN.md §9).\n//\n// Click selection is a pure function of the current selection, the clicked id\n// (or null for an empty click), the modifiers, and whether multi-select is\n// enabled. Keeping it pure means the engine just applies the result and the\n// rules are unit-testable without any DOM or canvas.\n\nexport interface SelectionMods {\n /** `ctrl` on Windows/Linux or `⌘` on macOS — the multi-select modifier. */\n ctrlOrMeta: boolean;\n}\n\nexport interface SelectionResult {\n /** The next selection, in stable order. */\n ids: string[];\n /** Whether the selection actually changed (drives `selectionChange` emission). */\n changed: boolean;\n}\n\n/**\n * Compute the next selection after a click (§9):\n * - multi-select off → plain click selects the hit (or clears on empty click);\n * - multi-select on → `ctrl`/`⌘`+click toggles the hit in/out, a plain click\n * replaces the selection with the hit (or clears on empty click).\n */\nexport function nextSelection(\n current: ReadonlySet<string>,\n hitId: string | null,\n mods: SelectionMods,\n multiSelect: boolean,\n): SelectionResult {\n const next = new Set(current);\n\n if (multiSelect && mods.ctrlOrMeta) {\n if (hitId === null) {\n // Modifier-click on empty space is a no-op (preserves the selection).\n return { ids: [...current], changed: false };\n }\n if (next.has(hitId)) next.delete(hitId);\n else next.add(hitId);\n } else {\n next.clear();\n if (hitId !== null) next.add(hitId);\n }\n\n return { ids: [...next], changed: !sameSet(current, next) };\n}\n\n/** Set equality by membership — the basis for \"did the selection change?\". */\nexport function sameSet(\n a: ReadonlySet<string>,\n b: ReadonlySet<string>,\n): boolean {\n if (a.size !== b.size) return false;\n for (const id of a) if (!b.has(id)) return false;\n return true;\n}\n","// Trailing-edge debounce (DESIGN.md §7 \"debounced recompute\", §10).\n//\n// Coalesces rapid calls into a single trailing invocation with the latest\n// arguments — used so high-frequency data mutations re-run layout once rather\n// than per mutation. Framework-free and timer-based (no rAF), so it is testable\n// with fake timers and reusable outside the render loop. `setTimeout` is\n// referenced lazily inside the call so the module stays import-safe in SSR.\n\nexport interface Debounced<TArgs extends unknown[]> {\n (...args: TArgs): void;\n /** Drop any pending trailing call (idempotent — safe to call when idle). */\n cancel(): void;\n /** Run a pending trailing call now, if one is scheduled. */\n flush(): void;\n}\n\nexport function debounce<TArgs extends unknown[]>(\n fn: (...args: TArgs) => void,\n delayMs: number,\n): Debounced<TArgs> {\n let handle: ReturnType<typeof setTimeout> | null = null;\n let pendingArgs: TArgs | null = null;\n\n const run = () => {\n handle = null;\n if (pendingArgs === null) return;\n const args = pendingArgs;\n pendingArgs = null;\n fn(...args);\n };\n\n const debounced = ((...args: TArgs) => {\n pendingArgs = args;\n if (handle !== null) clearTimeout(handle);\n handle = setTimeout(run, delayMs);\n }) as Debounced<TArgs>;\n\n debounced.cancel = () => {\n if (handle !== null) {\n clearTimeout(handle);\n handle = null;\n }\n pendingArgs = null;\n };\n\n debounced.flush = () => {\n if (handle !== null) {\n clearTimeout(handle);\n run();\n }\n };\n\n return debounced;\n}\n","// Typed pub/sub for engine events (DESIGN.md §9).\n//\n// The full event map is typed so on/off are checked against each event's\n// payload type. Phase 1 only EMITS viewportChange, ready, and dataChange; the\n// hover/click/selection events are part of the contract but fire from Phase 3.\n\nimport type { HitResult } from '../interaction/hit';\n\nexport interface TimelineEventMap<TData = unknown> {\n viewportChange: {\n timeRange: [number, number];\n scrollY: number;\n pxPerMs: number;\n visibleRowRange: [number, number];\n };\n hover: HitResult<TData> | null;\n click: {\n hit: HitResult<TData>;\n modifiers: { ctrlOrMeta: boolean; shift: boolean };\n };\n selectionChange: { ids: string[] };\n dataChange: { added: number; removed: number; updated: number };\n ready: void;\n}\n\ntype Listener<T> = (payload: T) => void;\n\nexport class TypedEmitter<M> {\n private readonly listeners = new Map<keyof M, Set<Listener<unknown>>>();\n\n on<K extends keyof M>(key: K, fn: Listener<M[K]>): () => void {\n let set = this.listeners.get(key);\n if (set === undefined) {\n set = new Set();\n this.listeners.set(key, set);\n }\n set.add(fn as Listener<unknown>);\n return () => this.off(key, fn);\n }\n\n off<K extends keyof M>(key: K, fn: Listener<M[K]>): void {\n this.listeners.get(key)?.delete(fn as Listener<unknown>);\n }\n\n emit<K extends keyof M>(key: K, payload: M[K]): void {\n const set = this.listeners.get(key);\n if (set === undefined) return;\n for (const fn of set) (fn as Listener<M[K]>)(payload);\n }\n\n clear(): void {\n this.listeners.clear();\n }\n}\n","// rAF render loop with per-layer dirty flags (DESIGN.md §4).\n//\n// Nothing redraws unless a layer is marked dirty — there is no continuous\n// repaint. Multiple markDirty calls before a frame coalesce into one render.\n// rAF is referenced lazily (inside markDirty) so the module is import-safe in\n// SSR environments.\n\nimport type { Layer } from '../render/types';\n\nexport interface DirtyFlags {\n base: boolean;\n overlay: boolean;\n}\n\nexport class FrameScheduler {\n private dirty: DirtyFlags = { base: false, overlay: false };\n private frameHandle: number | null = null;\n private disposed = false;\n\n constructor(private readonly render: (dirty: DirtyFlags) => void) {}\n\n markDirty(layer: Layer): void {\n if (this.disposed) return;\n this.dirty[layer] = true;\n if (this.frameHandle === null) {\n this.frameHandle = requestAnimationFrame(() => this.tick());\n }\n }\n\n private tick(): void {\n this.frameHandle = null;\n if (this.disposed) return;\n const dirty = this.dirty;\n this.dirty = { base: false, overlay: false };\n if (dirty.base || dirty.overlay) {\n this.render(dirty);\n }\n }\n\n dispose(): void {\n this.disposed = true;\n if (this.frameHandle !== null) {\n cancelAnimationFrame(this.frameHandle);\n this.frameHandle = null;\n }\n }\n}\n","// Default theme + shallow merge (DESIGN.md §11).\n//\n// Phase 1 ships the theme defaults only; the per-item style resolver chain\n// (resolver callback → per-item `style`) arrives in Phase 6.\n\nimport type { Theme } from '../model/types';\n\nexport const defaultTheme: Theme = {\n background: '#161b22',\n gridlineColor: 'rgba(255, 255, 255, 0.08)',\n headerTextColor: '#9aa4b2',\n headerFont: '12px system-ui, sans-serif',\n headerHeight: 44,\n rowHeight: 28,\n rowGap: 6,\n labelPadding: 8,\n hoverColor: '#ffd166',\n selectionColor: '#4fc3f7',\n clusterColor: '#d29922',\n element: {\n lineColor: '#5aa0ff',\n lineWidth: 2,\n labelColor: '#e6e6e6',\n labelFont: '12px system-ui, sans-serif',\n iconSize: 16,\n },\n event: {\n arrowColor: '#8b949e',\n arrowWidth: 1,\n arrowheadSize: 6,\n labelColor: '#c9d1d9',\n labelFont: '11px system-ui, sans-serif',\n nodeRadius: 3,\n },\n};\n\n/**\n * Merge a partial theme over the defaults. Top-level keys and the nested\n * `element`/`event` style objects are merged one level deep so a partial only\n * overrides the keys it sets.\n */\nexport function resolveTheme(partial?: Partial<Theme>): Theme {\n if (partial === undefined) return defaultTheme;\n return {\n ...defaultTheme,\n ...partial,\n element: { ...defaultTheme.element, ...partial.element },\n event: { ...defaultTheme.event, ...partial.event },\n };\n}\n","// The composition root and public engine API (DESIGN.md §2, §4, §12).\n//\n// A thin facade that wires the store, camera, layout, renderer, scheduler,\n// emitter, and pan controller together and owns the per-frame draw assembly.\n// It contains no coordinate math of its own (delegates to Camera) and no\n// validation of its own (delegates to DataStore).\n\nimport { byFirstEvent } from '../layout/byFirstEvent';\nimport { stableAppend } from '../layout/stableAppend';\nimport type { LayoutStrategy } from '../layout/types';\nimport { bySourceTargetColumn } from '../cluster/strategies';\nimport type { ClusterStrategy } from '../cluster/types';\nimport { computeRowLayout, type RowLayout } from '../layout/positions';\nimport type { OnDiagnostic } from '../model/diagnostics';\nimport { DataStore, type DataChangeCounts } from '../model/store';\nimport type {\n ElementStyle,\n EventStyle,\n TimelineData,\n TimelineElement,\n TimelineEvent,\n Theme,\n Time,\n} from '../model/types';\nimport { buildArrows } from '../render/arrows';\nimport { Canvas2DRenderer } from '../render/canvas2d';\nimport {\n hairlineOffset,\n scaleFontToDevice,\n snapDevice,\n} from '../render/device';\nimport { buildElementLines, markerReserveLeftPx } from '../render/elementLines';\nimport { IconCache, isIconUrl } from '../render/iconCache';\nimport { visibleRowBand } from '../render/rowBand';\nimport {\n snapArrowheads,\n snapIcons,\n snapLabels,\n snapLines,\n snapNodes,\n} from '../render/snap';\nimport type {\n BuildContext,\n ClusteringConfig,\n LodConfig,\n ResolveIcon,\n} from '../render/specs';\nimport type { LineSegment } from '../render/types';\nimport {\n Camera,\n computeZoomBounds,\n fit,\n type FitInset,\n type RowMetrics,\n type Viewport,\n} from '../scale/camera';\nimport { generateTicks, type TickFormatter } from '../scale/ticks';\nimport {\n overlayStyle,\n type ElementStyleResolver,\n type EventStyleResolver,\n} from '../render/resolveStyle';\nimport { PointerController, type PointerHost } from '../interaction/pointer';\nimport { buildHitGrid, type HitGrid } from '../interaction/hitGrid';\nimport { hitTest } from '../interaction/hitTest';\nimport type { HitResult } from '../interaction/hit';\nimport { nextSelection, sameSet } from '../interaction/selection';\nimport type { HitTarget } from '../render/specs';\nimport { debounce, type Debounced } from './debounce';\nimport { TypedEmitter, type TimelineEventMap } from './emitter';\nimport { FrameScheduler, type DirtyFlags } from './scheduler';\nimport { resolveTheme } from './theme';\n\n/** Event collapsing/aggregation config (DESIGN.md §6); all fields defaulted. */\nexport interface ClusteringOptions {\n /** Collapse dense events into count markers. Default `true`. */\n enabled?: boolean;\n /** Keying strategy. Default `bySourceTargetColumn`. */\n strategy?: ClusterStrategy;\n /** Pixel separation under which same-key events merge. Default 12. */\n minSeparationPx?: number;\n}\n\n/** Level-of-detail config (DESIGN.md §6); all fields defaulted. */\nexport interface LodOptions {\n /** Zoom (CSS px per ms) at/above which per-event labels are drawn. */\n eventLabelMinPxPerMs?: number;\n}\n\n/**\n * Per-frame timing for one drawn layer (DESIGN.md §13). Emitted to the optional\n * `onFrameStats` sink after each layer draw so hosts and the perf benchmark can\n * assert the §13 budgets (≤16ms base, ≤4ms overlay at 50k) without the engine\n * itself depending on `performance` or any logging implementation (DIP).\n */\nexport interface FrameStats {\n layer: 'base' | 'overlay';\n /** Wall-clock cost of the layer's draw, in milliseconds. */\n durationMs: number;\n}\n\n/**\n * Data-driven per-item style overrides (DESIGN.md §11). Each callback runs\n * between the theme default and the item's own `.style`; most specific wins.\n */\nexport interface StyleResolvers<TData = unknown> {\n element?: ElementStyleResolver<TData>;\n event?: EventStyleResolver<TData>;\n}\n\n/**\n * Label/tick text formatters (DESIGN.md §11). When omitted the engine echoes the\n * raw label (and the built-in UTC tick formatter of §8).\n */\nexport interface Formatters<TData = unknown> {\n tickLabel?: TickFormatter;\n eventLabel?: (event: TimelineEvent<TData>) => string;\n elementLabel?: (element: TimelineElement<TData>) => string;\n}\n\nexport interface TimelineEngineOptions<TData = unknown> {\n theme?: Partial<Theme>;\n onDiagnostic?: OnDiagnostic;\n layout?: LayoutStrategy;\n /**\n * Trailing-edge delay (ms) for coalescing incremental re-layouts (DESIGN.md\n * §7, §10). Applies only to the incremental seam ({@link scheduleLayoutRecompute});\n * a full `setData` always recomputes synchronously. Default 120.\n */\n layoutDebounceMs?: number;\n /** Allow `ctrl`/`⌘`+click to extend the selection (DESIGN.md §9). */\n multiSelect?: boolean;\n /**\n * Re-layout policy for incremental mutations (`addEvents`/… §10). Default\n * `'stable-append'`: existing rows stay put and new elements append, applied\n * synchronously so updates appear at once with no jarring reshuffle (§7).\n * `'full'` opts into re-running the configured {@link layout} strategy on the\n * debounced {@link layoutDebounceMs} seam. `setData` always relayouts in full.\n */\n streamingLayout?: 'stable-append' | 'full';\n clustering?: ClusteringOptions;\n lod?: LodOptions;\n /** Data-driven per-item style overrides (DESIGN.md §11). */\n styleResolvers?: StyleResolvers<TData>;\n /** Label/tick text formatters (DESIGN.md §11). */\n formatters?: Formatters<TData>;\n /**\n * Optional per-frame timing sink (DESIGN.md §13). When supplied, each layer\n * draw is bracketed with `performance.now()` and reported; when omitted the\n * draw path stays allocation- and measurement-free (zero overhead).\n */\n onFrameStats?: (stats: FrameStats) => void;\n}\n\n/** Minimum pixel spacing header labels need (§8). */\nconst MIN_LABEL_GAP_PX = 64;\nconst MS_PER_DAY = 86_400_000;\n/** Default clustering merge distance in CSS px (§6). */\nconst DEFAULT_CLUSTER_MIN_SEPARATION_PX = 12;\n/** Default label-LOD threshold: show event labels at ≥40 CSS px per day (§6). */\nconst DEFAULT_EVENT_LABEL_MIN_PX_PER_DAY = 40;\n/** Default trailing-edge delay (ms) for coalesced incremental re-layout (§7). */\nconst DEFAULT_LAYOUT_DEBOUNCE_MS = 120;\n\nexport class TimelineEngine<TData = unknown> {\n private readonly theme: Theme;\n private readonly metrics: RowMetrics;\n private readonly store: DataStore<TData>;\n private readonly camera: Camera;\n private readonly renderer: Canvas2DRenderer;\n private readonly scheduler: FrameScheduler;\n private readonly emitter = new TypedEmitter<TimelineEventMap<TData>>();\n private readonly pointer: PointerController;\n private readonly multiSelect: boolean;\n private readonly layoutStrategy: LayoutStrategy;\n /** Incremental re-layout policy (DESIGN.md §7, §10). */\n private readonly streamingLayout: 'stable-append' | 'full';\n /**\n * Coalesced incremental re-layout (DESIGN.md §7). Streaming mutations\n * (`addEvents`/`removeEvents`, §10) call {@link scheduleLayoutRecompute} so a\n * burst re-runs layout once; `setData` bypasses this and recomputes inline.\n */\n private readonly debouncedRecomputeLayout: Debounced<[]>;\n /** Resolved per-frame LOD/clustering config (DESIGN.md §6). */\n private readonly lod: LodConfig;\n private readonly clustering: ClusteringConfig;\n /**\n * §11 style/label resolution, bound once from the theme + host resolvers. The\n * builders receive these via `BuildContext`, so resolution lives in one place.\n */\n private readonly resolveElementStyle: (\n element: TimelineElement<TData>,\n ) => ElementStyle;\n private readonly resolveEventStyle: (\n event: TimelineEvent<TData>,\n ) => EventStyle;\n private readonly formatElementLabel: (\n element: TimelineElement<TData>,\n ) => string;\n private readonly formatEventLabel: (\n event: TimelineEvent<TData>,\n ) => string | undefined;\n private readonly tickFormatter: TickFormatter | undefined;\n /** Optional per-frame timing sink (DESIGN.md §13); undefined disables timing. */\n private readonly onFrameStats?: (stats: FrameStats) => void;\n private readonly iconCache = new IconCache(() =>\n this.scheduler.markDirty('base'),\n );\n\n /**\n * Resolve an element icon for the current frame (§1, §11): a preloaded image\n * is used directly when decoded, a URL is loaded/cached (skipped until ready),\n * and any other string (emoji/glyph) is drawn as text by the builder.\n */\n private readonly resolveIcon: ResolveIcon = (icon) => {\n if (typeof icon !== 'string') {\n return icon.complete && icon.naturalWidth > 0\n ? { kind: 'image', image: icon }\n : { kind: 'none' };\n }\n if (isIconUrl(icon)) {\n const image = this.iconCache.get(icon);\n return image ? { kind: 'image', image } : { kind: 'none' };\n }\n return { kind: 'text', text: icon };\n };\n\n private viewport: Viewport = { cssWidth: 0, cssHeight: 0 };\n private dpr = 1;\n private rowLayout: RowLayout = computeRowLayout([], {\n headerHeight: 0,\n rowHeight: 0,\n rowGap: 0,\n });\n private hasFitted = false;\n private disposed = false;\n\n // --- Interaction state (Phase 3, §9) ---\n /** Hit grid + targets rebuilt each base draw; reused during pure hover (§5). */\n private hitGrid: HitGrid<TData> | null = null;\n private frameTargets: HitTarget<TData>[] = [];\n /** Latest cursor position pending a (frame-coalesced) hit-test, or null. */\n private pendingPointer: { x: number; y: number } | null = null;\n private hovered: HitResult<TData> | null = null;\n private readonly selectedIds = new Set<string>();\n\n constructor(\n baseCanvas: HTMLCanvasElement,\n overlayCanvas: HTMLCanvasElement,\n options: TimelineEngineOptions<TData> = {},\n ) {\n this.theme = resolveTheme(options.theme);\n this.metrics = {\n headerHeight: this.theme.headerHeight,\n rowHeight: this.theme.rowHeight,\n rowGap: this.theme.rowGap,\n };\n this.layoutStrategy = options.layout ?? byFirstEvent;\n this.streamingLayout = options.streamingLayout ?? 'stable-append';\n this.debouncedRecomputeLayout = debounce(() => {\n if (this.disposed) return;\n this.recomputeLayout('full');\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }, options.layoutDebounceMs ?? DEFAULT_LAYOUT_DEBOUNCE_MS);\n this.multiSelect = options.multiSelect ?? false;\n this.clustering = {\n enabled: options.clustering?.enabled ?? true,\n strategy: options.clustering?.strategy ?? bySourceTargetColumn,\n minSeparationPx:\n options.clustering?.minSeparationPx ??\n DEFAULT_CLUSTER_MIN_SEPARATION_PX,\n };\n this.lod = {\n eventLabelMinPxPerMs:\n options.lod?.eventLabelMinPxPerMs ??\n DEFAULT_EVENT_LABEL_MIN_PX_PER_DAY / MS_PER_DAY,\n };\n // Bind §11 resolution once: theme → resolver → per-item `.style`. The theme is\n // fixed per engine instance, so binding here (not per frame) is correct.\n const elementResolver = options.styleResolvers?.element;\n this.resolveElementStyle = (element) =>\n overlayStyle(\n this.theme.element,\n elementResolver?.(element),\n element.style,\n );\n const eventResolver = options.styleResolvers?.event;\n this.resolveEventStyle = (event) =>\n overlayStyle(this.theme.event, eventResolver?.(event), event.style);\n this.formatElementLabel =\n options.formatters?.elementLabel ??\n ((element) => element.label ?? element.id);\n this.formatEventLabel =\n options.formatters?.eventLabel ?? ((event) => event.label);\n this.tickFormatter = options.formatters?.tickLabel;\n this.onFrameStats = options.onFrameStats;\n this.store = new DataStore<TData>({ onDiagnostic: options.onDiagnostic });\n this.camera = new Camera(this.metrics);\n this.renderer = new Canvas2DRenderer(\n baseCanvas,\n overlayCanvas,\n this.theme.background,\n );\n this.scheduler = new FrameScheduler((dirty) => this.drawFrame(dirty));\n // The overlay is the topmost layer, so it receives pointer events; the\n // pointer controller attaches there (base draws beneath it). The controller\n // is a pure input translator — all camera/hit-test math lives in this host.\n this.pointer = new PointerController(overlayCanvas, this.pointerHost());\n\n queueMicrotask(() => {\n if (!this.disposed) this.emitter.emit('ready', undefined);\n });\n }\n\n // --- Public API ---\n\n setData(data: TimelineData<TData>): void {\n const counts = this.store.setData(data);\n this.recomputeLayout('full');\n this.maybeFit();\n this.emitter.emit('dataChange', counts);\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n /** Incrementally insert events without a full rebuild (DESIGN.md §10). */\n addEvents(events: readonly TimelineEvent<TData>[]): void {\n this.applyMutation(this.store.addEvents(events));\n }\n\n /** Remove events by id (DESIGN.md §10). */\n removeEvents(ids: readonly string[]): void {\n this.applyMutation(this.store.removeEvents(ids));\n }\n\n /** Append elements with stable-append layout (DESIGN.md §7, §10). */\n addElements(elements: readonly TimelineElement<TData>[]): void {\n this.applyMutation(this.store.addElements(elements));\n }\n\n /** Patch an element's label/icon/style/order in place (DESIGN.md §10). */\n updateElement(id: string, patch: Partial<TimelineElement<TData>>): void {\n this.applyMutation(this.store.updateElement(id, patch));\n }\n\n /**\n * Shared tail for the incremental mutations (§10): a no-op change emits and\n * redraws nothing; otherwise re-layout (stable-append by default, §7), emit\n * `dataChange`, and mark the base dirty. Streaming never refits — that would\n * jerk the camera mid-stream.\n */\n private applyMutation(counts: DataChangeCounts): void {\n if (counts.added === 0 && counts.removed === 0 && counts.updated === 0) {\n return;\n }\n this.scheduleLayoutRecompute();\n this.emitter.emit('dataChange', counts);\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n resize(cssWidth: number, cssHeight: number, dpr: number): void {\n this.viewport = { cssWidth, cssHeight };\n this.dpr = dpr;\n this.renderer.resize(snapDevice(cssWidth, dpr), snapDevice(cssHeight, dpr));\n this.camera.setPxPerMs(this.camera.state.pxPerMs, this.zoomBounds());\n this.maybeFit();\n this.camera.clampScrollY(this.rowLayout.contentHeight, this.viewport);\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n fit(): void {\n fit(\n this.camera,\n this.store.getDataExtent(),\n this.viewport,\n this.now(),\n this.fitInset(),\n );\n this.hasFitted = true;\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n panToTime(t: Time): void {\n this.camera.setOriginTime(t);\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n /** Frame a time range across the viewport width (DESIGN.md §12). */\n zoomToRange(start: Time, end: Time): void {\n const span = end - start;\n if (!(span > 0) || this.viewport.cssWidth <= 0) return;\n this.camera.setOriginTime(start);\n this.camera.setPxPerMs(this.viewport.cssWidth / span, this.zoomBounds());\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n /**\n * Replace the selection imperatively (DESIGN.md §9, §12). Ids are the\n * `kind:id` composites produced by hit-testing (see {@link hitId}), so an\n * element and an event sharing a raw id stay distinct. A no-op replacement\n * emits nothing and skips the overlay redraw.\n */\n select(ids: string[]): void {\n const next = new Set(ids);\n if (sameSet(this.selectedIds, next)) return;\n this.selectedIds.clear();\n for (const id of next) this.selectedIds.add(id);\n this.emitter.emit('selectionChange', { ids: [...this.selectedIds] });\n this.scheduler.markDirty('overlay');\n }\n\n getViewport(): TimelineEventMap<TData>['viewportChange'] {\n const { scrollY, pxPerMs } = this.camera.state;\n const timeRange: [number, number] = [\n this.camera.screenXToTime(0),\n this.camera.screenXToTime(this.viewport.cssWidth),\n ];\n const top = Math.max(\n 0,\n Math.floor(this.camera.screenYToRow(this.metrics.headerHeight)),\n );\n const bottom = Math.min(\n this.rowLayout.rowCount,\n Math.ceil(this.camera.screenYToRow(this.viewport.cssHeight)),\n );\n return {\n timeRange,\n scrollY,\n pxPerMs,\n visibleRowRange: [top, Math.max(top, bottom)],\n };\n }\n\n on<K extends keyof TimelineEventMap<TData>>(\n key: K,\n fn: (payload: TimelineEventMap<TData>[K]) => void,\n ): () => void {\n return this.emitter.on(key, fn);\n }\n\n off<K extends keyof TimelineEventMap<TData>>(\n key: K,\n fn: (payload: TimelineEventMap<TData>[K]) => void,\n ): void {\n this.emitter.off(key, fn);\n }\n\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n this.debouncedRecomputeLayout.cancel();\n this.scheduler.dispose();\n this.pointer.dispose();\n this.emitter.clear();\n }\n\n // --- Internals ---\n\n private now(): Time {\n return Date.now();\n }\n\n private zoomBounds() {\n return computeZoomBounds(\n this.store.getDataExtent(),\n this.viewport,\n this.now(),\n this.fitInset(),\n );\n }\n\n /**\n * Edge space reserved when fitting (§3): a left gutter so the leftmost line's\n * start marker (icon + label, §1) clears the viewport edge instead of being\n * clipped. Derived from the theme so host themes scale it. With no elements\n * there are no markers, so nothing is reserved (the empty-state window stays\n * centred on `now`, §3.1).\n */\n private fitInset(): FitInset {\n if (this.store.getElements().length === 0) return {};\n return { left: markerReserveLeftPx(this.theme) };\n }\n\n /**\n * Recompute row order + positions (DESIGN.md §7). `'full'` runs the configured\n * strategy (used by `setData` and the opt-in streaming relayout); `'stable-append'`\n * keeps existing rows and appends new elements (the streaming default, §10).\n */\n private recomputeLayout(mode: 'full' | 'stable-append' = 'full'): void {\n const orderedIds =\n mode === 'full'\n ? this.layoutStrategy.order(\n this.store.getElements(),\n this.store.getEvents(),\n )\n : stableAppend(this.rowLayout.orderedIds, this.store.getElements());\n this.rowLayout = computeRowLayout(orderedIds, this.metrics);\n this.camera.clampScrollY(this.rowLayout.contentHeight, this.viewport);\n }\n\n /**\n * Apply layout after an *incremental* mutation (DESIGN.md §7, §10). By default\n * (`streamingLayout: 'stable-append'`) this runs synchronously so new rows and\n * extents appear at once with no reshuffle; under `'full'` a burst is coalesced\n * into one trailing strategy recompute via the debounced seam. Full `setData`\n * bypasses this and recomputes synchronously so `fit`/scroll-clamp see\n * `contentHeight` immediately.\n */\n private scheduleLayoutRecompute(): void {\n if (this.streamingLayout === 'full') {\n this.debouncedRecomputeLayout();\n } else {\n this.recomputeLayout('stable-append');\n }\n }\n\n /**\n * Frame the view before the first explicit fit. With data, fit to it once and\n * latch (`hasFitted`). Without data, frame the default window on `now` (§3.1)\n * but stay un-latched, so real data still auto-fits when it arrives.\n */\n private maybeFit(): void {\n if (this.hasFitted || this.viewport.cssWidth <= 0) return;\n if (this.store.getDataExtent() !== null) {\n this.fit();\n return;\n }\n fit(this.camera, null, this.viewport, this.now(), this.fitInset());\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n /** Mark the base layer dirty and emit the new viewport (any camera change). */\n private onCameraChange(): void {\n this.scheduler.markDirty('base');\n this.emitViewportChange();\n }\n\n /**\n * The semantic-intent sink for the pointer controller (§9). The controller\n * does no math; every camera mutation and hit-test is applied here so the\n * Camera stays the single source of coordinate truth (§3).\n */\n private pointerHost(): PointerHost {\n return {\n panBy: (dx, dy) => {\n this.camera.panByPixels(dx, dy);\n this.camera.clampScrollY(this.rowLayout.contentHeight, this.viewport);\n this.onCameraChange();\n },\n zoomBy: (factor, cursorX) => {\n this.camera.zoomAboutCursor(factor, cursorX, this.zoomBounds());\n this.onCameraChange();\n },\n scrollBy: (dy) => {\n this.camera.panByPixels(0, -dy);\n this.camera.clampScrollY(this.rowLayout.contentHeight, this.viewport);\n this.onCameraChange();\n },\n hoverAt: (x, y) => {\n // Coalesced to one hit-test per frame: store the latest position and\n // let the overlay draw resolve it (§9).\n this.pendingPointer = { x, y };\n this.scheduler.markDirty('overlay');\n },\n clickAt: (x, y, mods) => this.onClick(x, y, mods),\n leave: () => {\n this.pendingPointer = null;\n if (this.hovered !== null) {\n this.hovered = null;\n this.emitter.emit('hover', null);\n this.scheduler.markDirty('overlay');\n }\n },\n };\n }\n\n /** Resolve a click against the current hit grid: emit click + update selection. */\n private onClick(\n x: number,\n y: number,\n mods: { ctrlOrMeta: boolean; shift: boolean },\n ): void {\n const hit = this.hitGrid ? hitTest(this.hitGrid, x, y) : null;\n if (hit !== null) this.emitter.emit('click', { hit, modifiers: mods });\n\n // A cluster is an ephemeral aggregate, not a selectable entity: clicking it\n // expands the collapsed events by zooming to their span (§6), leaving the\n // selection untouched.\n if (hit?.kind === 'cluster') {\n this.expandCluster(hit.events);\n return;\n }\n\n const result = nextSelection(\n this.selectedIds,\n hit !== null ? hitId(hit) : null,\n mods,\n this.multiSelect,\n );\n if (result.changed) {\n this.selectedIds.clear();\n for (const id of result.ids) this.selectedIds.add(id);\n this.emitter.emit('selectionChange', { ids: result.ids });\n this.scheduler.markDirty('overlay');\n }\n }\n\n /** Zoom to a clicked cluster's member time span, expanding it (§6). */\n private expandCluster(events: readonly { time: Time }[]): void {\n let min = Infinity;\n let max = -Infinity;\n for (const event of events) {\n if (event.time < min) min = event.time;\n if (event.time > max) max = event.time;\n }\n // zoomToRange no-ops on a zero/negative span (e.g. same-instant clusters).\n if (Number.isFinite(min)) this.zoomToRange(min, max);\n }\n\n private emitViewportChange(): void {\n if (this.viewport.cssWidth <= 0 || !(this.camera.state.pxPerMs > 0)) return;\n this.emitter.emit('viewportChange', this.getViewport());\n }\n\n private drawFrame(dirty: DirtyFlags): void {\n if (this.disposed) return;\n if (dirty.base) this.timed('base', this.drawBase);\n // The overlay highlights this frame's `frameTargets`, which `drawBase`\n // rebuilds at the current camera position. So it must re-render whenever the\n // base moved — not only on overlay-only (hover/selection) changes —\n // otherwise a pan/zoom slides the content while a stale highlight stays\n // pinned to its old screen position. (§4's independence is the *other*\n // direction: an overlay-only change never forces a base redraw.)\n if (dirty.base || dirty.overlay) this.timed('overlay', this.drawOverlay);\n }\n\n /**\n * Run one layer's draw, reporting its wall-clock cost to `onFrameStats` when a\n * sink is set (DESIGN.md §13). With no sink the draw runs directly — no\n * `performance.now()` calls, no allocation — so timing is truly opt-in.\n */\n private timed(layer: 'base' | 'overlay', draw: () => void): void {\n if (this.onFrameStats === undefined) {\n draw.call(this);\n return;\n }\n const start = performance.now();\n draw.call(this);\n this.onFrameStats({ layer, durationMs: performance.now() - start });\n }\n\n private drawBase(): void {\n const { cssWidth, cssHeight } = this.viewport;\n const { headerHeight } = this.metrics;\n const dpr = this.dpr;\n this.renderer.beginFrame('base');\n\n const ticks = generateTicks(\n this.camera.screenXToTime(0),\n this.camera.screenXToTime(cssWidth),\n this.camera.state.pxPerMs,\n MIN_LABEL_GAP_PX,\n this.tickFormatter,\n );\n\n // Major gridlines run from the header bottom down through the content; drawn\n // before content so element lines and arrows sit over them.\n const gridWidth = Math.max(1, snapDevice(1, dpr));\n const gridSegments: LineSegment[] = ticks.major.map((tick) => {\n const x =\n snapDevice(this.camera.timeToScreenX(tick.time), dpr) +\n hairlineOffset(gridWidth);\n return {\n x1: x,\n y1: snapDevice(headerHeight, dpr),\n x2: x,\n y2: snapDevice(cssHeight, dpr),\n };\n });\n this.renderer.drawLines({\n color: this.theme.gridlineColor,\n width: gridWidth,\n segments: gridSegments,\n });\n\n // Content: build CSS-px primitives, snap to device px, draw bottom-to-top\n // (lines → risers → source nodes → arrowheads → labels → icons).\n const ctx: BuildContext<TData> = {\n camera: this.camera,\n rowLayout: this.rowLayout,\n data: this.store,\n viewport: this.viewport,\n theme: this.theme,\n band: visibleRowBand(\n this.camera,\n this.viewport,\n this.rowLayout.rowCount,\n headerHeight,\n ),\n resolveIcon: this.resolveIcon,\n lod: this.lod,\n clustering: this.clustering,\n resolveElementStyle: this.resolveElementStyle,\n resolveEventStyle: this.resolveEventStyle,\n formatElementLabel: this.formatElementLabel,\n formatEventLabel: this.formatEventLabel,\n };\n const elements = buildElementLines(ctx);\n const arrows = buildArrows(ctx);\n\n // Rebuild the hit-test index from this frame's visible primitives (§5). It\n // is reused unchanged for pure hover until the next base redraw.\n this.frameTargets = [...elements.targets, ...arrows.targets];\n this.hitGrid = buildHitGrid(this.frameTargets);\n\n for (const spec of elements.lines) {\n this.renderer.drawLines(snapLines(spec, dpr));\n }\n for (const spec of arrows.lines) {\n this.renderer.drawLines(snapLines(spec, dpr));\n }\n for (const spec of arrows.nodes) {\n this.renderer.drawNodes(snapNodes(spec, dpr));\n }\n for (const spec of arrows.arrowheads) {\n this.renderer.drawArrowheads(snapArrowheads(spec, dpr));\n }\n for (const spec of arrows.labels) {\n this.renderer.drawText(snapLabels(spec, dpr));\n }\n for (const spec of elements.labels) {\n this.renderer.drawText(snapLabels(spec, dpr));\n }\n this.renderer.drawImages(snapIcons(elements.icons, dpr));\n\n // Header is drawn last (§4): mask any content that bled into the header\n // band, then draw the baseline separator and the adaptive tick labels.\n this.renderer.fillRect(\n 0,\n 0,\n snapDevice(cssWidth, dpr),\n snapDevice(headerHeight, dpr),\n this.theme.background,\n );\n const baselineY = snapDevice(headerHeight, dpr) + hairlineOffset(gridWidth);\n this.renderer.drawLines({\n color: this.theme.gridlineColor,\n width: gridWidth,\n segments: [\n { x1: 0, y1: baselineY, x2: snapDevice(cssWidth, dpr), y2: baselineY },\n ],\n });\n\n const headerFont = scaleFontToDevice(this.theme.headerFont, dpr);\n this.renderer.drawText({\n color: this.theme.headerTextColor,\n font: headerFont,\n baseline: 'middle',\n align: 'center',\n items: ticks.major.map((tick) => ({\n x: snapDevice(this.camera.timeToScreenX(tick.time), dpr),\n y: snapDevice(headerHeight * 0.32, dpr),\n text: tick.label,\n })),\n });\n this.renderer.drawText({\n color: this.theme.headerTextColor,\n font: headerFont,\n baseline: 'middle',\n align: 'center',\n items: ticks.minor.map((tick) => ({\n x: snapDevice(this.camera.timeToScreenX(tick.time), dpr),\n y: snapDevice(headerHeight * 0.72, dpr),\n text: tick.label,\n })),\n });\n\n this.renderer.endFrame('base');\n }\n\n /**\n * Overlay pass (DESIGN.md §4, §9): resolve the pending hover against the hit\n * grid (emitting `hover` only on change), then redraw the hovered and selected\n * primitives in the highlight/selection colours. It reuses this frame's\n * `frameTargets` geometry — no recompute — and never touches the base layer,\n * so hover/selection stay independent of the expensive base redraw.\n */\n private drawOverlay(): void {\n this.resolveHover();\n this.renderer.beginFrame('overlay');\n\n const dpr = this.dpr;\n const hoveredKey = this.hovered !== null ? hitId(this.hovered) : null;\n // Highlighting an element also lights its connected events (§9): collect the\n // hovered/selected *element* ids so an arrow touching one is highlighted too.\n const hoveredElementId =\n this.hovered?.kind === 'element' ? this.hovered.element.id : null;\n const selectedElementIds = elementIdsFromKeys(this.selectedIds);\n\n for (const target of this.frameTargets) {\n const color = this.highlightColorFor(\n target,\n hoveredKey,\n hoveredElementId,\n selectedElementIds,\n );\n if (color !== null) this.drawHighlight(target, color, dpr);\n }\n\n this.renderer.endFrame('overlay');\n }\n\n /**\n * Overlay colour for a target, or null when it should not highlight. A target\n * highlights when it is itself hovered/selected, or — for an event/cluster —\n * when one of its endpoints is a hovered/selected element (§9). Hover wins the\n * colour over selection.\n */\n private highlightColorFor(\n target: HitTarget<TData>,\n hoveredKey: string | null,\n hoveredElementId: string | null,\n selectedElementIds: ReadonlySet<string>,\n ): string | null {\n const key = targetKey(target);\n const hovered =\n key === hoveredKey ||\n (hoveredElementId !== null && touchesElement(target, hoveredElementId));\n if (hovered) return this.theme.hoverColor;\n const selected =\n this.selectedIds.has(key) ||\n touchesAnyElement(target, selectedElementIds);\n if (selected) return this.theme.selectionColor;\n return null;\n }\n\n /** Run the coalesced hit-test for the latest cursor position and emit on change. */\n private resolveHover(): void {\n if (this.pendingPointer === null || this.hitGrid === null) return;\n const hit = hitTest(\n this.hitGrid,\n this.pendingPointer.x,\n this.pendingPointer.y,\n );\n const nextKey = hit !== null ? hitId(hit) : null;\n const prevKey = this.hovered !== null ? hitId(this.hovered) : null;\n if (nextKey !== prevKey) {\n this.hovered = hit;\n this.emitter.emit('hover', hit);\n }\n }\n\n /** Redraw one target's geometry in `color`, slightly thickened, on the overlay. */\n private drawHighlight(\n target: HitTarget<TData>,\n color: string,\n dpr: number,\n ): void {\n if (target.kind === 'element') {\n this.renderer.drawLines(\n snapLines(\n {\n color,\n width: target.width + 2,\n segments: [\n { x1: target.x1, y1: target.y, x2: target.x2, y2: target.y },\n ],\n },\n dpr,\n ),\n );\n return;\n }\n if (target.kind === 'cluster') {\n if (target.segments.length > 0) {\n this.renderer.drawLines(\n snapLines(\n { color, width: target.width + 2, segments: target.segments },\n dpr,\n ),\n );\n }\n this.renderer.drawNodes(\n snapNodes(\n { color, radius: target.markerSize + 1, items: [target.marker] },\n dpr,\n ),\n );\n return;\n }\n this.renderer.drawLines(\n snapLines(\n { color, width: target.width + 2, segments: target.segments },\n dpr,\n ),\n );\n const dots = [target.node, target.targetNode].filter(\n (n): n is { x: number; y: number } => n !== undefined,\n );\n if (dots.length > 0) {\n this.renderer.drawNodes(\n snapNodes(\n { color, radius: this.theme.event.nodeRadius + 1, items: dots },\n dpr,\n ),\n );\n }\n if (target.arrowhead !== undefined) {\n this.renderer.drawArrowheads(\n snapArrowheads(\n {\n color,\n size: target.arrowheadSize + 1,\n items: [{ ...target.arrowhead, angle: arrowheadAngle(target) }],\n },\n dpr,\n ),\n );\n }\n }\n}\n\n/** Stable key (`kind:id`) for comparing a hit across frames. */\nfunction hitId(hit: HitResult): string {\n switch (hit.kind) {\n case 'element':\n return `element:${hit.element.id}`;\n case 'event':\n return `event:${hit.event.id}`;\n case 'cluster':\n return `cluster:${hit.events.map((e) => e.id).join(',')}`;\n }\n}\n\n/** The `kind:id` key matching {@link hitId} for a target. */\nfunction targetKey(target: HitTarget): string {\n switch (target.kind) {\n case 'element':\n return `element:${target.element.id}`;\n case 'event':\n return `event:${target.event.id}`;\n case 'cluster':\n return `cluster:${target.events.map((e) => e.id).join(',')}`;\n }\n}\n\nconst ELEMENT_KEY_PREFIX = 'element:';\n\n/** Element ids embedded in a set of selection keys (`element:<id>`). */\nfunction elementIdsFromKeys(keys: ReadonlySet<string>): Set<string> {\n const ids = new Set<string>();\n for (const key of keys) {\n if (key.startsWith(ELEMENT_KEY_PREFIX)) {\n ids.add(key.slice(ELEMENT_KEY_PREFIX.length));\n }\n }\n return ids;\n}\n\n/** Element ids an event/cluster target connects to; empty for an element target. */\nfunction targetElementIds(target: HitTarget): string[] {\n switch (target.kind) {\n case 'element':\n return [];\n case 'event':\n return [target.event.sourceId, target.event.targetId];\n case 'cluster':\n return target.events.flatMap((e) => [e.sourceId, e.targetId]);\n }\n}\n\nfunction touchesElement(target: HitTarget, elementId: string): boolean {\n return targetElementIds(target).includes(elementId);\n}\n\nfunction touchesAnyElement(\n target: HitTarget,\n ids: ReadonlySet<string>,\n): boolean {\n return ids.size > 0 && targetElementIds(target).some((id) => ids.has(id));\n}\n\n/** Recover the arrowhead direction from a target's last segment (y-down). */\nfunction arrowheadAngle(target: {\n segments: { y1: number }[];\n arrowhead?: { y: number };\n}): number {\n const last = target.segments[target.segments.length - 1];\n if (last === undefined || target.arrowhead === undefined) return Math.PI / 2;\n return target.arrowhead.y >= last.y1 ? Math.PI / 2 : -Math.PI / 2;\n}\n","// Crossing-reduction layout: iterative barycenter sweeps (DESIGN.md §7).\n//\n// This is *not* layered (Sugiyama) graph drawing — there are no layers; arrows\n// run between arbitrary rows at arbitrary times. It is the single-axis\n// ordering/linear-arrangement problem (NP-hard), for which iterative barycenter\n// sweeps are a standard heuristic: starting from an order, repeatedly reposition\n// each row at the (weighted) average row-index of its neighbours to pull\n// strongly-connected elements together and reduce arrow vertical span/crossings.\n\nimport { byFirstEvent } from './byFirstEvent';\nimport type { LayoutStrategy } from './types';\n\n/** Sweeps to run; each is O(elements + edges). 8 converges on typical graphs. */\nconst MAX_SWEEPS = 8;\n\n/** Shared empty neighbour map (every seed id is in `adjacency`, so unreachable). */\nconst NO_NEIGHBOURS: ReadonlyMap<string, number> = new Map();\n\n/**\n * Undirected neighbour weights keyed by element id. An event contributes a unit\n * of attraction between its endpoints; repeated edges between the same pair add\n * up, so heavily-connected elements pull together more strongly. Self-events\n * (`sourceId === targetId`) add no ordering constraint and are skipped.\n */\ntype Adjacency = Map<string, Map<string, number>>;\n\nfunction buildAdjacency(\n ids: readonly string[],\n events: readonly { sourceId: string; targetId: string }[],\n): Adjacency {\n const adjacency: Adjacency = new Map();\n for (const id of ids) adjacency.set(id, new Map());\n const link = (a: string, b: string) => {\n const neighbours = adjacency.get(a);\n if (neighbours === undefined) return; // edge endpoint not in the element set\n neighbours.set(b, (neighbours.get(b) ?? 0) + 1);\n };\n for (const { sourceId, targetId } of events) {\n if (sourceId === targetId) continue;\n link(sourceId, targetId);\n link(targetId, sourceId);\n }\n return adjacency;\n}\n\n/**\n * Weighted mean of a node's neighbours' current row indices, or `null` when it\n * has no neighbours (such nodes keep their position via the stable tiebreak).\n */\nfunction barycenterOf(\n neighbours: ReadonlyMap<string, number>,\n rowIndexById: Map<string, number>,\n): number | null {\n let weightedSum = 0;\n let weight = 0;\n for (const [neighbourId, w] of neighbours) {\n const row = rowIndexById.get(neighbourId);\n if (row === undefined) continue;\n weightedSum += row * w;\n weight += w;\n }\n return weight === 0 ? null : weightedSum / weight;\n}\n\n/**\n * Total vertical span of all edges under an ordering: Σ weight·|row(a) − row(b)|.\n * This is the linear-arrangement objective the sweeps drive down, and it is\n * O(edges) — cheap enough to evaluate every sweep so we can return the *best*\n * order seen rather than whichever the final sweep happened to land on (sweeps\n * can oscillate; see `order`). Each undirected edge is counted from both of its\n * endpoints, so the sum double-counts — harmless, since it is only ever compared\n * against other spans computed the same way.\n */\nfunction totalEdgeSpan(order: readonly string[], adjacency: Adjacency): number {\n const rowIndexById = new Map(order.map((id, index) => [id, index]));\n let span = 0;\n for (const [id, neighbours] of adjacency) {\n const row = rowIndexById.get(id);\n if (row === undefined) continue;\n for (const [neighbourId, weight] of neighbours) {\n const neighbourRow = rowIndexById.get(neighbourId);\n if (neighbourRow === undefined) continue;\n span += Math.abs(row - neighbourRow) * weight;\n }\n }\n return span;\n}\n\nexport const barycenter: LayoutStrategy = {\n order(elements, events): string[] {\n // Seed from the default chronological order: a stable, sensible start that\n // already groups by introduction time (DRY — reuse byFirstEvent).\n const seed = byFirstEvent.order(elements, events);\n if (seed.length < 3) return seed; // nothing to reduce\n\n const adjacency = buildAdjacency(seed, events);\n\n // Each sweep recomputes every node's barycenter from the *same* snapshot of\n // the previous order, then re-sorts globally — a Jacobi-style update, not\n // the node-by-node Gauss-Seidel \"alternating direction\" variant. It is\n // simpler and order-independent, at the cost of period-2 oscillation between\n // two orderings. We tame that by (a) stopping as soon as an order repeats\n // either of the last two, and (b) returning the lowest-span order *seen*\n // across all sweeps, never merely the final one — so the result is robust to\n // the oscillation and can never be worse than the seed.\n let order = seed;\n let best = seed;\n let bestSpan = totalEdgeSpan(seed, adjacency);\n let twoBackKey = '';\n let previousKey = seed.join(' ');\n\n for (let sweep = 0; sweep < MAX_SWEEPS; sweep++) {\n const rowIndexById = new Map(order.map((id, index) => [id, index]));\n // Decorate with the barycenter; nodes without neighbours keep their row so\n // they don't drift. A stable sort on the row keeps equal barycenters in\n // their current relative order (deterministic).\n const ranked = order.map((id, index) => {\n const key = barycenterOf(\n adjacency.get(id) ?? NO_NEIGHBOURS,\n rowIndexById,\n );\n return { id, index, key: key ?? index };\n });\n ranked.sort((a, b) =>\n a.key !== b.key ? a.key - b.key : a.index - b.index,\n );\n order = ranked.map((entry) => entry.id);\n\n const span = totalEdgeSpan(order, adjacency);\n if (span < bestSpan) {\n best = order;\n bestSpan = span;\n }\n\n // Converged (period 1) or oscillating (period 2): further sweeps only\n // revisit these same orders, so stop and keep the best already found.\n const key = order.join(' ');\n if (key === previousKey || key === twoBackKey) break;\n twoBackKey = previousKey;\n previousKey = key;\n }\n\n return best;\n },\n};\n","// Explicit/pinned layout: honour `element.order` exactly (DESIGN.md §7, §1).\n//\n// Host-controlled ordering — the hook a future drag-to-reorder feature would\n// write into. Elements carrying a finite numeric `order` are placed first, in\n// ascending `order` (stable on input position for ties). Elements without an\n// `order` hint have no pin, so they fall back to the default chronological\n// `byFirstEvent` order and follow the pinned block (reuse — DRY).\n\nimport { byFirstEvent } from './byFirstEvent';\nimport type { LayoutStrategy } from './types';\nimport type { TimelineElement } from '../model/types';\n\nexport const explicit: LayoutStrategy = {\n order(elements, events): string[] {\n const pinned: { id: string; order: number; index: number }[] = [];\n const unpinned: TimelineElement[] = [];\n for (let index = 0; index < elements.length; index++) {\n const element = elements[index]!;\n if (Number.isFinite(element.order)) {\n pinned.push({ id: element.id, order: element.order!, index });\n } else {\n unpinned.push(element);\n }\n }\n\n pinned.sort((a, b) =>\n a.order !== b.order ? a.order - b.order : a.index - b.index,\n );\n\n return [\n ...pinned.map((entry) => entry.id),\n ...byFirstEvent.order(unpinned, events),\n ];\n },\n};\n","// Public entry point for @event-timeline/core.\n//\n// Phase 1 exposes the engine facade (TimelineEngine) plus the domain, layout,\n// theme, and diagnostic types hosts need. The internals — Camera, DataStore,\n// Renderer/Canvas2DRenderer, scheduler, controllers — are deliberately NOT\n// exported, keeping the seam and the bundle surface minimal (DESIGN.md §2).\n\n/** Current package version placeholder; real releases are driven by Changesets. */\nexport const VERSION = '0.0.0';\n\nexport type {\n Time,\n TimelineElement,\n TimelineEvent,\n TimelineData,\n ElementStyle,\n EventStyle,\n Theme,\n} from './model/types';\n\nexport type {\n Diagnostic,\n DiagnosticCode,\n OnDiagnostic,\n} from './model/diagnostics';\n\nexport { TimelineEngine } from './engine/timeline';\nexport type {\n TimelineEngineOptions,\n ClusteringOptions,\n LodOptions,\n StyleResolvers,\n Formatters,\n FrameStats,\n} from './engine/timeline';\nexport type { TimelineEventMap } from './engine/emitter';\n\nexport { overlayStyle } from './render/resolveStyle';\nexport type {\n ElementStyleResolver,\n EventStyleResolver,\n} from './render/resolveStyle';\nexport type { TickFormatter, TickLevel } from './scale/ticks';\n\nexport { byFirstEvent, barycenter, explicit } from './layout';\nexport type { LayoutStrategy } from './layout/types';\n\nexport {\n byPixelColumn,\n byElementPair,\n byDay,\n bySourceTargetColumn,\n} from './cluster/strategies';\nexport type { ClusterStrategy, ClusterContext, Cluster } from './cluster/types';\n\nexport { defaultTheme } from './engine/theme';\n\nexport type { HitResult } from './interaction/hit';\n"]}