{"version":3,"sources":["../../src/core/type-registry.ts","../../src/core/semantic-types.ts","../../src/core/decisions.ts","../../src/core/field-semantics.ts","../../src/core/resolve-semantics.ts","../../src/core/axis-detection.ts","../../src/core/compute-layout.ts","../../src/core/filter-overflow.ts","../../src/excel/chart-types.ts","../../src/excel/templates/area.ts","../../src/excel/templates/bar.ts","../../src/excel/templates/boxplot.ts","../../src/excel/templates/candlestick.ts","../../src/excel/templates/funnel.ts","../../src/excel/templates/histogram.ts","../../src/excel/templates/line.ts","../../src/excel/templates/pie.ts","../../src/excel/templates/pyramid.ts","../../src/excel/templates/radar.ts","../../src/excel/templates/types.ts","../../src/excel/templates/scatter.ts","../../src/excel/templates/sunburst.ts","../../src/excel/templates/treemap.ts","../../src/chart-types/waterfall.ts","../../src/excel/templates/waterfall.ts","../../src/excel/templates/index.ts","../../src/excel/assemble.ts","../../src/excel/artifact.ts","../../src/excel/codegen.ts","../../src/excel/runtime.ts"],"names":["distinct","ar","nRows","uniqueValues","decimals","niceMaximum","niceStep"],"mappings":";;;AAgFA,IAAM,aAAA,GAAmD;AAAA;AAAA,EAErD,QAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,UAAU,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAmB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC1N,IAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,UAAU,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAmB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC1N,IAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,UAAU,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAmB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC1N,SAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,UAAU,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAmB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAG1N,IAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,UAAA,EAAY,SAAS,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,SAAA,EAAkB,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,IAAA,EAAK;AAAA,EACpO,OAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,SAAS,CAAA,EAAc,SAAS,WAAA,EAAa,WAAA,EAAa,UAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAkB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,KAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,SAAS,CAAA,EAAc,SAAS,WAAA,EAAa,WAAA,EAAa,UAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAkB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,IAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,SAAS,CAAA,EAAc,SAAS,WAAA,EAAa,WAAA,EAAa,UAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAkB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,GAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,SAAS,CAAA,EAAc,SAAS,WAAA,EAAa,WAAA,EAAa,UAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAkB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,IAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,SAAS,CAAA,EAAc,SAAS,WAAA,EAAa,WAAA,EAAa,UAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,SAAA,EAAkB,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,CAAA,EAAE;AAAA,EAChO,SAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,UAAA,EAAY,SAAS,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,QAAU,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAkB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,WAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,UAAA,EAAY,SAAS,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,QAAU,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAkB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,QAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,UAAA,EAAY,SAAS,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,QAAU,SAAA,EAAW,MAAA,EAAQ,aAAa,OAAA,EAAkB,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,MAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,aAAA,EAAe,YAAA,EAAc,CAAC,UAAA,EAAY,SAAS,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,QAAU,SAAA,EAAW,MAAA,EAAQ,aAAa,SAAA,EAAkB,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,IAAA,EAAK;AAAA;AAAA,EAGnO,QAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,cAAc,CAAA,EAAS,SAAS,UAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAQ,aAAa,aAAA,EAAmB,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAGhO,MAAA,EAAe,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,QAAA,EAAU,YAAA,EAAc,CAAC,cAAc,CAAA,EAAY,SAAS,UAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,UAAA,EAAc,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA,EAClO,KAAA,EAAe,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,QAAA,EAAU,YAAA,EAAc,CAAC,cAAc,CAAA,EAAY,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,UAAA,EAAc,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAGlO,QAAA,EAAe,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,cAAc,CAAA,EAAU,SAAS,UAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,aAAA,EAAe,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA,EACnO,WAAA,EAAe,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,cAAc,CAAA,EAAU,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,aAAA,EAAe,aAAa,aAAA,EAAe,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,IAAA,EAAK;AAAA;AAAA,EAGrO,UAAA,EAAe,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,YAAA,EAAc,YAAA,EAAc,CAAC,cAAc,CAAA,EAAQ,SAAS,WAAA,EAAc,WAAA,EAAa,WAAW,SAAA,EAAW,MAAA,EAAe,aAAa,SAAA,EAAc,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAGlO,MAAA,EAAoB,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,eAAA,EAAiB,YAAA,EAAc,CAAC,cAAc,CAAA,EAAG,SAAS,iBAAA,EAAmB,WAAA,EAAa,QAAQ,SAAA,EAAW,aAAA,EAAe,aAAa,SAAA,EAAoB,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA,EAC7O,gBAAA,EAAoB,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,eAAA,EAAiB,YAAA,EAAc,CAAC,cAAc,CAAA,EAAG,SAAS,WAAA,EAAmB,WAAA,EAAa,QAAQ,SAAA,EAAW,aAAA,EAAe,aAAa,SAAA,EAAoB,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,IAAA,EAAK;AAAA,EAChP,SAAA,EAAoB,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,eAAA,EAAiB,YAAA,EAAc,CAAC,cAAc,CAAA,EAAG,SAAS,WAAA,EAAmB,WAAA,EAAa,QAAQ,SAAA,EAAW,UAAA,EAAe,aAAa,SAAA,EAAoB,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA,EAC7O,WAAA,EAAoB,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,eAAA,EAAiB,YAAA,EAAc,CAAC,cAAc,CAAA,EAAG,SAAS,WAAA,EAAmB,WAAA,EAAa,WAAW,SAAA,EAAW,UAAA,EAAY,aAAa,SAAA,EAAoB,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAG7O,KAAA,EAAe,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,gBAAA,EAAkB,YAAA,EAAc,CAAC,cAAc,CAAA,EAAI,SAAS,UAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,SAAA,EAAc,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA,EAClO,MAAA,EAAe,EAAE,EAAA,EAAI,SAAA,EAAW,IAAI,gBAAA,EAAkB,YAAA,EAAc,CAAC,cAAc,CAAA,EAAI,SAAS,UAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,SAAA,EAAc,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAGlO,IAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,MAAA,EAAS,YAAA,EAAc,CAAC,SAAS,CAAA,EAAiB,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,SAAA,EAAc,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,IAAA,EAAK;AAAA,EACpO,KAAA,EAAe,EAAE,EAAA,EAAI,UAAA,EAAY,IAAI,OAAA,EAAS,YAAA,EAAc,CAAC,cAAA,EAAgB,SAAS,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,WAAW,SAAA,EAAW,aAAA,EAAe,aAAa,SAAA,EAAc,YAAA,EAAc,YAAA,EAAc,OAAA,EAAS,IAAA,EAAK;AAAA,EACtO,EAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,IAAA,EAAO,YAAA,EAAc,CAAC,SAAS,CAAA,EAAiB,SAAS,YAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAGjO,QAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,eAAA,EAAiB,YAAA,EAAc,CAAC,cAAA,EAAgB,YAAY,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,SAAS,SAAA,EAAW,MAAA,EAAQ,aAAa,SAAA,EAAc,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,IAAA,EAAK;AAAA,EACzO,SAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,eAAA,EAAiB,YAAA,EAAc,CAAC,cAAA,EAAgB,YAAY,CAAA,EAAG,SAAS,WAAA,EAAa,WAAA,EAAa,SAAS,SAAA,EAAW,MAAA,EAAQ,aAAa,SAAA,EAAc,YAAA,EAAc,WAAA,EAAa,OAAA,EAAS,IAAA,EAAK;AAAA,EACzO,OAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,SAAS,CAAA,EAAW,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,KAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,SAAS,CAAA,EAAW,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,IAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,SAAS,CAAA,EAAW,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,MAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,SAAS,CAAA,EAAW,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,OAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,SAAS,CAAA,EAAW,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC3N,OAAA,EAAe,EAAE,EAAA,EAAI,YAAA,EAAc,IAAI,UAAA,EAAY,YAAA,EAAc,CAAC,SAAS,CAAA,EAAW,SAAS,YAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAE3N,QAAA,EAAe,EAAE,EAAA,EAAI,aAAA,EAAe,IAAI,QAAA,EAAU,YAAA,EAAc,CAAC,SAAS,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC5N,IAAA,EAAe,EAAE,EAAA,EAAI,aAAA,EAAe,IAAI,QAAA,EAAU,YAAA,EAAc,CAAC,SAAS,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAG5N,MAAA,EAAe,EAAE,EAAA,EAAI,aAAA,EAAe,IAAI,OAAA,EAAS,YAAA,EAAc,CAAC,SAAS,CAAA,EAAc,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC5N,OAAA,EAAe,EAAE,EAAA,EAAI,aAAA,EAAe,IAAI,OAAA,EAAS,YAAA,EAAc,CAAC,SAAS,CAAA,EAAc,SAAS,WAAA,EAAc,WAAA,EAAa,SAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA,EAC5N,SAAA,EAAe,EAAE,EAAA,EAAI,aAAA,EAAe,IAAI,OAAA,EAAS,YAAA,EAAc,CAAC,SAAA,EAAW,SAAS,CAAA,EAAG,SAAS,WAAA,EAAc,WAAA,EAAa,UAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAG5N,KAAA,EAAe,EAAE,EAAA,EAAI,aAAA,EAAe,IAAI,QAAA,EAAU,YAAA,EAAc,CAAC,SAAS,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA,EAAE;AAAA;AAAA,EAG5N,OAAA,EAAe,EAAE,EAAA,EAAI,aAAA,EAAe,IAAI,QAAA,EAAU,YAAA,EAAc,CAAC,SAAS,CAAA,EAAa,SAAS,WAAA,EAAc,WAAA,EAAa,QAAW,SAAA,EAAW,MAAA,EAAe,aAAa,OAAA,EAAc,YAAA,EAAc,MAAA,EAAQ,OAAA,EAAS,CAAA;AAC9N,CAAA;AAGA,IAAM,aAAA,GAAmC;AAAA,EACrC,EAAA,EAAI,aAAA;AAAA,EAAe,EAAA,EAAI,QAAA;AAAA,EACvB,YAAA,EAAc,CAAC,SAAS,CAAA;AAAA,EACxB,OAAA,EAAS,WAAA;AAAA,EACT,WAAA,EAAa,MAAA;AAAA,EACb,SAAA,EAAW,MAAA;AAAA,EACX,WAAA,EAAa,OAAA;AAAA,EACb,YAAA,EAAc,MAAA;AAAA,EACd,OAAA,EAAS;AACb,CAAA;AAOO,SAAS,iBAAiB,YAAA,EAAyC;AACtE,EAAA,OAAO,aAAA,CAAc,YAAY,CAAA,IAAK,aAAA;AAC1C;AAGO,SAAS,aAAa,YAAA,EAA+B;AACxD,EAAA,OAAO,YAAA,IAAgB,aAAA;AAC3B;AAMO,SAAS,kBAAA,GAA+B;AAC3C,EAAA,OAAO,MAAA,CAAO,KAAK,aAAa,CAAA;AACpC;;;ACdO,IAAM,eAAe,IAAI,GAAA;AAAA,EAC5B,kBAAA,EAAmB,CAAE,MAAA,CAAO,CAAA,CAAA,KAAK;AAC7B,IAAA,MAAM,CAAA,GAAI,iBAAiB,CAAC,CAAA;AAC5B,IAAA,OAAO,CAAC,UAAA,EAAY,WAAA,EAAa,iBAAiB,CAAA,CAAE,SAAS,CAAA,CAAE,OAAO,CAAA,IAAK,CAAA,CAAE,EAAA,KAAO,OAAA;AAAA,EACxF,CAAC;AACL,CAAA;AAkBgC,IAAI,GAAA;AAAA,EAChC,kBAAA,EAAmB,CAAE,MAAA,CAAO,CAAA,CAAA,KAAK;AAC7B,IAAA,MAAM,CAAA,GAAI,iBAAiB,CAAC,CAAA;AAC5B,IAAA,OAAQ,CAAA,CAAE,aAAa,QAAA,CAAS,SAAS,KAAK,CAAA,CAAE,OAAA,KAAY,YAAA,IAAiB,CAAA,CAAE,EAAA,KAAO,QAAA;AAAA,EAC1F,CAAC;AACL;AAOO,IAAM,eAAe,IAAI,GAAA;AAAA,EAC5B,kBAAA,EAAmB,CAAE,MAAA,CAAO,CAAA,CAAA,KAAK;AAC7B,IAAA,MAAM,CAAA,GAAI,iBAAiB,CAAC,CAAA;AAC5B,IAAA,OAAO,CAAA,CAAE,YAAA,CAAa,QAAA,CAAS,SAAS,CAAA;AAAA,EAC5C,CAAC;AACL,CAAA;AA8BO,SAAS,eAAe,YAAA,EAA0C;AAGrE,EAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,YAAA,CAAa,YAAY,GAAG,OAAO,IAAA;AACzD,EAAA,OAAO,gBAAA,CAAiB,YAAY,CAAA,CAAE,YAAA,CAAa,CAAC,CAAA,IAAK,IAAA;AAC7D;AAQO,SAAS,iBAAiB,MAAA,EAA4B;AACzD,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,SAAA;AAChC,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,KAAW,CAAA,KAAM,IAAA,IAAQ,CAAA,KAAM,KAAA,IAAS,MAAA,CAAO,SAAA,CAAU,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,kBAAA;AACjG,EAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAW,CAAC,MAAM,CAAC,CAAC,CAAA,IAAK,EAAE,MAAA,CAAO,SAAA,CAAU,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,eAAA,CAAA;AAGnF,EAAA,MAAM,gBAAgB,CAAC,CAAA,KAAc,0DAA0D,IAAA,CAAK,CAAA,CAAE,MAAM,CAAA;AAC5G,EAAA,MAAM,MAAA,GAAS,CAAC,CAAA,KAAW;AACvB,IAAA,IAAI,aAAa,IAAA,EAAM,OAAO,CAAC,KAAA,CAAM,CAAA,CAAE,SAAS,CAAA;AAChD,IAAA,IAAI,OAAO,CAAA,KAAM,QAAA,EAAU,OAAO,aAAA,CAAc,CAAC,CAAA,IAAK,CAAC,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAC1E,IAAA,OAAO,CAAC,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EAC/B,CAAA;AACA,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,MAAA,CAAO,CAAA,CAAA,KAAK,KAAK,IAAI,CAAA;AAC5C,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,SAAA;AACjC,EAAA,IAAI,OAAA,CAAQ,KAAA,CAAM,SAAS,CAAA,EAAG,OAAO,SAAA;AACrC,EAAA,IAAI,OAAA,CAAQ,KAAA,CAAM,QAAQ,CAAA,EAAG,OAAO,cAAA;AACpC,EAAA,IAAI,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAA,EAAG,OAAO,UAAA;AAClC,EAAA,OAAO,SAAA;AACX;AAyIO,SAAS,aAAa,YAAA,EAA6C;AACtE,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,YAAY,CAAA,CAAE,YAAA;AAChD,EAAA,IAAI,QAAA,KAAa,QAAQ,OAAO,SAAA;AAChC,EAAA,OAAO,QAAA;AACX;AA6PO,SAAS,yBAAA,CACZ,YAAA,EACA,YAAA,EACA,gBAAA,GAA2B,EAAA,EAC3B,YAAoB,EAAA,EACpB,MAAA,GAAgB,EAAC,EACjB,SAAA,EACyB;AAGzB,EAAA,MAAM,UAAA,GAAa,CAAC,OAAA,EAAmB,IAAA,KAAyB;AAC5D,IAAA,IAAI,IAAA,GAAO,CAAA;AACX,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AAClC,MAAA,IAAA,GAAA,CAAS,IAAA,IAAQ,CAAA,IAAK,IAAA,GAAQ,IAAA,CAAK,WAAW,CAAC,CAAA;AAC/C,MAAA,IAAA,GAAO,IAAA,GAAO,IAAA;AAAA,IAClB;AACA,IAAA,OAAO,QAAQ,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,GAAI,QAAQ,MAAM,CAAA;AAAA,EAClD,CAAA;AAGA,EAAA,IAAI,CAAC,YAAA,EAAc;AACf,IAAA,IAAI,iBAAiB,cAAA,EAAgB;AACjC,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,YAAA,EAAc,QAAQ,0BAAA,EAA2B;AAAA,IACvF;AACA,IAAA,IAAI,iBAAiB,SAAA,EAAW;AAC5B,MAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,YAAA,EAAc,QAAQ,qBAAA,EAAsB;AAAA,IAChF;AAEA,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,gBAAA,GAAmB,EAAA,GAAK,WAAA,GAAc,WAAA;AAAA,MAC9C,IAAA,EAAM,aAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AAQA,EAAA,IAAI,iBAAiB,aAAA,EAAe;AAChC,IAAA,IAAI,SAAA,EAAW,SAAS,WAAA,EAAa;AACjC,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,WAAA,EAAa,QAAQ,6CAAA,EAA8C;AAAA,IACzG;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,YAAA,EAAc,QAAQ,8CAAA,EAA+C;AAAA,EACxG;AAGA,EAAA,IAAI,iBAAiB,YAAA,EAAc;AAC/B,IAAA,IAAI,SAAA,EAAW,SAAS,WAAA,EAAa;AACjC,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,WAAA,EAAa,QAAQ,wCAAA,EAAyC;AAAA,IACpG;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,YAAA,EAAc,QAAQ,0CAAA,EAA2C;AAAA,EACvG;AAGA,EAAA,IAAI,CAAC,OAAA,EAAS,QAAQ,CAAA,CAAE,QAAA,CAAS,YAAY,CAAA,EAAG;AAC5C,IAAA,IAAI,SAAA,EAAW,SAAS,WAAA,EAAa;AACjC,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,WAAA,EAAa,QAAQ,4CAAA,EAA6C;AAAA,IACxG;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,WAAA,EAAa,IAAA,EAAM,YAAA,EAAc,QAAQ,gCAAA,EAAiC;AAAA,EAC/F;AAGA,EAAA,IAAI,iBAAiB,OAAA,EAAS;AAC1B,IAAA,IAAI,SAAA,EAAW,SAAS,WAAA,EAAa;AACjC,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,WAAA,EAAa,QAAQ,wCAAA,EAAyC;AAAA,IACpG;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,mBAAA,EAAqB,IAAA,EAAM,YAAA,EAAc,QAAQ,4BAAA,EAA6B;AAAA,EACnG;AAGA,EAAA,IAAI,iBAAiB,MAAA,EAAQ;AACzB,IAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,YAAA,EAAc,QAAQ,iCAAA,EAAkC;AAAA,EAC9F;AAGA,EAAA,IAAI,iBAAiB,OAAA,EAAS;AAC1B,IAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,IAAA,EAAM,YAAA,EAAc,QAAQ,6BAAA,EAA8B;AAAA,EACxF;AAGA,EAAA,IAAI,YAAA,CAAa,GAAA,CAAI,YAAY,CAAA,IAAK,CAAC,MAAA,EAAQ,SAAA,EAAW,OAAA,EAAS,MAAA,EAAQ,OAAO,MAAA,EAAQ,QAAQ,CAAA,CAAE,QAAA,CAAS,YAAY,CAAA,EAAG;AACxH,IAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,YAAA,EAAc,QAAQ,4CAAA,EAA6C;AAAA,EACzG;AAGA,EAAA,IAAI,gBAAA,CAAiB,YAAA,IAAgB,EAAE,CAAA,CAAE,OAAO,UAAA,EAAY;AACxD,IAAA,IAAI,oBAAoB,EAAA,EAAI;AACxB,MAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,aAAA,EAAe,QAAQ,yCAAA,EAA0C;AAAA,IACpG;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,WAAA,EAAa,IAAA,EAAM,aAAA,EAAe,QAAQ,oCAAA,EAAqC;AAAA,EACpG;AAGA,EAAA,IAAI,CAAC,QAAA,EAAU,SAAS,CAAA,CAAE,QAAA,CAAS,YAAY,CAAA,EAAG;AAC9C,IAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,aAAA,EAAe,QAAQ,uCAAA,EAAwC;AAAA,EAClG;AAGA,EAAA,IAAI,iBAAiB,UAAA,EAAY;AAC7B,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,gBAAA,GAAmB,EAAA,GAAK,WAAA,GAAc,WAAA;AAAA,MAC9C,IAAA,EAAM,aAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AAGA,EAAA,IAAI,iBAAiB,MAAA,EAAQ;AACzB,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,gBAAA,GAAmB,CAAA,GAAI,WAAA,GAAc,MAAA;AAAA,MAC7C,IAAA,EAAM,aAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AAGA,EAAA,IAAI,iBAAiB,UAAA,EAAY;AAC7B,IAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,YAAA,EAAc,QAAQ,0CAAA,EAA2C;AAAA,EACvG;AAKA,EAAA,IAAI,YAAA,CAAa,GAAA,CAAI,YAAY,CAAA,EAAG;AAChC,IAAA,IAAI,SAAA,EAAW,SAAS,WAAA,EAAa;AACjC,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,WAAA,EAAa,QAAQ,+BAAA,EAAgC;AAAA,IAC3F;AACA,IAAA,MAAM,oBAAoB,CAAC,SAAA,EAAW,SAAS,QAAA,EAAU,MAAA,EAAQ,qBAAqB,WAAW,CAAA;AACjG,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,UAAA,CAAW,iBAAA,EAAmB,SAAS,CAAA;AAAA,MAC/C,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AAGA,EAAA,IAAI,YAAA,CAAa,GAAA,CAAI,YAAY,CAAA,IAAK,iBAAiB,SAAA,EAAW;AAC9D,IAAA,MAAM,cAAA,GAAiB,CAAC,OAAA,EAAS,QAAA,EAAU,WAAW,SAAS,CAAA;AAC/D,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,UAAA,CAAW,cAAA,EAAgB,SAAS,CAAA;AAAA,MAC5C,IAAA,EAAM,YAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AAGA,EAAA,IAAI,YAAA,KAAiB,SAAA,IAAa,YAAA,KAAiB,UAAA,EAAY;AAC3D,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,gBAAA,GAAmB,EAAA,GAAK,WAAA,GAAc,WAAA;AAAA,MAC9C,IAAA,EAAM,aAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AAGA,EAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,IAAA,EAAM,YAAA,EAAc,QAAQ,oBAAA,EAAqB;AACjF;AAmBA,IAAM,UAAA,GAAa,CAAC,SAAA,EAAU,UAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,KAAA,EAAM,MAAA,EAAO,MAAA,EAAO,QAAA,EAAS,WAAA,EAAY,SAAA,EAAU,YAAW,UAAU,CAAA;AACjI,IAAM,WAAA,GAAc,CAAC,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,KAAA,EAAM,OAAM,KAAK,CAAA;AAC5F,IAAM,SAAA,GAAY,CAAC,GAAA,EAAI,GAAA,EAAI,GAAA,EAAI,GAAA,EAAI,GAAA,EAAI,GAAA,EAAI,GAAA,EAAI,GAAA,EAAI,GAAA,EAAI,IAAA,EAAK,MAAK,IAAI,CAAA;AAGrE,IAAM,QAAA,GAAW,CAAC,QAAA,EAAS,SAAA,EAAU,aAAY,UAAA,EAAW,QAAA,EAAS,YAAW,QAAQ,CAAA;AACxF,IAAM,SAAA,GAAY,CAAC,KAAA,EAAM,KAAA,EAAM,OAAM,KAAA,EAAM,KAAA,EAAM,OAAM,KAAK,CAAA;AAC5D,IAAM,SAAA,GAAY,CAAC,IAAA,EAAK,IAAA,EAAK,MAAK,IAAA,EAAK,IAAA,EAAK,MAAK,IAAI,CAAA;AAGrD,IAAM,YAAA,GAAe,CAAC,QAAA,EAAS,QAAA,EAAS,WAAU,WAAA,EAAY,UAAA,EAAW,UAAS,UAAU,CAAA;AAC5F,IAAM,aAAA,GAAgB,CAAC,KAAA,EAAM,KAAA,EAAM,OAAM,KAAA,EAAM,KAAA,EAAM,OAAM,KAAK,CAAA;AAGhE,IAAM,cAAA,GAAiB,CAAC,IAAA,EAAK,IAAA,EAAK,MAAK,IAAI,CAAA;AAG3C,IAAM,SAAA,GAAY,CAAC,GAAA,EAAI,IAAA,EAAK,KAAI,IAAA,EAAK,GAAA,EAAI,IAAA,EAAK,GAAA,EAAI,IAAI,CAAA;AACtD,IAAM,cAAA,GAAiB,CAAC,OAAA,EAAQ,WAAA,EAAY,QAAO,WAAA,EAAY,OAAA,EAAQ,WAAA,EAAY,MAAA,EAAO,WAAW,CAAA;AACrG,IAAM,SAAA,GAAY,CAAC,GAAA,EAAI,GAAA,EAAI,KAAI,GAAG,CAAA;AAClC,IAAM,cAAA,GAAiB,CAAC,OAAA,EAAQ,MAAA,EAAO,SAAQ,MAAM,CAAA;AAUrD,IAAM,iBAAA,GAAuD;AAAA,EACzD,KAAA,EAAO;AAAA,IACH,EAAE,MAAA,EAAQ,UAAA,EAAY,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC5C,EAAE,MAAA,EAAQ,WAAA,EAAa,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC7C,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA,EAAiB,KAAA;AAAM,GAChD;AAAA,EACA,GAAA,EAAK;AAAA,IACD,EAAE,MAAA,EAAQ,QAAA,EAAU,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC1C,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC3C,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC3C,EAAE,MAAA,EAAQ,YAAA,EAAc,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC9C,EAAE,MAAA,EAAQ,aAAA,EAAe,eAAA,EAAiB,IAAA;AAAK,GACnD;AAAA,EACA,OAAA,EAAS;AAAA,IACL,EAAE,MAAA,EAAQ,cAAA,EAAgB,eAAA,EAAiB,IAAA;AAAK,GACpD;AAAA,EACA,SAAA,EAAW;AAAA,IACP,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC3C,EAAE,MAAA,EAAQ,cAAA,EAAgB,eAAA,EAAiB,IAAA,EAAK;AAAA,IAChD,EAAE,MAAA,EAAQ,SAAA,EAAW,eAAA,EAAiB,IAAA,EAAK;AAAA,IAC3C,EAAE,MAAA,EAAQ,cAAA,EAAgB,eAAA,EAAiB,IAAA;AAAK;AAExD,CAAA;AAMA,SAAS,YAAY,GAAA,EAA2C;AAC5D,EAAA,MAAM,CAAA,uBAAQ,GAAA,EAAoB;AAClC,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,CAAO,QAAQ,CAAA,EAAA,EAAK;AACxC,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,GAAkB,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA;AAC5E,IAAA,CAAA,CAAE,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EAChB;AACA,EAAA,OAAO,CAAA;AACX;AAgBA,SAAS,aAAA,CAAc,QAAe,SAAA,EAAoD;AACtF,EAAA,MAAM,YAAA,GAAe,CAAC,GAAG,IAAI,IAAI,MAAA,CAAO,GAAA,CAAI,OAAK,CAAA,IAAK,IAAA,GAAO,OAAO,CAAC,CAAA,GAAI,EAAE,CAAC,CAAC,EAAE,MAAA,CAAO,CAAA,CAAA,KAAK,MAAM,EAAE,CAAA;AACnG,EAAA,IAAI,YAAA,CAAa,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAEtC,EAAA,KAAA,MAAW,OAAO,SAAA,EAAW;AACzB,IAAA,MAAM,MAAA,GAAS,YAAY,GAAG,CAAA;AAC9B,IAAA,MAAM,UAA8C,EAAC;AACrD,IAAA,MAAM,YAAsB,EAAC;AAE7B,IAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC5B,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,GAAkB,GAAA,CAAI,aAAY,GAAI,GAAA;AACtD,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAC1B,MAAA,IAAI,QAAQ,MAAA,EAAW;AACnB,QAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,GAAA,EAAK,KAAA,EAAO,KAAK,CAAA;AAAA,MAC3C,CAAA,MAAO;AACH,QAAA,SAAA,CAAU,KAAK,GAAG,CAAA;AAAA,MACtB;AAAA,IACJ;AAGA,IAAA,IAAI,QAAQ,MAAA,IAAU,YAAA,CAAa,SAAS,GAAA,IAAO,OAAA,CAAQ,UAAU,CAAA,EAAG;AAEpE,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAK,CAAA;AACxC,MAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,KAAK,CAAA;AAEvC,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,SAAS,CAAA;AACxB,MAAA,OAAO,MAAA;AAAA,IACX;AAAA,EACJ;AACA,EAAA,OAAO,MAAA;AACX;AAkBO,SAAS,qBAAA,CACZ,cACA,MAAA,EACoB;AAEpB,EAAA,MAAM,SAAA,GAAY,kBAAkB,YAAY,CAAA;AAChD,EAAA,IAAI,SAAA,EAAW;AACX,IAAA,OAAO,aAAA,CAAc,QAAQ,SAAS,CAAA;AAAA,EAC1C;AAGA,EAAA,IAAI,CAAC,YAAA,IAAgB,YAAA,KAAiB,UAAA,IAAc,iBAAiB,SAAA,EAAW;AAC5E,IAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,MAAA,CAAO,iBAAiB,CAAA,EAAG;AACjD,MAAA,MAAM,MAAA,GAAS,aAAA,CAAc,MAAA,EAAQ,IAAI,CAAA;AACzC,MAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,IACvB;AAAA,EACJ;AAEA,EAAA,OAAO,MAAA;AACX;;;ACv6BA,SAAS,oBAAoB,EAAA,EAAsE;AAC/F,EAAA,QAAQ,EAAA;AAAI,IACR,KAAK,cAAA;AAAgB,MAAA,OAAO,cAAA;AAAA,IAC5B,KAAK,SAAA;AAAW,MAAA,OAAO,SAAA;AAAA,IACvB,KAAK,UAAA;AAAY,MAAA,OAAO,UAAA;AAAA,IACxB,KAAK,YAAA;AAAc,MAAA,OAAO,cAAA;AAAA,IAC1B,KAAK,SAAA;AAAA,IACL;AAAS,MAAA,OAAO,SAAA;AAAA;AAExB;AASA,SAAS,uBAAA,CACL,IAAA,EACA,SAAA,EACA,YAAA,EACO;AACP,EAAA,MAAM,eAAe,IAAA,CAAK,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,CAAC,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,KAAW,KAAK,IAAI,CAAA;AAC1F,EAAA,IAAI,YAAA,CAAa,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AAGtC,EAAA,MAAM,eAAe,IAAI,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,MAAM,CAAC,CAAA;AACrD,EAAA,IAAI,YAAA,CAAa,IAAA,IAAQ,CAAA,EAAG,OAAO,KAAA;AAEnC,EAAA,MAAM,kBAAA,GAAqB,CAAC,GAAA,KAAsB;AAC9C,IAAA,IAAI,GAAA,YAAe,MAAM,OAAO,IAAA;AAChC,IAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAEzB,MAAA,IAAI,OAAO,IAAA,IAAQ,GAAA,IAAO,QAAQ,GAAA,GAAM,CAAA,KAAM,GAAG,OAAO,IAAA;AAExD,MAAA,IAAI,GAAA,GAAM,KAAA,IAAY,GAAA,GAAM,KAAA,EAAe,OAAO,IAAA;AAClD,MAAA,OAAO,KAAA;AAAA,IACX;AACA,IAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AACzB,MAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAK;AACzB,MAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AACrB,MAAA,IAAI,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,IAAA;AACpC,MAAA,OAAO,CAAC,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,OAAO,CAAC,CAAA;AAAA,IAC5C;AACA,IAAA,OAAO,KAAA;AAAA,EACX,CAAA;AAEA,EAAA,MAAM,YAAA,GAAe,YAAA,CAAa,MAAA,CAAO,kBAAkB,CAAA,CAAE,MAAA;AAC7D,EAAA,MAAM,WAAA,GAAc,eAAe,GAAA,GAAM,GAAA;AACzC,EAAA,OAAO,YAAA,GAAe,aAAa,MAAA,IAAU,WAAA;AACjD;AAMA,SAAS,uBAAA,CACL,WAAA,EACA,OAAA,EACA,IAAA,EACA,WACA,YAAA,EACoB;AAEpB,EAAA,IAAI,CAAC,MAAA,EAAQ,QAAA,EAAU,KAAK,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG;AAC7C,IAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,aAAa,eAAA,EAAiB,IAAA,EAAM,kBAAkB,KAAA,EAAM;AAAA,EAC5F;AAEA,EAAA,IAAI,YAAY,OAAA,EAAS;AACrB,IAAA,MAAM,WAAA,GAAc,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,OAAK,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA,CAAE,IAAA;AACzD,IAAA,IAAI,eAAe,EAAA,EAAI;AACnB,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,aAAa,eAAA,EAAiB,IAAA,EAAM,kBAAkB,KAAA,EAAM;AAAA,IAC5F;AAAA,EACJ;AAEA,EAAA,IAAI,CAAC,uBAAA,CAAwB,IAAA,EAAM,SAAA,EAAW,YAAY,CAAA,EAAG;AACzD,IAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,aAAa,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAAA,EAC7F;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,UAAA,EAAY,aAAa,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAC9F;AAgBA,SAAS,mBACL,WAAA,EACA,OAAA,EACA,IAAA,EACA,SAAA,EACA,aACA,YAAA,EACoB;AACpB,EAAA,MAAM,WAAA,GAAc,WAAA,CAAY,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,IAAK,IAAA,IAAQ,CAAC,KAAA,CAAM,CAAC,CAAC,CAAC,CAAA,CAAE,IAAI,MAAM,CAAA;AAC/E,EAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AACxB,IAAA,MAAM,WAAA,GAAc,IAAI,GAAA,CAAI,WAAW,CAAA,CAAE,IAAA;AACzC,IAAA,MAAM,eAAe,WAAA,CAAY,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,GAAI,MAAM,CAAC,CAAA;AAKtD,IAAA,IAAI,CAAC,YAAA,IAAgB,YAAA,IAAgB,WAAA,GAAc,EAAA,EAAI;AACnD,MAAA,OAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,aAAa,eAAA,EAAiB,KAAA,EAAO,kBAAkB,IAAA,EAAK;AAAA,IACjG;AAKA,IAAA,IAAI,CAAC,YAAA,IAAgB,WAAA,GAAc,EAAA,IAAM,CAAC,SAAS,OAAO,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG;AAC3E,MAAA,OAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,aAAa,eAAA,EAAiB,IAAA,EAAM,kBAAkB,IAAA,EAAK;AAAA,IAChG;AAOA,IAAA,IAAI,CAAC,YAAA,IAAgB,WAAA,GAAc,EAAA,IAAM,CAAC,KAAK,GAAG,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG;AACnE,MAAA,OAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,aAAa,eAAA,EAAiB,IAAA,EAAM,kBAAkB,IAAA,EAAK;AAAA,IAChG;AAAA,EACJ;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,aAAa,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAC7F;AAcA,SAAS,yBAAA,CACL,UAAA,EACA,OAAA,EACA,IAAA,EACA,WACA,WAAA,EACoB;AACpB,EAAA,MAAM,GAAA,GAAM,CAAC,EAAA,KAAoB,UAAA,CAAW,SAAS,EAAE,CAAA;AAKvD,EAAA,IAAI,GAAA,CAAI,UAAU,CAAA,IAAK,GAAA,CAAI,SAAS,CAAA,EAAG;AACnC,IAAA,OAAO,uBAAA,CAAwB,UAAA,EAAY,OAAA,EAAS,IAAA,EAAM,WAAW,IAAI,CAAA;AAAA,EAC7E;AAMA,EAAA,IAAI,GAAA,CAAI,cAAc,CAAA,IAAK,GAAA,CAAI,SAAS,CAAA,EAAG;AACvC,IAAA,IAAI,CAAC,OAAA,EAAS,OAAO,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG;AACtC,MAAA,MAAM,WAAA,GAAc,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,OAAK,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA,CAAE,IAAA;AACzD,MAAA,IAAI,eAAe,EAAA,EAAI;AACnB,QAAA,OAAO,EAAE,QAAQ,SAAA,EAAW,WAAA,EAAa,WAAW,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAAA,MACxG;AAEA,MAAA,OAAO,EAAE,QAAQ,cAAA,EAAgB,WAAA,EAAa,gBAAgB,eAAA,EAAiB,KAAA,EAAO,kBAAkB,IAAA,EAAK;AAAA,IACjH;AACA,IAAA,IAAI,CAAC,QAAA,EAAU,KAAK,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG;AACrC,MAAA,OAAO,EAAE,QAAQ,SAAA,EAAW,WAAA,EAAa,WAAW,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAAA,IACxG;AAEA,IAAA,OAAO,EAAE,QAAQ,cAAA,EAAgB,WAAA,EAAa,gBAAgB,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAAA,EAClH;AAIA,EAAA,IAAI,GAAA,CAAI,cAAc,CAAA,IAAK,GAAA,CAAI,YAAY,CAAA,EAAG;AAC1C,IAAA,OAAO,EAAE,QAAQ,cAAA,EAAgB,WAAA,EAAa,gBAAgB,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAAA,EAClH;AAKA,EAAA,IAAI,GAAA,CAAI,SAAS,CAAA,IAAK,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,IAAA,IAAI,CAAC,OAAA,EAAS,OAAO,CAAA,CAAE,QAAA,CAAS,OAAO,CAAA,EAAG;AACtC,MAAA,OAAO,EAAE,QAAQ,SAAA,EAAW,WAAA,EAAa,WAAW,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAAA,IACxG;AACA,IAAA,OAAO,EAAE,QAAQ,SAAA,EAAW,WAAA,EAAa,WAAW,eAAA,EAAiB,KAAA,EAAO,kBAAkB,KAAA,EAAM;AAAA,EACxG;AAGA,EAAA,MAAM,QAAA,GAAW,WAAW,CAAC,CAAA;AAC7B,EAAA,OAAO,EAAE,MAAA,EAAQ,mBAAA,CAAoB,QAAQ,CAAA,EAAG,aAAa,QAAA,EAAU,eAAA,EAAiB,KAAA,EAAO,gBAAA,EAAkB,KAAA,EAAM;AAC3H;AA6BO,SAAS,mBAAA,CACZ,YAAA,EACA,WAAA,EACA,OAAA,EACA,MACA,SAAA,EACoB;AAOpB,EAAA,IAAI,YAAA,IAAgB,YAAA,CAAa,YAAY,CAAA,EAAG;AAC5C,IAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,IAAA,MAAM,aAAa,KAAA,CAAM,YAAA;AAEzB,IAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AAEvB,MAAA,OAAO,yBAAA,CAA0B,UAAA,EAAY,OAAA,EAAS,IAAA,EAAM,SAAsB,CAAA;AAAA,IACtF;AAGA,IAAA,MAAM,QAAA,GAAW,WAAW,CAAC,CAAA;AAM7B,IAAA,IAAI,aAAa,cAAA,EAAgB;AAC7B,MAAA,MAAM,OAAA,GAAU,WAAA,CAAY,MAAA,CAAO,CAAA,CAAA,KAAK,KAAK,IAAI,CAAA;AACjD,MAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,GAAS,CAAA,IAChC,QAAQ,KAAA,CAAM,CAAA,CAAA,KAAK,OAAO,CAAA,KAAM,QAAA,IAAa,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA,IAAK,CAAA,CAAE,IAAA,EAAK,KAAM,EAAG,CAAA;AACxG,MAAA,IAAI,CAAC,UAAA,EAAY;AAEb,QAAA,MAAM,QAAA,GAAW,iBAAiB,WAAW,CAAA;AAC7C,QAAA,OAAO;AAAA,UACH,MAAA,EAAQ,oBAAoB,QAAQ,CAAA;AAAA,UACpC,WAAA,EAAa,QAAA;AAAA,UACb,eAAA,EAAiB,KAAA;AAAA,UACjB,gBAAA,EAAkB;AAAA,SACtB;AAAA,MACJ;AAAA,IACJ;AAEA,IAAA,IAAI,aAAa,UAAA,EAAY;AACzB,MAAA,OAAO,uBAAA,CAAwB,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,WAAW,IAAI,CAAA;AAAA,IAC3E;AACA,IAAA,IAAI,aAAa,SAAA,EAAW;AACxB,MAAA,OAAO,mBAAmB,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,aAAa,IAAI,CAAA;AAAA,IACnF;AACA,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,oBAAoB,QAAQ,CAAA;AAAA,MACpC,WAAA,EAAa,QAAA;AAAA,MACb,eAAA,EAAiB,KAAA;AAAA,MACjB,gBAAA,EAAkB;AAAA,KACtB;AAAA,EACJ;AAOA,EAAA,MAAM,WAAA,GAA2B,iBAAiB,WAAW,CAAA;AAC7D,EAAA,MAAM,eAAA,GAAkB,KAAA;AACxB,EAAA,MAAM,gBAAA,GAAmB,KAAA;AAEzB,EAAA,QAAQ,WAAA;AAAa,IACjB,KAAK,UAAA;AACD,MAAA,OAAO,uBAAA,CAAwB,WAAA,EAAa,OAAA,EAAS,IAAA,EAAM,WAAW,KAAK,CAAA;AAAA,IAE/E,KAAK,SAAA;AACD,MAAA,OAAO,mBAAmB,WAAA,EAAa,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,aAAa,KAAK,CAAA;AAAA,IAEvF,KAAK,cAAA;AACD,MAAA,OAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,WAAA,EAAa,iBAAiB,gBAAA,EAAiB;AAAA,IAEpF,KAAK,YAAA;AACD,MAAA,OAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,WAAA,EAAa,iBAAiB,gBAAA,EAAiB;AAAA,IAEpF,KAAK,SAAA;AAAA,IACL;AACI,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,WAAA,EAAa,iBAAiB,gBAAA,EAAiB;AAAA;AAEvF;;;AChMO,SAAS,aAAa,KAAA,EAAwD;AACjF,EAAA,IAAI,CAAC,OAAO,OAAO,EAAA;AACnB,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,OAAO,MAAM,YAAA,IAAgB,EAAA;AACjC;AAeO,SAAS,oBACZ,KAAA,EACkB;AAClB,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAE,cAAc,SAAA,EAAU;AAC7C,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,SAAiB,EAAE,YAAA,EAAc,SAAS,SAAA,EAAU;AACzE,EAAA,OAAO,EAAE,GAAG,KAAA,EAAO,YAAA,EAAc,KAAA,CAAM,gBAAgB,SAAA,EAAU;AACrE;AAOA,IAAM,YAAA,GAAuC;AAAA,EACzC,GAAA,EAAK,GAAA;AAAA,EAAK,GAAA,EAAK,QAAA;AAAA,EAAK,GAAA,EAAK,MAAA;AAAA,EAAK,GAAA,EAAK,MAAA;AAAA,EAAK,GAAA,EAAK,MAAA;AAAA,EAC7C,GAAA,EAAK,QAAA;AAAA,EAAK,GAAA,EAAK,QAAA;AAAA,EAAK,GAAA,EAAK,IAAA;AAAA,EAAM,GAAA,EAAK,KAAA;AAAA,EAAO,GAAA,EAAK,IAAA;AAAA,EAChD,GAAA,EAAK,KAAA;AAAA,EAAO,GAAA,EAAK,IAAA;AAAA,EAAM,GAAA,EAAK,IAAA;AAAA,EAAM,GAAA,EAAK;AAC3C,CAAA;AAUA,IAAM,eAAA,GAA0C;AAAA;AAAA,EAE5C,OAAA,EAAM,OAAA;AAAA,EAAM,OAAA,EAAM,OAAA;AAAA,EAAM,CAAA,EAAG,OAAA;AAAA,EAAM,CAAA,EAAG,OAAA;AAAA;AAAA,EAEpC,EAAA,EAAI,KAAA;AAAA,EAAO,EAAA,EAAI,KAAA;AAAA;AAAA,EAEf,EAAA,EAAI,KAAA;AAAA,EAAO,EAAA,EAAI,KAAA;AAAA,EAAO,CAAA,EAAG,IAAA;AAAA,EAAM,EAAA,EAAI,KAAA;AAAA;AAAA,EAEnC,MAAA,EAAQ,OAAA;AAAA,EAAS,GAAA,EAAK,MAAA;AAAA;AAAA,EAEtB,GAAA,EAAK,IAAA;AAAA,EAAM,GAAA,EAAK,MAAA;AAAA,EAAQ,EAAA,EAAI,KAAA;AAAA,EAC5B,OAAA,EAAS,IAAA;AAAA,EAAM,OAAA,EAAS,MAAA;AAAA,EAAQ,KAAA,EAAO,KAAA;AAAA;AAAA,EAEvC,GAAA,EAAK;AACT,CAAA;AASA,SAAS,+BAA+B,MAAA,EAAmC;AACvE,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,OAAA;AAChC,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA;AAE/B,EAAA,MAAM,cAAc,GAAA,CAAI,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,IAAK,CAAC,CAAA,CAAE,MAAA;AAC5C,EAAA,IAAI,WAAA,GAAc,GAAA,CAAI,MAAA,IAAU,GAAA,EAAK,OAAO,KAAA;AAC5C,EAAA,OAAO,OAAA;AACX;AAQA,SAAS,gBAAgB,MAAA,EAA0B;AAC/C,EAAA,IAAI,WAAA,GAAc,CAAA;AAClB,EAAA,KAAA,MAAW,KAAK,MAAA,EAAQ;AACpB,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,EAAG;AAEzB,IAAA,MAAM,CAAA,GAAI,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AACtB,IAAA,MAAM,GAAA,GAAM,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA;AACzB,IAAA,IAAI,QAAQ,EAAA,EAAI;AAEhB,IAAA,IAAI,GAAA,GAAM,EAAE,MAAA,GAAS,CAAA;AACrB,IAAA,OAAO,GAAA,GAAM,GAAA,IAAO,CAAA,CAAE,GAAG,MAAM,GAAA,EAAK,GAAA,EAAA;AACpC,IAAA,MAAM,QAAA,GAAW,GAAA,GAAM,GAAA,GAAM,GAAA,GAAM,GAAA,GAAM,CAAA;AACzC,IAAA,IAAI,QAAA,GAAW,aAAa,WAAA,GAAc,QAAA;AAAA,EAC9C;AACA,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,CAAC,CAAA;AAClC;AAUA,SAAS,eAAA,CAAgB,MAAA,EAAkB,WAAA,GAAc,IAAA,EAAM,WAAqB,EAAA,EAAY;AAC5F,EAAA,MAAM,CAAA,GAAI,gBAAgB,MAAM,CAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,cAAc,GAAA,GAAM,EAAA;AAClC,EAAA,IAAI,MAAM,CAAA,EAAG,OAAO,CAAA,EAAG,QAAQ,GAAG,KAAK,CAAA,CAAA,CAAA;AACvC,EAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,EAAG,KAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AACnC;AAQO,SAAS,aAAA,CACZ,YAAA,EACA,UAAA,EACA,MAAA,EACmD;AACnD,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,EAAA,MAAM,OAAO,UAAA,CAAW,IAAA;AAGxB,EAAA,MAAM,cAAA,GAAiB,OAAO,YAAA,CAAa,IAAA,CAAK,aAAa,CAAA,IAAK,YAAA,CAAa,IAAI,CAAA,GAAI,MAAA;AAIvF,EAAA,MAAM,UAAA,GAAa,IAAA,GAAO,eAAA,CAAgB,IAAI,CAAA,GAAI,MAAA;AAElD,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA;AASzE,EAAA,QAAQ,MAAM,WAAA;AAAa,IACvB,KAAK,UAAA,EAAY;AACb,MAAA,MAAM,GAAA,GAAM,cAAA;AAGZ,MAAA,IAAI,GAAA,EAAK;AACL,QAAA,MAAM,WAAA,GAAc,YAAA,KAAiB,OAAA,GAAU,MAAA,GAAS,gBAAgB,IAAI,CAAA;AAC5E,QAAA,OAAO;AAAA,UACH,MAAA,EAAQ,EAAE,OAAA,EAAS,WAAA,EAAa,QAAQ,GAAA,EAAI;AAAA,UAC5C,aAAA,EAAe,EAAE,OAAA,EAAS,MAAA,EAAQ,QAAQ,GAAA;AAAI,SAClD;AAAA,MACJ;AACA,MAAA,OAAO,EAAE,aAAA,EAAe,EAAE,OAAA,EAAS,QAAO,EAAE;AAAA,IAChD;AAAA,IAEA,KAAK,SAAA,EAAW;AAGZ,MAAA,IAAI,CAAC,WAAW,eAAA,EAAiB;AAC7B,QAAA,OAAO,EAAE,aAAA,EAAe,EAAE,SAAS,eAAA,CAAgB,IAAI,GAAE,EAAE;AAAA,MAC/D;AACA,MAAA,MAAM,GAAA,GAAM,+BAA+B,IAAI,CAAA;AAC/C,MAAA,IAAI,QAAQ,KAAA,EAAO;AAEf,QAAA,MAAM,CAAA,GAAI,gBAAgB,IAAI,CAAA;AAC9B,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAI,CAAC,CAAA;AAC/B,QAAA,MAAM,IAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,KAAA,GAAQ,GAAG,CAAC,CAAA;AACnC,QAAA,OAAO;AAAA,UACH,MAAA,EAAQ,EAAE,OAAA,EAAS,CAAA,CAAA,EAAI,KAAK,CAAA,EAAA,CAAA,EAAK;AAAA,UACjC,aAAA,EAAe,EAAE,OAAA,EAAS,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,CAAA;AAAI,SAC1C;AAAA,MACJ;AAGA,MAAA,OAAO;AAAA,QACH,aAAA,EAAe,EAAE,OAAA,EAAS,eAAA,CAAgB,MAAM,KAAK,CAAA,EAAG,QAAQ,GAAA;AAAI,OACxE;AAAA,IACJ;AAAA,IAEA,KAAK,aAAA;AACD,MAAA,OAAO;AAAA,QACH,aAAA,EAAe,UAAA,GACT,EAAE,OAAA,EAAS,gBAAgB,IAAI,CAAA,EAAG,MAAA,EAAQ,UAAA,EAAW,GACrD,EAAE,OAAA,EAAS,eAAA,CAAgB,IAAI,CAAA;AAAE,OAC3C;AAAA,IAEJ,KAAK,SAAA;AAGD,MAAA,IAAI,YAAA,KAAiB,MAAA,IAAU,YAAA,KAAiB,QAAA,EAAU;AACtD,QAAA,OAAO,EAAC;AAAA,MACZ;AACA,MAAA,OAAO,EAAE,aAAA,EAAe,EAAE,OAAA,EAAS,MAAK,EAAE;AAAA,IAE9C,KAAK,SAAA;AACD,MAAA,OAAO,EAAE,aAAA,EAAe,EAAE,SAAS,eAAA,CAAgB,IAAI,GAAE,EAAE;AAAA,IAE/D,KAAK,OAAA;AAAA,IACL;AACI,MAAA,OAAO,EAAC;AAAA;AAEpB;AAYO,SAAS,qBAAA,CACZ,cACA,MAAA,EACW;AAEX,EAAA,IAAI,CAAC,YAAA,CAAa,YAAY,CAAA,EAAG;AAC7B,IAAA,OAAO,iBAAiB,MAAM,CAAA;AAAA,EAClC;AAEA,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,EAAA,MAAM,aAAa,KAAA,CAAM,YAAA;AACzB,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAGzB,IAAA,IAAI,UAAA,CAAW,CAAC,CAAA,KAAM,cAAA,EAAgB;AAClC,MAAA,MAAM,OAAA,GAAU,MAAA,CAAO,MAAA,CAAO,CAAA,CAAA,KAAK,KAAK,IAAI,CAAA;AAC5C,MAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,GAAS,CAAA,IAChC,QAAQ,KAAA,CAAM,CAAA,CAAA,KAAK,OAAO,CAAA,KAAM,QAAA,IAAa,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA,IAAK,CAAA,CAAE,IAAA,EAAK,KAAM,EAAG,CAAA;AACxG,MAAA,IAAI,CAAC,UAAA,EAAY;AACb,QAAA,OAAO,iBAAiB,MAAM,CAAA;AAAA,MAClC;AAAA,IACJ;AACA,IAAA,OAAO,WAAW,CAAC,CAAA;AAAA,EACvB;AAGA,EAAA,IAAI,WAAW,QAAA,CAAS,cAAc,KAAK,UAAA,CAAW,QAAA,CAAS,SAAS,CAAA,EAAG;AACvE,IAAA,MAAMA,SAAAA,GAAW,IAAI,GAAA,CAAI,MAAA,CAAO,OAAO,CAAA,CAAA,KAAK,CAAA,IAAK,IAAI,CAAC,CAAA,CAAE,IAAA;AAExD,IAAA,OAAOA,SAAAA,IAAY,KAAK,SAAA,GAAY,cAAA;AAAA,EACxC;AAGA,EAAA,IAAI,WAAW,QAAA,CAAS,UAAU,KAAK,UAAA,CAAW,QAAA,CAAS,SAAS,CAAA,EAAG;AACnE,IAAA,MAAMA,SAAAA,GAAW,IAAI,GAAA,CAAI,MAAA,CAAO,OAAO,CAAA,CAAA,KAAK,CAAA,IAAK,IAAI,CAAC,CAAA,CAAE,IAAA;AAExD,IAAA,OAAOA,SAAAA,IAAY,IAAI,SAAA,GAAY,UAAA;AAAA,EACvC;AAGA,EAAA,IAAI,WAAW,QAAA,CAAS,YAAY,KAAK,UAAA,CAAW,QAAA,CAAS,cAAc,CAAA,EAAG;AAC1E,IAAA,OAAO,cAAA;AAAA,EACX;AAEA,EAAA,OAAO,WAAW,CAAC,CAAA;AACvB;AAcO,SAAS,0BACZ,YAAA,EAC6B;AAC7B,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,EAAA,QAAQ,MAAM,OAAA;AAAS,IACnB,KAAK,UAAA;AAAmB,MAAA,OAAO,KAAA;AAAA,IAC/B,KAAK,iBAAA;AAAmB,MAAA,OAAO,KAAA;AAAA,IAC/B,KAAK,WAAA;AAAmB,MAAA,OAAO,SAAA;AAAA,IAC/B,KAAK,WAAA;AAAmB,MAAA,OAAO,MAAA;AAAA,IAC/B,KAAK,YAAA;AAAmB,MAAA,OAAO,MAAA;AAAA,IAC/B;AAAwB,MAAA,OAAO,MAAA;AAAA;AAEvC;AAYO,SAAS,8BAAA,CACZ,cACA,MAAA,EACqB;AAErB,EAAA,IAAI,MAAA,IAAU,MAAA,CAAO,CAAC,CAAA,GAAI,GAAG,OAAO,WAAA;AAGpC,EAAA,OAAO,aAAa,YAAY,CAAA;AACpC;AAoBO,SAAS,gBAAA,CACZ,cACA,MAAA,EACgD;AAOhD,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,KAAY,UAAA,IAAc,MAAM,WAAA,KAAgB,MAAA,IAChE,MAAM,EAAA,KAAO,gBAAA;AACpB,EAAA,IAAI,CAAC,UAAU,OAAO,MAAA;AAEtB,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,EAAA,EAAI,OAAO,MAAA;AAE/B,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,MAAA,CAAO,CAAA,CAAA,KAAK,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAA,IAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AACrF,EAAA,IAAI,QAAA,CAAS,MAAA,GAAS,EAAA,EAAI,OAAO,MAAA;AAEjC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAA;AAChC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,QAAQ,CAAA;AAChC,EAAA,IAAI,GAAA,IAAO,CAAA,IAAK,GAAA,KAAQ,GAAA,EAAK,OAAO,MAAA;AAGpC,EAAA,IAAI,GAAA,GAAM,GAAG,OAAO,MAAA;AAGpB,EAAA,MAAM,WAAA,GAAc,KAAK,GAAA,CAAI,GAAG,SAAS,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,GAAI,CAAC,CAAC,CAAA;AAC3D,EAAA,IAAI,WAAA,GAAc,CAAA,IAAK,GAAA,GAAM,WAAA,IAAe,GAAA,EAAS;AAIjD,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,IAAA,CAAK,CAAA,CAAA,KAAK,MAAM,CAAC,CAAA;AAC3C,IAAA,OAAO,WAAW,QAAA,GAAW,KAAA;AAAA,EACjC;AAEA,EAAA,OAAO,MAAA;AACX;AAiBA,SAAS,sBAAA,CACL,SAAA,EACA,MAAA,EACA,IAAA,EACgB;AAChB,EAAA,IAAI,IAAA,EAAM;AACN,IAAA,OAAO,EAAE,GAAA,EAAK,SAAA,CAAU,CAAC,CAAA,EAAG,KAAK,SAAA,CAAU,CAAC,CAAA,EAAG,KAAA,EAAO,IAAA,EAAK;AAAA,EAC/D;AACA,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA;AACzE,EAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACnB,IAAA,OAAO,EAAE,GAAA,EAAK,SAAA,CAAU,CAAC,CAAA,EAAG,KAAK,SAAA,CAAU,CAAC,CAAA,EAAG,KAAA,EAAO,KAAA,EAAM;AAAA,EAChE;AACA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAChC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAChC,EAAA,OAAO;AAAA,IACH,KAAK,IAAA,CAAK,GAAA,CAAI,SAAA,CAAU,CAAC,GAAG,OAAO,CAAA;AAAA,IACnC,KAAK,IAAA,CAAK,GAAA,CAAI,SAAA,CAAU,CAAC,GAAG,OAAO,CAAA;AAAA,IACnC,KAAA,EAAO;AAAA,GACX;AACJ;AA0CO,SAAS,oBAAA,CACZ,WACA,MAAA,EAC4B;AAC5B,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA;AACzE,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAE9B,EAAA,MAAM,CAAC,EAAA,EAAI,EAAE,CAAA,GAAI,SAAA;AACjB,EAAA,MAAM,QAAQ,EAAA,GAAK,EAAA;AACnB,EAAA,IAAI,KAAA,IAAS,GAAG,OAAO,MAAA;AAEvB,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAChC,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAMhC,EAAA,MAAM,UAAA,GAAa,EAAA,GAAK,CAAA,IAAK,EAAA,GAAK,CAAA;AAClC,EAAA,MAAM,WAAA,GAAc,IAAA,IAAQ,UAAA,GAAc,CAAA,GAAI,EAAA,GAAM,KAAA,CAAA;AACpD,EAAA,MAAM,WAAA,GAAc,IAAA,IAAQ,UAAA,GAAa,EAAA,GAAW,KAAA,CAAA;AAEpD,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,OAAA;AAIJ,EAAA,IAAI,OAAA,IAAW,EAAA,IAAM,OAAA,IAAW,EAAA,GAAK,WAAA,EAAa;AAC9C,IAAA,OAAA,GAAU,EAAA;AAAA,EACd;AAIA,EAAA,IAAI,OAAA,IAAW,EAAA,IAAM,OAAA,IAAW,EAAA,GAAK,WAAA,EAAa;AAC9C,IAAA,OAAA,GAAU,EAAA;AAAA,EACd;AAEA,EAAA,IAAI,OAAA,KAAY,MAAA,IAAa,OAAA,KAAY,MAAA,EAAW,OAAO,MAAA;AAE3D,EAAA,OAAO,EAAE,GAAA,EAAK,OAAA,EAAS,GAAA,EAAK,OAAA,EAAS,OAAO,KAAA,EAAM;AACtD;AAaO,SAAS,uBAAA,CACZ,YAAA,EACA,UAAA,EACA,MAAA,EAC4B;AAC5B,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAG3C,EAAA,IAAI,WAAW,eAAA,EAAiB;AAK5B,IAAA,IAAI,KAAA,CAAM,EAAA,KAAO,YAAA,IAAgB,KAAA,CAAM,OAAO,eAAA,EAAiB;AAC3D,MAAA,OAAO,oBAAA,CAAqB,UAAA,CAAW,eAAA,EAAiB,MAAM,CAAA;AAAA,IAClE;AAEA,IAAA,OAAO,sBAAA,CAAuB,UAAA,CAAW,eAAA,EAAiB,MAAA,EAAQ,KAAK,CAAA;AAAA,EAC3E;AAGA,EAAA,IAAI,YAAA,KAAiB,YAAe,OAAO,sBAAA,CAAuB,CAAC,GAAA,EAAK,EAAE,CAAA,EAAG,MAAA,EAAQ,IAAI,CAAA;AACzF,EAAA,IAAI,YAAA,KAAiB,aAAe,OAAO,sBAAA,CAAuB,CAAC,IAAA,EAAM,GAAG,CAAA,EAAG,MAAA,EAAQ,IAAI,CAAA;AAC3F,EAAA,IAAI,YAAA,KAAiB,eAAe,OAAO,sBAAA,CAAuB,CAAC,EAAA,EAAI,CAAC,CAAA,EAAG,MAAA,EAAQ,IAAI,CAAA;AAGvF,EAAA,IAAI,iBAAiB,YAAA,EAAc;AAC/B,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA;AACzE,IAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACjB,MAAA,MAAM,GAAA,GAAM,+BAA+B,IAAI,CAAA;AAC/C,MAAA,MAAM,CAAA,GAAI,GAAA,KAAQ,KAAA,GAAQ,CAAA,GAAI,GAAA;AAC9B,MAAA,OAAO,oBAAA,CAAqB,CAAC,CAAA,EAAG,CAAC,GAAG,MAAM,CAAA;AAAA,IAC9C;AAAA,EACJ;AAEA,EAAA,OAAO,MAAA;AACX;AAYO,SAAS,qBAAA,CACZ,cACA,MAAA,EAC0B;AAC1B,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAE3C,EAAA,IAAI,KAAA,CAAM,gBAAgB,SAAA,EAAW;AACjC,IAAA,MAAM,EAAA,GAAqB,EAAE,YAAA,EAAc,IAAA,EAAM,SAAS,CAAA,EAAE;AAE5D,IAAA,IAAI,MAAA,EAAQ;AACR,MAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA;AACjC,MAAA,IAAI,IAAA,IAAQ,EAAA,IAAM,IAAA,GAAO,CAAA,EAAG;AACxB,QAAA,EAAA,CAAG,aAAa,EAAC;AACjB,QAAA,KAAA,IAAS,CAAA,GAAI,OAAO,CAAC,CAAA,EAAG,KAAK,MAAA,CAAO,CAAC,GAAG,CAAA,EAAA,EAAK;AACzC,UAAA,EAAA,CAAG,UAAA,CAAW,KAAK,CAAC,CAAA;AAAA,QACxB;AAAA,MACJ;AAAA,IACJ;AACA,IAAA,OAAO,EAAA;AAAA,EACX;AAMA,EAAA,IAAI,YAAA,KAAiB,WAAW,MAAA,EAAQ;AACpC,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA;AACjC,IAAA,IAAI,QAAQ,CAAA,EAAG;AACX,MAAA,MAAM,EAAA,GAAqB,EAAE,YAAA,EAAc,IAAA,EAAM,SAAS,CAAA,EAAE;AAC5D,MAAA,IAAI,QAAQ,EAAA,EAAI;AACZ,QAAA,EAAA,CAAG,aAAa,EAAC;AACjB,QAAA,KAAA,IAAS,CAAA,GAAI,OAAO,CAAC,CAAA,EAAG,KAAK,MAAA,CAAO,CAAC,GAAG,CAAA,EAAA,EAAK;AACzC,UAAA,EAAA,CAAG,UAAA,CAAW,KAAK,CAAC,CAAA;AAAA,QACxB;AAAA,MACJ;AACA,MAAA,OAAO,EAAA;AAAA,IACX;AAAA,EACJ;AAEA,EAAA,OAAO,MAAA;AACX;AAWO,SAAS,qBAAA,CACZ,YAAA,EACA,UAAA,EACA,MAAA,EACoB;AAEpB,EAAA,IAAI,UAAA,CAAW,SAAA,IAAa,UAAA,CAAW,SAAA,CAAU,SAAS,CAAA,EAAG;AACzD,IAAA,OAAO,UAAA,CAAW,SAAA;AAAA,EACtB;AAGA,EAAA,OAAO,qBAAA,CAAsB,cAAc,MAAM,CAAA;AACrD;AAQO,SAAS,cAAc,YAAA,EAA+B;AACzD,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,EAAA,OAAO,MAAM,WAAA,KAAgB,QAAA;AACjC;AAYO,SAAS,eAAA,CAAgB,cAAsB,OAAA,EAA2B;AAC7E,EAAA,IAAI,iBAAiB,MAAA,EAAQ;AAGzB,IAAA,OAAO,OAAA,KAAY,GAAA;AAAA,EACvB;AACA,EAAA,OAAO,KAAA;AACX;AAaO,SAAS,WAAA,CACZ,cACA,gBAAA,EACO;AACP,EAAA,IAAI,gBAAA,EAAkB,OAAO,OAAO,KAAA;AACpC,EAAA,IAAI,oBAAoB,gBAAA,CAAiB,GAAA,KAAQ,MAAA,IAAa,gBAAA,CAAiB,QAAQ,MAAA,EAAW;AAC9F,IAAA,OAAO,KAAA;AAAA,EACX;AACA,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,EAAA,IAAI,KAAA,CAAM,WAAA,KAAgB,OAAA,EAAS,OAAO,KAAA;AAC1C,EAAA,OAAO,IAAA;AACX;AAiBO,SAAS,oBAAA,CACZ,YAAA,EACA,UAAA,EACA,MAAA,EACyB;AACzB,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAI3C,EAAA,IAAI,YAAA,KAAiB,aAAA,IAAiB,UAAA,CAAW,IAAA,EAAM;AACnD,IAAA,MAAM,aAAA,GAAwC;AAAA,MAC1C,OAAA,EAAM,CAAA;AAAA,MAAG,OAAA,EAAM,EAAA;AAAA,MAAI,GAAA,EAAK,MAAA;AAAA,MAAQ,CAAA,EAAG,CAAA;AAAA,MAAG,CAAA,EAAG;AAAA,KAC7C;AACA,IAAA,MAAM,GAAA,GAAM,aAAA,CAAc,UAAA,CAAW,IAAI,CAAA;AACzC,IAAA,IAAI,QAAQ,MAAA,EAAW;AACnB,MAAA,OAAO,EAAE,QAAA,EAAU,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,QAAQ,MAAA,EAAO;AAAA,IAC5D;AAAA,EACJ;AAGA,EAAA,IAAI,KAAA,CAAM,cAAc,UAAA,EAAY;AAChC,IAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,IAAA,EAAM,QAAQ,gBAAA,EAAiB;AAAA,EACnE;AACA,EAAA,IAAI,KAAA,CAAM,cAAc,aAAA,EAAe;AACnC,IAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,KAAA,EAAO,QAAQ,gBAAA,EAAiB;AAAA,EACpE;AAGA,EAAA,IAAI,WAAW,eAAA,EAAiB;AAC5B,IAAA,OAAO;AAAA,MACH,QAAA,EAAA,CAAW,WAAW,eAAA,CAAgB,CAAC,IAAI,UAAA,CAAW,eAAA,CAAgB,CAAC,CAAA,IAAK,CAAA;AAAA,MAC5E,QAAA,EAAU,KAAA;AAAA,MACV,MAAA,EAAQ;AAAA,KACZ;AAAA,EACJ;AAGA,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACnB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA;AAC9B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA;AAC9B,IAAA,IAAI,GAAA,GAAM,CAAA,IAAK,GAAA,GAAM,CAAA,EAAG;AACpB,MAAA,OAAO,EAAE,QAAA,EAAU,CAAA,EAAG,QAAA,EAAU,KAAA,EAAO,QAAQ,MAAA,EAAO;AAAA,IAC1D;AAAA,EACJ;AAEA,EAAA,OAAO,MAAA;AACX;AAMO,SAAS,sBAAA,CACZ,YAAA,EACA,UAAA,EACA,MAAA,EACe;AACf,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA;AAGzE,EAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,YAAA,EAAc,UAAA,EAAY,IAAI,CAAA;AACnE,EAAA,IAAI,OAAA,EAAS;AACT,IAAA,MAAM,GAAA,GAAM,KAAK,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,IAAI,CAAA,GAAI,CAAA;AAClD,IAAA,MAAM,GAAA,GAAM,KAAK,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,IAAI,CAAA,GAAI,CAAA;AAClD,IAAA,MAAM,cAAA,GAAiB,GAAA,GAAM,OAAA,CAAQ,QAAA,IAAY,MAAM,OAAA,CAAQ,QAAA;AAE/D,IAAA,IAAI,OAAA,CAAQ,YAAY,cAAA,EAAgB;AACpC,MAAA,OAAO;AAAA,QACH,IAAA,EAAM,WAAA;AAAA,QACN,mBAAmB,OAAA,CAAQ,QAAA;AAAA,QAC3B,qBAAqB,OAAA,CAAQ;AAAA,OACjC;AAAA,IACJ;AAAA,EACJ;AAGA,EAAA,IAAI,KAAA,CAAM,YAAA,CAAa,QAAA,CAAS,cAAc,CAAA,EAAG;AAC7C,IAAA,OAAO,EAAE,MAAM,YAAA,EAAa;AAAA,EAChC;AACA,EAAA,OAAO,EAAE,MAAM,aAAA,EAAc;AACjC;AAYO,SAAS,uBAAA,CACZ,cACA,MAAA,EACO;AACP,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAG3C,EAAA,IAAI,CAAC,KAAA,CAAM,YAAA,CAAa,QAAA,CAAS,cAAc,GAAG,OAAO,KAAA;AAGzD,EAAA,IAAI,MAAM,OAAA,KAAY,YAAA,IAAgB,KAAA,CAAM,OAAA,KAAY,aAAa,OAAO,KAAA;AAG5E,EAAA,IAAI,YAAA,KAAiB,MAAA,IAAU,YAAA,KAAiB,QAAA,EAAU,OAAO,KAAA;AAGjE,EAAA,IAAI,MAAA,IAAW,OAAO,CAAC,CAAA,GAAI,OAAO,CAAC,CAAA,IAAM,IAAI,OAAO,KAAA;AAGpD,EAAA,IAAI,YAAA,KAAiB,OAAA,IAAW,CAAC,MAAA,EAAQ,OAAO,KAAA;AAEhD,EAAA,OAAO,IAAA;AACX;AAaO,SAAS,iBACZ,YAAA,EAC2B;AAC3B,EAAA,MAAM,KAAA,GAAQ,iBAAiB,YAAY,CAAA;AAE3C,EAAA,QAAQ,MAAM,OAAA;AAAS,IACnB,KAAK,UAAA;AAAmB,MAAA,OAAO,KAAA;AAAA,IAC/B,KAAK,iBAAA;AAAmB,MAAA,OAAO,KAAA;AAAA,IAC/B,KAAK,WAAA;AAED,MAAA,IAAI,YAAA,KAAiB,cAAc,OAAO,WAAA;AAC1C,MAAA,OAAO,KAAA;AAAA,IACX,KAAK,WAAA;AAAmB,MAAA,OAAO,KAAA;AAAA,IAC/B,KAAK,YAAA;AAAmB,MAAA,OAAO,KAAA;AAAA,IAC/B;AAAwB,MAAA,OAAO,KAAA;AAAA;AAEvC;AASO,SAAS,qBACZ,YAAA,EAC0B;AAE1B,EAAA,IAAI,YAAA,KAAiB,QAAQ,OAAO,YAAA;AACpC,EAAA,OAAO,WAAA;AACX;AAsBO,SAAS,qBAAA,CACZ,KAAA,EACA,SAAA,EACA,MAAA,EACc;AAEd,EAAA,MAAM,UAAA,GAAa,oBAAoB,KAAK,CAAA;AAC5C,EAAA,MAAM,eAAe,UAAA,CAAW,YAAA;AAGhC,EAAA,MAAM,aAAA,GAAgB,MAAA,CACjB,MAAA,CAAO,CAAC,MAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAA,IAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAGzE,EAAA,MAAM,cAAA,GAAiB,qBAAA,CAAsB,YAAA,EAAc,MAAM,CAAA;AACjE,EAAA,MAAM,EAAE,MAAA,EAAQ,aAAA,KAAkB,aAAA,CAAc,YAAA,EAAc,YAAY,MAAM,CAAA;AAChF,EAAA,IAAI,kBAAA,GAAqB,0BAA0B,YAAY,CAAA;AAC/D,EAAA,IAAI,SAAA,GAAY,8BAAA,CAA+B,YAAA,EAAc,UAAA,CAAW,eAAe,CAAA;AACvF,EAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,YAAA,EAAc,aAAa,CAAA;AAC9D,EAAA,MAAM,gBAAA,GAAmB,uBAAA,CAAwB,YAAA,EAAc,UAAA,EAAY,MAAM,CAAA;AACjF,EAAA,MAAM,cAAA,GAAiB,qBAAA,CAAsB,YAAA,EAAc,UAAA,EAAY,MAAM,CAAA;AAC7E,EAAA,MAAM,MAAA,GAAS,cAAc,YAAY,CAAA;AACzC,EAAA,IAAI,gBAAA,GAAmB,uBAAA,CAAwB,YAAA,EAAc,UAAA,CAAW,eAAe,CAAA;AACvF,EAAA,MAAM,aAAA,GAAgB,qBAAqB,YAAY,CAAA;AAKvD,EAAA,IAAI,CAAC,YAAA,CAAa,YAAY,CAAA,IAAK,mBAAmB,cAAA,EAAgB;AAElE,IAAA,IAAI,CAAC,oBAAoB,kBAAA,GAAqB,KAAA;AAC9C,IAAA,IAAI,SAAA,KAAc,WAAW,SAAA,GAAY,YAAA;AACzC,IAAA,gBAAA,GAAmB,IAAA;AAAA,EACvB;AAEA,EAAA,OAAO;AAAA,IACH,kBAAA,EAAoB,UAAA;AAAA,IACpB,cAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,kBAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAW,SAAA,IAAa,MAAA;AAAA,IACxB,gBAAA;AAAA,IACA,cAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA;AAAA,GACJ;AACJ;;;AC/gCA,IAAM,iBAAA,GAAoB,UAAA;AAC1B,IAAM,gBAAA,GAAmB,UAAA;AAEzB,SAAS,kBAAkB,GAAA,EAAsB;AAC7C,EAAA,IAAI,GAAA,IAAO,GAAA,IAAO,GAAA,IAAO,iBAAA,EAAmB,OAAO,IAAA;AACnD,EAAA,IAAI,GAAA,GAAM,iBAAA,IAAqB,GAAA,IAAO,gBAAA,EAAkB,OAAO,IAAA;AAC/D,EAAA,OAAO,KAAA;AACX;AAEA,SAAS,cAAc,GAAA,EAAqB;AACxC,EAAA,OAAO,GAAA,IAAO,iBAAA,GAAoB,GAAA,GAAM,GAAA,GAAO,GAAA;AACnD;AAyBA,SAAS,qBAAqB,WAAA,EAA6C;AACvE,EAAA,MAAM,QAAgB,EAAC;AACvB,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,KAAA,MAAW,CAAA,IAAK,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,EAAG;AACvC,IAAA,IAAI,KAAK,IAAA,EAAM;AACf,IAAA,OAAA,EAAA;AACA,IAAA,MAAM,IAAI,CAAA,YAAa,IAAA,GAAO,CAAA,GAAI,IAAI,KAAK,CAAC,CAAA;AAC5C,IAAA,IAAI,CAAC,MAAM,CAAA,CAAE,OAAA,EAAS,CAAA,EAAG,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,EACzC;AACA,EAAA,IAAI,MAAM,MAAA,GAAS,CAAA,IAAK,MAAM,MAAA,GAAS,OAAA,GAAU,KAAK,OAAO,IAAA;AAE7D,EAAA,MAAM,QAAA,GAAY,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AACzD,EAAA,MAAM,MAAA,GAAY,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,EAAY,CAAC,CAAA;AACxD,EAAA,MAAM,OAAA,GAAY,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AACzD,EAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,aAAA,EAAe,CAAC,CAAA;AAC3D,EAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,aAAA,EAAe,CAAC,CAAA;AAC3D,EAAA,MAAM,OAAA,GAAY,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,cAAA,EAAgB,CAAC,CAAA;AAE5D,EAAA,MAAM,aAAA,GAAgB,CAAC,CAAA,EAAgB,SAAA,GAAoB,CAAA,KAAM;AAC7D,IAAA,IAAI,CAAA,CAAE,IAAA,IAAQ,CAAA,EAAG,OAAO,IAAA;AACxB,IAAA,MAAM,GAAA,GAAM,CAAC,GAAG,CAAC,CAAA;AACjB,IAAA,OAAO,IAAA,CAAK,IAAI,GAAG,GAAG,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,GAAG,CAAA,IAAK,SAAA;AAAA,EAClD,CAAA;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA,IACT,KAAA,EAAQ,SAAS,IAAA,KAAU,CAAA;AAAA,IAC3B,GAAA,EAAQ,OAAO,IAAA,KAAY,CAAA;AAAA,IAC3B,IAAA,EAAQ,aAAA,CAAc,OAAA,EAAS,CAAC,CAAA;AAAA,IAChC,MAAA,EAAQ,UAAU,IAAA,KAAS,CAAA;AAAA,IAC3B,MAAA,EAAQ,UAAU,IAAA,KAAS;AAAA,GAC/B;AAEA,EAAA,MAAM,QAAA,GAAY,QAAQ,IAAA,KAAS,CAAA;AACnC,EAAA,MAAM,SAAA,GAAY,YAAY,IAAA,CAAK,KAAA;AACnC,EAAA,MAAM,OAAA,GAAY,aAAa,IAAA,CAAK,GAAA;AAEpC,EAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,QAAA,EAAU,WAAW,OAAA,EAAQ;AACvD;AAEA,SAAS,iBAAiB,IAAA,EAA0C;AAChE,EAAA,MAAM,QAAQ,CAAC,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAC,CAAA;AAE/B,EAAA,IAAI,IAAA,CAAK,MAAA,EAAkE,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,KAAK,MAAA,IAAU,IAAA,CAAK,MAAA,EAAmD,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,IAAA,CAAK,QAAU,IAAA,CAAK,MAAA,IAAU,KAAK,MAAA,EAAoC,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,IAAA,CAAK,GAAA,IAAU,IAAA,CAAK,IAAA,IAAU,IAAA,CAAK,UAAU,IAAA,CAAK,MAAA,EAAqB,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,IAAA,CAAK,KAAA,IAAU,IAAA,CAAK,GAAA,IAAU,IAAA,CAAK,IAAA,IAAU,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAEzF,EAAA,IAAI,IAAA,CAAK,MAAA,EAAkE,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,KAAK,MAAA,IAAU,IAAA,CAAK,MAAA,EAAmD,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,IAAA,CAAK,QAAU,IAAA,CAAK,MAAA,IAAU,KAAK,MAAA,EAAoC,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,IAAA,CAAK,GAAA,IAAU,IAAA,CAAK,IAAA,IAAU,IAAA,CAAK,UAAU,IAAA,CAAK,MAAA,EAAqB,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,CAAC,IAAA,CAAK,KAAA,IAAS,IAAA,CAAK,GAAA,IAAO,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,MAAA,EAAW,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAEvF,EAAA,IAAI,IAAA,CAAK,MAAA,EAAkE,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,KAAK,MAAA,IAAU,IAAA,CAAK,MAAA,EAAmD,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,IAAA,CAAK,QAAU,IAAA,CAAK,MAAA,IAAU,KAAK,MAAA,EAAoC,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AACvF,EAAA,IAAI,CAAC,IAAA,CAAK,GAAA,IAAO,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,MAAA,IAAU,IAAA,CAAK,MAAA,EAAyB,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAEvF,EAAA,IAAI,IAAA,CAAK,MAAA,EAAsC,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAC3D,EAAA,IAAI,KAAK,MAAA,IAAU,IAAA,CAAK,MAAA,EAAuB,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAC3D,EAAA,IAAI,CAAC,KAAK,IAAA,IAAQ,IAAA,CAAK,UAAU,IAAA,CAAK,MAAA,EAAS,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAE3D,EAAA,IAAI,IAAA,CAAK,MAAA,EAA2B,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAChD,EAAA,IAAI,CAAC,IAAA,CAAK,MAAA,IAAU,KAAK,MAAA,EAAW,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAEhD,EAAA,IAAI,CAAC,IAAA,CAAK,MAAA,EAAQ,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA;AAE9B,EAAA,OAAO,KAAA;AACX;AAEA,IAAM,cAAA,GAAyC;AAAA,EAC3C,IAAA,EAAa,CAAA;AAAA,EAAG,MAAA,EAAa,CAAA;AAAA,EAC7B,SAAA,EAAa,CAAA;AAAA,EAAG,KAAA,EAAa,CAAA;AAAA,EAAG,WAAA,EAAa,CAAA;AAAA,EAAG,OAAA,EAAS,CAAA;AAAA,EACzD,IAAA,EAAa,CAAA;AAAA,EAAG,GAAA,EAAa,CAAA;AAAA,EAC7B,IAAA,EAAa,CAAA;AAAA,EACb,QAAA,EAAa,CAAA;AAAA,EACb,SAAA,EAAa;AACjB,CAAA;AAEA,SAAS,cAAc,KAAA,EAAmD;AACtE,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,IAAI,SAAA,GAAY,MAAM,CAAC,CAAA;AACvB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,IAAK,CAAA,EAAG,CAAA,EAAA,EAAK;AACzB,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,IAAK,SAAA,EAAW;AACvB,MAAA,SAAA,GAAY,MAAM,CAAC,CAAA;AACnB,MAAA,SAAA,GAAY,CAAA;AAAA,IAChB;AAAA,EACJ;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,SAAA,EAAU;AAChD;AAEA,SAAS,aAAA,CAAc,OAAe,QAAA,EAA2C;AAC7E,EAAA,QAAQ,KAAA;AAAO,IACX,KAAK,CAAA;AAAG,MAAA,OAAO,IAAA;AAAA,IACf,KAAK,CAAA;AAAG,MAAA,OAAO,QAAA,CAAS,WAAW,IAAA,GAAO,OAAA;AAAA,IAC1C,KAAK,CAAA;AAAG,MAAA,OAAO,QAAA,CAAS,WAAW,OAAA,GAAU,WAAA;AAAA,IAC7C,KAAK,CAAA;AAAG,MAAA,OAAO,QAAA,CAAS,UAAW,OAAA,GAAU,aAAA;AAAA,IAC7C,KAAK,CAAA;AAAG,MAAA,OAAO,QAAA,CAAS,UAAW,OAAA,GAAU,aAAA;AAAA,IAC7C,KAAK,CAAA;AAAG,MAAA,OAAO,QAAA,CAAS,UAAW,UAAA,GAAa,gBAAA;AAAA,IAChD;AAAS,MAAA,OAAO,IAAA;AAAA;AAExB;AAMA,SAAS,qBAAA,CACL,aACA,YAAA,EACa;AACb,EAAA,MAAM,QAAA,GAAW,qBAAqB,WAAW,CAAA;AACjD,EAAA,IAAI,CAAC,UAAU,OAAO,IAAA;AAEtB,EAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,QAAA,CAAS,IAAI,CAAA;AAC5C,EAAA,MAAM,QAAA,GAAW,eAAe,YAAY,CAAA;AAC5C,EAAA,IAAI,QAAA,KAAa,MAAA,EAAW,KAAA,CAAM,QAAQ,CAAA,IAAK,CAAA;AAC/C,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,aAAA,CAAc,KAAK,CAAA;AACrC,EAAA,OAAO,aAAA,CAAc,OAAO,QAAQ,CAAA;AACxC;AAeA,SAAS,iBAAiB,GAAA,EAAqB;AAC3C,EAAA,MAAM,OAAA,GAAU,IAAI,IAAA,EAAK;AACzB,EAAA,IAAI,SAAA,CAAU,IAAA,CAAK,OAAO,CAAA,EAAG;AACzB,IAAA,MAAM,CAAA,GAAI,QAAA,CAAS,OAAA,EAAS,EAAE,CAAA;AAC9B,IAAA,OAAO,OAAO,CAAA,IAAK,EAAA,GAAK,GAAA,GAAO,CAAA,GAAI,OAAO,CAAC,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,GAAA;AACX;AASO,SAAS,mBAAA,CACZ,MACA,aAAA,EACK;AACL,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE9B,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,CAAC,CAAC,CAAA;AAChC,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAc;AAC5C,IAAA,MAAM,EAAA,GAAK,YAAA,CAAa,aAAA,CAAc,CAAC,CAAC,CAAA;AACxC,IAAA,MAAM,EAAA,GAAK,iBAAiB,IAAA,CAAK,GAAA,CAAI,OAAK,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAC/C,IAAA,MAAM,UAAA,GAAa,EAAA,GAAK,cAAA,CAAe,EAAE,CAAA,GAAI,IAAA;AAC7C,IAAA,OAAO,EAAA,KAAO,UAAA,IAAc,UAAA,KAAe,UAAA,IAAc,EAAA,KAAO,QAAA;AAAA,EACpE,CAAC,CAAA;AAED,EAAA,IAAI,YAAA,CAAa,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAEtC,EAAA,MAAM,MAAA,GAAS,gBAAgB,IAAI,CAAA;AACnC,EAAA,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAW;AAC1B,IAAA,KAAA,MAAW,eAAe,YAAA,EAAc;AACpC,MAAA,MAAM,GAAA,GAAM,EAAE,WAAW,CAAA;AACzB,MAAA,MAAM,EAAA,GAAK,YAAA,CAAa,aAAA,CAAc,WAAW,CAAC,CAAA;AAElD,MAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AACzB,QAAA,IAAI,EAAA,KAAO,MAAA,IAAU,EAAA,KAAO,QAAA,EAAU;AAClC,UAAA,CAAA,CAAE,WAAW,CAAA,GAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,GAAG,CAAC,CAAA,CAAA;AAAA,QACvC,CAAA,MAAA,IAAW,iBAAA,CAAkB,GAAG,CAAA,EAAG;AAC/B,UAAA,CAAA,CAAE,WAAW,IAAI,IAAI,IAAA,CAAK,cAAc,GAAG,CAAC,EAAE,WAAA,EAAY;AAAA,QAC9D,CAAA,MAAO;AACH,UAAA,CAAA,CAAE,WAAW,CAAA,GAAI,MAAA,CAAO,GAAG,CAAA;AAAA,QAC/B;AAAA,MACJ,CAAA,MAAA,IAAW,eAAe,IAAA,EAAM;AAC5B,QAAA,CAAA,CAAE,WAAW,CAAA,GAAI,GAAA,CAAI,WAAA,EAAY;AAAA,MACrC,CAAA,MAAO;AAIH,QAAA,IAAA,CAAK,OAAO,MAAA,IAAU,EAAA,KAAO,QAAA,KAAa,OAAO,QAAQ,QAAA,EAAU;AAC/D,UAAA,CAAA,CAAE,WAAW,CAAA,GAAI,gBAAA,CAAiB,GAAG,CAAA;AAAA,QACzC,CAAA,MAAO;AACH,UAAA,CAAA,CAAE,WAAW,CAAA,GAAI,MAAA,CAAO,GAAG,CAAA;AAAA,QAC/B;AAAA,MACJ;AAAA,IACJ;AACA,IAAA,OAAO,CAAA;AAAA,EACX,CAAC,CAAA;AACL;AAuBO,SAAS,uBAAA,CACZ,SAAA,EACA,IAAA,EACA,aAAA,EACA,aAAA,EACc;AACd,EAAA,MAAM,SAAyB,EAAC;AAGhC,EAAA,MAAM,eAAe,aAAA,IAAiB,IAAA;AAEtC,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzD,IAAA,MAAM,YAAY,QAAA,CAAS,KAAA;AAC3B,IAAA,IAAI,CAAC,SAAA,IAAa,QAAA,CAAS,SAAA,KAAc,OAAA,EAAS;AAGlD,IAAA,IAAI,CAAC,SAAA,IAAa,QAAA,CAAS,SAAA,KAAc,OAAA,EAAS;AAC9C,MAAA,MAAA,CAAO,OAAO,CAAA,GAAI;AAAA,QACd,KAAA,EAAO,QAAA;AAAA,QACP,kBAAA,EAAoB,EAAE,YAAA,EAAc,OAAA,EAAQ;AAAA,QAC5C,IAAA,EAAM,cAAA;AAAA,QACN,kBAAA,EAAoB;AAAA,OACxB;AACA,MAAA;AAAA,IACJ;AAEA,IAAA,IAAI,CAAC,SAAA,EAAW;AAEhB,IAAA,MAAM,aAAA,GAAgB,cAAc,SAAS,CAAA;AAC7C,IAAA,MAAM,eAAe,OAAO,aAAA,KAAkB,WACvC,aAAA,IAAiB,EAAA,GACjB,eAAe,YAAA,IAAgB,EAAA;AACtC,IAAA,MAAM,cAAc,IAAA,CAAK,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,CAAC,CAAA;AAG9C,IAAA,MAAM,YAAA,GAAe,mBAAA;AAAA,MACjB,YAAA;AAAA,MAAc,WAAA;AAAA,MAAa,OAAA;AAAA,MAAS,IAAA;AAAA,MAAM;AAAA,KAC9C;AAGA,IAAA,IAAI,eAAe,YAAA,CAAa,MAAA;AAChC,IAAA,IAAI,SAAS,IAAA,EAAM;AACf,MAAA,YAAA,GAAe,QAAA,CAAS,IAAA;AAAA,IAC5B,CAAA,MAAA,IAAW,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,KAAA,EAAO;AAClD,MAAA,IAAI,YAAA,KAAiB,SAAA,IAAa,YAAA,KAAiB,SAAA,EAAW;AAC1D,QAAA,YAAA,GAAe,SAAA;AAAA,MACnB;AAAA,IACJ;AAGA,IAAA,IAAI,iBAAiB,cAAA,EAAgB;AACjC,MAAA,MAAM,eAAe,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,EAAE,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,KAAK,MAAS,CAAA,CAAE,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,CAAC,CAAA;AACnG,MAAA,MAAM,YAAA,GAAe,mEAAA;AACrB,MAAA,IAAI,YAAA,CAAa,MAAA,GAAS,CAAA,IAAK,YAAA,CAAa,MAAM,CAAC,GAAA,KAAa,YAAA,CAAa,IAAA,CAAK,GAAG,GAAG,CAAA,CAAA,CAAG,IAAA,EAAM,CAAC,CAAA,EAAG;AACjG,QAAA,YAAA,GAAe,UAAA;AAAA,MACnB;AAAA,IACJ;AAIA,IAAA,MAAM,EAAA,GAAK,qBAAA,CAAsB,aAAA,EAAe,SAAA,EAAW,WAAW,CAAA;AACtE,IAAA,MAAM,aAAa,EAAA,CAAG,kBAAA;AAGtB,IAAA,MAAM,cAAA,GAAiB,qBAAA,CAAsB,UAAA,CAAW,YAAA,EAAc,WAAW,eAAe,CAAA;AAChG,IAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,UAAA,CAAW,YAAA,EAAc,OAAO,CAAA;AACjE,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,UAAA,CAAW,YAAA,EAAc,GAAG,gBAAgB,CAAA;AACrE,IAAA,MAAM,SAAA,GAAY,gBAAA,CAAiB,UAAA,CAAW,YAAY,CAAA;AAE1D,IAAA,MAAM,EAAA,GAAuB;AAAA,MACzB,KAAA,EAAO,SAAA;AAAA,MACP,kBAAA,EAAoB,UAAA;AAAA,MACpB,IAAA,EAAM,YAAA;AAAA;AAAA,MAGN,QAAQ,EAAA,CAAG,MAAA;AAAA,MACX,eAAe,EAAA,CAAG,aAAA;AAAA,MAClB,oBAAoB,EAAA,CAAG,kBAAA;AAAA,MACvB,WAAW,EAAA,CAAG,SAAA;AAAA,MACd,kBAAkB,EAAA,CAAG,gBAAA;AAAA,MACrB,MAAA,EAAQ,GAAG,MAAA,IAAU,MAAA;AAAA,MACrB,eAAe,EAAA,CAAG,aAAA;AAAA,MAClB,gBAAA,EAAkB,GAAG,gBAAA,IAAoB,MAAA;AAAA;AAAA,MAGzC,IAAA;AAAA,MACA,cAAA;AAAA,MACA,UAAU,QAAA,IAAY,MAAA;AAAA,MACtB;AAAA,KACJ;AAIA,IAAA,IAAI,SAAS,SAAA,EAAW;AACpB,MAAA,IAAI,QAAA,CAAS,cAAc,OAAA,EAAS;AAChC,QAAA,EAAA,CAAG,KAAA,GAAQ,QAAA;AACX,QAAA,EAAA,CAAG,IAAA,GAAO,cAAA;AAAA,MACd,CAAA,MAAO;AACH,QAAA,EAAA,CAAG,KAAA,GAAQ,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,SAAS,SAAS,CAAA,CAAA;AAC7C,QAAA,EAAA,CAAG,IAAA,GAAO,cAAA;AAAA,MACd;AAAA,IACJ;AAKA,IAAA,IAAA,CAAK,OAAA,KAAY,OAAA,IAAW,OAAA,KAAY,OAAA,KAAY,SAAA,EAAW;AAC3D,MAAA,IAAI,QAAA,CAAS,MAAA,IAAU,QAAA,CAAS,MAAA,KAAW,SAAA,EAAW;AAClD,QAAA,EAAA,CAAG,WAAA,GAAc;AAAA,UACb,QAAQ,QAAA,CAAS,MAAA;AAAA,UACjB,IAAA,EAAM,aAAA;AAAA,UACN,MAAA,EAAQ;AAAA,SACZ;AAAA,MACJ,CAAA,MAAO;AACH,QAAA,MAAM,iBAAiB,EAAA,CAAG,IAAA;AAE1B,QAAA,MAAM,SAAA,GAAY,sBAAA,CAAuB,YAAA,EAAc,UAAA,EAAY,WAAW,CAAA;AAC9E,QAAA,MAAM,eAAe,CAAC,GAAG,IAAI,GAAA,CAAI,WAAW,CAAC,CAAA;AAC7C,QAAA,EAAA,CAAG,WAAA,GAAc,yBAAA;AAAA,UACb,YAAA;AAAA,UAAc,cAAA;AAAA,UAAgB,YAAA,CAAa,MAAA;AAAA,UAAQ,SAAA;AAAA,UACnD,WAAA;AAAA,UAAa,EAAE,IAAA,EAAM,SAAA,CAAU,IAAA;AAAK,SACxC;AAEA,QAAA,IAAI,EAAA,CAAG,WAAA,CAAY,IAAA,KAAS,WAAA,IAAe,mBAAmB,cAAA,EAAgB;AAC1E,UAAA,MAAM,IAAA,GAAO,WAAA,CAAY,MAAA,CAAO,CAAC,CAAA,KAAW,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,CAAC,CAAC,CAAA;AAC9E,UAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,YAAA,EAAc,UAAA,EAAY,IAAI,CAAA;AACnE,UAAA,IAAI,OAAA,EAAS;AACT,YAAA,EAAA,CAAG,WAAA,CAAY,YAAY,OAAA,CAAQ,QAAA;AAAA,UACvC;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAGA,IAAA,IAAI,GAAG,IAAA,KAAS,UAAA,IAAe,gBAAgB,cAAA,CAAe,YAAY,MAAM,UAAA,EAAa;AACzF,MAAA,MAAM,uBAAuB,YAAA,CAAa,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,CAAC,CAAA;AAC/D,MAAA,MAAM,GAAA,GAAM,qBAAA,CAAsB,oBAAA,EAAsB,YAAY,CAAA;AACpE,MAAA,IAAI,GAAA,KAAQ,cAAA,GAAiB,GAAA;AAAA,IACjC;AAGA,IAAA,IAAI,EAAA,CAAG,IAAA,KAAS,SAAA,IAAa,EAAA,CAAG,SAAS,SAAA,EAAW;AAChD,MAAA,IAAI,CAAC,QAAA,CAAS,SAAA,IAAa,CAAC,SAAS,MAAA,EAAQ;AACzC,QAAA,MAAM,WAAA,GAAc,qBAAA,CAAsB,YAAA,EAAc,WAAW,CAAA;AACnE,QAAA,IAAI,WAAA,EAAa;AACb,UAAA,EAAA,CAAG,gBAAA,GAAmB,WAAA;AAAA,QAC1B;AAAA,MACJ;AAAA,IACJ;AAEA,IAAA,MAAA,CAAO,OAAO,CAAA,GAAI,EAAA;AAAA,EACtB;AAEA,EAAA,OAAO,MAAA;AACX;;;ACncA,IAAM,UAAA,GAAa,CAAC,IAAA,KAChB,IAAA,KAAS,aAAa,IAAA,KAAS,SAAA;AAEnC,IAAM,mBAAA,GAAsB,CAAC,KAAA,EAAe,KAAA,KACxC,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAC,GAAA,KAAa,IAAI,KAAK,CAAC,EAAE,MAAA,CAAO,CAAC,UAAe,KAAA,IAAS,IAAI,CAAC,CAAA,CAAE,IAAA;AAGhF,SAAS,mBAAA,CACZ,WAAA,EACA,KAAA,EACA,KAAA,EACqB;AACrB,EAAA,IAAI,WAAA,KAAgB,WAAW,OAAO,SAAA;AACtC,EAAA,IAAI,WAAA,KAAgB,WAAW,OAAO,SAAA;AACtC,EAAA,IAAI,WAAA,KAAgB,YAAY,OAAO,SAAA;AACvC,EAAA,IAAI,WAAA,KAAgB,cAAA,IAAkB,KAAA,IAAS,KAAA,CAAM,SAAS,CAAA,EAAG;AAC7D,IAAA,OAAO,mBAAA,CAAoB,KAAA,EAAO,KAAK,CAAA,IAAK,KAAK,SAAA,GAAY,SAAA;AAAA,EACjE;AACA,EAAA,OAAO,SAAA;AACX;AAGO,SAAS,6BAAA,CACZ,gBAAA,EACA,KAAA,EACA,OAAA,GAAsC,EAAC,EAChB;AACvB,EAAA,MAAM,KAAA,GAAQ,iBAAiB,CAAA,EAAG,IAAA;AAClC,EAAA,MAAM,KAAA,GAAQ,iBAAiB,CAAA,EAAG,IAAA;AAElC,EAAA,IAAI,SAAS,UAAA,CAAW,KAAK,GAAG,OAAO,EAAE,MAAM,GAAA,EAAI;AACnD,EAAA,IAAI,SAAS,UAAA,CAAW,KAAK,GAAG,OAAO,EAAE,MAAM,GAAA,EAAI;AAEnD,EAAA,IAAI,SAAS,KAAA,EAAO;AAChB,IAAA,IAAI,KAAA,KAAU,cAAA,IAAkB,KAAA,KAAU,cAAA,EAAgB;AACtD,MAAA,OAAO,EAAE,MAAM,GAAA,EAAI;AAAA,IACvB;AACA,IAAA,IAAI,KAAA,KAAU,cAAA,IAAkB,KAAA,KAAU,cAAA,EAAgB;AACtD,MAAA,OAAO,EAAE,MAAM,GAAA,EAAI;AAAA,IACvB;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,CAAQ,UAAA,IAAc,GAAA,EAAI;AAAA,EAC7C;AAEA,EAAA,IAAI,KAAA,EAAO;AACP,IAAA,MAAM,UAAU,mBAAA,CAAoB,KAAA,EAAO,gBAAA,CAAiB,CAAA,EAAG,OAAO,KAAK,CAAA;AAC3E,IAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,eAAe,EAAE,CAAA,EAAG,SAAQ,EAAE;AAAA,EACtD;AACA,EAAA,IAAI,KAAA,EAAO;AACP,IAAA,MAAM,UAAU,mBAAA,CAAoB,KAAA,EAAO,gBAAA,CAAiB,CAAA,EAAG,OAAO,KAAK,CAAA;AAC3E,IAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,eAAe,EAAE,CAAA,EAAG,SAAQ,EAAE;AAAA,EACtD;AAEA,EAAA,OAAO,IAAA;AACX;;;ACuFO,SAAS,mBAAmB,OAAA,EAAoD;AACnF,EAAA,MAAM,GAAA,GAAM,QAAQ,UAAA,IAAc,mBAAA;AAClC,EAAA,OAAO;AAAA,IACH,GAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,eAAe,GAAG,CAAA;AAAA,IACzC,GAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAA,CAAQ,eAAe,GAAG;AAAA,GAC7C;AACJ;AAGO,IAAM,iBAAA,GAAoB,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AASpD,IAAM,mBAAA,GAAsB,GAAA;AAa5B,SAAS,eAAA,CACZ,cACA,OAAA,EACiC;AACjC,EAAA,MAAM,IAAA,GAAO,YAAA,IAAgB,EAAE,GAAG,iBAAA,EAAkB;AACpD,EAAA,IAAI,CAAC,SAAS,OAAO,EAAE,OAAO,IAAA,CAAK,KAAA,EAAO,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO;AAC9D,EAAA,OAAO;AAAA,IACH,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,KAAA,EAAO,QAAQ,KAAK,CAAA;AAAA,IACzC,QAAQ,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ,QAAQ,MAAM;AAAA,GAChD;AACJ;AAiCO,SAAS,iBAAA,CACZ,QAAA,EACA,OAAA,EACA,OAAA,EAC4C;AAC5C,EAAA,MAAM,GAAA,GAAM,QAAQ,UAAA,IAAc,mBAAA;AAClC,EAAA,OAAO;AAAA,IACH,WAAA,EAAa,UAAU,IAAA,CAAK,GAAA,CAAI,GAAG,OAAA,CAAQ,KAAA,GAAQ,QAAA,CAAS,KAAK,CAAA,GAAI,GAAA;AAAA,IACrE,WAAA,EAAa,UAAU,IAAA,CAAK,GAAA,CAAI,GAAG,OAAA,CAAQ,MAAA,GAAS,QAAA,CAAS,MAAM,CAAA,GAAI;AAAA,GAC3E;AACJ;AAu4BA,SAAS,iBACL,OAAA,EACA,OAAA,EACA,OAAA,EACA,OAAA,EACA,YACA,WAAA,EACM;AACN,EAAA,MAAM,MAAA,GAAS,GAAA;AACf,EAAA,MAAM,MAAA,GAAS,CAAA;AAEf,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,CAAC,CAAA,GAAI,QAAQ,CAAC,CAAA;AACrC,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,CAAC,CAAA,GAAI,QAAQ,CAAC,CAAA;AACrC,EAAA,IAAI,MAAA,IAAU,CAAA,IAAK,MAAA,IAAU,CAAA,EAAG,OAAO,CAAA;AAGvC,EAAA,IAAI,CAAC,WAAA,EAAa;AACd,IAAA,MAAM,IAAI,OAAA,CAAQ,MAAA;AAClB,IAAA,IAAI,IAAA,GAAO,GAAG,IAAA,GAAO,CAAA;AACrB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AACxB,MAAA,IAAA,IAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,GAAI,OAAA,CAAQ,CAAC,CAAA,IAAK,MAAA;AACpC,MAAA,IAAA,IAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,GAAI,OAAA,CAAQ,CAAC,CAAA,IAAK,MAAA;AAAA,IACxC;AACA,IAAA,MAAM,QAAQ,IAAA,GAAO,CAAA;AACrB,IAAA,MAAM,QAAQ,IAAA,GAAO,CAAA;AACrB,IAAA,IAAI,IAAA,GAAO,GAAG,IAAA,GAAO,CAAA;AACrB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AACxB,MAAA,MAAM,MAAM,OAAA,CAAQ,CAAC,IAAI,OAAA,CAAQ,CAAC,KAAK,MAAA,GAAS,KAAA;AAChD,MAAA,MAAM,MAAM,OAAA,CAAQ,CAAC,IAAI,OAAA,CAAQ,CAAC,KAAK,MAAA,GAAS,KAAA;AAChD,MAAA,IAAA,IAAQ,EAAA,GAAK,EAAA;AACb,MAAA,IAAA,IAAQ,EAAA,GAAK,EAAA;AAAA,IACjB;AACA,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,IAAA,GAAO,CAAC,CAAA;AAC9B,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,IAAA,CAAK,IAAA,GAAO,CAAC,CAAA;AAC9B,IAAA,IAAI,GAAA,IAAO,GAAG,OAAO,MAAA;AACrB,IAAA,IAAI,GAAA,IAAO,GAAG,OAAO,MAAA;AAErB,IAAA,MAAM,UAAU,GAAA,GAAM,GAAA;AACtB,IAAA,MAAMC,GAAAA,GAAK,UAAU,CAAA,GACf,CAAA,GAAA,CAAK,UAAU,CAAA,IAAK,GAAA,GACpB,CAAA,GAAA,CAAK,CAAA,GAAI,OAAA,IAAW,GAAA;AAC1B,IAAA,OAAO,KAAK,GAAA,CAAI,MAAA,EAAQ,KAAK,GAAA,CAAI,MAAA,EAAQA,GAAE,CAAC,CAAA;AAAA,EAChD;AAKA,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAwC;AAC9D,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,CAAQ,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,GAAA,GAAM,WAAW,CAAC,CAAA;AACxB,IAAA,IAAI,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA;AAC3B,IAAA,IAAI,CAAC,GAAA,EAAK;AAAE,MAAA,GAAA,GAAM,EAAC;AAAG,MAAA,SAAA,CAAU,GAAA,CAAI,KAAK,GAAG,CAAA;AAAA,IAAG;AAC/C,IAAA,GAAA,CAAI,IAAA,CAAK,EAAE,CAAA,EAAG,OAAA,CAAQ,CAAC,GAAG,CAAA,EAAG,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA;AAAA,EAC7C;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,SAAA,CAAU,MAAA,EAAO,EAAG;AAClC,IAAA,GAAA,CAAI,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,CAAA,GAAI,EAAE,CAAC,CAAA;AAAA,EAChC;AAMA,EAAA,MAAM,eAAyB,EAAC;AAIhC,EAAA,IAAI,YAAA,GAAe,CAAA;AACnB,EAAA,KAAA,MAAW,GAAA,IAAO,SAAA,CAAU,MAAA,EAAO,EAAG;AAClC,IAAA,IAAI,GAAA,CAAI,MAAA,GAAS,YAAA,EAAc,YAAA,GAAe,GAAA,CAAI,MAAA;AAAA,EACtD;AACA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,YAAY,CAAC,CAAA,GAAI,CAAC,CAAA;AAEpE,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,IAAS,QAAA,EAAU,KAAA,EAAA,EAAS;AAC5C,IAAA,MAAM,aAAa,CAAA,IAAK,KAAA;AACxB,IAAA,MAAM,YAAsB,EAAC;AAE7B,IAAA,KAAA,MAAW,GAAA,IAAO,SAAA,CAAU,MAAA,EAAO,EAAG;AAGlC,MAAA,MAAM,IAAI,GAAA,CAAI,MAAA;AACd,MAAA,IAAI,IAAI,CAAA,EAAG;AAEX,MAAA,MAAM,WAAuC,EAAC;AAC9C,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,KAAK,UAAA,EAAY;AACpC,QAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,YAAY,CAAC,CAAA;AACtC,QAAA,IAAI,EAAA,GAAK,GAAG,EAAA,GAAK,CAAA;AACjB,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,EAAK,CAAA,EAAA,EAAK;AAC1B,UAAA,EAAA,IAAM,GAAA,CAAI,CAAC,CAAA,CAAE,CAAA;AACb,UAAA,EAAA,IAAM,GAAA,CAAI,CAAC,CAAA,CAAE,CAAA;AAAA,QACjB;AACA,QAAA,MAAM,MAAM,GAAA,GAAM,CAAA;AAClB,QAAA,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA,EAAG,EAAA,GAAK,KAAK,CAAA,EAAG,EAAA,GAAK,KAAK,CAAA;AAAA,MAC9C;AAGA,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACtC,QAAA,MAAM,EAAA,GAAA,CAAM,SAAS,CAAC,CAAA,CAAE,IAAI,QAAA,CAAS,CAAA,GAAI,CAAC,CAAA,CAAE,CAAA,IAAK,MAAA;AACjD,QAAA,MAAM,EAAA,GAAA,CAAM,SAAS,CAAC,CAAA,CAAE,IAAI,QAAA,CAAS,CAAA,GAAI,CAAC,CAAA,CAAE,CAAA,IAAK,MAAA;AACjD,QAAA,IAAI,OAAO,CAAA,EAAG;AACd,QAAA,SAAA,CAAU,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,EAAA,GAAK,EAAE,CAAC,CAAA;AAAA,MACpC;AAAA,IACJ;AAEA,IAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAG5B,IAAA,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,CAAC,CAAA;AAC9B,IAAA,MAAM,GAAA,GAAM,UAAU,MAAA,IAAU,CAAA;AAChC,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,MAAA,GAAS,CAAA,KAAM,IAClC,SAAA,CAAU,GAAG,CAAA,GAAA,CACZ,SAAA,CAAU,GAAA,GAAM,CAAC,CAAA,GAAI,SAAA,CAAU,GAAG,CAAA,IAAK,CAAA;AAC9C,IAAA,IAAI,SAAS,CAAA,EAAG;AACZ,MAAA,YAAA,CAAa,KAAK,MAAM,CAAA;AAAA,IAC5B;AAAA,EACJ;AAEA,EAAA,IAAI,YAAA,CAAa,MAAA,KAAW,CAAA,EAAG,OAAO,CAAA;AAKtC,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,MAAW,KAAK,YAAA,EAAc;AAC1B,IAAA,MAAA,IAAU,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,EACxB;AACA,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,aAAa,MAAM,CAAA;AAE3D,EAAA,IAAI,aAAA,IAAiB,GAAG,OAAO,MAAA;AAe/B,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAK,aAAa,CAAA;AACtC,EAAA,OAAO,KAAK,GAAA,CAAI,MAAA,EAAQ,KAAK,GAAA,CAAI,MAAA,EAAQ,EAAE,CAAC,CAAA;AAChD;AA0BO,SAAS,qBAAA,CACZ,gBAAA,EACA,WAAA,EACA,IAAA,EACA,YACA,OAAA,EACc;AACd,EAAA,MAAM;AAAA,IACF,SAAS,UAAA,GAAa,CAAA;AAAA,IACtB,aAAa,cAAA,GAAiB,GAAA;AAAA,IAC9B,gBAAgB,WAAA,GAAc;AAAA,GAClC,GAAI,OAAA;AAEJ,EAAA,MAAM,EAAE,CAAA,EAAG,WAAA,EAAa,GAAG,WAAA,EAAY,GAAI,mBAAmB,OAAO,CAAA;AAErE,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,iBAAA,EAAmB,KAAA,IAAS,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,iBAAA,EAAmB,MAAA,IAAU,CAAA;AAClD,EAAA,MAAM,GAAA,GAAM,QAAQ,QAAA,IAAY,CAAA;AAEhC,EAAA,MAAM,cAAA,GAAiB,CAAC,CAAA,KAA0B,CAAA,KAAM,aAAa,CAAA,KAAM,SAAA;AAC3E,EAAA,MAAM,aAAA,GAAgB,CAAC,EAAA,KACnB,WAAA,CAAY,gBAAgB,EAAE,CAAA,IAAK,gBAAA,CAAiB,EAAE,CAAA,EAAG,IAAA;AAG7D,EAAA,MAAM,SAAA,GAAY,gBAAA;AAAA,IACd,gBAAA;AAAA,IAAkB,WAAA;AAAA,IAAa,IAAA;AAAA,IAAM,UAAA;AAAA,IAAY;AAAA,GACrD;AACA,EAAA,MAAM,SAAA,GAAY,WAAW,OAAA,IAAW,CAAA;AACxC,EAAA,MAAM,SAAA,GAAY,WAAW,IAAA,IAAQ,CAAA;AAGrC,EAAA,MAAM,cAAc,IAAA,CAAK,GAAA;AAAA,IACrB,QAAQ,cAAA,IAAkB,EAAA;AAAA,IAAA,CACzB,UAAA,CAAW,KAAA,GAAQ,WAAA,GAAc,IAAA,IAAQ,SAAA,GAAY;AAAA,GAC1D;AACA,EAAA,MAAM,cAAc,IAAA,CAAK,GAAA;AAAA,IACrB,QAAQ,cAAA,IAAkB,EAAA;AAAA,IAAA,CACzB,UAAA,CAAW,MAAA,GAAS,WAAA,GAAc,IAAA,IAAQ,SAAA,GAAY;AAAA,GAC3D;AAGA,EAAA,MAAM,UAAA,GAAa,iBAAiB,KAAA,EAAO,KAAA;AAC3C,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,UAAA,EAAY;AACZ,IAAA,UAAA,GAAa,IAAI,IAAI,IAAA,CAAK,GAAA,CAAI,OAAK,CAAA,CAAE,UAAU,CAAC,CAAC,CAAA,CAAE,IAAA;AACnD,IAAA,IAAI,cAAA,CAAe,aAAA,CAAc,GAAG,CAAC,GAAG,SAAA,GAAY,GAAA;AAAA,SAAA,IAC3C,cAAA,CAAe,aAAA,CAAc,GAAG,CAAC,GAAG,SAAA,GAAY,GAAA;AAAA,EAC7D;AAEA,EAAA,MAAM,gBAAA,GAAoB,SAAA,KAAc,GAAA,IAAO,UAAA,GAAa,IAAK,UAAA,GAAa,CAAA;AAC9E,EAAA,MAAM,gBAAA,GAAoB,SAAA,KAAc,GAAA,IAAO,UAAA,GAAa,IAAK,UAAA,GAAa,CAAA;AAE9E,EAAA,MAAM,gBAAA,GAAmB,CAAA;AACzB,EAAA,MAAM,aAAA,GAAgB,gBAAA,GAAmB,CAAA,GACnC,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,IAAA,CAAK,gBAAA,GAAmB,cAAc,CAAA,EAAG,CAAA,GAAI,gBAAgB,CAAA,GAC3E,UAAA;AACN,EAAA,MAAM,aAAA,GAAgB,gBAAA,GAAmB,CAAA,GACnC,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,IAAA,CAAK,gBAAA,GAAmB,cAAc,CAAA,EAAG,CAAA,GAAI,gBAAgB,CAAA,GAC3E,UAAA;AAGN,EAAA,IAAI,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,WAAA,GAAc,aAAa,CAAA;AACvD,EAAA,IAAI,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,WAAA,GAAc,aAAa,CAAA;AAavD,EAAA,IAAI,SAAA,EAAW;AACX,IAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,UAAA,CAAW,KAAA,GAAQ,aAAa,CAAC,CAAA;AAC3E,IAAA,MAAM,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,UAAA,CAAW,MAAA,GAAS,aAAa,CAAC,CAAA;AAE5E,IAAA,IAAI,UAAA,GAAa,UAAA,IAAc,UAAA,GAAa,UAAA,EAAY;AACpD,MAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,UAAU,CAAA;AAC5C,MAAA,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,UAAU,CAAA;AAK5C,MAAA,MAAM,QAAA,GAAW,iBAAiB,MAAA,EAAQ,KAAA;AAC1C,MAAA,MAAM,QAAA,GAAW,iBAAiB,GAAA,EAAK,KAAA;AACvC,MAAA,MAAM,QAAA,GAAW,QAAA,GACX,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,QAAQ,CAAC,CAAC,CAAA,CAAE,IAAA,GAAO,CAAA;AAEjD,MAAA,IAAI,QAAA,GAAW,CAAA,IAAK,CAAC,QAAA,EAAU;AAC3B,QAAA,MAAM,WAAW,IAAA,CAAK,GAAA;AAAA,UAClB,QAAQ,cAAA,IAAkB,EAAA;AAAA,UAC1B,UAAA,GAAa;AAAA,SACjB;AACA,QAAA,MAAM,MAAA,GAAS,UAAA,CAAW,KAAA,GAAQ,WAAA,GAAc,IAAA;AAChD,QAAA,MAAM,MAAA,GAAS,UAAA,CAAW,MAAA,GAAS,WAAA,GAAc,IAAA;AACjD,QAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA;AAAA,UACpC,UAAU,QAAA,GAAW,GAAA;AAAA,SACxB,CAAA;AACD,QAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA;AAAA,UACpC,MAAA,IAAA,CAAW,OAAA,CAAQ,cAAA,IAAkB,EAAA,IAAM,GAAA;AAAA,SAC9C,CAAA;AACD,QAAA,MAAM,WAAW,cAAA,GAAiB,cAAA;AAClC,QAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,QAAQ,CAAA;AAClD,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,cAAA,GAAiB,cAAc,CAAA;AACzD,QAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,cAAA,GAAiB,OAAO,CAAA;AAElD,QAAA,SAAA,CAAU,OAAA,GAAU,OAAA;AACpB,QAAA,SAAA,CAAU,IAAA,GAAO,OAAA;AACjB,QAAA,SAAA,CAAU,eAAA,GAAkB,QAAA;AAAA,MAChC;AAAA,IACJ;AAAA,EACJ;AAKA,EAAA,MAAM,SAAA,GAAoC;AAAA,IACtC,CAAA,EAAG,UAAA;AAAA,IACH,CAAA,EAAG,UAAA;AAAA,IACH,MAAA,EAAQ,WAAW,eAAA,IAAmB,QAAA;AAAA,IACtC,GAAA,EAAK,WAAW,YAAA,IAAgB,QAAA;AAAA,IAChC,KAAA,EAAO;AAAA,GACX;AAEA,EAAA,OAAO,EAAE,WAAW,SAAA,EAAU;AAClC;AAwBO,SAAS,gBAAA,CACZ,gBAAA,EACA,WAAA,EACA,IAAA,EACA,YACA,OAAA,EAC6C;AAC7C,EAAA,MAAM,EAAE,CAAA,EAAG,GAAA,EAAK,GAAG,GAAA,EAAI,GAAI,mBAAmB,OAAO,CAAA;AACrD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,iBAAA,EAAmB,KAAA,IAAS,CAAA;AACjD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,iBAAA,EAAmB,MAAA,IAAU,CAAA;AAClD,EAAA,MAAM,GAAA,GAAM,QAAQ,QAAA,IAAY,CAAA;AAChC,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,CAAA;AACnC,EAAA,MAAM,WAAA,GAAc,QAAQ,WAAA,IAAe,GAAA;AAC3C,EAAA,MAAM,cAAA,GAAiB,QAAQ,cAAA,IAAkB,EAAA;AAEjD,EAAA,MAAM,cAAA,GAAiB,CAAC,CAAA,KAA0B,CAAA,KAAM,aAAa,CAAA,KAAM,SAAA;AAmB3E,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,KAAA,GAAQ,GAAA,GAAM,IAAA;AACtC,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,MAAA,GAAS,GAAA,GAAM,IAAA;AACvC,EAAA,MAAM,gBAAA,GAAmB,CAAA;AAGzB,EAAA,MAAM,UAAA,GAAa,iBAAiB,KAAA,EAAO,KAAA;AAC3C,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,UAAA,EAAY;AACZ,IAAA,UAAA,GAAa,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,MAAW,CAAA,CAAE,UAAU,CAAC,CAAC,CAAA,CAAE,IAAA;AAC1D,IAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,aAAA,EAAe,CAAA,IAAK,iBAAiB,CAAA,EAAG,IAAA;AAClE,IAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,aAAA,EAAe,CAAA,IAAK,iBAAiB,CAAA,EAAG,IAAA;AAClE,IAAA,IAAI,cAAA,CAAe,KAAK,CAAA,EAAG,SAAA,GAAY,GAAA;AAAA,SAAA,IAC9B,cAAA,CAAe,KAAK,CAAA,EAAG,SAAA,GAAY,GAAA;AAAA,EAChD;AAEA,EAAA,IAAI,eAAA,GAAkB,cAAA;AACtB,EAAA,IAAI,gBAAA,GAAmB,cAAA;AAGvB,EAAA,MAAM,uBAAA,GAA0B,EAAA;AAChC,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,GAAA,EAAK,GAAG,CAAA,EAAY;AACpC,IAAA,MAAM,EAAA,GAAK,iBAAiB,IAAI,CAAA;AAChC,IAAA,IAAI,CAAC,EAAA,EAAI,KAAA,IAAS,CAAC,GAAG,SAAA,EAAW;AACjC,IAAA,IAAI,EAAA,CAAG,SAAA,KAAc,KAAA,IAAS,EAAA,CAAG,cAAc,QAAA,EAAU;AACzD,IAAA,MAAM,IAAA,GAAO,KACR,GAAA,CAAI,CAAC,MAAW,CAAA,CAAE,EAAA,CAAG,KAAK,CAAC,CAAA,CAC3B,OAAO,CAAC,CAAA,KAAW,OAAO,CAAA,KAAM,QAAA,IAAY,IAAI,CAAA,IAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AACrE,IAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACrB,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,IAAI,GAAG,IAAI,CAAC,CAAA,GAAI,KAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAC,CAAA;AAC5E,IAAA,MAAM,MAAA,GAAS,KAAK,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA,EAAG,OAAO,CAAC,CAAA,GAAI,uBAAA;AACjD,IAAA,IAAI,SAAS,GAAA,EAAK,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,iBAAiB,MAAM,CAAA;AAAA,SAC/D,gBAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,gBAAA,EAAkB,MAAM,CAAA;AAAA,EAC7D;AAEA,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,GAAA,EAAK,GAAG,CAAA,EAAY;AACpC,IAAA,MAAM,EAAA,GAAK,iBAAiB,IAAI,CAAA;AAChC,IAAA,IAAI,CAAC,IAAI,KAAA,EAAO;AAEhB,IAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,aAAA,GAAgB,IAAI,KAAK,EAAA,CAAG,IAAA;AAC9D,IAAA,MAAM,QAAA,GAAW,WAAA,CAAY,SAAA,GAAY,IAAI,GAAG,MAAA,KAAW,IAAA;AAC3D,IAAA,IAAI,CAAC,cAAA,CAAe,aAAa,CAAA,IAAK,CAAC,QAAA,EAAU;AAEjD,IAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAW,CAAA,CAAE,EAAA,CAAG,KAAK,CAAC,CAAC,CAAA,CAAE,IAAA;AAC9D,IAAA,MAAM,cAAA,GAAkB,SAAA,KAAc,IAAA,IAAQ,UAAA,GAAa,IAAK,UAAA,GAAa,CAAA;AAC7E,IAAA,MAAM,MAAA,GAAS,IAAA,KAAS,GAAA,GAAM,IAAA,GAAO,IAAA;AAErC,IAAA,IAAI,eAAA;AACJ,IAAA,IAAI,iBAAiB,CAAA,EAAG;AAGpB,MAAA,MAAM,eAAe,IAAA,CAAK,GAAA;AAAA,QACtB,IAAA,CAAK,IAAA,CAAK,gBAAA,GAAmB,WAAW,CAAA;AAAA,QACxC,CAAA,GAAI;AAAA,OACR;AACA,MAAA,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,OAAA,GAAU,cAAA,EAAgB,YAAY,CAAA;AAAA,IACrE,CAAA,MAAO;AAEH,MAAA,eAAA,GAAkB,OAAA;AAAA,IACtB;AAEA,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,eAAA,GAAkB,YAAY,MAAM,CAAA;AACnE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,cAAA,EAAgB,aAAa,CAAA;AAErD,IAAA,IAAI,SAAS,GAAA,EAAK;AACd,MAAA,eAAA,GAAkB,MAAA;AAAA,IACtB,CAAA,MAAO;AACH,MAAA,gBAAA,GAAmB,MAAA;AAAA,IACvB;AAAA,EACJ;AAQA,EAAA,MAAM,WAAW,MAAM;AACnB,IAAA,MAAM,KAAK,gBAAA,CAAiB,CAAA;AAC5B,IAAA,IAAI,CAAC,EAAA,EAAI,KAAA,EAAO,OAAO,KAAA;AACvB,IAAA,MAAM,CAAA,GAAI,WAAA,CAAY,aAAA,EAAe,CAAA,IAAK,EAAA,CAAG,IAAA;AAC7C,IAAA,OAAO,CAAC,eAAe,CAAC,CAAA,IAAK,EAAE,WAAA,CAAY,SAAA,EAAW,GAAG,MAAA,KAAW,IAAA,CAAA;AAAA,EACxE,CAAA,GAAG;AACH,EAAA,MAAM,WAAW,MAAM;AACnB,IAAA,MAAM,KAAK,gBAAA,CAAiB,CAAA;AAC5B,IAAA,IAAI,CAAC,EAAA,EAAI,KAAA,EAAO,OAAO,KAAA;AACvB,IAAA,MAAM,CAAA,GAAI,WAAA,CAAY,aAAA,EAAe,CAAA,IAAK,EAAA,CAAG,IAAA;AAC7C,IAAA,OAAO,CAAC,eAAe,CAAC,CAAA,IAAK,EAAE,WAAA,CAAY,SAAA,EAAW,GAAG,MAAA,KAAW,IAAA,CAAA;AAAA,EACxE,CAAA,GAAG;AAEH,EAAA,IAAI,WAAW,OAAA,EAAS;AACpB,IAAA,MAAM,MAAM,gBAAA,CAAiB,CAAA;AAC7B,IAAA,MAAM,MAAM,gBAAA,CAAiB,CAAA;AAC7B,IAAA,IAAI,GAAA,EAAK,KAAA,IAAS,GAAA,EAAK,KAAA,EAAO;AAC1B,MAAA,MAAM,OAAA,GAAA,CAAW,WAAA,CAAY,aAAA,EAAe,CAAA,IAAK,IAAI,IAAA,MAAU,UAAA;AAC/D,MAAA,MAAM,OAAA,GAAA,CAAW,WAAA,CAAY,aAAA,EAAe,CAAA,IAAK,IAAI,IAAA,MAAU,UAAA;AAC/D,MAAA,MAAM,OAAO,OAAA,CAAQ,0BAAA;AACrB,MAAA,MAAM,SAAS,OAAO,IAAA,KAAS,QAAA,IAAY,CAAC,CAAC,IAAA,CAAK,eAAA;AAElD,MAAA,MAAM,OAAiB,EAAC;AACxB,MAAA,MAAM,OAAiB,EAAC;AACxB,MAAA,MAAM,QAAkB,EAAC;AACzB,MAAA,MAAM,UAAoB,EAAC;AAG3B,MAAA,MAAM,IAAA,GAAO,iBAAiB,MAAA,EAAQ,KAAA;AACtC,MAAA,MAAM,IAAA,GAAO,iBAAiB,GAAA,EAAK,KAAA;AACnC,MAAA,IAAI,IAAA,EAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA;AAC3B,MAAA,IAAI,IAAA,EAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA;AAC3B,MAAA,MAAM,EAAA,GAAK,iBAAiB,KAAA,EAAO,KAAA;AACnC,MAAA,MAAM,EAAA,GAAK,iBAAiB,MAAA,EAAQ,KAAA;AACpC,MAAA,IAAI,EAAA,EAAI,OAAA,CAAQ,IAAA,CAAK,EAAE,CAAA;AACvB,MAAA,IAAI,EAAA,IAAM,EAAA,KAAO,EAAA,EAAI,OAAA,CAAQ,KAAK,EAAE,CAAA;AAEpC,MAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACpB,QAAA,MAAM,EAAA,GAAK,GAAA,CAAI,GAAA,CAAI,KAAK,CAAA;AACxB,QAAA,MAAM,EAAA,GAAK,GAAA,CAAI,GAAA,CAAI,KAAK,CAAA;AACxB,QAAA,IAAI,EAAA,IAAM,IAAA,IAAQ,EAAA,IAAM,IAAA,EAAM;AAC9B,QAAA,MAAM,KAAK,OAAA,GAAU,CAAC,IAAI,IAAA,CAAK,EAAE,IAAI,CAAC,EAAA;AACtC,QAAA,MAAM,KAAK,OAAA,GAAU,CAAC,IAAI,IAAA,CAAK,EAAE,IAAI,CAAC,EAAA;AACtC,QAAA,IAAI,KAAA,CAAM,EAAE,CAAA,IAAK,KAAA,CAAM,EAAE,CAAA,EAAG;AAC5B,QAAA,IAAA,CAAK,KAAK,EAAE,CAAA;AACZ,QAAA,IAAA,CAAK,KAAK,EAAE,CAAA;AACZ,QAAA,KAAA,CAAM,KAAK,OAAA,CAAQ,MAAA,GAAS,CAAA,GACtB,OAAA,CAAQ,IAAI,CAAA,CAAA,KAAK,MAAA,CAAO,GAAA,CAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAA,CAAK,IAAM,IAClD,EAAE,CAAA;AAAA,MACZ;AAEA,MAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACjB,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAC7B,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAC7B,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAC7B,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAC7B,QAAA,MAAM,IAAA,GAAyB,CAAC,IAAA,EAAM,IAAI,CAAA;AAC1C,QAAA,MAAM,IAAA,GAAyB,CAAC,IAAA,EAAM,IAAI,CAAA;AAC1C,QAAA,IAAI,GAAA,CAAI,MAAM,IAAA,EAAM;AAChB,UAAA,IAAI,KAAK,CAAC,CAAA,GAAI,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AAC3B,UAAA,IAAI,KAAK,CAAC,CAAA,GAAI,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AAAA,QAC/B;AACA,QAAA,IAAI,GAAA,CAAI,MAAM,IAAA,EAAM;AAChB,UAAA,IAAI,KAAK,CAAC,CAAA,GAAI,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AAC3B,UAAA,IAAI,KAAK,CAAC,CAAA,GAAI,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA,GAAI,CAAA;AAAA,QAC/B;AAEA,QAAA,MAAM,KAAK,gBAAA,CAAiB,IAAA,EAAM,MAAM,IAAA,EAAM,IAAA,EAAM,OAAO,MAAM,CAAA;AAGjE,QAAA,IAAI,MAAM,CAAA,EAAG;AACT,UAAA,eAAA,GAAkB,IAAA,CAAK,GAAA;AAAA,YAAI,eAAA;AAAA,YACvB,KAAK,KAAA,CAAM,cAAA,GAAiB,KAAK,GAAA,CAAI,EAAA,EAAI,GAAG,CAAC;AAAA,WAAC;AAClD,UAAA,gBAAA,GAAmB,IAAA,CAAK,GAAA,CAAI,gBAAA,EAAkB,cAAc,CAAA;AAAA,QAChE,CAAA,MAAO;AACH,UAAA,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,eAAA,EAAiB,cAAc,CAAA;AAC1D,UAAA,gBAAA,GAAmB,IAAA,CAAK,GAAA;AAAA,YAAI,gBAAA;AAAA,YACxB,IAAA,CAAK,MAAM,cAAA,GAAiB,IAAA,CAAK,IAAI,CAAA,GAAI,EAAA,EAAI,GAAG,CAAC;AAAA,WAAC;AAAA,QAC1D;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ;AAGA,EAAA,MAAM,UAAA,GAAa,IAAA;AACnB,EAAA,MAAM,UAAA,GAAa,IAAA;AACnB,EAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA;AAAA,IACrC,cAAc,eAAA,GAAkB,GAAA;AAAA,GACnC,CAAA;AACD,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA;AAAA,IAClC,cAAc,gBAAA,GAAmB,GAAA;AAAA,GACpC,CAAA;AAGD,EAAA,MAAM,QAAA,GAAW,iBAAiB,MAAA,EAAQ,KAAA;AAC1C,EAAA,MAAM,QAAA,GAAW,iBAAiB,GAAA,EAAK,KAAA;AACvC,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,QAAA,EAAU,OAAO,MAAA;AAEnC,EAAA,MAAM,QAAA,GAAW,QAAA,GACX,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAW,CAAA,CAAE,QAAQ,CAAC,CAAC,EAAE,IAAA,GAAO,CAAA;AACxD,EAAA,MAAM,QAAA,GAAW,QAAA,GACX,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAW,CAAA,CAAE,QAAQ,CAAC,CAAC,EAAE,IAAA,GAAO,CAAA;AAExD,EAAA,IAAI,QAAA,KAAa,CAAA,IAAK,QAAA,KAAa,CAAA,EAAG,OAAO,MAAA;AAK7C,EAAA,MAAM,UAAA,GAAa,QAAQ,YAAA,IAAgB,IAAA,IAAQ,QAAQ,YAAA,IAAgB,CAAA,GACrE,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,KAAA,CAAM,OAAA,CAAQ,YAAY,CAAC,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,CAAC,CAAA,GAC7E,MAAA;AAEN,EAAA,IAAI,QAAA,GAAW,CAAA,IAAK,QAAA,KAAa,CAAA,EAAG;AAChC,IAAA,IAAI,cAAc,IAAA,EAAM;AACpB,MAAA,MAAMC,MAAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,QAAA,GAAW,UAAU,CAAA;AAC7C,MAAA,OAAO;AAAA,QACH,OAAA,EAAS,UAAA;AAAA,QACT,IAAA,EAAMA,MAAAA;AAAA,QACN,iBAAiB,UAAA,GAAaA,MAAAA;AAAA,QAC9B,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,YAAA,EAAcA,MAAK;AAAA,OAC9C;AAAA,IACJ;AAKA,IAAA,IAAI,YAAY,eAAA,EAAiB;AAC7B,MAAA,OAAO;AAAA,QACH,OAAA,EAAS,QAAA;AAAA,QACT,IAAA,EAAM,CAAA;AAAA,QACN,eAAA,EAAiB,QAAA;AAAA,QACjB,YAAA,EAAc;AAAA,OAClB;AAAA,IACJ;AAKA,IAAA,IAAI,KAAA,GAAQ,eAAA;AACZ,IAAA,IAAI,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,QAAA,GAAW,KAAK,CAAA;AAKtC,IAAA,OAAO,KAAA,GAAQ,CAAA,IAAM,QAAA,GAAW,KAAA,KAAW,CAAA,EAAG;AAC1C,MAAA,KAAA,EAAA;AACA,MAAA,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,QAAA,GAAW,KAAK,CAAA;AAAA,IACtC;AAEA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,YAAY,CAAA;AAC5C,IAAA,MAAM,WAAW,KAAA,GAAQ,OAAA;AAEzB,IAAA,OAAO;AAAA,MACH,OAAA,EAAS,KAAA;AAAA,MACT,IAAA,EAAM,OAAA;AAAA,MACN,eAAA,EAAiB,QAAA;AAAA,MACjB,YAAA,EAAc;AAAA,KAClB;AAAA,EACJ;AAGA,EAAA,OAAO;AAAA,IACH,OAAA,EAAS,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,QAAA,EAAU,eAAe,CAAC,CAAA;AAAA,IACxD,IAAA,EAAM,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,QAAA,EAAU,YAAY,CAAC,CAAA;AAAA,IAClD,eAAA,EAAiB,eAAA;AAAA,IACjB,YAAA,EAAc;AAAA,GAClB;AACJ;;;ACvpDO,SAAS,eACZ,gBAAA,EACA,WAAA,EACA,SAAA,EACA,IAAA,EACA,SACA,YAAA,EACc;AAId,EAAA,MAAM,aAAA,GAAgB,CAAC,EAAA,KACnB,WAAA,CAAY,gBAAgB,EAAE,CAAA,IAAK,gBAAA,CAAiB,EAAE,CAAA,EAAG,IAAA;AAE7D,EAAA,MAAM,cAAA,GAAiB,CAAC,EAAA,KAAmC;AACvD,IAAA,IAAI,iBAAiB,EAAE,CAAA,EAAG,OAAO,OAAO,gBAAA,CAAiB,EAAE,CAAA,CAAE,KAAA;AAC7D,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAEA,EAAA,MAAM,cAAA,GAAiB,CAAC,CAAA,KAA0B,CAAA,KAAM,aAAa,CAAA,KAAM,SAAA;AAI3E,EAAA,MAAM,aAAA,GAAwC;AAAA,IAC1C,CAAA,EAAG,CAAA;AAAA,IAAG,CAAA,EAAG,CAAA;AAAA,IAAG,MAAA,EAAQ,CAAA;AAAA,IAAG,GAAA,EAAK,CAAA;AAAA,IAAG,KAAA,EAAO;AAAA,GAC1C;AACA,EAAA,MAAM,cAAmC,EAAC;AAC1C,EAAA,MAAM,WAA2B,EAAC;AAClC,EAAA,IAAI,YAAA,GAAe,IAAA;AAGnB,EAAA,MAAM,UAAA,GAAa,iBAAiB,KAAA,EAAO,KAAA;AAC3C,EAAA,IAAI,UAAA,EAAY;AACZ,IAAA,aAAA,CAAc,KAAA,GAAQ,IAAI,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,OAAK,CAAA,CAAE,UAAU,CAAC,CAAC,CAAA,CAAE,IAAA;AAAA,EAChE;AAGA,EAAA,MAAM,eAAA,GAA2C;AAAA,IAC7C,IAAA;AAAA,IACA,gBAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACJ;AAEA,EAAA,MAAM,QAAA,GAAW,YAAY,gBAAA,IAAoB,uBAAA;AAEjD,EAAA,KAAA,MAAW,WAAW,CAAC,GAAA,EAAK,KAAK,QAAA,EAAU,KAAA,EAAO,OAAO,CAAA,EAAY;AACjE,IAAA,MAAM,SAAA,GAAY,eAAe,OAAO,CAAA;AACxC,IAAA,MAAM,IAAA,GAAO,cAAc,OAAO,CAAA;AAClC,IAAA,IAAI,CAAC,SAAA,EAAW;AAGhB,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,SAAA,CAAU,OAAO,CAAA,IAAK,QAAA;AAIhD,IAAA,IAAI,CAAC,cAAA,CAAe,IAAI,CAAA,EAAG;AACvB,MAAA,IAAI,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,KAAA,EAAO;AAC3C,QAAA,MAAMC,aAAAA,GAAe,CAAC,GAAG,IAAI,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,CAAC,CAAC,CAAC,CAAA;AACrE,QAAA,aAAA,CAAc,OAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAIA,aAAAA,CAAa,QAAQ,SAAS,CAAA;AAEhE,QAAA,IAAIA,aAAAA,CAAa,SAAS,SAAA,EAAW;AAEjC,UAAA,MAAM,MAAA,GAAS,CAAC,GAAGA,aAAY,EAAE,IAAA,EAAK;AACtC,UAAA,MAAM,YAAA,GAAe,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AAE9C,UAAA,MAAM,YAAA,GAAeA,aAAAA,CAAa,MAAA,GAAS,YAAA,CAAa,MAAA;AACxD,UAAA,QAAA,CAAS,IAAA,CAAK;AAAA,YACV,QAAA,EAAU,SAAA;AAAA,YACV,IAAA,EAAM,UAAA;AAAA,YACN,OAAA,EAAS,CAAA,EAAG,YAAY,CAAA,IAAA,EAAOA,aAAAA,CAAa,MAAM,CAAA,YAAA,EAAe,SAAS,CAAA,8BAAA,EAAiC,YAAA,CAAa,MAAM,CAAA,EAAA,CAAA;AAAA,YAC9H,OAAA;AAAA,YACA,KAAA,EAAO;AAAA,WACV,CAAA;AAED,UAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,YAAY,CAAA;AACpC,UAAA,YAAA,GAAe,YAAA,CAAa,OAAO,CAAA,GAAA,KAAO,OAAA,CAAQ,IAAI,GAAA,CAAI,SAAS,CAAC,CAAC,CAAA;AAAA,QACzE;AAAA,MACJ;AACA,MAAA;AAAA,IACJ;AAEA,IAAA,MAAM,YAAA,GAAe,CAAC,GAAG,IAAI,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,CAAC,CAAC,CAAC,CAAA;AACrE,IAAA,aAAA,CAAc,OAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,YAAA,CAAa,QAAQ,SAAS,CAAA;AAEhE,IAAA,IAAI,YAAA,CAAa,SAAS,SAAA,EAAW;AACjC,MAAA,MAAM,eAAe,QAAA,CAAS,OAAA,EAAS,SAAA,EAAW,YAAA,EAAc,WAAW,eAAe,CAAA;AAE1F,MAAA,MAAM,YAAA,GAAe,YAAA,CAAa,MAAA,GAAS,YAAA,CAAa,MAAA;AACxD,MAAA,MAAM,WAAA,GAAc,MAAM,YAAY,CAAA,cAAA,CAAA;AAEtC,MAAA,QAAA,CAAS,IAAA,CAAK;AAAA,QACV,QAAA,EAAU,SAAA;AAAA,QACV,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,CAAA,EAAG,YAAY,CAAA,IAAA,EAAO,YAAA,CAAa,MAAM,CAAA,YAAA,EAAe,SAAS,CAAA,8BAAA,EAAiC,YAAA,CAAa,MAAM,CAAA,gBAAA,CAAA;AAAA,QAC9H,OAAA;AAAA,QACA,KAAA,EAAO;AAAA,OACV,CAAA;AAED,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACb,QAAA,EAAU,SAAA;AAAA,QACV,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,CAAA,EAAG,YAAY,CAAA,IAAA,EAAO,YAAA,CAAa,MAAM,CAAA,YAAA,EAAe,SAAS,CAAA,8BAAA,EAAiC,YAAA,CAAa,MAAM,CAAA,gBAAA,CAAA;AAAA,QAC9H,OAAA;AAAA,QACA,KAAA,EAAO,SAAA;AAAA,QACP,UAAA,EAAY,YAAA;AAAA,QACZ,YAAA;AAAA,QACA;AAAA,OACH,CAAA;AAGD,MAAA,IAAI,YAAY,OAAA,EAAS;AACrB,QAAA,YAAA,GAAe,YAAA,CAAa,OAAO,CAAA,GAAA,KAAO,YAAA,CAAa,SAAS,GAAA,CAAI,SAAS,CAAC,CAAC,CAAA;AAAA,MACnF;AAAA,IACJ;AAAA,EACJ;AAEA,EAAA,OAAO,EAAE,YAAA,EAAc,aAAA,EAAe,WAAA,EAAa,QAAA,EAAS;AAChE;AAcA,IAAM,0BAA4C,CAC9C,OAAA,EAAS,SAAA,EAAW,YAAA,EAAc,WAAW,OAAA,KAC5C;AACD,EAAA,MAAM,EAAE,IAAA,EAAM,gBAAA,EAAkB,SAAA,EAAW,cAAa,GAAI,OAAA;AAG5D,EAAA,MAAM,QAAA,GAAW,UAAU,OAAO,CAAA;AAClC,EAAA,MAAM,SAAS,QAAA,EAAU,MAAA;AACzB,EAAA,MAAM,YAAY,QAAA,EAAU,SAAA;AAG5B,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,aAAA;AACJ,EAAA,IAAI,YAAA,GAAe,KAAA;AAEnB,EAAA,IAAI,MAAA,EAAQ;AAER,IAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,IAAO,WAAW,OAAA,EAAS;AACxD,MAAA,MAAM,MAAA,GAAS,iBAAiB,MAAM,CAAA;AACtC,MAAA,SAAA,GAAY,MAAA,EAAQ,KAAA;AACpB,MAAA,aAAA,GAAgB,MAAA,EAAQ,IAAA;AACxB,MAAA,YAAA,GAAe,SAAA,KAAc,YAAA,IAAiB,SAAA,KAAc,WAAA,IAAe,MAAA,KAAW,OAAA;AAAA,IAC1F,CAAA,MAAO;AAEH,MAAA,IAAI;AACA,QAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AACpC,QAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC3B,UAAA,MAAM,aAAA,GAAiB,SAAA,KAAc,YAAA,GAAgB,UAAA,CAAW,SAAQ,GAAI,UAAA;AAC5E,UAAA,OAAO,aAAA,CAAc,MAAA,CAAO,CAAC,CAAA,KAAW,YAAA,CAAa,QAAA,CAAS,CAAC,CAAC,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AAAA,QACxF;AAAA,MACJ,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA,YAAA,GAAe,SAAA,KAAc,YAAA;AAAA,IACjC;AAAA,EACJ;AAGA,EAAA,IAAI,SAAA,IAAa,kBAAkB,cAAA,EAAgB;AAC/C,IAAA,IAAI,cAAc,IAAA,CAAK,GAAA;AACvB,IAAA,IAAI,YAAA,GAAe,CAAA,QAAA;AACnB,IAAA,IAAI,aAAa,GAAA,CAAI,KAAK,KAAK,SAAA,KAAc,gBAAA,CAAiB,OAAO,KAAA,EAAO;AACxE,MAAA,WAAA,GAAc,CAAC,CAAA,EAAW,CAAA,KAAc,CAAA,GAAI,CAAA;AAC5C,MAAA,YAAA,GAAe,CAAA;AAAA,IACnB;AAEA,IAAA,MAAM,eAAA,uBAAsB,GAAA,EAAiB;AAC7C,IAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACpB,MAAA,MAAM,UAAA,GAAa,IAAI,SAAS,CAAA;AAChC,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,GAAA,CAAI,SAAS,KAAK,CAAC,CAAA;AAC5C,MAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,UAAU,CAAA,EAAG;AACjC,QAAA,eAAA,CAAgB,GAAA,CAAI,YAAY,WAAA,CAAY,eAAA,CAAgB,IAAI,UAAU,CAAA,EAAI,SAAS,CAAC,CAAA;AAAA,MAC5F,CAAA,MAAO;AACH,QAAA,eAAA,CAAgB,GAAA,CAAI,UAAA,EAAY,WAAA,CAAY,YAAA,EAAc,SAAS,CAAC,CAAA;AAAA,MACxE;AAAA,IACJ;AAEA,IAAA,OAAO,MAAM,IAAA,CAAK,eAAA,CAAgB,OAAA,EAAS,EACtC,GAAA,CAAI,CAAC,CAAC,KAAA,EAAO,GAAG,CAAA,MAAO,EAAE,OAAO,GAAA,EAAI,CAAE,EACtC,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,eAAe,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,GAAA,GAAM,EAAE,GAAA,GAAM,CAAA,CAAE,GAAG,CAAA,CAC3D,MAAM,CAAA,EAAG,SAAS,EAClB,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,KAAK,CAAA;AAAA,EACzB;AAEA,EAAA,MAAM,cAAA,GAAiB,gBAAA,CAAiB,OAAO,CAAA,EAAG,gBAAA;AAClD,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,SAAA,IAAa,gBAAgB,MAAA,EAAQ;AACjD,IAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,YAAY,CAAA;AACpC,IAAA,MAAM,UAAU,cAAA,CAAe,MAAA,CAAO,WAAS,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAC,CAAA;AACjE,IAAA,MAAM,eAAA,GAAkB,IAAI,GAAA,CAAI,OAAO,CAAA;AACvC,IAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,YAAA,CAAa,MAAA,CAAO,CAAA,KAAA,KAAS,CAAC,eAAA,CAAgB,GAAA,CAAI,KAAK,CAAC,CAAC,CAAA;AACzE,IAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AAAA,EACrC;AAGA,EAAA,MAAM,iBAAA,GAAoB,iBAAiB,IAAA,CAAK,GAAA,CAAI,OAAK,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA;AACtE,EAAA,IAAI,iBAAA,KAAsB,cAAA,IAAkB,OAAA,KAAY,OAAA,EAAS;AAC7D,IAAA,OAAO,CAAC,GAAG,YAAY,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,MAAA,CAAO,CAAC,IAAI,MAAA,CAAO,CAAC,CAAC,CAAA,CACxD,KAAA,CAAM,GAAG,SAAS,CAAA;AAAA,EAC3B;AAGA,EAAA,IAAI,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,KAAA,EAAO;AAC3C,IAAA,OAAO,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AAAA,EAC1C;AAGA,EAAA,IAAI,cAAc,YAAA,EAAc;AAC5B,IAAA,OAAO,CAAC,GAAG,YAAY,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,MAAA,CAAO,CAAC,CAAA,CAAE,aAAA,CAAc,OAAO,CAAC,CAAA,EAAG,MAAA,EAAW,EAAE,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AAAA,EAChI;AACA,EAAA,IAAI,cAAc,WAAA,EAAa;AAC3B,IAAA,OAAO,CAAC,GAAG,YAAY,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,MAAA,CAAO,CAAC,CAAA,CAAE,aAAA,CAAc,OAAO,CAAC,CAAA,EAAG,MAAA,EAAW,EAAE,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AAAA,EAChI;AAGA,EAAA,OAAO,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AAC1C,CAAA;;;AC7PO,IAAM,cAAA,GAAmD;AAAA,EAC5D,WAAA,EAAa,EAAE,QAAA,EAAU,iBAAA,EAAmB,YAAY,cAAA,EAAe;AAAA,EACvE,mBAAA,EAAqB,EAAE,QAAA,EAAU,iBAAA,EAAmB,YAAY,cAAA,EAAe;AAAA,EAC/E,mBAAA,EAAqB,EAAE,QAAA,EAAU,eAAA,EAAiB,YAAY,YAAA,EAAa;AAAA,EAC3E,eAAA,EAAiB,EAAE,QAAA,EAAU,YAAA,EAAc,YAAY,YAAA,EAAa;AAAA,EACpE,WAAA,EAAa,EAAE,QAAA,EAAU,iBAAA,EAAkB;AAAA,EAC3C,YAAA,EAAc,EAAE,QAAA,EAAU,MAAA,EAAO;AAAA,EACjC,YAAA,EAAc,EAAE,QAAA,EAAU,MAAA,EAAQ,YAAY,MAAA,EAAU;AAAA,EACxD,cAAA,EAAgB,EAAE,QAAA,EAAU,WAAA,EAAa,IAAI,IAAA,EAAK;AAAA,EAClD,wBAAA,EAA0B,EAAE,QAAA,EAAU,gBAAA,EAAkB,IAAI,IAAA,EAAK;AAAA,EACjE,WAAA,EAAa,EAAE,QAAA,EAAU,KAAA,EAAO,QAAQ,IAAA,EAAK;AAAA,EAC7C,aAAA,EAAe,EAAE,QAAA,EAAU,UAAA,EAAY,QAAQ,IAAA,EAAK;AAAA,EACpD,SAAA,EAAW,EAAE,QAAA,EAAU,YAAA,EAAa;AAAA,EACpC,mBAAA,EAAqB,EAAE,QAAA,EAAU,WAAA,EAAY;AAAA,EAC7C,iBAAA,EAAmB,EAAE,QAAA,EAAU,WAAA,EAAY;AAAA,EAC3C,aAAA,EAAe,EAAE,QAAA,EAAU,cAAA,EAAe;AAAA,EAC1C,cAAA,EAAgB,EAAE,QAAA,EAAU,QAAA,EAAU,QAAQ,IAAA,EAAK;AAAA,EACnD,SAAA,EAAW,EAAE,QAAA,EAAU,SAAA,EAAW,QAAQ,IAAA,EAAK;AAAA,EAC/C,gBAAA,EAAkB,EAAE,QAAA,EAAU,UAAA,EAAY,QAAQ,IAAA;AACtD;AAGO,SAAS,iBAAiB,cAAA,EAAiC;AAC9D,EAAA,OAAO,cAAA,IAAkB,cAAA;AAC7B;AASO,SAAS,kBAAkB,GAAA,EAAiD;AAC/E,EAAA,IAAI,CAAC,KAAK,OAAO,MAAA;AACjB,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,IAAU,EAAA;AAC7B,EAAA,MAAM,MAAA,GAAS,IAAI,MAAA,IAAU,EAAA;AAC7B,EAAA,MAAM,GAAA,GAAM,IAAI,OAAA,IAAW,EAAA;AAG3B,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,GAAA,CAAI,QAAA,CAAS,GAAG,CAAA,EAAG;AACrC,IAAA,MAAMC,SAAAA,GAAW,oBAAoB,GAAG,CAAA;AACxC,IAAA,OAAOA,YAAW,CAAA,GAAI,CAAA,EAAA,EAAK,IAAI,MAAA,CAAOA,SAAQ,CAAC,CAAA,CAAA,CAAA,GAAM,IAAA;AAAA,EACzD;AAGA,EAAA,MAAM,QAAA,GAAW,oBAAoB,GAAG,CAAA;AACxC,EAAA,IAAI,IAAA,GAAO,WAAW,CAAA,GAAI,CAAA,MAAA,EAAS,IAAI,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAA,GAAK,OAAA;AAC5D,EAAA,IAAI,GAAA,CAAI,YAAY,IAAA,GAAO,WAAA;AAE3B,EAAA,MAAM,GAAA,GAAM,MAAA,GAAS,aAAA,CAAc,MAAM,CAAA,GAAI,EAAA;AAC7C,EAAA,MAAM,GAAA,GAAM,MAAA,GAAS,aAAA,CAAc,MAAM,CAAA,GAAI,EAAA;AAC7C,EAAA,IAAI,CAAC,OAAO,CAAC,GAAA,IAAO,CAAC,GAAA,CAAI,UAAA,IAAc,QAAA,KAAa,CAAA,EAAG,OAAO,SAAA;AAC9D,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,EAAG,IAAI,GAAG,GAAG,CAAA,CAAA;AAC9B;AAGA,SAAS,oBAAoB,GAAA,EAAqB;AAC9C,EAAA,MAAM,CAAA,GAAI,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA;AAC7B,EAAA,OAAO,CAAA,GAAI,MAAA,CAAO,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,CAAA;AAC9B;AAGA,SAAS,cAAc,CAAA,EAAmB;AAEtC,EAAA,IAAI,CAAA,KAAM,OAAO,CAAA,KAAM,QAAA,IAAO,MAAM,MAAA,IAAO,CAAA,KAAM,QAAK,OAAO,CAAA;AAC7D,EAAA,OAAO,IAAI,CAAC,CAAA,CAAA,CAAA;AAChB;;;ACzFO,IAAM,iBAAA,GAAsC;AAAA,EAC/C,KAAA,EAAO,YAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,MAAA,EAAO;AAAA,EAChC,QAAA,EAAU,CAAC,EAAE,MAAA,OAAa,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA,GACpC,+DAAA,GACA;AACV,CAAA;;;ACPO,IAAM,gBAAA,GAAqC;AAAA,EAC9C,KAAA,EAAO,WAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,iBAAA,EAAmB,YAAY,cAAA,EAAe;AAAA,EACvE,QAAA,EAAU,CAAC,EAAE,MAAA,EAAO,KAAM,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA,IAAkB,MAAA,CAAO,GAAG,CAAA,KAAM,iBACtE,qEAAA,GACA;AACV,CAAA;AAEO,IAAM,uBAAA,GAA4C;AAAA,EACrD,KAAA,EAAO,mBAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,iBAAA,EAAmB,YAAY,cAAA,EAAe;AAAA,EACvE,UAAU,CAAC,OAAA,KAAY,gBAAA,CAAiB,QAAA,GAAW,OAAO,CAAA,KAClD,OAAA,CAAQ,MAAA,CAAO,OAAO,MAAM,cAAA,IAAkB,OAAA,CAAQ,OAAO,OAAO,CAAA,KAAM,aACxE,0EAAA,GACA,MAAA;AACd,CAAA;AAEO,IAAM,uBAAA,GAA4C;AAAA,EACrD,KAAA,EAAO,mBAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,eAAA,EAAiB,YAAY,YAAA,EAAa;AAAA,EACnE,UAAU,CAAC,OAAA,KAAY,gBAAA,CAAiB,QAAA,GAAW,OAAO,CAAA,KAClD,OAAA,CAAQ,MAAA,CAAO,OAAO,MAAM,cAAA,IAAkB,OAAA,CAAQ,OAAO,OAAO,CAAA,KAAM,aACxE,uEAAA,GACA,MAAA;AACd,CAAA;;;AC1BO,IAAM,eAAA,GAAoC;AAAA,EAC7C,KAAA,EAAO,SAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,YAAA,EAAa;AAAA,EACtC,UAAU,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AACtC,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAG,KAAK,MAAA,CAAO,GAAG,MAAM,UAAA,EAAY;AAC7C,MAAA,OAAO,yEAAA;AAAA,IACX;AACA,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAG,KAAK,MAAA,CAAO,GAAG,MAAM,cAAA,EAAgB;AACjD,MAAA,OAAO,0EAAA;AAAA,IACX;AACA,IAAA,IAAI,OAAA,CAAQ,OAAO,CAAA,EAAG;AAClB,MAAA,OAAO,wEAAA;AAAA,IACX;AACA,IAAA,IAAI,OAAA,CAAQ,QAAQ,CAAA,IAAK,OAAA,CAAQ,KAAK,CAAA,EAAG;AACrC,MAAA,OAAO,qEAAA;AAAA,IACX;AACA,IAAA,IAAI,KAAA,CAAM,UAAA,CAAW,eAAA,EAAiB,aAAA,KAAkB,QAAA,EAAU;AAC9D,MAAA,OAAO,yGAAA;AAAA,IACX;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,OAAO,KAAA,EAAO,SAAA,EAAW,SAAQ,KAAM;AACnD,IAAA,MAAM,aAAA,GAAgB,QAAQ,GAAG,CAAA;AACjC,IAAA,MAAM,UAAA,GAAa,QAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,OAAO,KAAA,CAAM,MAAA,CAAO,CAAC,GAAA,KAAQ,IAAI,aAAa,CAAA,IAAK,IAAA,IAAQ,MAAA,CAAO,SAAS,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAC,CAAA;AACzG,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,MAAM,UAAA,GAAa,MAAM,UAAA,CAAW,eAAA;AAEpC,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,YAAA;AAAA,MACX,KAAA,EAAO,CAAA,EAAG,UAAU,CAAA,IAAA,EAAO,aAAa,CAAA,CAAA;AAAA,MACxC,QAAA,EAAU,SAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACF,CAAC,eAAe,UAAU,CAAA;AAAA,QAC1B,GAAG,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,MAAA,CAAO,GAAA,CAAI,aAAa,CAAC,GAAG,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAC;AAAA,OAC9E;AAAA,MACA,YAAA,EAAc,EAAE,KAAA,EAAO,aAAA,EAAc;AAAA,MACrC,SAAA,EAAW;AAAA,QACP,KAAA,EAAO,UAAA;AAAA,QACP,YAAA,EAAc,iBAAA,CAAkB,SAAA,CAAU,CAAA,EAAG,MAAM;AAAA,OACvD;AAAA,MACA,MAAA,EAAQ,EAAE,OAAA,EAAS,KAAA,EAAM;AAAA,MACzB,iBAAA,EAAmB;AAAA,QACf,mBAAA,EAAqB,WAAA;AAAA,QACrB,eAAA,EAAiB,KAAA;AAAA,QACjB,YAAA,EAAc,KAAA;AAAA,QACd,cAAA,EAAgB,KAAA;AAAA,QAChB,iBAAA,EAAmB,YAAY,YAAA,KAAiB;AAAA,OACpD;AAAA,MACA,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,MAAA,EAAQ,EAAE,SAAA,EAAW,SAAA,EAAW,eAAe,UAAA,EAAY,eAAA,EAAiB,KAAK,MAAA;AAAO,KAC5F;AAAA,EACJ;AACJ,CAAA;;;AC1DA,IAAM,cAAA,GAAiB,CAAC,MAAA,EAAQ,MAAA,EAAQ,OAAO,OAAO,CAAA;AACtD,IAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,IAAI,EAAE,CAAA;AACzC,IAAM,gBAAA,GAAmB,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAExC,SAAS,gBAAgB,KAAA,EAAwB;AAC7C,EAAA,OAAA,CAAQ,IAAI,IAAA,CAAK,KAA+B,CAAA,CAAE,OAAA,KAAY,WAAA,IAAe,gBAAA;AACjF;AAEA,SAAS,SAAS,IAAA,EAAsB;AACpC,EAAA,MAAM,QAAQ,IAAA,GAAO,CAAA;AACrB,EAAA,MAAM,QAAQ,EAAA,IAAM,IAAA,CAAK,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA;AAChD,EAAA,MAAM,WAAW,KAAA,GAAQ,KAAA;AACzB,EAAA,OAAA,CAAQ,QAAA,IAAY,IAAI,CAAA,GAAI,QAAA,IAAY,IAAI,CAAA,GAAI,QAAA,IAAY,CAAA,GAAI,CAAA,GAAI,EAAA,IAAM,KAAA;AAC9E;AAEO,IAAM,mBAAA,GAAwC;AAAA,EACjD,KAAA,EAAO,mBAAA;AAAA,EACP,UAAU,CAAC,GAAA,EAAK,MAAA,EAAQ,MAAA,EAAQ,OAAO,OAAO,CAAA;AAAA,EAC9C,WAAA,EAAa,EAAE,QAAA,EAAU,WAAA,EAAY;AAAA,EACrC,UAAU,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AACtC,IAAA,MAAM,MAAA,GAAS,QAAQ,GAAG,CAAA;AAC1B,IAAA,IAAI,CAAC,MAAA,IAAU,CAAC,CAAC,UAAA,EAAY,SAAS,CAAA,CAAE,QAAA,CAAS,MAAA,CAAO,GAAG,CAAA,IAAK,EAAE,CAAA,EAAG;AACjE,MAAA,OAAO,uEAAA;AAAA,IACX;AACA,IAAA,KAAA,MAAW,WAAW,cAAA,EAAgB;AAClC,MAAA,IAAI,CAAC,OAAA,CAAQ,OAAO,KAAK,MAAA,CAAO,OAAO,MAAM,cAAA,EAAgB;AACzD,QAAA,OAAO,2BAA2B,OAAO,CAAA,qCAAA,CAAA;AAAA,MAC7C;AAAA,IACJ;AACA,IAAA,IAAI,OAAA,CAAQ,OAAO,CAAA,IAAK,OAAA,CAAQ,OAAO,CAAA,IAAK,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAC3D,MAAA,OAAO,kFAAA;AAAA,IACX;AACA,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACpB,MAAA,OAAO,+DAAA;AAAA,IACX;AAEA,IAAA,IAAI,eAAe,MAAA,CAAO,iBAAA;AAC1B,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,GAAG,CAAA,IAAK,KAAA,CAAM,SAAQ,EAAG;AACxC,MAAA,MAAM,OAAO,IAAI,IAAA,CAAK,IAAI,MAAM,CAAC,EAAE,OAAA,EAAQ;AAC3C,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,EAAG;AACxB,QAAA,OAAO,CAAA,6BAAA,EAAgC,QAAQ,CAAC,CAAA,+BAAA,CAAA;AAAA,MACpD;AACA,MAAA,IAAI,QAAQ,YAAA,EAAc;AACtB,QAAA,OAAO,oGAAA;AAAA,MACX;AACA,MAAA,YAAA,GAAe,IAAA;AAEf,MAAA,MAAM,SAAA,GAAY,eAAe,GAAA,CAAI,CAAC,YAAY,GAAA,CAAI,OAAA,CAAQ,OAAO,CAAE,CAAC,CAAA;AACxE,MAAA,MAAM,CAAC,MAAM,IAAA,EAAM,GAAA,EAAK,KAAK,CAAA,GAAI,SAAA,CAAU,IAAI,MAAM,CAAA;AACrD,MAAA,IAAI,UAAU,IAAA,CAAK,CAAC,UAAU,KAAA,IAAS,IAAA,IAAQ,UAAU,EAAE,CAAA,IAAK,CAAC,CAAC,IAAA,EAAM,MAAM,GAAA,EAAK,KAAK,EAAE,KAAA,CAAM,MAAA,CAAO,QAAQ,CAAA,EAAG;AAC9G,QAAA,OAAO,CAAA,yDAAA,EAA4D,QAAQ,CAAC,CAAA,+BAAA,CAAA;AAAA,MAChF;AACA,MAAA,IAAI,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,GAAA,EAAK,KAAK,CAAA,IAAK,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,IAAA,EAAM,KAAK,CAAA,EAAG;AACxE,QAAA,OAAO,CAAA,qCAAA,EAAwC,QAAQ,CAAC,CAAA,oDAAA,CAAA;AAAA,MAC5D;AAAA,IACJ;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,OAAO,KAAA,EAAO,SAAA,EAAW,SAAQ,KAAM;AACnD,IAAA,MAAM,MAAA,GAAS,QAAQ,GAAG,CAAA;AAC1B,IAAA,MAAM,SAAS,cAAA,CAAe,GAAA,CAAI,CAAC,OAAA,KAAY,OAAA,CAAQ,OAAO,CAAE,CAAA;AAChE,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,IAAA,CAAK,OAAO,IAAA,CAAK,KAAA,GAAQ,EAAA,IAAM,EAAE,CAAC,CAAA;AACnE,IAAA,MAAM,gBAAA,GAAmB,MAAM,MAAA,GAAS,WAAA,GAAc,KAAK,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,WAAW,CAAA,GAAI,MAAA;AAC9F,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAA,CAAI,MAAA,CAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AACtD,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAA,CAAI,MAAA,CAAO,CAAC,CAAC,CAAC,CAAC,CAAA;AACvD,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,IAAI,CAAA;AAChC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,KAAK,CAAA;AACjC,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,IAAA,CAAK,GAAA,CAAI,OAAA,GAAU,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,GAAI,GAAA,EAAK,CAAC,CAAC,CAAA;AAClF,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,SAAS,CAAA,GAAI,SAAA;AACvD,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,IAAA,CAAK,OAAA,GAAU,SAAS,CAAA,GAAI,SAAA;AAEtD,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,WAAA;AAAA,MACX,OAAO,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,OAAO,MAAM,CAAA,CAAA;AAAA,MAChC,QAAA,EAAU,SAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACF,CAAC,MAAA,EAAQ,GAAG,MAAM,CAAA;AAAA,QAClB,GAAG,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ;AAAA,UAClB,eAAA,CAAgB,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,UAC3B,GAAG,OAAO,GAAA,CAAI,CAAC,UAAU,MAAA,CAAO,GAAA,CAAI,KAAK,CAAC,CAAC;AAAA,SAC9C;AAAA,OACL;AAAA,MACA,cAAc,EAAE,KAAA,EAAO,MAAA,EAAQ,YAAA,EAAc,cAAc,gBAAA,EAAiB;AAAA,MAC5E,SAAA,EAAW;AAAA,QACP,KAAA,EAAO,OAAA;AAAA,QACP,YAAA,EAAc,iBAAA,CAAkB,SAAA,CAAU,KAAA,EAAO,MAAM,CAAA;AAAA,QACvD,YAAA;AAAA,QACA,YAAA,EAAc,YAAA,KAAiB,OAAA,GAAU,YAAA,GAAe,SAAA,GAAY,YAAA;AAAA,QACpE;AAAA,OACJ;AAAA,MACA,MAAA,EAAQ,EAAE,OAAA,EAAS,KAAA,EAAM;AAAA,MACzB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,QAAQ,EAAE,SAAA,EAAW,mBAAA,EAAqB,MAAA,EAAQ,aAAa,MAAA;AAAO,KAC1E;AAAA,EACJ;AACJ,CAAA;;;ACpGO,IAAM,mBAAA,GAAwC;AAAA,EACjD,KAAA,EAAO,cAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,MAAM,CAAA;AAAA,EACtB,WAAA,EAAa,EAAE,QAAA,EAAU,QAAA,EAAU,QAAQ,IAAA,EAAK;AAAA,EAChD,UAAU,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AACtC,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAG,KAAK,MAAA,CAAO,GAAG,MAAM,cAAA,EAAgB;AACjD,MAAA,OAAO,sEAAA;AAAA,IACX;AACA,IAAA,IAAI,MAAA,CAAO,MAAM,CAAA,KAAM,cAAA,EAAgB;AACnC,MAAA,OAAO,oEAAA;AAAA,IACX;AACA,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,CAAA;AACjC,IAAA,IAAI,MAAM,IAAA,CAAK,CAAC,QAAQ,MAAA,CAAO,QAAA,CAAS,OAAO,GAAA,CAAI,UAAU,CAAC,CAAC,KAAK,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA,GAAI,CAAC,CAAA,EAAG;AAC9F,MAAA,OAAO,8DAAA;AAAA,IACX;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,OAAO,KAAA,EAAO,SAAA,EAAW,SAAQ,KAAM;AACnD,IAAA,MAAM,UAAA,GAAa,QAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,CAAA;AACjC,IAAA,MAAM,WAAA,uBAAkB,GAAA,EAAoB;AAC5C,IAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACrB,MAAA,MAAM,KAAA,GAAQ,IAAI,UAAU,CAAA;AAC5B,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA;AACpC,MAAA,IAAI,SAAS,IAAA,IAAQ,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC9C,MAAA,MAAM,KAAA,GAAQ,OAAO,KAAK,CAAA;AAC1B,MAAA,WAAA,CAAY,IAAI,KAAA,EAAA,CAAQ,WAAA,CAAY,IAAI,KAAK,CAAA,IAAK,KAAK,KAAK,CAAA;AAAA,IAChE;AAEA,IAAA,MAAM,IAAA,GAAO,CAAC,GAAG,WAAA,CAAY,SAAS,CAAA;AACtC,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,UAAA,CAAW,eAAA,EAAiB,IAAA,IAAQ,YAAA;AACvD,IAAA,IAAI,IAAA,KAAS,YAAA,EAAc,IAAA,CAAK,IAAA,CAAK,CAAC,IAAA,EAAM,KAAA,KAAU,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAC,CAAA;AACxE,IAAA,IAAI,IAAA,KAAS,WAAA,EAAa,IAAA,CAAK,IAAA,CAAK,CAAC,IAAA,EAAM,KAAA,KAAU,IAAA,CAAK,CAAC,CAAA,GAAI,KAAA,CAAM,CAAC,CAAC,CAAA;AAEvE,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,QAAA;AAAA,MACX,KAAA,EAAO,CAAA,EAAG,UAAU,CAAA,IAAA,EAAO,UAAU,CAAA,CAAA;AAAA,MACrC,QAAA,EAAU,SAAA;AAAA,MACV,MAAM,CAAC,CAAC,YAAY,UAAU,CAAA,EAAG,GAAG,IAAI,CAAA;AAAA,MACxC,MAAA,EAAQ,EAAE,OAAA,EAAS,KAAA,EAAM;AAAA,MACzB,UAAA,EAAY;AAAA,QACR,OAAA,EAAS,IAAA;AAAA,QACT,YAAA,EAAc,iBAAA,CAAkB,SAAA,CAAU,IAAA,EAAM,MAAM,CAAA;AAAA,QACtD,SAAA,EAAW,SAAA;AAAA,QACX,QAAA,EAAU;AAAA,OACd;AAAA,MACA,aAAA,EAAe,CAAC,EAAE,KAAA,EAAO,WAAW,CAAA;AAAA,MACpC,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,MAAA,EAAQ;AAAA,QACJ,SAAA,EAAW,cAAA;AAAA,QACX,UAAA;AAAA,QACA,UAAA;AAAA,QACA,IAAA;AAAA,QACA,iBAAA,EAAmB,iBAAA,CAAkB,SAAA,CAAU,IAAA,EAAM,MAAM;AAAA;AAC/D,KACJ;AAAA,EACJ;AACJ,CAAA;;;AC/DA,SAAS,WAAA,CAAY,OAAA,EAAiB,OAAA,EAAiB,OAAA,EAAyB;AAC5E,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,OAAA,EAAS,OAAA,GAAU,OAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAA;AAC7E,EAAA,MAAM,QAAQ,EAAA,IAAM,IAAA,CAAK,MAAM,IAAA,CAAK,KAAA,CAAM,GAAG,CAAC,CAAA;AAC9C,EAAA,MAAM,QAAQ,GAAA,GAAM,KAAA;AACpB,EAAA,MAAM,MAAA,GAAS,SAAS,CAAA,GAAI,EAAA,GAAK,SAAS,CAAA,GAAI,CAAA,GAAI,KAAA,IAAS,CAAA,GAAI,CAAA,GAAI,CAAA;AACnE,EAAA,OAAO,MAAA,GAAS,KAAA;AACpB;AAEO,IAAM,iBAAA,GAAsC;AAAA,EAC/C,KAAA,EAAO,WAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,OAAO,CAAA;AAAA,EACvB,WAAA,EAAa,EAAE,QAAA,EAAU,iBAAA,EAAkB;AAAA,EAC3C,QAAA,EAAU,CAAC,EAAE,OAAA,EAAS,QAAO,KAAM;AAC/B,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAG,CAAA,GAAI,GAAA,GAAM,GAAA;AAC1C,IAAA,OAAO,CAAC,QAAQ,YAAY,CAAA,IAAK,OAAO,YAAY,CAAA,KAAM,iBACpD,kEAAA,GACA,MAAA;AAAA,EACV,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,KAAA,EAAO,KAAA,EAAO,SAAQ,KAAM;AACxC,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,GAAG,CAAA,IAAK,QAAQ,GAAG,CAAA;AAC9C,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAA,CAAE,MAAA,CAAO,OAAO,QAAQ,CAAA;AACjF,IAAA,IAAI,OAAO,MAAA,KAAW,CAAA,EAAG,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAE1F,IAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,KAAA,CAAM,UAAA,CAAW,iBAAiB,QAAQ,CAAA;AACvE,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,QAAA,CAAS,aAAa,KAAK,aAAA,GAAgB,CAAA,GAC5D,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,KAAA,CAAM,aAAa,CAAC,CAAA,GACrC,EAAA;AACN,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA;AAClC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA;AAClC,IAAA,MAAM,WAAW,OAAA,GAAU,OAAA,GAAU,YAAY,OAAA,EAAS,OAAA,EAAS,OAAO,CAAA,GAAI,CAAA;AAC9E,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,QAAQ,CAAA,GAAI,QAAA;AACpD,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,IAAA,CAAK,OAAA,GAAU,QAAQ,CAAA,GAAI,QAAA;AACnD,IAAA,MAAM,QAAA,GAAW,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAA,CAAO,UAAA,GAAa,UAAA,IAAc,QAAQ,CAAC,CAAA;AAC7E,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,EAAE,QAAQ,QAAA,EAAS,EAAG,CAAC,MAAA,EAAQ,KAAA,KAAU;AAC/D,MAAA,MAAM,KAAA,GAAQ,aAAa,KAAA,GAAQ,QAAA;AACnC,MAAA,MAAM,KAAA,GAAQ,UAAA,GAAA,CAAc,KAAA,GAAQ,CAAA,IAAK,QAAA;AACzC,MAAA,OAAO,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAC,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAC,CAAC,CAAA,CAAA;AAAA,IAClE,CAAC,CAAA;AACD,IAAA,MAAM,UAAA,GAAa,QAAQ,OAAO,CAAA;AAClC,IAAA,MAAM,aAAa,UAAA,GACb,CAAC,GAAG,IAAI,GAAA,CAAI,MAAM,GAAA,CAAI,CAAC,QAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA,GACxD,CAAC,OAAO,CAAA;AACd,IAAA,MAAM,YAAA,GAAe,UAAA,CAAW,GAAA,CAAI,MAAM,IAAI,MAAM,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,CAAA;AACrE,IAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACrB,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA;AACpC,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC7B,MAAA,MAAM,WAAW,IAAA,CAAK,GAAA;AAAA,QAClB,QAAA,GAAW,CAAA;AAAA,QACX,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,OAAO,KAAA,GAAQ,UAAA,IAAc,QAAQ,CAAC;AAAA,OAC3D;AACA,MAAA,MAAM,WAAA,GAAc,aAAa,UAAA,CAAW,OAAA,CAAQ,OAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAA,GAAI,CAAA;AAC/E,MAAA,IAAI,eAAe,CAAA,EAAG,YAAA,CAAa,WAAW,CAAA,CAAE,QAAQ,CAAA,IAAK,CAAA;AAAA,IACjE;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,aAAa,eAAA,GAAkB,iBAAA;AAAA,MAC1C,KAAA,EAAO,mBAAmB,UAAU,CAAA,CAAA;AAAA,MACpC,QAAA,EAAU,SAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACF,CAAC,UAAA,EAAY,GAAG,UAAU,CAAA;AAAA,QAC1B,GAAG,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAO,UAAU,CAAC,KAAA,EAAO,GAAG,YAAA,CAAa,IAAI,CAAC,MAAA,KAAW,OAAO,KAAK,CAAC,CAAC,CAAC;AAAA,OAC3F;AAAA,MACA,YAAA,EAAc,EAAE,KAAA,EAAO,UAAA,EAAW;AAAA,MAClC,SAAA,EAAW,EAAE,KAAA,EAAO,OAAA,EAAS,cAAc,GAAA,EAAI;AAAA,MAC/C,QAAQ,EAAE,OAAA,EAAS,QAAQ,UAAU,CAAA,EAAG,UAAU,QAAA,EAAS;AAAA,MAC3D,QAAA,EAAU,CAAA;AAAA,MACV,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,MAAA,EAAQ,EAAE,SAAA,EAAW,WAAA,EAAa,YAAY,UAAA,EAAY,QAAA,EAAU,YAAY,UAAA;AAAW,KAC/F;AAAA,EACJ;AACJ,CAAA;;;AC1EO,IAAM,iBAAA,GAAsC;AAAA,EAC/C,KAAA,EAAO,YAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,SAAS,YAAY,CAAA;AAAA,EAC1C,WAAA,EAAa,EAAE,QAAA,EAAU,MAAA,EAAO;AAAA,EAChC,QAAA,EAAU,CAAC,EAAE,MAAA,EAAO,KAAM;AACtB,IAAA,IAAI,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA,EAAgB;AAChC,MAAA,OAAO,+DAAA;AAAA,IACX;AACA,IAAA,IAAI,OAAO,OAAO,CAAA,KAAM,kBAAkB,MAAA,CAAO,OAAO,MAAM,UAAA,EAAY;AACtE,MAAA,OAAO,gEAAA;AAAA,IACX;AACA,IAAA,OAAO,MAAA;AAAA,EACX;AACJ,CAAA;;;ACbO,IAAM,gBAAA,GAAqC;AAAA,EAC9C,KAAA,EAAO,WAAA;AAAA,EACP,QAAA,EAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,OAAO,CAAA;AAAA,EACnC,WAAA,EAAa,EAAE,QAAA,EAAU,KAAA,EAAO,QAAQ,IAAA;AAC5C,CAAA;AAEO,IAAM,kBAAA,GAAuC;AAAA,EAChD,KAAA,EAAO,aAAA;AAAA,EACP,QAAA,EAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,OAAO,CAAA;AAAA,EACnC,WAAA,EAAa,EAAE,QAAA,EAAU,UAAA,EAAY,QAAQ,IAAA;AACjD,CAAA;;;ACTA,SAAS,YAAY,KAAA,EAAuD;AACxE,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,CAAC,CAAA,GAAI,CAAA;AACvC,EAAA,MAAM,QAAQ,EAAA,IAAM,IAAA,CAAK,MAAM,IAAA,CAAK,KAAA,CAAM,SAAS,CAAC,CAAA;AACpD,EAAA,MAAM,WAAW,SAAA,GAAY,KAAA;AAC7B,EAAA,MAAM,SAAA,GAAA,CAAa,QAAA,IAAY,CAAA,GAAI,CAAA,GAAI,QAAA,IAAY,IAAI,CAAA,GAAI,QAAA,IAAY,CAAA,GAAI,CAAA,GAAI,EAAA,IAAM,KAAA;AACrF,EAAA,OAAO,EAAE,SAAS,IAAA,CAAK,IAAA,CAAK,QAAQ,SAAS,CAAA,GAAI,WAAW,SAAA,EAAU;AAC1E;AAEA,SAAS,qBAAqB,MAAA,EAAoC;AAC9D,EAAA,MAAM,QAAA,GAAW,CAAC,MAAA,IAAU,MAAA,KAAW,YAAY,OAAA,GAAU,MAAA;AAC7D,EAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,QAAQ,CAAA,EAAA,CAAA;AAClC;AAEO,IAAM,oBAAA,GAAyC;AAAA,EAClD,KAAA,EAAO,eAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,YAAA,EAAc,YAAY,YAAA,EAAa;AAAA,EAChE,UAAU,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AACtC,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA;AACnC,IAAA,MAAM,UAAA,GAAa,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA;AACnC,IAAA,IAAI,eAAe,UAAA,EAAY;AAC3B,MAAA,OAAO,iFAAA;AAAA,IACX;AACA,IAAA,MAAM,eAAA,GAAkB,aAAa,GAAA,GAAM,GAAA;AAC3C,IAAA,IAAI,CAAC,OAAA,CAAQ,eAAe,KAAK,MAAA,CAAO,eAAe,MAAM,cAAA,EAAgB;AACzE,MAAA,OAAO,oEAAA;AAAA,IACX;AACA,IAAA,MAAM,UAAA,GAAa,QAAQ,OAAO,CAAA;AAClC,IAAA,IAAI,CAAC,UAAA,IAAc,CAAC,cAAA,EAAgB,UAAU,CAAA,CAAE,QAAA,CAAS,MAAA,CAAO,OAAO,CAAA,IAAK,EAAE,CAAA,EAAG;AAC7E,MAAA,OAAO,kEAAA;AAAA,IACX;AACA,IAAA,MAAM,SAAS,CAAC,GAAG,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAC,GAAA,KAAQ,IAAI,UAAU,CAAC,EAAE,MAAA,CAAO,CAAC,UAAU,KAAA,IAAS,IAAI,CAAC,CAAC,CAAA;AAChG,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACrB,MAAA,OAAO,CAAA,oEAAA,EAAuE,OAAO,MAAM,CAAA,CAAA,CAAA;AAAA,IAC/F;AACA,IAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,UAAA,GAAa,GAAA,GAAM,GAAG,CAAA;AACnD,IAAA,IAAI,MAAM,IAAA,CAAK,CAAC,QAAQ,MAAA,CAAO,QAAA,CAAS,OAAO,GAAA,CAAI,YAAY,CAAC,CAAC,KAAK,MAAA,CAAO,GAAA,CAAI,YAAY,CAAC,CAAA,GAAI,CAAC,CAAA,EAAG;AAClG,MAAA,OAAO,+DAAA;AAAA,IACX;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,WAAA,EAAa,CAAC,EAAE,KAAA,EAAO,OAAO,SAAA,EAAW,OAAA,EAAS,QAAO,KAAM;AAC3D,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,GAAG,CAAA,KAAM,iBAAiB,GAAA,GAAM,GAAA;AAC9D,IAAA,MAAM,eAAA,GAAkB,cAAA,KAAmB,GAAA,GAAM,GAAA,GAAM,GAAA;AACvD,IAAA,MAAM,YAAA,GAAe,QAAQ,cAAc,CAAA;AAC3C,IAAA,MAAM,aAAA,GAAgB,QAAQ,eAAe,CAAA;AAC7C,IAAA,MAAM,UAAA,GAAa,QAAQ,OAAO,CAAA;AAClC,IAAA,MAAM,aAAa,CAAC,GAAG,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAC,GAAA,KAAQ,IAAI,aAAa,CAAC,EAAE,MAAA,CAAO,CAAC,UAAU,KAAA,IAAS,IAAI,CAAC,CAAC,CAAA;AACvG,IAAA,MAAM,SAAS,CAAC,GAAG,IAAI,GAAA,CAAI,KAAA,CAAM,IAAI,CAAC,GAAA,KAAQ,IAAI,UAAU,CAAC,EAAE,MAAA,CAAO,CAAC,UAAU,KAAA,IAAS,IAAI,CAAC,CAAC,CAAA;AAChG,IAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,IAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACrB,MAAA,MAAM,QAAA,GAAW,IAAI,aAAa,CAAA;AAClC,MAAA,MAAM,KAAA,GAAQ,IAAI,UAAU,CAAA;AAC5B,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,YAAY,CAAC,CAAA;AACtC,MAAA,IAAI,QAAA,IAAY,QAAQ,KAAA,IAAS,IAAA,IAAQ,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAClE,MAAA,MAAM,GAAA,GAAM,GAAG,MAAA,CAAO,QAAQ,CAAC,CAAA,EAAA,EAAS,MAAA,CAAO,KAAK,CAAC,CAAA,CAAA;AACrD,MAAA,MAAA,CAAO,IAAI,GAAA,EAAA,CAAM,MAAA,CAAO,IAAI,GAAG,CAAA,IAAK,KAAK,KAAK,CAAA;AAAA,IAClD;AACA,IAAA,MAAM,OAAA,GAAU,CAAC,QAAA,EAAmB,KAAA,KAAkC;AAClE,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,QAAQ,CAAC,CAAA,EAAA,EAAS,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AACpE,MAAA,OAAO,KAAA,KAAU,SAAY,IAAA,GAAO,KAAA;AAAA,IACxC,CAAA;AACA,IAAA,MAAM,eAAe,IAAA,CAAK,GAAA,CAAI,GAAG,GAAG,MAAA,CAAO,QAAQ,CAAA;AACnD,IAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAU,GAAI,YAAY,YAAY,CAAA;AACvD,IAAA,MAAM,YAAA,GAAe,iBAAA,CAAkB,SAAA,CAAU,cAAc,GAAG,MAAM,CAAA;AACxE,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AAEpE,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,YAAA;AAAA,MACX,OAAO,CAAA,EAAG,YAAY,CAAA,IAAA,EAAO,aAAa,QAAQ,UAAU,CAAA,CAAA;AAAA,MAC5D,QAAA,EAAU,SAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACF,CAAC,aAAA,EAAe,GAAG,MAAA,CAAO,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,QACrC,GAAG,UAAA,CAAW,GAAA,CAAI,CAAC,QAAA,KAAa;AAC5B,UAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,QAAA,EAAU,MAAA,CAAO,CAAC,CAAC,CAAA;AAC7C,UAAA,OAAO;AAAA,YACH,OAAO,QAAQ,CAAA;AAAA,YACf,SAAA,KAAc,IAAA,GAAO,IAAA,GAAO,CAAC,SAAA;AAAA,YAC7B,OAAA,CAAQ,QAAA,EAAU,MAAA,CAAO,CAAC,CAAC;AAAA,WAC/B;AAAA,QACJ,CAAC;AAAA,OACL;AAAA,MACA,YAAA,EAAc,EAAE,KAAA,EAAO,aAAA,EAAe,kBAAkB,IAAA,EAAK;AAAA,MAC7D,SAAA,EAAW;AAAA,QACP,KAAA,EAAO,YAAA;AAAA,QACP,YAAA,EAAc,qBAAqB,YAAY,CAAA;AAAA,QAC/C,cAAc,CAAC,OAAA;AAAA,QACf,YAAA,EAAc,OAAA;AAAA,QACd;AAAA,OACJ;AAAA,MACA,MAAA,EAAQ,EAAE,OAAA,EAAS,IAAA,EAAM,UAAU,QAAA,EAAS;AAAA,MAC5C,aAAA,EAAe,CAAC,EAAE,KAAA,EAAO,WAAU,EAAG,EAAE,KAAA,EAAO,SAAA,EAAW,CAAA;AAAA,MAC1D,QAAA,EAAU,EAAA;AAAA,MACV,OAAA,EAAS,GAAA;AAAA,MACT,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,MAAA,EAAQ;AAAA,QACJ,SAAA,EAAW,eAAA;AAAA,QACX,aAAA;AAAA,QACA,YAAA;AAAA,QACA,UAAA;AAAA,QACA,MAAA,EAAQ,MAAA,CAAO,GAAA,CAAI,MAAM;AAAA;AAC7B,KACJ;AAAA,EACJ;AACJ,CAAA;;;AC7GA,SAASC,aAAY,KAAA,EAAuB;AACxC,EAAA,IAAI,EAAE,KAAA,GAAQ,CAAA,CAAA,EAAI,OAAO,CAAA;AACzB,EAAA,MAAM,QAAQ,EAAA,IAAM,IAAA,CAAK,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA;AAChD,EAAA,MAAM,WAAW,KAAA,GAAQ,KAAA;AACzB,EAAA,MAAM,YAAA,GAAe,QAAA,IAAY,CAAA,GAAI,CAAA,GAC/B,QAAA,IAAY,CAAA,GAAI,CAAA,GAChB,QAAA,IAAY,GAAA,GAAM,GAAA,GAClB,QAAA,IAAY,CAAA,GAAI,CAAA,GAChB,EAAA;AACN,EAAA,OAAO,YAAA,GAAe,KAAA;AAC1B;AAEO,IAAM,kBAAA,GAAuC;AAAA,EAChD,KAAA,EAAO,aAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,cAAA,EAAe;AAAA,EACxC,UAAU,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AACtC,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAG,CAAA,IAAK,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA,IAAkB,MAAA,CAAO,GAAG,CAAA,KAAM,UAAA,EAAY;AAC/E,MAAA,OAAO,sEAAA;AAAA,IACX;AACA,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAG,KAAK,MAAA,CAAO,GAAG,MAAM,cAAA,EAAgB;AACjD,MAAA,OAAO,gEAAA;AAAA,IACX;AACA,IAAA,IAAI,OAAA,CAAQ,OAAO,CAAA,KAAM,MAAA,CAAO,OAAO,MAAM,cAAA,IAAkB,MAAA,CAAO,OAAO,CAAA,KAAM,UAAA,CAAA,EAAa;AAC5F,MAAA,OAAO,+DAAA;AAAA,IACX;AACA,IAAA,IAAI,OAAA,CAAQ,QAAQ,CAAA,IAAK,OAAA,CAAQ,KAAK,CAAA,EAAG;AACrC,MAAA,OAAO,2DAAA;AAAA,IACX;AACA,IAAA,MAAM,UAAA,GAAa,QAAQ,GAAG,CAAA;AAC9B,IAAA,IAAI,KAAA,CAAM,IAAA,CAAK,CAAC,GAAA,KAAQ,MAAA,CAAO,IAAI,UAAU,CAAC,CAAA,GAAI,CAAC,CAAA,EAAG;AAClD,MAAA,OAAO,6DAAA;AAAA,IACX;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,KAAA,EAAO,KAAA,EAAO,SAAQ,KAAM;AACxC,IAAA,MAAM,WAAA,GAAc,QAAQ,GAAG,CAAA;AAC/B,IAAA,MAAM,UAAA,GAAa,QAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,WAAA,GAAc,QAAQ,OAAO,CAAA;AACnC,IAAA,MAAM,OAAA,GAAU,CAAC,GAAG,IAAI,IAAI,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ,OAAO,GAAA,CAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AACzE,IAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACpB,MAAA,MAAM,IAAI,MAAM,wDAAwD,CAAA;AAAA,IAC5E;AACA,IAAA,MAAM,aAAa,WAAA,GACb,CAAC,GAAG,IAAI,GAAA,CAAI,MAAM,GAAA,CAAI,CAAC,QAAQ,MAAA,CAAO,GAAA,CAAI,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA,GACzD,CAAC,UAAU,CAAA;AACjB,IAAA,MAAM,iBAAiB,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AACnD,MAAA,MAAM,MAAA,GAAS,MACV,MAAA,CAAO,CAAC,QAAQ,MAAA,CAAO,GAAA,CAAI,WAAW,CAAC,CAAA,KAAM,MAAM,EACnD,GAAA,CAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAA,CACpC,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA;AAC3B,MAAA,OAAO,CAAC,MAAA,EAAQA,YAAAA,CAAY,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA,GAAI,CAAC,CAAC,CAAA;AAAA,IAC5E,CAAC,CAAC,CAAA;AACF,IAAA,MAAM,YAAA,uBAAmB,GAAA,EAA4C;AACrE,IAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACrB,MAAA,MAAM,MAAA,GAAS,MAAA,CAAO,GAAA,CAAI,WAAW,CAAC,CAAA;AACtC,MAAA,MAAM,SAAS,WAAA,GAAc,MAAA,CAAO,GAAA,CAAI,WAAW,CAAC,CAAA,GAAI,UAAA;AACxD,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA;AACpC,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC7B,MAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAM,CAAA,EAAA,EAAS,MAAM,CAAA,CAAA;AACpC,MAAA,MAAM,WAAA,GAAc,aAAa,GAAA,CAAI,GAAG,KAAK,EAAE,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,CAAA,EAAE;AAChE,MAAA,WAAA,CAAY,GAAA,IAAO,KAAA;AACnB,MAAA,WAAA,CAAY,KAAA,IAAS,CAAA;AACrB,MAAA,YAAA,CAAa,GAAA,CAAI,KAAK,WAAW,CAAA;AAAA,IACrC;AACA,IAAA,MAAM,eAAA,GAAkB,CAAC,MAAA,EAAgB,MAAA,KAA2B;AAChE,MAAA,MAAM,cAAc,YAAA,CAAa,GAAA,CAAI,GAAG,MAAM,CAAA,EAAA,EAAS,MAAM,CAAA,CAAE,CAAA;AAC/D,MAAA,IAAI,CAAC,aAAa,OAAO,CAAA;AACzB,MAAA,OAAQ,YAAY,GAAA,GAAM,WAAA,CAAY,KAAA,GAAS,cAAA,CAAe,IAAI,MAAM,CAAA;AAAA,IAC5E,CAAA;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,UAAA,CAAW,eAAA,EAAiB,MAAA,KAAW,KAAA;AACrE,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,cAAA;AAAA,MACX,KAAA,EAAO,CAAA,EAAG,UAAU,CAAA,IAAA,EAAO,WAAW,CAAA,CAAA;AAAA,MACtC,QAAA,EAAU,SAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACF,CAAC,WAAA,EAAa,GAAG,UAAU,CAAA;AAAA,QAC3B,GAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAAA,UACvB,GAAG,MAAM,CAAA,EAAA,EAAK,cAAA,CAAe,GAAA,CAAI,MAAM,CAAC,CAAA,CAAA,CAAA;AAAA,UACxC,GAAG,WAAW,GAAA,CAAI,CAAC,WAAW,eAAA,CAAgB,MAAA,EAAQ,MAAM,CAAC;AAAA,SAChE;AAAA,OACL;AAAA,MACA,WAAW,EAAE,YAAA,EAAc,GAAG,YAAA,EAAc,CAAA,EAAG,WAAW,IAAA,EAAK;AAAA,MAC/D,QAAQ,EAAE,OAAA,EAAS,QAAQ,WAAW,CAAA,EAAG,UAAU,QAAA,EAAS;AAAA,MAC5D,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,QAAA,EAAU,kBAAkB,CAAC;AAAA,QACzB,QAAA,EAAU,MAAA;AAAA,QACV,IAAA,EAAM,8BAAA;AAAA,QACN,OAAA,EAAS;AAAA,OACZ,IAAI,EAAC;AAAA,MACN,MAAA,EAAQ;AAAA,QACJ,SAAA,EAAW,aAAA;AAAA,QACX,WAAA;AAAA,QACA,UAAA;AAAA,QACA,WAAA;AAAA,QACA,cAAA,EAAgB,MAAA,CAAO,WAAA,CAAY,cAAc,CAAA;AAAA,QACjD,UAAA,EAAY,IAAA;AAAA,QACZ;AAAA;AACJ,KACJ;AAAA,EACJ;AACJ,CAAA;;;ACvFO,SAAS,wBAAwB,OAAA,EAAmD;AACvF,EAAA,IAAI,OAAA,CAAQ,OAAO,GAAG,CAAA,KAAM,kBAAkB,OAAA,CAAQ,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA,EAAgB;AAClF,IAAA,OAAO,kEAAA;AAAA,EACX;AACA,EAAA,IAAI,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAA,EAAG;AAC1B,IAAA,OAAO,0DAAA;AAAA,EACX;AACA,EAAA,OAAO,MAAA;AACX;;;ACzBO,IAAM,mBAAA,GAAwC;AAAA,EACjD,KAAA,EAAO,cAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,SAAS,MAAM,CAAA;AAAA,EACpC,WAAA,EAAa,EAAE,QAAA,EAAU,WAAA,EAAa,IAAI,IAAA,EAAK;AAAA,EAC/C,UAAU,CAAC,OAAA,KAAY,uBAAA,CAAwB,OAAO,MAC9C,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,KAAM,kBAAkB,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,KAAM,aACxE,6EAAA,GACA,MAAA;AACd,CAAA;AAEO,IAAM,4BAAA,GAAiD;AAAA,EAC1D,KAAA,EAAO,wBAAA;AAAA,EACP,UAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAA,EAAS,SAAS,QAAQ,CAAA;AAAA,EAC/C,WAAA,EAAa,EAAE,QAAA,EAAU,gBAAA,EAAkB,IAAI,IAAA,EAAK;AAAA,EACpD,QAAA,EAAU,CAAC,OAAA,KAAY,uBAAA,CAAwB,OAAO,CAAA,KAC9C,CAAC,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAA,GACtB,6EAAA,GACA,OAAA,CAAQ,OAAA,CAAQ,QAAQ,CAAA,GACpB,wFAAA,GACA,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,KAAM,cAAA,IAAkB,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,KAAM,UAAA,GACtE,6EAAA,GACA,MAAA;AACtB,CAAA;;;ACvBO,IAAM,qBAAA,GAA0C;AAAA,EACnD,KAAA,EAAO,gBAAA;AAAA,EACP,QAAA,EAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,SAAS,QAAQ,CAAA;AAAA,EAC7C,WAAA,EAAa,EAAE,QAAA,EAAU,UAAA,EAAY,QAAQ,IAAA,EAAK;AAAA,EAClD,UAAU,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AACtC,IAAA,IAAI,CAAC,OAAA,CAAQ,OAAO,KAAK,MAAA,CAAO,OAAO,MAAM,cAAA,EAAgB;AACzD,MAAA,OAAO,sEAAA;AAAA,IACX;AACA,IAAA,IAAI,MAAA,CAAO,MAAM,CAAA,KAAM,cAAA,EAAgB;AACnC,MAAA,OAAO,sEAAA;AAAA,IACX;AACA,IAAA,IAAI,QAAQ,OAAO,CAAA,IAAK,MAAA,CAAO,OAAO,MAAM,cAAA,EAAgB;AACxD,MAAA,OAAO,0EAAA;AAAA,IACX;AACA,IAAA,IAAI,QAAQ,QAAQ,CAAA,IAAK,CAAC,OAAA,CAAQ,OAAO,CAAA,EAAG;AACxC,MAAA,OAAO,2EAAA;AAAA,IACX;AACA,IAAA,IAAI,QAAQ,QAAQ,CAAA,IAAK,MAAA,CAAO,QAAQ,MAAM,cAAA,EAAgB;AAC1D,MAAA,OAAO,2EAAA;AAAA,IACX;AACA,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,CAAA;AACjC,IAAA,IAAI,MAAM,IAAA,CAAK,CAAC,QAAQ,MAAA,CAAO,QAAA,CAAS,OAAO,GAAA,CAAI,UAAU,CAAC,CAAC,KAAK,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA,GAAI,CAAC,CAAA,EAAG;AAC9F,MAAA,OAAO,gEAAA;AAAA,IACX;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,KAAA,EAAO,KAAA,EAAO,SAAQ,KAAM;AACxC,IAAA,MAAM,aAAA,GAAgB,QAAQ,OAAO,CAAA;AACrC,IAAA,MAAM,UAAA,GAAa,QAAQ,OAAO,CAAA;AAClC,IAAA,MAAM,WAAA,GAAc,QAAQ,QAAQ,CAAA;AACpC,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,CAAA;AACjC,IAAA,MAAM,eAAA,GAAkB,CAAC,aAAA,EAAe,UAAA,EAAY,WAAW,CAAA,CAAE,MAAA,CAAO,CAAC,KAAA,KAA2B,OAAA,CAAQ,KAAK,CAAC,CAAA;AAClH,IAAA,MAAM,MAAA,uBAAa,GAAA,EAA+C;AAClE,IAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACrB,MAAA,MAAM,OAAO,eAAA,CAAgB,GAAA,CAAI,CAAC,KAAA,KAAU,GAAA,CAAI,KAAK,CAAC,CAAA;AACtD,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA;AACpC,MAAA,IAAI,IAAA,CAAK,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,IAAQ,IAAI,CAAA,IAAK,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAClE,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAC9B,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,IAAQ,CAAA;AAChC,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAC/B,MAAA,MAAA,CAAO,GAAA,CAAI,GAAA,EAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,QAAQ,QAAA,EAAU,KAAA,IAAS,CAAA,IAAK,KAAA,EAAO,CAAA;AAAA,IAC3E;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,UAAA;AAAA,MACX,KAAA,EAAO,GAAG,UAAU,CAAA,IAAA,EAAO,gBAAgB,eAAA,CAAgB,MAAA,GAAS,CAAC,CAAC,CAAA,CAAA;AAAA,MACtE,QAAA,EAAU,SAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACF,CAAC,GAAG,eAAA,EAAiB,UAAU,CAAA;AAAA,QAC/B,GAAG,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,CAAC,GAAG,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,KAAK,CAAC;AAAA,OACpE;AAAA,MACA,MAAA,EAAQ,EAAE,OAAA,EAAS,KAAA,EAAM;AAAA,MACzB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,MAAA,EAAQ,EAAE,SAAA,EAAW,gBAAA,EAAkB,iBAAiB,UAAA;AAAW,KACvE;AAAA,EACJ;AACJ,CAAA;;;AC7DO,IAAM,eAAA,GAAoC;AAAA,EAC7C,KAAA,EAAO,SAAA;AAAA,EACP,QAAA,EAAU,CAAC,OAAA,EAAS,MAAA,EAAQ,QAAQ,CAAA;AAAA,EACpC,WAAA,EAAa,EAAE,QAAA,EAAU,SAAA,EAAW,QAAQ,IAAA,EAAK;AAAA,EACjD,UAAU,CAAC,EAAE,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AACtC,IAAA,IAAI,CAAC,OAAA,CAAQ,OAAO,KAAK,MAAA,CAAO,OAAO,MAAM,cAAA,EAAgB;AACzD,MAAA,OAAO,+DAAA;AAAA,IACX;AACA,IAAA,IAAI,MAAA,CAAO,MAAM,CAAA,KAAM,cAAA,EAAgB;AACnC,MAAA,OAAO,+DAAA;AAAA,IACX;AACA,IAAA,IAAI,QAAQ,QAAQ,CAAA,IAAK,MAAA,CAAO,QAAQ,MAAM,cAAA,EAAgB;AAC1D,MAAA,OAAO,0EAAA;AAAA,IACX;AACA,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,CAAA;AACjC,IAAA,IAAI,MAAM,IAAA,CAAK,CAAC,QAAQ,MAAA,CAAO,QAAA,CAAS,OAAO,GAAA,CAAI,UAAU,CAAC,CAAC,KAAK,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA,GAAI,CAAC,CAAA,EAAG;AAC9F,MAAA,OAAO,yDAAA;AAAA,IACX;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,KAAA,EAAO,KAAA,EAAO,SAAQ,KAAM;AACxC,IAAA,MAAM,aAAA,GAAgB,QAAQ,OAAO,CAAA;AACrC,IAAA,MAAM,WAAA,GAAc,QAAQ,QAAQ,CAAA;AACpC,IAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,CAAA;AACjC,IAAA,MAAM,MAAA,uBAAa,GAAA,EAAkE;AACrF,IAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACrB,MAAA,MAAM,QAAA,GAAW,IAAI,aAAa,CAAA;AAClC,MAAA,MAAM,MAAA,GAAS,WAAA,GAAc,GAAA,CAAI,WAAW,CAAA,GAAI,MAAA;AAChD,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAA;AACpC,MAAA,IAAI,QAAA,IAAY,QAAS,WAAA,IAAe,MAAA,IAAU,QAAS,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACpF,MAAA,MAAM,aAAA,GAAgB,OAAO,QAAQ,CAAA;AACrC,MAAA,MAAM,WAAA,GAAc,WAAA,GAAc,MAAA,CAAO,MAAM,CAAA,GAAI,MAAA;AACnD,MAAA,MAAM,GAAA,GAAM,CAAA,EAAG,aAAa,CAAA,EAAA,EAAS,eAAe,EAAE,CAAA,CAAA;AACtD,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA;AAC/B,MAAA,MAAA,CAAO,IAAI,GAAA,EAAK;AAAA,QACZ,QAAA,EAAU,aAAA;AAAA,QACV,MAAA,EAAQ,WAAA;AAAA,QACR,KAAA,EAAA,CAAQ,QAAA,EAAU,KAAA,IAAS,CAAA,IAAK;AAAA,OACnC,CAAA;AAAA,IACL;AAEA,IAAA,MAAM,IAAA,GAAO,CAAC,GAAG,MAAA,CAAO,QAAQ,CAAA;AAChC,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,SAAA;AAAA,MACX,KAAA,EAAO,CAAA,EAAG,UAAU,CAAA,IAAA,EAAO,eAAe,aAAa,CAAA,CAAA;AAAA,MACvD,QAAA,EAAU,SAAA;AAAA,MACV,MAAM,WAAA,GACA,CAAC,CAAC,aAAA,EAAe,aAAa,UAAU,CAAA,EAAG,GAAG,IAAA,CAAK,IAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,CAAI,QAAA,EAAU,IAAI,MAAA,EAAS,GAAA,CAAI,KAAK,CAAC,CAAC,CAAA,GACvG,CAAC,CAAC,aAAA,EAAe,UAAU,GAAG,GAAG,IAAA,CAAK,GAAA,CAAI,CAAC,QAAQ,CAAC,GAAA,CAAI,UAAU,GAAA,CAAI,KAAK,CAAC,CAAC,CAAA;AAAA,MACnF,MAAA,EAAQ,EAAE,OAAA,EAAS,KAAA,EAAM;AAAA,MACzB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,QAAQ,EAAE,SAAA,EAAW,SAAA,EAAW,aAAA,EAAe,aAAa,UAAA;AAAW,KAC3E;AAAA,EACJ;AACJ,CAAA;;;AC1CO,SAAS,wBAAwB,MAAA,EAA2B;AAC/D,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,KAAA;AAC9B,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,MAAA,GAAS,GAAG,CAAA,EAAA,EAAK;AACxC,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,OAAO,CAAC,CAAC,GAAG,OAAO,KAAA;AACxC,IAAA,OAAA,IAAW,OAAO,CAAC,CAAA;AAAA,EACvB;AACA,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AACrC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,IAAI,GAAG,OAAO,KAAA;AACnC,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,CAAI,IAAA,EAAM,OAAQ,IAAA,CAAK,GAAA,CAAI,OAAO,CAAC,CAAA;AACpD,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,IAAA,GAAO,OAAO,CAAA,IAAK,GAAA;AACvC;AAQO,SAAS,sBAAsB,MAAA,EAAoC;AACtE,EAAA,OAAO,uBAAA,CAAwB,MAAM,CAAA,GAAI,MAAA,GAAS,OAAA;AACtD;AAOO,SAAS,iBAAA,CAAkB,QAAkB,QAAA,EAAyC;AACzF,EAAA,IAAI,aAAa,MAAA,IAAU,QAAA,KAAa,WAAW,QAAA,KAAa,MAAA,IAAU,aAAa,MAAA,EAAQ;AAC3F,IAAA,OAAO,QAAA;AAAA,EACX;AACA,EAAA,OAAO,sBAAsB,MAAM,CAAA;AACvC;;;AChDO,IAAM,sBAAA,GAA2C;AAAA,EACpD,KAAA,EAAO,iBAAA;AAAA,EACP,QAAA,EAAU,CAAC,GAAA,EAAK,GAAA,EAAK,OAAO,CAAA;AAAA,EAC5B,WAAA,EAAa,EAAE,QAAA,EAAU,WAAA,EAAY;AAAA,EACrC,UAAU,CAAC,EAAE,OAAO,KAAA,EAAO,OAAA,EAAS,QAAO,KAAM;AAC7C,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAG,CAAA,EAAG,OAAO,gEAAA;AAC1B,IAAA,IAAI,MAAA,CAAO,GAAG,CAAA,KAAM,cAAA,EAAgB;AAChC,MAAA,OAAO,oEAAA;AAAA,IACX;AACA,IAAA,IAAI,QAAQ,OAAO,CAAA,IAAK,MAAA,CAAO,OAAO,MAAM,cAAA,EAAgB;AACxD,MAAA,OAAO,oFAAA;AAAA,IACX;AACA,IAAA,MAAM,UAAA,GAAa,QAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,SAAA,GAAY,QAAQ,OAAO,CAAA;AACjC,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAA,CAAE,MAAA,CAAO,OAAO,QAAQ,CAAA;AACjF,IAAA,IAAI,SAAA,EAAW;AACX,MAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,SAAA,CAAU,CAAC,KAAK,KAAA,KAAU;AACrD,QAAA,MAAM,OAAO,MAAA,CAAO,GAAA,CAAI,SAAS,CAAA,IAAK,EAAE,EAAE,WAAA,EAAY;AACtD,QAAA,OAAO,QAAQ,CAAA,KAAM,IAAA,KAAS,OAAA,IAAW,IAAA,KAAS,SAAS,IAAA,KAAS,OAAA,CAAA;AAAA,MACxE,CAAC,CAAA;AACD,MAAA,IAAI,oBAAoB,CAAA,EAAG;AACvB,QAAA,OAAO,wGAAA;AAAA,MACX;AAAA,IACJ,CAAA,MAAO;AACH,MAAA,MAAM,SAAS,iBAAA,CAAkB,MAAA,EAAQ,KAAA,CAAM,UAAA,CAAW,iBAAiB,MAAM,CAAA;AACjF,MAAA,IAAI,MAAA,KAAW,MAAA,IAAU,MAAA,KAAW,MAAA,EAAQ;AACxC,QAAA,OAAO,6FAAA;AAAA,MACX;AAAA,IACJ;AACA,IAAA,OAAO,MAAA;AAAA,EACX,CAAA;AAAA,EACA,aAAa,CAAC,EAAE,OAAO,KAAA,EAAO,SAAA,EAAW,SAAQ,KAAM;AACnD,IAAA,MAAM,aAAA,GAAgB,QAAQ,GAAG,CAAA;AACjC,IAAA,MAAM,UAAA,GAAa,QAAQ,GAAG,CAAA;AAC9B,IAAA,MAAM,OAAO,KAAA,CAAM,MAAA,CAAO,CAAC,GAAA,KAAQ,IAAI,aAAa,CAAA,IAAK,IAAA,IAAQ,MAAA,CAAO,SAAS,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAC,CAAA;AAEzG,IAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,IAAA,OAAO;AAAA,MACH,MAAA,EAAQ,sBAAA;AAAA,MACR,IAAA,EAAM,OAAA;AAAA,MACN,SAAA,EAAW,WAAA;AAAA,MACX,KAAA,EAAO,CAAA,EAAG,UAAU,CAAA,IAAA,EAAO,aAAa,CAAA,CAAA;AAAA,MACxC,QAAA,EAAU,SAAA;AAAA,MACV,IAAA,EAAM;AAAA,QACF,CAAC,eAAe,UAAU,CAAA;AAAA,QAC1B,GAAG,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,MAAA,CAAO,GAAA,CAAI,aAAa,CAAC,GAAG,MAAA,CAAO,GAAA,CAAI,UAAU,CAAC,CAAC,CAAC;AAAA,OAC9E;AAAA,MACA,YAAA,EAAc,EAAE,KAAA,EAAO,aAAA,EAAc;AAAA,MACrC,SAAA,EAAW;AAAA,QACP,KAAA,EAAO,UAAA;AAAA,QACP,YAAA,EAAc,iBAAA,CAAkB,SAAA,CAAU,CAAA,EAAG,MAAM;AAAA,OACvD;AAAA,MACA,MAAA,EAAQ,EAAE,OAAA,EAAS,KAAA,EAAM;AAAA,MACzB,kBAAA,EAAoB,IAAA;AAAA,MACpB,OAAO,IAAA,CAAK,KAAA;AAAA,MACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,EAAC;AAAA,MACX,MAAA,EAAQ,EAAE,SAAA,EAAW,iBAAA,EAAmB,eAAe,UAAA;AAAW,KACtE;AAAA,EACJ;AACJ,CAAA;;;AChDO,IAAM,oBAAA,GAA2C;AAAA,EACpD,gBAAA;AAAA,EACA,uBAAA;AAAA,EACA,uBAAA;AAAA,EACA,oBAAA;AAAA,EACA,iBAAA;AAAA,EACA,iBAAA;AAAA,EACA,mBAAA;AAAA,EACA,4BAAA;AAAA,EACA,gBAAA;AAAA,EACA,kBAAA;AAAA,EACA,iBAAA;AAAA,EACA,eAAA;AAAA,EACA,mBAAA;AAAA,EACA,sBAAA;AAAA,EACA,kBAAA;AAAA,EACA,mBAAA;AAAA,EACA,eAAA;AAAA,EACA;AACJ;AAEO,SAAS,oBAAoB,SAAA,EAAiD;AACjF,EAAA,OAAO,qBAAqB,IAAA,CAAK,CAAC,QAAA,KAAa,QAAA,CAAS,UAAU,SAAS,CAAA;AAC/E;AAEO,SAAS,yBAAyB,SAAA,EAA6B;AAClE,EAAA,OAAO,mBAAA,CAAoB,SAAS,CAAA,EAAG,QAAA,IAAY,EAAC;AACxD;;;ACHA,IAAM,sBAAsB,CAAC,SAAA,EAAW,WAAW,SAAA,EAAW,SAAA,EAAW,WAAW,SAAS,CAAA;AAE7F,SAASC,SAAAA,CAAS,IAAA,EAAc,WAAA,GAAc,CAAA,EAAW;AACrD,EAAA,IAAI,EAAE,IAAA,GAAO,CAAA,CAAA,EAAI,OAAO,CAAA;AACxB,EAAA,MAAM,QAAQ,IAAA,GAAO,WAAA;AACrB,EAAA,MAAM,QAAQ,EAAA,IAAM,IAAA,CAAK,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,CAAC,CAAA;AAChD,EAAA,MAAM,WAAW,KAAA,GAAQ,KAAA;AACzB,EAAA,MAAM,YAAA,GAAe,YAAY,CAAA,GAAI,CAAA,GAAI,YAAY,CAAA,GAAI,CAAA,GAAI,QAAA,IAAY,CAAA,GAAI,CAAA,GAAI,EAAA;AACjF,EAAA,OAAO,YAAA,GAAe,KAAA;AAC1B;AAEA,SAAS,mBAAmB,MAAA,EAA+F;AACvH,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA;AAC5C,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AACjC,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA;AACtC,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,GAAG,MAAM,CAAA;AACtC,EAAA,MAAM,WAAW,WAAA,GAAc,WAAA;AAC/B,EAAA,MAAM,aAAA,GAAgB,QAAA,GAAW,CAAA,GAAI,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,WAAW,CAAA,GAAI,GAAG,CAAA;AACvF,EAAA,MAAM,SAAA,GAAYA,UAAS,aAAa,CAAA;AACxC,EAAA,MAAM,SAAA,GAAY,EAAA,IAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,CAAC,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,SAAS,CAAC,IAAI,CAAC,CAAA;AAC1E,EAAA,MAAM,QAAQ,CAAC,KAAA,KAAkB,KAAK,KAAA,CAAM,KAAA,GAAQ,SAAS,CAAA,GAAI,SAAA;AACjE,EAAA,IAAI,aAAa,CAAA,EAAG;AAChB,IAAA,OAAO;AAAA,MACH,YAAA,EAAc,KAAA,CAAM,WAAA,GAAc,SAAS,CAAA;AAAA,MAC3C,YAAA,EAAc,KAAA,CAAM,WAAA,GAAc,SAAS,CAAA;AAAA,MAC3C;AAAA,KACJ;AAAA,EACJ;AACA,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAkB,IAAA,CAAK,GAAA,CAAI,KAAA,GAAQ,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,SAAS,CAAC,CAAA,GAAI,IAAA;AACrG,EAAA,MAAM,YAAA,GAAe,WAAA,IAAe,CAAA,IAAK,WAAA,IAAe,aAAA,GAAgB,GAAA,GAClE,CAAA,GACA,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,WAAA,GAAc,SAAS,IAAI,SAAS,CAAA;AAC3D,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,IAAA,CAAK,WAAA,GAAc,SAAS,CAAA,GAAI,SAAA;AAC3D,EAAA,MAAM,eAAe,WAAA,CAAY,WAAW,CAAA,GACtC,WAAA,GAAc,YAAY,IAAA,GAC1B,aAAA;AACN,EAAA,OAAO;AAAA,IACH,YAAA;AAAA,IACA,YAAA,EAAc,MAAM,YAAY,CAAA;AAAA,IAChC;AAAA,GACJ;AACJ;AAEA,SAAS,oBAAA,CAAqB,eAAuB,KAAA,EAAmC;AACpF,EAAA,MAAM,WAAA,GAAc,KAAK,GAAA,CAAI,EAAA,EAAI,KAAK,KAAA,CAAA,CAAO,KAAA,GAAQ,EAAA,IAAM,EAAE,CAAC,CAAA;AAC9D,EAAA,OAAO,gBAAgB,WAAA,GAAc,IAAA,CAAK,IAAA,CAAK,aAAA,GAAgB,WAAW,CAAA,GAAI,MAAA;AAClF;AAGA,SAAS,mBACL,GAAA,EAC6B;AAC7B,EAAA,MAAM,MAAqC,EAAC;AAC5C,EAAA,KAAA,MAAW,CAAC,IAAI,CAAC,CAAA,IAAK,OAAO,OAAA,CAAQ,GAAA,IAAO,EAAE,CAAA,EAAG;AAC7C,IAAA,IAAI,KAAK,IAAA,EAAM;AACf,IAAA,GAAA,CAAI,EAAE,IAAI,OAAO,CAAA,KAAM,WAAW,EAAE,KAAA,EAAO,GAAE,GAAK,CAAA;AAAA,EACtD;AACA,EAAA,OAAO,GAAA;AACX;AAGA,SAAS,QAAA,CAAS,MAAa,KAAA,EAAuB;AAClD,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAa;AAC9B,EAAA,MAAM,MAAc,EAAC;AACrB,EAAA,KAAA,MAAW,KAAK,IAAA,EAAM;AAClB,IAAA,MAAM,CAAA,GAAI,EAAE,KAAK,CAAA;AACjB,IAAA,IAAI,CAAC,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG;AAAE,MAAA,IAAA,CAAK,IAAI,CAAC,CAAA;AAAG,MAAA,GAAA,CAAI,KAAK,CAAS,CAAA;AAAA,IAAG;AAAA,EAC1D;AACA,EAAA,OAAO,GAAA;AACX;AAEA,SAAS,mBAAmB,MAAA,EAAwB;AAChD,EAAA,MAAM,MAAA,GAAS,CAAC,GAAG,MAAM,CAAA;AACzB,EAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,MAAA,CAAO,MAAA,EAAQ,SAAS,CAAA,EAAG;AACnD,IAAA,IAAI,MAAA,CAAO,KAAK,CAAA,IAAK,IAAA,EAAM;AAC3B,IAAA,IAAI,WAAW,KAAA,GAAQ,CAAA;AACvB,IAAA,IAAI,OAAO,KAAA,GAAQ,CAAA;AACnB,IAAA,OAAO,YAAY,CAAA,IAAK,MAAA,CAAO,QAAQ,CAAA,IAAK,MAAM,QAAA,IAAY,CAAA;AAC9D,IAAA,OAAO,OAAO,MAAA,CAAO,MAAA,IAAU,OAAO,IAAI,CAAA,IAAK,MAAM,IAAA,IAAQ,CAAA;AAC7D,IAAA,IAAI,QAAA,GAAW,CAAA,IAAK,IAAA,IAAQ,MAAA,CAAO,MAAA,EAAQ;AAC3C,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAC,CAAA;AACrC,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,MAAA,CAAO,IAAI,CAAC,CAAA;AAC/B,IAAA,IAAI,CAAC,OAAO,QAAA,CAAS,KAAK,KAAK,CAAC,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACtD,IAAA,MAAA,CAAO,KAAK,CAAA,GAAI,KAAA,GAAA,CAAU,MAAM,KAAA,KAAU,KAAA,GAAQ,aAAc,IAAA,GAAO,QAAA,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,MAAA;AACX;AAEA,SAAS,qBAAA,CACL,IAAA,EACA,KAAA,EACA,IAAA,EACA,OACA,MAAA,EACgB;AAChB,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,KAAK,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,KAAA,KAAU,SAAS,IAAI,CAAA;AAC5E,EAAA,MAAM,SAAS,CAAC,GAAG,IAAI,GAAA,CAAI,MAAM,CAAC,CAAA;AAClC,EAAA,MAAM,cAAc,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,CAAI,EAAA,EAAI,KAAK,GAAA,CAAI,GAAA,EAAM,QAAQ,MAAA,GAAS,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,GAAK,GAAG,CAAC,CAAC,CAAA;AAC7G,EAAA,MAAM,WAAA,GAAc,SAAS,cAAA,IAAkB,IAAA,KAAS,aAClD,CAAA,GACA,IAAA,CAAK,KAAA,CAAM,WAAA,GAAc,CAAC,CAAA;AAChC,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAiB;AACpC,EAAA,IAAI,IAAA,KAAS,cAAA,IAAkB,IAAA,KAAS,UAAA,EAAY;AAChD,IAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,EAAO,KAAA,KAAU;AAC7B,MAAA,MAAM,IAAI,MAAA,CAAO,MAAA,GAAS,IAAI,KAAA,IAAS,MAAA,CAAO,SAAS,CAAA,CAAA,GAAK,GAAA;AAC5D,MAAA,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,WAAA,GAAc,CAAA,IAAK,cAAc,WAAA,CAAY,CAAA;AAAA,IACnE,CAAC,CAAA;AACD,IAAA,OAAO,MAAA;AAAA,EACX;AAEA,EAAA,MAAM,UAAU,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA,CAAE,MAAA,CAAO,OAAO,QAAQ,CAAA;AACzD,EAAA,MAAM,OAAA,GAAU,QAAQ,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,OAAO,CAAA,GAAI,CAAA;AAC5D,EAAA,MAAM,cAAc,IAAA,CAAK,IAAA,CAAK,KAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAC,CAAA;AAClD,EAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,KAAA,KAAU;AACtB,IAAA,MAAM,YAAA,GAAe,OAAO,KAAK,CAAA;AACjC,IAAA,MAAM,CAAA,GAAI,WAAA,GAAc,CAAA,IAAK,MAAA,CAAO,SAAS,YAAY,CAAA,GACnD,IAAA,CAAK,IAAA,CAAK,KAAK,GAAA,CAAI,CAAA,EAAG,YAAY,CAAC,IAAI,WAAA,GACvC,CAAA;AACN,IAAA,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,WAAA,GAAc,CAAA,IAAK,cAAc,WAAA,CAAY,CAAA;AAAA,EACnE,CAAC,CAAA;AACD,EAAA,OAAO,MAAA;AACX;AAEA,SAAS,gBAAA,CAAiB,KAAA,EAAe,GAAA,EAAa,CAAA,EAAmB;AACrE,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,EAAe,MAAA,KAAmB,MAAA,CAAO,QAAA,CAAS,KAAA,CAAM,KAAA,CAAM,MAAA,EAAQ,MAAA,GAAS,CAAC,CAAA,EAAG,EAAE,CAAA;AACtG,EAAA,MAAM,GAAA,GAAM,CAAC,KAAA,KAAkB,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AAC7E,EAAA,OAAO,CAAA,CAAA,EAAI,IAAI,OAAA,CAAQ,KAAA,EAAO,CAAC,CAAA,GAAA,CAAK,OAAA,CAAQ,KAAK,CAAC,CAAA,GAAI,QAAQ,KAAA,EAAO,CAAC,KAAK,CAAC,CAAC,GAAG,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,CAAC,CAAA,GAAA,CAAK,OAAA,CAAQ,KAAK,CAAC,CAAA,GAAI,QAAQ,KAAA,EAAO,CAAC,KAAK,CAAC,CAAC,CAAA,EAAG,GAAA,CAAI,OAAA,CAAQ,KAAA,EAAO,CAAC,CAAA,GAAA,CAAK,OAAA,CAAQ,KAAK,CAAC,CAAA,GAAI,QAAQ,KAAA,EAAO,CAAC,CAAA,IAAK,CAAC,CAAC,CAAA,CAAA;AAC3N;AAOO,SAAS,cAAc,KAAA,EAA2C;AACrE,EAAA,MAAM,SAAA,GAAY,MAAM,UAAA,CAAW,SAAA;AACnC,EAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,cAAA,IAAkB,EAAC;AAC/C,EAAA,MAAM,OAAA,GAAiB,KAAA,CAAM,IAAA,CAAK,MAAA,IAAU,EAAC;AAC7C,EAAA,MAAM,SAAA,GAAY,kBAAA,CAAmB,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA;AAG/D,EAAA,IAAI,aAAA,GAAgB,mBAAA,CAAoB,OAAA,EAAS,aAAa,CAAA;AAC9D,EAAA,MAAM,GAAA,GAAsB,uBAAA;AAAA,IACxB,SAAA;AAAA,IAAW,OAAA;AAAA,IAAS,aAAA;AAAA,IAAe;AAAA,GACvC;AACA,EAAA,MAAM,MAAA,GAAS,CAAC,EAAA,KAAe,GAAA,CAAI,EAAE,CAAA,EAAG,IAAA;AACxC,EAAA,MAAM,SAAA,GAAY,CAAC,EAAA,KAAe,MAAA,CAAO,EAAE,CAAA,KAAM,cAAA;AACjD,EAAA,MAAM,OAAA,GAAU,CAAC,EAAA,KAAe,SAAA,CAAU,EAAE,CAAA,EAAG,KAAA;AAC/C,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAoB;AAC9C,EAAA,MAAM,aAAA,GAAgB,oBAAoB,SAAS,CAAA;AACnD,EAAA,IAAI,CAAC,aAAA,EAAe;AAChB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2CAAA,EAA8C,SAAS,CAAA,8BAAA,CAAgC,CAAA;AAAA,EAC3G;AACA,EAAA,IAAI,OAAA,CAAQ,QAAQ,CAAA,IAAK,OAAA,CAAQ,KAAK,CAAA,EAAG;AACrC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oEAAA,EAAuE,SAAS,CAAA,EAAA,CAAI,CAAA;AAAA,EACxG;AACA,EAAA,MAAM,eAAA,GAAkB,EAAE,KAAA,EAAO,KAAA,EAAO,eAAe,SAAA,EAAW,GAAA,EAAK,SAAS,MAAA,EAAO;AACvF,EAAA,MAAM,iBAAA,GAAoB,aAAA,CAAc,QAAA,GAAW,eAAe,CAAA;AAClE,EAAA,IAAI,iBAAA,EAAmB;AACnB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,iBAAiB,CAAA,GAAA,EAAM,SAAS,CAAA,EAAA,CAAI,CAAA;AAAA,EACzE;AAEA,EAAA,IAAI,cAAc,WAAA,EAAa;AAC3B,IAAA,OAAO,aAAA,CAAc,YAAY,eAAe,CAAA;AAAA,EACpD;AAEA,EAAA,IAAI,SAAA,KAAc,WAAA,IAAe,SAAA,KAAc,mBAAA,IAAuB,cAAc,mBAAA,EAAqB;AACrG,IAAA,MAAM,WAAW,6BAAA,CAA8B,GAAA,EAAK,eAAe,EAAE,UAAA,EAAY,KAAK,CAAA;AACtF,IAAA,MAAM,WAAA,GAAiC;AAAA,MACnC,WAAW,QAAA,GAAW,EAAE,CAAC,QAAA,CAAS,IAAI,GAAG,EAAE,MAAA,EAAQ,IAAA,IAAO,GAAI,EAAE,GAAG,EAAE,MAAA,EAAQ,MAAK,EAAE;AAAA,MACpF,eAAe,QAAA,EAAU;AAAA,KAC7B;AACA,IAAA,MAAM,WAAW,eAAA,CAAgB,KAAA,CAAM,WAAW,QAAA,EAAU,KAAA,CAAM,WAAW,UAAU,CAAA;AACvF,IAAA,MAAM,OAAA,GAAU;AAAA,MACZ,iBAAA,EAAmB,EAAE,KAAA,EAAO,EAAA,EAAI,QAAQ,EAAA,EAAG;AAAA,MAC3C,QAAA,EAAU,EAAA;AAAA,MAEV,GAAG,iBAAA,CAAkB,QAAA,EAAU,MAAM,UAAA,CAAW,UAAA,EAAY,EAAE;AAAA,KAClE;AACA,IAAA,MAAM,UAAU,qBAAA,CAAsB,GAAA,EAAK,WAAA,EAAa,aAAA,EAAe,UAAU,OAAO,CAAA;AACxF,IAAA,MAAM,cAAA,GAAiB,cAAA;AAAA,MACnB,GAAA;AAAA,MACA,WAAA;AAAA,MACA,SAAA;AAAA,MACA,aAAA;AAAA,MACA,OAAA;AAAA,sBACA,IAAI,GAAA,CAAI,CAAC,KAAK,CAAC;AAAA,KACnB;AACA,IAAA,aAAA,GAAgB,cAAA,CAAe,YAAA;AAC/B,IAAA,cAAA,CAAe,WAAA,CAAY,OAAA,CAAQ,CAAC,UAAA,KAAe;AAC/C,MAAA,aAAA,CAAc,GAAA,CAAI,UAAA,CAAW,KAAA,EAAO,UAAA,CAAW,UAAoB,CAAA;AAAA,IACvE,CAAC,CAAA;AAAA,EACL;AAEA,EAAA,MAAM,UAAU,aAAA,CAAc,WAAA;AAG9B,EAAA,IAAI,KAAA;AACJ,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,WAAA,GAAyC,UAAA;AAC7C,EAAA,IAAI,IAAA,GAAO,KAAA;AAGX,EAAA,MAAM,UAAA,GAAa,SAAA,CAAU,KAAA,GACvB,OAAA,GACA,SAAA,CAAU,SAAS,CAAC,SAAA,CAAU,OAAO,CAAA,GACjC,OAAA,GACA,MAAA;AACV,EAAA,MAAM,YAAA,GAAe,UAAA;AAErB,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAEhB,IAAA,KAAA,GAAQ,SAAA,CAAU,KAAA,GAAQ,OAAA,GAAU,SAAA,CAAU,IAAI,GAAA,GAAM,MAAA;AACxD,IAAA,MAAA,GAAS,SAAA,CAAU,OAAO,MAAA,GAAS,SAAA,CAAU,QAAQ,OAAA,GAAU,SAAA,CAAU,IAAI,GAAA,GAAM,MAAA;AACnF,IAAA,QAAA,GAAW,MAAA;AAAA,EACf,CAAA,MAAA,IAAW,QAAQ,EAAA,EAAI;AACnB,IAAA,KAAA,GAAQ,GAAA;AAAK,IAAA,MAAA,GAAS,GAAA;AAAK,IAAA,IAAA,GAAO,IAAA;AAAM,IAAA,QAAA,GAAW,YAAA;AAAA,EACvD,WAAW,SAAA,CAAU,GAAG,KAAK,CAAC,SAAA,CAAU,GAAG,CAAA,EAAG;AAC1C,IAAA,KAAA,GAAQ,GAAA;AAAK,IAAA,MAAA,GAAS,GAAA;AAAK,IAAA,WAAA,GAAc,YAAA;AAAc,IAAA,QAAA,GAAW,YAAA;AAAA,EACtE,CAAA,MAAO;AACH,IAAA,KAAA,GAAQ,GAAA;AAAK,IAAA,MAAA,GAAS,GAAA;AAAK,IAAA,QAAA,GAAW,YAAA;AAAA,EAC1C;AAEA,EAAA,MAAM,QAAA,GAAW,KAAA,GAAQ,OAAA,CAAQ,KAAK,CAAA,GAAI,MAAA;AAC1C,EAAA,MAAM,SAAA,GAAY,MAAA,GAAS,OAAA,CAAQ,MAAM,CAAA,GAAI,MAAA;AAC7C,EAAA,MAAM,WAAA,GAAc,QAAA,GAAW,OAAA,CAAQ,QAAQ,CAAA,GAAI,MAAA;AACnD,EAAA,MAAM,SAAA,GAAY,QAAQ,YAAY,CAAA;AACtC,EAAA,MAAM,UAAA,GAAa,QAAQ,OAAO,CAAA;AAClC,EAAA,MAAM,SAAA,GAAY,QAAQ,MAAM,CAAA;AAChC,EAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,QAAA,IAAY,EAAE,KAAA,EAAO,GAAA,EAAK,QAAQ,GAAA,EAAI;AACpE,EAAA,MAAM,WAAA,GAAc,SAAA,GACd,qBAAA,CAAsB,aAAA,EAAe,SAAA,EAAW,MAAA,CAAO,MAAM,CAAA,EAAG,IAAA,CAAK,KAAA,EAAO,IAAA,CAAK,MAAM,CAAA,GACvF,MAAA;AACN,EAAA,MAAM,WAA2B,EAAC;AAElC,EAAA,IAAI,CAAC,QAAA,IAAY,CAAC,SAAA,EAAW;AACzB,IAAA,MAAM,IAAI,KAAA;AAAA,MACN,CAAA,sDAAA,EAAyD,SAAS,CAAA,YAAA,EACrD,QAAQ,aAAa,SAAS,CAAA,EAAA;AAAA,KAC/C;AAAA,EACJ;AAEA,EAAA,MAAM,eAAe,SAAA,KAAc,YAAA,IAAgB,UAAU,GAAG,CAAA,IAAK,UAAU,GAAG,CAAA;AAClF,EAAA,IAAI,YAAA,EAAc;AACd,IAAA,IAAA,GAAO,IAAA;AACP,IAAA,KAAA,GAAQ,GAAA;AACR,IAAA,MAAA,GAAS,GAAA;AAAA,EACb;AAGA,EAAA,MAAM,OAA2B,EAAC;AAClC,EAAA,IAAI,cAAA;AACJ,EAAA,IAAI,aAAA;AACJ,EAAA,IAAI,IAAA,EAAM;AACN,IAAA,MAAM,aAAa,WAAA,GAAc,QAAA,CAAS,eAAe,WAAW,CAAA,GAAI,CAAC,SAAS,CAAA;AAClF,IAAA,MAAM,mBAAA,GAAsB,OAAA,CAAQ,WAAA,IAAe,SAAS,CAAA;AAC5D,IAAA,IAAI,mBAAA,EAAqB;AACrB,MAAA,MAAM,gBAAA,GAAmB,YAAY,CAAA,GAAI,CAAA;AACzC,MAAA,MAAM,WAAA,GAAc,UAAA,CAAW,GAAA,CAAI,CAAC,SAAA,KAAc;AAC9C,QAAA,MAAM,IAAA,GAAO,aAAA,CAAc,MAAA,CAAO,CAAC,GAAA,KAAQ,CAAC,WAAA,IAAe,GAAA,CAAI,WAAW,CAAA,KAAM,SAAS,CAAA;AACzF,QAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AACxB,QAAA,OAAO,CAAC,GAAG,IAAI,EAAE,IAAA,CAAK,CAAC,MAAM,KAAA,KAAU;AACnC,UAAA,MAAM,SAAA,GAAY,KAAK,UAAU,CAAA;AACjC,UAAA,MAAM,UAAA,GAAa,MAAM,UAAU,CAAA;AACnC,UAAA,MAAM,UAAA,GAAa,OAAO,SAAS,CAAA;AACnC,UAAA,MAAM,WAAA,GAAc,OAAO,UAAU,CAAA;AACrC,UAAA,IAAI,MAAA,CAAO,SAAS,UAAU,CAAA,IAAK,OAAO,QAAA,CAAS,WAAW,CAAA,EAAG,OAAO,UAAA,GAAa,WAAA;AACrF,UAAA,MAAM,WAAW,IAAI,IAAA,CAAK,OAAO,SAAS,CAAC,EAAE,OAAA,EAAQ;AACrD,UAAA,MAAM,YAAY,IAAI,IAAA,CAAK,OAAO,UAAU,CAAC,EAAE,OAAA,EAAQ;AACvD,UAAA,IAAI,MAAA,CAAO,SAAS,QAAQ,CAAA,IAAK,OAAO,QAAA,CAAS,SAAS,CAAA,EAAG,OAAO,QAAA,GAAW,SAAA;AAC/E,UAAA,OAAO,MAAA,CAAO,SAAS,CAAA,CAAE,aAAA,CAAc,MAAA,CAAO,UAAU,CAAA,EAAG,MAAA,EAAW,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA;AAAA,QAC3F,CAAC,CAAA;AAAA,MACL,CAAC,CAAA;AACD,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,GAAG,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,MAAM,CAAC,CAAA;AACtE,MAAA,cAAA,GAAiB,UAAA,CAAW,GAAA,CAAI,CAAC,SAAA,EAAW,KAAA,MAAW;AAAA,QACnD,IAAA,EAAM,OAAO,SAAS,CAAA;AAAA,QACtB,SAAS,KAAA,GAAQ,gBAAA;AAAA,QACjB,OAAA,EAAS,QAAQ,gBAAA,GAAmB,CAAA;AAAA,QACpC,QAAA,EAAU,WAAA,CAAY,KAAK,CAAA,CAAE,MAAA;AAAA,QAC7B,gBAAA,EAAkB,SAAA,GAAY,KAAA,GAAQ,gBAAA,GAAmB,CAAA,GAAI;AAAA,OACjE,CAAE,CAAA;AACF,MAAA,IAAA,CAAK,IAAA,CAAK,UAAA,CAAW,OAAA,CAAQ,CAAC,SAAA,KAAc;AAAA,QACxC,CAAA,EAAG,MAAA,CAAO,SAAS,CAAC,IAAI,QAAQ,CAAA,CAAA;AAAA,QAChC,CAAA,EAAG,MAAA,CAAO,SAAS,CAAC,IAAI,SAAS,CAAA,CAAA;AAAA,QACjC,GAAI,SAAA,GAAY,CAAC,CAAA,EAAG,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA,GAAI;AAAC,OAC5D,CAAC,CAAA;AACF,MAAA,KAAA,IAAS,QAAA,GAAW,CAAA,EAAG,QAAA,GAAW,QAAA,EAAU,YAAY,CAAA,EAAG;AACvD,QAAA,IAAA,CAAK,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,CAAC,IAAA,KAAS;AACpC,UAAA,MAAM,GAAA,GAAM,KAAK,QAAQ,CAAA;AACzB,UAAA,IAAI,CAAC,KAAK,OAAO,IAAI,MAAM,gBAAgB,CAAA,CAAE,KAAK,IAAI,CAAA;AACtD,UAAA,OAAO;AAAA,YACH,IAAI,QAAQ,CAAA;AAAA,YACZ,MAAA,CAAO,GAAA,CAAI,SAAS,CAAC,CAAA;AAAA,YACrB,GAAI,SAAA,GAAY,CAAC,WAAA,EAAa,GAAA,CAAI,GAAA,CAAI,SAAS,CAAC,CAAA,IAAK,CAAC,CAAA,GAAI;AAAC,WAC/D;AAAA,QACJ,CAAC,CAAC,CAAA;AAAA,MACN;AAAA,IACJ,CAAA,MAAO;AACH,MAAA,IAAA,CAAK,IAAA,CAAK,CAAC,QAAA,EAAU,SAAS,CAAC,CAAA;AAC/B,MAAA,MAAM,IAAA,GAAO,aACP,CAAC,GAAG,aAAa,CAAA,CAAE,IAAA,CAAK,CAAC,IAAA,EAAM,KAAA,KAAU;AACvC,QAAA,MAAM,SAAA,GAAY,KAAK,UAAU,CAAA;AACjC,QAAA,MAAM,UAAA,GAAa,MAAM,UAAU,CAAA;AACnC,QAAA,MAAM,UAAA,GAAa,OAAO,SAAS,CAAA;AACnC,QAAA,MAAM,WAAA,GAAc,OAAO,UAAU,CAAA;AACrC,QAAA,IAAI,MAAA,CAAO,SAAS,UAAU,CAAA,IAAK,OAAO,QAAA,CAAS,WAAW,CAAA,EAAG,OAAO,UAAA,GAAa,WAAA;AACrF,QAAA,MAAM,WAAW,IAAI,IAAA,CAAK,OAAO,SAAS,CAAC,EAAE,OAAA,EAAQ;AACrD,QAAA,MAAM,YAAY,IAAI,IAAA,CAAK,OAAO,UAAU,CAAC,EAAE,OAAA,EAAQ;AACvD,QAAA,IAAI,MAAA,CAAO,SAAS,QAAQ,CAAA,IAAK,OAAO,QAAA,CAAS,SAAS,CAAA,EAAG,OAAO,QAAA,GAAW,SAAA;AAC/E,QAAA,OAAO,MAAA,CAAO,SAAS,CAAA,CAAE,aAAA,CAAc,MAAA,CAAO,UAAU,CAAA,EAAG,MAAA,EAAW,EAAE,OAAA,EAAS,IAAA,EAAM,CAAA;AAAA,MAC3F,CAAC,CAAA,GACC,aAAA;AACN,MAAA,KAAA,MAAW,KAAK,IAAA,EAAM;AAClB,QAAA,MAAM,CAAA,GAAI,EAAE,QAAQ,CAAA;AACpB,QAAA,MAAM,CAAA,GAAI,EAAE,SAAS,CAAA;AACrB,QAAA,IAAI,CAAA,IAAK,IAAA,IAAQ,CAAA,IAAK,IAAA,EAAM;AAC5B,QAAA,IAAA,CAAK,KAAK,CAAC,CAAA,EAAW,MAAA,CAAO,CAAC,CAAC,CAAC,CAAA;AAAA,MACpC;AAAA,IACJ;AAAA,EACJ,CAAA,MAAO;AACH,IAAA,IAAI,UAAA,GAAa,QAAA,CAAS,aAAA,EAAe,QAAQ,CAAA;AACjD,IAAA,MAAM,gBAAA,GAAmB,aAAA,CAAc,GAAA,CAAI,QAAQ,CAAA;AACnD,IAAA,IAAI,kBAAkB,UAAA,GAAa,gBAAA;AACnC,IAAA,IAAI,SAAA,KAAc,YAAA,IAAgB,SAAA,KAAc,YAAA,EAAc;AAC1D,MAAA,IAAI,MAAA,CAAO,KAAM,CAAA,KAAM,UAAA,EAAY;AAC/B,QAAA,UAAA,GAAa,CAAC,GAAG,UAAU,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAI,IAAA,CAAK,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,OAAA,EAAQ,GAAI,IAAI,IAAA,CAAK,OAAO,CAAC,CAAC,CAAA,CAAE,OAAA,EAAS,CAAA;AAAA,MAC7G,CAAA,MAAA,IAAW,MAAA,CAAO,KAAM,CAAA,KAAM,cAAA,EAAgB;AAC1C,QAAA,UAAA,GAAa,CAAC,GAAG,UAAU,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,MAAA,CAAO,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MACrE;AAAA,IACJ;AACA,IAAA,IAAI,aAAa,WAAA,GAAc,QAAA,CAAS,eAAe,WAAW,CAAA,GAAI,CAAC,SAAS,CAAA;AAChF,IAAA,IAAI,WAAA,KAAgB,SAAA,KAAc,mBAAA,IAAuB,SAAA,KAAc,WAAA,CAAA,EAAc;AACjF,MAAA,UAAA,GAAa,CAAC,GAAG,UAAU,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,MAAM,MAAA,CAAO,CAAC,EAAE,aAAA,CAAc,MAAA,CAAO,CAAC,CAAA,EAAG,MAAA,EAAW,EAAE,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA;AAC5G,MAAA,IAAI,WAAA,KAAgB,UAAA,EAAY,UAAA,CAAW,OAAA,EAAQ;AAAA,IACvD;AACA,IAAA,MAAM,aAAa,SAAA,GAAY,QAAA,CAAS,aAAA,EAAe,SAAS,IAAI,EAAC;AACrE,IAAA,MAAM,oBAAoB,SAAA,GACpB,aAAA,CAAc,MAAA,CAAkF,CAAC,QAAQ,GAAA,KAAQ;AAC/G,MAAA,MAAM,WAAA,GAAe,WAAA,GAAc,GAAA,CAAI,WAAW,CAAA,GAAI,SAAA;AACtD,MAAA,MAAM,SAAA,GAAY,IAAI,SAAS,CAAA;AAC/B,MAAA,MAAM,GAAA,GAAM,GAAG,MAAA,CAAO,WAAW,CAAC,CAAA,CAAA,EAAS,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAC5D,MAAA,IAAI,CAAC,OAAO,IAAA,CAAK,CAAC,eAAe,UAAA,CAAW,GAAA,KAAQ,GAAG,CAAA,EAAG;AACtD,QAAA,MAAA,CAAO,IAAA,CAAK;AAAA,UACR,GAAA;AAAA,UACA,KAAA,EAAO,WAAA,GAAc,CAAA,EAAG,MAAA,CAAO,WAAW,CAAC,CAAA,QAAA,EAAM,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA,GAAK,MAAA,CAAO,SAAS,CAAA;AAAA,UACvF,WAAA;AAAA,UACA;AAAA,SACH,CAAA;AAAA,MACL;AACA,MAAA,OAAO,MAAA;AAAA,IACX,GAAG,EAAE,IACH,UAAA,CAAW,GAAA,CAAI,CAAC,WAAA,MAAiB;AAAA,MAC/B,GAAA,EAAK,OAAO,WAAW,CAAA;AAAA,MACvB,KAAA,EAAO,OAAO,WAAW,CAAA;AAAA,MACzB,WAAA;AAAA,MACA,SAAA,EAAW;AAAA,KACf,CAAE,CAAA;AACN,IAAA,MAAM,gBAAgB,OAAA,CAAQ,WAAW,CAAA,IAClC,MAAA,CAAO,QAAS,CAAA,KAAM,SAAA;AAC7B,IAAA,MAAM,mBAAA,GAAsB,aAAA,GACtB,UAAA,CAAW,GAAA,CAAI,MAAM,EAAE,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAA,GAC7C,EAAC;AACP,IAAA,MAAM,aAAA,GAAgB,oBAAoB,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,mBAAmB,CAAA,GAAI,CAAA;AAC1F,IAAA,MAAM,aAAA,GAAgB,oBAAoB,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,mBAAmB,CAAA,GAAI,CAAA;AAC1F,IAAA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAAgB;AACxC,MAAA,MAAM,YAAA,GAAe,OAAO,KAAK,CAAA;AACjC,MAAA,MAAM,CAAA,GAAI,MAAA,CAAO,QAAA,CAAS,YAAY,CAAA,IAAK,kBAAkB,aAAA,GAAA,CACtD,YAAA,GAAe,aAAA,KAAkB,aAAA,GAAgB,aAAA,CAAA,GAClD,GAAA;AACN,MAAA,OAAO,gBAAA,CAAiB,SAAA,EAAW,SAAA,EAAW,CAAC,CAAA;AAAA,IACnD,CAAA;AACA,IAAA,IAAI,aAAA,EAAe;AACf,MAAA,aAAA,GAAgB,iBAAA,CAAkB,GAAA,CAAI,CAAC,UAAA,MAAgB;AAAA,QACnD,KAAA,EAAO,kBAAA,CAAmB,UAAA,CAAW,WAAW;AAAA,OACpD,CAAE,CAAA;AAAA,IACN;AACA,IAAA,IAAI,SAAA,EAAW;AACX,MAAA,aAAA,GAAgB,iBAAA,CAAkB,GAAA,CAAI,CAAC,UAAA,MAAgB;AAAA,QACnD,KAAA,EAAO,mBAAA,CAAoB,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAA,CAAW,OAAA,CAAQ,UAAA,CAAW,WAAW,CAAC,CAAA,GAAI,mBAAA,CAAoB,MAAM,CAAA;AAAA,QAC/G,WAAW,UAAA,CAAW,OAAA,CAAQ,WAAW,SAAS,CAAA,KAAM,IAAI,YAAA,GAAe;AAAA,OAC/E,CAAE,CAAA;AAAA,IACN;AAGA,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,MAAO,CAAA,EAAG,kBAAA,IAAsB,KAAA;AAChD,IAAA,MAAM,GAAA,uBAAU,GAAA,EAA4C;AAC5D,IAAA,KAAA,MAAW,KAAK,aAAA,EAAe;AAC3B,MAAA,MAAM,EAAA,GAAK,EAAE,QAAQ,CAAA;AACrB,MAAA,IAAI,MAAM,IAAA,EAAM;AAChB,MAAA,MAAM,WAAA,GAAc,WAAA,GAAc,CAAA,CAAE,WAAW,CAAA,GAAI,SAAA;AACnD,MAAA,MAAM,EAAA,GAAK,SAAA,GACL,CAAA,EAAG,MAAA,CAAO,WAAW,CAAC,CAAA,CAAA,EAAS,MAAA,CAAO,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA,CAAA,GACnD,WAAA;AACN,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,CAAA,CAAE,SAAS,CAAC,CAAA;AAC/B,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AAC3B,MAAA,MAAM,GAAA,GAAM,GAAG,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAS,MAAA,CAAO,EAAE,CAAC,CAAA,CAAA;AAC5C,MAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,GAAG,KAAK,EAAE,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,CAAA,EAAE;AAC7C,MAAA,CAAA,CAAE,GAAA,IAAO,GAAA;AAAK,MAAA,CAAA,CAAE,KAAA,IAAS,CAAA;AAAG,MAAA,GAAA,CAAI,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,IAC9C;AACA,IAAA,MAAM,OAAA,GAAU,CAAC,EAAA,EAAU,EAAA,KAAmB;AAC1C,MAAA,MAAM,CAAA,GAAI,GAAA,CAAI,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,EAAE,CAAC,CAAA,EAAA,EAAS,MAAA,CAAO,EAAE,CAAC,CAAA,CAAE,CAAA;AACpD,MAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,MAAA,OAAO,QAAQ,SAAA,GAAY,CAAA,CAAE,GAAA,GAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,GAAA;AAAA,IACnD,CAAA;AAEA,IAAA,IAAI,YAAA,GAAe,iBAAA,CAAkB,GAAA,CAAI,CAAC,eAAe,UAAA,CAAW,GAAA,CAAI,CAAC,QAAA,KAAa,OAAA,CAAQ,QAAA,EAAU,UAAA,CAAW,GAAG,CAAC,CAAC,CAAA;AACxH,IAAA,IAAI,SAAA,KAAc,YAAA,IAAgB,SAAA,KAAc,YAAA,EAAc;AAC1D,MAAA,YAAA,GAAe,YAAA,CAAa,IAAI,kBAAkB,CAAA;AAAA,IACtD;AACA,IAAA,IAAI,SAAA,KAAc,gBAAgB,MAAA,CAAO,KAAM,MAAM,cAAA,IAAkB,UAAA,CAAW,SAAS,CAAA,EAAG;AAC1F,MAAA,MAAM,OAAA,GAAU,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AACrC,MAAA,MAAM,WAAA,GAAc,KAAK,GAAA,CAAI,EAAA,EAAI,KAAK,GAAA,CAAI,EAAA,EAAI,UAAA,CAAW,MAAM,CAAC,CAAA;AAChE,MAAA,MAAM,OAAA,GAAU,QAAQ,CAAC,CAAA;AACzB,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA;AAC1C,MAAA,MAAM,UAAU,KAAA,CAAM,IAAA;AAAA,QAClB,EAAE,QAAQ,WAAA,EAAY;AAAA,QACtB,CAAC,MAAA,EAAQ,KAAA,KAAU,UAAW,KAAA,IAAS,WAAA,GAAc,MAAO,OAAA,GAAU,OAAA;AAAA,OAC1E;AACA,MAAA,YAAA,GAAe,YAAA,CAAa,GAAA,CAAI,CAAC,MAAA,KAAW;AACxC,QAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,QAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM;AACtB,UAAA,OAAO,KAAA,GAAQ,QAAQ,MAAA,GAAS,CAAA,IAAK,QAAQ,KAAK,CAAA,GAAI,GAAG,KAAA,IAAS,CAAA;AAClE,UAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,CAAC,CAAA;AAClC,UAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAK,CAAA,GAAI,QAAQ,IAAI,CAAA;AAC1C,UAAA,MAAM,IAAI,IAAA,KAAS,CAAA,GAAI,KAAK,CAAA,GAAI,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA;AACjD,UAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,IAAI,CAAC,CAAA;AACrC,UAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,KAAK,CAAC,CAAA;AACvC,UAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,SAAU,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,GAAI,UAAA,GAAa,IAAA;AACnF,UAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,UAAU,GAAG,OAAO,SAAA;AACzC,UAAA,OAAO,SAAA,GAAA,CAAa,aAAa,SAAA,IAAa,CAAA;AAAA,QAClD,CAAC,CAAA;AAAA,MACL,CAAC,CAAA;AACD,MAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,KAAA,CAAM,IAAA;AAAA,QAC7B,EAAE,QAAQ,CAAA,EAAE;AAAA,QACZ,CAAC,QAAQ,KAAA,KAAU;AAAA,UACf,IAAA,CAAK,KAAA,CAAO,KAAA,GAAQ,CAAA,IAAM,cAAc,CAAA,CAAE,CAAA;AAAA,UAC1C,MAAA,CAAA,CAAQ,UAAW,KAAA,GAAQ,CAAA,IAAM,UAAU,OAAA,CAAA,EAAU,WAAA,CAAY,CAAC,CAAC;AAAA;AACvE,OACH,CAAA;AACD,MAAA,UAAA,GAAa,OAAA,CAAQ,IAAI,CAAC,MAAA,EAAQ,UAAU,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA,IAAK,EAAE,CAAA;AAAA,IAC3E;AACA,IAAA,IAAA,CAAK,IAAA,CAAK,CAAC,QAAA,EAAU,GAAG,iBAAA,CAAkB,GAAA,CAAI,CAAC,UAAA,KAAe,UAAA,CAAW,KAAK,CAAC,CAAC,CAAA;AAChF,IAAA,KAAA,IAAS,gBAAgB,CAAA,EAAG,aAAA,GAAgB,UAAA,CAAW,MAAA,EAAQ,iBAAiB,CAAA,EAAG;AAC/E,MAAA,IAAA,CAAK,IAAA,CAAK;AAAA,QACN,MAAA,CAAO,UAAA,CAAW,aAAa,CAAC,CAAA;AAAA,QAChC,GAAG,YAAA,CAAa,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,CAAC;AAAA,OACxD,CAAA;AAAA,IACL;AAAA,EACJ;AAGA,EAAA,IAAI,iBAAiB,WAAA,KAAgB,YAAA,IAAgB,QAAQ,UAAA,GACvD,OAAA,CAAQ,aACR,OAAA,CAAQ,QAAA;AACd,EAAA,IAAI,cAAc,cAAA,GAAiB,gBAAA;AACnC,EAAA,IAAI,SAAA,KAAc,0BAA0B,cAAA,GAAiB,gBAAA;AAC7D,EAAA,IAAI,SAAA,KAAc,cAAA,IAAkB,SAAA,EAAW,cAAA,GAAiB,QAAA;AAChE,EAAA,IAAI,SAAA,KAAc,YAAA,IAAgB,WAAA,EAAa,cAAA,GAAiB,aAAA;AAChE,EAAA,IAAI,SAAA,KAAc,eAAe,WAAA,EAAa;AAC1C,IAAA,cAAA,GAAiB,WAAA,KAAgB,eAAe,YAAA,GAAe,eAAA;AAAA,EACnE;AACA,EAAA,MAAM,WAAA,GAAc,YAAA,CAAa,IAAA,CAAK,cAAc,CAAA;AACpD,EAAA,MAAM,cAAA,GAAiB,kBAAA,CAAmB,IAAA,CAAK,cAAc,CAAA;AAC7D,EAAA,MAAM,eAAe,iBAAA,CAAkB,MAAA,GAAS,IAAI,MAAM,CAAA,EAAG,SAAS,MAAS,CAAA;AAC/E,EAAA,MAAM,QAAA,GAA0B,SAAA;AAEhC,EAAA,MAAM,IAAA,GAA6B;AAAA,IAC/B,MAAA,EAAQ,sBAAA;AAAA,IACR,IAAA,EAAM,OAAA;AAAA,IACN,SAAA,EAAW,cAAA;AAAA,IACX,KAAA,EAAO,CAAA,EAAG,SAAS,CAAA,IAAA,EAAO,QAAQ,CAAA,CAAA;AAAA,IAClC,QAAA;AAAA,IACA,MAAA,EAAQ,cAAA;AAAA,IACR,aAAA;AAAA,IACA,WAAA,EAAa,SAAA,KAAc,cAAA,IAAkB,SAAA,GAAY,EAAA,GAAK,MAAA;AAAA,IAC9D,kBAAkB,SAAA,KAAc,aAAA,GAC1B,IAAA,CAAK,GAAA,CAAI,IAAI,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,MAAA,CAAO,MAAM,UAAA,CAAW,eAAA,EAAiB,eAAe,EAAE,CAAC,CAAC,CAAA,GACtF,MAAA;AAAA,IACN,IAAA;AAAA,IACA,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,QAAA;AAAA,IACA,QAAQ,EAAE,SAAA,EAAW,UAAU,SAAA,EAAW,WAAA,EAAa,aAAa,IAAA;AAAK,GAC7E;AAEA,EAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ;AACjB,IAAA,MAAM,aAAA,GAAgB,aAAA,CACjB,GAAA,CAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAA,CAAI,SAAS,CAAC,CAAC,CAAA,CACnC,MAAA,CAAO,OAAO,QAAQ,CAAA;AAC3B,IAAA,MAAM,cAAA,GAAiB,cAAc,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,aAAa,CAAA,GAAI,MAAA;AAC/E,IAAA,MAAM,cAAA,GAAiB,cAAc,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,CAAI,GAAG,aAAa,CAAA,GAAI,MAAA;AAC/E,IAAA,MAAM,kBAAA,GAAqB,SAAA,KAAc,YAAA,IAAgB,cAAA,KAAmB,UAAa,cAAA,KAAmB,MAAA,GACtG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,cAAA,GAAA,CAAkB,cAAA,GAAiB,cAAA,IAAkB,IAAI,CAAA,GACrE,MAAA;AACN,IAAA,MAAM,aAAA,GAAgB,cAAA,GAChB,kBAAA,CAAmB,aAAA,CAAc,IAAI,CAAC,GAAA,KAAQ,MAAA,CAAO,GAAA,CAAI,QAAQ,CAAC,CAAC,CAAC,IACpE,EAAC;AACP,IAAA,MAAM,aAAA,GAAgB,cAAA,GAChB,kBAAA,CAAmB,aAAa,IAChC,EAAC;AACP,IAAA,IAAA,CAAK,YAAA,GAAe;AAAA,MAChB,KAAA,EAAO,QAAA;AAAA,MACP,aAAA,EAAe,gBAAgB,YAAA,IAAgB,IAAA,CAAK,SAAS,EAAA,GACvD,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,IAAI,EAAA,EAAA,CAAM,IAAA,CAAK,SAAS,EAAA,KAAO,IAAA,CAAK,SAAS,CAAA,CAAA,GAAM,IAAI,CAAC,CAAA,GACzE,MAAA;AAAA,MACN,gBAAA,EAAkB,WAAA,KAAgB,UAAA,IAAc,MAAA,CAAO,KAAM,CAAA,KAAM,UAAA,GAC7D,oBAAA,CAAqB,IAAA,CAAK,MAAA,GAAS,CAAA,EAAG,IAAA,CAAK,KAAK,CAAA,GAChD,MAAA;AAAA,MACN,gBAAA,EAAkB,WAAA,KAAgB,YAAA,IAAgB,MAAA,CAAO,KAAM,CAAA,KAAM,UAAA;AAAA,MACrE,GAAG;AAAA,KACP;AACA,IAAA,IAAA,CAAK,SAAA,GAAY;AAAA,MACb,KAAA,EAAO,SAAA;AAAA,MACP,YAAA;AAAA,MACA,YAAA,EAAc,SAAA,KAAc,YAAA,GAAe,CAAA,GAAI,kBAAA;AAAA,MAC/C,GAAG;AAAA,KACP;AAAA,EACJ;AACA,EAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA,GAChB,EAAE,OAAA,EAAS,IAAA,EAAM,UAAU,OAAA,EAAQ,GACnC,eAAe,SAAA,GACX,EAAE,SAAS,IAAA,EAAM,QAAA,EAAU,UAAS,GACpC,EAAE,SAAS,KAAA,EAAM;AAC3B,EAAA,IAAI,WAAA,OAAkB,QAAA,GAAW,EAAA;AACjC,EAAA,IAAI,cAAc,mBAAA,EAAqB;AACnC,IAAA,MAAM,WAAA,GAAc,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAC,CAAA,CAAE,SAAS,CAAC,CAAA;AAClD,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,GAAA,EAAA,CAAM,cAAA,CAAe,WAAW,QAAQ,CAAA,GAAI,EAAA,GAAK,EAAA,IAAM,WAAW,CAAA;AAC3F,IAAA,IAAA,CAAK,OAAA,GAAU,CAAA;AAAA,EACnB;AAEA,EAAA,OAAO,IAAA;AACX;;;AC7jBO,IAAM,qBAAA,GAAwB;AAE9B,IAAM,2BAAA,GAA8B;AAAA,EACvC,MAAA;AAAA,EACA,aAAA;AAAA,EACA,cAAA;AAAA,EACA,YAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,iBAAA;AAAA,EACA,eAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA;AACJ;AAEA,IAAM,mBAAA,GAAsB,IAAI,GAAA,CAAY,2BAA2B,CAAA;AAiBhE,SAAS,kBAAkB,KAAA,EAAuB;AACrD,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA,IAAK,QAAQ,CAAA,EAAG;AACvC,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,IAAI,YAAY,KAAA,GAAQ,CAAA;AACxB,EAAA,OAAO,YAAY,CAAA,EAAG;AAClB,IAAA,MAAM,KAAA,GAAA,CAAS,YAAY,CAAA,IAAK,EAAA;AAChC,IAAA,MAAA,GAAS,MAAA,CAAO,YAAA,CAAa,EAAA,GAAK,KAAK,CAAA,GAAI,MAAA;AAC3C,IAAA,SAAA,GAAY,IAAA,CAAK,KAAA,CAAA,CAAO,SAAA,GAAY,CAAA,IAAK,EAAE,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,MAAA;AACX;AAEO,SAAS,qBAAqB,KAAA,EAAuC;AACxE,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACrC,IAAA,MAAM,IAAI,MAAM,mCAAmC,CAAA;AAAA,EACvD;AACA,EAAA,MAAM,IAAA,GAAO,KAAA;AACb,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,qBAAA,IAAyB,IAAA,CAAK,SAAS,OAAA,EAAS;AAChE,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,WAAA,EAAc,qBAAqB,CAAA,gBAAA,CAAkB,CAAA;AAAA,EACzE;AACA,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,EAAA,IAAI,OAAO,SAAA,KAAc,QAAA,IAAY,CAAC,mBAAA,CAAoB,GAAA,CAAI,SAAS,CAAA,EAAG;AACtE,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,OAAO,IAAA,CAAK,SAAS,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,EAC9E;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,KAAa,SAAA,IAAa,IAAA,CAAK,aAAa,MAAA,EAAQ;AACzD,IAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AAAA,EACtE;AACA,EAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,IAAK,IAAA,CAAK,KAAK,MAAA,GAAS,CAAA,IAAK,KAAK,IAAA,CAAK,IAAA,CAAK,CAAC,GAAA,KAAQ,CAAC,MAAM,OAAA,CAAQ,GAAG,CAAC,CAAA,EAAG;AACnG,IAAA,MAAM,IAAI,MAAM,sEAAsE,CAAA;AAAA,EAC1F;AACA,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,MAAM,CAAC,CAAA;AAC9D,EAAA,IAAI,UAAU,CAAA,EAAG;AACb,IAAA,MAAM,IAAI,MAAM,wDAAwD,CAAA;AAAA,EAC5E;AACA,EAAA,MAAM,IAAA,GAAO,KAAK,IAAA,CAAK,MAAA;AACvB,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AAChC,IAAA,MAAM,MAAA,GAAS,IAAI,KAAA,EAAM;AACzB,IAAA,OAAO,MAAA,CAAO,MAAA,GAAS,OAAA,EAAS,MAAA,CAAO,KAAK,IAAI,CAAA;AAChD,IAAA,OAAO,MAAA;AAAA,EACX,CAAC,CAAA;AACD,EAAA,MAAM,WAAA,GAAc,mBAAA,CAAoB,IAAA,CAAK,SAAS,IAChD,CAAA,GACA,IAAA,CAAK,MAAA,EAAQ,MAAA,KAAW,IAAA,CAAK,QAAA,KAAa,MAAA,GAAS,IAAA,GAAO,IAAI,OAAA,GAAU,CAAA,CAAA;AAE9E,EAAA,OAAO;AAAA,IACH,IAAA;AAAA,IACA,IAAA;AAAA,IACA,IAAA;AAAA,IACA,OAAA;AAAA,IACA,SAAS,CAAA,GAAA,EAAM,iBAAA,CAAkB,UAAU,CAAC,CAAC,GAAG,IAAI,CAAA,CAAA;AAAA,IACpD,SAAA;AAAA,IACA,WAAA,EAAa,mBAAA,CAAoB,IAAA,CAAK,SAAS,CAAA;AAAA,IAC/C,QAAA,EAAU,QAAA,CAAS,IAAA,CAAK,SAAS,CAAA;AAAA,IACjC,OAAA,EAAS,CAAC,uCAAA,CAAwC,IAAA,CAAK,SAAS,CAAA;AAAA,IAChE,KAAA,EAAO,aAAA,CAAc,IAAA,CAAK,SAAS,CAAA;AAAA,IACnC,MAAA,EAAQ,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA;AAAA,IAC9B;AAAA,GACJ;AACJ;;;ACnFA,SAAS,QAAA,CAAS,UAAwC,IAAA,EAA+B;AACrF,EAAA,MAAM,MAAA,GAAS,cAAc,QAAQ,CAAA,CAAA;AACrC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,KAAK,KAAA,EAAO;AACZ,IAAA,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA,cAAA,EAAiB,KAAK,SAAA,CAAU,IAAA,CAAK,KAAK,CAAC,CAAA,CAAA,CAAG,CAAA;AACpE,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,MAAM,CAAA,sBAAA,CAAwB,CAAA;AAAA,EAClD;AACA,EAAA,IAAI,IAAA,CAAK,YAAA,EAAc,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,MAAM,CAAA,gBAAA,EAAmB,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,YAAY,CAAC,CAAA,CAAA,CAAG,CAAA;AACpG,EAAA,IAAI,IAAA,CAAK,aAAA,KAAkB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA,oBAAA,EAAuB,IAAA,CAAK,aAAa,CAAA,CAAA,CAAG,CAAA;AACxG,EAAA,IAAI,IAAA,CAAK,gBAAA,KAAqB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA,oBAAA,EAAuB,IAAA,CAAK,gBAAgB,CAAA,CAAA,CAAG,CAAA;AAC9G,EAAA,IAAI,IAAA,CAAK,gBAAA,KAAqB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA,oBAAA,EAAuB,IAAA,CAAK,gBAAgB,CAAA,CAAA,CAAG,CAAA;AAC9G,EAAA,IAAI,IAAA,CAAK,YAAA,KAAiB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA,WAAA,EAAc,IAAA,CAAK,YAAY,CAAA,CAAA,CAAG,CAAA;AAC7F,EAAA,IAAI,IAAA,CAAK,YAAA,KAAiB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA,WAAA,EAAc,IAAA,CAAK,YAAY,CAAA,CAAA,CAAG,CAAA;AAC7F,EAAA,IAAI,IAAA,CAAK,SAAA,KAAc,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,KAAK,MAAM,CAAA,aAAA,EAAgB,IAAA,CAAK,SAAS,CAAA,CAAA,CAAG,CAAA;AACzF,EAAA,OAAO,KAAA;AACX;AAEA,SAAS,cAAc,KAAA,EAAmC;AACtD,EAAA,MAAM,QAAQ,KAAA,IAAS,CAAA;AACvB,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,IAAK,SAAS,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,yCAAyC,CAAA;AACpG,EAAA,OAAO,KAAA;AACX;AAEO,SAAS,gBAAA,CAAiB,KAAA,EAAgB,OAAA,GAAkC,EAAC,EAAsB;AACtG,EAAA,MAAM,QAAA,GAAW,qBAAqB,KAAK,CAAA;AAC3C,EAAA,MAAM,EAAE,MAAK,GAAI,QAAA;AACjB,EAAA,MAAM,YAAA,GAAe,QAAQ,YAAA,IAAgB,kBAAA;AAC7C,EAAA,IAAI,CAAC,oBAAA,CAAqB,IAAA,CAAK,YAAY,CAAA,EAAG;AAC1C,IAAA,MAAM,IAAI,MAAM,+DAA+D,CAAA;AAAA,EACnF;AACA,EAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,IAAS,GAAA;AAC5B,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,IAAU,GAAA;AAC9B,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,OAAA,CAAQ,KAAK,CAAA;AACzC,EAAA,MAAM,aAAa,IAAA,CAAK,KAAA,CAAM,KAAA,IAAS,EAAA,GAAK,MAAM,KAAK,CAAA;AACvD,EAAA,MAAM,cAAc,IAAA,CAAK,KAAA,CAAM,MAAA,IAAU,EAAA,GAAK,MAAM,KAAK,CAAA;AACzD,EAAA,MAAM,KAAA,GAAQ;AAAA,IACV,kBAAkB,YAAY,CAAA,WAAA,CAAA;AAAA,IAC9B;AAAA,GACJ;AAEA,EAAA,IAAI,QAAQ,cAAA,EAAgB;AACxB,IAAA,KAAA,CAAM,IAAA;AAAA,MACF,oCAAA;AAAA,MACA,2DAAA;AAAA,MACA,yBAAA;AAAA,MACA,0EAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAEA,EAAA,KAAA,CAAM,IAAA;AAAA,IACF,CAAA,iBAAA,EAAoB,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,IACjD,CAAA,mCAAA,EAAsC,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,OAAO,CAAC,CAAA,EAAA,CAAA;AAAA,IACtE,0DAAA;AAAA,IACA,mFAAmF,QAAA,CAAS,QAAQ,CAAA,uCAAA,EAA0C,CAAC,SAAS,WAAW,CAAA,oBAAA,CAAA;AAAA,IACnK,MAAA;AAAA,IACA,8BAAA;AAAA,IACA,CAAA,iCAAA,EAAoC,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,SAAS,CAAC,CAAA,aAAA,EAAgB,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,QAAQ,CAAC,CAAA,EAAA;AAAA,GACvH;AAEA,EAAA,IAAI,IAAA,CAAK,QAAQ,MAAA,EAAQ;AACrB,IAAA,KAAA,CAAM,IAAA,CAAK,iCAAiC,yBAAyB,CAAA;AACrE,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,kCAAA,EAAqC,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,oDAAA,CAAsD,CAAA;AACxH,IAAA,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,CAAC,OAAA,EAAS,KAAA,KAAU;AACpC,MAAA,KAAA,CAAM,IAAA;AAAA,QACF,wBAAwB,KAAK,CAAA,SAAA,EAAY,KAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,QACrE,wBAAwB,KAAK,CAAA,4CAAA,EAA+C,QAAQ,OAAO,CAAA,EAAA,EAAK,QAAQ,QAAQ,CAAA,MAAA,CAAA;AAAA,QAChH,wBAAwB,KAAK,CAAA,uCAAA,EAA0C,QAAQ,OAAO,CAAA,EAAA,EAAK,QAAQ,QAAQ,CAAA,MAAA;AAAA,OAC/G;AACA,MAAA,IAAI,OAAA,CAAQ,qBAAqB,MAAA,EAAW;AACxC,QAAA,KAAA,CAAM,IAAA,CAAK,wBAAwB,KAAK,CAAA,4CAAA,EAA+C,QAAQ,gBAAgB,CAAA,EAAA,EAAK,OAAA,CAAQ,QAAQ,CAAA,MAAA,CAAQ,CAAA;AAAA,MAChJ;AAAA,IACJ,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,IAAA;AAAA,MACF,CAAA,2DAAA,EAA8D,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,eAAA,CAAA;AAAA,MAChF,6CAAA;AAAA,MACA,2BAAA;AAAA,MACA;AAAA,KACJ;AAAA,EACJ;AAEA,EAAA,KAAA,CAAM,KAAK,CAAA,gBAAA,EAAmB,KAAK,CAAA,CAAA,CAAA,EAAK,CAAA,iBAAA,EAAoB,MAAM,CAAA,CAAA,CAAG,CAAA;AACrE,EAAA,IAAI,KAAK,KAAA,EAAO;AACZ,IAAA,KAAA,CAAM,IAAA,CAAK,wBAAwB,IAAA,CAAK,SAAA,CAAU,KAAK,KAAK,CAAC,KAAK,+BAA+B,CAAA;AAAA,EACrG;AACA,EAAA,IAAI,KAAK,MAAA,EAAQ;AACb,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,yBAAA,EAA4B,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAAA,CAAG,CAAA;AAC7D,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,IAAA,CAAK,OAAO,QAAA,EAAU;AAC7C,MAAA,KAAA,CAAM,IAAA,CAAK,6BAA6B,IAAA,CAAK,SAAA,CAAU,KAAK,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAA,CAAG,CAAA;AAAA,IACnF;AAAA,EACJ;AACA,EAAA,IAAI,KAAK,UAAA,EAAY;AACjB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,6BAAA,EAAgC,IAAA,CAAK,UAAA,CAAW,OAAO,CAAA,CAAA,CAAG,CAAA;AACrE,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,CAAA,8BAAA,EAAiC,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAC,CAAA,CAAA,CAAG,CAAA;AACrH,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,YAAA,EAAc,KAAA,CAAM,IAAA,CAAK,CAAA,kCAAA,EAAqC,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,UAAA,CAAW,YAAY,CAAC,CAAA,CAAA,CAAG,CAAA;AACjI,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,SAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,uCAAA,EAA0C,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,UAAA,CAAW,SAAS,CAAC,CAAA,CAAA,CAAG,CAAA;AAChI,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,QAAA,KAAa,MAAA,EAAW,KAAA,CAAM,KAAK,CAAA,sCAAA,EAAyC,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,EAC/H;AACA,EAAA,IAAI,SAAS,OAAA,EAAS;AAClB,IAAA,IAAI,IAAA,CAAK,cAAc,KAAA,CAAM,IAAA,CAAK,GAAG,QAAA,CAAS,cAAA,EAAgB,IAAA,CAAK,YAAY,CAAC,CAAA;AAChF,IAAA,IAAI,IAAA,CAAK,WAAW,KAAA,CAAM,IAAA,CAAK,GAAG,QAAA,CAAS,WAAA,EAAa,IAAA,CAAK,SAAS,CAAC,CAAA;AAAA,EAC3E;AAEA,EAAA,KAAA,CAAM,IAAA,CAAK,2BAA2B,IAAA,CAAK,SAAA,CAAU,KAAK,aAAA,IAAiB,EAAE,CAAC,CAAA,CAAA,CAAG,CAAA;AACjF,EAAA,KAAA,CAAM,KAAK,CAAA,8BAAA,EAAiC,QAAA,CAAS,WAAW,CAAA,eAAA,CAAA,EAAmB,qDAAqD,0CAA0C,CAAA;AAClL,EAAA,IAAI,QAAA,CAAS,KAAA,IAAS,IAAA,CAAK,QAAA,KAAa,MAAA,QAAiB,IAAA,CAAK,CAAA,sBAAA,EAAyB,IAAA,CAAK,QAAQ,CAAA,CAAA,CAAG,CAAA;AACvG,EAAA,IAAI,QAAA,CAAS,KAAA,IAAS,IAAA,CAAK,OAAA,KAAY,MAAA,QAAiB,IAAA,CAAK,CAAA,qBAAA,EAAwB,IAAA,CAAK,OAAO,CAAA,CAAA,CAAG,CAAA;AACpG,EAAA,IAAI,SAAA,CAAU,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,WAAA,KAAgB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,yBAAA,EAA4B,IAAA,CAAK,WAAW,CAAA,CAAA,CAAG,CAAA;AACpI,EAAA,IAAI,WAAA,CAAY,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,gBAAA,KAAqB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,8BAAA,EAAiC,IAAA,CAAK,gBAAgB,CAAA,CAAA,CAAG,CAAA;AACrJ,EAAA,IAAI,aAAA,CAAc,IAAA,CAAK,QAAA,CAAS,SAAS,KAAK,IAAA,CAAK,iBAAA,EAAmB,KAAA,CAAM,IAAA,CAAK,oCAAoC,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,iBAAiB,CAAC,CAAA,EAAA,CAAI,CAAA;AAC/J,EAAA,IAAI,YAAA,CAAa,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,kBAAA,KAAuB,MAAA,EAAW,KAAA,CAAM,IAAA,CAAK,CAAA,gCAAA,EAAmC,IAAA,CAAK,kBAAkB,CAAA,CAAA,CAAG,CAAA;AAC5J,EAAA,KAAA,CAAM,KAAK,0BAA0B,CAAA;AACrC,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,EAAQ,KAAA,CAAM,KAAK,uDAAuD,CAAA;AACxF,EAAA,KAAA,CAAM,IAAA,CAAK,gDAAA,EAAkD,OAAA,EAAS,6EAAA,EAA+E,KAAK,CAAA;AAC1J,EAAA,KAAA,CAAM,IAAA;AAAA,IACF,CAAA,+BAAA,EAAkC,UAAU,CAAA,EAAA,EAAK,WAAW,CAAA,8BAAA,CAAA;AAAA,IAC5D,yBAAA;AAAA,IACA,uBAAA;AAAA,IACA,GAAA;AAAA,IACA,EAAA;AAAA,IACA,yBAAA;AAAA,IACA,sBAAsB,YAAY,CAAA,EAAA,CAAA;AAAA,IAClC,GAAA;AAAA,IACA;AAAA,GACJ;AAEA,EAAA,OAAO;AAAA,IACH,IAAA,EAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAAA,IACrB,IAAA,EAAM;AAAA,MACF,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,QAAA,CAAS,OAAA;AAAA,MAClB,WAAW,QAAA,CAAS,SAAA;AAAA,MACpB,MAAM,QAAA,CAAS,IAAA;AAAA,MACf,SAAS,QAAA,CAAS;AAAA;AACtB,GACJ;AACJ;;;AC1IA,SAAS,gBAAA,CAAiB,OAAY,QAAA,EAAuC;AACzE,EAAA,MAAM,EAAE,MAAK,GAAI,QAAA;AACjB,EAAA,IAAI,KAAK,MAAA,EAAQ;AACb,IAAA,KAAA,CAAM,MAAA,CAAO,OAAA,GAAU,IAAA,CAAK,MAAA,CAAO,OAAA;AACnC,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,OAAA,IAAW,IAAA,CAAK,MAAA,CAAO,UAAU,KAAA,CAAM,MAAA,CAAO,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,QAAA;AAAA,EACzF;AACA,EAAA,IAAI,SAAS,OAAA,EAAS;AAClB,IAAA,MAAM,IAAA,GAAO;AAAA,MACT,CAAC,KAAA,CAAM,IAAA,CAAK,YAAA,EAAc,KAAK,YAAY,CAAA;AAAA,MAC3C,CAAC,KAAA,CAAM,IAAA,CAAK,SAAA,EAAW,KAAK,SAAS;AAAA,KACzC;AACA,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,MAAM,CAAA,IAAK,IAAA,EAAM;AAC/B,MAAA,IAAI,CAAC,MAAA,EAAQ;AACb,MAAA,IAAI,OAAO,KAAA,EAAO;AACd,QAAA,IAAA,CAAK,KAAA,CAAM,OAAO,MAAA,CAAO,KAAA;AACzB,QAAA,IAAA,CAAK,MAAM,OAAA,GAAU,IAAA;AAAA,MACzB;AACA,MAAA,IAAI,MAAA,CAAO,YAAA,EAAc,IAAA,CAAK,YAAA,GAAe,MAAA,CAAO,YAAA;AACpD,MAAA,IAAI,OAAO,aAAA,KAAkB,MAAA,OAAgB,MAAA,CAAO,IAAA,CAAK,OAAO,MAAA,CAAO,aAAA;AACvE,MAAA,IAAI,MAAA,CAAO,gBAAA,KAAqB,MAAA,EAAW,IAAA,CAAK,mBAAmB,MAAA,CAAO,gBAAA;AAC1E,MAAA,IAAI,MAAA,CAAO,gBAAA,KAAqB,MAAA,EAAW,IAAA,CAAK,mBAAmB,MAAA,CAAO,gBAAA;AAC1E,MAAA,IAAI,MAAA,CAAO,YAAA,KAAiB,MAAA,EAAW,IAAA,CAAK,UAAU,MAAA,CAAO,YAAA;AAC7D,MAAA,IAAI,MAAA,CAAO,YAAA,KAAiB,MAAA,EAAW,IAAA,CAAK,UAAU,MAAA,CAAO,YAAA;AAC7D,MAAA,IAAI,MAAA,CAAO,SAAA,KAAc,MAAA,EAAW,IAAA,CAAK,YAAY,MAAA,CAAO,SAAA;AAAA,IAChE;AAAA,EACJ;AACA,EAAA,IAAI,KAAK,UAAA,EAAY;AACjB,IAAA,KAAA,CAAM,UAAA,CAAW,OAAA,GAAU,IAAA,CAAK,UAAA,CAAW,OAAA;AAC3C,IAAA,IAAI,KAAK,UAAA,CAAW,QAAA,QAAgB,UAAA,CAAW,QAAA,GAAW,KAAK,UAAA,CAAW,QAAA;AAC1E,IAAA,IAAI,KAAK,UAAA,CAAW,YAAA,QAAoB,UAAA,CAAW,YAAA,GAAe,KAAK,UAAA,CAAW,YAAA;AAClF,IAAA,IAAI,IAAA,CAAK,WAAW,SAAA,EAAW,KAAA,CAAM,WAAW,MAAA,CAAO,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,UAAA,CAAW,SAAA;AACpF,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,QAAA,KAAa,MAAA,EAAW,KAAA,CAAM,WAAW,MAAA,CAAO,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,UAAA,CAAW,QAAA;AAAA,EACpG;AACA,EAAA,KAAA,IAAS,QAAQ,CAAA,EAAG,KAAA,GAAQ,QAAA,CAAS,WAAA,EAAa,SAAS,CAAA,EAAG;AAC1D,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA;AAC3C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,aAAA,GAAgB,KAAK,CAAA;AACzC,IAAA,IAAI,QAAQ,KAAA,EAAO;AACf,MAAA,IAAI,CAAC,SAAS,MAAA,EAAQ,MAAA,CAAO,OAAO,IAAA,CAAK,aAAA,CAAc,OAAO,KAAK,CAAA;AACnE,MAAA,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,KAAA;AAAA,IACtC;AACA,IAAA,IAAI,QAAQ,SAAA,EAAW,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,YAAY,MAAA,CAAO,SAAA;AAC7D,IAAA,IAAI,SAAS,KAAA,IAAS,IAAA,CAAK,aAAa,MAAA,EAAW,MAAA,CAAO,WAAW,IAAA,CAAK,QAAA;AAC1E,IAAA,IAAI,SAAS,KAAA,IAAS,IAAA,CAAK,YAAY,MAAA,EAAW,MAAA,CAAO,UAAU,IAAA,CAAK,OAAA;AACxE,IAAA,IAAI,SAAA,CAAU,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,KAAK,WAAA,KAAgB,MAAA,EAAW,MAAA,CAAO,WAAA,GAAc,IAAA,CAAK,WAAA;AACpG,IAAA,IAAI,WAAA,CAAY,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,KAAK,gBAAA,KAAqB,MAAA,EAAW,MAAA,CAAO,gBAAA,GAAmB,IAAA,CAAK,gBAAA;AAChH,IAAA,IAAI,aAAA,CAAc,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,IAAA,CAAK,iBAAA,EAAmB,MAAA,CAAO,iBAAA,CAAkB,GAAA,CAAI,IAAA,CAAK,iBAAiB,CAAA;AACzH,IAAA,IAAI,YAAA,CAAa,IAAA,CAAK,QAAA,CAAS,SAAS,CAAA,IAAK,KAAK,kBAAA,KAAuB,MAAA,EAAW,MAAA,CAAO,kBAAA,GAAqB,IAAA,CAAK,kBAAA;AAAA,EACzH;AACJ;AAEA,eAAe,YAAA,CAAa,OAAA,EAAc,KAAA,EAAY,SAAA,EAAgB,KAAA,EAA8B;AAChG,EAAA,IAAI;AACA,IAAA,SAAA,CAAU,KAAK,6BAA6B,CAAA;AAC5C,IAAA,MAAM,SAAA,GAAY,MAAM,wBAAA,EAAyB;AACjD,IAAA,SAAA,CAAU,KAAK,6BAA6B,CAAA;AAC5C,IAAA,KAAA,CAAM,KAAK,gBAAgB,CAAA;AAC3B,IAAA,KAAA,CAAM,MAAA,CAAO,KAAK,0DAA0D,CAAA;AAC5E,IAAA,MAAM,QAAQ,IAAA,EAAK;AACnB,IAAA,KAAA,MAAW,MAAA,IAAU,KAAA,CAAM,MAAA,CAAO,KAAA,EAAO;AACrC,MAAA,MAAA,CAAO,UAAA,CAAW,KAAK,4EAA4E,CAAA;AAAA,IACvG;AACA,IAAA,MAAM,mBAAA,GAAsB,KAAA,CAAM,IAAA,CAAK,mBAAA,CAAoB,YAAY,SAAS,CAAA;AAChF,IAAA,MAAM,gBAAA,GAAmB,KAAA,CAAM,IAAA,CAAK,mBAAA,CAAoB,SAAS,SAAS,CAAA;AAC1E,IAAA,MAAM,kBAAA,GAAqB,KAAA,CAAM,IAAA,CAAK,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAC9E,IAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,mBAAA,EAAqB,gBAAA,EAAkB,kBAAkB,CAAA,EAAG;AAC5E,MAAA,IAAA,CAAK,KAAK,sEAAsE,CAAA;AAChF,MAAA,IAAA,CAAK,KAAA,CAAM,KAAK,cAAc,CAAA;AAAA,IAClC;AACA,IAAA,MAAM,QAAQ,IAAA,EAAK;AACnB,IAAA,MAAM,YAAA,GAAe,CAAC,IAAA,KAAc,IAAA,CAAK,eAAe,IAAA,GAAO,EAAE,GAAG,IAAA,CAAK,QAAO,EAAG,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,QAAO,EAAE;AAC9G,IAAA,OAAO;AAAA,MACH,WAAA,EAAa;AAAA,QACT,SAAS,SAAA,CAAU,OAAA;AAAA,QACnB,QAAQ,SAAA,CAAU,MAAA;AAAA,QAClB,cAAc,SAAA,CAAU;AAAA,OAC5B;AAAA,MACA,SAAA,EAAW,SAAA,CAAU,YAAA,GAAe,IAAA,GAAO;AAAA,QACvC,SAAS,SAAA,CAAU,OAAA;AAAA,QACnB,QAAQ,SAAA,CAAU;AAAA,OACtB;AAAA,MACA,KAAA,EAAO;AAAA,QACH,MAAM,KAAA,CAAM,IAAA;AAAA,QACZ,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,QAAQ,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,GAAA,CAAI,CAAC,MAAA,MAAiB;AAAA,UAC7C,GAAG,OAAO,MAAA,EAAO;AAAA,UACjB,UAAA,EAAY,MAAA,CAAO,UAAA,CAAW,MAAA;AAAO,SACzC,CAAE,CAAA;AAAA,QACF,IAAA,EAAM;AAAA,UACF,eAAA,EAAiB,aAAa,mBAAmB,CAAA;AAAA,UACjD,YAAA,EAAc,aAAa,gBAAgB,CAAA;AAAA,UAC3C,cAAA,EAAgB,aAAa,kBAAkB;AAAA;AACnD;AACJ,KACJ;AAAA,EACJ,SAAS,KAAA,EAAO;AACZ,IAAA,OAAO,EAAE,OAAO,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA,EAAE;AAAA,EAC3E;AACJ;AAEA,SAAS,WAAW,KAAA,EAAmC;AACnD,EAAA,MAAM,QAAQ,KAAA,IAAS,CAAA;AACvB,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,IAAK,SAAS,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,yCAAyC,CAAA;AACpG,EAAA,OAAO,KAAA;AACX;AAEA,eAAsB,gBAAA,CAClB,QAAA,EACA,KAAA,EACA,OAAA,GAA8B,EAAC,EACL;AAC1B,EAAA,MAAM,QAAA,GAAW,qBAAqB,KAAK,CAAA;AAC3C,EAAA,MAAM,EAAE,MAAK,GAAI,QAAA;AACjB,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,OAAA,CAAQ,KAAK,CAAA;AACtC,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,OAAO,OAAA,KAAY;AACnC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,QAAA,CAAS,UAAA,CAAW,kBAAA,EAAmB;AAC7D,IAAA,IAAI,OAAA,CAAQ,mBAAmB,KAAA,EAAO;AAClC,MAAA,KAAA,CAAM,MAAA,CAAO,KAAK,YAAY,CAAA;AAC9B,MAAA,MAAM,aAAA,GAAgB,MAAM,wBAAA,EAAyB;AACrD,MAAA,MAAM,QAAQ,IAAA,EAAK;AACnB,MAAA,KAAA,CAAM,OAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,aAAA,KAAuB,aAAA,CAAc,QAAQ,CAAA;AACzE,MAAA,IAAI,CAAC,aAAA,CAAc,YAAA,EAAc,aAAA,CAAc,KAAA,EAAM;AAAA,IACzD;AAEA,IAAA,MAAM,SAAA,GAAY,KAAA,CAAM,QAAA,CAAS,QAAA,CAAS,OAAO,CAAA;AACjD,IAAA,SAAA,CAAU,eAAe,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,GAAA,EAAK,aAAa,GAAA,CAAI,GAAA;AAAA,MAAI,CAAC,KAAA,EAAO,WAAA,KAC1E,QAAA,KAAa,CAAA,GACP,MACA,WAAA,KAAgB,CAAA,IAAK,QAAA,CAAS,QAAA,GAC1B,eACA,WAAA,KAAgB,CAAA,IAAK,CAAC,QAAA,CAAS,cAAc,GAAA,GAAM;AAAA,KAChE,CAAA;AACD,IAAA,SAAA,CAAU,SAAS,QAAA,CAAS,IAAA;AAC5B,IAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,GAAA,CAAI,SAAS,SAAA,EAAW,SAAA,EAAW,KAAK,QAAQ,CAAA;AAE3E,IAAA,IAAI,IAAA,CAAK,QAAQ,MAAA,EAAQ;AACrB,MAAA,KAAA,CAAM,MAAA,CAAO,KAAK,OAAO,CAAA;AACzB,MAAA,MAAM,QAAQ,IAAA,EAAK;AACnB,MAAA,IAAI,MAAM,MAAA,CAAO,KAAA,CAAM,MAAA,GAAS,IAAA,CAAK,OAAO,MAAA,EAAQ;AAChD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,eAAA,EAAkB,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,SAAA,EAAY,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,UAAA,CAAY,CAAA;AAAA,MACzG;AACA,MAAA,KAAA,MAAW,CAAC,KAAA,EAAO,OAAO,KAAK,IAAA,CAAK,MAAA,CAAO,SAAQ,EAAG;AAClD,QAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA;AACvC,QAAA,MAAA,CAAO,OAAO,OAAA,CAAQ,IAAA;AACtB,QAAA,MAAA,CAAO,cAAA,CAAe,MAAM,iBAAA,CAAkB,CAAA,EAAG,QAAQ,OAAA,EAAS,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAC,CAAA;AACtF,QAAA,MAAA,CAAO,SAAA,CAAU,MAAM,iBAAA,CAAkB,CAAA,EAAG,QAAQ,OAAA,EAAS,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAC,CAAA;AACjF,QAAA,IAAI,OAAA,CAAQ,qBAAqB,MAAA,EAAW;AACxC,UAAA,MAAA,CAAO,cAAA,CAAe,MAAM,iBAAA,CAAkB,CAAA,EAAG,QAAQ,gBAAA,EAAkB,OAAA,CAAQ,QAAA,EAAU,CAAC,CAAC,CAAA;AAAA,QACnG;AAAA,MACJ;AACA,MAAA,KAAA,IAAS,KAAA,GAAQ,KAAA,CAAM,MAAA,CAAO,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,KAAA,IAAS,IAAA,CAAK,MAAA,CAAO,MAAA,EAAQ,KAAA,IAAS,CAAA,EAAG;AACrF,QAAA,KAAA,CAAM,MAAA,CAAO,SAAA,CAAU,KAAK,CAAA,CAAE,MAAA,EAAO;AACrC,QAAA,MAAM,QAAQ,IAAA,EAAK;AAAA,MACvB;AAAA,IACJ;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,IAAS,GAAA;AAC5B,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,IAAU,GAAA;AAC9B,IAAA,KAAA,CAAM,KAAA,GAAQ,KAAA;AACd,IAAA,KAAA,CAAM,MAAA,GAAS,MAAA;AACf,IAAA,IAAI,KAAK,KAAA,EAAO;AACZ,MAAA,KAAA,CAAM,KAAA,CAAM,OAAO,IAAA,CAAK,KAAA;AACxB,MAAA,KAAA,CAAM,MAAM,OAAA,GAAU,IAAA;AAAA,IAC1B;AACA,IAAA,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AAChC,IAAA,MAAM,QAAQ,IAAA,EAAK;AACnB,IAAA,MAAM,QAAQ,KAAA,CAAM,QAAA;AAAA,MAChB,IAAA,CAAK,KAAA,CAAM,KAAA,IAAS,EAAA,GAAK,MAAM,KAAK,CAAA;AAAA,MACpC,IAAA,CAAK,KAAA,CAAM,MAAA,IAAU,EAAA,GAAK,MAAM,KAAK,CAAA;AAAA,MACrC,SAAS,gBAAA,CAAiB;AAAA,KAC9B;AACA,IAAA,MAAM,QAAQ,IAAA,EAAK;AACnB,IAAA,MAAM,UAAA,GAAa,QAAQ,kBAAA,GACrB,MAAM,aAAa,OAAA,EAAS,KAAA,EAAO,SAAA,EAAW,KAAK,CAAA,GACnD,IAAA;AACN,IAAA,OAAO,EAAE,SAAA,EAAW,KAAA,CAAM,KAAA,EAAO,UAAA,EAAW;AAAA,EAChD,CAAC,CAAA;AACL","file":"index.cjs","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * =============================================================================\n * TYPE REGISTRY — Single Source of Truth\n * =============================================================================\n *\n * Every recognized semantic type is registered here with its orthogonal\n * compilation dimensions. This is the ONLY place where per-type properties\n * are defined. All other files (field-semantics.ts, semantic-types.ts)\n * derive helper functions by querying this registry.\n *\n * To add a new semantic type: add an entry here.\n * To query a type's properties: use `getRegistryEntry()`.\n * =============================================================================\n */\n\n// ---------------------------------------------------------------------------\n// Visualization Categories\n// ---------------------------------------------------------------------------\n\nexport type VisCategory = 'quantitative' | 'ordinal' | 'nominal' | 'temporal' | 'geographic';\n\n// ---------------------------------------------------------------------------\n// Registry Dimension Types\n// ---------------------------------------------------------------------------\n\n/** Top-level type family */\nexport type T0Family = 'Temporal' | 'Measure' | 'Discrete' | 'Geographic' | 'Categorical' | 'Identifier';\n\n/** Mid-level category within a family */\nexport type T1Category =\n    | 'DateTime' | 'DateGranule' | 'Duration'\n    | 'Amount' | 'Physical' | 'Proportion' | 'SignedMeasure' | 'GenericMeasure'\n    | 'Rank' | 'Score'\n    | 'GeoCoordinate' | 'GeoPlace'\n    | 'Entity' | 'Coded' | 'Binned'\n    | 'ID';\n\nexport type DomainShape = 'open' | 'bounded' | 'fixed' | 'cyclic';\nexport type AggRole = 'additive' | 'intensive' | 'signed-additive' | 'dimension' | 'identifier';\nexport type DivergingClass = 'none' | 'inherent' | 'conditional';\nexport type FormatClass = 'currency' | 'percent'\n    | 'unit-suffix' | 'integer' | 'decimal' | 'plain';\n\n/**\n * Zero-baseline classification for quantitative axes.\n *\n * - `meaningful`: 0 = absence of the measured thing; axis should include 0 (Count, Revenue).\n * - `arbitrary`:  0 is arbitrary or nonexistent; data-fit the axis (Temperature, Year, Rank).\n * - `contextual`: 0 is meaningful but data-fitting may be better when data is far from 0 (Percentage, Score).\n * - `none`:       Not a quantitative type; zero question is irrelevant (all categorical/temporal types).\n */\nexport type ZeroBaseline = 'meaningful' | 'arbitrary' | 'contextual' | 'none';\n\nexport interface TypeRegistryEntry {\n    t0: T0Family;\n    t1: T1Category;\n    visEncodings: VisCategory[];\n    aggRole: AggRole;\n    domainShape: DomainShape;\n    diverging: DivergingClass;\n    formatClass: FormatClass;\n    /** Zero-baseline classification for quantitative axes */\n    zeroBaseline: ZeroBaseline;\n    /** Domain padding fraction for non-zero axes (0 = no padding) */\n    zeroPad: number;\n}\n\n// ---------------------------------------------------------------------------\n// The Registry\n// ---------------------------------------------------------------------------\n\n/**\n * Static registry mapping every recognized semantic type to its\n * tier membership and orthogonal compilation dimensions.\n *\n * Types not in this registry are treated as 'Unknown' → nominal/plain.\n */\nconst TYPE_REGISTRY: Record<string, TypeRegistryEntry> = {\n    // --- Temporal: DateTime ---\n    DateTime:      { t0: 'Temporal', t1: 'DateTime', visEncodings: ['temporal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none', formatClass: 'plain',           zeroBaseline: 'none', zeroPad: 0 },\n    Date:          { t0: 'Temporal', t1: 'DateTime', visEncodings: ['temporal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none', formatClass: 'plain',           zeroBaseline: 'none', zeroPad: 0 },\n    Time:          { t0: 'Temporal', t1: 'DateTime', visEncodings: ['temporal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none', formatClass: 'plain',           zeroBaseline: 'none', zeroPad: 0 },\n    Timestamp:     { t0: 'Temporal', t1: 'DateTime', visEncodings: ['temporal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none', formatClass: 'plain',           zeroBaseline: 'none', zeroPad: 0 },\n\n    // --- Temporal: DateGranule ---\n    Year:          { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['temporal', 'ordinal'], aggRole: 'dimension', domainShape: 'open',    diverging: 'none', formatClass: 'integer',        zeroBaseline: 'arbitrary', zeroPad: 0.03 },\n    Quarter:       { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['ordinal'],            aggRole: 'dimension', domainShape: 'cyclic',  diverging: 'none', formatClass: 'plain',          zeroBaseline: 'none', zeroPad: 0 },\n    Month:         { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['ordinal'],            aggRole: 'dimension', domainShape: 'cyclic',  diverging: 'none', formatClass: 'plain',          zeroBaseline: 'none', zeroPad: 0 },\n    Week:          { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['ordinal'],            aggRole: 'dimension', domainShape: 'cyclic',  diverging: 'none', formatClass: 'plain',          zeroBaseline: 'none', zeroPad: 0 },\n    Day:           { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['ordinal'],            aggRole: 'dimension', domainShape: 'cyclic',  diverging: 'none', formatClass: 'plain',          zeroBaseline: 'none', zeroPad: 0 },\n    Hour:          { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['ordinal'],            aggRole: 'dimension', domainShape: 'cyclic',  diverging: 'none', formatClass: 'integer',        zeroBaseline: 'arbitrary', zeroPad: 0 },\n    YearMonth:     { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['temporal', 'ordinal'], aggRole: 'dimension', domainShape: 'open',   diverging: 'none', formatClass: 'plain',          zeroBaseline: 'none', zeroPad: 0 },\n    YearQuarter:   { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['temporal', 'ordinal'], aggRole: 'dimension', domainShape: 'open',   diverging: 'none', formatClass: 'plain',          zeroBaseline: 'none', zeroPad: 0 },\n    YearWeek:      { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['temporal', 'ordinal'], aggRole: 'dimension', domainShape: 'open',   diverging: 'none', formatClass: 'plain',          zeroBaseline: 'none', zeroPad: 0 },\n    Decade:        { t0: 'Temporal', t1: 'DateGranule', visEncodings: ['temporal', 'ordinal'], aggRole: 'dimension', domainShape: 'open',   diverging: 'none', formatClass: 'integer',        zeroBaseline: 'arbitrary', zeroPad: 0.03 },\n\n    // --- Temporal: Duration ---\n    Duration:      { t0: 'Temporal', t1: 'Duration', visEncodings: ['quantitative'],       aggRole: 'additive',   domainShape: 'open',    diverging: 'none', formatClass: 'unit-suffix',     zeroBaseline: 'meaningful', zeroPad: 0 },\n\n    // --- Measure: Amount ---\n    Amount:        { t0: 'Measure', t1: 'Amount', visEncodings: ['quantitative'],          aggRole: 'additive',   domainShape: 'open',    diverging: 'none',        formatClass: 'currency',   zeroBaseline: 'meaningful', zeroPad: 0 },\n    Price:         { t0: 'Measure', t1: 'Amount', visEncodings: ['quantitative'],          aggRole: 'intensive',  domainShape: 'open',    diverging: 'none',        formatClass: 'currency',   zeroBaseline: 'meaningful', zeroPad: 0 },\n\n    // --- Measure: Physical ---\n    Quantity:      { t0: 'Measure', t1: 'Physical', visEncodings: ['quantitative'],        aggRole: 'additive',   domainShape: 'open',    diverging: 'none',        formatClass: 'unit-suffix', zeroBaseline: 'meaningful', zeroPad: 0 },\n    Temperature:   { t0: 'Measure', t1: 'Physical', visEncodings: ['quantitative'],        aggRole: 'intensive',  domainShape: 'open',    diverging: 'conditional', formatClass: 'unit-suffix', zeroBaseline: 'arbitrary', zeroPad: 0.05 },\n\n    // --- Measure: Proportion ---\n    Percentage:    { t0: 'Measure', t1: 'Proportion', visEncodings: ['quantitative'],      aggRole: 'intensive',  domainShape: 'bounded', diverging: 'none',        formatClass: 'percent',    zeroBaseline: 'contextual', zeroPad: 0 },\n\n    // --- Measure: SignedMeasure ---\n    Profit:             { t0: 'Measure', t1: 'SignedMeasure', visEncodings: ['quantitative'], aggRole: 'signed-additive', domainShape: 'open', diverging: 'conditional', formatClass: 'decimal',          zeroBaseline: 'meaningful', zeroPad: 0 },\n    PercentageChange:   { t0: 'Measure', t1: 'SignedMeasure', visEncodings: ['quantitative'], aggRole: 'intensive',       domainShape: 'open', diverging: 'conditional', formatClass: 'percent',          zeroBaseline: 'contextual', zeroPad: 0.05 },\n    Sentiment:          { t0: 'Measure', t1: 'SignedMeasure', visEncodings: ['quantitative'], aggRole: 'intensive',       domainShape: 'open', diverging: 'inherent',    formatClass: 'decimal',          zeroBaseline: 'meaningful', zeroPad: 0 },\n    Correlation:        { t0: 'Measure', t1: 'SignedMeasure', visEncodings: ['quantitative'], aggRole: 'intensive',       domainShape: 'bounded', diverging: 'inherent', formatClass: 'decimal',          zeroBaseline: 'meaningful', zeroPad: 0 },\n\n    // --- Measure: GenericMeasure ---\n    Count:         { t0: 'Measure', t1: 'GenericMeasure', visEncodings: ['quantitative'],  aggRole: 'additive',   domainShape: 'open',    diverging: 'none',        formatClass: 'integer',    zeroBaseline: 'meaningful', zeroPad: 0 },\n    Number:        { t0: 'Measure', t1: 'GenericMeasure', visEncodings: ['quantitative'],  aggRole: 'additive',   domainShape: 'open',    diverging: 'none',        formatClass: 'decimal',    zeroBaseline: 'meaningful', zeroPad: 0 },\n\n    // --- Discrete ---\n    Rank:          { t0: 'Discrete', t1: 'Rank',  visEncodings: ['ordinal'],               aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'integer',    zeroBaseline: 'arbitrary', zeroPad: 0.08 },\n    Score:         { t0: 'Discrete', t1: 'Score', visEncodings: ['quantitative', 'ordinal'], aggRole: 'intensive', domainShape: 'bounded', diverging: 'conditional', formatClass: 'decimal',    zeroBaseline: 'contextual', zeroPad: 0.05 },\n    ID:            { t0: 'Identifier', t1: 'ID',  visEncodings: ['nominal'],               aggRole: 'identifier', domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'arbitrary', zeroPad: 0 },\n\n    // --- Geographic ---\n    Latitude:      { t0: 'Geographic', t1: 'GeoCoordinate', visEncodings: ['quantitative', 'geographic'], aggRole: 'dimension', domainShape: 'fixed', diverging: 'none', formatClass: 'decimal',    zeroBaseline: 'arbitrary', zeroPad: 0.02 },\n    Longitude:     { t0: 'Geographic', t1: 'GeoCoordinate', visEncodings: ['quantitative', 'geographic'], aggRole: 'dimension', domainShape: 'fixed', diverging: 'none', formatClass: 'decimal',    zeroBaseline: 'arbitrary', zeroPad: 0.02 },\n    Country:       { t0: 'Geographic', t1: 'GeoPlace', visEncodings: ['nominal'],         aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    State:         { t0: 'Geographic', t1: 'GeoPlace', visEncodings: ['nominal'],         aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    City:          { t0: 'Geographic', t1: 'GeoPlace', visEncodings: ['nominal'],         aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    Region:        { t0: 'Geographic', t1: 'GeoPlace', visEncodings: ['nominal'],         aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    Address:       { t0: 'Geographic', t1: 'GeoPlace', visEncodings: ['nominal'],         aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    ZipCode:       { t0: 'Geographic', t1: 'GeoPlace', visEncodings: ['nominal'],         aggRole: 'identifier', domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    // --- Categorical: Entity ---\n    Category:      { t0: 'Categorical', t1: 'Entity', visEncodings: ['nominal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    Name:          { t0: 'Categorical', t1: 'Entity', visEncodings: ['nominal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n\n    // --- Categorical: Coded ---\n    Status:        { t0: 'Categorical', t1: 'Coded', visEncodings: ['nominal'],            aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    Boolean:       { t0: 'Categorical', t1: 'Coded', visEncodings: ['nominal'],            aggRole: 'dimension',  domainShape: 'fixed',   diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n    Direction:     { t0: 'Categorical', t1: 'Coded', visEncodings: ['ordinal', 'nominal'], aggRole: 'dimension',  domainShape: 'cyclic',  diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n\n    // --- Categorical: Binned ---\n    Range:         { t0: 'Categorical', t1: 'Binned', visEncodings: ['ordinal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n\n    // --- Fallbacks ---\n    Unknown:       { t0: 'Categorical', t1: 'Entity', visEncodings: ['nominal'],           aggRole: 'dimension',  domainShape: 'open',    diverging: 'none',        formatClass: 'plain',      zeroBaseline: 'none', zeroPad: 0 },\n};\n\n/** Default entry for unrecognized types */\nconst UNKNOWN_ENTRY: TypeRegistryEntry = {\n    t0: 'Categorical', t1: 'Entity',\n    visEncodings: ['nominal'],\n    aggRole: 'dimension',\n    domainShape: 'open',\n    diverging: 'none',\n    formatClass: 'plain',\n    zeroBaseline: 'none',\n    zeroPad: 0,\n};\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/** Look up a semantic type in the registry. Falls back to UNKNOWN_ENTRY. */\nexport function getRegistryEntry(semanticType: string): TypeRegistryEntry {\n    return TYPE_REGISTRY[semanticType] ?? UNKNOWN_ENTRY;\n}\n\n/** Check whether a semantic type string is explicitly registered. */\nexport function isRegistered(semanticType: string): boolean {\n    return semanticType in TYPE_REGISTRY;\n}\n\n/**\n * Get all registered type names.\n * Useful for validation or iterating over the type system.\n */\nexport function getRegisteredTypes(): string[] {\n    return Object.keys(TYPE_REGISTRY);\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { getRegistryEntry, getRegisteredTypes, isRegistered, type VisCategory } from './type-registry';\nexport type { VisCategory } from './type-registry';\n\n/**\n * =============================================================================\n * SEMANTIC TYPE SYSTEM\n * =============================================================================\n * \n * Semantic types classify data fields for intelligent chart recommendations.\n * Uses strings for flexibility and easy JSON serialization.\n * \n * DESIGN GOALS:\n * 1. Comprehensive: Cover common data types seen in real-world datasets\n * 2. Visualization-aware: Map to Vega-Lite encoding types (Q, O, N, T)\n * 3. Hierarchical: Support generalization via lattice structure\n * 4. Simple: Use strings with helper functions, no complex enums\n * \n * =============================================================================\n * SEMANTIC TYPE LATTICE\n * =============================================================================\n * \n *                           ┌─────────────┐\n *                           │   AnyType   │\n *                           └──────┬──────┘\n *            ┌────────────────────┼────────────────────┐\n *            ▼                    ▼                    ▼\n *     ┌──────────┐         ┌──────────┐         ┌───────-───┐\n *     │ Temporal │         │ Numeric  │         │Categorical│\n *     └────┬─────┘         └────┬─────┘         └─────┬────┘\n *          │                    │                     │\n *    ┌─────┴─────┐        ┌─────┴─────┐         ┌─────┴─────┐\n *    │           │        │           │         │           │\n *  DateTime     Granule    Measure   Discrete    Entity     Coded\n *    │           │        │           │         │           │\n * DateTime    Year     Quantity    Rank      Category   Status\n * Date        Month    Count       Score     Name       Boolean\n * Time        Day      Price       ID                   Direction\n *             Quarter  Percentage\n *             Decade   Amount\n *                      Temperature\n * \n * =============================================================================\n */\n\n// ---------------------------------------------------------------------------\n// All Semantic Types (as string constants)\n// ---------------------------------------------------------------------------\n\n/**\n * All recognized semantic types.\n * Use these constants when comparing or assigning types.\n */\nexport const SemanticTypes = {\n    // =========================================================================\n    // TEMPORAL TYPES - Time-related concepts\n    // =========================================================================\n    \n    // Point-in-time (full timestamp precision)\n    DateTime: 'DateTime',       // Full date and time: \"2024-01-15T14:30:00\"\n    Date: 'Date',               // Date only: \"2024-01-15\"\n    Time: 'Time',               // Time only: \"14:30:00\"\n    Timestamp: 'Timestamp',     // Unix timestamp (seconds or milliseconds since epoch)\n    \n    // Temporal granules (discrete time units, inherently ordered)\n    Year: 'Year',               // \"2024\" (as a time unit, not a measure)\n    Quarter: 'Quarter',         // \"Q1\", \"Q2\", \"2024-Q1\"\n    Month: 'Month',             // \"January\", \"Jan\", 1-12\n    Week: 'Week',               // \"Week 1\", 1-52\n    Day: 'Day',                 // \"Monday\", \"Mon\", 1-31\n    Hour: 'Hour',               // 0-23\n    \n    // Combined temporal\n    YearMonth: 'YearMonth',     // \"2024-01\", \"Jan 2024\"\n    YearQuarter: 'YearQuarter', // \"2024-Q1\"\n    YearWeek: 'YearWeek',       // \"2024-W01\"\n    Decade: 'Decade',           // \"1990s\", \"2000s\"\n    \n    // Temporal duration/span\n    Duration: 'Duration',       // Time span: \"2 hours\", \"3 days\", milliseconds\n    \n    // =========================================================================\n    // NUMERIC MEASURE TYPES - Continuous values for aggregation\n    // =========================================================================\n    \n    Quantity: 'Quantity',       // Generic continuous measure\n    Count: 'Count',             // Discrete count of items\n    Amount: 'Amount',           // Monetary or general amounts\n    Price: 'Price',             // Unit price\n    Percentage: 'Percentage',   // 0-100% or 0-1 ratio\n    Temperature: 'Temperature', // Degrees\n    \n    // Signed measures (can be positive or negative, zero has meaning)\n    Profit: 'Profit',             // Gain/loss, profit/deficit\n    PercentageChange: 'PercentageChange', // Growth rate, change %\n    Sentiment: 'Sentiment',       // Positive/negative sentiment score\n    Correlation: 'Correlation',   // Positive/negative correlation coefficient\n    \n    // =========================================================================\n    // NUMERIC DISCRETE TYPES - Numbers with ordinal/identifier meaning\n    // =========================================================================\n    \n    Rank: 'Rank',               // Position in ordered list: 1st, 2nd, 3rd\n    ID: 'ID',                   // Unique identifier (not for aggregation!)\n    Score: 'Score',             // Rating score: 1-5, 1-10, 0-100\n    \n    // =========================================================================\n    // GEOGRAPHIC TYPES - Location-based data\n    // =========================================================================\n    \n    Latitude: 'Latitude',       // -90 to 90\n    Longitude: 'Longitude',     // -180 to 180\n    Country: 'Country',         // Country name or code\n    State: 'State',             // State/Province\n    City: 'City',               // City name\n    Region: 'Region',           // Geographic region\n    Address: 'Address',         // Street address (geo lookup)\n    ZipCode: 'ZipCode',         // Postal code (geo lookup)\n    \n    // =========================================================================\n    // CATEGORICAL ENTITY TYPES - Named entities\n    // =========================================================================\n    \n    Category: 'Category',       // Discrete category / product / entity class\n    Name: 'Name',               // Generic named entity (person, company, product, etc.)\n    \n    // =========================================================================\n    // CATEGORICAL CODED TYPES - Discrete categories/statuses\n    // =========================================================================\n    \n    Status: 'Status',           // State: \"Active\", \"Pending\", \"Closed\"\n    Boolean: 'Boolean',         // True/False, Yes/No\n    Direction: 'Direction',     // Compass direction: \"N\", \"NE\", \"East\", etc.\n    \n    // =========================================================================\n    // BINNED/RANGE TYPES - Discretized continuous values\n    // =========================================================================\n    \n    Range: 'Range',             // Numeric range, age group, binned values\n    \n    // =========================================================================\n    // FALLBACK TYPES\n    // =========================================================================\n    \n    Number: 'Number',           // Generic number (measure fallback)\n    Unknown: 'Unknown',         // Cannot determine type\n} as const;\n\n// Type for any semantic type string\nexport type SemanticType = typeof SemanticTypes[keyof typeof SemanticTypes];\n\n// ---------------------------------------------------------------------------\n// Visualization Categories  →  defined in type-registry.ts (single source of truth)\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Type Sets for Classification — derived from type-registry.ts\n// ---------------------------------------------------------------------------\n\n// timeseriesXTypes: REMOVED — derived from type-registry.ts via isTimeSeriesType()\n\n/**\n * Types suitable for quantitative encoding (true continuous measures).\n *\n * Derived from the registry: aggRole ∈ {additive, intensive, signed-additive},\n * excluding Score/Rating (t1='Score') which behave as bounded ordinal scales\n * for vis purposes (e.g., 1–5 star rating). This is an intentional vis-level\n * distinction, not a mathematical one.\n */\nexport const measureTypes = new Set<string>(\n    getRegisteredTypes().filter(t => {\n        const e = getRegistryEntry(t);\n        return ['additive', 'intensive', 'signed-additive'].includes(e.aggRole) && e.t1 !== 'Score';\n    })\n);\n\n/** Numeric types that should NOT be used as measures (don't aggregate) */\nexport const nonMeasureNumericTypes = new Set<string>([\n    'Rank', 'ID', 'Score',\n    'Year', 'Month', 'Day', 'Hour',\n    'Latitude', 'Longitude',\n]);\n\n/**\n * Types suitable for categorical color/grouping encoding.\n *\n * Derived from the registry: types that include 'nominal' in visEncodings\n * (at any position — Direction has ['ordinal','nominal']),\n * plus binned types (Range, AgeGroup) which also work as categorical for\n * color/grouping despite having 'ordinal' as their primary encoding.\n * Excludes identifiers (ID) which are nominal but not useful for grouping.\n */\nexport const categoricalTypes = new Set<string>(\n    getRegisteredTypes().filter(t => {\n        const e = getRegistryEntry(t);\n        return (e.visEncodings.includes('nominal') && e.aggRole !== 'identifier') || e.t1 === 'Binned';\n    })\n);\n\n/**\n * Types suitable for ordinal encoding (have inherent order).\n *\n * Derived from the registry: types whose visEncodings include 'ordinal'.\n */\nexport const ordinalTypes = new Set<string>(\n    getRegisteredTypes().filter(t => {\n        const e = getRegistryEntry(t);\n        return e.visEncodings.includes('ordinal');\n    })\n);\n\n// geoTypes, geoCoordinateTypes, geoLocationTypes: REMOVED — derived from type-registry.ts\n// via isGeoType(), isGeoCoordinateType(), isGeoLocationString()\n\n// ---------------------------------------------------------------------------\n// Type Hierarchy — REMOVED\n// ---------------------------------------------------------------------------\n// The typeHierarchy map and its helper functions (getParentType,\n// getAncestorTypes, isSubtypeOf) have been removed. They were unused\n// externally — no consumer ever imported them.\n//\n// The registry's t0/t1 dimensions capture family grouping (e.g., all\n// Amount types share t1='Amount'). If fine-grained parent-child lattice\n// traversal is ever needed in the future, it can be rebuilt from\n// type-registry.ts with an explicit `parent` field per entry.\n// ---------------------------------------------------------------------------\n\n// visCategoryMap: REMOVED — derived from type-registry.ts via getRegistryEntry().visEncodings[0]\n\n// ---------------------------------------------------------------------------\n// Helper Functions\n// ---------------------------------------------------------------------------\n\n/**\n * Get the Vega-Lite visualization category for a semantic type.\n * Derived from the registry's visEncodings[0] (primary encoding).\n * Returns null for unrecognised types so callers can fall back\n * to data-driven inference.\n */\nexport function getVisCategory(semanticType: string): VisCategory | null {\n    // Return null for empty, 'Unknown', or any unregistered type string\n    // so callers fall back to data-driven inference (inferVisCategory).\n    if (!semanticType || !isRegistered(semanticType)) return null;\n    return getRegistryEntry(semanticType).visEncodings[0] ?? null;\n}\n\n\n/**\n * Infer a VisCategory from raw data values when no semantic type is available.\n * Mirrors the DataType → VL encoding type mapping:\n *   number/integer → quantitative, boolean → nominal, date → temporal, string → nominal.\n */\nexport function inferVisCategory(values: any[]): VisCategory {\n    if (values.length === 0) return 'nominal';\n    const isBoolean = (v: any) => v === true || v === false || Object.prototype.toString.call(v) === '[object Boolean]';\n    const isNumber = (v: any) => !isNaN(+v) && !(Object.prototype.toString.call(v) === '[object Date]');\n    // Date.parse is too permissive in V8 — \"FY 2018\", \"hello world 2018\" all parse.\n    // Require the string to start with a digit or a known month-name prefix.\n    const looksLikeDate = (s: string) => /^\\d|^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i.test(s.trim());\n    const isDate = (v: any) => {\n        if (v instanceof Date) return !isNaN(v.getTime());\n        if (typeof v === 'string') return looksLikeDate(v) && !isNaN(Date.parse(v));\n        return !isNaN(Date.parse(v));\n    };\n    const nonNull = values.filter(v => v != null);\n    if (nonNull.length === 0) return 'nominal';\n    if (nonNull.every(isBoolean)) return 'nominal';\n    if (nonNull.every(isNumber)) return 'quantitative';\n    if (nonNull.every(isDate)) return 'temporal';\n    return 'nominal';\n}\n\n/**\n * Check if a semantic type is a true measure (suitable for quantitative encoding).\n */\nexport function isMeasureType(semanticType: string): boolean {\n    return measureTypes.has(semanticType);\n}\n\n/**\n * Check if a semantic type is suitable for time-series X axis.\n * Derived from type-registry: t0 === 'Temporal' but not Duration.\n */\nexport function isTimeSeriesType(semanticType: string): boolean {\n    const entry = getRegistryEntry(semanticType);\n    return entry.t0 === 'Temporal' && entry.t1 !== 'Duration';\n}\n\n/**\n * Check if a semantic type is categorical (suitable for color/grouping).\n */\nexport function isCategoricalType(semanticType: string): boolean {\n    return categoricalTypes.has(semanticType);\n}\n\n/**\n * Check if a semantic type is ordinal (has inherent order).\n */\nexport function isOrdinalType(semanticType: string): boolean {\n    return ordinalTypes.has(semanticType);\n}\n\n/**\n * Check if a semantic type is geographic.\n * Derived from type-registry: t0 === 'Geographic'.\n */\nexport function isGeoType(semanticType: string): boolean {\n    return getRegistryEntry(semanticType).t0 === 'Geographic';\n}\n\n/**\n * Check if a semantic type is a geographic coordinate (lat/lon).\n * Derived from type-registry: t1 === 'GeoCoordinate'.\n */\nexport function isGeoCoordinateType(semanticType: string): boolean {\n    return getRegistryEntry(semanticType).t1 === 'GeoCoordinate';\n}\n\n/**\n * Check if a semantic type is a named geographic location.\n * Derived from type-registry: t1 === 'GeoPlace'.\n */\nexport function isGeoLocationString(semanticType: string): boolean {\n    return getRegistryEntry(semanticType).t1 === 'GeoPlace';\n}\n\n/**\n * Check if a semantic type is numeric but should not be aggregated.\n */\nexport function isNonMeasureNumeric(semanticType: string): boolean {\n    return nonMeasureNumericTypes.has(semanticType);\n}\n\n// ---------------------------------------------------------------------------\n// Zero-Baseline Classification  →  data lives in type-registry.ts (zeroBaseline, zeroPad)\n// ---------------------------------------------------------------------------\n\n/**\n * Classification of whether zero is a meaningful baseline for a semantic type.\n *\n * - `meaningful`: 0 has a real-world interpretation (absence of the measured thing).\n *   Comparisons to zero and ratios between values are meaningful.\n *   Examples: Count, Revenue, Distance, Weight.\n *\n * - `arbitrary`: 0 is either meaningless, doesn't exist, or is an arbitrary\n *   reference point. The data's range is what matters.\n *   Examples: Temperature (0°F is arbitrary), Year (year 0 doesn't exist),\n *   Rank (0th place doesn't exist).\n *\n * - `contextual`: 0 is meaningful but data-fitting may be better when data\n *   is concentrated far from zero and the mark is not bar/area.\n *   Examples: Percentage (0–100% natural, but 48–52% benefits from zoom),\n *   Score (1–5 scale, but 4.2–4.8 benefits from zoom).\n */\nexport type ZeroClass = 'meaningful' | 'arbitrary' | 'contextual';\n\n/**\n * Result of the zero-baseline decision.\n * Encapsulates both the boolean decision and domain padding for non-zero axes.\n */\nexport interface ZeroDecision {\n    /** Whether the axis should include zero */\n    zero: boolean;\n    /**\n     * For non-zero axes: fraction of data range to pad on each side\n     * so edge values aren't crushed against the axis boundary.\n     * e.g. 0.05 = 5% padding on each side.\n     */\n    domainPadFraction: number;\n    /** The zero class that drove this decision */\n    zeroClass: ZeroClass | 'unknown';\n    /**\n     * Whether this is a *forced* (non-debatable) decision:\n     *   - `true`  → mandatory: a length/area mark, data that crosses zero, or a\n     *     zero-meaningful type on a length mark. Including zero is structural.\n     *   - `false` → the engine still has a recommended `zero`, but anchoring at\n     *     zero is at least conceptually a choice.\n     * `forced` records the structural side of the decision; it is NOT the gate\n     * for the UI toggle — see `uncertain` below.\n     */\n    forced: boolean;\n    /**\n     * Whether the zero-vs-fit choice is a *genuine toss-up worth surfacing* to\n     * the user. Hosts read this (via the property `check`) to decide whether to\n     * show the \"Zero X/Y\" toggle at all.\n     *\n     * We deliberately keep this narrow to avoid UI clutter: it is `true` ONLY\n     * for a zero-meaningful field on a position mark whose data sits far enough\n     * from zero that anchoring at zero would noticeably compress the view (a\n     * real zoom-in-vs-anchor tradeoff). Every other case — arbitrary types\n     * (zero is meaningless, just fit the data), contextual types (the engine's\n     * data-range call is confident enough), meaningful types whose data already\n     * spans most of the way to zero (the choice barely changes anything), and\n     * all forced/unknown cases — is `false`, so no toggle is shown and the\n     * engine's `zero` value simply applies. The engine's `zero` remains the\n     * recommended default when the toggle is shown.\n     */\n    uncertain: boolean;\n}\n\n// zeroMeaningfulTypes, zeroArbitraryTypes, zeroContextualTypes, zeroPadMap:\n// REMOVED — now stored as zeroBaseline/zeroPad in type-registry.ts\n\n/**\n * Classify a semantic type's relationship to zero.\n * Derived from the registry's zeroBaseline dimension.\n */\nexport function getZeroClass(semanticType: string): ZeroClass | 'unknown' {\n    const baseline = getRegistryEntry(semanticType).zeroBaseline;\n    if (baseline === 'none') return 'unknown';\n    return baseline;\n}\n\n/**\n * Compute whether a quantitative axis should start at zero, based on\n * semantic type, mark type, channel, and data values.\n *\n * Priority: semantic type > mark type > data range > VL default.\n *\n * This is a pure decision function — it returns a ZeroDecision object\n * without modifying any spec. The caller applies the decision to VL.\n *\n * @param semanticType  The semantic type of the field (e.g. 'Amount', 'Temperature')\n * @param channel       The VL channel ('x', 'y', 'size', etc.)\n * @param markType      The mark type ('bar', 'line', 'point', etc.)\n * @param values        Optional numeric data values for data-range analysis\n */\n/**\n * Above this ratio of dataMin/dataMax, the data band sits far enough above\n * zero that anchoring the axis at zero would leave at least half the axis\n * empty — a big enough gap that \"zoom into the data\" vs \"keep the zero\n * reference\" is a genuine toss-up worth offering as a toggle. Below it, the\n * data already spans most of the way to zero, so including zero barely changes\n * the view and we keep it on silently.\n */\nconst ZERO_BASELINE_GAP_THRESHOLD = 0.5;\n\n/**\n * True when strictly-positive data sits far enough from zero that anchoring at\n * zero would noticeably compress the view (see ZERO_BASELINE_GAP_THRESHOLD).\n * Returns false for empty data or any data that touches/crosses zero (there the\n * baseline is inside the data range, so it is not a debatable gap).\n */\nfunction dataFarFromZero(values?: number[]): boolean {\n    if (!values || values.length === 0) return false;\n    const dataMin = Math.min(...values);\n    const dataMax = Math.max(...values);\n    if (dataMin <= 0 || dataMax <= 0) return false;\n    return dataMin / dataMax >= ZERO_BASELINE_GAP_THRESHOLD;\n}\n\nexport function computeZeroDecision(\n    semanticType: string,\n    channel: string,\n    markType: string,\n    values?: number[],\n): ZeroDecision {\n    const isBarLike = ['bar', 'area', 'rect'].includes(markType);\n    const isScatterMark = markType === 'circle' || markType === 'point';\n    const isPositional = ['x', 'y'].includes(channel);\n    const entry = getRegistryEntry(semanticType);\n    const zeroClass = getZeroClass(semanticType);\n\n    // --- Zero-meaningful types: zero is the conventional baseline ---\n    if (zeroClass === 'meaningful') {\n        // Length marks (bar/area/rect): the baseline is structurally required —\n        // a bar's length is meaningless without zero. Not debatable.\n        if (isBarLike) {\n            return { zero: true, domainPadFraction: 0, zeroClass, forced: true, uncertain: false };\n        }\n        // Scatter (circle/point position): the read is correlation / cloud shape,\n        // not distance from zero — data-fit is the conventional default. Offer\n        // Zero X/Y as an opt-in toggle when the user wants a zero reference.\n        if (isPositional && isScatterMark) {\n            if (values && values.length > 0 && Math.min(...values) <= 0) {\n                return { zero: true, domainPadFraction: 0, zeroClass, forced: true, uncertain: false };\n            }\n            return {\n                zero: false,\n                domainPadFraction: entry.zeroPad || 0.05,\n                zeroClass,\n                forced: false,\n                uncertain: true,\n            };\n        }\n        // Position marks (line/strip): zero is the conventional reference,\n        // so the recommended default is ON. We only *offer* the toggle when the\n        // data sits far enough from zero that anchoring at zero would noticeably\n        // compress the view — a genuine zoom-in-vs-keep-the-reference toss-up.\n        // When the data already spans most of the way to zero, the choice barely\n        // changes anything, so we keep zero on silently and hide the toggle.\n        return {\n            zero: true,\n            domainPadFraction: 0,\n            zeroClass,\n            forced: false,\n            uncertain: dataFarFromZero(values),\n        };\n    }\n\n    // --- Zero-arbitrary types: never zero, apply padding ---\n    if (zeroClass === 'arbitrary') {\n        // Exception: bar/area marks with data that touches/crosses zero —\n        // the baseline is structurally required, so this is forced.\n        if (isBarLike && values && values.length > 0) {\n            const dataMin = Math.min(...values);\n            if (dataMin <= 0) {\n                return { zero: true, domainPadFraction: 0, zeroClass, forced: true, uncertain: false };\n            }\n        }\n        // Strictly away from zero on an arbitrary scale: zero is meaningless\n        // here, so data-fit is simply the right answer — there is nothing to\n        // debate and no toggle is offered.\n        return {\n            zero: false,\n            domainPadFraction: entry.zeroPad || 0.05,\n            zeroClass,\n            forced: false,\n            uncertain: false,\n        };\n    }\n\n    // --- Contextual types: use data range + mark to decide ---\n    if (zeroClass === 'contextual' && values && values.length > 0) {\n        const dataMin = Math.min(...values);\n        const dataMax = Math.max(...values);\n\n        // Data touches/crosses zero → include it (forced: the baseline is\n        // inside the data range).\n        if (dataMin <= 0) {\n            return { zero: true, domainPadFraction: 0, zeroClass, forced: true, uncertain: false };\n        }\n\n        // How far is data from zero?\n        const proximity = dataMax > 0 ? dataMin / dataMax : 0;\n\n        // Close to zero → include it. The engine's data-range call is confident\n        // enough here, so no toggle is offered.\n        if (proximity < 0.3) {\n            return { zero: true, domainPadFraction: 0, zeroClass, forced: false, uncertain: false };\n        }\n\n        // Far from zero + bar/area → still include (bar length integrity, forced).\n        if (isBarLike) {\n            return { zero: true, domainPadFraction: 0, zeroClass, forced: true, uncertain: false };\n        }\n\n        // Far from zero + non-bar → data-fit with padding (engine's call, no toggle).\n        return { zero: false, domainPadFraction: 0.05, zeroClass, forced: false, uncertain: false };\n    }\n\n    // --- No semantic type or unrecognized → no opinion, let VL decide ---\n    // Unknown class is never debatable: we have no basis for a toggle.\n    if (isBarLike && isPositional) {\n        return { zero: true, domainPadFraction: 0, zeroClass: 'unknown', forced: true, uncertain: false };\n    }\n    return { zero: false, domainPadFraction: 0.05, zeroClass: 'unknown', forced: true, uncertain: false };\n}\n\n/**\n * Compute padded domain bounds for a non-zero axis.\n * Pure computation — returns [paddedMin, paddedMax] without modifying any spec.\n *\n * @param values         Numeric data values\n * @param padFraction    Fraction of data range to pad on each side\n * @returns              [paddedMin, paddedMax] or null if padding is not applicable\n */\nexport function computePaddedDomain(\n    values: number[],\n    padFraction: number,\n): [number, number] | null {\n    if (padFraction <= 0 || values.length < 2) return null;\n\n    const dataMin = Math.min(...values);\n    const dataMax = Math.max(...values);\n    const span = dataMax - dataMin;\n    if (span <= 0) return null;\n\n    const padding = span * padFraction;\n    return [dataMin - padding, dataMax + padding];\n}\n\n// ---------------------------------------------------------------------------\n// Color Scheme Recommendations\n// ---------------------------------------------------------------------------\n\nexport type ColorSchemeType = 'categorical' | 'sequential' | 'diverging';\n\nexport interface ColorSchemeRecommendation {\n    scheme: string;\n    type: ColorSchemeType;\n    reason: string;\n    /** For diverging schemes, the recommended midpoint value */\n    domainMid?: number;\n}\n\n// getDivergingMidpoint: REMOVED — superseded by resolveDivergingInfo() in field-semantics.ts\n// which uses a priority chain (unit → type-intrinsic → domain → data) and\n// distinguishes inherent vs conditional diverging.\n\n/**\n * Vega-Lite color schemes organized by use case\n * See: https://vega.github.io/vega/docs/schemes/\n */\nconst colorSchemes = {\n    // Categorical (nominal) - good for distinct categories\n    categorical: {\n        default: 'category10',\n        large: 'category20',\n        pastel: 'pastel1',\n        accent: 'accent',\n        paired: 'paired',      // Good for paired comparisons\n        set1: 'set1',          // Distinct, saturated\n        set2: 'set2',          // Pastel\n        set3: 'set3',          // Larger set\n        tableau10: 'tableau10',\n        tableau20: 'tableau20',\n    },\n    // Sequential - good for ordered/quantitative data\n    sequential: {\n        blues: 'blues',\n        greens: 'greens',\n        oranges: 'oranges',\n        reds: 'reds',\n        purples: 'purples',\n        greys: 'greys',\n        // Multi-hue sequential\n        viridis: 'viridis',\n        inferno: 'inferno',\n        magma: 'magma',\n        plasma: 'plasma',\n        turbo: 'turbo',\n        // Domain-specific\n        yellowGreen: 'yellowgreen',\n        yellowOrangeBrown: 'yelloworangebrown',\n        goldGreen: 'goldgreen',\n        goldOrange: 'goldorange',\n        goldRed: 'goldred',\n    },\n    // Diverging - good for data with meaningful center point\n    diverging: {\n        redBlue: 'redblue',\n        redGrey: 'redgrey',\n        redYellowBlue: 'redyellowblue',\n        redYellowGreen: 'redyellowgreen',\n        pinkYellowGreen: 'pinkyellowgreen',\n        purpleGreen: 'purplegreen',\n        purpleOrange: 'purpleorange',\n        brownBlueGreen: 'brownbluegreen',\n    },\n};\n\n/**\n * Get recommended color scheme based on semantic type and encoding context.\n * \n * @param semanticType - The semantic type of the field\n * @param encodingType - The Vega-Lite encoding type ('nominal', 'ordinal', 'quantitative')\n * @param uniqueValueCount - Number of unique values (for categorical sizing)\n * @param fieldName - Field name (for consistent hashing)\n * @param values - Optional actual data values (for inspecting data range)\n * @param colorHint - Optional classification from resolveColorSchemeHint().\n *        When provided, the hint's type ('diverging'|'sequential'|'categorical')\n *        overrides inline detection, avoiding duplicate diverging logic.\n */\nexport function getRecommendedColorScheme(\n    semanticType: string | undefined,\n    encodingType: 'nominal' | 'ordinal' | 'quantitative' | 'temporal',\n    uniqueValueCount: number = 10,\n    fieldName: string = '',\n    values: any[] = [],\n    colorHint?: { type: 'categorical' | 'sequential' | 'diverging' },\n): ColorSchemeRecommendation {\n    \n    // Helper for consistent scheme selection from array\n    const pickScheme = (schemes: string[], name: string): string => {\n        let hash = 0;\n        for (let i = 0; i < name.length; i++) {\n            hash = ((hash << 5) - hash) + name.charCodeAt(i);\n            hash = hash & hash;\n        }\n        return schemes[Math.abs(hash) % schemes.length];\n    };\n\n    // If no semantic type, use defaults based on encoding type\n    if (!semanticType) {\n        if (encodingType === 'quantitative') {\n            return { scheme: 'viridis', type: 'sequential', reason: 'default for quantitative' };\n        }\n        if (encodingType === 'ordinal') {\n            return { scheme: 'blues', type: 'sequential', reason: 'default for ordinal' };\n        }\n        // nominal/temporal default to categorical — use saturated schemes for readability\n        return { \n            scheme: uniqueValueCount > 10 ? 'tableau20' : 'tableau10', \n            type: 'categorical', \n            reason: 'default for categorical' \n        };\n    }\n\n    // --- Diverging-capable types ---\n    // When a colorHint is provided (from resolveColorSchemeHint), it drives the\n    // diverging/sequential decision. Without a hint, fall back to sequential.\n    // This avoids duplicating the diverging detection logic from field-semantics.ts.\n\n    // Temperature\n    if (semanticType === 'Temperature') {\n        if (colorHint?.type === 'diverging') {\n            return { scheme: 'redblue', type: 'diverging', reason: 'temperature diverging around freezing point' };\n        }\n        return { scheme: 'reds', type: 'sequential', reason: 'temperature single-direction uses sequential' };\n    }\n\n    // Percentage\n    if (semanticType === 'Percentage') {\n        if (colorHint?.type === 'diverging') {\n            return { scheme: 'redblue', type: 'diverging', reason: 'percentage spans positive and negative' };\n        }\n        return { scheme: 'oranges', type: 'sequential', reason: 'percentage all same sign uses sequential' };\n    }\n\n    // Price/Amount\n    if (['Price', 'Amount'].includes(semanticType)) {\n        if (colorHint?.type === 'diverging') {\n            return { scheme: 'redblue', type: 'diverging', reason: 'financial data spans positive and negative' };\n        }\n        return { scheme: 'goldgreen', type: 'sequential', reason: 'financial data uses gold-green' };\n    }\n\n    // Score - evaluation metrics; diverging when hint says so (e.g., domain midpoint)\n    if (semanticType === 'Score') {\n        if (colorHint?.type === 'diverging') {\n            return { scheme: 'redblue', type: 'diverging', reason: 'score/rating diverging around midpoint' };\n        }\n        return { scheme: 'yelloworangebrown', type: 'sequential', reason: 'scores use warm sequential' };\n    }\n\n    // Rank - use single-hue sequential\n    if (semanticType === 'Rank') {\n        return { scheme: 'purples', type: 'sequential', reason: 'ranks use single-hue sequential' };\n    }\n\n    // Ranges - use sequential\n    if (semanticType === 'Range') {\n        return { scheme: 'blues', type: 'sequential', reason: 'range groups use sequential' };\n    }\n\n    // Temporal granules (Year, Month, Quarter, etc.) - sequential for continuity\n    if (ordinalTypes.has(semanticType) && ['Year', 'Quarter', 'Month', 'Week', 'Day', 'Hour', 'Decade'].includes(semanticType)) {\n        return { scheme: 'viridis', type: 'sequential', reason: 'temporal granules use perceptually uniform' };\n    }\n\n    // Geographic locations - use geographic-friendly palettes\n    if (getRegistryEntry(semanticType ?? '').t1 === 'GeoPlace') {\n        if (uniqueValueCount <= 10) {\n            return { scheme: 'set2', type: 'categorical', reason: 'geographic regions use distinct pastels' };\n        }\n        return { scheme: 'tableau20', type: 'categorical', reason: 'many regions use large categorical' };\n    }\n\n    // Status/Boolean - use accent colors for clear distinction\n    if (['Status', 'Boolean'].includes(semanticType)) {\n        return { scheme: 'set1', type: 'categorical', reason: 'status uses high-contrast categorical' };\n    }\n\n    // Categories - use standard categorical\n    if (semanticType === 'Category') {\n        return { \n            scheme: uniqueValueCount > 10 ? 'tableau20' : 'tableau10', \n            type: 'categorical', \n            reason: 'categories use standard categorical' \n        };\n    }\n\n    // Names (persons, companies, products) - use saturated schemes for readability\n    if (semanticType === 'Name') {\n        return { \n            scheme: uniqueValueCount > 8 ? 'tableau20' : 'set2', \n            type: 'categorical', \n            reason: 'names use readable categorical' \n        };\n    }\n\n    // Duration - use sequential (longer = more intense)\n    if (semanticType === 'Duration') {\n        return { scheme: 'oranges', type: 'sequential', reason: 'duration uses intensity-based sequential' };\n    }\n\n    // Quantity/Count/Distance/etc. - general measures\n    // Check colorHint first — signed measures (Profit, Sentiment, Correlation,\n    // PercentageChange) pass through here and should honor their diverging hint.\n    if (measureTypes.has(semanticType)) {\n        if (colorHint?.type === 'diverging') {\n            return { scheme: 'redblue', type: 'diverging', reason: 'measure with diverging nature' };\n        }\n        const sequentialSchemes = ['viridis', 'blues', 'greens', 'reds', 'yelloworangebrown', 'goldgreen'];\n        return { \n            scheme: pickScheme(sequentialSchemes, fieldName), \n            type: 'sequential', \n            reason: 'measures use perceptually uniform sequential' \n        };\n    }\n\n    // Ordinal types not already handled\n    if (ordinalTypes.has(semanticType) || encodingType === 'ordinal') {\n        const ordinalSchemes = ['blues', 'greens', 'purples', 'oranges'];\n        return { \n            scheme: pickScheme(ordinalSchemes, fieldName), \n            type: 'sequential', \n            reason: 'ordinal data uses sequential scheme' \n        };\n    }\n\n    // Default categorical for nominal\n    if (encodingType === 'nominal' || encodingType === 'temporal') {\n        return { \n            scheme: uniqueValueCount > 10 ? 'tableau20' : 'tableau10', \n            type: 'categorical', \n            reason: 'default categorical palette' \n        };\n    }\n\n    // Fallback\n    return { scheme: 'viridis', type: 'sequential', reason: 'universal fallback' };\n}\n\n// getRecommendedColorSchemeWithMidpoint: REMOVED — diverging midpoint is now\n// resolved via resolveDivergingInfo() in field-semantics.ts and applied directly\n// by the caller in resolve-semantics.ts. See resolveChannelSemantics().\n\n// ===========================================================================\n// Canonical Ordinal Sort Orders\n// ===========================================================================\n\n/**\n * Well-known canonical ordinal sequences.\n *\n * Used to detect when data values belong to a known ordinal domain\n * (months, days of the week, quarters, etc.) and sort them in their\n * natural order instead of alphabetically or by a quantitative axis.\n */\n\n/** Full and abbreviated English month names (case-insensitive lookup). */\nconst MONTH_FULL = ['January','February','March','April','May','June','July','August','September','October','November','December'];\nconst MONTH_ABBR3 = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];\nconst MONTH_NUM = ['1','2','3','4','5','6','7','8','9','10','11','12'];\n\n/** Full and abbreviated English day-of-week names. */\nconst DOW_FULL = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'];\nconst DOW_ABBR3 = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'];\nconst DOW_ABBR2 = ['Mo','Tu','We','Th','Fr','Sa','Su'];\n\n/** Sunday-first variant (US convention). */\nconst DOW_FULL_SUN = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];\nconst DOW_ABBR3_SUN = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];\n\n/** Quarter labels. */\nconst QUARTER_LABELS = ['Q1','Q2','Q3','Q4'];\n\n/** Compass directions — clockwise from North (top of chart). */\nconst COMPASS_8 = ['N','NE','E','SE','S','SW','W','NW'];\nconst COMPASS_8_FULL = ['North','Northeast','East','Southeast','South','Southwest','West','Northwest'];\nconst COMPASS_4 = ['N','E','S','W'];\nconst COMPASS_4_FULL = ['North','East','South','West'];\n\ninterface OrdinalSequence {\n    /** Canonical labels in order */\n    labels: string[];\n    /** Case-insensitive matching */\n    caseInsensitive: boolean;\n}\n\n/** All known ordinal sequences, keyed by semantic type. */\nconst ORDINAL_SEQUENCES: Record<string, OrdinalSequence[]> = {\n    Month: [\n        { labels: MONTH_FULL, caseInsensitive: true },\n        { labels: MONTH_ABBR3, caseInsensitive: true },\n        { labels: MONTH_NUM, caseInsensitive: false },\n    ],\n    Day: [\n        { labels: DOW_FULL, caseInsensitive: true },\n        { labels: DOW_ABBR3, caseInsensitive: true },\n        { labels: DOW_ABBR2, caseInsensitive: true },\n        { labels: DOW_FULL_SUN, caseInsensitive: true },\n        { labels: DOW_ABBR3_SUN, caseInsensitive: true },\n    ],\n    Quarter: [\n        { labels: QUARTER_LABELS, caseInsensitive: true },\n    ],\n    Direction: [\n        { labels: COMPASS_8, caseInsensitive: true },\n        { labels: COMPASS_8_FULL, caseInsensitive: true },\n        { labels: COMPASS_4, caseInsensitive: true },\n        { labels: COMPASS_4_FULL, caseInsensitive: true },\n    ],\n};\n\n/**\n * Build a case-insensitive lookup map from a sequence's labels.\n * Returns map: lowercased label → index.\n */\nfunction buildLookup(seq: OrdinalSequence): Map<string, number> {\n    const m = new Map<string, number>();\n    for (let i = 0; i < seq.labels.length; i++) {\n        const key = seq.caseInsensitive ? seq.labels[i].toLowerCase() : seq.labels[i];\n        m.set(key, i);\n    }\n    return m;\n}\n\n/**\n * Try to match a set of data values against a well-known ordinal sequence.\n *\n * Returns the canonical sort order (subset of the sequence, in order) if\n * enough values match, or `undefined` if no match.\n *\n * Matching rules:\n * - At least 60% of unique data values must be found in the sequence\n * - All matched values are returned in canonical order\n * - Unmatched values are appended at the end (preserving data order)\n *\n * @param values     The data values (strings or numbers) on this channel\n * @param sequences  The candidate sequences for the semantic type\n */\nfunction matchSequence(values: any[], sequences: OrdinalSequence[]): string[] | undefined {\n    const uniqueValues = [...new Set(values.map(v => v != null ? String(v) : ''))].filter(v => v !== '');\n    if (uniqueValues.length === 0) return undefined;\n\n    for (const seq of sequences) {\n        const lookup = buildLookup(seq);\n        const matched: { value: string; index: number }[] = [];\n        const unmatched: string[] = [];\n\n        for (const val of uniqueValues) {\n            const key = seq.caseInsensitive ? val.toLowerCase() : val;\n            const idx = lookup.get(key);\n            if (idx !== undefined) {\n                matched.push({ value: val, index: idx });\n            } else {\n                unmatched.push(val);\n            }\n        }\n\n        // Require at least 60% match rate\n        if (matched.length >= uniqueValues.length * 0.6 && matched.length >= 2) {\n            // Sort matched values by canonical index\n            matched.sort((a, b) => a.index - b.index);\n            const result = matched.map(m => m.value);\n            // Append unmatched at the end\n            result.push(...unmatched);\n            return result;\n        }\n    }\n    return undefined;\n}\n\n/**\n * Infer a canonical ordinal sort order for a field based on its semantic type\n * and data values.\n *\n * Works for:\n * - Month names (full/abbreviated/numeric): Jan, Feb, ... or January, February, ...\n * - Day-of-week names (full/abbreviated): Mon, Tue, ... or Monday, Tuesday, ...\n * - Quarter labels: Q1, Q2, Q3, Q4\n *\n * Falls back to `undefined` if no known sequence is detected, letting the\n * caller use its own default sort logic.\n *\n * @param semanticType  The semantic type of the field (e.g. 'Month', 'Day')\n * @param values        The data values on this channel\n * @returns Sorted unique values in canonical order, or undefined\n */\nexport function inferOrdinalSortOrder(\n    semanticType: string,\n    values: any[],\n): string[] | undefined {\n    // 1. Check by explicit semantic type\n    const sequences = ORDINAL_SEQUENCES[semanticType];\n    if (sequences) {\n        return matchSequence(values, sequences);\n    }\n\n    // 2. Auto-detect: try all sequences if semantic type is generic\n    if (!semanticType || semanticType === 'Category' || semanticType === 'Unknown') {\n        for (const seqs of Object.values(ORDINAL_SEQUENCES)) {\n            const result = matchSequence(values, seqs);\n            if (result) return result;\n        }\n    }\n\n    return undefined;\n}\n\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * =============================================================================\n * REUSABLE DECISION LOGIC\n * =============================================================================\n *\n * Pure decision functions that determine chart layout behavior.\n * These functions take data/config inputs and return decision objects —\n * NO Vega-Lite spec mutation happens here.\n *\n * The separation ensures:\n * 1. Decision logic is testable in isolation\n * 2. Same decisions can drive different output formats (VL, SVG, etc.)\n * 3. Templates can call decision functions without coupling to VL\n *\n * Naming conventions:\n *   - `compute*()` — returns a decision/value from inputs\n *   - `resolve*()` — picks from alternatives (type resolution, etc.)\n *   - `classify*()` — categorizes an input\n * =============================================================================\n */\n\nimport {\n    inferVisCategory,\n    type VisCategory,\n} from './semantic-types';\nimport { getRegistryEntry, isRegistered } from './type-registry';\n\n// ---------------------------------------------------------------------------\n// Encoding Type Resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Result of encoding type resolution.\n * Separates the decision from what gets written into VL.\n */\nexport interface EncodingTypeDecision {\n    /** The resolved VL encoding type */\n    vlType: 'quantitative' | 'ordinal' | 'nominal' | 'temporal';\n    /** The VisCategory that drove the decision */\n    visCategory: VisCategory;\n    /** Whether the type was overridden by channel rules */\n    channelOverride: boolean;\n    /** Whether the type was overridden by cardinality/fraction guard */\n    cardinalityGuard: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers for encoding type resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Map a VisCategory to the corresponding VL encoding type string.\n * Geographic maps to quantitative since VL uses quantitative for coordinates.\n */\nfunction visCategoryToVLType(vc: VisCategory): 'quantitative' | 'ordinal' | 'nominal' | 'temporal' {\n    switch (vc) {\n        case 'quantitative': return 'quantitative';\n        case 'ordinal': return 'ordinal';\n        case 'temporal': return 'temporal';\n        case 'geographic': return 'quantitative';\n        case 'nominal':\n        default: return 'nominal';\n    }\n}\n\n/**\n * Validate that field values actually parse as dates.\n *\n * @param fromRegistry  If true, uses a looser threshold (≥30%) since the\n *                      semantic type explicitly identified the field as temporal.\n *                      If false (data-inferred), requires ≥50%.\n */\nfunction validateTemporalParsing(\n    data: any[],\n    fieldName: string,\n    fromRegistry: boolean,\n): boolean {\n    const sampleValues = data.map(r => r[fieldName]).slice(0, 15).filter((v: any) => v != null);\n    if (sampleValues.length === 0) return false;\n\n    // Single unique value → not useful as temporal axis (would show a single point)\n    const uniqueValues = new Set(sampleValues.map(String));\n    if (uniqueValues.size <= 1) return false;\n\n    const looksTemporalValue = (val: any): boolean => {\n        if (val instanceof Date) return true;\n        if (typeof val === 'number') {\n            // Year-like integers (1500–2200)\n            if (val >= 1500 && val <= 2200 && val % 1 === 0) return true;\n            // Unix-ms timestamps: 86_400_000 (Jan 2, 1970) to ~year 2103\n            if (val > 86400000 && val < 4200000000000) return true;\n            return false;\n        }\n        if (typeof val === 'string') {\n            const trimmed = val.trim();\n            if (!trimmed) return false;\n            if (/^\\d{4}$/.test(trimmed)) return true;\n            return !Number.isNaN(Date.parse(trimmed));\n        }\n        return false;\n    };\n\n    const passingCount = sampleValues.filter(looksTemporalValue).length;\n    const minFraction = fromRegistry ? 0.3 : 0.5;\n    return passingCount / sampleValues.length >= minFraction;\n}\n\n/**\n * Apply temporal channel-compatibility adjustments, shared by both\n * registry-driven and data-inferred temporal paths.\n */\nfunction resolveTemporalEncoding(\n    visCategory: VisCategory,\n    channel: string,\n    data: any[],\n    fieldName: string,\n    fromRegistry: boolean,\n): EncodingTypeDecision {\n    // Temporal on facet/size channels → ordinal (VL limitation)\n    if (['size', 'column', 'row'].includes(channel)) {\n        return { vlType: 'ordinal', visCategory, channelOverride: true, cardinalityGuard: false };\n    }\n    // Temporal on color with low cardinality → ordinal for distinct colors\n    if (channel === 'color') {\n        const uniqueCount = new Set(data.map(r => r[fieldName])).size;\n        if (uniqueCount <= 12) {\n            return { vlType: 'ordinal', visCategory, channelOverride: true, cardinalityGuard: false };\n        }\n    }\n    // Validate temporal parsing\n    if (!validateTemporalParsing(data, fieldName, fromRegistry)) {\n        return { vlType: 'ordinal', visCategory, channelOverride: false, cardinalityGuard: false };\n    }\n    return { vlType: 'temporal', visCategory, channelOverride: false, cardinalityGuard: false };\n}\n\n/**\n * Apply channel-context guards to an ordinal encoding.\n *\n * Even when the registry says a field is ordinal, channel context may\n * require promoting to quantitative:\n *   - High cardinality on color/group → unreadable legend\n *   - High cardinality on x/y        → bars/lollipops need proportional\n *     spacing and baseline anchoring (y2/x2)\n *   - Fractional values + high cardinality → mis-classified continuous measure\n *\n * @param fromRegistry  Whether the ordinal type came from the registry\n *        (true) or was data-inferred (false). Data-inferred additionally\n *        checks for fractional values (Guard 1).\n */\nfunction applyOrdinalGuards(\n    visCategory: VisCategory,\n    channel: string,\n    data: any[],\n    fieldName: string,\n    fieldValues: any[],\n    fromRegistry: boolean,\n): EncodingTypeDecision {\n    const numericVals = fieldValues.filter(v => v != null && !isNaN(+v)).map(Number);\n    if (numericVals.length > 0) {\n        const uniqueCount = new Set(numericVals).size;\n        const hasFractions = numericVals.some(v => v % 1 !== 0);\n\n        // Guard 1 (data-inferred only): fractional + high-cardinality →\n        // mis-classified continuous measure. Registry types are explicit,\n        // so this guard only applies when the type was inferred from data.\n        if (!fromRegistry && hasFractions && uniqueCount > 20) {\n            return { vlType: 'quantitative', visCategory, channelOverride: false, cardinalityGuard: true };\n        }\n\n        // Guard 2: integer ordinal with high cardinality on color/group →\n        // a discrete legend with 12+ entries is unreadable; promote to\n        // quantitative so VL renders a continuous gradient instead.\n        if (!hasFractions && uniqueCount > 12 && ['color', 'group'].includes(channel)) {\n            return { vlType: 'quantitative', visCategory, channelOverride: true, cardinalityGuard: true };\n        }\n\n        // Guard 3: integer ordinal with high cardinality on position\n        // axes (x, y) → charts like bar/lollipop need a quantitative\n        // axis for proportional length; treating 12+ unique integers\n        // as discrete categories produces an unreadable axis and\n        // prevents baseline anchoring (y2/x2).\n        if (!hasFractions && uniqueCount > 12 && ['x', 'y'].includes(channel)) {\n            return { vlType: 'quantitative', visCategory, channelOverride: true, cardinalityGuard: true };\n        }\n    }\n    return { vlType: 'ordinal', visCategory, channelOverride: false, cardinalityGuard: false };\n}\n\n/**\n * Disambiguate when the registry lists multiple visEncodings for a type.\n *\n * Uses channel context and data characteristics to select the most\n * appropriate encoding from the candidates. Each combination of\n * candidate encodings has dedicated logic:\n *\n *   temporal + ordinal  (Year, YearMonth, Decade, …)\n *   quantitative + ordinal  (Score, Rating)\n *   quantitative + geographic  (Latitude, Longitude)\n *   ordinal + nominal  (Direction)\n */\nfunction disambiguateMultiEncoding(\n    candidates: VisCategory[],\n    channel: string,\n    data: any[],\n    fieldName: string,\n    fieldValues: any[],\n): EncodingTypeDecision {\n    const has = (vc: VisCategory) => candidates.includes(vc);\n\n    // ── Temporal + Ordinal (Year, YearMonth, Decade, etc.) ────────\n    // Time-unit granules. Temporal for continuous time axes (x/y);\n    // ordinal for grouping channels (color, facet, size).\n    if (has('temporal') && has('ordinal')) {\n        return resolveTemporalEncoding('temporal', channel, data, fieldName, true);\n    }\n\n    // ── Quantitative + Ordinal (Score, Rating) ────────────────────\n    // Bounded discrete numerics. Use ordinal for grouping channels\n    // with low cardinality (distinct colors/symbols); quantitative\n    // for position axes (proportional spacing, zero-baseline).\n    if (has('quantitative') && has('ordinal')) {\n        if (['color', 'group'].includes(channel)) {\n            const uniqueCount = new Set(data.map(r => r[fieldName])).size;\n            if (uniqueCount <= 12) {\n                return { vlType: 'ordinal', visCategory: 'ordinal', channelOverride: false, cardinalityGuard: false };\n            }\n            // High-cardinality Score/Rating on color → quantitative gradient\n            return { vlType: 'quantitative', visCategory: 'quantitative', channelOverride: false, cardinalityGuard: true };\n        }\n        if (['column', 'row'].includes(channel)) {\n            return { vlType: 'ordinal', visCategory: 'ordinal', channelOverride: false, cardinalityGuard: false };\n        }\n        // x, y, size → quantitative (proportional axis)\n        return { vlType: 'quantitative', visCategory: 'quantitative', channelOverride: false, cardinalityGuard: false };\n    }\n\n    // ── Quantitative + Geographic (Latitude, Longitude) ───────────\n    // Geographic is for map projections; standard encodings use quantitative.\n    if (has('quantitative') && has('geographic')) {\n        return { vlType: 'quantitative', visCategory: 'quantitative', channelOverride: false, cardinalityGuard: false };\n    }\n\n    // ── Ordinal + Nominal (Direction) ─────────────────────────────\n    // Inherently ordered, but nominal for grouping channels to get\n    // distinct (unordered) colors rather than a sequential scale.\n    if (has('ordinal') && has('nominal')) {\n        if (['color', 'group'].includes(channel)) {\n            return { vlType: 'nominal', visCategory: 'nominal', channelOverride: false, cardinalityGuard: false };\n        }\n        return { vlType: 'ordinal', visCategory: 'ordinal', channelOverride: false, cardinalityGuard: false };\n    }\n\n    // ── Fallback: first candidate ─────────────────────────────────\n    const fallback = candidates[0];\n    return { vlType: visCategoryToVLType(fallback), visCategory: fallback, channelOverride: false, cardinalityGuard: false };\n}\n\n// ---------------------------------------------------------------------------\n// Main API\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the VL encoding type for a field.\n *\n * Two-stage pipeline:\n *\n * **Stage 1 — Registry-driven** (when semanticType is registered):\n *   - Single visEncoding  → use it directly (with channel adjustments)\n *   - Multiple visEncodings → `disambiguateMultiEncoding()` selects best\n *     option using channel context + data characteristics\n *\n * **Stage 2 — Data-inferred fallback** (no registered semantic type):\n *   - `inferVisCategory()` inspects raw values → VisCategory\n *   - Heuristic guards catch common mis-classifications (e.g., dense\n *     fractional data inferred as ordinal)\n *\n * This is a pure decision — it does NOT mutate any spec.\n *\n * @param semanticType   Semantic type string (e.g. 'Quantity', 'Country')\n * @param fieldValues    Sampled values from the field\n * @param channel        VL channel name (e.g. 'x', 'y', 'color')\n * @param data           Full data table (for computing unique value counts)\n * @param fieldName      Field name (for data lookups)\n */\nexport function resolveEncodingType(\n    semanticType: string,\n    fieldValues: any[],\n    channel: string,\n    data: any[],\n    fieldName: string,\n): EncodingTypeDecision {\n    // ═══════════════════════════════════════════════════════════════════\n    // Stage 1: Registry-driven resolution\n    // ═══════════════════════════════════════════════════════════════════\n    // The registry's visEncodings array is the source of truth.\n    //   - Single encoding  → resolved directly\n    //   - Multiple encodings → disambiguated by channel + data\n    if (semanticType && isRegistered(semanticType)) {\n        const entry = getRegistryEntry(semanticType);\n        const candidates = entry.visEncodings;\n\n        if (candidates.length > 1) {\n            // Multiple encodings listed — disambiguate semantically\n            return disambiguateMultiEncoding(candidates, channel, data, fieldName, fieldValues);\n        }\n\n        // Single encoding — use it directly with channel adjustments\n        const baseType = candidates[0];\n\n        // Guard: if the registry says quantitative but the actual values\n        // are strings (e.g. semantic \"Quantity\" on a binned field like\n        // \"91-95\"), fall back to data-inferred type.  Numeric strings\n        // that parse as numbers (e.g. \"42\") still count as numeric.\n        if (baseType === 'quantitative') {\n            const nonNull = fieldValues.filter(v => v != null);\n            const allNumeric = nonNull.length > 0 &&\n                nonNull.every(v => typeof v === 'number' || (typeof v === 'string' && !isNaN(+v) && v.trim() !== ''));\n            if (!allNumeric) {\n                // Values aren't actually numeric — infer from data instead\n                const inferred = inferVisCategory(fieldValues);\n                return {\n                    vlType: visCategoryToVLType(inferred),\n                    visCategory: inferred,\n                    channelOverride: false,\n                    cardinalityGuard: false,\n                };\n            }\n        }\n\n        if (baseType === 'temporal') {\n            return resolveTemporalEncoding(baseType, channel, data, fieldName, true);\n        }\n        if (baseType === 'ordinal') {\n            return applyOrdinalGuards(baseType, channel, data, fieldName, fieldValues, true);\n        }\n        return {\n            vlType: visCategoryToVLType(baseType),\n            visCategory: baseType,\n            channelOverride: false,\n            cardinalityGuard: false,\n        };\n    }\n\n    // ═══════════════════════════════════════════════════════════════════\n    // Stage 2: Data-inferred fallback\n    // ═══════════════════════════════════════════════════════════════════\n    // No registered semantic type — infer from raw data values, then\n    // apply heuristic guards for common data-inference mis-classifications.\n    const visCategory: VisCategory = inferVisCategory(fieldValues);\n    const channelOverride = false;\n    const cardinalityGuard = false;\n\n    switch (visCategory) {\n        case 'temporal':\n            return resolveTemporalEncoding(visCategory, channel, data, fieldName, false);\n\n        case 'ordinal':\n            return applyOrdinalGuards(visCategory, channel, data, fieldName, fieldValues, false);\n\n        case 'quantitative':\n            return { vlType: 'quantitative', visCategory, channelOverride, cardinalityGuard };\n\n        case 'geographic':\n            return { vlType: 'quantitative', visCategory, channelOverride, cardinalityGuard };\n\n        case 'nominal':\n        default:\n            return { vlType: 'nominal', visCategory, channelOverride, cardinalityGuard };\n    }\n}\n\n// ---------------------------------------------------------------------------\n// Continuous Axis Gas Pressure Model (docs/design-stretch-model.md §2)\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for the per-axis stretch model (docs/design-stretch-model.md §2).\n *\n * Each axis is stretched independently based on how many distinguishable\n * positions (or series) compete for pixel space along that axis.\n */\nexport interface GasPressureParams {\n    /** Mark cross-section in px² — used as default σ for both axes (default: 30) */\n    markCrossSection: number;\n    /** Per-axis cross-section overrides. When set, the per-axis stretch\n     *  uses these instead of `markCrossSection`.\n     *  Useful for line charts where X needs more stretch than Y. */\n    markCrossSectionX?: number;\n    markCrossSectionY?: number;\n    /** Override X item count for stretch.\n     *  When set, X stretch uses this count (e.g. number of series)\n     *  instead of counting unique X pixel positions. */\n    xItemCountOverride?: number;\n    /** Override Y item count for stretch.\n     *  When set, Y stretch uses this count (e.g. number of series)\n     *  instead of counting unique Y pixel positions. */\n    yItemCountOverride?: number;\n    /** Power-law exponent for continuous stretch (default: 0.3) */\n    elasticity: number;\n    /** Maximum stretch multiplier cap (default: 1.5) */\n    maxStretch: number;\n}\n\n/** Default gas pressure parameters (§2 recommendations). */\nexport const DEFAULT_GAS_PRESSURE_PARAMS: GasPressureParams = {\n    markCrossSection: 30,\n    elasticity: 0.3,\n    maxStretch: 1.5,\n};\n\n/**\n * Result of the per-axis stretch decision.\n */\nexport interface GasPressureDecision {\n    /** Per-axis stretch: X axis (1 = no stretch, capped by maxStretch) */\n    stretchX: number;\n    /** Per-axis stretch: Y axis (1 = no stretch, capped by maxStretch) */\n    stretchY: number;\n    /** Uncapped stretch for X (raw pressure^elasticity, not clipped to maxStretch).\n     *  Used by the layout engine to compute ideal aspect ratio before squeezing. */\n    rawStretchX: number;\n    /** Uncapped stretch for Y (raw pressure^elasticity, not clipped to maxStretch). */\n    rawStretchY: number;\n}\n\n/**\n * Compute per-axis stretch for a continuous 2D axis region.\n *\n * Implements docs/design-stretch-model.md §2: each axis is stretched independently based\n * on how many distinguishable positions (or series) compete for pixel\n * space along that axis.\n *\n * Two modes per axis:\n *   - Positional: count unique pixel positions, σ_1d = √σ.\n *   - Series-count: when xItemCountOverride / yItemCountOverride is set,\n *     use that count directly with σ (not sqrt'd) since it's already 1D.\n *\n * @param xValues      Numeric x-coordinates of data points\n * @param yValues      Numeric y-coordinates of data points\n * @param xDomain      Scale domain [min, max] for x-axis\n * @param yDomain      Scale domain [min, max] for y-axis\n * @param canvasWidth  Base canvas width W₀\n * @param canvasHeight Base canvas height H₀\n * @param params       Gas pressure parameters (optional, uses defaults)\n */\nexport function computeGasPressure(\n    xValues: number[],\n    yValues: number[],\n    xDomain: [number, number],\n    yDomain: [number, number],\n    canvasWidth: number,\n    canvasHeight: number,\n    params: GasPressureParams = DEFAULT_GAS_PRESSURE_PARAMS,\n): GasPressureDecision {\n    const N = xValues.length;\n\n    if (N <= 1 || canvasWidth <= 0 || canvasHeight <= 0) {\n        return { stretchX: 1, stretchY: 1, rawStretchX: 1, rawStretchY: 1 };\n    }\n\n    // Per-axis stretch via unique-position linear packing.\n    // The question for each axis is: \"how many distinguishable positions\n    // compete for pixel space along this axis?\"\n    //\n    // Count unique positions (bucketed to ~1px resolution) along each\n    // axis. Each unique position needs σ_1d ≈ √σ pixels of space.\n    // 1D pressure = uniquePositions × σ_1d / axisDimension.\n    const sigma1dDefault = Math.sqrt(params.markCrossSection); // ~5 px\n\n    /** Returns [cappedStretch, rawStretch] for one axis. */\n    const computeAxisStretch = (values: number[], domain: [number, number], baseDim: number, sigma1d: number): [number, number] => {\n        if (baseDim <= 0 || values.length <= 1) return [1, 1];\n\n        const range = domain[1] - domain[0];\n        if (range <= 0) return [1, 1];\n\n        // Bucket values to ~1px resolution in pixel space\n        const pxPerUnit = baseDim / range;\n        const seen = new Set<number>();\n        for (const v of values) {\n            seen.add(Math.round((v - domain[0]) * pxPerUnit));\n        }\n        const uniquePositions = seen.size;\n\n        // 1D pressure: how many sigma-sized marks fight for baseDim pixels\n        const pressure = (uniquePositions * sigma1d) / baseDim;\n        if (pressure <= 1) return [1, 1];\n        const raw = Math.pow(pressure, params.elasticity);\n        return [Math.min(params.maxStretch, raw), raw];\n    };\n\n    const sigma1dX = params.markCrossSectionX != null ? Math.sqrt(params.markCrossSectionX) : sigma1dDefault;\n    const sigma1dY = params.markCrossSectionY != null ? Math.sqrt(params.markCrossSectionY) : sigma1dDefault;\n\n    // Helper: compute stretch for one axis, using series-count override if set.\n    // When a series override is provided, σ is used directly (not sqrt'd)\n    // because series count is already a 1D concept.\n    /** Returns [cappedStretch, rawStretch] for one axis, with series-count override support. */\n    const computeStretchForAxis = (\n        values: number[], domain: [number, number], baseDim: number,\n        sigma1d: number, sigmaRaw: number, itemCountOverride?: number,\n    ): [number, number] => {\n        if (itemCountOverride != null && sigmaRaw > 0) {\n            const pressure = (itemCountOverride * sigmaRaw) / baseDim;\n            if (pressure <= 1) return [1, 1];\n            const raw = Math.pow(pressure, params.elasticity);\n            return [Math.min(params.maxStretch, raw), raw];\n        }\n        return sigma1d > 0 ? computeAxisStretch(values, domain, baseDim, sigma1d) : [1, 1];\n    };\n\n    const sigmaRawX = params.markCrossSectionX ?? params.markCrossSection;\n    const sigmaRawY = params.markCrossSectionY ?? params.markCrossSection;\n    const [stretchX, rawStretchX] = computeStretchForAxis(xValues, xDomain, canvasWidth, sigma1dX, sigmaRawX, params.xItemCountOverride);\n    const [stretchY, rawStretchY] = computeStretchForAxis(yValues, yDomain, canvasHeight, sigma1dY, sigmaRawY, params.yItemCountOverride);\n\n    return { stretchX, stretchY, rawStretchX, rawStretchY };\n}\n\n// ---------------------------------------------------------------------------\n// Elastic Stretch Computation\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for elastic axis stretch computation.\n * These control the spring-model behavior from docs/design-stretch-model.md §1.\n */\nexport interface ElasticStretchParams {\n    /** Power-law exponent for stretch (default: 0.5) */\n    elasticity: number;\n    /** Maximum stretch multiplier cap (default: 2) */\n    maxStretch: number;\n    /** Default step size in px per discrete item */\n    defaultStepSize: number;\n    /** Minimum pixels per discrete item (default: 6) */\n    minStep: number;\n}\n\n/**\n * Result of elastic budget computation for a single axis.\n */\nexport interface ElasticBudget {\n    /** Elastic-stretched canvas budget in px */\n    budget: number;\n    /** Stretch multiplier applied (1 = no stretch) */\n    stretchFactor: number;\n}\n\n/**\n * Compute the elastic canvas budget for an axis with N discrete items.\n *\n * When N items at defaultStepSize exceed the base dimension, the axis\n * stretches using a power-law: stretch = min(maxStretch, pressure^elasticity).\n *\n * @param itemCount       Number of discrete items on the axis\n * @param baseDimension   Base canvas size (width or height) in px\n * @param params          Elastic stretch parameters\n */\nexport function computeElasticBudget(\n    itemCount: number,\n    baseDimension: number,\n    params: ElasticStretchParams,\n): ElasticBudget {\n    if (itemCount <= 0) {\n        return { budget: baseDimension, stretchFactor: 1 };\n    }\n    const pressure = (itemCount * params.defaultStepSize) / baseDimension;\n    if (pressure <= 1) {\n        return { budget: baseDimension, stretchFactor: 1 };\n    }\n    const stretchFactor = Math.min(params.maxStretch, Math.pow(pressure, params.elasticity));\n    return {\n        budget: baseDimension * stretchFactor,\n        stretchFactor,\n    };\n}\n\n/**\n * Result of per-axis step computation.\n */\nexport interface AxisStepDecision {\n    /** Computed step size in px per item */\n    step: number;\n    /** Total canvas budget in px */\n    budget: number;\n    /** Number of items this step was computed for */\n    itemCount: number;\n}\n\n/**\n * Compute the step size for a single axis, covering both discrete\n * and continuous-as-discrete (banded) cases.\n *\n * @param nominalCount       Number of discrete (nominal/ordinal) items\n * @param continuousCount    Number of continuous-as-discrete items (banded Q/T)\n * @param baseDimension      Base canvas size (width or height) in px\n * @param params             Elastic stretch parameters\n */\nexport function computeAxisStep(\n    nominalCount: number,\n    continuousCount: number,\n    baseDimension: number,\n    params: ElasticStretchParams,\n): AxisStepDecision {\n    if (nominalCount > 0) {\n        const { budget } = computeElasticBudget(nominalCount, baseDimension, params);\n        return { step: Math.floor(budget / nominalCount), budget, itemCount: nominalCount };\n    }\n    if (continuousCount > 0) {\n        const { budget } = computeElasticBudget(continuousCount, baseDimension, params);\n        return { step: Math.floor(budget / continuousCount), budget, itemCount: continuousCount };\n    }\n    return { step: params.defaultStepSize, budget: baseDimension, itemCount: 0 };\n}\n\n// ---------------------------------------------------------------------------\n// Facet Layout Decisions\n// ---------------------------------------------------------------------------\n\n/**\n * Result of facet layout computation.\n */\nexport interface FacetLayoutDecision {\n    /** Number of facet columns */\n    columns: number;\n    /** Number of facet rows */\n    rows: number;\n    /** Per-subplot width in px */\n    subplotWidth: number;\n    /** Per-subplot height in px */\n    subplotHeight: number;\n}\n\n/**\n * Parameters for facet layout computation.\n */\nexport interface FacetLayoutParams {\n    /** Power-law exponent for facet stretch (default: 0.3) */\n    facetElasticity: number;\n    /** Maximum total stretch multiplier cap (default: 2) */\n    maxStretch: number;\n    /** Minimum subplot size in px (default: 60) */\n    minSubplotSize: number;\n}\n\n/**\n * Compute facet subplot dimensions.\n *\n * @param facetCols       Number of facet columns\n * @param facetRows       Number of facet rows\n * @param baseWidth       Base canvas width in px\n * @param baseHeight      Base canvas height in px\n * @param params          Facet layout parameters\n */\nexport function computeFacetLayout(\n    facetCols: number,\n    facetRows: number,\n    baseWidth: number,\n    baseHeight: number,\n    params: FacetLayoutParams,\n): FacetLayoutDecision {\n    // Minimum subplot dimension — use the caller-supplied parameter\n    // (default 60px) so subplots remain readable.\n    const minContinuousSize = params.minSubplotSize;\n\n    let subplotWidth: number;\n    if (facetCols > 1) {\n        const stretch = Math.min(params.maxStretch, Math.pow(facetCols, params.facetElasticity));\n        subplotWidth = Math.round(Math.max(minContinuousSize, baseWidth * stretch / facetCols));\n    } else {\n        subplotWidth = baseWidth;\n    }\n\n    let subplotHeight: number;\n    if (facetRows > 1) {\n        const stretch = Math.min(params.maxStretch, Math.pow(facetRows, params.facetElasticity));\n        subplotHeight = Math.round(Math.max(minContinuousSize, baseHeight * stretch / facetRows));\n    } else {\n        subplotHeight = baseHeight;\n    }\n\n    return { columns: facetCols, rows: facetRows, subplotWidth, subplotHeight };\n}\n\n// ---------------------------------------------------------------------------\n// Label Sizing Decisions\n// ---------------------------------------------------------------------------\n\n/**\n * Result of label sizing computation for a discrete axis.\n */\nexport interface LabelSizingDecision {\n    /** Font size in px */\n    fontSize: number;\n    /** Max label width in px */\n    labelLimit: number;\n    /** Label rotation angle (undefined = no rotation) */\n    labelAngle?: number;\n    /** Label alignment (for rotated labels) */\n    labelAlign?: string;\n    /** Label baseline (for rotated labels) */\n    labelBaseline?: string;\n}\n\n/**\n * Compute label sizing for a discrete axis based on the effective step size.\n * Pure decision — returns sizing params without modifying any spec.\n *\n * The font descends the **shrink → rotate → cap** ladder from a backend-native\n * base font (`baseFont`), never exceeding it and never dropping below `minFont`:\n *   1. Wide band  → horizontal label at (up to) `baseFont`.\n *   2. Medium band → shrink a little and rotate -45°.\n *   3. Narrow band → shrink more and rotate -90°.\n * `labelLimit` caps the label width so long text is truncated (…) rather than\n * overflowing arbitrarily.\n *\n * @param effectiveStep      Pixels per discrete item\n * @param hasDiscreteItems   Whether the axis has discrete items\n * @param opts               `baseFont` (native ceiling) and `minFont` (floor)\n */\nexport function computeLabelSizing(\n    effectiveStep: number,\n    hasDiscreteItems: boolean,\n    opts?: { baseFont?: number; minFont?: number },\n): LabelSizingDecision {\n    const baseFont = opts?.baseFont ?? 10;\n    const minFont = opts?.minFont ?? 6;\n    const defaultLimit = 100;\n\n    if (!hasDiscreteItems) {\n        return { fontSize: baseFont, labelLimit: defaultLimit };\n    }\n\n    // Shrink lever: font tracks the band step but is bounded by [minFont, baseFont].\n    let fontSize = Math.max(minFont, Math.min(baseFont, effectiveStep - 1));\n    let labelLimit = Math.max(30, Math.min(100, effectiveStep * 8));\n    let labelAngle: number | undefined;\n    let labelAlign: string | undefined;\n    let labelBaseline: string | undefined;\n\n    if (effectiveStep < 10) {\n        // Narrow band → rotate vertical, shrink harder (but keep the ceiling\n        // one notch below base so a 12-native backend still reads ~10 here).\n        labelAngle = -90;\n        fontSize = Math.max(minFont, Math.min(baseFont - 2, effectiveStep));\n        labelLimit = 40;\n        labelAlign = 'right';\n        labelBaseline = 'middle';\n    } else if (effectiveStep < 16) {\n        // Medium band → rotate 45°, shrink slightly.\n        labelAngle = -45;\n        fontSize = Math.max(minFont, Math.min(baseFont - 1, effectiveStep));\n        labelLimit = 60;\n        labelAlign = 'right';\n        labelBaseline = 'top';\n    }\n\n    return { fontSize, labelLimit, labelAngle, labelAlign, labelBaseline };\n}\n\n/**\n * Canvas-adaptive font sizes for headers (axis titles, legend, chart title) and\n * the base for axis tick labels.\n *\n * The per-backend base fonts are the preferred (native) sizes. Fonts render at\n * that base and only **shrink** for genuinely small small-multiple subplots\n * (so dense facets don't overflow); they are never grown above native, matching\n * how the underlying renderers keep fonts constant across canvas sizes.\n *\n * @param minPlotDimension  The smaller of the (sub)plot width/height in px\n * @param opts              Backend-native base font sizes\n */\nexport interface FontSizingDecision {\n    /** Ceiling for axis tick labels (feeds computeLabelSizing `baseFont`). */\n    tickBase: number;\n    /** Header font for axis titles and chart title. */\n    titleFontSize: number;\n    /** Legend entry font (one notch below the title). */\n    legendFontSize: number;\n}\n\nexport function computeFontSizing(\n    minPlotDimension: number,\n    opts?: { baseLabelFontSize?: number; baseTitleFontSize?: number },\n): FontSizingDecision {\n    const baseLabel = opts?.baseLabelFontSize ?? 10;\n    const baseTitle = opts?.baseTitleFontSize ?? 11;\n    // The per-backend base fonts ARE the preferred (native) sizes: native\n    // renderers (Plotly/VL/ECharts) keep tick/title/legend fonts CONSTANT at\n    // every canvas size. So we do NOT grow above base — growth made large\n    // charts render heavy, oversized text. Fonts only SHRINK for genuinely\n    // small small-multiple subplots (minDim < 220) so dense facets don't\n    // overflow; otherwise they render at native base.\n    const minDim = minPlotDimension || 320;\n    const ratio = minDim >= 220 ? 1 : Math.max(0.7, minDim / 220);\n    const atMostNative = (base: number) =>\n        Math.round(Math.max(base - 2, Math.min(base, base * ratio)));\n    const tickBase = atMostNative(baseLabel);\n    const titleFontSize = atMostNative(baseTitle);\n    const legendFontSize = Math.max(baseTitle - 2, titleFontSize - 1);\n    return { tickBase, titleFontSize, legendFontSize };\n}\n\n// ---------------------------------------------------------------------------\n// Overflow Decision\n// ---------------------------------------------------------------------------\n\n/**\n * Result of overflow analysis for a discrete axis.\n */\nexport interface OverflowDecision {\n    /** Whether overflow occurred (more items than can fit) */\n    overflowed: boolean;\n    /** Maximum items to keep */\n    maxToKeep: number;\n    /** Number of items omitted */\n    omittedCount: number;\n}\n\n/**\n * Compute whether a discrete axis overflows and how many items to keep.\n *\n * @param uniqueCount    Number of unique values on the axis\n * @param maxDimension   Maximum canvas dimension (with stretch) in px\n * @param minStepSize    Minimum px per item\n */\nexport function computeOverflow(\n    uniqueCount: number,\n    maxDimension: number,\n    minStepSize: number,\n): OverflowDecision {\n    const maxToKeep = Math.floor(maxDimension / minStepSize);\n    const overflowed = uniqueCount > maxToKeep;\n    return {\n        overflowed,\n        maxToKeep,\n        omittedCount: overflowed ? uniqueCount - maxToKeep : 0,\n    };\n}\n\n// ---------------------------------------------------------------------------\n// Circumference-pressure model for radial charts (§3)\n// ---------------------------------------------------------------------------\n\n/**\n * Parameters for circumference-pressure scaling (spring model on polar axis).\n */\nexport interface CircumferencePressureParams {\n    /** Minimum arc-length (px) each \"effective bar\" needs on the\n     *  circumference — analogous to defaultStepSize in the spring model.\n     *  Default: 45 */\n    minArcPx?: number;\n    /** Minimum chart radius in px. Default: 60 */\n    minRadius?: number;\n    /** Maximum chart radius in px. Caps runaway growth. Default: 400 */\n    maxRadius?: number;\n    /** Power-law exponent for pressure → stretch (same as spring model).\n     *  0.5 = square-root growth. Default: 0.5 */\n    elasticity?: number;\n    /** Per-dimension maximum stretch multiplier cap (matches bar-chart\n     *  default of 2.0).  The effective max stretch on the radius is\n     *  derived from min(baseW, baseH) × maxStretch so that the chart\n     *  never exceeds the cap in either dimension.  Default: 2.0 */\n    maxStretch?: number;\n    /** Per-dimension cap for the width axis. Defaults to `maxStretch`.\n     *  Lets the radius ceiling honor an asymmetric canvas (canvasW/baseW). */\n    maxStretchX?: number;\n    /** Per-dimension cap for the height axis. Defaults to `maxStretch`.\n     *  Lets the radius ceiling honor an asymmetric canvas (canvasH/baseH). */\n    maxStretchY?: number;\n    /** Extra margin outside the chart circle (px) for labels, legend, etc.\n     *  Added to each side when computing canvas dimensions. Default: 20 */\n    margin?: number;\n}\n\n/**\n * Result of circumference pressure computation.\n */\nexport interface CircumferencePressureResult {\n    /** Computed chart radius in px */\n    radius: number;\n    /** Recommended canvas width (px) */\n    canvasW: number;\n    /** Recommended canvas height (px) */\n    canvasH: number;\n}\n\n/**\n * Compute radial chart sizing using the spring model mapped to a polar axis.\n *\n * Treats the circumference as a linear \"bar axis\":\n *   baseCircumference = 2π × baseRadius\n *   pressure = effectiveItemCount × minArcPx / baseCircumference\n *   if pressure > 1:  stretch = min(maxStretch, pressure ^ elasticity)\n *   radius = baseRadius × stretch\n *\n * **effectiveItemCount** varies by chart type:\n *   - Rose / Radar: N categories (uniform slices/spokes)\n *   - Pie: total / minValue — how many of the smallest slice fit in the\n *     full circle.  This captures the worst-case thin slice that needs\n *     minimum arc width.\n *   - Sunburst: same as pie but computed on the outer ring leaves only.\n *\n * Both canvas dimensions grow equally (maintains 1:1 circular aspect).\n *\n * @param effectiveItemCount  Effective number of uniform \"bars\" around\n *                            the circle (see above)\n * @param canvasSize          Base canvas dimensions (from context)\n * @param params              Optional tuning parameters\n */\nexport function computeCircumferencePressure(\n    effectiveItemCount: number,\n    canvasSize: { width: number; height: number },\n    params: CircumferencePressureParams = {},\n): CircumferencePressureResult {\n    const {\n        minArcPx = 45,\n        minRadius = 60,\n        maxRadius = 400,\n        elasticity = 0.5,\n        maxStretch = 2.0,\n        margin = 20,\n    } = params;\n\n    // Per-dimension caps default to the scalar maxStretch (symmetric canvas).\n    const maxStretchX = Math.max(1, params.maxStretchX ?? maxStretch);\n    const maxStretchY = Math.max(1, params.maxStretchY ?? maxStretch);\n\n    const baseW = canvasSize.width;\n    const baseH = canvasSize.height;\n\n    // Base radius: largest circle that fits in the base canvas\n    const baseRadius = Math.max(minRadius,\n        (Math.min(baseW, baseH) / 2) - margin);\n\n    // ── Effective max-stretch on the radius ──────────────────────────\n    // The radius stretch expands the canvas in BOTH x and y equally.\n    // Cap so that neither dimension exceeds its per-dimension budget.\n    const maxCanvasW = baseW * maxStretchX;\n    const maxCanvasH = baseH * maxStretchY;\n    const maxDiameter = Math.min(maxCanvasW, maxCanvasH);\n    const effectiveMaxRadius = Math.min(maxRadius,\n        (maxDiameter - 2 * margin) / 2);\n    const effectiveMaxStretch = Math.max(1, effectiveMaxRadius / baseRadius);\n\n    // Spring model: pressure = items × step / baseDimension\n    const baseCircumference = 2 * Math.PI * baseRadius;\n    const pressure = (effectiveItemCount * minArcPx) / baseCircumference;\n\n    let radius: number;\n    if (pressure <= 1) {\n        // No pressure — base radius is sufficient\n        radius = baseRadius;\n    } else {\n        // Elastic stretch (same power law as bar-chart spring model)\n        const stretch = Math.min(effectiveMaxStretch, Math.pow(pressure, elasticity));\n        radius = Math.round(baseRadius * stretch);\n    }\n\n    // Clamp\n    radius = Math.min(maxRadius, Math.max(minRadius, radius));\n\n    // Canvas = diameter + margins\n    const diameter = 2 * radius + 2 * margin;\n    const canvasW = Math.max(baseW, diameter);\n    const canvasH = Math.max(baseH, diameter);\n\n    return { radius, canvasW, canvasH };\n}\n\n/**\n * Compute effective bar count for variable-width slices (pie / sunburst).\n *\n * If all slices are equal, this returns N (number of slices).\n * If slices vary, this returns `total / minValue` — i.e., how many of the\n * thinnest slice would fill the whole circle.  This is the worst-case\n * pressure that determines whether the chart needs to grow.\n *\n * Capped at 100 to prevent degenerate cases (near-zero slices) from\n * blowing up the radius.\n *\n * @param values  Array of slice values (must be > 0)\n */\nexport function computeEffectiveBarCount(values: number[]): number {\n    if (values.length === 0) return 0;\n    const positiveValues = values.filter(v => v > 0);\n    if (positiveValues.length === 0) return values.length;\n\n    const total = positiveValues.reduce((s, v) => s + v, 0);\n    const minVal = Math.min(...positiveValues);\n\n    // effectiveCount = total / minVal → how many of the smallest slice fill the circle\n    const effective = total / minVal;\n\n    // Cap at 100 to prevent degenerate cases\n    return Math.min(100, effective);\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * =============================================================================\n * FIELD SEMANTICS\n * =============================================================================\n *\n * Resolves what a data field *is* by combining its semantic annotation\n * (from LLM or user) with the actual data values. This resolves the\n * one-to-many ambiguities in the type registry (e.g., Score can be\n * quantitative or ordinal depending on cardinality).\n *\n * The entry point is `resolveFieldSemantics()`. It produces a\n * `FieldSemantics` object that captures the field's identity, format,\n * aggregation role, domain, scale hint, and ordering — everything\n * about *what the data represents*, independent of how it will be\n * visualized on any particular channel.\n *\n * Design doc: docs/design-compilation-context.md\n *\n * VL dependency: **None** — pure TypeScript, no rendering library imports.\n * =============================================================================\n */\n\nimport {\n    type VisCategory,\n    getRegistryEntry,\n    isRegistered,\n} from './type-registry';\n\nimport {\n    getZeroClass,\n    inferOrdinalSortOrder,\n    inferVisCategory,\n    type ZeroClass,\n} from './semantic-types';\n\n// Re-export for backward compatibility — consumers can import from here or type-registry\nexport { getRegistryEntry } from './type-registry';\nexport type { TypeRegistryEntry } from './type-registry';\n\n// =============================================================================\n// §1  PUBLIC TYPES\n// =============================================================================\n\n/**\n * Enriched semantic annotation from LLM or user.\n */\nexport interface SemanticAnnotation {\n    /** The T2 semantic type string (e.g., \"Amount\", \"Score\", \"Month\") */\n    semanticType: string;\n\n    /**\n     * Intrinsic domain (value range) of this field's scale.\n     * Only for bounded/scaled types — NOT for open-ended measures.\n     * E.g., [1, 5] for 5-star rating, [0, 100] for score, [-90, 90] for latitude.\n     */\n    intrinsicDomain?: [number, number];\n\n    /** Unit or currency code. E.g., \"USD\", \"°C\", \"kg\" */\n    unit?: string;\n\n    /** Explicit ordinal ordering. E.g., [\"Low\", \"Medium\", \"High\"] */\n    sortOrder?: string[];\n}\n\n/** d3-compatible format specification */\nexport interface FormatSpec {\n    /** d3-format pattern: \",.2f\", \".1%\", \"+.2f\", etc. */\n    pattern?: string;\n    /** Prefix before the number: \"$\", \"€\", \"£\" */\n    prefix?: string;\n    /** Suffix after the number: \"°C\", \"%\", \" kg\" */\n    suffix?: string;\n    /** Whether large values should be abbreviated (1K, 1M, 1B) */\n    abbreviate?: boolean;\n}\n\n/** Domain bounds constraint */\nexport interface DomainConstraint {\n    min?: number;\n    max?: number;\n    /** Whether to hard-clamp values outside the domain */\n    clamp?: boolean;\n}\n\n/** Tick mark constraint */\nexport interface TickConstraint {\n    /** Only show integer tick values */\n    integersOnly?: boolean;\n    /** Exact tick values to show (for small domains like 1–5 rating) */\n    exactTicks?: number[];\n    /** Minimum step between ticks */\n    minStep?: number;\n}\n\n/** Color scheme recommendation from semantic analysis */\nexport interface ColorSchemeHint {\n    /** Whether the field is best shown with sequential, diverging, or categorical colors */\n    type: 'sequential' | 'diverging' | 'categorical';\n    /** For diverging: the midpoint value */\n    divergingMidpoint?: number;\n    /** Whether the field is inherently diverging (always show diverging) vs conditional */\n    inherentlyDiverging?: boolean;\n}\n\n/** Result of diverging midpoint analysis */\nexport interface DivergingInfo {\n    /** The midpoint value where the diverging center sits */\n    midpoint: number;\n    /** Whether this type is always diverging or only when data spans both sides */\n    inherent: boolean;\n    /** Source of the midpoint determination */\n    source: 'unit' | 'type-intrinsic' | 'domain' | 'data';\n}\n\n/**\n * Resolved field semantics — what the data field *is*.\n *\n * Derived from a `SemanticAnnotation` (semantic type + optional metadata)\n * plus actual data values. Resolves the one-to-many ambiguities in the\n * type registry by inspecting the concrete data representation.\n *\n * This is purely about the field’s identity and intrinsic properties —\n * NOT about how it will be visualized on a particular channel.\n * Channel-specific decisions (color scheme, axis reversal, interpolation,\n * tick strategy, stacking, etc.) belong in `ChannelSemantics`.\n *\n * Built once per field per dataset by `resolveFieldSemantics()`.\n */\nexport interface FieldSemantics {\n    // --- Identity ---\n    /** The semantic annotation (normalized from string or object input) */\n    semanticAnnotation: SemanticAnnotation;\n\n    // --- Encoding ---\n    /** Preferred encoding type, disambiguated from registry using data */\n    defaultVisType: VisCategory;\n\n    // --- Formatting ---\n    /** Number format derived from data type and unit (only set when confident) */\n    format?: FormatSpec;\n    /** Tooltip format (typically higher precision than axis format) */\n    tooltipFormat?: FormatSpec;\n\n    // --- Aggregation ---\n    /** Default aggregate function — intrinsic to the field (additive vs intensive) */\n    aggregationDefault?: 'sum' | 'average';\n\n    // --- Scale ---\n    /** Zero-baseline classification (meaningful / arbitrary / bipolar) */\n    zeroClass: ZeroClass | 'unknown';\n    /** Recommended scale type based on data distribution */\n    scaleType?: 'linear' | 'log' | 'sqrt' | 'symlog';\n\n    // --- Domain ---\n    /** Intrinsic domain bounds (from annotation, type-intrinsic, or data-inferred) */\n    domainConstraint?: DomainConstraint;\n\n    // --- Ordering ---\n    /** Canonical ordinal sort order (months, days, etc.) */\n    canonicalOrder?: string[];\n    /** Whether the canonical order is cyclic (wraps around) */\n    cyclic: boolean;\n    /** Default sort direction */\n    sortDirection: 'ascending' | 'descending';\n\n    // --- Histogram ---\n    /** Whether this field’s data distribution benefits from binning */\n    binningSuggested: boolean;\n}\n\n// =============================================================================\n// §2  TYPE REGISTRY  →  see ./type-registry.ts (single source of truth)\n// =============================================================================\n\n/**\n * Extract the semantic type string from a bare string or annotation object.\n * Used when downstream code only needs the type string, not the full annotation.\n */\nexport function toTypeString(input: string | SemanticAnnotation | undefined): string {\n    if (!input) return '';\n    if (typeof input === 'string') return input;\n    return input.semanticType || '';\n}\n\n// =============================================================================\n// §3  ANNOTATION NORMALIZATION\n// =============================================================================\n\n/**\n * Normalize a bare string or enriched annotation object into a\n * consistent SemanticAnnotation.\n *\n * Accepts:\n *   \"Amount\"                                          → { semanticType: \"Amount\" }\n *   { semanticType: \"Score\", intrinsicDomain: [1,5] }  → as-is\n *   undefined / \"\"                                     → { semanticType: \"Unknown\" }\n */\nexport function normalizeAnnotation(\n    input: string | SemanticAnnotation | undefined,\n): SemanticAnnotation {\n    if (!input) return { semanticType: 'Unknown' };\n    if (typeof input === 'string') return { semanticType: input || 'Unknown' };\n    return { ...input, semanticType: input.semanticType || 'Unknown' };\n}\n\n// =============================================================================\n// §4  FORMAT RESOLUTION\n// =============================================================================\n\n/** Map currency codes to display symbols */\nconst CURRENCY_MAP: Record<string, string> = {\n    USD: '$', EUR: '€', GBP: '£', JPY: '¥', CNY: '¥',\n    KRW: '₩', INR: '₹', BRL: 'R$', CAD: 'CA$', AUD: 'A$',\n    CHF: 'CHF', SEK: 'kr', NOK: 'kr', DKK: 'kr',\n};\n\n/**\n * Map common unit strings to suffix display.\n *\n * Limited to a small set of well-known, universally understood units.\n * Unknown/arbitrary annotation.unit values are intentionally excluded\n * to keep axis labels clean and avoid displaying obscure or verbose\n * unit strings on tick marks.\n */\nconst UNIT_SUFFIX_MAP: Record<string, string> = {\n    // Temperature\n    '°C': '°C', '°F': '°F', C: '°C', F: '°F',\n    // Mass\n    kg: ' kg', lb: ' lb',\n    // Distance\n    km: ' km', mi: ' mi', m: ' m', ft: ' ft',\n    // Speed\n    'km/h': ' km/h', mph: ' mph',\n    // Time\n    sec: ' s', min: ' min', hr: ' hr',\n    seconds: ' s', minutes: ' min', hours: ' hr',\n    // Percentage (handled by formatClass, but allow explicit suffix)\n    '%': '%',\n};\n\n/**\n * Detect whether percentage data uses 0–1 (fractional) or 0–100 (whole-number)\n * representation.\n *\n * Values can exceed the intrinsic range (e.g., 155 % growth), so we look at\n * the *majority* of absolute values rather than just the max.\n */\nfunction detectPercentageRepresentation(values: number[]): '0-1' | '0-100' {\n    if (values.length === 0) return '0-100';\n    const abs = values.map(Math.abs);\n    // If the majority of values are ≤ 1, treat as fractional 0–1 representation\n    const countBelow1 = abs.filter(v => v <= 1).length;\n    if (countBelow1 / abs.length >= 0.8) return '0-1';\n    return '0-100';\n}\n\n/**\n * Detect the maximum number of meaningful decimal places in a set of values.\n *\n * Returns 0 for all-integer data, 1 for data like [3.7, 4.2], 2 for [1.25, 3.50], etc.\n * Caps at 4 to avoid floating-point noise (e.g., 0.1 + 0.2 = 0.30000000000000004).\n */\nfunction detectPrecision(values: number[]): number {\n    let maxDecimals = 0;\n    for (const v of values) {\n        if (!Number.isFinite(v)) continue;\n        // Convert to string, trim trailing zeros, count decimal places\n        const s = v.toFixed(10);  // enough digits to detect real precision\n        const dot = s.indexOf('.');\n        if (dot === -1) continue;\n        // Trim trailing zeros\n        let end = s.length - 1;\n        while (end > dot && s[end] === '0') end--;\n        const decimals = end > dot ? end - dot : 0;\n        if (decimals > maxDecimals) maxDecimals = decimals;\n    }\n    return Math.min(maxDecimals, 4);\n}\n\n/**\n * Build a d3-format pattern that matches the detected data precision.\n *\n * @param values  Numeric data values\n * @param useGrouping  Whether to include thousands separator (,)\n * @param signMode  '' = default, '+' = always show sign\n * @returns  Format pattern string like ',d', ',.1f', ',.2f'\n */\nfunction precisionFormat(values: number[], useGrouping = true, signMode: '' | '+' = ''): string {\n    const p = detectPrecision(values);\n    const group = useGrouping ? ',' : '';\n    if (p === 0) return `${signMode}${group}d`;\n    return `${signMode}${group}.${p}f`;\n}\n\n/**\n * Resolve the format specification for a field based on its semantic type,\n * annotation metadata, and data values.\n *\n * Priority: annotation.unit > type-specific defaults\n */\nexport function resolveFormat(\n    semanticType: string,\n    annotation: SemanticAnnotation,\n    values: any[],\n): { format?: FormatSpec; tooltipFormat?: FormatSpec } {\n    const entry = getRegistryEntry(semanticType);\n    const unit = annotation.unit;\n\n    // Resolve currency prefix from annotation.unit\n    const currencyPrefix = unit ? CURRENCY_MAP[unit.toUpperCase()] ?? CURRENCY_MAP[unit] : undefined;\n    // Resolve unit suffix from annotation.unit — only use known units;\n    // unknown units are dropped to avoid polluting tick labels with\n    // obscure or verbose strings.\n    const unitSuffix = unit ? UNIT_SUFFIX_MAP[unit] : undefined;\n\n    const nums = values.filter((v: any) => typeof v === 'number' && !isNaN(v));\n\n    // ─── Policy: only override axis format when the raw number would be\n    // genuinely misleading.  Two cases qualify:\n    //   1. Percent with 0–1 data + intrinsicDomain → representation transform\n    //   2. Currency with a known unit → add currency symbol\n    // Everything else: let VL handle axis formatting natively.\n    // Tooltip format is lower-stakes (transient hover) so we're more liberal.\n\n    switch (entry.formatClass) {\n        case 'currency': {\n            const pfx = currencyPrefix;\n            // Only override axis when we have a known currency symbol;\n            // without it the axis is better left to VL defaults.\n            if (pfx) {\n                const axisPattern = semanticType === 'Price' ? ',.2f' : precisionFormat(nums);\n                return {\n                    format: { pattern: axisPattern, prefix: pfx },\n                    tooltipFormat: { pattern: ',.2f', prefix: pfx },\n                };\n            }\n            return { tooltipFormat: { pattern: ',.2f' } };\n        }\n\n        case 'percent': {\n            // Without intrinsicDomain we can't reliably distinguish 0–1\n            // from 0–100, so defer to VL.\n            if (!annotation.intrinsicDomain) {\n                return { tooltipFormat: { pattern: precisionFormat(nums) } };\n            }\n            const rep = detectPercentageRepresentation(nums);\n            if (rep === '0-1') {\n                // 0–1 fractional → axis must transform (0.45 → \"45%\")\n                const p = detectPrecision(nums);\n                const axisP = Math.max(0, p - 2);\n                const tipP  = Math.min(axisP + 1, 4);\n                return {\n                    format: { pattern: `.${axisP}~%` },\n                    tooltipFormat: { pattern: `.${tipP}%` },\n                };\n            }\n            // Whole-number 0–100: raw numbers are readable as-is.\n            // Axis title conveys \"percentage\"; tooltip adds suffix for clarity.\n            return {\n                tooltipFormat: { pattern: precisionFormat(nums, false), suffix: '%' },\n            };\n        }\n\n        case 'unit-suffix':\n            return {\n                tooltipFormat: unitSuffix\n                    ? { pattern: precisionFormat(nums), suffix: unitSuffix }\n                    : { pattern: precisionFormat(nums) },\n            };\n\n        case 'integer':\n            // Year/Decade: no comma — '2,024' is wrong for a year.\n            // Other integers (Count, Rank, Hour): comma separator aids readability.\n            if (semanticType === 'Year' || semanticType === 'Decade') {\n                return {};\n            }\n            return { tooltipFormat: { pattern: ',d' } };\n\n        case 'decimal':\n            return { tooltipFormat: { pattern: precisionFormat(nums) } };\n\n        case 'plain':\n        default:\n            return {};\n    }\n}\n\n// =============================================================================\n// §5  DEFAULT VIS TYPE\n// =============================================================================\n\n/**\n * Resolve the default Vega-Lite encoding type for a field.\n *\n * When the registry lists multiple candidates (e.g., Score → ['quantitative', 'ordinal']),\n * disambiguate using data statistics (distinct value count).\n */\nexport function resolveDefaultVisType(\n    semanticType: string,\n    values: any[],\n): VisCategory {\n    // For unregistered types, defer entirely to data characteristics\n    if (!isRegistered(semanticType)) {\n        return inferVisCategory(values);\n    }\n\n    const entry = getRegistryEntry(semanticType);\n    const candidates = entry.visEncodings;\n    if (candidates.length === 1) {\n        // Guard: if registry says quantitative but actual values are\n        // strings (e.g. binned ranges like \"91-95\"), defer to data inference.\n        if (candidates[0] === 'quantitative') {\n            const nonNull = values.filter(v => v != null);\n            const allNumeric = nonNull.length > 0 &&\n                nonNull.every(v => typeof v === 'number' || (typeof v === 'string' && !isNaN(+v) && v.trim() !== ''));\n            if (!allNumeric) {\n                return inferVisCategory(values);\n            }\n        }\n        return candidates[0];\n    }\n\n    // Disambiguate between quantitative and ordinal based on distinct count\n    if (candidates.includes('quantitative') && candidates.includes('ordinal')) {\n        const distinct = new Set(values.filter(v => v != null)).size;\n        // Small number of distinct values → ordinal feels more natural\n        return distinct <= 12 ? 'ordinal' : 'quantitative';\n    }\n\n    // Disambiguate between temporal and ordinal\n    if (candidates.includes('temporal') && candidates.includes('ordinal')) {\n        const distinct = new Set(values.filter(v => v != null)).size;\n        // Few values → ordinal (e.g., only 3 years: 2022, 2023, 2024)\n        return distinct <= 6 ? 'ordinal' : 'temporal';\n    }\n\n    // If geographic + quantitative (lat/lon), prefer quantitative for standard charts\n    if (candidates.includes('geographic') && candidates.includes('quantitative')) {\n        return 'quantitative';\n    }\n\n    return candidates[0];\n}\n\n// =============================================================================\n// §6  AGGREGATION DEFAULT\n// =============================================================================\n\n/**\n * Resolve the default aggregation function based on the field's role.\n *\n * - Additive measures → sum (parts sum to a meaningful total)\n * - Intensive measures → average (rates/averages shouldn't be summed)\n * - Signed-additive    → sum (preserves sign semantics)\n * - Dimensions/IDs     → undefined (aggregation not meaningful)\n */\nexport function resolveAggregationDefault(\n    semanticType: string,\n): 'sum' | 'average' | undefined {\n    const entry = getRegistryEntry(semanticType);\n    switch (entry.aggRole) {\n        case 'additive':        return 'sum';\n        case 'signed-additive': return 'sum';\n        case 'intensive':       return 'average';\n        case 'dimension':       return undefined;\n        case 'identifier':      return undefined;\n        default:                return undefined;\n    }\n}\n\n// =============================================================================\n// §7  ZERO-BASELINE CLASSIFICATION\n// =============================================================================\n\n/**\n * Resolve zero-baseline class, enhanced with annotation domain.\n *\n * If annotation provides a domain starting above 0 (e.g., Rating [1, 5]),\n * zero is arbitrary regardless of what the base type says.\n */\nexport function resolveZeroClassFromAnnotation(\n    semanticType: string,\n    domain?: [number, number],\n): ZeroClass | 'unknown' {\n    // If domain starts above zero (e.g., Rating [1,5]), zero is arbitrary\n    if (domain && domain[0] > 0) return 'arbitrary';\n\n    // Delegate to existing classification\n    return getZeroClass(semanticType);\n}\n\n// =============================================================================\n// §8  SCALE TYPE\n// =============================================================================\n\n/**\n * Recommend a scale type based on semantic type and data distribution.\n *\n * Conservative policy — only triggers when ALL of these hold:\n *   1. The semantic type is an additive measure with an open domain and is\n *      not a generic fallback (i.e. Amount, Quantity, Duration — types whose\n *      magnitude is meaningful and can legitimately span many decades).\n *   2. Data spans ≥ 6 orders of magnitude (1,000,000×).\n *   3. At least 10 data points, all non-negative.\n *\n * This intentionally almost never fires on everyday data; it only helps with\n * genuinely wide-range additive measures. When it does not fire the axis stays\n * linear, and the user can still opt into log via the per-axis quick control.\n */\nexport function resolveScaleType(\n    semanticType: string,\n    values: number[],\n): 'linear' | 'log' | 'sqrt' | 'symlog' | undefined {\n    // Only consider log for additive measures with open domains —\n    // these are the types that can legitimately span many orders of magnitude.\n    // (E.g., revenue, population, quantities across different scales.)\n    // Exclude generic fallback types (Number, Unknown) — they just mean\n    // \"we know it's numeric but not what it measures\", so applying\n    // log/symlog would be presumptuous.\n    const entry = getRegistryEntry(semanticType);\n    const eligible = entry.aggRole === 'additive' && entry.domainShape === 'open'\n        && entry.t1 !== 'GenericMeasure';\n    if (!eligible) return undefined;\n\n    if (values.length < 10) return undefined;\n\n    const filtered = values.filter(v => typeof v === 'number' && !isNaN(v) && isFinite(v));\n    if (filtered.length < 10) return undefined;\n\n    const min = Math.min(...filtered);\n    const max = Math.max(...filtered);\n    if (max <= 0 || min === max) return undefined;\n\n    // Only all-positive data — don't auto-log mixed-sign\n    if (min < 0) return undefined;\n\n    // Require ≥ 6 orders of magnitude (1000 000×) — very conservative\n    const positiveMin = Math.min(...filtered.filter(v => v > 0));\n    if (positiveMin > 0 && max / positiveMin >= 1000000) {\n        // If data contains zeros, log(0) = -∞ breaks the scale.\n        // Use symlog (linear near zero, logarithmic for large values)\n        // so zeros remain representable.\n        const hasZeros = filtered.some(v => v === 0);\n        return hasZeros ? 'symlog' : 'log';\n    }\n\n    return undefined;\n}\n\n// =============================================================================\n// §9  DOMAIN CONSTRAINTS\n// =============================================================================\n\n/**\n * Merge an intrinsic (semantic) domain with the actual data range.\n *\n * For **hard** domains (Latitude, Correlation) the intrinsic bounds are\n * physically absolute — data cannot exceed them, so we clamp.\n *\n * For **soft** domains (Percentage, Score, Rating, annotation-supplied)\n * the intrinsic bounds describe the *typical* range but real data can\n * legitimately exceed them (e.g., 155 % growth).  The effective domain\n * is the union: min(intrinsic[0], dataMin) … max(intrinsic[1], dataMax).\n */\nfunction mergeIntrinsicWithData(\n    intrinsic: [number, number],\n    values: any[],\n    hard: boolean,\n): DomainConstraint {\n    if (hard) {\n        return { min: intrinsic[0], max: intrinsic[1], clamp: true };\n    }\n    const nums = values.filter((v: any) => typeof v === 'number' && !isNaN(v));\n    if (nums.length === 0) {\n        return { min: intrinsic[0], max: intrinsic[1], clamp: false };\n    }\n    const dataMin = Math.min(...nums);\n    const dataMax = Math.max(...nums);\n    return {\n        min: Math.min(intrinsic[0], dataMin),\n        max: Math.max(intrinsic[1], dataMax),\n        clamp: false,\n    };\n}\n\n/**\n * Snap-to-bound heuristic for bounded types like Percentage / PercentageChange.\n *\n * Each bound is snapped independently:\n * - If data approaches the intrinsic lower bound → snap min\n * - If data approaches the intrinsic upper bound → snap max\n * - If data exceeds a bound → don't snap that side (let VL auto-extend)\n *\n * Threshold: 25% of the *effective side range*.\n *\n * We err on the side of snapping, because:\n * - Semantic types are opt-in — the bound carries meaning by definition.\n * - A wrong snap (extra white space) is less harmful than a wrong\n *   no-snap (viewer loses semantic reference, differences are\n *   exaggerated and proximity to the bound is hidden).\n * - Only when data is clearly in the interior (> 25% away from each\n *   bound) does the bound stop being a useful reference.\n *\n * When the intrinsic domain straddles zero (lo < 0 < hi), zero acts as a\n * visual baseline (bar charts, contextual zero).  Each bound's threshold\n * is computed relative to its distance from zero — not the full range —\n * so that snapping one side doesn't make values on the other side of zero\n * invisible (e.g., snapping to -100% when data has a tiny +0.2% bar).\n *\n * When the domain doesn't straddle zero (e.g., [0, 100]), the full range\n * is used as the reference.\n *\n * Examples for Percentage [0, 100] (threshold = 25, full range):\n *   20–45%   → snap min=0 only     (20 within 25 of 0; 45 far from 100)\n *   35–65%   → no snap             (both far from edges, in interior)\n *   55–82%   → snap max=100 only   (82 within 25 of 100; 55 far from 0)\n *   15–80%   → snap both [0, 100]  (15 near 0, 80 near 100)\n *   30–130%  → no snap             (130 exceeds 100 → no snap; 30 far from 0)\n *\n * Examples for PercentageChange [-1, 1] (threshold = 0.25 per side):\n *   -0.03 to +0.05 → no snap       (both far from ±0.75)\n *   -0.70 to +0.30 → no snap       (-0.70 > -0.75, not close enough)\n *   -0.80 to +0.30 → snap min=-1   (-0.80 ≤ -0.75; +0.30 < 0.75)\n *   -0.80 to +0.78 → snap both     (both within 0.25 of edges)\n */\nexport function snapToBoundHeuristic(\n    intrinsic: [number, number],\n    values: any[],\n): DomainConstraint | undefined {\n    const nums = values.filter((v: any) => typeof v === 'number' && !isNaN(v));\n    if (nums.length === 0) return undefined;\n\n    const [lo, hi] = intrinsic;\n    const range = hi - lo;\n    if (range <= 0) return undefined;\n\n    const dataMin = Math.min(...nums);\n    const dataMax = Math.max(...nums);\n\n    // When the domain straddles zero, compute each side's threshold relative\n    // to its distance from zero.  This prevents snapping one side from\n    // stretching the axis so wide that values near zero on the other side\n    // become invisible (sub-pixel bars).\n    const zeroInside = lo < 0 && hi > 0;\n    const thresholdLo = 0.25 * (zeroInside ? (0 - lo) : range);\n    const thresholdHi = 0.25 * (zeroInside ? hi       : range);\n\n    let snapMin: number | undefined;\n    let snapMax: number | undefined;\n\n    // Snap lower bound: data min is close to intrinsic lower bound\n    // AND data doesn't go below it (if it does, VL auto-extends)\n    if (dataMin >= lo && dataMin <= lo + thresholdLo) {\n        snapMin = lo;\n    }\n\n    // Snap upper bound: data max is close to intrinsic upper bound\n    // AND data doesn't exceed it\n    if (dataMax <= hi && dataMax >= hi - thresholdHi) {\n        snapMax = hi;\n    }\n\n    if (snapMin === undefined && snapMax === undefined) return undefined;\n\n    return { min: snapMin, max: snapMax, clamp: false };\n}\n\n/**\n * Resolve domain constraints from annotation, type-intrinsic rules, or data.\n *\n * Only truly fixed physical domains (Latitude, Longitude, Correlation)\n * use hard clamping. Bounded types like Percentage use a snap-to-bound\n * heuristic: the axis extends to the theoretical endpoint (e.g., 100%)\n * only when data is close to it, avoiding wasted space when data is\n * concentrated in a small region.\n *\n * Priority: annotation.intrinsicDomain > type-intrinsic > data-inferred\n */\nexport function resolveDomainConstraint(\n    semanticType: string,\n    annotation: SemanticAnnotation,\n    values: any[],\n): DomainConstraint | undefined {\n    const entry = getRegistryEntry(semanticType);\n\n    // 1. Explicit annotation intrinsicDomain\n    if (annotation.intrinsicDomain) {\n        // Proportion (Percentage) and SignedMeasure (PercentageChange, Profit):\n        // use snap-to-bound heuristic on both ends independently.\n        // Don't force the full theoretical range — only snap to a bound\n        // when data approaches it (e.g., 97% → snap to 100%, -0.95 → snap to -1).\n        if (entry.t1 === 'Proportion' || entry.t1 === 'SignedMeasure') {\n            return snapToBoundHeuristic(annotation.intrinsicDomain, values);\n        }\n        // All other types: soft merge (union of intrinsic + data)\n        return mergeIntrinsicWithData(annotation.intrinsicDomain, values, false);\n    }\n\n    // 2. Type-intrinsic hard domains (physically impossible to exceed)\n    if (semanticType === 'Latitude')    return mergeIntrinsicWithData([-90, 90], values, true);\n    if (semanticType === 'Longitude')   return mergeIntrinsicWithData([-180, 180], values, true);\n    if (semanticType === 'Correlation') return mergeIntrinsicWithData([-1, 1], values, true);\n\n    // 3. Percentage without explicit annotation — detect scale and apply snap\n    if (semanticType === 'Percentage') {\n        const nums = values.filter((v: any) => typeof v === 'number' && !isNaN(v));\n        if (nums.length > 0) {\n            const rep = detectPercentageRepresentation(nums);\n            const M = rep === '0-1' ? 1 : 100;\n            return snapToBoundHeuristic([0, M], values);\n        }\n    }\n\n    return undefined;\n}\n\n// =============================================================================\n// §10  TICK CONSTRAINTS\n// =============================================================================\n\n/**\n * Resolve tick constraints based on semantic type and domain.\n *\n * For bounded integer domains (e.g., Rating [1, 5]), generates exact ticks.\n * For integer types (Count, Rank, Year), enforces integer-only ticks.\n */\nexport function resolveTickConstraint(\n    semanticType: string,\n    domain?: [number, number],\n): TickConstraint | undefined {\n    const entry = getRegistryEntry(semanticType);\n\n    if (entry.formatClass === 'integer') {\n        const tc: TickConstraint = { integersOnly: true, minStep: 1 };\n        // If domain provided and span is small, generate exact ticks\n        if (domain) {\n            const span = domain[1] - domain[0];\n            if (span <= 20 && span > 0) {\n                tc.exactTicks = [];\n                for (let i = domain[0]; i <= domain[1]; i++) {\n                    tc.exactTicks.push(i);\n                }\n            }\n        }\n        return tc;\n    }\n\n    // Score with bounded domain → integer ticks ONLY when domain span\n    // indicates meaningful integer steps.  For small spans like [0, 1],\n    // the values are continuous (e.g., outlier_score 0–1) and forcing\n    // integer ticks would remove all intermediate tick marks.\n    if (semanticType === 'Score' && domain) {\n        const span = domain[1] - domain[0];\n        if (span >= 2) {\n            const tc: TickConstraint = { integersOnly: true, minStep: 1 };\n            if (span <= 20) {\n                tc.exactTicks = [];\n                for (let i = domain[0]; i <= domain[1]; i++) {\n                    tc.exactTicks.push(i);\n                }\n            }\n            return tc;\n        }\n    }\n\n    return undefined;\n}\n\n// =============================================================================\n// §11  CANONICAL ORDERING & CYCLIC\n// =============================================================================\n\n/**\n * Resolve the canonical sort order for a field.\n *\n * Priority: annotation.sortOrder > well-known type sequence > auto-detect from data\n */\nexport function resolveCanonicalOrder(\n    semanticType: string,\n    annotation: SemanticAnnotation,\n    values: any[],\n): string[] | undefined {\n    // 1. Explicit annotation sortOrder\n    if (annotation.sortOrder && annotation.sortOrder.length > 0) {\n        return annotation.sortOrder;\n    }\n\n    // 2. Delegate to existing well-known sequence detection\n    return inferOrdinalSortOrder(semanticType, values);\n}\n\n/**\n * Determine whether a field's values form a cyclic (wrap-around) sequence.\n *\n * Derived purely from semantic type — NOT an LLM annotation.\n * Types with domainShape='cyclic' in the registry are cyclic.\n */\nexport function resolveCyclic(semanticType: string): boolean {\n    const entry = getRegistryEntry(semanticType);\n    return entry.domainShape === 'cyclic';\n}\n\n// =============================================================================\n// §12  REVERSED AXIS\n// =============================================================================\n\n/**\n * Whether the axis should be reversed for this field.\n *\n * Rank is the primary case: 1st place should appear at the top of the\n * y-axis.  On the x-axis, rank 1 should stay on the left (no reversal).\n */\nexport function resolveReversed(semanticType: string, channel?: string): boolean {\n    if (semanticType === 'Rank') {\n        // Only reverse on the y-axis (rank 1 at top).\n        // On x-axis, natural left-to-right order is correct.\n        return channel !== 'x';\n    }\n    return false;\n}\n\n// =============================================================================\n// §13  NICE (domain rounding)\n// =============================================================================\n\n/**\n * Whether to apply \"nice\" rounding to scale domain endpoints.\n *\n * Nice is false when:\n * - There's a fixed domain constraint (Rating [1, 5] → axis should show exactly 1–5)\n * - The type has a fixed domain shape (Latitude, Correlation)\n */\nexport function resolveNice(\n    semanticType: string,\n    domainConstraint?: DomainConstraint,\n): boolean {\n    if (domainConstraint?.clamp) return false;\n    if (domainConstraint && domainConstraint.min !== undefined && domainConstraint.max !== undefined) {\n        return false;\n    }\n    const entry = getRegistryEntry(semanticType);\n    if (entry.domainShape === 'fixed') return false;\n    return true;\n}\n\n// =============================================================================\n// §14  DIVERGING & COLOR SCHEME HINT\n// =============================================================================\n\n/**\n * Resolve diverging midpoint information for a field.\n *\n * Priority chain:\n *   1. annotation.unit → type lookup (°C → 0, °F → 32)\n *   2. type-intrinsic midpoint (Sentiment → 0, Correlation → 0)\n *   3. annotation.intrinsicDomain midpoint (Rating [1,5] → 3)\n *   4. data-driven: data spans 0 → midpoint 0\n *\n * Returns undefined if no diverging treatment applies.\n */\nexport function resolveDivergingInfo(\n    semanticType: string,\n    annotation: SemanticAnnotation,\n    values: number[],\n): DivergingInfo | undefined {\n    const entry = getRegistryEntry(semanticType);\n    // Types with diverging='none' don't get diverging treatment\n\n    // 1. Unit-derived (Temperature)\n    if (semanticType === 'Temperature' && annotation.unit) {\n        const unitMidpoints: Record<string, number> = {\n            '°C': 0, '°F': 32, 'K': 273.15, C: 0, F: 32,\n        };\n        const mid = unitMidpoints[annotation.unit];\n        if (mid !== undefined) {\n            return { midpoint: mid, inherent: false, source: 'unit' };\n        }\n    }\n\n    // 3. Type-intrinsic\n    if (entry.diverging === 'inherent') {\n        return { midpoint: 0, inherent: true, source: 'type-intrinsic' };\n    }\n    if (entry.diverging === 'conditional') {\n        return { midpoint: 0, inherent: false, source: 'type-intrinsic' };\n    }\n\n    // 3. Domain-derived midpoint (e.g., Rating [1,5] → 3)\n    if (annotation.intrinsicDomain) {\n        return {\n            midpoint: (annotation.intrinsicDomain[0] + annotation.intrinsicDomain[1]) / 2,\n            inherent: false,\n            source: 'domain',\n        };\n    }\n\n    // 4. Data-driven: if data spans 0, use 0 as midpoint\n    if (values.length > 0) {\n        const min = Math.min(...values);\n        const max = Math.max(...values);\n        if (min < 0 && max > 0) {\n            return { midpoint: 0, inherent: false, source: 'data' };\n        }\n    }\n\n    return undefined;\n}\n\n/**\n * Resolve color scheme hint based on semantic type, diverging analysis,\n * and data values.\n */\nexport function resolveColorSchemeHint(\n    semanticType: string,\n    annotation: SemanticAnnotation,\n    values: any[],\n): ColorSchemeHint {\n    const entry = getRegistryEntry(semanticType);\n    const nums = values.filter((v: any) => typeof v === 'number' && !isNaN(v));\n\n    // Try diverging analysis\n    const divInfo = resolveDivergingInfo(semanticType, annotation, nums);\n    if (divInfo) {\n        const min = nums.length > 0 ? Math.min(...nums) : 0;\n        const max = nums.length > 0 ? Math.max(...nums) : 0;\n        const spansBothSides = min < divInfo.midpoint && max > divInfo.midpoint;\n\n        if (divInfo.inherent || spansBothSides) {\n            return {\n                type: 'diverging',\n                divergingMidpoint: divInfo.midpoint,\n                inherentlyDiverging: divInfo.inherent,\n            };\n        }\n    }\n\n    // Sequential for quantitative, categorical for nominal/ordinal\n    if (entry.visEncodings.includes('quantitative')) {\n        return { type: 'sequential' };\n    }\n    return { type: 'categorical' };\n}\n\n// =============================================================================\n// §15  BINNING SUITABILITY\n// =============================================================================\n\n/**\n * Whether this field benefits from histogram-style binning.\n *\n * False for small bounded domains (Rating 1–5), non-numeric types,\n * and identifiers.\n */\nexport function resolveBinningSuggested(\n    semanticType: string,\n    domain?: [number, number],\n): boolean {\n    const entry = getRegistryEntry(semanticType);\n\n    // Non-quantitative types don't get binned\n    if (!entry.visEncodings.includes('quantitative')) return false;\n\n    // Identifiers/dimensions don't get binned\n    if (entry.aggRole === 'identifier' || entry.aggRole === 'dimension') return false;\n\n    // Year should use temporal axis, not bins\n    if (semanticType === 'Year' || semanticType === 'Decade') return false;\n\n    // Small bounded domains have too few values to bin\n    if (domain && (domain[1] - domain[0]) <= 20) return false;\n\n    // Score with known small range\n    if (semanticType === 'Score' && !domain) return false;\n\n    return true;\n}\n\n// =============================================================================\n// §17  STACKING COMPATIBILITY\n// =============================================================================\n\n/**\n * Whether values of this type can be stacked in a bar/area chart, and how.\n *\n * - 'sum':       Additive measures (parts sum to whole)\n * - 'normalize': Proportions (show 100% breakdown)\n * - false:       Stacking is meaningless (rates, scores, identifiers)\n */\nexport function resolveStackable(\n    semanticType: string,\n): 'sum' | 'normalize' | false {\n    const entry = getRegistryEntry(semanticType);\n\n    switch (entry.aggRole) {\n        case 'additive':        return 'sum';\n        case 'signed-additive': return 'sum';\n        case 'intensive':\n            // Percentage is the exception — normalizable\n            if (semanticType === 'Percentage') return 'normalize';\n            return false;\n        case 'dimension':       return false;\n        case 'identifier':      return false;\n        default:                return false;\n    }\n}\n\n// =============================================================================\n// §18  SORT DIRECTION\n// =============================================================================\n\n/**\n * Default sort direction for this field when used on an axis.\n */\nexport function resolveSortDirection(\n    semanticType: string,\n): 'ascending' | 'descending' {\n    // Rank: show best first\n    if (semanticType === 'Rank') return 'descending';\n    return 'ascending';\n}\n\n// =============================================================================\n// §19  BUILDER: resolveFieldSemantics()\n// =============================================================================\n\n/**\n * Resolve field semantics from annotation + data.\n *\n * This is the sole entry point for data-identity decisions. It resolves\n * the one-to-many ambiguities in the type registry by inspecting the\n * concrete data representation.\n *\n * Visualization-specific decisions (color scheme, axis reversal,\n * interpolation, tick strategy, nice rounding, stacking) are NOT\n * computed here — those belong in `resolveChannelSemantics()`.\n *\n * @param input       The semantic type annotation (string or enriched object)\n * @param fieldName   Column name (used for unit detection heuristics)\n * @param values      Sampled data values from this field\n * @returns           Resolved field semantics\n */\nexport function resolveFieldSemantics(\n    input: string | SemanticAnnotation | undefined,\n    fieldName: string,\n    values: any[],\n): FieldSemantics {\n    // 1. Normalize annotation\n    const annotation = normalizeAnnotation(input);\n    const semanticType = annotation.semanticType;\n\n    // 2. Numeric values (filtered once, reused across resolvers)\n    const numericValues = values\n        .filter((v: any) => typeof v === 'number' && !isNaN(v) && isFinite(v));\n\n    // 3. Resolve field-intrinsic properties\n    const defaultVisType = resolveDefaultVisType(semanticType, values);\n    const { format, tooltipFormat } = resolveFormat(semanticType, annotation, values);\n    let aggregationDefault = resolveAggregationDefault(semanticType);\n    let zeroClass = resolveZeroClassFromAnnotation(semanticType, annotation.intrinsicDomain);\n    const scaleType = resolveScaleType(semanticType, numericValues);\n    const domainConstraint = resolveDomainConstraint(semanticType, annotation, values);\n    const canonicalOrder = resolveCanonicalOrder(semanticType, annotation, values);\n    const cyclic = resolveCyclic(semanticType);\n    let binningSuggested = resolveBinningSuggested(semanticType, annotation.intrinsicDomain);\n    const sortDirection = resolveSortDirection(semanticType);\n\n    // 4. For unregistered types, provide data-driven fallbacks.\n    //    The registry treats unknown types as categorical, but if the data\n    //    is actually numeric, we should behave like a generic measure.\n    if (!isRegistered(semanticType) && defaultVisType === 'quantitative') {\n        // Data looks numeric → treat like Number (GenericMeasure)\n        if (!aggregationDefault) aggregationDefault = 'sum';\n        if (zeroClass === 'unknown') zeroClass = 'meaningful';\n        binningSuggested = true;\n    }\n\n    return {\n        semanticAnnotation: annotation,\n        defaultVisType,\n        format,\n        tooltipFormat,\n        aggregationDefault,\n        zeroClass,\n        scaleType: scaleType ?? undefined,\n        domainConstraint,\n        canonicalOrder,\n        cyclic,\n        sortDirection,\n        binningSuggested,\n    };\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * =============================================================================\n * CHANNEL SEMANTICS RESOLVER\n * =============================================================================\n *\n * Stage 2 of the semantic pipeline:\n *   SemanticAnnotation + data → FieldSemantics → **ChannelSemantics**\n *\n * Takes each channel’s field, builds FieldSemantics (stage 1), then adds\n * channel-specific visualization decisions: encoding type, color scheme,\n * temporal format, ordinal sort, tick constraints, axis reversal, nice\n * rounding, interpolation, and stacking.\n *\n * Zero-baseline is NOT resolved here — it requires template mark knowledge\n * and is finalized by the assembler after this function returns.\n *\n * VL dependency: **None**\n * =============================================================================\n */\n\nimport type {\n    ChartEncoding,\n    ChannelSemantics,\n    SemanticResult,\n} from './types';\nimport {\n    getVisCategory,\n    inferVisCategory,\n    getRecommendedColorScheme,\n    inferOrdinalSortOrder,\n} from './semantic-types';\nimport {\n    resolveEncodingType as resolveEncodingTypeDecision,\n} from './decisions';\nimport {\n    resolveFieldSemantics,\n    toTypeString,\n    resolveNice,\n    resolveTickConstraint,\n    resolveReversed,\n    resolveStackable,\n    resolveColorSchemeHint,\n    resolveDivergingInfo,\n    type SemanticAnnotation,\n} from './field-semantics';\n\n// ---------------------------------------------------------------------------\n// Internal helpers (moved from assemble.ts)\n// ---------------------------------------------------------------------------\n\n/** Upper bounds for plausible timestamps (~2099-12-31). */\nconst MAX_TIMESTAMP_SEC = 4102444800;\nconst MAX_TIMESTAMP_MS = 4102444800000;\n\nfunction isLikelyTimestamp(val: number): boolean {\n    if (val >= 1e9 && val <= MAX_TIMESTAMP_SEC) return true;\n    if (val > MAX_TIMESTAMP_SEC && val <= MAX_TIMESTAMP_MS) return true;\n    return false;\n}\n\nfunction timestampToMs(val: number): number {\n    return val <= MAX_TIMESTAMP_SEC ? val * 1000 : val;\n}\n\nfunction looksLikeDateString(s: string): boolean {\n    const t = s.trim();\n    return /^\\d|^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i.test(t);\n}\n\n// ---------------------------------------------------------------------------\n// Temporal field analysis\n// ---------------------------------------------------------------------------\n\ninterface TemporalAnalysis {\n    dates: Date[];\n    same: {\n        month: boolean;\n        day: boolean;\n        hour: boolean;\n        minute: boolean;\n        second: boolean;\n    };\n    sameYear: boolean;\n    sameMonth: boolean;\n    sameDay: boolean;\n}\n\nfunction analyzeTemporalField(fieldValues: any[]): TemporalAnalysis | null {\n    const dates: Date[] = [];\n    let nonNull = 0;\n    for (const v of fieldValues.slice(0, 100)) {\n        if (v == null) continue;\n        nonNull++;\n        const d = v instanceof Date ? v : new Date(v);\n        if (!isNaN(d.getTime())) dates.push(d);\n    }\n    if (dates.length < 2 || dates.length < nonNull * 0.5) return null;\n\n    const monthSet  = new Set(dates.map(d => d.getUTCMonth()));\n    const daySet    = new Set(dates.map(d => d.getUTCDate()));\n    const hourSet   = new Set(dates.map(d => d.getUTCHours()));\n    const minuteSet = new Set(dates.map(d => d.getUTCMinutes()));\n    const secondSet = new Set(dates.map(d => d.getUTCSeconds()));\n    const yearSet   = new Set(dates.map(d => d.getUTCFullYear()));\n\n    const isSmallSpread = (s: Set<number>, maxSpread: number = 1) => {\n        if (s.size <= 1) return true;\n        const arr = [...s];\n        return Math.max(...arr) - Math.min(...arr) <= maxSpread;\n    };\n\n    const same = {\n        month:  monthSet.size  === 1,\n        day:    daySet.size    === 1,\n        hour:   isSmallSpread(hourSet, 1),\n        minute: minuteSet.size === 1,\n        second: secondSet.size === 1,\n    };\n\n    const sameYear  = yearSet.size === 1;\n    const sameMonth = sameYear && same.month;\n    const sameDay   = sameMonth && same.day;\n\n    return { dates, same, sameYear, sameMonth, sameDay };\n}\n\nfunction computeDataVotes(same: TemporalAnalysis['same']): number[] {\n    const votes = [0, 0, 0, 0, 0, 0];\n\n    if (same.second)                                                           votes[5] += 1;\n    if (same.minute && same.second)                                            votes[5] += 1;\n    if (same.hour   && same.minute && same.second)                             votes[5] += 1;\n    if (same.day    && same.hour   && same.minute && same.second)              votes[5] += 2;\n    if (same.month  && same.day    && same.hour   && same.minute && same.second) votes[5] += 3;\n\n    if (same.second)                                                           votes[4] += 1;\n    if (same.minute && same.second)                                            votes[4] += 1;\n    if (same.hour   && same.minute && same.second)                             votes[4] += 1;\n    if (same.day    && same.hour   && same.minute && same.second)              votes[4] += 2;\n    if (!same.month && same.day && same.hour && same.minute && same.second)    votes[4] += 3;\n\n    if (same.second)                                                           votes[3] += 1;\n    if (same.minute && same.second)                                            votes[3] += 1;\n    if (same.hour   && same.minute && same.second)                             votes[3] += 1;\n    if (!same.day && same.hour && same.minute && same.second)                  votes[3] += 3;\n\n    if (same.second)                               votes[2] += 1;\n    if (same.minute && same.second)                votes[2] += 1;\n    if (!same.hour && same.minute && same.second)  votes[2] += 3;\n\n    if (same.second)                    votes[1] += 1;\n    if (!same.minute && same.second)    votes[1] += 3;\n\n    if (!same.second) votes[0] += 4;\n\n    return votes;\n}\n\nconst SEMANTIC_LEVEL: Record<string, number> = {\n    Year:        5, Decade:      5,\n    YearMonth:   4, Month:       4, YearQuarter: 4, Quarter: 4,\n    Date:        3, Day:         3,\n    Hour:        2,\n    DateTime:    1,\n    Timestamp:   0,\n};\n\nfunction pickBestLevel(votes: number[]): { level: number; score: number } {\n    let bestLevel = 0;\n    let bestScore = votes[0];\n    for (let i = 1; i <= 5; i++) {\n        if (votes[i] >= bestScore) {\n            bestScore = votes[i];\n            bestLevel = i;\n        }\n    }\n    return { level: bestLevel, score: bestScore };\n}\n\nfunction levelToFormat(level: number, analysis: TemporalAnalysis): string | null {\n    switch (level) {\n        case 5: return '%Y';\n        case 4: return analysis.sameYear ? '%b' : '%b %Y';\n        case 3: return analysis.sameYear ? '%b %d' : '%b %d, %Y';\n        case 2: return analysis.sameDay  ? '%H:00' : '%b %d %H:00';\n        case 1: return analysis.sameDay  ? '%H:%M' : '%b %d %H:%M';\n        case 0: return analysis.sameDay  ? '%H:%M:%S' : '%b %d %H:%M:%S';\n        default: return null;\n    }\n}\n\n/**\n * Resolve temporal format for a field.\n * Used for both temporal and ordinal-temporal fields.\n */\nfunction resolveTemporalFormat(\n    fieldValues: any[],\n    semanticType: string,\n): string | null {\n    const analysis = analyzeTemporalField(fieldValues);\n    if (!analysis) return null;\n\n    const votes = computeDataVotes(analysis.same);\n    const semLevel = SEMANTIC_LEVEL[semanticType];\n    if (semLevel !== undefined) votes[semLevel] += 3;\n    const { level } = pickBestLevel(votes);\n    return levelToFormat(level, analysis);\n}\n\n// ---------------------------------------------------------------------------\n// Temporal data conversion\n// ---------------------------------------------------------------------------\n\n/**\n * Expand a year string to an unambiguous 4-digit representation.\n *\n * - \"98\" → \"1998\",  \"07\" → \"2007\",  \"00\" → \"2000\"\n * - \"1998\" → \"1998\" (already 4+ digits, pass through)\n * - \"FY 2018\" → \"FY 2018\" (non-numeric, pass through)\n *\n * Two-digit cutoff: 0–49 → 2000s, 50–99 → 1900s (same heuristic JS Date uses).\n */\nfunction expandToFullYear(val: string): string {\n    const trimmed = val.trim();\n    if (/^\\d{2}$/.test(trimmed)) {\n        const n = parseInt(trimmed, 10);\n        return String(n <= 49 ? 2000 + n : 1900 + n);\n    }\n    return val;\n}\n\n/**\n * Convert temporal field values in the data table to canonical string\n * representations for Vega-Lite consumption.\n *\n * This is a data-level concern (not VL-specific) — it ensures consistent\n * date parsing across backends.\n */\nexport function convertTemporalData(\n    data: any[],\n    semanticTypes: Record<string, string | SemanticAnnotation>,\n): any[] {\n    if (data.length === 0) return data;\n\n    const keys = Object.keys(data[0]);\n    const temporalKeys = keys.filter((k: string) => {\n        const st = toTypeString(semanticTypes[k]);\n        const vc = inferVisCategory(data.map(r => r[k]));\n        const stCategory = st ? getVisCategory(st) : null;\n        return vc === 'temporal' || stCategory === 'temporal' || st === 'Decade';\n    });\n\n    if (temporalKeys.length === 0) return data;\n\n    const values = structuredClone(data);\n    return values.map((r: any) => {\n        for (const temporalKey of temporalKeys) {\n            const val = r[temporalKey];\n            const st = toTypeString(semanticTypes[temporalKey]);\n\n            if (typeof val === 'number') {\n                if (st === 'Year' || st === 'Decade') {\n                    r[temporalKey] = `${Math.floor(val)}`;\n                } else if (isLikelyTimestamp(val)) {\n                    r[temporalKey] = new Date(timestampToMs(val)).toISOString();\n                } else {\n                    r[temporalKey] = String(val);\n                }\n            } else if (val instanceof Date) {\n                r[temporalKey] = val.toISOString();\n            } else {\n                // For Year/Decade strings, normalise to 4-digit years so\n                // Vega-Lite parses them unambiguously and doesn't auto-tick\n                // at sub-year intervals (e.g. \"98\" → \"1998\").\n                if ((st === 'Year' || st === 'Decade') && typeof val === 'string') {\n                    r[temporalKey] = expandToFullYear(val);\n                } else {\n                    r[temporalKey] = String(val);\n                }\n            }\n        }\n        return r;\n    });\n}\n\n// ---------------------------------------------------------------------------\n// Public API: resolveChannelSemantics\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve all channel-level semantic decisions.\n *\n * For each channel, builds FieldSemantics (data identity) then layers on\n * channel-specific visualization decisions (color scheme, temporal format,\n * tick constraints, axis reversal, interpolation, etc.).\n *\n * Zero-baseline (cs.zero) is NOT resolved here -- it requires template\n * mark knowledge (bar vs point) that belongs to the assembler.\n * The assembler finalizes zero after calling this function.\n *\n * @param encodings       Channel -> ChartEncoding from user / AI agent\n * @param data            Array of data rows (original, unconverted)\n * @param semanticTypes   Field name -> semantic type string\n * @param convertedData   Pre-converted temporal data (from convertTemporalData).\n *                        If omitted, falls back to data for temporal format detection.\n */\nexport function resolveChannelSemantics(\n    encodings: Record<string, ChartEncoding>,\n    data: any[],\n    semanticTypes: Record<string, string | SemanticAnnotation>,\n    convertedData?: any[],\n): SemanticResult {\n    const result: SemanticResult = {};\n\n    // Use pre-converted temporal data for format detection, or fall back to raw data\n    const temporalData = convertedData ?? data;\n\n    for (const [channel, encoding] of Object.entries(encodings)) {\n        const fieldName = encoding.field;\n        if (!fieldName && encoding.aggregate !== 'count') continue;\n\n        // Handle count aggregate without a field\n        if (!fieldName && encoding.aggregate === 'count') {\n            result[channel] = {\n                field: '_count',\n                semanticAnnotation: { semanticType: 'Count' },\n                type: 'quantitative',\n                aggregationDefault: 'sum',\n            };\n            continue;\n        }\n\n        if (!fieldName) continue;\n\n        const rawAnnotation = semanticTypes[fieldName];\n        const semanticType = typeof rawAnnotation === 'string'\n            ? (rawAnnotation || '')\n            : (rawAnnotation?.semanticType ?? '');\n        const fieldValues = data.map(r => r[fieldName]);\n\n        // Resolve encoding type\n        const typeDecision = resolveEncodingTypeDecision(\n            semanticType, fieldValues, channel, data, fieldName,\n        );\n\n        // Apply explicit type override\n        let resolvedType = typeDecision.vlType;\n        if (encoding.type) {\n            resolvedType = encoding.type;\n        } else if (channel === 'column' || channel === 'row') {\n            if (resolvedType !== 'nominal' && resolvedType !== 'ordinal') {\n                resolvedType = 'nominal';\n            }\n        }\n\n        // ISO date hack\n        if (resolvedType === 'quantitative') {\n            const sampleValues = data.slice(0, 15).filter(r => r[fieldName] != undefined).map(r => r[fieldName]);\n            const isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})?$/;\n            if (sampleValues.length > 0 && sampleValues.every((val: any) => isoDateRegex.test(`${val}`.trim()))) {\n                resolvedType = 'temporal';\n            }\n        }\n\n        // Build ChannelSemantics entry\n        // Stage 1: resolve field-level semantics (data identity)\n        const fc = resolveFieldSemantics(rawAnnotation, fieldName, fieldValues);\n        const annotation = fc.semanticAnnotation;\n\n        // Stage 2: layer on channel-specific visualization decisions\n        const tickConstraint = resolveTickConstraint(annotation.semanticType, annotation.intrinsicDomain);\n        const reversed = resolveReversed(annotation.semanticType, channel);\n        const nice = resolveNice(annotation.semanticType, fc.domainConstraint);\n        const stackable = resolveStackable(annotation.semanticType);\n\n        const cs: ChannelSemantics = {\n            field: fieldName,\n            semanticAnnotation: annotation,\n            type: resolvedType,\n\n            // From FieldSemantics (data identity)\n            format: fc.format,\n            tooltipFormat: fc.tooltipFormat,\n            aggregationDefault: fc.aggregationDefault,\n            scaleType: fc.scaleType,\n            domainConstraint: fc.domainConstraint,\n            cyclic: fc.cyclic || undefined,\n            sortDirection: fc.sortDirection,\n            binningSuggested: fc.binningSuggested || undefined,\n\n            // Channel-specific visualization decisions\n            nice,\n            tickConstraint,\n            reversed: reversed || undefined,\n            stackable,\n        };\n\n        // Adjust field name for aggregated fields (the derived column is either\n        // computed by applyAggregation or supplied pre-aggregated by the caller)\n        if (encoding.aggregate) {\n            if (encoding.aggregate === 'count') {\n                cs.field = '_count';\n                cs.type = 'quantitative';\n            } else {\n                cs.field = `${fieldName}_${encoding.aggregate}`;\n                cs.type = 'quantitative';\n            }\n        }\n\n        // --- Channel-specific semantic decisions ---\n\n        // Color scheme (color and group channels)\n        if ((channel === 'color' || channel === 'group') && fieldName) {\n            if (encoding.scheme && encoding.scheme !== 'default') {\n                cs.colorScheme = {\n                    scheme: encoding.scheme,\n                    type: 'categorical',\n                    reason: 'explicit user scheme',\n                };\n            } else {\n                const encodingVLType = cs.type as 'nominal' | 'ordinal' | 'quantitative' | 'temporal';\n                // Use design-aligned classification from field-semantics.ts\n                const colorHint = resolveColorSchemeHint(semanticType, annotation, fieldValues);\n                const uniqueValues = [...new Set(fieldValues)];\n                cs.colorScheme = getRecommendedColorScheme(\n                    semanticType, encodingVLType, uniqueValues.length, fieldName,\n                    fieldValues, { type: colorHint.type },\n                );\n                // Apply midpoint from design-aligned diverging analysis\n                if (cs.colorScheme.type === 'diverging' && encodingVLType === 'quantitative') {\n                    const nums = fieldValues.filter((v: any) => typeof v === 'number' && !isNaN(v));\n                    const divInfo = resolveDivergingInfo(semanticType, annotation, nums);\n                    if (divInfo) {\n                        cs.colorScheme.domainMid = divInfo.midpoint;\n                    }\n                }\n            }\n        }\n\n        // Temporal format\n        if (cs.type === 'temporal' || (semanticType && getVisCategory(semanticType) === 'temporal')) {\n            const convertedFieldValues = temporalData.map(r => r[fieldName]);\n            const fmt = resolveTemporalFormat(convertedFieldValues, semanticType);\n            if (fmt) cs.temporalFormat = fmt;\n        }\n\n        // Ordinal sort order (canonical ordering for months, days, quarters, etc.)\n        if (cs.type === 'ordinal' || cs.type === 'nominal') {\n            if (!encoding.sortOrder && !encoding.sortBy) {\n                const ordinalSort = inferOrdinalSortOrder(semanticType, fieldValues);\n                if (ordinalSort) {\n                    cs.ordinalSortOrder = ordinalSort;\n                }\n            }\n        }\n\n        result[channel] = cs;\n    }\n\n    return result;\n}\n\n// Re-export helpers needed by other modules\nexport {\n    analyzeTemporalField,\n    computeDataVotes,\n    pickBestLevel,\n    levelToFormat,\n    looksLikeDateString,\n    SEMANTIC_LEVEL,\n    type TemporalAnalysis,\n};\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ChannelSemantics } from './types';\n\ntype EncodingType = 'nominal' | 'ordinal' | 'quantitative' | 'temporal';\n\ntype BandedAxisResult = {\n    axis: 'x' | 'y';\n    resolvedTypes?: Record<string, EncodingType>;\n};\n\nconst isDiscrete = (type: string | undefined): boolean =>\n    type === 'nominal' || type === 'ordinal';\n\nconst getFieldCardinality = (field: string, table: any[]): number =>\n    new Set(table.map((row: any) => row[field]).filter((value: any) => value != null)).size;\n\n/** Resolve a backend-neutral discrete encoding type for a field. */\nexport function resolveDiscreteType(\n    currentType: string,\n    field: string | undefined,\n    table: any[],\n): 'nominal' | 'ordinal' {\n    if (currentType === 'nominal') return 'nominal';\n    if (currentType === 'ordinal') return 'ordinal';\n    if (currentType === 'temporal') return 'ordinal';\n    if (currentType === 'quantitative' && field && table.length > 0) {\n        return getFieldCardinality(field, table) <= 20 ? 'ordinal' : 'nominal';\n    }\n    return 'nominal';\n}\n\n/** Choose the position axis that should use banded layout. */\nexport function detectBandedAxisFromSemantics(\n    channelSemantics: Record<string, ChannelSemantics>,\n    table: any[],\n    options: { preferAxis?: 'x' | 'y' } = {},\n): BandedAxisResult | null {\n    const xType = channelSemantics.x?.type;\n    const yType = channelSemantics.y?.type;\n\n    if (xType && isDiscrete(xType)) return { axis: 'x' };\n    if (yType && isDiscrete(yType)) return { axis: 'y' };\n\n    if (xType && yType) {\n        if (xType === 'quantitative' && yType !== 'quantitative') {\n            return { axis: 'y' };\n        }\n        if (yType === 'quantitative' && xType !== 'quantitative') {\n            return { axis: 'x' };\n        }\n        return { axis: options.preferAxis || 'x' };\n    }\n\n    if (xType) {\n        const newType = resolveDiscreteType(xType, channelSemantics.x?.field, table);\n        return { axis: 'x', resolvedTypes: { x: newType } };\n    }\n    if (yType) {\n        const newType = resolveDiscreteType(yType, channelSemantics.y?.field, table);\n        return { axis: 'y', resolvedTypes: { y: newType } };\n    }\n\n    return null;\n}\n\n/** Choose a banded axis and force its encoding type to be discrete. */\nexport function detectBandedAxisForceDiscrete(\n    channelSemantics: Record<string, ChannelSemantics>,\n    table: any[],\n    options: { preferAxis?: 'x' | 'y' } = {},\n): BandedAxisResult | null {\n    const result = detectBandedAxisFromSemantics(channelSemantics, table, options);\n    if (!result) return null;\n\n    const axis = result.axis;\n    const semantics = channelSemantics[axis];\n    if (!semantics) return result;\n\n    if (!isDiscrete(semantics.type)) {\n        const newType = resolveDiscreteType(semantics.type, semantics.field, table);\n        return {\n            axis,\n            resolvedTypes: { ...result.resolvedTypes, [axis]: newType },\n        };\n    }\n\n    return result;\n}","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * =============================================================================\n * PHASE 1: COMPUTE LAYOUT\n * =============================================================================\n *\n * Determine how big things should be — axis lengths, step sizes,\n * subplot dimensions, label sizing, and overflow truncation — from data\n * density, axis classification, and template-provided tuning knobs.\n *\n * VL dependency: **None**\n *\n * This module reads abstract axis descriptors (AxisLayoutInput) and\n * produces abstract layout numbers (LayoutResult). The same layout\n * engine works regardless of output format.\n *\n * ── Backend Responsibility ──────────────────────────────────────────\n * The LayoutResult is a target-agnostic description of \"how big things\n * should be\".  Each rendering backend (Vega-Lite, ECharts, etc.) MUST:\n *\n *   1. Call computeLayout() once per chart (facet-aware — it already\n *      divides subplot sizes for the facet grid).\n *\n *   2. Translate the LayoutResult into its own rendering format:\n *      - subplotWidth / subplotHeight → plot area size (before margins)\n *      - xStep / yStep → bar widths, band sizes, category spacing\n *      - stepPadding → inter-category gap (barCategoryGap, paddingInner)\n *      - label sizing → font size, rotation, truncation\n *\n *   3. Add its own margins, padding, and chrome (axis labels, titles,\n *      legends, CANVAS_BUFFER) around the subplot area.\n *\n *   4. Handle facet-specific concerns itself:\n *      - Column wrapping (when user specifies column-only, the backend\n *        decides how many columns per visual row and restructures the\n *        panel grid accordingly).\n *      - Per-panel vs shared axis titles.\n *      - Panel positioning and header labels.\n *\n * The layout engine does NOT know about VL encodings, ECharts grid\n * objects, or any rendering-specific structure.\n * =============================================================================\n */\n\nimport type {\n    ChannelSemantics,\n    LayoutDeclaration,\n    LayoutResult,\n    AssembleOptions,\n    ChannelBudgets,\n} from './types';\nimport {\n    computeAxisStep,\n    computeGasPressure,\n    computeLabelSizing,\n    computeFontSizing,\n    DEFAULT_GAS_PRESSURE_PARAMS,\n    type ElasticStretchParams,\n    type GasPressureParams,\n} from './decisions';\nimport { planBandDodge } from './band-dodge';\n\n// ---------------------------------------------------------------------------\n// Short discrete axis labels (align with echarts/templates/bar.ts)\n// ---------------------------------------------------------------------------\n\nconst VL_SHORT_DISCRETE_CATEGORY_COUNT = 4;\nconst VL_SHORT_DISCRETE_LABEL_MAX_LEN = 8;\n\n/** Approximate width (px) of one label character at the given font size. */\nconst APPROX_CHAR_WIDTH_RATIO = 0.62;\n\n/** Distinct label strings for a discrete axis field, plus derived stats. */\ninterface DiscreteLabelStats {\n    count: number;\n    maxLen: number;\n    /** True when every label parses as a finite number (e.g. years, bins, IDs). */\n    allNumeric: boolean;\n}\n\nfunction computeDiscreteLabelStats(\n    field: string | undefined,\n    table: any[],\n): DiscreteLabelStats | null {\n    if (!field) return null;\n    const uniques = new Set<string>();\n    for (const row of table) {\n        const v = row[field];\n        if (v == null || v === '') continue;\n        uniques.add(String(v));\n    }\n    if (uniques.size === 0) return null;\n    const labels = [...uniques];\n    return {\n        count: labels.length,\n        maxLen: Math.max(...labels.map(s => s.length)),\n        allNumeric: labels.every(s => s.trim() !== '' && isFinite(Number(s))),\n    };\n}\n\n/**\n * Few, short category strings → keep axis labels horizontal in Vega-Lite. Used\n * for the Y axis, where banded labels read horizontally in the left margin\n * regardless of band height (so quantitative/numeric labels stay horizontal).\n */\nfunction discreteYAxisShouldUseHorizontalLabels(\n    field: string | undefined,\n    channelType: string | undefined,\n    table: any[],\n): boolean {\n    if (!field) return false;\n    if (channelType === 'quantitative') return true;\n    const stats = computeDiscreteLabelStats(field, table);\n    if (!stats) return false;\n    if (stats.count > VL_SHORT_DISCRETE_CATEGORY_COUNT) return false;\n    return stats.maxLen <= VL_SHORT_DISCRETE_LABEL_MAX_LEN;\n}\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ninterface AxisLayoutInput {\n    /** Spring model (banded) or gas pressure (non-banded) */\n    mode: 'banded' | 'non-banded';\n    /** Number of discrete positions (for banded) */\n    itemCount: number;\n    /** Number of sub-items per group (for grouped bars) */\n    subItemsPerGroup?: number;\n    /** Numeric values along this axis (for gas pressure) */\n    values?: number[];\n    /** Data extent [min, max] */\n    domain?: [number, number];\n    /** Number of distinct series (for series-based pressure) */\n    seriesCount?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Stretch caps\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the per-dimension maximum stretch caps (βx, βy) from options.\n *\n * The assembler derives `maxStretchX`/`maxStretchY` from the spec's\n * `canvasSize / baseSize` ratio (the hard ceiling). When neither is set,\n * both fall back to the scalar `maxStretch` (default {@link DEFAULT_MAX_STRETCH})\n * — the symmetric budget used when the spec pins no `canvasSize`. Each cap is\n * clamped to ≥ 1 (a chart never shrinks below its base under \"stretch\").\n */\nexport function resolveStretchCaps(options: AssembleOptions): { x: number; y: number } {\n    const def = options.maxStretch ?? DEFAULT_MAX_STRETCH;\n    return {\n        x: Math.max(1, options.maxStretchX ?? def),\n        y: Math.max(1, options.maxStretchY ?? def),\n    };\n}\n\n/** Default base (target) chart size in pixels when the spec omits `baseSize`. */\nexport const DEFAULT_BASE_SIZE = { width: 400, height: 320 } as const;\n\n/**\n * Default axis stretch cap used when the spec pins no `canvasSize` ceiling.\n *\n * Bounds how far a chart may grow past its base size (per dimension) under\n * layout pressure. 1.5 keeps growth modest; 2× was found to over-stretch\n * charts in the general (no-ceiling) case.\n */\nexport const DEFAULT_MAX_STRETCH = 1.5;\n\n/**\n * Resolve the effective base (target) size the layout pipeline aims for.\n *\n * Defaults to {@link DEFAULT_BASE_SIZE} when the spec omits `baseSize`, then\n * clamps each dimension to the optional `canvasSize` ceiling. This guarantees\n * the target never exceeds the hard maximum: when a user sets only a (small)\n * `canvasSize` and leaves `baseSize` defaulted — or sets a `baseSize` larger\n * than the ceiling — the chart shrinks to fit the box instead of overflowing\n * it. After clamping, `deriveStretchCaps` yields βx/βy = 1 in any clamped\n * dimension (pure fit-to-box, no growth past the ceiling).\n */\nexport function resolveBaseSize(\n    specBaseSize: { width: number; height: number } | undefined,\n    ceiling: { width: number; height: number } | undefined,\n): { width: number; height: number } {\n    const base = specBaseSize ?? { ...DEFAULT_BASE_SIZE };\n    if (!ceiling) return { width: base.width, height: base.height };\n    return {\n        width: Math.min(base.width, ceiling.width),\n        height: Math.min(base.height, ceiling.height),\n    };\n}\n\n/**\n * Read the user's `facetColumns` chart property (the interactive facet-wrap\n * control) off the RAW chart_spec.chartProperties, returning a clamped integer\n * column count or undefined for auto. Read raw (pre-normalization) because\n * `facetColumns` is a layout-level option, not a per-template mark property, so\n * `normalizeChartProperties` would otherwise drop it as an unknown key.\n */\nexport function resolveFacetColumnsOption(\n    chartProperties: Record<string, any> | undefined,\n): number | undefined {\n    const raw = chartProperties?.facetColumns;\n    if (raw == null) return undefined;\n    const n = Number(raw);\n    return Number.isFinite(n) && n >= 1 ? Math.floor(n) : undefined;\n}\n\n/**\n * Derive per-dimension stretch ceilings (βx, βy) for an assembler.\n *\n * When the spec supplies a hard `canvasSize` ceiling, the caps are the ratio\n * of ceiling to base in each dimension (clamped to ≥ 1). The base passed here\n * is expected to already be clamped to the ceiling (see {@link resolveBaseSize}),\n * so a ceiling smaller than the spec's base resolves to β = 1 (fit-to-box)\n * rather than an overflow. When no ceiling is given, both caps fall back to\n * `options.maxStretch` (or {@link DEFAULT_MAX_STRETCH} when that is unset too),\n * which already reflects any template `paramOverrides`.\n *\n * Assemblers inject the result into `effectiveOptions.maxStretchX/Y` so the\n * whole layout pipeline shares one budget — including faceted grids, whose\n * total size is bounded by the same ceiling.\n */\nexport function deriveStretchCaps(\n    baseSize: { width: number; height: number },\n    ceiling: { width: number; height: number } | undefined,\n    options: AssembleOptions,\n): { maxStretchX: number; maxStretchY: number } {\n    const def = options.maxStretch ?? DEFAULT_MAX_STRETCH;\n    return {\n        maxStretchX: ceiling ? Math.max(1, ceiling.width / baseSize.width) : def,\n        maxStretchY: ceiling ? Math.max(1, ceiling.height / baseSize.height) : def,\n    };\n}\n\n// ---------------------------------------------------------------------------\n// Public API: computeLayout\n// ---------------------------------------------------------------------------\n\n/**\n * Phase 1: Compute layout decisions.\n *\n * Takes channel semantics, template layout declaration, data, canvas size,\n * and assembly options to produce a LayoutResult with step sizes, subplot\n * dimensions, label sizing, and truncation warnings.\n *\n * VL dependency: **None**\n *\n * @param channelSemantics   Phase 0 output\n * @param declaration        Template's layout declaration (axisFlags, resolvedTypes,\n *                           grouping, binnedAxes)\n * @param table              Data rows (post-overflow filtered)\n * @param canvasSize         Target canvas dimensions\n * @param options            Assembly options (merged with template overrides)\n * @param facetGrid          Optional pre-decided facet grid from computeFacetGrid.\n *                           When provided, computeLayout uses these column/row\n *                           counts instead of counting from data — this\n *                           eliminates the circularity between wrapping and\n *                           banded axis sizing.\n */\nexport function computeLayout(\n    channelSemantics: Record<string, ChannelSemantics>,\n    declaration: LayoutDeclaration,\n    table: any[],\n    canvasSize: { width: number; height: number },\n    options: AssembleOptions = {},\n    facetGrid?: { columns: number; rows: number },\n): LayoutResult {\n    const {\n        elasticity: elasticityVal = 0.5,\n        facetElasticity: facetElasticityVal = 0.3,\n        minStep: minStepVal = 6,\n        minSubplotSize: minSubplotVal = 60,\n        stepPadding: stepPaddingVal = 0.1,\n        maintainContinuousAxisRatio = false,\n        continuousMarkCrossSection,\n        facetAspectRatioResistance = 0,\n    } = options;\n\n    // Per-dimension stretch ceilings: βx bounds width-related growth,\n    // βy bounds height-related growth. Both reduce to `maxStretch`\n    // (default 1.5) when the spec sets no explicit `canvasSize` ceiling.\n    const { x: maxStretchX, y: maxStretchY } = resolveStretchCaps(options);\n\n    const defaultChartWidth = canvasSize.width;\n    const defaultChartHeight = canvasSize.height;\n\n    // Facet overhead: fixed (axis labels, titles) + per-panel gap (spacing).\n    const fixW = options.facetFixedPadding?.width ?? 0;\n    const fixH = options.facetFixedPadding?.height ?? 0;\n    const gap = options.facetGap ?? 0;\n\n    const baseRefSize = 300;\n    const sizeRatio = Math.max(defaultChartWidth, defaultChartHeight) / baseRefSize;\n    const baseBandSize = options.defaultBandSize ?? 20;\n    const defaultStepSize = Math.round(baseBandSize * Math.max(1, sizeRatio));\n    // Sparse-expansion ceiling: a band may grow past its base size to fill a\n    // wide plot, but never past maxStepSize. Defaults to the base band, so a\n    // backend that doesn't opt in keeps the old \"cap at base\" behavior.\n    const maxBandSize = Math.max(baseBandSize, options.maxBandSize ?? baseBandSize);\n    const maxStepSize = Math.round(maxBandSize * Math.max(1, sizeRatio));\n\n    const isDiscreteType = (t: string | undefined) => t === 'nominal' || t === 'ordinal';\n\n    // Apply resolved types from template declaration\n    const effectiveTypes: Record<string, string> = {};\n    for (const [ch, cs] of Object.entries(channelSemantics)) {\n        effectiveTypes[ch] = declaration.resolvedTypes?.[ch] || cs.type;\n    }\n\n    // --- Classify axes and count items ---\n    const axisFlags = declaration.axisFlags || {};\n    const xBanded = axisFlags.x?.banded ?? false;\n    const yBanded = axisFlags.y?.banded ?? false;\n\n    const nominalCount: Record<string, number> = {\n        x: 0, y: 0, column: 0, row: 0, group: 0,\n    };\n\n    // Count discrete values per channel\n    for (const channel of ['x', 'y', 'column', 'row', 'color'] as const) {\n        const cs = channelSemantics[channel];\n        if (!cs?.field) continue;\n        const effectiveType = effectiveTypes[channel] || cs.type;\n        if (!isDiscreteType(effectiveType)) continue;\n        const uniqueValues = [...new Set(table.map((r: any) => r[cs.field]))];\n        nominalCount[channel] = uniqueValues.length;\n    }\n\n    // Detect grouping from 'group' channel + discrete axis\n    let groupField: string | undefined = channelSemantics.group?.field;\n    // Some templates (e.g. boxplot) subdivide a band by the COLOR field via an\n    // explicit offset rather than a dedicated 'group' channel. When they opt in,\n    // size the band as a group so total width is budgeted across categories and\n    // each sub-lane shrinks as the subgroup count grows.\n    if (!groupField && declaration.colorActsAsGroup) {\n        const colorCS = channelSemantics.color;\n        const colorType = effectiveTypes.color ?? colorCS?.type;\n        const axisField = isDiscreteType(effectiveTypes.x ?? channelSemantics.x?.type)\n            ? channelSemantics.x?.field\n            : channelSemantics.y?.field;\n        if (colorCS?.field && isDiscreteType(colorType) && colorCS.field !== axisField) {\n            groupField = colorCS.field;\n        }\n    }\n    // Guard: a grouping field that is redundant/nested with the categorical axis\n    // (group == x, or a 1:1 field pair) doesn't actually subdivide any band, so\n    // grouping it would collapse each bar/box to ~1/N of its band. When no band\n    // holds more than one distinct group value (confident-nested; threshold-\n    // independent), suppress grouping so glyphs fill their whole band. Genuine\n    // grouped charts (any band with >1 group value) are untouched.\n    if (groupField) {\n        const groupAxisField = isDiscreteType(effectiveTypes.x ?? channelSemantics.x?.type)\n            ? channelSemantics.x?.field\n            : channelSemantics.y?.field;\n        if (groupAxisField === groupField) {\n            groupField = undefined;  // group == axis: nothing to dodge\n        } else if (groupAxisField && planBandDodge(table, groupAxisField, groupField).maxPerBand <= 1) {\n            groupField = undefined;  // 1:1 / nested with the axis\n        }\n    }\n    let groupAxis: 'x' | 'y' | undefined;\n    if (groupField) {\n        // `local` dodge budgets only `maxPerBand` lanes (declaration.groupLaneCount);\n        // otherwise reserve one lane per global distinct group value.\n        nominalCount.group = declaration.groupLaneCount\n            ?? new Set(table.map((r: any) => r[groupField])).size;\n        if (isDiscreteType(effectiveTypes.x ?? channelSemantics.x?.type)) groupAxis = 'x';\n        else if (isDiscreteType(effectiveTypes.y ?? channelSemantics.y?.type)) groupAxis = 'y';\n    }\n\n    // Total discrete items per axis (grouping multiplies the grouped axis)\n    const xGroupMultiplier = (groupAxis === 'x' && nominalCount.group > 1) ? nominalCount.group : 1;\n    const yGroupMultiplier = (groupAxis === 'y' && nominalCount.group > 1) ? nominalCount.group : 1;\n    const xTotalNominalCount = nominalCount.x * xGroupMultiplier;\n    const yTotalNominalCount = nominalCount.y * yGroupMultiplier;\n\n    // --- Step size hints ---\n    // Minimum group step: the inter-group gap (stepPadding × step) must be\n    // at least MIN_GROUP_GAP_PX pixels so groups are visually separated.\n    const MIN_GROUP_GAP_PX = 3;\n    const xMinGroupStep = xGroupMultiplier > 1 ? Math.max(Math.ceil(MIN_GROUP_GAP_PX / stepPaddingVal), 2 * xGroupMultiplier) : minStepVal;\n    const yMinGroupStep = yGroupMultiplier > 1 ? Math.max(Math.ceil(MIN_GROUP_GAP_PX / stepPaddingVal), 2 * yGroupMultiplier) : minStepVal;\n\n    // (Overflow filtering is now handled by filterOverflow() before\n    //  computeLayout is called. The data passed here is already filtered.)\n\n    // --- Count banded continuous axes ---\n    let xContinuousAsDiscrete = 0;\n    let yContinuousAsDiscrete = 0;\n    for (const axis of ['x', 'y'] as const) {\n        const cs = channelSemantics[axis];\n        if (!cs?.field) continue;\n        const effectiveType = effectiveTypes[axis] || cs.type;\n        if (isDiscreteType(effectiveType)) continue;\n\n        const isBanded = (axis === 'x' ? xBanded : yBanded);\n        // Check for binned from declaration\n        const isBinned = declaration.binnedAxes?.[axis];\n        if (!isBanded && !isBinned) continue;\n\n        let count: number;\n        if (isBinned) {\n            const binDef = declaration.binnedAxes![axis];\n            // Default to 10 bins (Vega-Lite's default maxbins)\n            count = typeof binDef === 'object' && binDef.maxbins\n                ? binDef.maxbins : 10;\n        } else {\n            count = new Set(table.map((r: any) => r[cs.field])).size;\n        }\n        if (count <= 1) continue;\n\n        if (axis === 'x') {\n            xContinuousAsDiscrete = count;\n        } else {\n            yContinuousAsDiscrete = count;\n        }\n    }\n\n    // --- Facet layout ---\n    // Use pre-decided grid from filterOverflow when available.\n    // This avoids the circularity where wrapping depends on subplot\n    // width which depends on facet count which depends on wrapping.\n    let facetCols = 1;\n    let facetRows = 1;\n    if (facetGrid) {\n        facetCols = facetGrid.columns;\n        facetRows = facetGrid.rows;\n    } else {\n        if (nominalCount.column > 0) facetCols = nominalCount.column;\n        if (nominalCount.row > 0) facetRows = nominalCount.row;\n    }\n\n    // --- Facet subplot sizing ---\n    // Log-scale axes need more room so the minor grid lines (1,2,3…9 per\n    // decade) remain legible and act as the visual cue that it's log scale.\n    // Compute the number of orders of magnitude each axis spans; each\n    // decade needs ~40px minimum to avoid a dense wall of grid lines.\n    const LOG_PX_PER_DECADE = 40;\n    let logBoostX = 0;\n    let logBoostY = 0;\n    for (const axis of ['x', 'y'] as const) {\n        const cs = channelSemantics[axis];\n        if (!cs?.field || !cs.scaleType) continue;\n        if (cs.scaleType !== 'log' && cs.scaleType !== 'symlog') continue;\n        const vals = table\n            .map((r: any) => r[cs.field])\n            .filter((v: any) => typeof v === 'number' && v > 0 && isFinite(v));\n        if (vals.length < 2) continue;\n        const decades = Math.log10(Math.max(...vals)) - Math.log10(Math.min(...vals));\n        const needed = Math.ceil(Math.max(1, decades)) * LOG_PX_PER_DECADE;\n        if (axis === 'x') logBoostX = needed;\n        else logBoostY = needed;\n    }\n    const minContinuousSize = Math.max(10, minStepVal);\n    const minContinuousSizeX = Math.max(minContinuousSize, logBoostX);\n    const minContinuousSizeY = Math.max(minContinuousSize, logBoostY);\n\n    let subplotWidth: number;\n    if (facetCols > 1) {\n        const stretch = Math.min(maxStretchX, Math.pow(facetCols, facetElasticityVal));\n        subplotWidth = Math.round(Math.max(minContinuousSizeX,\n            (defaultChartWidth * stretch - fixW) / facetCols - gap));\n    } else {\n        subplotWidth = defaultChartWidth;\n    }\n\n    let subplotHeight: number;\n    if (facetRows > 1) {\n        const stretch = Math.min(maxStretchY, Math.pow(facetRows, facetElasticityVal));\n        subplotHeight = Math.round(Math.max(minContinuousSizeY,\n            (defaultChartHeight * stretch - fixH) / facetRows - gap));\n    } else {\n        subplotHeight = defaultChartHeight;\n    }\n\n    // --- Facet aspect-ratio resistance (non-gas-pressure charts) ---\n    // When faceting compresses one dimension (e.g. width ÷ columns), the\n    // aspect ratio drifts.  Line/area charts are very sensitive to this.\n    // For charts entering the 2D gas pressure path, AR resistance is\n    // handled inside the ideal-then-squeeze logic below. This block\n    // only applies when both axes are NOT continuous-non-banded.\n    const xIsContinuousNonBanded = xTotalNominalCount === 0 && xContinuousAsDiscrete === 0;\n    const yIsContinuousNonBanded = yTotalNominalCount === 0 && yContinuousAsDiscrete === 0;\n    const bothContinuousNonBanded = xIsContinuousNonBanded && yIsContinuousNonBanded;\n\n    if (facetAspectRatioResistance > 0 && !bothContinuousNonBanded\n        && (facetCols > 1 || facetRows > 1)) {\n        const baseAR = defaultChartWidth / defaultChartHeight;\n        const facetAR = subplotWidth / subplotHeight;\n        const arDrift = facetAR / baseAR; // <1 when panel got relatively narrower\n\n        if (arDrift < 1) {\n            // Panel is narrower than base → shrink height to compensate\n            subplotHeight = Math.round(\n                Math.max(minContinuousSizeY, subplotHeight * Math.pow(arDrift, facetAspectRatioResistance)),\n            );\n        } else if (arDrift > 1) {\n            // Panel is wider than base → shrink width to compensate\n            subplotWidth = Math.round(\n                Math.max(minContinuousSizeX, subplotWidth * Math.pow(1 / arDrift, facetAspectRatioResistance)),\n            );\n        }\n    }\n\n    // --- Gas pressure stretch for continuous non-banded axes ---\n    //\n    // Design: per-subplot baseline → pressure → AR blend → fit.\n    //\n    //   Baseline: each subplot gets a fair share of the canvas with\n    //             facet elasticity applied (cols^e / cols).\n    //   Step 1 — Gas pressure measures crowding against the per-subplot\n    //            baseline and produces per-axis raw stretches.\n    //   Step 2 — Decide AR: blend gas-pressure AR (density asymmetry)\n    //            with banking AR (perceptual slope optimization) in\n    //            log space.  Distribute gas-pressure area into the\n    //            blended AR.\n    //   Step 3 — Fit into budget: uniform scale-down so neither axis\n    //            exceeds maxStretch, preserving the AR.\n\n    if (bothContinuousNonBanded) {\n        const xCS = channelSemantics.x;\n        const yCS = channelSemantics.y;\n\n        if (xCS?.field && yCS?.field) {\n            const isTempX = (effectiveTypes.x || xCS.type) === 'temporal';\n            const isTempY = (effectiveTypes.y || yCS.type) === 'temporal';\n\n            const xNumeric: number[] = [];\n            const yNumeric: number[] = [];\n            for (const row of table) {\n                let xv = row[xCS.field];\n                let yv = row[yCS.field];\n                if (xv == null || yv == null) continue;\n                if (isTempX) xv = +new Date(xv);\n                else xv = +xv;\n                if (isTempY) yv = +new Date(yv);\n                else yv = +yv;\n                if (isNaN(xv) || isNaN(yv)) continue;\n                xNumeric.push(xv);\n                yNumeric.push(yv);\n            }\n\n            if (xNumeric.length > 1) {\n                const xMin = Math.min(...xNumeric);\n                const xMax = Math.max(...xNumeric);\n                const yMin = Math.min(...yNumeric);\n                const yMax = Math.max(...yNumeric);\n\n                // Expand to visual domain (include zero when axis starts at zero).\n                const xDomain: [number, number] = [xMin, xMax];\n                const yDomain: [number, number] = [yMin, yMax];\n                if (xCS.zero?.zero) {\n                    if (xDomain[0] > 0) xDomain[0] = 0;\n                    if (xDomain[1] < 0) xDomain[1] = 0;\n                }\n                if (yCS.zero?.zero) {\n                    if (yDomain[0] > 0) yDomain[0] = 0;\n                    if (yDomain[1] < 0) yDomain[1] = 0;\n                }\n\n                // Data-coverage guard: skip banking when zero dominates.\n                const xDataCoverage = (xDomain[1] - xDomain[0]) > 0\n                    ? (xMax - xMin) / (xDomain[1] - xDomain[0]) : 1;\n                const yDataCoverage = (yDomain[1] - yDomain[0]) > 0\n                    ? (yMax - yMin) / (yDomain[1] - yDomain[0]) : 1;\n                const BANKING_COVERAGE_THRESHOLD = 0.2;\n\n                // --- Gas pressure params ---\n                let gasPressureParams: GasPressureParams = DEFAULT_GAS_PRESSURE_PARAMS;\n                if (continuousMarkCrossSection != null) {\n                    if (typeof continuousMarkCrossSection === 'number') {\n                        gasPressureParams = { ...DEFAULT_GAS_PRESSURE_PARAMS, markCrossSection: continuousMarkCrossSection };\n                    } else {\n                        const maxCS = Math.max(continuousMarkCrossSection.x, continuousMarkCrossSection.y);\n                        gasPressureParams = {\n                            ...DEFAULT_GAS_PRESSURE_PARAMS,\n                            markCrossSection: maxCS,\n                            markCrossSectionX: continuousMarkCrossSection.x,\n                            markCrossSectionY: continuousMarkCrossSection.y,\n                            ...(continuousMarkCrossSection.elasticity != null && { elasticity: continuousMarkCrossSection.elasticity }),\n                            ...(continuousMarkCrossSection.maxStretch != null && { maxStretch: continuousMarkCrossSection.maxStretch }),\n                        };\n\n                        if (continuousMarkCrossSection.seriesCountAxis) {\n                            const resolvedAxis = continuousMarkCrossSection.seriesCountAxis === 'auto'\n                                ? 'y' : continuousMarkCrossSection.seriesCountAxis;\n                            const nSeries = countDistinctSeries(channelSemantics, table);\n                            if (resolvedAxis === 'y') {\n                                gasPressureParams.yItemCountOverride = nSeries;\n                            } else {\n                                gasPressureParams.xItemCountOverride = nSeries;\n                            }\n                        }\n                    }\n                }\n\n                // --- Per-subplot baseline canvas ---\n                // Gas pressure must measure crowding against the actual\n                // per-subplot space, not the full canvas.  When faceted,\n                // each subplot gets a share of the canvas that includes\n                // facet elasticity (the same formula used for discrete\n                // axes): `canvas × cols^elasticity / cols`.  This way\n                // 2 columns don't naively halve the space — some stretch\n                // is assumed before gas pressure even kicks in.\n                const perSubplotCanvasW = facetCols > 1\n                    ? Math.max(minContinuousSizeX,\n                        (defaultChartWidth * Math.min(maxStretchX, Math.pow(facetCols, facetElasticityVal)) - fixW)\n                        / facetCols - gap)\n                    : defaultChartWidth;\n                const perSubplotCanvasH = facetRows > 1\n                    ? Math.max(minContinuousSizeY,\n                        (defaultChartHeight * Math.min(maxStretchY, Math.pow(facetRows, facetElasticityVal)) - fixH)\n                        / facetRows - gap)\n                    : defaultChartHeight;\n\n                // --- Gas pressure: per-axis raw stretches ---\n                const idealResult = computeGasPressure(\n                    xNumeric, yNumeric, xDomain, yDomain,\n                    perSubplotCanvasW, perSubplotCanvasH, gasPressureParams,\n                );\n\n                const isConnected = typeof continuousMarkCrossSection === 'object'\n                    && !!continuousMarkCrossSection.seriesCountAxis;\n                const useBanking = xDataCoverage >= BANKING_COVERAGE_THRESHOLD\n                    && yDataCoverage >= BANKING_COVERAGE_THRESHOLD;\n\n                let idealW: number;\n                let idealH: number;\n\n                // Gas pressure's native per-axis dimensions (uncapped).\n                const rawW = perSubplotCanvasW * idealResult.rawStretchX;\n                const rawH = perSubplotCanvasH * idealResult.rawStretchY;\n\n                if (useBanking) {\n                    // ── Step 1: Decide AR ──────────────────────────────\n                    // Blend gas-pressure AR (which axis is more crowded)\n                    // with banking AR (perceptual slope optimization).\n                    const seriesFields: string[] = [];\n                    const colorField = channelSemantics.color?.field;\n                    const detailField = channelSemantics.detail?.field;\n                    if (colorField) seriesFields.push(colorField);\n                    if (detailField && detailField !== colorField) seriesFields.push(detailField);\n\n                    const perPointSeriesKeys: string[] = new Array(xNumeric.length);\n                    if (seriesFields.length === 0) {\n                        perPointSeriesKeys.fill('');\n                    } else {\n                        let idx = 0;\n                        for (const row of table) {\n                            const xv = xCS?.field ? row[xCS.field] : undefined;\n                            const yv = yCS?.field ? row[yCS.field] : undefined;\n                            if (xv == null || yv == null) continue;\n                            const xn = isTempX ? +new Date(xv) : +xv;\n                            const yn = isTempY ? +new Date(yv) : +yv;\n                            if (isNaN(xn) || isNaN(yn)) continue;\n                            perPointSeriesKeys[idx++] = seriesFields\n                                .map(f => String(row[f] ?? '')).join('\\x00');\n                        }\n                    }\n\n                    const bankingAR = computeBankingAR(\n                        xNumeric, yNumeric, xDomain, yDomain,\n                        perPointSeriesKeys, isConnected,\n                    );\n\n                    // ── Step 2: Blend AR + distribute area ────────────\n                    // Gas pressure knows which axis is crowded (per-axis\n                    // stretch).  Banking knows the perceptual ideal AR.\n                    // Blend in log space so both signals contribute:\n                    //   gasAR reflects density asymmetry (X crowded → landscape)\n                    //   bankingAR reflects slope perception\n                    const BANKING_BLEND = 0.5;\n                    const gasAR = rawW / rawH;\n                    const blendedAR = gasAR > 0 && bankingAR > 0\n                        ? Math.exp((1 - BANKING_BLEND) * Math.log(gasAR)\n                            + BANKING_BLEND * Math.log(bankingAR))\n                        : bankingAR;\n\n                    // Total area from gas pressure (capped so subplot\n                    // doesn't blow past per-subplot budget before fit).\n                    const rawArea = rawW * rawH;\n                    const maxArea = perSubplotCanvasW * perSubplotCanvasH * Math.max(maxStretchX, maxStretchY);\n                    const area = Math.min(rawArea, maxArea);\n\n                    idealW = Math.sqrt(area * blendedAR);\n                    idealH = Math.sqrt(area / blendedAR);\n                } else {\n                    // Banking skipped (zero dominates): gas pressure shape.\n                    idealW = rawW;\n                    idealH = rawH;\n                }\n\n                // ── Step 3: Fit into budget, preserving AR ───────────\n                // Hard ceiling per subplot: canvas × maxStretch shared\n                // across facet panels.\n                const availW = facetCols > 1\n                    ? Math.max(minContinuousSizeX, (defaultChartWidth * maxStretchX - fixW) / facetCols - gap)\n                    : defaultChartWidth * maxStretchX;\n                const availH = facetRows > 1\n                    ? Math.max(minContinuousSizeY, (defaultChartHeight * maxStretchY - fixH) / facetRows - gap)\n                    : defaultChartHeight * maxStretchY;\n\n                // Scale down to fit: if either axis exceeds its budget,\n                // shrink both axes by the tighter ratio so neither\n                // exceeds AND the AR is preserved.\n                const scaleX = idealW > availW ? availW / idealW : 1;\n                const scaleY = idealH > availH ? availH / idealH : 1;\n                const fitScale = Math.min(scaleX, scaleY);\n\n                let finalW = idealW * fitScale;\n                let finalH = idealH * fitScale;\n\n                // Enforce minimums (may slightly distort AR at extremes).\n                finalW = Math.max(finalW, minContinuousSizeX);\n                finalH = Math.max(finalH, minContinuousSizeY);\n\n                subplotWidth = Math.round(finalW);\n                subplotHeight = Math.round(finalH);\n            }\n        }\n    } else if (xIsContinuousNonBanded || yIsContinuousNonBanded) {\n        const contAxis = xIsContinuousNonBanded ? 'x' : 'y';\n        const otherAxisHasDiscreteItems = contAxis === 'x'\n            ? (yTotalNominalCount > 0 || yContinuousAsDiscrete > 0)\n            : (xTotalNominalCount > 0 || xContinuousAsDiscrete > 0);\n\n        let seriesStretchApplied = false;\n        if (typeof continuousMarkCrossSection === 'object' && continuousMarkCrossSection.seriesCountAxis) {\n            const resolvedAxis = continuousMarkCrossSection.seriesCountAxis === 'auto'\n                ? contAxis : continuousMarkCrossSection.seriesCountAxis;\n\n            if (resolvedAxis === contAxis) {\n                const sigmaPerSeries = contAxis === 'x'\n                    ? continuousMarkCrossSection.x\n                    : continuousMarkCrossSection.y;\n                const baseDim = contAxis === 'x' ? subplotWidth : subplotHeight;\n                const nSeries = countDistinctSeries(channelSemantics, table);\n                const pressure = (nSeries * sigmaPerSeries) / baseDim;\n\n                const elast = continuousMarkCrossSection.elasticity ?? DEFAULT_GAS_PRESSURE_PARAMS.elasticity;\n                const maxS = continuousMarkCrossSection.maxStretch ?? DEFAULT_GAS_PRESSURE_PARAMS.maxStretch;\n\n                if (pressure > 1) {\n                    const stretch = Math.min(maxS, Math.pow(pressure, elast));\n                    if (contAxis === 'x') {\n                        subplotWidth = Math.round(subplotWidth * stretch);\n                    } else {\n                        subplotHeight = Math.round(subplotHeight * stretch);\n                    }\n                }\n                seriesStretchApplied = true;\n            }\n        }\n\n        if (!seriesStretchApplied && !otherAxisHasDiscreteItems) {\n            const contCS = channelSemantics[contAxis];\n            if (contCS?.field) {\n                const isTemporal = (effectiveTypes[contAxis] || contCS.type) === 'temporal';\n                const contValues: number[] = [];\n                for (const row of table) {\n                    let v = row[contCS.field];\n                    if (v == null) continue;\n                    if (isTemporal) v = +new Date(v);\n                    else v = +v;\n                    if (!isNaN(v)) contValues.push(v);\n                }\n                const sigma1d = Math.sqrt(DEFAULT_GAS_PRESSURE_PARAMS.markCrossSection);\n                const baseDim = contAxis === 'x' ? subplotWidth : subplotHeight;\n                const pressure1d = (contValues.length * sigma1d) / baseDim;\n                if (pressure1d > 1) {\n                    const stretch1d = Math.min(\n                        DEFAULT_GAS_PRESSURE_PARAMS.maxStretch,\n                        Math.pow(pressure1d, DEFAULT_GAS_PRESSURE_PARAMS.elasticity),\n                    );\n                    if (contAxis === 'x') {\n                        subplotWidth = Math.round(subplotWidth * stretch1d);\n                    } else {\n                        subplotHeight = Math.round(subplotHeight * stretch1d);\n                    }\n                }\n            }\n        }\n    }\n\n    // --- Elastic stretch for discrete axes ---\n    // X axis grows under its width budget (βx); Y under its height budget (βy).\n    const elasticParamsX: ElasticStretchParams = {\n        elasticity: elasticityVal,\n        maxStretch: maxStretchX,\n        defaultStepSize,\n        minStep: minStepVal,\n    };\n    const elasticParamsY: ElasticStretchParams = {\n        elasticity: elasticityVal,\n        maxStretch: maxStretchY,\n        defaultStepSize,\n        minStep: minStepVal,\n    };\n\n    const xAxis = computeAxisStep(xTotalNominalCount, xContinuousAsDiscrete, subplotWidth, elasticParamsX);\n    const yAxis = computeAxisStep(yTotalNominalCount, yContinuousAsDiscrete, subplotHeight, elasticParamsY);\n\n    const xIsDiscrete = xTotalNominalCount > 0;\n    const yIsDiscrete = yTotalNominalCount > 0;\n\n    const xHasGrouping = groupAxis === 'x' && nominalCount.group > 0;\n    const yHasGrouping = groupAxis === 'y' && nominalCount.group > 0;\n\n    let xStepSize: number;\n    let yStepSize: number;\n    let xStepUnit: 'item' | 'group' | undefined;\n    let yStepUnit: 'item' | 'group' | undefined;\n\n    if (xIsDiscrete && xHasGrouping) {\n        const itemsPerGroup = nominalCount.group;\n        const defaultGroupStep = itemsPerGroup * maxStepSize;\n        const minGroupStep = Math.max(Math.ceil(MIN_GROUP_GAP_PX / stepPaddingVal), 2 * itemsPerGroup);\n        const groupAxis = computeAxisStep(nominalCount.x, 0, subplotWidth, elasticParamsX);\n        const groupStep = Math.max(minGroupStep, Math.min(defaultGroupStep, groupAxis.step));\n        xStepSize = groupStep;\n        xStepUnit = 'group';\n    } else if (xIsDiscrete) {\n        xStepSize = Math.max(minStepVal, Math.min(maxStepSize, xAxis.step));\n    } else if (xContinuousAsDiscrete > 0) {\n        xStepSize = Math.max(minStepVal, Math.min(maxStepSize, xAxis.step));\n    } else {\n        xStepSize = defaultStepSize;\n    }\n\n    if (yIsDiscrete && yHasGrouping) {\n        const itemsPerGroup = nominalCount.group;\n        const defaultGroupStep = itemsPerGroup * maxStepSize;\n        const minGroupStep = Math.max(Math.ceil(MIN_GROUP_GAP_PX / stepPaddingVal), 2 * itemsPerGroup);\n        const groupAxis = computeAxisStep(nominalCount.y, 0, subplotHeight, elasticParamsY);\n        const groupStep = Math.max(minGroupStep, Math.min(defaultGroupStep, groupAxis.step));\n        yStepSize = groupStep;\n        yStepUnit = 'group';\n    } else if (yIsDiscrete) {\n        yStepSize = Math.max(minStepVal, Math.min(maxStepSize, yAxis.step));\n    } else if (yContinuousAsDiscrete > 0) {\n        yStepSize = Math.max(minStepVal, Math.min(maxStepSize, yAxis.step));\n    } else {\n        yStepSize = defaultStepSize;\n    }\n\n    // --- Banded continuous canvas size ---\n    for (const axis of ['x', 'y'] as const) {\n        const count = axis === 'x' ? xContinuousAsDiscrete : yContinuousAsDiscrete;\n        if (count <= 0) continue;\n        const stepSize = axis === 'x' ? xStepSize : yStepSize;\n        const continuousSize = Math.round(stepSize * (count + 1));\n        if (axis === 'x') {\n            subplotWidth = continuousSize;\n        } else {\n            subplotHeight = continuousSize;\n        }\n    }\n\n    // --- Unified stretch budget ------------------------------------------------\n    // Cap the per-subplot dimensions so total canvas never exceeds\n    // canvasWidth × maxStretch (and canvasHeight × maxStretch).\n    // Formula: effectiveW = W × maxStretch − fixedPad; each panel costs subplot + gap.\n    const maxSubplotW = (defaultChartWidth * maxStretchX - fixW) / facetCols - gap;\n    const maxSubplotH = (defaultChartHeight * maxStretchY - fixH) / facetRows - gap;\n\n    // Clamp step sizes for discrete/banded axes so VL step-based\n    // sizing respects the same budget.\n    // When step unit is 'group', divide by the number of groups (nominalCount)\n    // rather than the total item count (groups × items-per-group).\n    if (xTotalNominalCount > 0) {\n        const divisor = xStepUnit === 'group' ? nominalCount.x : xTotalNominalCount;\n        const cap = Math.max(minStepVal, Math.floor(maxSubplotW / divisor));\n        if (xStepSize > cap) xStepSize = cap;\n    }\n    if (xContinuousAsDiscrete > 0) {\n        const cap = Math.max(minStepVal, Math.floor(maxSubplotW / (xContinuousAsDiscrete + 1)));\n        if (xStepSize > cap) xStepSize = cap;\n    }\n    if (yTotalNominalCount > 0) {\n        const divisor = yStepUnit === 'group' ? nominalCount.y : yTotalNominalCount;\n        const cap = Math.max(minStepVal, Math.floor(maxSubplotH / divisor));\n        if (yStepSize > cap) yStepSize = cap;\n    }\n    if (yContinuousAsDiscrete > 0) {\n        const cap = Math.max(minStepVal, Math.floor(maxSubplotH / (yContinuousAsDiscrete + 1)));\n        if (yStepSize > cap) yStepSize = cap;\n    }\n\n    // Recompute banded subplot size after step clamping.\n    for (const axis of ['x', 'y'] as const) {\n        const count = axis === 'x' ? xContinuousAsDiscrete : yContinuousAsDiscrete;\n        if (count <= 0) continue;\n        const stepSize = axis === 'x' ? xStepSize : yStepSize;\n        if (axis === 'x') subplotWidth = Math.round(stepSize * (count + 1));\n        else subplotHeight = Math.round(stepSize * (count + 1));\n    }\n\n    // --- Nominal discrete subplot sizing ---\n    // For nominal discrete axes, one backend (VL) overrides subplotWidth\n    // with step-based sizing (width:{step:N}), so the subplot dimension\n    // doesn't matter.  Other backends (Chart.js, ECharts) fill the canvas\n    // and divide evenly among categories — for them, the subplot dimension\n    // IS the canvas width.\n    //\n    // Ensure the subplot is at least as wide as canvasSize (the user's\n    // requested chart size) so backends that fill the canvas get generous\n    // bars when there are few categories.  The subplot only exceeds\n    // canvasSize when faceting shrinks it, which is already handled above.\n\n    // Clamp continuous subplot dimensions.\n    subplotWidth = Math.min(subplotWidth, Math.round(maxSubplotW));\n    subplotHeight = Math.min(subplotHeight, Math.round(maxSubplotH));\n\n    // --- Band AR blending ---\n    // When one axis is banded (discrete) and the other is continuous,\n    // each band has a natural AR = continuousSize / stepSize.  If the\n    // actual band AR exceeds the target, blend the subplot AR toward\n    // the target (in log space) to avoid excessively tall/wide bands.\n    const targetBandAR = options.targetBandAR;\n    if (targetBandAR && targetBandAR > 0) {\n        const xIsBanded = xTotalNominalCount > 0 || xContinuousAsDiscrete > 0;\n        const yIsBanded = yTotalNominalCount > 0 || yContinuousAsDiscrete > 0;\n\n        if (xIsBanded && !yIsBanded) {\n            // X is banded, Y is continuous → band AR = subplotHeight / xStepSize\n            const actualBandAR = subplotHeight / xStepSize;\n            if (actualBandAR > targetBandAR) {\n                const idealH = xStepSize * targetBandAR;\n                // Blend: 50/50 between actual and target in log space.\n                const blendedH = Math.exp(\n                    0.5 * Math.log(subplotHeight) + 0.5 * Math.log(idealH));\n                subplotHeight = Math.round(\n                    Math.max(minContinuousSizeY, Math.min(blendedH, subplotHeight)));\n            }\n        } else if (yIsBanded && !xIsBanded) {\n            // Y is banded, X is continuous → band AR = subplotWidth / yStepSize\n            const actualBandAR = subplotWidth / yStepSize;\n            if (actualBandAR > targetBandAR) {\n                const idealW = yStepSize * targetBandAR;\n                const blendedW = Math.exp(\n                    0.5 * Math.log(subplotWidth) + 0.5 * Math.log(idealW));\n                subplotWidth = Math.round(\n                    Math.max(minContinuousSizeX, Math.min(blendedW, subplotWidth)));\n            }\n        }\n    }\n\n    // --- Label sizing ---\n    // A temporal/numeric field used as a BANDED axis (one bar per value) is\n    // \"continuous-as-discrete\": its tick labels sit one-per-band exactly like a\n    // nominal axis, so they must follow the same discrete sizing ladder (shrink\n    // — and rotate when bands are narrow) rather than staying at the full\n    // continuous base font. Otherwise dense date/number bands render oversized\n    // labels that feel too large for their band and crowd together.\n    const xHasDiscreteItems = xTotalNominalCount > 0 || xContinuousAsDiscrete > 0;\n    const yHasDiscreteItems = yTotalNominalCount > 0 || yContinuousAsDiscrete > 0;\n    // Canvas-adaptive fonts: descend the tick ladder from the backend's native\n    // base, and derive header/legend sizes. Scaled by the (sub)plot's smaller\n    // dimension so small multiples shrink and large single views grow subtly.\n    const fontSizing = computeFontSizing(Math.min(subplotWidth, subplotHeight), {\n        baseLabelFontSize: options.baseLabelFontSize,\n        baseTitleFontSize: options.baseTitleFontSize,\n    });\n    const labelOpts = { baseFont: fontSizing.tickBase, minFont: 6 };\n    let xLabel = computeLabelSizing(xStepSize, xHasDiscreteItems, labelOpts);\n    let yLabel = computeLabelSizing(yStepSize, yHasDiscreteItems, labelOpts);\n\n    if (xHasDiscreteItems) {\n        const xf = channelSemantics.x?.field;\n        const xt = effectiveTypes.x || channelSemantics.x?.type;\n        const stats = computeDiscreteLabelStats(xf, table);\n        if (stats) {\n            // Numeric-like labels (declared quantitative, or all values parse as\n            // numbers — years, bins, IDs) compete for the band's width when laid\n            // out horizontally. A continuous field split into many narrow bands\n            // yields many/wide numbers that crowd. Decide horizontal vs. angled\n            // by whether the widest label fits within one band.\n            const numericLike = xt === 'quantitative' || stats.allNumeric;\n            let labelPx = stats.maxLen * xLabel.fontSize * APPROX_CHAR_WIDTH_RATIO;\n            const fewShortStrings = !numericLike\n                && stats.count <= VL_SHORT_DISCRETE_CATEGORY_COUNT\n                && stats.maxLen <= VL_SHORT_DISCRETE_LABEL_MAX_LEN;\n\n            if (fewShortStrings || (numericLike && labelPx <= xStepSize)) {\n                // We want horizontal labels here. But a small number of short\n                // string categories can still collide when the band step is\n                // narrower than the widest label (e.g. box marks declare a tiny\n                // defaultBandSize). Before committing to horizontal, make sure\n                // the label actually fits — widen the band within the stretch\n                // budget if it can, otherwise angle the labels instead of\n                // letting them overlap. (xStepSize is the per-label band width:\n                // the item step when ungrouped, the group step when grouped.)\n                if (labelPx > xStepSize) {\n                    const desiredStep = Math.ceil(labelPx) + 6; // label width + inter-label gap\n                    const cap = Math.max(minStepVal, Math.floor(maxSubplotW / stats.count));\n                    if (desiredStep <= cap) {\n                        xStepSize = Math.max(xStepSize, desiredStep);\n                        xLabel = computeLabelSizing(xStepSize, xHasDiscreteItems, labelOpts);\n                        labelPx = stats.maxLen * xLabel.fontSize * APPROX_CHAR_WIDTH_RATIO;\n                    }\n                }\n\n                if (labelPx <= xStepSize) {\n                    // Fits horizontally (already, or after widening the band).\n                    // Must be explicit: omitting labelAngle leaves VL defaults (e.g. -45° on ordinal).\n                    xLabel = {\n                        ...xLabel,\n                        labelAngle: 0,\n                        labelAlign: 'center',\n                        labelBaseline: 'top',\n                    };\n                } else {\n                    // Even the stretch budget can't fit a wide-enough band →\n                    // angle the labels rather than let them run together.\n                    xLabel = {\n                        ...xLabel,\n                        labelAngle: -45,\n                        labelAlign: 'right',\n                        labelBaseline: 'top',\n                    };\n                }\n            } else if (numericLike && labelPx > xStepSize && xLabel.labelAngle === undefined) {\n                // Numeric labels that don't fit horizontally and weren't already\n                // rotated by step-based sizing (which only rotates at narrow\n                // steps). Without this, VL keeps them horizontal and the numbers\n                // overlap. Rotate to -45°.\n                xLabel = {\n                    ...xLabel,\n                    labelAngle: -45,\n                    labelAlign: 'right',\n                    labelBaseline: 'top',\n                };\n            }\n        }\n    }\n    if (yHasDiscreteItems) {\n        const yf = channelSemantics.y?.field;\n        const yt = effectiveTypes.y || channelSemantics.y?.type;\n        if (discreteYAxisShouldUseHorizontalLabels(yf, yt, table)) {\n            yLabel = {\n                ...yLabel,\n                labelAngle: 0,\n                labelAlign: 'right',\n                labelBaseline: 'middle',\n            };\n        }\n    }\n\n    // Keep tick labels consistent across axes. A continuous value axis stays at\n    // the base font, but a banded axis shrinks its labels as bands tighten — so\n    // the value \"numbers\" can end up visibly larger than the category \"text\".\n    // Unify both tick fonts to the smaller of the two so they read as one size.\n    const unifiedTickFont = Math.min(xLabel.fontSize, yLabel.fontSize);\n    if (xLabel.fontSize !== unifiedTickFont) xLabel = { ...xLabel, fontSize: unifiedTickFont };\n    if (yLabel.fontSize !== unifiedTickFont) yLabel = { ...yLabel, fontSize: unifiedTickFont };\n\n    return {\n        subplotWidth,\n        subplotHeight,\n        xStep: xStepSize,\n        yStep: yStepSize,\n        xStepUnit,\n        yStepUnit,\n        xContinuousAsDiscrete,\n        yContinuousAsDiscrete,\n        xNominalCount: xTotalNominalCount,\n        yNominalCount: yTotalNominalCount,\n        xLabel,\n        yLabel,\n        titleFontSize: fontSizing.titleFontSize,\n        legendFontSize: fontSizing.legendFontSize,\n        stepPadding: stepPaddingVal,\n        facet: (facetCols > 1 || facetRows > 1) ? {\n            columns: facetCols,\n            rows: facetRows,\n            subplotWidth,\n            subplotHeight,\n        } : undefined,\n        effectiveFacetGap: gap,\n        truncations: [],  // Overflow truncations are handled by filterOverflow\n    };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Count distinct series (color/detail categories) from channel semantics.\n */\nfunction countDistinctSeries(\n    channelSemantics: Record<string, ChannelSemantics>,\n    data: any[],\n): number {\n    const seriesFields: string[] = [];\n    const colorField = channelSemantics.color?.field;\n    const detailField = channelSemantics.detail?.field;\n    if (colorField) seriesFields.push(colorField);\n    if (detailField && detailField !== colorField) seriesFields.push(detailField);\n\n    if (seriesFields.length === 0) return 1;\n\n    const seriesKeys = new Set<string>();\n    for (const row of data) {\n        const key = seriesFields.map(f => String(row[f] ?? '')).join('\\x00');\n        seriesKeys.add(key);\n    }\n    return seriesKeys.size;\n}\n\n/**\n * Compute the ideal aspect ratio for a both-continuous chart.\n *\n * Dispatches to two strategies depending on mark type:\n *\n * - **Scatter / point** (`isConnected = false`): Uses the normalized\n *   standard-deviation ratio of the point cloud — a unit-independent\n *   shape measure.  Dampened 0.3× toward 1.0 so scatter stays near\n *   square.\n *\n * - **Connected marks** (line/area/bump, `isConnected = true`): Uses\n *   multi-scale banking to 45° (Heer & Agrawala 2006).  Slopes are\n *   computed at multiple octave-band smoothing levels and combined via\n *   geometric mean so that trend, periodicity, and noise each\n *   contribute proportionally — avoiding the dense-data failure mode\n *   of Cleveland's single-scale median.\n *\n * @param xValues     Numeric X values\n * @param yValues     Numeric Y values (parallel array)\n * @param xDomain     [min, max] of the visual X axis\n * @param yDomain     [min, max] of the visual Y axis\n * @param seriesKeys  Per-point series key ('' if no series)\n * @param isConnected Whether the mark connects points (line/area vs scatter)\n * @returns Ideal AR (width/height). Clamped to [0.5, 3.0].\n */\nfunction computeBankingAR(\n    xValues: number[],\n    yValues: number[],\n    xDomain: [number, number],\n    yDomain: [number, number],\n    seriesKeys: string[],\n    isConnected: boolean,\n): number {\n    const MIN_AR = 0.5;\n    const MAX_AR = 3.0;\n\n    const xRange = xDomain[1] - xDomain[0];\n    const yRange = yDomain[1] - yDomain[0];\n    if (xRange <= 0 || yRange <= 0) return 1;\n\n    // ── Scatter: σ-ratio ──────────────────────────────────────────────\n    if (!isConnected) {\n        const n = xValues.length;\n        let sumX = 0, sumY = 0;\n        for (let i = 0; i < n; i++) {\n            sumX += (xValues[i] - xDomain[0]) / xRange;\n            sumY += (yValues[i] - yDomain[0]) / yRange;\n        }\n        const meanX = sumX / n;\n        const meanY = sumY / n;\n        let varX = 0, varY = 0;\n        for (let i = 0; i < n; i++) {\n            const dx = (xValues[i] - xDomain[0]) / xRange - meanX;\n            const dy = (yValues[i] - yDomain[0]) / yRange - meanY;\n            varX += dx * dx;\n            varY += dy * dy;\n        }\n        const sdX = Math.sqrt(varX / n);\n        const sdY = Math.sqrt(varY / n);\n        if (sdY <= 0) return MAX_AR;\n        if (sdX <= 0) return MIN_AR;\n\n        const sdRatio = sdX / sdY;\n        const ar = sdRatio > 1\n            ? 1 + (sdRatio - 1) * 0.3\n            : 1 - (1 - sdRatio) * 0.3;\n        return Math.min(MAX_AR, Math.max(MIN_AR, ar));\n    }\n\n    // ── Connected marks: multi-scale banking (Heer & Agrawala 2006) ──\n\n    // Group by series and sort by X.\n    const seriesMap = new Map<string, { x: number; y: number }[]>();\n    for (let i = 0; i < xValues.length; i++) {\n        const key = seriesKeys[i];\n        let arr = seriesMap.get(key);\n        if (!arr) { arr = []; seriesMap.set(key, arr); }\n        arr.push({ x: xValues[i], y: yValues[i] });\n    }\n    for (const pts of seriesMap.values()) {\n        pts.sort((a, b) => a.x - b.x);\n    }\n\n    // Collect per-scale median absolute slopes, then combine with\n    // geometric mean across scales.  Each scale is a box-filter\n    // smoothing at window width 2^k (k = 0, 1, 2, …).\n    // Scale 0 = raw data (Cleveland's original).\n    const scaleMedians: number[] = [];\n\n    // Determine max scale: largest power of 2 that still leaves ≥ 3\n    // points in the longest series after smoothing.\n    let maxSeriesLen = 0;\n    for (const pts of seriesMap.values()) {\n        if (pts.length > maxSeriesLen) maxSeriesLen = pts.length;\n    }\n    const maxScale = Math.max(0, Math.floor(Math.log2(maxSeriesLen)) - 1);\n\n    for (let scale = 0; scale <= maxScale; scale++) {\n        const windowSize = 1 << scale;  // 1, 2, 4, 8, …\n        const absSlopes: number[] = [];\n\n        for (const pts of seriesMap.values()) {\n            // Smooth: non-overlapping bucket averages of `windowSize` points.\n            // The last bucket may be smaller — included as-is.\n            const n = pts.length;\n            if (n < 2) continue;\n\n            const smoothed: { x: number; y: number }[] = [];\n            for (let i = 0; i < n; i += windowSize) {\n                const end = Math.min(i + windowSize, n);\n                let sx = 0, sy = 0;\n                for (let j = i; j < end; j++) {\n                    sx += pts[j].x;\n                    sy += pts[j].y;\n                }\n                const cnt = end - i;\n                smoothed.push({ x: sx / cnt, y: sy / cnt });\n            }\n\n            // Compute slopes between consecutive smoothed points.\n            for (let i = 1; i < smoothed.length; i++) {\n                const dx = (smoothed[i].x - smoothed[i - 1].x) / xRange;\n                const dy = (smoothed[i].y - smoothed[i - 1].y) / yRange;\n                if (dx === 0) continue;\n                absSlopes.push(Math.abs(dy / dx));\n            }\n        }\n\n        if (absSlopes.length === 0) continue;\n\n        // Median absolute slope at this scale.\n        absSlopes.sort((a, b) => a - b);\n        const mid = absSlopes.length >> 1;\n        const median = absSlopes.length % 2 === 1\n            ? absSlopes[mid]\n            : (absSlopes[mid - 1] + absSlopes[mid]) / 2;\n        if (median > 0) {\n            scaleMedians.push(median);\n        }\n    }\n\n    if (scaleMedians.length === 0) return 1;\n\n    // Geometric mean of per-scale median slopes.\n    // This gives equal weight to each octave band: trend (coarse),\n    // periodicity (middle), and noise (fine) all contribute.\n    let logSum = 0;\n    for (const m of scaleMedians) {\n        logSum += Math.log(m);\n    }\n    const combinedSlope = Math.exp(logSum / scaleMedians.length);\n\n    if (combinedSlope <= 0) return MAX_AR;\n\n    // Banking to 45°: display_slope = s_norm × (H/W).\n    // For median |display_slope| = 1:  H/W = 1/median(|s_norm|),\n    // so W/H = median(|s_norm|) = combinedSlope.\n    //\n    // No dampening here — the caller (computeLayout) blends banking AR\n    // with gas-pressure AR at 50/50, which already moderates it.\n    // Applying dampening on top of the blend would double-moderate.\n\n    // Landscape floor for connected marks: time series, line charts,\n    // and area charts are conventionally landscape.  Banking can push\n    // wider (when slopes are steep) but never portrait — the gentle-\n    // slope majority in typical time series would otherwise dominate\n    // the median and produce portrait, compressing the time axis.\n    const ar = Math.max(1.0, combinedSlope);\n    return Math.min(MAX_AR, Math.max(MIN_AR, ar));\n}\n\n// ---------------------------------------------------------------------------\n// Public: computeChannelBudgets\n// ---------------------------------------------------------------------------\n\n/**\n * Compute per-channel maximum values that can fit on the canvas.\n *\n * Uses the **most conservative** assumptions:\n *   - minStep  (smallest px per discrete item)\n *   - minSubplotSize (smallest subplot for continuous axes)\n *   - maxStretch (maximum canvas stretching)\n *\n * This is Step 0c-a in the pipeline — it runs before filterOverflow\n * and produces the budgets that filterOverflow consumes.\n *\n * Pipeline:  computeChannelBudgets → filterOverflow → computeLayout\n *\n * @param channelSemantics  Phase 0 output (field, type per channel)\n * @param declaration       Template layout declaration\n * @param data              Full data table (pre-overflow)\n * @param canvasSize        Target canvas dimensions\n * @param options           Assembly options\n * @returns                 ChannelBudgets with per-channel max-to-keep\n */\nexport function computeChannelBudgets(\n    channelSemantics: Record<string, ChannelSemantics>,\n    declaration: LayoutDeclaration,\n    data: any[],\n    canvasSize: { width: number; height: number },\n    options: AssembleOptions,\n): ChannelBudgets {\n    const {\n        minStep: minStepVal = 6,\n        stepPadding: stepPaddingVal = 0.1,\n        maxColorValues: maxColorVal = 24,\n    } = options;\n\n    const { x: maxStretchX, y: maxStretchY } = resolveStretchCaps(options);\n\n    const fixW = options.facetFixedPadding?.width ?? 0;\n    const fixH = options.facetFixedPadding?.height ?? 0;\n    const gap = options.facetGap ?? 0;\n\n    const isDiscreteType = (t: string | undefined) => t === 'nominal' || t === 'ordinal';\n    const effectiveType = (ch: string): string | undefined =>\n        declaration.resolvedTypes?.[ch] ?? channelSemantics[ch]?.type;\n\n    // --- 1. Facet grid (delegates to computeFacetGrid) ---\n    const facetGrid = computeFacetGrid(\n        channelSemantics, declaration, data, canvasSize, options,\n    );\n    const facetCols = facetGrid?.columns ?? 1;\n    const facetRows = facetGrid?.rows ?? 1;\n\n    // --- 2. Per-subplot budget at maximum stretch ---\n    const maxSubplotW = Math.max(\n        options.minSubplotSize ?? 60,\n        (canvasSize.width * maxStretchX - fixW) / facetCols - gap,\n    );\n    const maxSubplotH = Math.max(\n        options.minSubplotSize ?? 60,\n        (canvasSize.height * maxStretchY - fixH) / facetRows - gap,\n    );\n\n    // --- 3. Grouping detection ---\n    const groupField = channelSemantics.group?.field;\n    let groupCount = 0;\n    let groupAxis: 'x' | 'y' | undefined;\n    if (groupField) {\n        groupCount = new Set(data.map(r => r[groupField])).size;\n        if (isDiscreteType(effectiveType('x'))) groupAxis = 'x';\n        else if (isDiscreteType(effectiveType('y'))) groupAxis = 'y';\n    }\n\n    const xGroupMultiplier = (groupAxis === 'x' && groupCount > 1) ? groupCount : 1;\n    const yGroupMultiplier = (groupAxis === 'y' && groupCount > 1) ? groupCount : 1;\n\n    const MIN_GROUP_GAP_PX = 3;\n    const xMinGroupStep = xGroupMultiplier > 1\n        ? Math.max(Math.ceil(MIN_GROUP_GAP_PX / stepPaddingVal), 2 * xGroupMultiplier)\n        : minStepVal;\n    const yMinGroupStep = yGroupMultiplier > 1\n        ? Math.max(Math.ceil(MIN_GROUP_GAP_PX / stepPaddingVal), 2 * yGroupMultiplier)\n        : minStepVal;\n\n    // --- 4. Per-channel budgets ---\n    let maxXToKeep = Math.floor(maxSubplotW / xMinGroupStep);\n    let maxYToKeep = Math.floor(maxSubplotH / yMinGroupStep);\n\n    // --- 5. Faceted-chart canvas cap ---\n    // When a busy discrete axis makes each subplot wider than the\n    // un-stretched canvas, cap axis items to fit within one canvas\n    // width/height.  This lets subplots be narrower, potentially fitting\n    // more facet columns — reducing overall chart height.\n    //\n    // Example: 70 counties on X × 20 states on column.  Without the cap,\n    // minSubplotWidth = 70 × 6 = 420 → only 1 facet column fits → each\n    // state stacks vertically → excessively tall chart.  With the cap,\n    // X is truncated to floor(400/6) = 66 items, and the facet grid is\n    // re-derived with narrower subplots so more columns fit.\n    if (facetGrid) {\n        const canvasXCap = Math.max(1, Math.floor(canvasSize.width / xMinGroupStep));\n        const canvasYCap = Math.max(1, Math.floor(canvasSize.height / yMinGroupStep));\n\n        if (maxXToKeep > canvasXCap || maxYToKeep > canvasYCap) {\n            maxXToKeep = Math.min(maxXToKeep, canvasXCap);\n            maxYToKeep = Math.min(maxYToKeep, canvasYCap);\n\n            // With tighter axis items, subplots can be narrower, so more\n            // facet columns may fit.  Re-derive the grid for column-only\n            // wrapping (the most affected case).\n            const colField = channelSemantics.column?.field;\n            const rowField = channelSemantics.row?.field;\n            const colCount = colField\n                ? new Set(data.map(r => r[colField])).size : 0;\n\n            if (colCount > 1 && !rowField) {\n                const tighterW = Math.max(\n                    options.minSubplotSize ?? 60,\n                    maxXToKeep * xMinGroupStep,\n                );\n                const totalW = canvasSize.width * maxStretchX - fixW;\n                const totalH = canvasSize.height * maxStretchY - fixH;\n                const revisedMaxCols = Math.max(1, Math.floor(\n                    totalW / (tighterW + gap),\n                ));\n                const revisedMaxRows = Math.max(1, Math.floor(\n                    totalH / ((options.minSubplotSize ?? 60) + gap),\n                ));\n                const maxTotal = revisedMaxCols * revisedMaxRows;\n                const effectiveCount = Math.min(colCount, maxTotal);\n                const visRows = Math.ceil(effectiveCount / revisedMaxCols);\n                const visCols = Math.ceil(effectiveCount / visRows);\n\n                facetGrid.columns = visCols;\n                facetGrid.rows = visRows;\n                facetGrid.maxColumnValues = maxTotal;\n            }\n        }\n    }\n\n    // maxColumnValues already carries the correct semantics for both\n    // column+row (per-dimension cap) and column-only wrapping (total\n    // panel count = grid cols × grid rows).  No multiplication needed.\n    const maxValues: Record<string, number> = {\n        x: maxXToKeep,\n        y: maxYToKeep,\n        column: facetGrid?.maxColumnValues ?? Infinity,\n        row: facetGrid?.maxRowValues ?? Infinity,\n        color: maxColorVal,\n    };\n\n    return { maxValues, facetGrid };\n}\n\n// ---------------------------------------------------------------------------\n// Public: computeFacetGrid\n// ---------------------------------------------------------------------------\n\n/**\n * Decide the facet grid layout (including column-only wrapping).\n *\n * This runs BEFORE filterOverflow and computeLayout.  It:\n *   1. Counts unique column/row values from data.\n *   2. Computes banded-aware minimum subplot dimensions.\n *   3. Computes max columns/rows that fit in the canvas budget.\n *   4. For column-only: wraps into a 2D grid (total panels = cols × rows).\n *   5. For column+row: caps each dimension independently.\n *\n * Returns `undefined` when there are no facet channels.\n *\n * @param channelSemantics  Phase 0 output\n * @param declaration       Template layout declaration\n * @param data              Data rows (pre-overflow — possibly after temporal conversion)\n * @param canvasSize        Target canvas dimensions\n * @param options           Assembly options\n */\nexport function computeFacetGrid(\n    channelSemantics: Record<string, ChannelSemantics>,\n    declaration: LayoutDeclaration,\n    data: any[],\n    canvasSize: { width: number; height: number },\n    options: AssembleOptions,\n): import('./types').FacetGridResult | undefined {\n    const { x: msX, y: msY } = resolveStretchCaps(options);\n    const fixW = options.facetFixedPadding?.width ?? 0;\n    const fixH = options.facetFixedPadding?.height ?? 0;\n    const gap = options.facetGap ?? 0;\n    const minStep = options.minStep ?? 6;\n    const stepPadding = options.stepPadding ?? 0.1;\n    const baseMinSubplot = options.minSubplotSize ?? 60;\n\n    const isDiscreteType = (t: string | undefined) => t === 'nominal' || t === 'ordinal';\n\n    // --- Compute min subplot size per axis ---\n    //\n    // Continuous:  baseMinSubplot (e.g. 60px).\n    //\n    // Discrete (not grouped):\n    //   min(minStep × valueCount, maxDim)\n    //\n    // Discrete (grouped):\n    //   perCategoryStep = max(minStep × groupCount, minGroupStep)\n    //   min(perCategoryStep × valueCount, maxDim)\n    //\n    //   where minGroupStep accounts for the inter-group gap:\n    //     the gap = stepPadding × step, which must be ≥ MIN_GROUP_GAP_PX.\n    //\n    // Always capped at maxDim (full stretched canvas minus fixed overhead)\n    // to guarantee at least 1 facet column/row.\n\n    const maxW = canvasSize.width * msX - fixW;\n    const maxH = canvasSize.height * msY - fixH;\n    const MIN_GROUP_GAP_PX = 3;\n\n    // Grouping detection\n    const groupField = channelSemantics.group?.field;\n    let groupCount = 0;\n    let groupAxis: 'x' | 'y' | undefined;\n    if (groupField) {\n        groupCount = new Set(data.map((r: any) => r[groupField])).size;\n        const xType = declaration.resolvedTypes?.x ?? channelSemantics.x?.type;\n        const yType = declaration.resolvedTypes?.y ?? channelSemantics.y?.type;\n        if (isDiscreteType(xType)) groupAxis = 'x';\n        else if (isDiscreteType(yType)) groupAxis = 'y';\n    }\n\n    let minSubplotWidth = baseMinSubplot;\n    let minSubplotHeight = baseMinSubplot;\n\n    // Log-scale axes need more space for minor grid lines to be legible.\n    const LOG_PX_PER_DECADE_FACET = 40;\n    for (const axis of ['x', 'y'] as const) {\n        const cs = channelSemantics[axis];\n        if (!cs?.field || !cs.scaleType) continue;\n        if (cs.scaleType !== 'log' && cs.scaleType !== 'symlog') continue;\n        const vals = data\n            .map((r: any) => r[cs.field])\n            .filter((v: any) => typeof v === 'number' && v > 0 && isFinite(v));\n        if (vals.length < 2) continue;\n        const decades = Math.log10(Math.max(...vals)) - Math.log10(Math.min(...vals));\n        const needed = Math.ceil(Math.max(1, decades)) * LOG_PX_PER_DECADE_FACET;\n        if (axis === 'x') minSubplotWidth = Math.max(minSubplotWidth, needed);\n        else minSubplotHeight = Math.max(minSubplotHeight, needed);\n    }\n\n    for (const axis of ['x', 'y'] as const) {\n        const cs = channelSemantics[axis];\n        if (!cs?.field) continue;\n\n        const effectiveType = declaration.resolvedTypes?.[axis] ?? cs.type;\n        const isBanded = declaration.axisFlags?.[axis]?.banded === true;\n        if (!isDiscreteType(effectiveType) && !isBanded) continue;\n\n        const valueCount = new Set(data.map((r: any) => r[cs.field])).size;\n        const axisGroupCount = (groupAxis === axis && groupCount > 1) ? groupCount : 1;\n        const maxDim = axis === 'x' ? maxW : maxH;\n\n        let perCategoryStep: number;\n        if (axisGroupCount > 1) {\n            // Grouped: each category needs room for groupCount sub-items\n            // PLUS enough inter-group gap (stepPadding × step ≥ MIN_GROUP_GAP_PX).\n            const minGroupStep = Math.max(\n                Math.ceil(MIN_GROUP_GAP_PX / stepPadding),\n                2 * axisGroupCount,\n            );\n            perCategoryStep = Math.max(minStep * axisGroupCount, minGroupStep);\n        } else {\n            // Ungrouped: one item per category\n            perCategoryStep = minStep;\n        }\n\n        const dataDrivenMin = Math.min(perCategoryStep * valueCount, maxDim);\n        const minDim = Math.max(baseMinSubplot, dataDrivenMin);\n\n        if (axis === 'x') {\n            minSubplotWidth = minDim;\n        } else {\n            minSubplotHeight = minDim;\n        }\n    }\n\n    // --- Continuous axes: AR-based min subplot size ---\n    // When both axes are continuous (non-banded), the expected aspect\n    // ratio tells us which axis needs more room.  The shorter dimension\n    // stays at baseMinSubplot; the longer gets up to ms× (maxStretch)\n    // of the base.  This ensures line charts (landscape AR) get wider\n    // min subplots, so maxFacetColumns is lower → fewer, wider panels.\n    const xIsCont = (() => {\n        const cs = channelSemantics.x;\n        if (!cs?.field) return false;\n        const t = declaration.resolvedTypes?.x ?? cs.type;\n        return !isDiscreteType(t) && !(declaration.axisFlags?.x?.banded === true);\n    })();\n    const yIsCont = (() => {\n        const cs = channelSemantics.y;\n        if (!cs?.field) return false;\n        const t = declaration.resolvedTypes?.y ?? cs.type;\n        return !isDiscreteType(t) && !(declaration.axisFlags?.y?.banded === true);\n    })();\n\n    if (xIsCont && yIsCont) {\n        const xCS = channelSemantics.x;\n        const yCS = channelSemantics.y;\n        if (xCS?.field && yCS?.field) {\n            const isTempX = (declaration.resolvedTypes?.x ?? xCS.type) === 'temporal';\n            const isTempY = (declaration.resolvedTypes?.y ?? yCS.type) === 'temporal';\n            const cmcs = options.continuousMarkCrossSection;\n            const isConn = typeof cmcs === 'object' && !!cmcs.seriesCountAxis;\n\n            const xNum: number[] = [];\n            const yNum: number[] = [];\n            const sKeys: string[] = [];\n            const sFields: string[] = [];\n            // Include facet fields in series keys so banking computes\n            // slopes within each panel, not across panel boundaries.\n            const colF = channelSemantics.column?.field;\n            const rowF = channelSemantics.row?.field;\n            if (colF) sFields.push(colF);\n            if (rowF) sFields.push(rowF);\n            const cf = channelSemantics.color?.field;\n            const df = channelSemantics.detail?.field;\n            if (cf) sFields.push(cf);\n            if (df && df !== cf) sFields.push(df);\n\n            for (const row of data) {\n                const xv = row[xCS.field];\n                const yv = row[yCS.field];\n                if (xv == null || yv == null) continue;\n                const xn = isTempX ? +new Date(xv) : +xv;\n                const yn = isTempY ? +new Date(yv) : +yv;\n                if (isNaN(xn) || isNaN(yn)) continue;\n                xNum.push(xn);\n                yNum.push(yn);\n                sKeys.push(sFields.length > 0\n                    ? sFields.map(f => String(row[f] ?? '')).join('\\x00')\n                    : '');\n            }\n\n            if (xNum.length > 1) {\n                const xMin = Math.min(...xNum);\n                const xMax = Math.max(...xNum);\n                const yMin = Math.min(...yNum);\n                const yMax = Math.max(...yNum);\n                const xDom: [number, number] = [xMin, xMax];\n                const yDom: [number, number] = [yMin, yMax];\n                if (xCS.zero?.zero) {\n                    if (xDom[0] > 0) xDom[0] = 0;\n                    if (xDom[1] < 0) xDom[1] = 0;\n                }\n                if (yCS.zero?.zero) {\n                    if (yDom[0] > 0) yDom[0] = 0;\n                    if (yDom[1] < 0) yDom[1] = 0;\n                }\n\n                const ar = computeBankingAR(xNum, yNum, xDom, yDom, sKeys, isConn);\n\n                // Distribute: shorter side = base, longer side = base × min(ar, ms).\n                if (ar >= 1) {\n                    minSubplotWidth = Math.max(minSubplotWidth,\n                        Math.round(baseMinSubplot * Math.min(ar, msX)));\n                    minSubplotHeight = Math.max(minSubplotHeight, baseMinSubplot);\n                } else {\n                    minSubplotWidth = Math.max(minSubplotWidth, baseMinSubplot);\n                    minSubplotHeight = Math.max(minSubplotHeight,\n                        Math.round(baseMinSubplot * Math.min(1 / ar, msY)));\n                }\n            }\n        }\n    }\n\n    // effectiveW = totalBudget - fixedOverhead; each panel costs (subplot + gap).\n    const effectiveW = maxW;\n    const effectiveH = maxH;\n    const maxFacetColumns = Math.max(1, Math.floor(\n        effectiveW / (minSubplotWidth + gap),\n    ));\n    const maxFacetRows = Math.max(1, Math.floor(\n        effectiveH / (minSubplotHeight + gap),\n    ));\n\n    // Identify column/row fields\n    const colField = channelSemantics.column?.field;\n    const rowField = channelSemantics.row?.field;\n    if (!colField && !rowField) return undefined;\n\n    const colCount = colField\n        ? new Set(data.map((r: any) => r[colField])).size : 0;\n    const rowCount = rowField\n        ? new Set(data.map((r: any) => r[rowField])).size : 0;\n\n    if (colCount === 0 && rowCount === 0) return undefined;\n\n    // Explicit user override: force a specific column count for a column-wrapped\n    // facet (the `facetColumns` chart property). Clamped to [1, colCount]; the\n    // remaining panels wrap into as many rows as needed (all kept, canvas grows).\n    const forcedCols = options.facetColumns != null && options.facetColumns >= 1\n        ? Math.min(Math.max(1, Math.floor(options.facetColumns)), Math.max(1, colCount))\n        : undefined;\n\n    if (colCount > 0 && rowCount === 0) {\n        if (forcedCols != null) {\n            const nRows = Math.ceil(colCount / forcedCols);\n            return {\n                columns: forcedCols,\n                rows: nRows,\n                maxColumnValues: forcedCols * nRows,\n                maxRowValues: Math.max(maxFacetRows, nRows),\n            };\n        }\n        // Column-only.  If all panels fit in one row, use a single row.\n        // Otherwise wrap into a balanced grid: pick the number of rows\n        // that makes the grid as square as possible (cols ≈ rows) while\n        // staying within the max budget per dimension.\n        if (colCount <= maxFacetColumns) {\n            return {\n                columns: colCount,\n                rows: 1,\n                maxColumnValues: colCount,\n                maxRowValues: maxFacetRows,\n            };\n        }\n\n        // Need to wrap.  Use maxFacetColumns as the column count\n        // (fill the width), but reduce columns slightly if it would\n        // produce a widow row (a single orphan panel on the last row).\n        let nCols = maxFacetColumns;\n        let nRows = Math.ceil(colCount / nCols);\n\n        // Check for widow: if last row has only 1 panel, try nCols-1\n        // to redistribute more evenly.  Keep reducing while widow\n        // exists and nCols > 2.\n        while (nCols > 2 && (colCount % nCols) === 1) {\n            nCols--;\n            nRows = Math.ceil(colCount / nCols);\n        }\n\n        const visRows = Math.min(nRows, maxFacetRows);\n        const maxTotal = nCols * visRows;\n\n        return {\n            columns: nCols,\n            rows: visRows,\n            maxColumnValues: maxTotal,\n            maxRowValues: maxFacetRows,\n        };\n    }\n\n    // Column+row or row-only: cap each dimension independently.\n    return {\n        columns: Math.max(1, Math.min(colCount, maxFacetColumns)),\n        rows: Math.max(1, Math.min(rowCount, maxFacetRows)),\n        maxColumnValues: maxFacetColumns,\n        maxRowValues: maxFacetRows,\n    };\n}\n\n// ---------------------------------------------------------------------------\n// Public: computeMinSubplotDimensions\n// ---------------------------------------------------------------------------\n\n/**\n * Compute minimum subplot dimensions considering banded and discrete axes.\n *\n * For banded axes (e.g. temporal x on candlestick), each data point needs\n * `minStep` px, so the subplot minimum can be much larger than the generic\n * `minSubplotSize` (60px).  For discrete axes, the count of unique values\n * drives the minimum similarly.\n *\n * This is used by both filterOverflow (pre-layout) and the assemblers\n * (post-layout) to consistently compute facet column/row caps.\n *\n * @param channelSemantics  Phase 0 output (field, type per channel)\n * @param declaration       Template layout declaration (axisFlags, resolvedTypes)\n * @param data              Data rows\n * @param options           Assembly options ({ minStep, minSubplotSize })\n * @returns                 { minSubplotWidth, minSubplotHeight }\n */\nexport function computeMinSubplotDimensions(\n    channelSemantics: Record<string, ChannelSemantics>,\n    declaration: LayoutDeclaration,\n    data: any[],\n    options: { minStep?: number; minSubplotSize?: number },\n): { minSubplotWidth: number; minSubplotHeight: number } {\n    const minStep = options.minStep ?? 6;\n    const minSubplot = options.minSubplotSize ?? 60;\n\n    let minSubplotWidth = minSubplot;\n    let minSubplotHeight = minSubplot;\n\n    // Log-scale axes need more space so minor grid lines stay legible.\n    const LOG_PX_PER_DECADE_MIN = 40;\n    for (const axis of ['x', 'y'] as const) {\n        const cs = channelSemantics[axis];\n        if (!cs?.field || !cs.scaleType) continue;\n        if (cs.scaleType !== 'log' && cs.scaleType !== 'symlog') continue;\n        const vals = data\n            .map((r: any) => r[cs.field])\n            .filter((v: any) => typeof v === 'number' && v > 0 && isFinite(v));\n        if (vals.length < 2) continue;\n        const decades = Math.log10(Math.max(...vals)) - Math.log10(Math.min(...vals));\n        const needed = Math.ceil(Math.max(1, decades)) * LOG_PX_PER_DECADE_MIN;\n        if (axis === 'x') minSubplotWidth = Math.max(minSubplotWidth, needed);\n        else minSubplotHeight = Math.max(minSubplotHeight, needed);\n    }\n\n    const isDiscreteType = (t: string | undefined) =>\n        t === 'nominal' || t === 'ordinal';\n\n    for (const axis of ['x', 'y'] as const) {\n        const cs = channelSemantics[axis];\n        if (!cs?.field) continue;\n\n        const effectiveType = declaration.resolvedTypes?.[axis] ?? cs.type;\n        const isBanded = declaration.axisFlags?.[axis]?.banded === true;\n        const isDiscrete = isDiscreteType(effectiveType);\n\n        let itemCount = 0;\n        if (isBanded || isDiscrete) {\n            itemCount = new Set(data.map((r: any) => r[cs.field])).size;\n        }\n\n        if (itemCount > 0) {\n            const minDim = Math.max(minSubplot, itemCount * minStep);\n            if (axis === 'x') {\n                minSubplotWidth = Math.max(minSubplotWidth, minDim);\n            } else {\n                minSubplotHeight = Math.max(minSubplotHeight, minDim);\n            }\n        }\n    }\n\n    return { minSubplotWidth, minSubplotHeight };\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * =============================================================================\n * OVERFLOW FILTERING\n * =============================================================================\n *\n * Decides *which* discrete values to keep when there are too many for\n * the available canvas space, then filters the data accordingly.\n *\n * This module does **no layout math**.  Per-channel capacity budgets\n * are computed upstream by `computeChannelBudgets` and passed in as\n * a `ChannelBudgets` object.  This module focuses on:\n *   1. Iterating each discrete channel\n *   2. Applying the overflow strategy (which values to keep)\n *   3. Filtering data rows\n *   4. Producing truncation warnings\n *\n * Runs AFTER computeChannelBudgets and BEFORE computeLayout.\n *\n * VL dependency: **None**\n * =============================================================================\n */\n\nimport type {\n    ChannelSemantics,\n    ChartEncoding,\n    LayoutDeclaration,\n    TruncationWarning,\n    OverflowResult,\n    OverflowStrategy,\n    OverflowStrategyContext,\n    ChannelBudgets,\n} from './types';\nimport type { ChartWarning } from './types';\nimport { inferVisCategory } from './semantic-types';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Filter data to keep only the values that fit within the canvas.\n *\n * @param channelSemantics  Phase 0 output (field, type per channel)\n * @param declaration       Template layout declaration (resolvedTypes, overflowStrategy)\n * @param encodings         Original user-level encodings (for sort info)\n * @param data              Full data table\n * @param budgets           Per-channel capacity budgets from computeChannelBudgets\n * @param allMarkTypes      Set of all mark types in the template (for connected-mark detection)\n * @returns                 OverflowResult with filtered data, nominal counts, truncations, and warnings\n */\nexport function filterOverflow(\n    channelSemantics: Record<string, ChannelSemantics>,\n    declaration: LayoutDeclaration,\n    encodings: Record<string, ChartEncoding>,\n    data: any[],\n    budgets: ChannelBudgets,\n    allMarkTypes: Set<string>,\n): OverflowResult {\n\n    // --- Build effective channel info from semantics + declaration ---\n\n    const effectiveType = (ch: string): string | undefined =>\n        declaration.resolvedTypes?.[ch] ?? channelSemantics[ch]?.type;\n\n    const effectiveField = (ch: string): string | undefined => {\n        if (channelSemantics[ch]?.field) return channelSemantics[ch].field;\n        return undefined;\n    };\n\n    const isDiscreteType = (t: string | undefined) => t === 'nominal' || t === 'ordinal';\n\n    // --- Filter data ---\n\n    const nominalCounts: Record<string, number> = {\n        x: 0, y: 0, column: 0, row: 0, group: 0,\n    };\n    const truncations: TruncationWarning[] = [];\n    const warnings: ChartWarning[] = [];\n    let filteredData = data;\n\n    // Compute group nominal count\n    const groupField = channelSemantics.group?.field;\n    if (groupField) {\n        nominalCounts.group = new Set(data.map(r => r[groupField])).size;\n    }\n\n    // Strategy context for custom or default overflow\n    const strategyContext: OverflowStrategyContext = {\n        data,\n        channelSemantics,\n        encodings,\n        allMarkTypes,\n    };\n\n    const strategy = declaration.overflowStrategy ?? defaultOverflowStrategy;\n\n    for (const channel of ['x', 'y', 'column', 'row', 'color'] as const) {\n        const fieldName = effectiveField(channel);\n        const type = effectiveType(channel);\n        if (!fieldName) continue;\n\n        // Budget for this channel (Infinity if uncapped)\n        const maxToKeep = budgets.maxValues[channel] ?? Infinity;\n\n        // For non-discrete types on column/row, apply overflow cap —\n        // every unique value becomes a facet panel.\n        if (!isDiscreteType(type)) {\n            if (channel === 'column' || channel === 'row') {\n                const uniqueValues = [...new Set(filteredData.map(r => r[fieldName]))];\n                nominalCounts[channel] = Math.min(uniqueValues.length, maxToKeep);\n\n                if (uniqueValues.length > maxToKeep) {\n                    // For non-discrete facets, keep the first N values (sorted)\n                    const sorted = [...uniqueValues].sort();\n                    const valuesToKeep = sorted.slice(0, maxToKeep);\n\n                    const omittedCount = uniqueValues.length - valuesToKeep.length;\n                    warnings.push({\n                        severity: 'warning',\n                        code: 'overflow',\n                        message: `${omittedCount} of ${uniqueValues.length} values in '${fieldName}' were omitted (showing first ${valuesToKeep.length}).`,\n                        channel,\n                        field: fieldName,\n                    });\n\n                    const keepSet = new Set(valuesToKeep);\n                    filteredData = filteredData.filter(row => keepSet.has(row[fieldName]));\n                }\n            }\n            continue;\n        }\n\n        const uniqueValues = [...new Set(filteredData.map(r => r[fieldName]))];\n        nominalCounts[channel] = Math.min(uniqueValues.length, maxToKeep);\n\n        if (uniqueValues.length > maxToKeep) {\n            const valuesToKeep = strategy(channel, fieldName, uniqueValues, maxToKeep, strategyContext);\n\n            const omittedCount = uniqueValues.length - valuesToKeep.length;\n            const placeholder = `...${omittedCount} items omitted`;\n\n            warnings.push({\n                severity: 'warning',\n                code: 'overflow',\n                message: `${omittedCount} of ${uniqueValues.length} values in '${fieldName}' were omitted (showing first ${valuesToKeep.length} in sort order).`,\n                channel,\n                field: fieldName,\n            });\n\n            truncations.push({\n                severity: 'warning',\n                code: 'overflow',\n                message: `${omittedCount} of ${uniqueValues.length} values in '${fieldName}' were omitted (showing first ${valuesToKeep.length} in sort order).`,\n                channel,\n                field: fieldName,\n                keptValues: valuesToKeep,\n                omittedCount,\n                placeholder,\n            });\n\n            // Filter data rows (except for color — we keep all rows but style the legend)\n            if (channel !== 'color') {\n                filteredData = filteredData.filter(row => valuesToKeep.includes(row[fieldName]));\n            }\n        }\n    }\n\n    return { filteredData, nominalCounts, truncations, warnings };\n}\n\n// ---------------------------------------------------------------------------\n// Default overflow strategy\n// ---------------------------------------------------------------------------\n\n/**\n * Default overflow strategy: decides which discrete values to keep.\n *\n * - User-specified sort: respect it\n * - Canonical semantic order (months, ranks, etc.): keep the first N\n * - Numeric categories: keep the first N numerically\n * - Otherwise preserve data encounter order\n */\nconst defaultOverflowStrategy: OverflowStrategy = (\n    channel, fieldName, uniqueValues, maxToKeep, context,\n) => {\n    const { data, channelSemantics, encodings, allMarkTypes } = context;\n\n    // Determine sort intent from user encodings\n    const encoding = encodings[channel];\n    const sortBy = encoding?.sortBy;\n    const sortOrder = encoding?.sortOrder;\n\n    // Infer sort field and direction\n    let sortField: string | undefined;\n    let sortFieldType: string | undefined;\n    let isDescending = false;\n\n    if (sortBy) {\n        // User explicitly specified sort\n        if (sortBy === 'x' || sortBy === 'y' || sortBy === 'color') {\n            const sortCS = channelSemantics[sortBy];\n            sortField = sortCS?.field;\n            sortFieldType = sortCS?.type;\n            isDescending = sortOrder === 'descending' || (sortOrder !== 'ascending' && sortBy !== channel);\n        } else {\n            // Custom sort list — respect insertion order\n            try {\n                const sortedList = JSON.parse(sortBy);\n                if (Array.isArray(sortedList)) {\n                    const orderedValues = (sortOrder === 'descending') ? sortedList.reverse() : sortedList;\n                    return orderedValues.filter((v: any) => uniqueValues.includes(v)).slice(0, maxToKeep);\n                }\n            } catch {\n                // not a JSON list, fall through\n            }\n            isDescending = sortOrder === 'descending';\n        }\n    }\n\n    // Explicit value sort takes precedence over the category field's own type.\n    if (sortField && sortFieldType === 'quantitative') {\n        let aggregateOp = Math.max;\n        let initialValue = -Infinity;\n        if (allMarkTypes.has('bar') && sortField !== channelSemantics.color?.field) {\n            aggregateOp = (x: number, y: number) => x + y;\n            initialValue = 0;\n        }\n\n        const valueAggregates = new Map<any, number>();\n        for (const row of data) {\n            const fieldValue = row[fieldName];\n            const sortValue = Number(row[sortField] ?? 0);\n            if (valueAggregates.has(fieldValue)) {\n                valueAggregates.set(fieldValue, aggregateOp(valueAggregates.get(fieldValue)!, sortValue));\n            } else {\n                valueAggregates.set(fieldValue, aggregateOp(initialValue, sortValue));\n            }\n        }\n\n        return Array.from(valueAggregates.entries())\n            .map(([value, agg]) => ({ value, agg }))\n            .sort((a, b) => isDescending ? b.agg - a.agg : a.agg - b.agg)\n            .slice(0, maxToKeep)\n            .map(v => v.value);\n    }\n\n    const canonicalOrder = channelSemantics[channel]?.ordinalSortOrder;\n    if (!sortBy && !sortOrder && canonicalOrder?.length) {\n        const present = new Set(uniqueValues);\n        const ordered = canonicalOrder.filter(value => present.has(value));\n        const canonicalValues = new Set(ordered);\n        ordered.push(...uniqueValues.filter(value => !canonicalValues.has(value)));\n        return ordered.slice(0, maxToKeep);\n    }\n\n    // Match the display default for quantitative values treated as discrete.\n    const fieldOriginalType = inferVisCategory(data.map(r => r[fieldName]));\n    if (fieldOriginalType === 'quantitative' || channel === 'color') {\n        return [...uniqueValues].sort((a, b) => Number(a) - Number(b))\n            .slice(0, maxToKeep);\n    }\n\n    // Facet channels: first N\n    if (channel === 'column' || channel === 'row') {\n        return uniqueValues.slice(0, maxToKeep);\n    }\n\n    // Explicit field-order sort follows the displayed label order.\n    if (sortOrder === 'descending') {\n        return [...uniqueValues].sort((a, b) => String(b).localeCompare(String(a), undefined, { numeric: true })).slice(0, maxToKeep);\n    }\n    if (sortOrder === 'ascending') {\n        return [...uniqueValues].sort((a, b) => String(a).localeCompare(String(b), undefined, { numeric: true })).slice(0, maxToKeep);\n    }\n\n    // Default: first N values\n    return uniqueValues.slice(0, maxToKeep);\n};\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * Excel chart-type mapping + FormatSpec → Excel number format.\n *\n * Excel's native chart types are a fixed enum (`Excel.ChartType`), so a Flint\n * chart type maps to the closest native Excel chart. Orientation (vertical vs\n * horizontal) is decided by the assembler from channel semantics and selects\n * the Column* vs Bar* family.\n */\n\nimport type { FormatSpec } from '../core/field-semantics';\n\n/** Which native Excel family a Flint chart maps to. */\nexport interface ExcelTypeMapping {\n    /** Vertical (category on x) Excel.ChartType. */\n    vertical: string;\n    /** Horizontal (category on y) Excel.ChartType, when the family supports it. */\n    horizontal?: string;\n    /** True for pie/doughnut/… charts that have no value/category axes. */\n    noAxes?: boolean;\n    /** True for XY (both-measure) charts. */\n    xy?: boolean;\n}\n\n/** Flint chart type (display name) → Excel chart family. */\nexport const EXCEL_TYPE_MAP: Record<string, ExcelTypeMapping> = {\n    'Bar Chart': { vertical: 'ColumnClustered', horizontal: 'BarClustered' },\n    'Grouped Bar Chart': { vertical: 'ColumnClustered', horizontal: 'BarClustered' },\n    'Stacked Bar Chart': { vertical: 'ColumnStacked', horizontal: 'BarStacked' },\n    'Pyramid Chart': { vertical: 'BarStacked', horizontal: 'BarStacked' },\n    'Histogram': { vertical: 'ColumnClustered' },\n    'Line Chart': { vertical: 'Line' },\n    'Area Chart': { vertical: 'Area', horizontal: undefined },\n    'Scatter Plot': { vertical: 'XYScatter', xy: true },\n    'Connected Scatter Plot': { vertical: 'XYScatterLines', xy: true },\n    'Pie Chart': { vertical: 'Pie', noAxes: true },\n    'Donut Chart': { vertical: 'Doughnut', noAxes: true },\n    'Boxplot': { vertical: 'BoxWhisker' },\n    'Candlestick Chart': { vertical: 'StockOHLC' },\n    'Waterfall Chart': { vertical: 'Waterfall' },\n    'Radar Chart': { vertical: 'RadarMarkers' },\n    'Funnel Chart': { vertical: 'Funnel', noAxes: true },\n    'Treemap': { vertical: 'Treemap', noAxes: true },\n    'Sunburst Chart': { vertical: 'Sunburst', noAxes: true },\n};\n\n/** Chart types this backend can render natively in Excel. */\nexport function isExcelSupported(flintChartType: string): boolean {\n    return flintChartType in EXCEL_TYPE_MAP;\n}\n\n/**\n * Map a Flint {@link FormatSpec} to an Excel number-format string.\n *\n * Excel formats are pattern strings (`\"$#,##0\"`, `\"0.0%\"`, `\"#,##0\"`), distinct\n * from d3/Vega patterns, so we translate from the FormatSpec's intent (prefix,\n * suffix, abbreviate) rather than its d3 `pattern`.\n */\nexport function formatSpecToExcel(fmt: FormatSpec | undefined): string | undefined {\n    if (!fmt) return undefined;\n    const prefix = fmt.prefix ?? '';\n    const suffix = fmt.suffix ?? '';\n    const pat = fmt.pattern ?? '';\n\n    // percent\n    if (suffix === '%' || pat.includes('%')) {\n        const decimals = decimalsFromPattern(pat);\n        return decimals > 0 ? `0.${'0'.repeat(decimals)}%` : '0%';\n    }\n\n    // decide the numeric core\n    const decimals = decimalsFromPattern(pat);\n    let core = decimals > 0 ? `#,##0.${'0'.repeat(decimals)}` : '#,##0';\n    if (fmt.abbreviate) core = '#,##0,\"K\"'; // thousands abbreviation (approx)\n\n    const pre = prefix ? escapeLiteral(prefix) : '';\n    const suf = suffix ? escapeLiteral(suffix) : '';\n    if (!pre && !suf && !fmt.abbreviate && decimals === 0) return 'General';\n    return `${pre}${core}${suf}`;\n}\n\n/** Number of fractional digits requested by a d3-ish pattern (best-effort). */\nfunction decimalsFromPattern(pat: string): number {\n    const m = pat.match(/\\.(\\d+)/);\n    return m ? Number(m[1]) : 0;\n}\n\n/** Wrap non-numeric literal text so Excel treats it literally in a format. */\nfunction escapeLiteral(s: string): string {\n    // A leading/trailing currency symbol is fine bare; wrap other text in quotes.\n    if (s === '$' || s === '€' || s === '£' || s === '¥') return s;\n    return `\"${s}\"`;\n}\n","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelAreaChartDef: ExcelTemplateDef = {\n    chart: 'Area Chart',\n    channels: ['x', 'y', 'color'],\n    typeMapping: { vertical: 'Area' },\n    validate: ({ typeOf }) => typeOf('y') !== 'quantitative'\n        ? 'requires a quantitative y field for a native Excel area chart'\n        : undefined,\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelBarChartDef: ExcelTemplateDef = {\n    chart: 'Bar Chart',\n    channels: ['x', 'y', 'color'],\n    typeMapping: { vertical: 'ColumnClustered', horizontal: 'BarClustered' },\n    validate: ({ typeOf }) => typeOf('x') !== 'quantitative' && typeOf('y') !== 'quantitative'\n        ? 'requires one quantitative measure axis for a native Excel bar chart'\n        : undefined,\n};\n\nexport const excelGroupedBarChartDef: ExcelTemplateDef = {\n    chart: 'Grouped Bar Chart',\n    channels: ['x', 'y', 'group'],\n    typeMapping: { vertical: 'ColumnClustered', horizontal: 'BarClustered' },\n    validate: (context) => excelBarChartDef.validate?.(context)\n        ?? (context.typeOf('group') === 'quantitative' || context.typeOf('group') === 'temporal'\n            ? 'does not support continuous grouping in a native Excel grouped bar chart'\n            : undefined),\n};\n\nexport const excelStackedBarChartDef: ExcelTemplateDef = {\n    chart: 'Stacked Bar Chart',\n    channels: ['x', 'y', 'color'],\n    typeMapping: { vertical: 'ColumnStacked', horizontal: 'BarStacked' },\n    validate: (context) => excelBarChartDef.validate?.(context)\n        ?? (context.typeOf('color') === 'quantitative' || context.typeOf('color') === 'temporal'\n            ? 'does not support continuous color in a native Excel stacked bar chart'\n            : undefined),\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { formatSpecToExcel } from '../chart-types';\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelBoxplotDef: ExcelTemplateDef = {\n    chart: 'Boxplot',\n    channels: ['x', 'y', 'color'],\n    typeMapping: { vertical: 'BoxWhisker' },\n    validate: ({ input, fieldOf, typeOf }) => {\n        if (!fieldOf('x') || typeOf('x') === 'temporal') {\n            return 'requires a categorical x field for a native Excel box and whisker chart';\n        }\n        if (!fieldOf('y') || typeOf('y') !== 'quantitative') {\n            return 'requires a quantitative y field for a native Excel box and whisker chart';\n        }\n        if (fieldOf('color')) {\n            return 'does not yet support color-grouped native Excel box and whisker charts';\n        }\n        if (fieldOf('column') || fieldOf('row')) {\n            return 'does not support faceting in one native Excel box and whisker chart';\n        }\n        if (input.chart_spec.chartProperties?.whiskerMethod === 'minmax') {\n            return 'does not support min-max whiskers because Office.js exposes no native BoxWhisker whisker-method control';\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, semantics, fieldOf }) => {\n        const categoryField = fieldOf('x')!;\n        const valueField = fieldOf('y')!;\n        const rows = table.filter((row) => row[categoryField] != null && Number.isFinite(Number(row[valueField])));\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n        const properties = input.chart_spec.chartProperties;\n\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'BoxWhisker',\n            title: `${valueField} by ${categoryField}`,\n            seriesBy: 'Columns',\n            data: [\n                [categoryField, valueField],\n                ...rows.map((row) => [String(row[categoryField]), Number(row[valueField])]),\n            ],\n            categoryAxis: { title: categoryField },\n            valueAxis: {\n                title: valueField,\n                numberFormat: formatSpecToExcel(semantics.y?.format),\n            },\n            legend: { visible: false },\n            boxWhiskerOptions: {\n                quartileCalculation: 'Inclusive',\n                showInnerPoints: false,\n                showMeanLine: false,\n                showMeanMarker: false,\n                showOutlierPoints: properties?.showOutliers !== false,\n            },\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: { flintType: 'Boxplot', categoryField, valueField, rawObservations: rows.length },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { formatSpecToExcel } from '../chart-types';\nimport type { ExcelTemplateDef } from './types';\n\nconst PRICE_CHANNELS = ['open', 'high', 'low', 'close'] as const;\nconst EXCEL_EPOCH = Date.UTC(1899, 11, 30);\nconst DAY_MILLISECONDS = 24 * 60 * 60 * 1000;\n\nfunction excelDateSerial(value: unknown): number {\n    return (new Date(value as string | number | Date).getTime() - EXCEL_EPOCH) / DAY_MILLISECONDS;\n}\n\nfunction niceStep(span: number): number {\n    const rough = span / 5;\n    const power = 10 ** Math.floor(Math.log10(rough));\n    const fraction = rough / power;\n    return (fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10) * power;\n}\n\nexport const excelCandlestickDef: ExcelTemplateDef = {\n    chart: 'Candlestick Chart',\n    channels: ['x', 'open', 'high', 'low', 'close'],\n    typeMapping: { vertical: 'StockOHLC' },\n    validate: ({ table, fieldOf, typeOf }) => {\n        const xField = fieldOf('x');\n        if (!xField || !['temporal', 'ordinal'].includes(typeOf('x') ?? '')) {\n            return 'requires a temporal or ordered x field for a native Excel stock chart';\n        }\n        for (const channel of PRICE_CHANNELS) {\n            if (!fieldOf(channel) || typeOf(channel) !== 'quantitative') {\n                return `requires a quantitative ${channel} field for a native Excel stock chart`;\n            }\n        }\n        if (fieldOf('color') || fieldOf('group') || fieldOf('detail')) {\n            return 'does not support color, group, or detail encodings in a native Excel stock chart';\n        }\n        if (table.length === 0) {\n            return 'requires at least one OHLC row for a native Excel stock chart';\n        }\n\n        let previousTime = Number.NEGATIVE_INFINITY;\n        for (const [index, row] of table.entries()) {\n            const time = new Date(row[xField]).getTime();\n            if (!Number.isFinite(time)) {\n                return `requires a valid date at row ${index + 1} for a native Excel stock chart`;\n            }\n            if (time <= previousTime) {\n                return 'requires x values sorted in strictly increasing chronological order for a native Excel stock chart';\n            }\n            previousTime = time;\n\n            const rawPrices = PRICE_CHANNELS.map((channel) => row[fieldOf(channel)!]);\n            const [open, high, low, close] = rawPrices.map(Number);\n            if (rawPrices.some((value) => value == null || value === '') || ![open, high, low, close].every(Number.isFinite)) {\n                return `requires finite open, high, low, and close values at row ${index + 1} for a native Excel stock chart`;\n            }\n            if (high < Math.max(open, low, close) || low > Math.min(open, high, close)) {\n                return `requires coherent OHLC values at row ${index + 1} (high >= open/close/low and low <= open/close/high)`;\n            }\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, semantics, fieldOf }) => {\n        const xField = fieldOf('x')!;\n        const fields = PRICE_CHANNELS.map((channel) => fieldOf(channel)!);\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n        const labelBudget = Math.max(12, Math.floor((base.width - 90) / 14));\n        const tickLabelSpacing = table.length > labelBudget ? Math.ceil(table.length / labelBudget) : undefined;\n        const lows = table.map((row) => Number(row[fields[2]]));\n        const highs = table.map((row) => Number(row[fields[1]]));\n        const minimum = Math.min(...lows);\n        const maximum = Math.max(...highs);\n        const majorUnit = niceStep(Math.max(maximum - minimum, Math.abs(maximum) * 0.1, 1));\n        const minimumScale = Math.floor(minimum / majorUnit) * majorUnit;\n        const maximumScale = Math.ceil(maximum / majorUnit) * majorUnit;\n\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'StockOHLC',\n            title: `${fields[3]} by ${xField}`,\n            seriesBy: 'Columns',\n            data: [\n                [xField, ...fields],\n                ...table.map((row) => [\n                    excelDateSerial(row[xField]),\n                    ...fields.map((field) => Number(row[field])),\n                ]),\n            ],\n            categoryAxis: { title: xField, numberFormat: 'yyyy-mm-dd', tickLabelSpacing },\n            valueAxis: {\n                title: 'Price',\n                numberFormat: formatSpecToExcel(semantics.close?.format),\n                minimumScale,\n                maximumScale: maximumScale === maximum ? maximumScale + majorUnit : maximumScale,\n                majorUnit,\n            },\n            legend: { visible: false },\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: { flintType: 'Candlestick Chart', xField, priceFields: fields },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { formatSpecToExcel } from '../chart-types';\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelFunnelChartDef: ExcelTemplateDef = {\n    chart: 'Funnel Chart',\n    channels: ['y', 'size'],\n    typeMapping: { vertical: 'Funnel', noAxes: true },\n    validate: ({ table, fieldOf, typeOf }) => {\n        if (!fieldOf('y') || typeOf('y') === 'quantitative') {\n            return 'requires a categorical y stage field for a native Excel funnel chart';\n        }\n        if (typeOf('size') !== 'quantitative') {\n            return 'requires a quantitative size field for a native Excel funnel chart';\n        }\n        const valueField = fieldOf('size')!;\n        if (table.some((row) => Number.isFinite(Number(row[valueField])) && Number(row[valueField]) < 0)) {\n            return 'requires non-negative values for a native Excel funnel chart';\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, semantics, fieldOf }) => {\n        const stageField = fieldOf('y')!;\n        const valueField = fieldOf('size')!;\n        const stageValues = new Map<string, number>();\n        for (const row of table) {\n            const stage = row[stageField];\n            const value = Number(row[valueField]);\n            if (stage == null || !Number.isFinite(value)) continue;\n            const label = String(stage);\n            stageValues.set(label, (stageValues.get(label) ?? 0) + value);\n        }\n\n        const rows = [...stageValues.entries()];\n        const sort = input.chart_spec.chartProperties?.sort ?? 'descending';\n        if (sort === 'descending') rows.sort((left, right) => right[1] - left[1]);\n        if (sort === 'ascending') rows.sort((left, right) => left[1] - right[1]);\n\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'Funnel',\n            title: `${valueField} by ${stageField}`,\n            seriesBy: 'Columns',\n            data: [[stageField, valueField], ...rows],\n            legend: { visible: false },\n            dataLabels: {\n                visible: true,\n                numberFormat: formatSpecToExcel(semantics.size?.format),\n                fontColor: '#FFFFFF',\n                fontSize: 11,\n            },\n            seriesFormats: [{ color: '#4472C4' }],\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: {\n                flintType: 'Funnel Chart',\n                stageField,\n                valueField,\n                sort,\n                valueNumberFormat: formatSpecToExcel(semantics.size?.format),\n            },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nfunction niceBinStep(minimum: number, maximum: number, maxBins: number): number {\n    const raw = Math.max(Number.EPSILON, maximum - minimum) / Math.max(1, maxBins);\n    const power = 10 ** Math.floor(Math.log10(raw));\n    const error = raw / power;\n    const factor = error >= 5 ? 10 : error >= 2 ? 5 : error >= 1 ? 2 : 1;\n    return factor * power;\n}\n\nexport const excelHistogramDef: ExcelTemplateDef = {\n    chart: 'Histogram',\n    channels: ['x', 'color'],\n    typeMapping: { vertical: 'ColumnClustered' },\n    validate: ({ fieldOf, typeOf }) => {\n        const valueChannel = fieldOf('x') ? 'x' : 'y';\n        return !fieldOf(valueChannel) || typeOf(valueChannel) !== 'quantitative'\n            ? 'requires a quantitative value field for a native Excel histogram'\n            : undefined;\n    },\n    instantiate: ({ input, table, fieldOf }) => {\n        const valueField = fieldOf('x') ?? fieldOf('y')!;\n        const values = table.map((row) => Number(row[valueField])).filter(Number.isFinite);\n        if (values.length === 0) throw new Error('Excel histogram requires finite numeric values.');\n\n        const requestedBins = Number(input.chart_spec.chartProperties?.binCount);\n        const maxBins = Number.isFinite(requestedBins) && requestedBins > 0\n            ? Math.max(1, Math.round(requestedBins))\n            : 10;\n        const minimum = Math.min(...values);\n        const maximum = Math.max(...values);\n        const binWidth = maximum > minimum ? niceBinStep(minimum, maximum, maxBins) : 1;\n        const binMinimum = Math.floor(minimum / binWidth) * binWidth;\n        const binMaximum = Math.ceil(maximum / binWidth) * binWidth;\n        const binCount = Math.max(1, Math.round((binMaximum - binMinimum) / binWidth));\n        const labels = Array.from({ length: binCount }, (_value, index) => {\n            const lower = binMinimum + index * binWidth;\n            const upper = binMinimum + (index + 1) * binWidth;\n            return `${Number(lower.toFixed(2))}-${Number(upper.toFixed(2))}`;\n        });\n        const colorField = fieldOf('color');\n        const seriesKeys = colorField\n            ? [...new Set(table.map((row) => String(row[colorField])))]\n            : ['Count'];\n        const seriesCounts = seriesKeys.map(() => new Array(binCount).fill(0));\n        for (const row of table) {\n            const value = Number(row[valueField]);\n            if (!Number.isFinite(value)) continue;\n            const binIndex = Math.min(\n                binCount - 1,\n                Math.max(0, Math.floor((value - binMinimum) / binWidth)),\n            );\n            const seriesIndex = colorField ? seriesKeys.indexOf(String(row[colorField])) : 0;\n            if (seriesIndex >= 0) seriesCounts[seriesIndex][binIndex] += 1;\n        }\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: colorField ? 'ColumnStacked' : 'ColumnClustered',\n            title: `Distribution of ${valueField}`,\n            seriesBy: 'Columns',\n            data: [\n                [valueField, ...seriesKeys],\n                ...labels.map((label, index) => [label, ...seriesCounts.map((series) => series[index])]),\n            ],\n            categoryAxis: { title: valueField },\n            valueAxis: { title: 'Count', numberFormat: '0' },\n            legend: { visible: Boolean(colorField), position: 'Bottom' },\n            gapWidth: 0,\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: { flintType: 'Histogram', valueField, colorField, binCount, binMinimum, binMaximum },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelLineChartDef: ExcelTemplateDef = {\n    chart: 'Line Chart',\n    channels: ['x', 'y', 'color', 'strokeDash'],\n    typeMapping: { vertical: 'Line' },\n    validate: ({ typeOf }) => {\n        if (typeOf('y') !== 'quantitative') {\n            return 'requires a quantitative y field for a native Excel line chart';\n        }\n        if (typeOf('color') === 'quantitative' || typeOf('color') === 'temporal') {\n            return 'does not support continuous color on a native Excel line chart';\n        }\n        return undefined;\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelPieChartDef: ExcelTemplateDef = {\n    chart: 'Pie Chart',\n    channels: ['color', 'size', 'theta'],\n    typeMapping: { vertical: 'Pie', noAxes: true },\n};\n\nexport const excelDonutChartDef: ExcelTemplateDef = {\n    chart: 'Donut Chart',\n    channels: ['color', 'size', 'theta'],\n    typeMapping: { vertical: 'Doughnut', noAxes: true },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { formatSpecToExcel } from '../chart-types';\nimport type { ExcelTemplateDef } from './types';\n\nfunction niceMaximum(value: number): { maximum: number; majorUnit: number } {\n    const roughStep = Math.max(value, 1) / 5;\n    const power = 10 ** Math.floor(Math.log10(roughStep));\n    const fraction = roughStep / power;\n    const majorUnit = (fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10) * power;\n    return { maximum: Math.ceil(value / majorUnit) * majorUnit, majorUnit };\n}\n\nfunction absoluteNumberFormat(format: string | undefined): string {\n    const positive = !format || format === 'General' ? '#,##0' : format;\n    return `${positive};${positive};0`;\n}\n\nexport const excelPyramidChartDef: ExcelTemplateDef = {\n    chart: 'Pyramid Chart',\n    channels: ['x', 'y', 'color'],\n    typeMapping: { vertical: 'BarStacked', horizontal: 'BarStacked' },\n    validate: ({ table, fieldOf, typeOf }) => {\n        const xIsMeasure = typeOf('x') === 'quantitative';\n        const yIsMeasure = typeOf('y') === 'quantitative';\n        if (xIsMeasure === yIsMeasure) {\n            return 'requires exactly one quantitative measure axis for a native Excel pyramid chart';\n        }\n        const categoryChannel = xIsMeasure ? 'y' : 'x';\n        if (!fieldOf(categoryChannel) || typeOf(categoryChannel) === 'quantitative') {\n            return 'requires a discrete category axis for a native Excel pyramid chart';\n        }\n        const groupField = fieldOf('color');\n        if (!groupField || ['quantitative', 'temporal'].includes(typeOf('color') ?? '')) {\n            return 'requires a discrete color field for a native Excel pyramid chart';\n        }\n        const groups = [...new Set(table.map((row) => row[groupField]).filter((value) => value != null))];\n        if (groups.length !== 2) {\n            return `requires exactly two groups for a native Excel pyramid chart (found ${groups.length})`;\n        }\n        const measureField = fieldOf(xIsMeasure ? 'x' : 'y')!;\n        if (table.some((row) => Number.isFinite(Number(row[measureField])) && Number(row[measureField]) < 0)) {\n            return 'requires non-negative values for a native Excel pyramid chart';\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, semantics, fieldOf, typeOf }) => {\n        const measureChannel = typeOf('x') === 'quantitative' ? 'x' : 'y';\n        const categoryChannel = measureChannel === 'x' ? 'y' : 'x';\n        const measureField = fieldOf(measureChannel)!;\n        const categoryField = fieldOf(categoryChannel)!;\n        const groupField = fieldOf('color')!;\n        const categories = [...new Set(table.map((row) => row[categoryField]).filter((value) => value != null))];\n        const groups = [...new Set(table.map((row) => row[groupField]).filter((value) => value != null))];\n        const totals = new Map<string, number>();\n        for (const row of table) {\n            const category = row[categoryField];\n            const group = row[groupField];\n            const value = Number(row[measureField]);\n            if (category == null || group == null || !Number.isFinite(value)) continue;\n            const key = `${String(category)}\\u0000${String(group)}`;\n            totals.set(key, (totals.get(key) ?? 0) + value);\n        }\n        const valueAt = (category: unknown, group: unknown): number | null => {\n            const value = totals.get(`${String(category)}\\u0000${String(group)}`);\n            return value === undefined ? null : value;\n        };\n        const maximumValue = Math.max(0, ...totals.values());\n        const { maximum, majorUnit } = niceMaximum(maximumValue);\n        const numberFormat = formatSpecToExcel(semantics[measureChannel]?.format);\n        const base = input.chart_spec.baseSize ?? { width: 560, height: 360 };\n\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'BarStacked',\n            title: `${measureField} by ${categoryField} and ${groupField}`,\n            seriesBy: 'Columns',\n            data: [\n                [categoryField, ...groups.map(String)],\n                ...categories.map((category) => {\n                    const leftValue = valueAt(category, groups[0]);\n                    return [\n                        String(category),\n                        leftValue === null ? null : -leftValue,\n                        valueAt(category, groups[1]),\n                    ];\n                }),\n            ],\n            categoryAxis: { title: categoryField, reversePlotOrder: true },\n            valueAxis: {\n                title: measureField,\n                numberFormat: absoluteNumberFormat(numberFormat),\n                minimumScale: -maximum,\n                maximumScale: maximum,\n                majorUnit,\n            },\n            legend: { visible: true, position: 'Bottom' },\n            seriesFormats: [{ color: '#4472C4' }, { color: '#C55A5A' }],\n            gapWidth: 45,\n            overlap: 100,\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: {\n                flintType: 'Pyramid Chart',\n                categoryField,\n                measureField,\n                groupField,\n                groups: groups.map(String),\n            },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nfunction niceMaximum(value: number): number {\n    if (!(value > 0)) return 1;\n    const power = 10 ** Math.floor(Math.log10(value));\n    const fraction = value / power;\n    const niceFraction = fraction <= 1 ? 1\n        : fraction <= 2 ? 2\n        : fraction <= 2.5 ? 2.5\n        : fraction <= 5 ? 5\n        : 10;\n    return niceFraction * power;\n}\n\nexport const excelRadarChartDef: ExcelTemplateDef = {\n    chart: 'Radar Chart',\n    channels: ['x', 'y', 'color'],\n    typeMapping: { vertical: 'RadarMarkers' },\n    validate: ({ table, fieldOf, typeOf }) => {\n        if (!fieldOf('x') || typeOf('x') === 'quantitative' || typeOf('x') === 'temporal') {\n            return 'requires a categorical metric x field for a native Excel radar chart';\n        }\n        if (!fieldOf('y') || typeOf('y') !== 'quantitative') {\n            return 'requires a quantitative y field for a native Excel radar chart';\n        }\n        if (fieldOf('color') && (typeOf('color') === 'quantitative' || typeOf('color') === 'temporal')) {\n            return 'requires a discrete color field for native Excel radar series';\n        }\n        if (fieldOf('column') || fieldOf('row')) {\n            return 'does not support faceting in one native Excel radar chart';\n        }\n        const valueField = fieldOf('y')!;\n        if (table.some((row) => Number(row[valueField]) < 0)) {\n            return 'requires non-negative values for a native Excel radar chart';\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, fieldOf }) => {\n        const metricField = fieldOf('x')!;\n        const valueField = fieldOf('y')!;\n        const seriesField = fieldOf('color');\n        const metrics = [...new Set(table.map((row) => String(row[metricField])))];\n        if (metrics.length < 3) {\n            throw new Error('Excel radar chart requires at least three metric axes.');\n        }\n        const seriesKeys = seriesField\n            ? [...new Set(table.map((row) => String(row[seriesField])))]\n            : [valueField];\n        const metricMaximums = new Map(metrics.map((metric) => {\n            const values = table\n                .filter((row) => String(row[metricField]) === metric)\n                .map((row) => Number(row[valueField]))\n                .filter(Number.isFinite);\n            return [metric, niceMaximum(values.length > 0 ? Math.max(...values) : 1)] as const;\n        }));\n        const accumulators = new Map<string, { sum: number; count: number }>();\n        for (const row of table) {\n            const metric = String(row[metricField]);\n            const series = seriesField ? String(row[seriesField]) : valueField;\n            const value = Number(row[valueField]);\n            if (!Number.isFinite(value)) continue;\n            const key = `${series}\\u0000${metric}`;\n            const accumulator = accumulators.get(key) ?? { sum: 0, count: 0 };\n            accumulator.sum += value;\n            accumulator.count += 1;\n            accumulators.set(key, accumulator);\n        }\n        const normalizedValue = (series: string, metric: string): number => {\n            const accumulator = accumulators.get(`${series}\\u0000${metric}`);\n            if (!accumulator) return 0;\n            return (accumulator.sum / accumulator.count) / metricMaximums.get(metric)!;\n        };\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 400 };\n        const filledRequested = input.chart_spec.chartProperties?.filled !== false;\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'RadarMarkers',\n            title: `${valueField} by ${metricField}`,\n            seriesBy: 'Columns',\n            data: [\n                [metricField, ...seriesKeys],\n                ...metrics.map((metric) => [\n                    `${metric} (${metricMaximums.get(metric)})`,\n                    ...seriesKeys.map((series) => normalizedValue(series, metric)),\n                ]),\n            ],\n            valueAxis: { minimumScale: 0, maximumScale: 1, majorUnit: 0.25 },\n            legend: { visible: Boolean(seriesField), position: 'Bottom' },\n            width: base.width,\n            height: base.height,\n            warnings: filledRequested ? [{\n                severity: 'info',\n                code: 'excel-radar-fill-unsupported',\n                message: 'Excel Radar uses outlines and markers because Office.js does not expose translucent chart-series fills.',\n            }] : [],\n            _flint: {\n                flintType: 'Radar Chart',\n                metricField,\n                valueField,\n                seriesField,\n                metricMaximums: Object.fromEntries(metricMaximums),\n                normalized: true,\n                filledRequested,\n            },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ChartAssemblyInput, SemanticResult } from '../../core/types';\nimport type { ExcelTypeMapping } from '../chart-types';\nimport type { ExcelNativeChartSpec } from '../types';\n\nexport interface ExcelTemplateContext {\n    input: ChartAssemblyInput;\n    table: any[];\n    semantics: SemanticResult;\n    fieldOf: (channel: string) => string | undefined;\n    typeOf: (channel: string) => string | undefined;\n}\n\nexport interface ExcelTemplateDef {\n    chart: string;\n    channels: string[];\n    typeMapping: ExcelTypeMapping;\n    validate?: (context: ExcelTemplateContext) => string | undefined;\n    instantiate?: (context: ExcelTemplateContext) => ExcelNativeChartSpec;\n}\n\nexport function requireQuantitativeAxes(context: ExcelTemplateContext): string | undefined {\n    if (context.typeOf('x') !== 'quantitative' || context.typeOf('y') !== 'quantitative') {\n        return 'requires quantitative x and y fields for a native Excel XY chart';\n    }\n    if (context.fieldOf('shape')) {\n        return 'does not support a shape encoding in native Excel charts';\n    }\n    return undefined;\n}","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\nimport { requireQuantitativeAxes } from './types';\n\nexport const excelScatterPlotDef: ExcelTemplateDef = {\n    chart: 'Scatter Plot',\n    channels: ['x', 'y', 'color', 'size'],\n    typeMapping: { vertical: 'XYScatter', xy: true },\n    validate: (context) => requireQuantitativeAxes(context)\n        ?? (context.typeOf('color') === 'quantitative' || context.typeOf('color') === 'temporal'\n            ? 'does not support continuous color in a native Excel Scatter or Bubble chart'\n            : undefined),\n};\n\nexport const excelConnectedScatterPlotDef: ExcelTemplateDef = {\n    chart: 'Connected Scatter Plot',\n    channels: ['x', 'y', 'order', 'color', 'detail'],\n    typeMapping: { vertical: 'XYScatterLines', xy: true },\n    validate: (context) => requireQuantitativeAxes(context)\n        ?? (!context.fieldOf('order')\n            ? 'requires an explicit order field for a native Excel connected scatter chart'\n            : context.fieldOf('detail')\n                ? 'does not support an unlegended detail series in a native Excel connected scatter chart'\n                : context.typeOf('color') === 'quantitative' || context.typeOf('color') === 'temporal'\n                    ? 'does not support continuous color in a native Excel connected scatter chart'\n                    : undefined),\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelSunburstChartDef: ExcelTemplateDef = {\n    chart: 'Sunburst Chart',\n    channels: ['color', 'size', 'group', 'detail'],\n    typeMapping: { vertical: 'Sunburst', noAxes: true },\n    validate: ({ table, fieldOf, typeOf }) => {\n        if (!fieldOf('color') || typeOf('color') === 'quantitative') {\n            return 'requires a categorical color field for a native Excel sunburst chart';\n        }\n        if (typeOf('size') !== 'quantitative') {\n            return 'requires a quantitative size field for a native Excel sunburst chart';\n        }\n        if (fieldOf('group') && typeOf('group') === 'quantitative') {\n            return 'requires a categorical group field for a native Excel sunburst hierarchy';\n        }\n        if (fieldOf('detail') && !fieldOf('group')) {\n            return 'requires a group field before detail in a native Excel sunburst hierarchy';\n        }\n        if (fieldOf('detail') && typeOf('detail') === 'quantitative') {\n            return 'requires a categorical detail field for a native Excel sunburst hierarchy';\n        }\n        const valueField = fieldOf('size')!;\n        if (table.some((row) => Number.isFinite(Number(row[valueField])) && Number(row[valueField]) < 0)) {\n            return 'requires non-negative values for a native Excel sunburst chart';\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, fieldOf }) => {\n        const categoryField = fieldOf('color')!;\n        const groupField = fieldOf('group');\n        const detailField = fieldOf('detail');\n        const valueField = fieldOf('size')!;\n        const hierarchyFields = [categoryField, groupField, detailField].filter((field): field is string => Boolean(field));\n        const leaves = new Map<string, { path: string[]; value: number }>();\n        for (const row of table) {\n            const path = hierarchyFields.map((field) => row[field]);\n            const value = Number(row[valueField]);\n            if (path.some((part) => part == null) || !Number.isFinite(value)) continue;\n            const labels = path.map(String);\n            const key = labels.join('\\u0000');\n            const existing = leaves.get(key);\n            leaves.set(key, { path: labels, value: (existing?.value ?? 0) + value });\n        }\n\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'Sunburst',\n            title: `${valueField} by ${hierarchyFields[hierarchyFields.length - 1]}`,\n            seriesBy: 'Columns',\n            data: [\n                [...hierarchyFields, valueField],\n                ...[...leaves.values()].map((leaf) => [...leaf.path, leaf.value]),\n            ],\n            legend: { visible: false },\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: { flintType: 'Sunburst Chart', hierarchyFields, valueField },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelTreemapDef: ExcelTemplateDef = {\n    chart: 'Treemap',\n    channels: ['color', 'size', 'detail'],\n    typeMapping: { vertical: 'Treemap', noAxes: true },\n    validate: ({ table, fieldOf, typeOf }) => {\n        if (!fieldOf('color') || typeOf('color') === 'quantitative') {\n            return 'requires a categorical color field for a native Excel treemap';\n        }\n        if (typeOf('size') !== 'quantitative') {\n            return 'requires a quantitative size field for a native Excel treemap';\n        }\n        if (fieldOf('detail') && typeOf('detail') === 'quantitative') {\n            return 'requires a categorical detail field for a native Excel treemap hierarchy';\n        }\n        const valueField = fieldOf('size')!;\n        if (table.some((row) => Number.isFinite(Number(row[valueField])) && Number(row[valueField]) < 0)) {\n            return 'requires non-negative values for a native Excel treemap';\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, fieldOf }) => {\n        const categoryField = fieldOf('color')!;\n        const detailField = fieldOf('detail');\n        const valueField = fieldOf('size')!;\n        const leaves = new Map<string, { category: string; detail?: string; value: number }>();\n        for (const row of table) {\n            const category = row[categoryField];\n            const detail = detailField ? row[detailField] : undefined;\n            const value = Number(row[valueField]);\n            if (category == null || (detailField && detail == null) || !Number.isFinite(value)) continue;\n            const categoryLabel = String(category);\n            const detailLabel = detailField ? String(detail) : undefined;\n            const key = `${categoryLabel}\\u0000${detailLabel ?? ''}`;\n            const existing = leaves.get(key);\n            leaves.set(key, {\n                category: categoryLabel,\n                detail: detailLabel,\n                value: (existing?.value ?? 0) + value,\n            });\n        }\n\n        const rows = [...leaves.values()];\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'Treemap',\n            title: `${valueField} by ${detailField ?? categoryField}`,\n            seriesBy: 'Columns',\n            data: detailField\n                ? [[categoryField, detailField, valueField], ...rows.map((row) => [row.category, row.detail!, row.value])]\n                : [[categoryField, valueField], ...rows.map((row) => [row.category, row.value])],\n            legend: { visible: false },\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: { flintType: 'Treemap', categoryField, detailField, valueField },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * Shared waterfall \"totals\" semantics, used by every backend template\n * (Vega-Lite / ECharts / Chart.js) and by the `totals` property `check` so the\n * options UI and the rendered chart never disagree on the default.\n *\n * A waterfall bar is either a *delta* (floats off the running cumulative) or a\n * *total* (anchored at zero, \"touches down\" to the running cumulative). When\n * the data has no explicit type column, Flint infers which ends are totals.\n * The user's `totals` property is purely an *override* of that inference.\n */\n\nexport type WaterfallTotalsMode = 'none' | 'first' | 'last' | 'both';\n\n/**\n * True when the final value reconciles with the running cumulative of every\n * prior row — i.e. the last row reads like a genuine grand-total restatement\n * (`last ≈ Σ prior`). Tolerance is relative (0.5% of the cumulative) with a\n * tiny absolute floor for near-zero totals. Non-finite values never reconcile.\n */\nexport function waterfallLastReconciles(values: number[]): boolean {\n    if (values.length < 2) return false;\n    let cumPrev = 0;\n    for (let i = 0; i < values.length - 1; i++) {\n        if (!Number.isFinite(values[i])) return false;\n        cumPrev += values[i];\n    }\n    const last = values[values.length - 1];\n    if (!Number.isFinite(last)) return false;\n    const tol = Math.max(1e-6, 0.005 * Math.abs(cumPrev));\n    return Math.abs(last - cumPrev) <= tol;\n}\n\n/**\n * The compiler's inferred default when the user hasn't set `totals` and there\n * is no explicit type column. The first bar is always a reasonable start total;\n * the last bar is only treated as a total when it reconciles with the prior\n * cumulative — otherwise it stays a floating delta.\n */\nexport function recommendedTotalsMode(values: number[]): 'first' | 'both' {\n    return waterfallLastReconciles(values) ? 'both' : 'first';\n}\n\n/**\n * Resolve the effective totals mode: a valid explicit user value wins;\n * anything else (undefined, or the UI default 'auto') falls back to the\n * data-aware recommendation.\n */\nexport function resolveTotalsMode(values: number[], explicit?: unknown): WaterfallTotalsMode {\n    if (explicit === 'none' || explicit === 'first' || explicit === 'last' || explicit === 'both') {\n        return explicit;\n    }\n    return recommendedTotalsMode(values);\n}","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { resolveTotalsMode } from '../../chart-types/waterfall';\nimport { formatSpecToExcel } from '../chart-types';\nimport type { ExcelTemplateDef } from './types';\n\nexport const excelWaterfallChartDef: ExcelTemplateDef = {\n    chart: 'Waterfall Chart',\n    channels: ['x', 'y', 'color'],\n    typeMapping: { vertical: 'Waterfall' },\n    validate: ({ input, table, fieldOf, typeOf }) => {\n        if (!fieldOf('x')) return 'requires a category x field for a native Excel waterfall chart';\n        if (typeOf('y') !== 'quantitative') {\n            return 'requires a quantitative y field for a native Excel waterfall chart';\n        }\n        if (fieldOf('color') && typeOf('color') === 'quantitative') {\n            return 'requires color to contain start/delta/end roles for a native Excel waterfall chart';\n        }\n        const valueField = fieldOf('y')!;\n        const typeField = fieldOf('color');\n        const values = table.map((row) => Number(row[valueField])).filter(Number.isFinite);\n        if (typeField) {\n            const unsupportedTotal = table.findIndex((row, index) => {\n                const role = String(row[typeField] ?? '').toLowerCase();\n                return index > 0 && (role === 'start' || role === 'end' || role === 'total');\n            });\n            if (unsupportedTotal >= 0) {\n                return 'cannot mark non-initial total points because Office.js does not expose Waterfall total-point semantics';\n            }\n        } else {\n            const totals = resolveTotalsMode(values, input.chart_spec.chartProperties?.totals);\n            if (totals === 'last' || totals === 'both') {\n                return 'cannot mark a final total because Office.js does not expose Waterfall total-point semantics';\n            }\n        }\n        return undefined;\n    },\n    instantiate: ({ input, table, semantics, fieldOf }) => {\n        const categoryField = fieldOf('x')!;\n        const valueField = fieldOf('y')!;\n        const rows = table.filter((row) => row[categoryField] != null && Number.isFinite(Number(row[valueField])));\n\n        const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n        return {\n            schema: 'flint.excel.chart/v1',\n            kind: 'chart',\n            chartType: 'Waterfall',\n            title: `${valueField} by ${categoryField}`,\n            seriesBy: 'Columns',\n            data: [\n                [categoryField, valueField],\n                ...rows.map((row) => [String(row[categoryField]), Number(row[valueField])]),\n            ],\n            categoryAxis: { title: categoryField },\n            valueAxis: {\n                title: valueField,\n                numberFormat: formatSpecToExcel(semantics.y?.format),\n            },\n            legend: { visible: false },\n            showConnectorLines: true,\n            width: base.width,\n            height: base.height,\n            warnings: [],\n            _flint: { flintType: 'Waterfall Chart', categoryField, valueField },\n        };\n    },\n};","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { ExcelTemplateDef } from './types';\nimport { excelAreaChartDef } from './area';\nimport { excelBarChartDef, excelGroupedBarChartDef, excelStackedBarChartDef } from './bar';\nimport { excelBoxplotDef } from './boxplot';\nimport { excelCandlestickDef } from './candlestick';\nimport { excelFunnelChartDef } from './funnel';\nimport { excelHistogramDef } from './histogram';\nimport { excelLineChartDef } from './line';\nimport { excelDonutChartDef, excelPieChartDef } from './pie';\nimport { excelPyramidChartDef } from './pyramid';\nimport { excelRadarChartDef } from './radar';\nimport { excelConnectedScatterPlotDef, excelScatterPlotDef } from './scatter';\nimport { excelSunburstChartDef } from './sunburst';\nimport { excelTreemapDef } from './treemap';\nimport { excelWaterfallChartDef } from './waterfall';\n\nexport const excelAllTemplateDefs: ExcelTemplateDef[] = [\n    excelBarChartDef,\n    excelGroupedBarChartDef,\n    excelStackedBarChartDef,\n    excelPyramidChartDef,\n    excelLineChartDef,\n    excelAreaChartDef,\n    excelScatterPlotDef,\n    excelConnectedScatterPlotDef,\n    excelPieChartDef,\n    excelDonutChartDef,\n    excelHistogramDef,\n    excelBoxplotDef,\n    excelCandlestickDef,\n    excelWaterfallChartDef,\n    excelRadarChartDef,\n    excelFunnelChartDef,\n    excelTreemapDef,\n    excelSunburstChartDef,\n];\n\nexport function excelGetTemplateDef(chartType: string): ExcelTemplateDef | undefined {\n    return excelAllTemplateDefs.find((template) => template.chart === chartType);\n}\n\nexport function excelGetTemplateChannels(chartType: string): string[] {\n    return excelGetTemplateDef(chartType)?.channels ?? [];\n}\n\nexport type { ExcelTemplateContext, ExcelTemplateDef } from './types';","// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\n/**\n * Excel chart assembly — Stage-3 code generator for Office.js Excel charts.\n *\n * Reuses the SAME core analysis pipeline as the other backends:\n *   Phase 0:  convertTemporalData + resolveChannelSemantics → ChannelSemantics\n *             (this decides each channel's role: quantitative = MEASURE,\n *              nominal/ordinal/temporal = CATEGORY — no heuristics)\n *   Stage 3:  pivot the long/tidy rows into Excel's WIDE matrix and emit an\n *             ExcelChartSpec (native Office.js chart description).\n *\n * Excel charts consume a rectangular range (`charts.add(type, range, seriesBy)`),\n * so the long/tidy data is pivoted: category field → first column, series field\n * → series columns, measure → cells. Visual STYLE stays native to Excel (its\n * own palette/gridlines); only Flint's LAYOUT decisions (which field is the\n * category, number format, legend, orientation) are carried over.\n */\n\nimport type {\n    ChartAssemblyInput,\n    ChartEncoding,\n    ChartWarning,\n    LayoutDeclaration,\n    SemanticResult,\n} from '../core/types';\nimport { resolveChannelSemantics, convertTemporalData } from '../core/resolve-semantics';\nimport { detectBandedAxisFromSemantics } from '../core/axis-detection';\nimport { computeChannelBudgets, deriveStretchCaps, resolveBaseSize } from '../core/compute-layout';\nimport { filterOverflow } from '../core/filter-overflow';\nimport { formatSpecToExcel } from './chart-types';\nimport { excelGetTemplateDef } from './templates';\nimport type {\n    ExcelAxisSpec,\n    ExcelChartSpec,\n    ExcelNativeChartSpec,\n    ExcelNativeSeriesSpec,\n    ExcelSeriesBy,\n} from './types';\n\ntype Cell = string | number | null;\n\nconst EXCEL_SERIES_COLORS = ['#4472C4', '#ED7D31', '#70AD47', '#FFC000', '#5B9BD5', '#A5A5A5'];\n\nfunction niceStep(span: number, targetTicks = 5): number {\n    if (!(span > 0)) return 1;\n    const rough = span / targetTicks;\n    const power = 10 ** Math.floor(Math.log10(rough));\n    const fraction = rough / power;\n    const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;\n    return niceFraction * power;\n}\n\nfunction focusedNumericAxis(values: number[]): Partial<Pick<ExcelAxisSpec, 'minimumScale' | 'maximumScale' | 'majorUnit'>> {\n    const finite = values.filter(Number.isFinite);\n    if (finite.length === 0) return {};\n    const dataMinimum = Math.min(...finite);\n    const dataMaximum = Math.max(...finite);\n    const dataSpan = dataMaximum - dataMinimum;\n    const referenceSpan = dataSpan > 0 ? dataSpan : Math.max(1, Math.abs(dataMaximum) * 0.1);\n    const majorUnit = niceStep(referenceSpan);\n    const precision = 10 ** Math.max(0, -Math.floor(Math.log10(majorUnit)) + 1);\n    const round = (value: number) => Math.round(value * precision) / precision;\n    if (dataSpan === 0) {\n        return {\n            minimumScale: round(dataMinimum - majorUnit),\n            maximumScale: round(dataMaximum + majorUnit),\n            majorUnit,\n        };\n    }\n    const onMajorTick = (value: number) => Math.abs(value / majorUnit - Math.round(value / majorUnit)) < 1e-9;\n    const minimumScale = dataMinimum >= 0 && dataMinimum <= referenceSpan * 0.1\n        ? 0\n        : round(Math.floor(dataMinimum / majorUnit) * majorUnit);\n    const nextMajorTick = Math.ceil(dataMaximum / majorUnit) * majorUnit;\n    const maximumScale = onMajorTick(dataMaximum)\n        ? dataMaximum + majorUnit * 0.25\n        : nextMajorTick;\n    return {\n        minimumScale,\n        maximumScale: round(maximumScale),\n        majorUnit,\n    };\n}\n\nfunction temporalLabelSpacing(categoryCount: number, width: number): number | undefined {\n    const labelBudget = Math.max(12, Math.floor((width - 90) / 14));\n    return categoryCount > labelBudget ? Math.ceil(categoryCount / labelBudget) : undefined;\n}\n\n/** Normalize shorthand (`\"x\": \"field\"`) to `{ field }`. */\nfunction normalizeEncodings(\n    raw: Record<string, unknown>,\n): Record<string, ChartEncoding> {\n    const out: Record<string, ChartEncoding> = {};\n    for (const [ch, v] of Object.entries(raw ?? {})) {\n        if (v == null) continue;\n        out[ch] = typeof v === 'string' ? { field: v } : (v as ChartEncoding);\n    }\n    return out;\n}\n\n/** Distinct values of a field, first-seen order. */\nfunction distinct(rows: any[], field: string): Cell[] {\n    const seen = new Set<unknown>();\n    const out: Cell[] = [];\n    for (const r of rows) {\n        const v = r[field];\n        if (!seen.has(v)) { seen.add(v); out.push(v as Cell); }\n    }\n    return out;\n}\n\nfunction interpolateMissing(values: Cell[]): Cell[] {\n    const output = [...values];\n    for (let index = 0; index < output.length; index += 1) {\n        if (output[index] != null) continue;\n        let previous = index - 1;\n        let next = index + 1;\n        while (previous >= 0 && output[previous] == null) previous -= 1;\n        while (next < output.length && output[next] == null) next += 1;\n        if (previous < 0 || next >= output.length) continue;\n        const start = Number(output[previous]);\n        const end = Number(output[next]);\n        if (!Number.isFinite(start) || !Number.isFinite(end)) continue;\n        output[index] = start + ((end - start) * (index - previous)) / (next - previous);\n    }\n    return output;\n}\n\nfunction normalizedBubbleSizes(\n    rows: any[],\n    field: string,\n    type: string | undefined,\n    width: number,\n    height: number,\n): Map<any, number> {\n    const values = rows.map((row) => row[field]).filter((value) => value != null);\n    const unique = [...new Set(values)];\n    const maximumArea = Math.round(Math.max(16, Math.min(361, (width * height / Math.max(1, rows.length)) * 0.6)));\n    const minimumArea = type === 'quantitative' || type === 'temporal'\n        ? 9\n        : Math.round(maximumArea / 4);\n    const output = new Map<any, number>();\n    if (type !== 'quantitative' && type !== 'temporal') {\n        unique.forEach((value, index) => {\n            const t = unique.length > 1 ? index / (unique.length - 1) : 0.5;\n            output.set(value, minimumArea + t * (maximumArea - minimumArea));\n        });\n        return output;\n    }\n\n    const numeric = values.map(Number).filter(Number.isFinite);\n    const maximum = numeric.length > 0 ? Math.max(...numeric) : 1;\n    const sqrtMaximum = Math.sqrt(Math.max(0, maximum));\n    unique.forEach((value) => {\n        const numericValue = Number(value);\n        const t = sqrtMaximum > 0 && Number.isFinite(numericValue)\n            ? Math.sqrt(Math.max(0, numericValue)) / sqrtMaximum\n            : 0;\n        output.set(value, minimumArea + t * (maximumArea - minimumArea));\n    });\n    return output;\n}\n\nfunction interpolateColor(start: string, end: string, t: number): string {\n    const channel = (color: string, offset: number) => Number.parseInt(color.slice(offset, offset + 2), 16);\n    const hex = (value: number) => Math.round(value).toString(16).padStart(2, '0');\n    return `#${hex(channel(start, 1) + (channel(end, 1) - channel(start, 1)) * t)}${hex(channel(start, 3) + (channel(end, 3) - channel(start, 3)) * t)}${hex(channel(start, 5) + (channel(end, 5) - channel(start, 5)) * t)}`;\n}\n\n/**\n * Assemble an {@link ExcelChartSpec} from a {@link ChartAssemblyInput}.\n *\n * @throws if the chart type has no native Excel equivalent (e.g. Heatmap).\n */\nexport function assembleExcel(input: ChartAssemblyInput): ExcelChartSpec {\n    const flintType = input.chart_spec.chartType;\n    const semanticTypes = input.semantic_types ?? {};\n    const rawData: any[] = input.data.values ?? [];\n    const encodings = normalizeEncodings(input.chart_spec.encodings);\n\n    // ── Phase 0 (reused core): resolve per-channel semantics ────────────────\n    let convertedData = convertTemporalData(rawData, semanticTypes);\n    const sem: SemanticResult = resolveChannelSemantics(\n        encodings, rawData, semanticTypes, convertedData,\n    );\n    const typeOf = (ch: string) => sem[ch]?.type;\n    const isMeasure = (ch: string) => typeOf(ch) === 'quantitative';\n    const fieldOf = (ch: string) => encodings[ch]?.field;\n    const overflowOrder = new Map<string, Cell[]>();\n    const chartTemplate = excelGetTemplateDef(flintType);\n    if (!chartTemplate) {\n        throw new Error(`Excel backend does not support chart type \"${flintType}\" as a native Office.js chart.`);\n    }\n    if (fieldOf('column') || fieldOf('row')) {\n        throw new Error(`Excel backend does not support faceting in one native Excel chart: \"${flintType}\".`);\n    }\n    const templateContext = { input, table: convertedData, semantics: sem, fieldOf, typeOf };\n    const unsupportedReason = chartTemplate.validate?.(templateContext);\n    if (unsupportedReason) {\n        throw new Error(`Excel backend ${unsupportedReason}: \"${flintType}\".`);\n    }\n\n    if (chartTemplate.instantiate) {\n        return chartTemplate.instantiate(templateContext);\n    }\n\n    if (flintType === 'Bar Chart' || flintType === 'Grouped Bar Chart' || flintType === 'Stacked Bar Chart') {\n        const detected = detectBandedAxisFromSemantics(sem, convertedData, { preferAxis: 'x' });\n        const declaration: LayoutDeclaration = {\n            axisFlags: detected ? { [detected.axis]: { banded: true } } : { x: { banded: true } },\n            resolvedTypes: detected?.resolvedTypes,\n        };\n        const baseSize = resolveBaseSize(input.chart_spec.baseSize, input.chart_spec.canvasSize);\n        const options = {\n            facetFixedPadding: { width: 50, height: 40 },\n            facetGap: 10,\n            targetBandAR: 10,\n            ...deriveStretchCaps(baseSize, input.chart_spec.canvasSize, {}),\n        };\n        const budgets = computeChannelBudgets(sem, declaration, convertedData, baseSize, options);\n        const overflowResult = filterOverflow(\n            sem,\n            declaration,\n            encodings,\n            convertedData,\n            budgets,\n            new Set(['bar']),\n        );\n        convertedData = overflowResult.filteredData;\n        overflowResult.truncations.forEach((truncation) => {\n            overflowOrder.set(truncation.field, truncation.keptValues as Cell[]);\n        });\n    }\n\n    const mapping = chartTemplate.typeMapping;\n\n    // ── Resolve roles (category / measure / series) from semantics ──────────\n    let catCh: string | undefined;\n    let measCh: string | undefined;\n    let seriesCh: string | undefined;\n    let orientation: 'vertical' | 'horizontal' = 'vertical';\n    let isXY = false;\n\n    // categorical series candidate (group preferred, else categorical color)\n    const seriesCand = encodings.group\n        ? 'group'\n        : encodings.color && !isMeasure('color')\n            ? 'color'\n            : undefined;\n    const seriesField0 = seriesCand;\n\n    if (mapping.noAxes) {\n        // pie/doughnut: color = slices (category), size/theta/y = value\n        catCh = encodings.color ? 'color' : encodings.x ? 'x' : undefined;\n        measCh = encodings.size ? 'size' : encodings.theta ? 'theta' : encodings.y ? 'y' : undefined;\n        seriesCh = undefined;\n    } else if (mapping.xy) {\n        catCh = 'x'; measCh = 'y'; isXY = true; seriesCh = seriesField0;\n    } else if (isMeasure('x') && !isMeasure('y')) {\n        catCh = 'y'; measCh = 'x'; orientation = 'horizontal'; seriesCh = seriesField0;\n    } else {\n        catCh = 'x'; measCh = 'y'; seriesCh = seriesField0;\n    }\n\n    const catField = catCh ? fieldOf(catCh) : undefined;\n    const measField = measCh ? fieldOf(measCh) : undefined;\n    const seriesField = seriesCh ? fieldOf(seriesCh) : undefined;\n    const dashField = fieldOf('strokeDash');\n    const orderField = fieldOf('order');\n    const sizeField = fieldOf('size');\n    const base = input.chart_spec.baseSize ?? { width: 480, height: 320 };\n    const bubbleSizes = sizeField\n        ? normalizedBubbleSizes(convertedData, sizeField, typeOf('size'), base.width, base.height)\n        : undefined;\n    const warnings: ChartWarning[] = [];\n\n    if (!catField || !measField) {\n        throw new Error(\n            `Excel backend could not resolve category/measure for \"${flintType}\" ` +\n            `(category=${catField}, measure=${measField}).`,\n        );\n    }\n\n    const numericXLine = flintType === 'Line Chart' && isMeasure('x') && isMeasure('y');\n    if (numericXLine) {\n        isXY = true;\n        catCh = 'x';\n        measCh = 'y';\n    }\n\n    // ── Stage 3: pivot long → wide matrix ───────────────────────────────────\n    const data: Array<Array<Cell>> = [];\n    let explicitSeries: ExcelNativeSeriesSpec[] | undefined;\n    let seriesFormats: ExcelNativeChartSpec['seriesFormats'];\n    if (isXY) {\n        const seriesKeys = seriesField ? distinct(convertedData, seriesField) : [measField];\n        const needsExplicitSeries = Boolean(seriesField || sizeField);\n        if (needsExplicitSeries) {\n            const columnsPerSeries = sizeField ? 3 : 2;\n            const groupedRows = seriesKeys.map((seriesKey) => {\n                const rows = convertedData.filter((row) => !seriesField || row[seriesField] === seriesKey);\n                if (!orderField) return rows;\n                return [...rows].sort((left, right) => {\n                    const leftValue = left[orderField];\n                    const rightValue = right[orderField];\n                    const leftNumber = Number(leftValue);\n                    const rightNumber = Number(rightValue);\n                    if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) return leftNumber - rightNumber;\n                    const leftTime = new Date(String(leftValue)).getTime();\n                    const rightTime = new Date(String(rightValue)).getTime();\n                    if (Number.isFinite(leftTime) && Number.isFinite(rightTime)) return leftTime - rightTime;\n                    return String(leftValue).localeCompare(String(rightValue), undefined, { numeric: true });\n                });\n            });\n            const rowCount = Math.max(0, ...groupedRows.map((rows) => rows.length));\n            explicitSeries = seriesKeys.map((seriesKey, index) => ({\n                name: String(seriesKey),\n                xColumn: index * columnsPerSeries,\n                yColumn: index * columnsPerSeries + 1,\n                rowCount: groupedRows[index].length,\n                bubbleSizeColumn: sizeField ? index * columnsPerSeries + 2 : undefined,\n            }));\n            data.push(seriesKeys.flatMap((seriesKey) => [\n                `${String(seriesKey)} ${catField}`,\n                `${String(seriesKey)} ${measField}`,\n                ...(sizeField ? [`${String(seriesKey)} ${sizeField}`] : []),\n            ]));\n            for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n                data.push(groupedRows.flatMap((rows) => {\n                    const row = rows[rowIndex];\n                    if (!row) return new Array(columnsPerSeries).fill(null);\n                    return [\n                        row[catField] as Cell,\n                        Number(row[measField]),\n                        ...(sizeField ? [bubbleSizes?.get(row[sizeField]) ?? 9] : []),\n                    ];\n                }));\n            }\n        } else {\n            data.push([catField, measField]);\n            const rows = orderField\n                ? [...convertedData].sort((left, right) => {\n                    const leftValue = left[orderField];\n                    const rightValue = right[orderField];\n                    const leftNumber = Number(leftValue);\n                    const rightNumber = Number(rightValue);\n                    if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) return leftNumber - rightNumber;\n                    const leftTime = new Date(String(leftValue)).getTime();\n                    const rightTime = new Date(String(rightValue)).getTime();\n                    if (Number.isFinite(leftTime) && Number.isFinite(rightTime)) return leftTime - rightTime;\n                    return String(leftValue).localeCompare(String(rightValue), undefined, { numeric: true });\n                })\n                : convertedData;\n            for (const r of rows) {\n                const x = r[catField];\n                const y = r[measField];\n                if (x == null || y == null) continue;\n                data.push([x as Cell, Number(y)]);\n            }\n        }\n    } else {\n        let categories = distinct(convertedData, catField);\n        const rankedCategories = overflowOrder.get(catField);\n        if (rankedCategories) categories = rankedCategories;\n        if (flintType === 'Line Chart' || flintType === 'Area Chart') {\n            if (typeOf(catCh!) === 'temporal') {\n                categories = [...categories].sort((a, b) => new Date(String(a)).getTime() - new Date(String(b)).getTime());\n            } else if (typeOf(catCh!) === 'quantitative') {\n                categories = [...categories].sort((a, b) => Number(a) - Number(b));\n            }\n        }\n        let seriesKeys = seriesField ? distinct(convertedData, seriesField) : [measField];\n        if (seriesField && (flintType === 'Stacked Bar Chart' || flintType === 'Bar Chart')) {\n            seriesKeys = [...seriesKeys].sort((a, b) => String(a).localeCompare(String(b), undefined, { numeric: true }));\n            if (orientation === 'vertical') seriesKeys.reverse();\n        }\n        const dashValues = dashField ? distinct(convertedData, dashField) : [];\n        const seriesDescriptors = dashField\n            ? convertedData.reduce<Array<{ key: string; label: string; seriesValue: Cell; dashValue: Cell }>>((output, row) => {\n                const seriesValue = (seriesField ? row[seriesField] : measField) as Cell;\n                const dashValue = row[dashField] as Cell;\n                const key = `${String(seriesValue)}\\u0001${String(dashValue)}`;\n                if (!output.some((descriptor) => descriptor.key === key)) {\n                    output.push({\n                        key,\n                        label: seriesField ? `${String(seriesValue)} — ${String(dashValue)}` : String(dashValue),\n                        seriesValue,\n                        dashValue,\n                    });\n                }\n                return output;\n            }, [])\n            : seriesKeys.map((seriesValue) => ({\n                key: String(seriesValue),\n                label: String(seriesValue),\n                seriesValue,\n                dashValue: null,\n            }));\n        const orderedSeries = Boolean(seriesField)\n            && typeOf(seriesCh!) === 'ordinal';\n        const numericSeriesValues = orderedSeries\n            ? seriesKeys.map(Number).filter(Number.isFinite)\n            : [];\n        const seriesMinimum = numericSeriesValues.length > 0 ? Math.min(...numericSeriesValues) : 0;\n        const seriesMaximum = numericSeriesValues.length > 0 ? Math.max(...numericSeriesValues) : 1;\n        const orderedSeriesColor = (value: Cell) => {\n            const numericValue = Number(value);\n            const t = Number.isFinite(numericValue) && seriesMaximum !== seriesMinimum\n                ? (numericValue - seriesMinimum) / (seriesMaximum - seriesMinimum)\n                : 0.5;\n            return interpolateColor('#D9E2F3', '#2F5597', t);\n        };\n        if (orderedSeries) {\n            seriesFormats = seriesDescriptors.map((descriptor) => ({\n                color: orderedSeriesColor(descriptor.seriesValue),\n            }));\n        }\n        if (dashField) {\n            seriesFormats = seriesDescriptors.map((descriptor) => ({\n                color: EXCEL_SERIES_COLORS[Math.max(0, seriesKeys.indexOf(descriptor.seriesValue)) % EXCEL_SERIES_COLORS.length],\n                lineStyle: dashValues.indexOf(descriptor.dashValue) === 0 ? 'Continuous' : 'Dash',\n            }));\n        }\n\n        // aggregate duplicates per (category × series) using the measure's default\n        const agg = sem[measCh!]?.aggregationDefault ?? 'sum';\n        const acc = new Map<string, { sum: number; count: number }>();\n        for (const r of convertedData) {\n            const cv = r[catField];\n            if (cv == null) continue;\n            const seriesValue = seriesField ? r[seriesField] : measField;\n            const sv = dashField\n                ? `${String(seriesValue)}\\u0001${String(r[dashField])}`\n                : seriesValue;\n            const num = Number(r[measField]);\n            if (!Number.isFinite(num)) continue;\n            const key = `${String(cv)}\\u0000${String(sv)}`;\n            const e = acc.get(key) ?? { sum: 0, count: 0 };\n            e.sum += num; e.count += 1; acc.set(key, e);\n        }\n        const valueAt = (cv: Cell, sv: Cell): Cell => {\n            const e = acc.get(`${String(cv)}\\u0000${String(sv)}`);\n            if (!e) return null;\n            return agg === 'average' ? e.sum / e.count : e.sum;\n        };\n\n        let seriesValues = seriesDescriptors.map((descriptor) => categories.map((category) => valueAt(category, descriptor.key)));\n        if (flintType === 'Line Chart' || flintType === 'Area Chart') {\n            seriesValues = seriesValues.map(interpolateMissing);\n        }\n        if (flintType === 'Area Chart' && typeOf(catCh!) === 'quantitative' && categories.length > 1) {\n            const sourceX = categories.map(Number);\n            const sampleCount = Math.min(97, Math.max(49, categories.length));\n            const minimum = sourceX[0];\n            const maximum = sourceX[sourceX.length - 1];\n            const targetX = Array.from(\n                { length: sampleCount },\n                (_value, index) => minimum + (index / (sampleCount - 1)) * (maximum - minimum),\n            );\n            seriesValues = seriesValues.map((values) => {\n                let right = 1;\n                return targetX.map((x) => {\n                    while (right < sourceX.length - 1 && sourceX[right] < x) right += 1;\n                    const left = Math.max(0, right - 1);\n                    const span = sourceX[right] - sourceX[left];\n                    const t = span === 0 ? 0 : (x - sourceX[left]) / span;\n                    const leftValue = Number(values[left]);\n                    const rightValue = Number(values[right]);\n                    if (!Number.isFinite(leftValue)) return Number.isFinite(rightValue) ? rightValue : null;\n                    if (!Number.isFinite(rightValue)) return leftValue;\n                    return leftValue + (rightValue - leftValue) * t;\n                });\n            });\n            const tickLabels = new Map(Array.from(\n                { length: 5 },\n                (_value, index) => [\n                    Math.round((index / 4) * (sampleCount - 1)),\n                    Number((minimum + (index / 4) * (maximum - minimum)).toPrecision(4)),\n                ] as const,\n            ));\n            categories = targetX.map((_value, index) => tickLabels.get(index) ?? '');\n        }\n        data.push([catField, ...seriesDescriptors.map((descriptor) => descriptor.label)]);\n        for (let categoryIndex = 0; categoryIndex < categories.length; categoryIndex += 1) {\n            data.push([\n                String(categories[categoryIndex]),\n                ...seriesValues.map((values) => values[categoryIndex]),\n            ]);\n        }\n    }\n\n    // ── Chart type + styling (native Excel) ─────────────────────────────────\n    let excelChartType = orientation === 'horizontal' && mapping.horizontal\n        ? mapping.horizontal\n        : mapping.vertical;\n    if (numericXLine) excelChartType = 'XYScatterLines';\n    if (flintType === 'Connected Scatter Plot') excelChartType = 'XYScatterLines';\n    if (flintType === 'Scatter Plot' && sizeField) excelChartType = 'Bubble';\n    if (flintType === 'Area Chart' && seriesField) excelChartType = 'AreaStacked';\n    if (flintType === 'Bar Chart' && seriesField) {\n        excelChartType = orientation === 'horizontal' ? 'BarStacked' : 'ColumnStacked';\n    }\n    const isBarFamily = /Column|Bar/.test(excelChartType);\n    const hasNumericAxes = /XYScatter|Bubble/.test(excelChartType);\n    const numberFormat = formatSpecToExcel(measCh ? sem[measCh]?.format : undefined);\n    const seriesBy: ExcelSeriesBy = 'Columns';\n\n    const spec: ExcelNativeChartSpec = {\n        schema: 'flint.excel.chart/v1',\n        kind: 'chart',\n        chartType: excelChartType,\n        title: `${measField} by ${catField}`,\n        seriesBy,\n        series: explicitSeries,\n        seriesFormats,\n        bubbleScale: flintType === 'Scatter Plot' && sizeField ? 20 : undefined,\n        doughnutHoleSize: flintType === 'Donut Chart'\n            ? Math.max(10, Math.min(90, Number(input.chart_spec.chartProperties?.innerRadius ?? 50)))\n            : undefined,\n        data,\n        width: base.width,\n        height: base.height,\n        warnings,\n        _flint: { flintType, catField, measField, seriesField, orientation, isXY },\n    };\n\n    if (!mapping.noAxes) {\n        const measureValues = convertedData\n            .map((row) => Number(row[measField]))\n            .filter(Number.isFinite);\n        const measureMinimum = measureValues.length > 0 ? Math.min(...measureValues) : undefined;\n        const measureMaximum = measureValues.length > 0 ? Math.max(...measureValues) : undefined;\n        const focusedLineMinimum = flintType === 'Line Chart' && measureMinimum !== undefined && measureMaximum !== undefined\n            ? Math.max(0, measureMinimum - (measureMaximum - measureMinimum) * 0.05)\n            : undefined;\n        const numericXScale = hasNumericAxes\n            ? focusedNumericAxis(convertedData.map((row) => Number(row[catField])))\n            : {};\n        const numericYScale = hasNumericAxes\n            ? focusedNumericAxis(measureValues)\n            : {};\n        spec.categoryAxis = {\n            title: catField,\n            labelFontSize: orientation === 'horizontal' && data.length > 25\n                ? Math.max(5, Math.min(10, ((base.height - 80) / (data.length - 1)) * 0.72))\n                : undefined,\n            tickLabelSpacing: orientation === 'vertical' && typeOf(catCh!) === 'temporal'\n                ? temporalLabelSpacing(data.length - 1, base.width)\n                : undefined,\n            reversePlotOrder: orientation === 'horizontal' && typeOf(catCh!) !== 'temporal',\n            ...numericXScale,\n        };\n        spec.valueAxis = {\n            title: measField,\n            numberFormat,\n            minimumScale: flintType === 'Area Chart' ? 0 : focusedLineMinimum,\n            ...numericYScale,\n        };\n    }\n    spec.legend = mapping.noAxes\n        ? { visible: true, position: 'Right' }\n        : seriesField || dashField\n            ? { visible: true, position: 'Bottom' }\n            : { visible: false };\n    if (isBarFamily) spec.gapWidth = 60;\n    if (flintType === 'Grouped Bar Chart') {\n        const seriesCount = Math.max(1, data[0].length - 1);\n        spec.gapWidth = Math.min(500, (excelChartType.startsWith('Column') ? 60 : 40) * seriesCount);\n        spec.overlap = 0;\n    }\n\n    return spec;\n}\n","import type { ExcelNativeChartSpec } from './types';\n\nexport const EXCEL_ARTIFACT_SCHEMA = 'flint.excel.chart/v1' as const;\n\nexport const SUPPORTED_EXCEL_CHART_TYPES = [\n    'Area',\n    'AreaStacked',\n    'BarClustered',\n    'BarStacked',\n    'BoxWhisker',\n    'Bubble',\n    'ColumnClustered',\n    'ColumnStacked',\n    'Doughnut',\n    'Funnel',\n    'Line',\n    'Pie',\n    'RadarMarkers',\n    'StockOHLC',\n    'Sunburst',\n    'Treemap',\n    'Waterfall',\n    'XYScatter',\n    'XYScatterLines',\n] as const;\n\nconst supportedChartTypes = new Set<string>(SUPPORTED_EXCEL_CHART_TYPES);\n\nexport interface PreparedExcelArtifact {\n    spec: ExcelNativeChartSpec;\n    data: Array<Array<string | number | null>>;\n    rows: number;\n    columns: number;\n    rangeA1: string;\n    chartType: string;\n    numericAxis: boolean;\n    dateAxis: boolean;\n    hasAxes: boolean;\n    isBar: boolean;\n    isLine: boolean;\n    seriesCount: number;\n}\n\nexport function excelColumnLetter(index: number): string {\n    if (!Number.isInteger(index) || index < 0) {\n        throw new Error('Column index must be a non-negative integer.');\n    }\n    let result = '';\n    let remaining = index + 1;\n    while (remaining > 0) {\n        const digit = (remaining - 1) % 26;\n        result = String.fromCharCode(65 + digit) + result;\n        remaining = Math.floor((remaining - 1) / 26);\n    }\n    return result;\n}\n\nexport function prepareExcelArtifact(value: unknown): PreparedExcelArtifact {\n    if (!value || typeof value !== 'object') {\n        throw new Error('Excel artifact must be an object.');\n    }\n    const spec = value as Partial<ExcelNativeChartSpec>;\n    if (spec.schema !== EXCEL_ARTIFACT_SCHEMA || spec.kind !== 'chart') {\n        throw new Error(`Expected a ${EXCEL_ARTIFACT_SCHEMA} chart artifact.`);\n    }\n    const chartType = spec.chartType;\n    if (typeof chartType !== 'string' || !supportedChartTypes.has(chartType)) {\n        throw new Error(`Unsupported Excel chart type: ${String(spec.chartType)}.`);\n    }\n    if (spec.seriesBy !== 'Columns' && spec.seriesBy !== 'Rows') {\n        throw new Error('Excel artifact seriesBy must be Columns or Rows.');\n    }\n    if (!Array.isArray(spec.data) || spec.data.length < 2 || spec.data.some((row) => !Array.isArray(row))) {\n        throw new Error('Excel artifact data must contain a header and at least one data row.');\n    }\n    const columns = Math.max(...spec.data.map((row) => row.length));\n    if (columns < 2) {\n        throw new Error('Excel artifact data must contain at least two columns.');\n    }\n    const rows = spec.data.length;\n    const data = spec.data.map((row) => {\n        const padded = row.slice();\n        while (padded.length < columns) padded.push(null);\n        return padded;\n    });\n    const seriesCount = /Treemap|Sunburst/i.test(chartType)\n        ? 1\n        : spec.series?.length ?? (spec.seriesBy === 'Rows' ? rows - 1 : columns - 1);\n\n    return {\n        spec: spec as ExcelNativeChartSpec,\n        data,\n        rows,\n        columns,\n        rangeA1: `A1:${excelColumnLetter(columns - 1)}${rows}`,\n        chartType,\n        numericAxis: /XYScatter|Bubble/i.test(chartType),\n        dateAxis: /Stock/i.test(chartType),\n        hasAxes: !/Pie|Doughnut|Treemap|Sunburst|Funnel/i.test(chartType),\n        isBar: /Bar|Column/i.test(chartType),\n        isLine: /Line/i.test(chartType),\n        seriesCount,\n    };\n}\n","import { prepareExcelArtifact } from './artifact';\nimport type { ExcelAxisSpec, ExcelNativeChartSpec } from './types';\n\nexport interface OfficeJsCodegenOptions {\n    scale?: number;\n    cleanWorksheet?: boolean;\n    functionName?: string;\n}\n\nexport interface GeneratedOfficeJs {\n    code: string;\n    meta: {\n        schema: ExcelNativeChartSpec['schema'];\n        rangeA1: string;\n        chartType: string;\n        rows: number;\n        columns: number;\n    };\n}\n\nfunction axisCode(axisName: 'categoryAxis' | 'valueAxis', axis: ExcelAxisSpec): string[] {\n    const target = `chart.axes.${axisName}`;\n    const lines: string[] = [];\n    if (axis.title) {\n        lines.push(`  ${target}.title.text = ${JSON.stringify(axis.title)};`);\n        lines.push(`  ${target}.title.visible = true;`);\n    }\n    if (axis.numberFormat) lines.push(`  ${target}.numberFormat = ${JSON.stringify(axis.numberFormat)};`);\n    if (axis.labelFontSize !== undefined) lines.push(`  ${target}.format.font.size = ${axis.labelFontSize};`);\n    if (axis.tickLabelSpacing !== undefined) lines.push(`  ${target}.tickLabelSpacing = ${axis.tickLabelSpacing};`);\n    if (axis.reversePlotOrder !== undefined) lines.push(`  ${target}.reversePlotOrder = ${axis.reversePlotOrder};`);\n    if (axis.minimumScale !== undefined) lines.push(`  ${target}.minimum = ${axis.minimumScale};`);\n    if (axis.maximumScale !== undefined) lines.push(`  ${target}.maximum = ${axis.maximumScale};`);\n    if (axis.majorUnit !== undefined) lines.push(`  ${target}.majorUnit = ${axis.majorUnit};`);\n    return lines;\n}\n\nfunction positiveScale(value: number | undefined): number {\n    const scale = value ?? 3;\n    if (!Number.isFinite(scale) || scale <= 0) throw new Error('Office.js image scale must be positive.');\n    return scale;\n}\n\nexport function generateOfficeJs(value: unknown, options: OfficeJsCodegenOptions = {}): GeneratedOfficeJs {\n    const prepared = prepareExcelArtifact(value);\n    const { spec } = prepared;\n    const functionName = options.functionName ?? 'renderFlintChart';\n    if (!/^[$A-Z_a-z][$\\w]*$/.test(functionName)) {\n        throw new Error('Office.js functionName must be a valid JavaScript identifier.');\n    }\n    const width = spec.width ?? 400;\n    const height = spec.height ?? 300;\n    const scale = positiveScale(options.scale);\n    const imageWidth = Math.round(width * (96 / 72) * scale);\n    const imageHeight = Math.round(height * (96 / 72) * scale);\n    const lines = [\n        `async function ${functionName}(context) {`,\n        '  const sheet = context.workbook.worksheets.getActiveWorksheet();',\n    ];\n\n    if (options.cleanWorksheet) {\n        lines.push(\n            \"  sheet.charts.load('items/name');\",\n            '  const previousRange = sheet.getUsedRangeOrNullObject();',\n            '  await context.sync();',\n            '  sheet.charts.items.forEach((existingChart) => existingChart.delete());',\n            '  if (!previousRange.isNullObject) previousRange.clear();',\n        );\n    }\n\n    lines.push(\n        `  const values = ${JSON.stringify(prepared.data)};`,\n        `  const dataRange = sheet.getRange(${JSON.stringify(prepared.rangeA1)});`,\n        '  dataRange.numberFormat = values.map((row, rowIndex) =>',\n        `    row.map((_cell, columnIndex) => rowIndex === 0 ? '@' : columnIndex === 0 && ${prepared.dateAxis} ? 'yyyy-mm-dd' : columnIndex === 0 && ${!prepared.numericAxis} ? '@' : 'General'),`,\n        '  );',\n        '  dataRange.values = values;',\n        `  const chart = sheet.charts.add(${JSON.stringify(prepared.chartType)}, dataRange, ${JSON.stringify(spec.seriesBy)});`,\n    );\n\n    if (spec.series?.length) {\n        lines.push(\"  chart.series.load('items');\", '  await context.sync();');\n        lines.push(`  if (chart.series.items.length < ${spec.series.length}) throw new Error('Excel inferred too few series.');`);\n        spec.series.forEach((binding, index) => {\n            lines.push(\n                `  chart.series.items[${index}].name = ${JSON.stringify(binding.name)};`,\n                `  chart.series.items[${index}].setXAxisValues(sheet.getRangeByIndexes(1, ${binding.xColumn}, ${binding.rowCount}, 1));`,\n                `  chart.series.items[${index}].setValues(sheet.getRangeByIndexes(1, ${binding.yColumn}, ${binding.rowCount}, 1));`,\n            );\n            if (binding.bubbleSizeColumn !== undefined) {\n                lines.push(`  chart.series.items[${index}].setBubbleSizes(sheet.getRangeByIndexes(1, ${binding.bubbleSizeColumn}, ${binding.rowCount}, 1));`);\n            }\n        });\n        lines.push(\n            `  for (let index = chart.series.items.length - 1; index >= ${spec.series.length}; index -= 1) {`,\n            '    chart.series.getItemAt(index).delete();',\n            '    await context.sync();',\n            '  }',\n        );\n    }\n\n    lines.push(`  chart.width = ${width};`, `  chart.height = ${height};`);\n    if (spec.title) {\n        lines.push(`  chart.title.text = ${JSON.stringify(spec.title)};`, '  chart.title.visible = true;');\n    }\n    if (spec.legend) {\n        lines.push(`  chart.legend.visible = ${spec.legend.visible};`);\n        if (spec.legend.visible && spec.legend.position) {\n            lines.push(`  chart.legend.position = ${JSON.stringify(spec.legend.position)};`);\n        }\n    }\n    if (spec.dataLabels) {\n        lines.push(`  chart.dataLabels.visible = ${spec.dataLabels.visible};`);\n        if (spec.dataLabels.position) lines.push(`  chart.dataLabels.position = ${JSON.stringify(spec.dataLabels.position)};`);\n        if (spec.dataLabels.numberFormat) lines.push(`  chart.dataLabels.numberFormat = ${JSON.stringify(spec.dataLabels.numberFormat)};`);\n        if (spec.dataLabels.fontColor) lines.push(`  chart.dataLabels.format.font.color = ${JSON.stringify(spec.dataLabels.fontColor)};`);\n        if (spec.dataLabels.fontSize !== undefined) lines.push(`  chart.dataLabels.format.font.size = ${spec.dataLabels.fontSize};`);\n    }\n    if (prepared.hasAxes) {\n        if (spec.categoryAxis) lines.push(...axisCode('categoryAxis', spec.categoryAxis));\n        if (spec.valueAxis) lines.push(...axisCode('valueAxis', spec.valueAxis));\n    }\n\n    lines.push(`  const seriesFormats = ${JSON.stringify(spec.seriesFormats ?? [])};`);\n    lines.push(`  for (let index = 0; index < ${prepared.seriesCount}; index += 1) {`, '    const series = chart.series.getItemAt(index);', '    const format = seriesFormats[index];');\n    if (prepared.isBar && spec.gapWidth !== undefined) lines.push(`    series.gapWidth = ${spec.gapWidth};`);\n    if (prepared.isBar && spec.overlap !== undefined) lines.push(`    series.overlap = ${spec.overlap};`);\n    if (/Bubble/i.test(prepared.chartType) && spec.bubbleScale !== undefined) lines.push(`    series.bubbleScale = ${spec.bubbleScale};`);\n    if (/Doughnut/i.test(prepared.chartType) && spec.doughnutHoleSize !== undefined) lines.push(`    series.doughnutHoleSize = ${spec.doughnutHoleSize};`);\n    if (/BoxWhisker/i.test(prepared.chartType) && spec.boxWhiskerOptions) lines.push(`    series.boxwhiskerOptions.set(${JSON.stringify(spec.boxWhiskerOptions)});`);\n    if (/Waterfall/i.test(prepared.chartType) && spec.showConnectorLines !== undefined) lines.push(`    series.showConnectorLines = ${spec.showConnectorLines};`);\n    lines.push('    if (format?.color) {');\n    if (!prepared.isLine) lines.push('      series.format.fill.setSolidColor(format.color);');\n    lines.push('      series.format.line.color = format.color;', '    }', '    if (format?.lineStyle) series.format.line.lineStyle = format.lineStyle;', '  }');\n    lines.push(\n        `  const image = chart.getImage(${imageWidth}, ${imageHeight}, Excel.ImageFittingMode.fit);`,\n        '  await context.sync();',\n        '  return image.value;',\n        '}',\n        '',\n        'async function main() {',\n        `  return Excel.run(${functionName});`,\n        '}',\n        '',\n    );\n\n    return {\n        code: lines.join('\\n'),\n        meta: {\n            schema: spec.schema,\n            rangeA1: prepared.rangeA1,\n            chartType: prepared.chartType,\n            rows: prepared.rows,\n            columns: prepared.columns,\n        },\n    };\n}\n","import { prepareExcelArtifact, type PreparedExcelArtifact } from './artifact';\n\nexport interface OfficeJsExcelApi {\n    run<T>(callback: (context: any) => Promise<T>): Promise<T>;\n    ImageFittingMode: { fit: any };\n}\n\nexport interface ExcelRenderOptions {\n    scale?: number;\n    cleanWorksheet?: boolean;\n    inspectNativeChart?: boolean;\n}\n\nexport interface ExcelRenderResult {\n    pngBase64: string;\n    inspection: unknown | null;\n}\n\nfunction applyChartFormat(chart: any, prepared: PreparedExcelArtifact): void {\n    const { spec } = prepared;\n    if (spec.legend) {\n        chart.legend.visible = spec.legend.visible;\n        if (spec.legend.visible && spec.legend.position) chart.legend.position = spec.legend.position;\n    }\n    if (prepared.hasAxes) {\n        const axes = [\n            [chart.axes.categoryAxis, spec.categoryAxis],\n            [chart.axes.valueAxis, spec.valueAxis],\n        ] as const;\n        for (const [axis, format] of axes) {\n            if (!format) continue;\n            if (format.title) {\n                axis.title.text = format.title;\n                axis.title.visible = true;\n            }\n            if (format.numberFormat) axis.numberFormat = format.numberFormat;\n            if (format.labelFontSize !== undefined) axis.format.font.size = format.labelFontSize;\n            if (format.tickLabelSpacing !== undefined) axis.tickLabelSpacing = format.tickLabelSpacing;\n            if (format.reversePlotOrder !== undefined) axis.reversePlotOrder = format.reversePlotOrder;\n            if (format.minimumScale !== undefined) axis.minimum = format.minimumScale;\n            if (format.maximumScale !== undefined) axis.maximum = format.maximumScale;\n            if (format.majorUnit !== undefined) axis.majorUnit = format.majorUnit;\n        }\n    }\n    if (spec.dataLabels) {\n        chart.dataLabels.visible = spec.dataLabels.visible;\n        if (spec.dataLabels.position) chart.dataLabels.position = spec.dataLabels.position;\n        if (spec.dataLabels.numberFormat) chart.dataLabels.numberFormat = spec.dataLabels.numberFormat;\n        if (spec.dataLabels.fontColor) chart.dataLabels.format.font.color = spec.dataLabels.fontColor;\n        if (spec.dataLabels.fontSize !== undefined) chart.dataLabels.format.font.size = spec.dataLabels.fontSize;\n    }\n    for (let index = 0; index < prepared.seriesCount; index += 1) {\n        const series = chart.series.getItemAt(index);\n        const format = spec.seriesFormats?.[index];\n        if (format?.color) {\n            if (!prepared.isLine) series.format.fill.setSolidColor(format.color);\n            series.format.line.color = format.color;\n        }\n        if (format?.lineStyle) series.format.line.lineStyle = format.lineStyle;\n        if (prepared.isBar && spec.gapWidth !== undefined) series.gapWidth = spec.gapWidth;\n        if (prepared.isBar && spec.overlap !== undefined) series.overlap = spec.overlap;\n        if (/Bubble/i.test(prepared.chartType) && spec.bubbleScale !== undefined) series.bubbleScale = spec.bubbleScale;\n        if (/Doughnut/i.test(prepared.chartType) && spec.doughnutHoleSize !== undefined) series.doughnutHoleSize = spec.doughnutHoleSize;\n        if (/BoxWhisker/i.test(prepared.chartType) && spec.boxWhiskerOptions) series.boxwhiskerOptions.set(spec.boxWhiskerOptions);\n        if (/Waterfall/i.test(prepared.chartType) && spec.showConnectorLines !== undefined) series.showConnectorLines = spec.showConnectorLines;\n    }\n}\n\nasync function inspectChart(context: any, sheet: any, dataRange: any, chart: any): Promise<unknown> {\n    try {\n        dataRange.load('address,values,numberFormat');\n        const usedRange = sheet.getUsedRangeOrNullObject();\n        usedRange.load('isNullObject,address,values');\n        chart.load('name,chartType');\n        chart.series.load('items/name,items/chartType,items/axisGroup,items/formula');\n        await context.sync();\n        for (const series of chart.series.items) {\n            series.binOptions.load('type,count,width,allowOverflow,overflowValue,allowUnderflow,underflowValue');\n        }\n        const primaryCategoryAxis = chart.axes.getItemOrNullObject('Category', 'Primary');\n        const primaryValueAxis = chart.axes.getItemOrNullObject('Value', 'Primary');\n        const secondaryValueAxis = chart.axes.getItemOrNullObject('Value', 'Secondary');\n        for (const axis of [primaryCategoryAxis, primaryValueAxis, secondaryValueAxis]) {\n            axis.load('isNullObject,axisType,axisGroup,visible,minimum,maximum,numberFormat');\n            axis.title.load('text,visible');\n        }\n        await context.sync();\n        const describeAxis = (axis: any) => axis.isNullObject ? null : { ...axis.toJSON(), title: axis.title.toJSON() };\n        return {\n            sourceRange: {\n                address: dataRange.address,\n                values: dataRange.values,\n                numberFormat: dataRange.numberFormat,\n            },\n            usedRange: usedRange.isNullObject ? null : {\n                address: usedRange.address,\n                values: usedRange.values,\n            },\n            chart: {\n                name: chart.name,\n                chartType: chart.chartType,\n                series: chart.series.items.map((series: any) => ({\n                    ...series.toJSON(),\n                    binOptions: series.binOptions.toJSON(),\n                })),\n                axes: {\n                    primaryCategory: describeAxis(primaryCategoryAxis),\n                    primaryValue: describeAxis(primaryValueAxis),\n                    secondaryValue: describeAxis(secondaryValueAxis),\n                },\n            },\n        };\n    } catch (error) {\n        return { error: error instanceof Error ? error.message : String(error) };\n    }\n}\n\nfunction imageScale(value: number | undefined): number {\n    const scale = value ?? 3;\n    if (!Number.isFinite(scale) || scale <= 0) throw new Error('Office.js image scale must be positive.');\n    return scale;\n}\n\nexport async function renderExcelChart(\n    excelApi: OfficeJsExcelApi,\n    value: unknown,\n    options: ExcelRenderOptions = {},\n): Promise<ExcelRenderResult> {\n    const prepared = prepareExcelArtifact(value);\n    const { spec } = prepared;\n    const scale = imageScale(options.scale);\n    return excelApi.run(async (context) => {\n        const sheet = context.workbook.worksheets.getActiveWorksheet();\n        if (options.cleanWorksheet !== false) {\n            sheet.charts.load('items/name');\n            const previousRange = sheet.getUsedRangeOrNullObject();\n            await context.sync();\n            sheet.charts.items.forEach((existingChart: any) => existingChart.delete());\n            if (!previousRange.isNullObject) previousRange.clear();\n        }\n\n        const dataRange = sheet.getRange(prepared.rangeA1);\n        dataRange.numberFormat = prepared.data.map((row, rowIndex) => row.map((_cell, columnIndex) =>\n            rowIndex === 0\n                ? '@'\n                : columnIndex === 0 && prepared.dateAxis\n                    ? 'yyyy-mm-dd'\n                    : columnIndex === 0 && !prepared.numericAxis ? '@' : 'General',\n        ));\n        dataRange.values = prepared.data;\n        const chart = sheet.charts.add(prepared.chartType, dataRange, spec.seriesBy);\n\n        if (spec.series?.length) {\n            chart.series.load('items');\n            await context.sync();\n            if (chart.series.items.length < spec.series.length) {\n                throw new Error(`Excel inferred ${chart.series.items.length} series; ${spec.series.length} required.`);\n            }\n            for (const [index, binding] of spec.series.entries()) {\n                const series = chart.series.items[index];\n                series.name = binding.name;\n                series.setXAxisValues(sheet.getRangeByIndexes(1, binding.xColumn, binding.rowCount, 1));\n                series.setValues(sheet.getRangeByIndexes(1, binding.yColumn, binding.rowCount, 1));\n                if (binding.bubbleSizeColumn !== undefined) {\n                    series.setBubbleSizes(sheet.getRangeByIndexes(1, binding.bubbleSizeColumn, binding.rowCount, 1));\n                }\n            }\n            for (let index = chart.series.items.length - 1; index >= spec.series.length; index -= 1) {\n                chart.series.getItemAt(index).delete();\n                await context.sync();\n            }\n        }\n\n        const width = spec.width ?? 400;\n        const height = spec.height ?? 300;\n        chart.width = width;\n        chart.height = height;\n        if (spec.title) {\n            chart.title.text = spec.title;\n            chart.title.visible = true;\n        }\n        applyChartFormat(chart, prepared);\n        await context.sync();\n        const image = chart.getImage(\n            Math.round(width * (96 / 72) * scale),\n            Math.round(height * (96 / 72) * scale),\n            excelApi.ImageFittingMode.fit,\n        );\n        await context.sync();\n        const inspection = options.inspectNativeChart\n            ? await inspectChart(context, sheet, dataRange, chart)\n            : null;\n        return { pngBase64: image.value, inspection };\n    });\n}\n"]}