@koda-sl/baker-cli 0.549.0 → 0.551.0-dev.ad2740332
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -1
- package/dist/account-IG3U6UXZ.js +82 -0
- package/dist/account-JCQYOGJD.js +82 -0
- package/dist/account-reads-LOCJMS35.js +219 -0
- package/dist/account-users-AZPQPHD3.js +64 -0
- package/dist/account-writes-BSSKSTZ2.js +68 -0
- package/dist/accounts-2PZV6VRS.js +80 -0
- package/dist/accounts-5I6USVT7.js +701 -0
- package/dist/actions-TSNXITQM.js +55 -0
- package/dist/activecampaign-2RKR6P74.js +938 -0
- package/dist/ad-group-writes-KMB3OMJG.js +172 -0
- package/dist/ad-groups-E67CNQS4.js +70 -0
- package/dist/ad-writes-FNMKNFUN.js +176 -0
- package/dist/add-ENUFKN5V.js +305 -0
- package/dist/add-SRHNKSJT.js +107 -0
- package/dist/ads-4LASBP4G.js +79 -0
- package/dist/ads-X33452HM.js +48 -0
- package/dist/advertisers-XO5EJXR5.js +123 -0
- package/dist/analytics-AZTZVHVA.js +447 -0
- package/dist/analytics-ED3NBGJJ.js +2437 -0
- package/dist/animate-OWXAT2RK.js +480 -0
- package/dist/assign-SIXEBHRW.js +80 -0
- package/dist/audience-size-ACNA4JIX.js +76 -0
- package/dist/audiences-3R574STZ.js +280 -0
- package/dist/audit-K5BEYW7G.js +154 -0
- package/dist/autocomplete-XIYI56SU.js +114 -0
- package/dist/avatars-C5CUPLIV.js +38 -0
- package/dist/bid-pricing-2UF6O2K6.js +103 -0
- package/dist/brand-ATWMTJFS.js +22 -0
- package/dist/brief-A65JXAER.js +543 -0
- package/dist/campaign-groups-F5C7C7NG.js +99 -0
- package/dist/campaign-writes-TNW7KKQQ.js +168 -0
- package/dist/campaign-writes-Z2J24SUZ.js +176 -0
- package/dist/campaigns-43OS6EUG.js +78 -0
- package/dist/campaigns-TQZXAMWE.js +111 -0
- package/dist/campaigns-XTNWM3VV.js +113 -0
- package/dist/canvas-UGO5IHCA.js +46 -0
- package/dist/capabilities-XHPLFYH2.js +147 -0
- package/dist/catalog-7LINLVVY.js +66 -0
- package/dist/catalogs-IR22RGZD.js +130 -0
- package/dist/changes-JAGWBHQC.js +143 -0
- package/dist/chatgpt-NE2RBMFK.js +47 -0
- package/dist/chats-QFZ4DGI7.js +449 -0
- package/dist/check-AEMZGF5G.js +107 -0
- package/dist/chunk-34JTMTPJ.js +224 -0
- package/dist/chunk-3C42N42Q.js +297 -0
- package/dist/chunk-3EUITH4J.js +638 -0
- package/dist/chunk-4IRJ5JXA.js +46 -0
- package/dist/chunk-4QGNRCSE.js +930 -0
- package/dist/chunk-4XFP43NH.js +142 -0
- package/dist/chunk-5EHSDRMJ.js +377 -0
- package/dist/chunk-5IFFPSEN.js +225 -0
- package/dist/chunk-64ALJ6TJ.js +274 -0
- package/dist/chunk-6KGMWAUL.js +494 -0
- package/dist/chunk-6OIKNJ7G.js +26 -0
- package/dist/chunk-6ZUGN27V.js +103 -0
- package/dist/chunk-7MWELLCN.js +51 -0
- package/dist/chunk-7UFV6H7J.js +167 -0
- package/dist/chunk-B3CDNANO.js +843 -0
- package/dist/chunk-B3LSWNUR.js +392 -0
- package/dist/chunk-BIHU5GCE.js +19 -0
- package/dist/chunk-BNI5DAB7.js +783 -0
- package/dist/chunk-CISE4DOX.js +89 -0
- package/dist/chunk-CVWYS7SE.js +191 -0
- package/dist/chunk-CXRS5YLB.js +150 -0
- package/dist/chunk-E5H7JIWB.js +3510 -0
- package/dist/chunk-EI6R7GKQ.js +275 -0
- package/dist/chunk-F3CZFUXZ.js +3187 -0
- package/dist/chunk-F3CZFUXZ.js.map +1 -0
- package/dist/chunk-F743MUNY.js +344 -0
- package/dist/chunk-FEVA2MNA.js +438 -0
- package/dist/chunk-FJXSVDWW.js +203 -0
- package/dist/chunk-G6J6AWTE.js +5471 -0
- package/dist/chunk-GCZK4BMB.js +5368 -0
- package/dist/chunk-GKIYKOJW.js +156 -0
- package/dist/chunk-GKMDBLTQ.js +7852 -0
- package/dist/chunk-GKMDBLTQ.js.map +1 -0
- package/dist/chunk-H4CLWLYF.js +4269 -0
- package/dist/chunk-H4CLWLYF.js.map +1 -0
- package/dist/chunk-H4OVNGUK.js +91 -0
- package/dist/chunk-HWOOMK5A.js +66 -0
- package/dist/chunk-IABSARSS.js +334 -0
- package/dist/chunk-IAOKMWUF.js +910 -0
- package/dist/chunk-ICEYCLRU.js +679 -0
- package/dist/chunk-JBNT444M.js +285 -0
- package/dist/chunk-K3HZVRBJ.js +8954 -0
- package/dist/chunk-KCZY5Y4E.js +61 -0
- package/dist/chunk-KTO2Y3DI.js +1646 -0
- package/dist/chunk-L7AJMZ6Z.js +24026 -0
- package/dist/chunk-L7AJMZ6Z.js.map +1 -0
- package/dist/chunk-LDFM37DM.js +148 -0
- package/dist/chunk-LHC6OHQ6.js +857 -0
- package/dist/chunk-LMSV7NQY.js +455 -0
- package/dist/chunk-LPDHNMOY.js +57 -0
- package/dist/chunk-METHLFNZ.js +63 -0
- package/dist/chunk-MI3HAKXY.js +170 -0
- package/dist/chunk-P6FMQHJJ.js +131 -0
- package/dist/chunk-PT73IEI6.js +479 -0
- package/dist/chunk-Q6LCL67T.js +1518 -0
- package/dist/chunk-RFGO4DHJ.js +2209 -0
- package/dist/chunk-RMTM22JO.js +685 -0
- package/dist/chunk-RQOSSYVH.js +718 -0
- package/dist/chunk-RQOSSYVH.js.map +1 -0
- package/dist/chunk-S2L2A2ZN.js +430 -0
- package/dist/chunk-SA3P64PQ.js +169 -0
- package/dist/chunk-SIKCVWM3.js +76 -0
- package/dist/chunk-SIOLRCLE.js +831 -0
- package/dist/chunk-TK6BXI5A.js +392 -0
- package/dist/chunk-V4UJERGL.js +64 -0
- package/dist/chunk-V6NFLQKX.js +207 -0
- package/dist/chunk-VISKG4IA.js +547 -0
- package/dist/chunk-WJ6KKTIU.js +23 -0
- package/dist/chunk-WPZTFSED.js +163 -0
- package/dist/chunk-X5UMVG4S.js +249 -0
- package/dist/chunk-X7ROPKZT.js +197 -0
- package/dist/chunk-XDJZH2JV.js +604 -0
- package/dist/chunk-XU6XQPNM.js +1919 -0
- package/dist/chunk-YKFGXS26.js +228 -0
- package/dist/chunk-YQB66YKJ.js +98 -0
- package/dist/chunk-YSTAPNQP.js +1902 -0
- package/dist/chunk-ZSLZOUGC.js +91 -0
- package/dist/claim-R6OG5IHM.js +200 -0
- package/dist/cli.js +34 -33
- package/dist/cli.js.map +1 -1
- package/dist/companies-M36P2XXN.js +198 -0
- package/dist/company-NQAS3QF6.js +308 -0
- package/dist/complete-FJHCHRYO.js +84 -0
- package/dist/connect-TEWDGN6C.js +45 -0
- package/dist/conversation-UC7PXJQ3.js +96 -0
- package/dist/conversion-report-R4KJI4VA.js +127 -0
- package/dist/conversion-upload-command-WCLWA27O.js +439 -0
- package/dist/conversion-writes-XIQEIDPS.js +122 -0
- package/dist/conversions-D7P3KVQK.js +140 -0
- package/dist/conversions-RMBQNW3T.js +78 -0
- package/dist/create-GMZHI4BK.js +62 -0
- package/dist/create-J2AICQFF.js +135 -0
- package/dist/create-RVR33UQM.js +239 -0
- package/dist/create-VXHOWOVI.js +210 -0
- package/dist/creatives-SLKM5XNE.js +223 -0
- package/dist/creatives-YMFRT6SE.js +58 -0
- package/dist/credentials-T3IID6QG.js +290 -0
- package/dist/critique-2Y53EQ3S.js +1451 -0
- package/dist/critique-SMLSUHY2.js +232 -0
- package/dist/crm-E35C36E3.js +323 -0
- package/dist/crm-TPV4H4KN.js +227 -0
- package/dist/currency-BY647ZB7.js +88 -0
- package/dist/customers-PH376T52.js +65 -0
- package/dist/delete-4MNN3QXP.js +67 -0
- package/dist/delete-7PEW3V6J.js +69 -0
- package/dist/delete-TRONZNM2.js +57 -0
- package/dist/demographics-EZXWOSZE.js +141 -0
- package/dist/discard-PHO5BKEZ.js +69 -0
- package/dist/discover-TAJUFO5R.js +172 -0
- package/dist/domain-7GNF7QHV.js +101 -0
- package/dist/download-A4EYH6VD.js +172 -0
- package/dist/draft-NQG5RBSF.js +220 -0
- package/dist/draft-PA3L7VG6.js +342 -0
- package/dist/draft-QQWTEXVT.js +313 -0
- package/dist/draft-RGSDXFFT.js +408 -0
- package/dist/draft-SKEGKHIK.js +288 -0
- package/dist/engine/index.js +8 -8
- package/dist/experiments-DEUWFSDQ.js +236 -0
- package/dist/facets-KWT2NAGR.js +117 -0
- package/dist/feedback-A56L3VWN.js +115 -0
- package/dist/feedback-O3BVHXJA.js +136 -0
- package/dist/feedback-O3BVHXJA.js.map +1 -0
- package/dist/feedback-record-FE4P5MKS.js +269 -0
- package/dist/fetch-M5U4E5IE.js +204 -0
- package/dist/fit-AYFRRDAN.js +65 -0
- package/dist/flows-QKR7JW6H.js +250 -0
- package/dist/fonts-RUHNGL7R.js +39 -0
- package/dist/forecast-V7IPL6EC.js +121 -0
- package/dist/forecast-VOND3WVO.js +169 -0
- package/dist/funnel-WNVS53CO.js +397 -0
- package/dist/generate-SW5KLHXG.js +263 -0
- package/dist/get-AJNPJIX6.js +59 -0
- package/dist/get-ZLRSDJM6.js +82 -0
- package/dist/google-VYARAUQH.js +3270 -0
- package/dist/google-ads-3PIHLIIF.js +198 -0
- package/dist/history-34E26WGP.js +153 -0
- package/dist/history-7DF5HFJT.js +69 -0
- package/dist/history-LWAKFSHW.js +102 -0
- package/dist/hubspot-HH7KVQU5.js +782 -0
- package/dist/ideas-VFZXVUFZ.js +45 -0
- package/dist/images-LB4E2F5I.js +92 -0
- package/dist/ingest-LRUKF3EK.js +27 -0
- package/dist/ingest-VZ77AODJ.js +123 -0
- package/dist/insights-YVV5MHPQ.js +132 -0
- package/dist/inspect-X6XU4CXL.js +192 -0
- package/dist/intent-GIAQDMHF.js +95 -0
- package/dist/keyword-gap-NZF75XGF.js +130 -0
- package/dist/keyword-metrics-P546E6KW.js +200 -0
- package/dist/keywords-for-site-AEFJ5BTU.js +131 -0
- package/dist/landing-RKO3LUST.js +28 -0
- package/dist/languages-GGNN7FEK.js +40 -0
- package/dist/leads-OVYF2EKX.js +115 -0
- package/dist/learn-UWJ24ZD5.js +207 -0
- package/dist/line-item-writes-46K4NKPJ.js +211 -0
- package/dist/line-items-YRSGOQFS.js +107 -0
- package/dist/link-XXRDZQFM.js +67 -0
- package/dist/linkedin-W4OWO6QA.js +1330 -0
- package/dist/linkedin-person-SQTWLIN5.js +139 -0
- package/dist/list-E6WPSAQK.js +154 -0
- package/dist/list-S34STWB3.js +306 -0
- package/dist/list-XERZMEWU.js +67 -0
- package/dist/locations-7RYEWKJO.js +69 -0
- package/dist/locations-BU4ZGWAS.js +40 -0
- package/dist/log-CDN4H2JY.js +95 -0
- package/dist/make-JE7V2RWR.js +1367 -0
- package/dist/map-SPSJ532D.js +436 -0
- package/dist/mcp-PBPHIS4Q.js +729 -0
- package/dist/media-sources-MZL4XML4.js +35 -0
- package/dist/members-RDNSONMW.js +47 -0
- package/dist/metrics-Z75Q2FHP.js +152 -0
- package/dist/models-X2IXXAD6.js +155 -0
- package/dist/normalize-4KL73UBE.js +144 -0
- package/dist/options-7MN5WH3J.js +125 -0
- package/dist/organization-NJT4G355.js +949 -0
- package/dist/performance-PG5T4D7M.js +27 -0
- package/dist/performance-SB2KLMTO.js +5565 -0
- package/dist/pixels-DBSPNHIE.js +62 -0
- package/dist/promoted-tweet-writes-PCWFF2EG.js +183 -0
- package/dist/promoted-tweets-ZSXREC4V.js +119 -0
- package/dist/publish-FIYZNQYO.js +344 -0
- package/dist/query-NMQKS4MY.js +62 -0
- package/dist/reddit-7WRZ5B3I.js +29 -0
- package/dist/refresh-IKHSUY3E.js +97 -0
- package/dist/release-JCKOGRTY.js +63 -0
- package/dist/relevant-pages-JRIDJL4L.js +99 -0
- package/dist/remove-KE63VJ3M.js +53 -0
- package/dist/reopen-4YSAVTOS.js +66 -0
- package/dist/rerun-K5SQ6GAQ.js +96 -0
- package/dist/research-OFHOHRFD.js +75 -0
- package/dist/research-ORXD6AV4.js +265 -0
- package/dist/reset-4CLSOD77.js +57 -0
- package/dist/reset-BN4FDUZB.js +57 -0
- package/dist/resolve-F6QVMQGX.js +124 -0
- package/dist/retry-JGAJF6CN.js +65 -0
- package/dist/retry-NJUIX2QT.js +63 -0
- package/dist/revenue-BYGHXTYJ.js +91 -0
- package/dist/rules-MWTPVJTK.js +99 -0
- package/dist/rules-add-3MJRAYXB.js +465 -0
- package/dist/run-CXD7RKYN.js +71 -0
- package/dist/run-NDJSLZNE.js +69 -0
- package/dist/scaffold-ad-2N7H7ACP.js +1513 -0
- package/dist/scaffold-static-ad-R7T766AD.js +1011 -0
- package/dist/scaffold-video-22HVSFRR.js +885 -0
- package/dist/schedule-ZEREUVXT.js +64 -0
- package/dist/scheduled-agents-5URJWW2E.js +55 -0
- package/dist/schema-NQ7DXUHX.js +135 -0
- package/dist/schema-U6GAKTQZ.js +121 -0
- package/dist/search-T5JFYDCZ.js +177 -0
- package/dist/select-SDFGLXMV.js +110 -0
- package/dist/set-prompt-JI5W6VPR.js +199 -0
- package/dist/setup-links-TOL7BFBE.js +144 -0
- package/dist/shopify-QXOGNIVU.js +3980 -0
- package/dist/site-NJDIUQY6.js +180 -0
- package/dist/sources-EMUT5MV7.js +457 -0
- package/dist/sources-M4IJL4H7.js +30 -0
- package/dist/stale-YYJNWLIE.js +90 -0
- package/dist/status-UZJGIDRI.js +65 -0
- package/dist/studio-OV2ZY5W3.js +49 -0
- package/dist/sync-T3E7SP7B.js +57 -0
- package/dist/sync-definition-TLY4FQKC.js +70 -0
- package/dist/tags-DPI3CAPB.js +23 -0
- package/dist/tags-DS3W4EDB.js +26 -0
- package/dist/tags-HSUBVXPJ.js +227 -0
- package/dist/tags-WP7W57FY.js +23 -0
- package/dist/tags-WWZFKW3Y.js +23 -0
- package/dist/targeting-criteria-PICDCHEV.js +113 -0
- package/dist/targets-WOMHJXY7.js +106 -0
- package/dist/testimonials-LDL66SSG.js +32 -0
- package/dist/themes-RRLYZ46U.js +95 -0
- package/dist/top-companies-RBRWAW27.js +111 -0
- package/dist/transcript-V6LZKOKQ.js +165 -0
- package/dist/translate-53TPL46A.js +603 -0
- package/dist/triggers-DDV73LZ4.js +144 -0
- package/dist/unlink-PLS3GA5V.js +70 -0
- package/dist/unstage-GSWMVEVP.js +88 -0
- package/dist/update-CIMCN33A.js +155 -0
- package/dist/update-KK7QO2KE.js +101 -0
- package/dist/update-X2H3GZ4I.js +192 -0
- package/dist/update-XNV6KHYK.js +66 -0
- package/dist/upload-OL2S2OSA.js +130 -0
- package/dist/url-options-2TQCGD2W.js +131 -0
- package/dist/url-params-QNSGNQ6N.js +101 -0
- package/dist/validate-KC3UA552.js +125 -0
- package/dist/videos-GBD36TD2.js +41 -0
- package/dist/viewer-check-LQUD2OYO.js +83 -0
- package/dist/web-K3L2BKAH.js +173 -0
- package/dist/winning-ads-X3VYALHK.js +86 -0
- package/dist/write-commands-XUOCRBME.js +1525 -0
- package/dist/x-65WPQWOP.js +47 -0
- package/package.json +1 -1
- package/dist/account-2HJ4GKHN.js +0 -82
- package/dist/account-MTMCQQYH.js +0 -82
- package/dist/account-reads-X36NPCX5.js +0 -219
- package/dist/account-users-FJ63HUJT.js +0 -64
- package/dist/account-writes-FZ3KCJZY.js +0 -68
- package/dist/accounts-PLZTPM52.js +0 -701
- package/dist/accounts-VYQINKID.js +0 -80
- package/dist/actions-NKCYYR7Q.js +0 -55
- package/dist/activecampaign-LQHDIHN5.js +0 -938
- package/dist/ad-group-writes-XGG3WQEO.js +0 -172
- package/dist/ad-groups-GZIPUN64.js +0 -70
- package/dist/ad-writes-2VTRWQLW.js +0 -176
- package/dist/add-6EHN5G6X.js +0 -107
- package/dist/add-HLBKTI3H.js +0 -305
- package/dist/ads-CWXQLZCC.js +0 -48
- package/dist/ads-LNWALF6G.js +0 -79
- package/dist/advertisers-YMIPR2QG.js +0 -123
- package/dist/analytics-37M6Z37U.js +0 -2437
- package/dist/analytics-6VAB2VYM.js +0 -447
- package/dist/animate-DM4OUJMR.js +0 -480
- package/dist/assign-V25HMGMU.js +0 -80
- package/dist/audience-size-FKNAK4QD.js +0 -76
- package/dist/audiences-7D5VPOWF.js +0 -280
- package/dist/audit-6VVUMMYL.js +0 -154
- package/dist/autocomplete-NETVGJRC.js +0 -114
- package/dist/avatars-HH4LOUA3.js +0 -38
- package/dist/bid-pricing-SCTUSHFI.js +0 -103
- package/dist/brand-FTPQYYDU.js +0 -22
- package/dist/brief-MCKNRSWM.js +0 -543
- package/dist/campaign-groups-ZNKBTXPV.js +0 -99
- package/dist/campaign-writes-5TWXZ44R.js +0 -168
- package/dist/campaign-writes-H22P6YPW.js +0 -176
- package/dist/campaigns-265JXD2Z.js +0 -78
- package/dist/campaigns-E64SHT67.js +0 -111
- package/dist/campaigns-GYNO5P22.js +0 -113
- package/dist/canvas-E4ZT2K7I.js +0 -46
- package/dist/capabilities-RVNBW4OL.js +0 -147
- package/dist/catalog-DPUQBZZ7.js +0 -66
- package/dist/catalogs-SBXFAD3X.js +0 -130
- package/dist/changes-HXVZUJMH.js +0 -143
- package/dist/chatgpt-UXJPCGZU.js +0 -47
- package/dist/chats-4SQSGOFC.js +0 -449
- package/dist/check-4WC2RLDR.js +0 -107
- package/dist/chunk-3I66ZQTI.js +0 -203
- package/dist/chunk-3SEXQVMX.js +0 -91
- package/dist/chunk-4D73PLXU.js +0 -843
- package/dist/chunk-4EGXO63N.js +0 -479
- package/dist/chunk-4S5ZAG4S.js +0 -63
- package/dist/chunk-5UEBOBLO.js +0 -170
- package/dist/chunk-6FLUNQHT.js +0 -91
- package/dist/chunk-6I7N2WYU.js +0 -19
- package/dist/chunk-6KWT3Z35.js +0 -103
- package/dist/chunk-AI2SKWZE.js +0 -197
- package/dist/chunk-ANV42DGJ.js +0 -455
- package/dist/chunk-AYEWXTSF.js +0 -392
- package/dist/chunk-CKIDKN6H.js +0 -191
- package/dist/chunk-D4NK7SPT.js +0 -930
- package/dist/chunk-DNZVBP2W.js +0 -61
- package/dist/chunk-DYTBVVQX.js +0 -679
- package/dist/chunk-EBWOLUII.js +0 -24026
- package/dist/chunk-EBWOLUII.js.map +0 -1
- package/dist/chunk-EH34RWKR.js +0 -604
- package/dist/chunk-EOMY5SUJ.js +0 -783
- package/dist/chunk-EQAEWL6A.js +0 -547
- package/dist/chunk-F5UU5PAE.js +0 -494
- package/dist/chunk-FVDC6AKZ.js +0 -150
- package/dist/chunk-G4VG6ZV3.js +0 -430
- package/dist/chunk-GEQUWPAX.js +0 -715
- package/dist/chunk-GEQUWPAX.js.map +0 -1
- package/dist/chunk-GN7K3NPI.js +0 -148
- package/dist/chunk-H6CS7VSO.js +0 -1902
- package/dist/chunk-HBDWE7WK.js +0 -98
- package/dist/chunk-I6JPTDKR.js +0 -377
- package/dist/chunk-IGIACW2B.js +0 -207
- package/dist/chunk-IRINY4B2.js +0 -2209
- package/dist/chunk-J4JY435Z.js +0 -438
- package/dist/chunk-JAC6JVCI.js +0 -26
- package/dist/chunk-JLLGXYOZ.js +0 -857
- package/dist/chunk-JY3OJBKZ.js +0 -3510
- package/dist/chunk-KIXVHP2C.js +0 -1919
- package/dist/chunk-LODEDXCD.js +0 -156
- package/dist/chunk-MCJ5I5LR.js +0 -3187
- package/dist/chunk-MCJ5I5LR.js.map +0 -1
- package/dist/chunk-MEK7SMWO.js +0 -685
- package/dist/chunk-MELSTI6W.js +0 -66
- package/dist/chunk-MSMTG6OC.js +0 -4269
- package/dist/chunk-MSMTG6OC.js.map +0 -1
- package/dist/chunk-MZPS46OR.js +0 -76
- package/dist/chunk-NBWZVBDG.js +0 -131
- package/dist/chunk-P3VY5JEM.js +0 -274
- package/dist/chunk-PXGR3VGW.js +0 -1646
- package/dist/chunk-QK3HMAVU.js +0 -5471
- package/dist/chunk-QYKZ3FVE.js +0 -51
- package/dist/chunk-RHEWQB5O.js +0 -638
- package/dist/chunk-RP36XHWT.js +0 -46
- package/dist/chunk-SNWFM2DB.js +0 -228
- package/dist/chunk-SWPJZJTY.js +0 -8954
- package/dist/chunk-SXYEIZND.js +0 -275
- package/dist/chunk-T62SKL4T.js +0 -831
- package/dist/chunk-T7SOINEA.js +0 -169
- package/dist/chunk-TARINRA4.js +0 -1518
- package/dist/chunk-TBIDT7FG.js +0 -392
- package/dist/chunk-TNHIYELA.js +0 -249
- package/dist/chunk-TNZUMU55.js +0 -167
- package/dist/chunk-UT77RVVU.js +0 -142
- package/dist/chunk-VOUCQ2YW.js +0 -64
- package/dist/chunk-VR2AF7I7.js +0 -7823
- package/dist/chunk-VR2AF7I7.js.map +0 -1
- package/dist/chunk-VVMRSEW6.js +0 -23
- package/dist/chunk-WFJ7KR5K.js +0 -163
- package/dist/chunk-WLA7CA4G.js +0 -297
- package/dist/chunk-WOE4TZHJ.js +0 -285
- package/dist/chunk-XJ2GXHU4.js +0 -57
- package/dist/chunk-XLG3SJ3K.js +0 -334
- package/dist/chunk-XYNQMRNX.js +0 -5368
- package/dist/chunk-YDGBWP3I.js +0 -89
- package/dist/chunk-Z4TWYYM3.js +0 -910
- package/dist/chunk-ZEUAJAKN.js +0 -225
- package/dist/chunk-ZKYJYBDR.js +0 -344
- package/dist/chunk-ZL43WZBX.js +0 -224
- package/dist/claim-G4MRH7Q7.js +0 -200
- package/dist/companies-TV5SX7IW.js +0 -198
- package/dist/company-W2N3H7AG.js +0 -308
- package/dist/complete-CTS2VDY5.js +0 -84
- package/dist/connect-64CFSYYE.js +0 -45
- package/dist/conversation-T57OY4L4.js +0 -96
- package/dist/conversion-report-RB2MU7UD.js +0 -127
- package/dist/conversion-upload-command-HFZYKVXA.js +0 -439
- package/dist/conversion-writes-56AIPXPK.js +0 -122
- package/dist/conversions-NRX76ZIT.js +0 -78
- package/dist/conversions-P75BZDDN.js +0 -140
- package/dist/create-2IFLWXCE.js +0 -135
- package/dist/create-2ZM3SAMX.js +0 -239
- package/dist/create-I6AVOYOS.js +0 -210
- package/dist/create-YKV66SQ6.js +0 -62
- package/dist/creatives-4HMWWE4O.js +0 -58
- package/dist/creatives-CSXTXOTD.js +0 -223
- package/dist/credentials-YQND7EIL.js +0 -290
- package/dist/critique-ABUU725C.js +0 -232
- package/dist/critique-EBQKUWBV.js +0 -1451
- package/dist/crm-4GXVHO4R.js +0 -323
- package/dist/crm-G2QOW4WY.js +0 -227
- package/dist/currency-CHBV6WIO.js +0 -88
- package/dist/customers-SNDSWS2C.js +0 -65
- package/dist/delete-AXECUWUU.js +0 -57
- package/dist/delete-WSWCPQ4R.js +0 -67
- package/dist/delete-YE3ZJKGK.js +0 -69
- package/dist/demographics-UPLQV4VW.js +0 -141
- package/dist/discard-D3SPLQP2.js +0 -69
- package/dist/discover-ZU2DAV23.js +0 -172
- package/dist/domain-OXNE56NK.js +0 -101
- package/dist/download-DGVEUXKX.js +0 -172
- package/dist/draft-2SMIRPNZ.js +0 -220
- package/dist/draft-2YTMB4YM.js +0 -313
- package/dist/draft-EWGNZUU4.js +0 -288
- package/dist/draft-L7EN5TZD.js +0 -342
- package/dist/draft-R7BNWMBR.js +0 -408
- package/dist/experiments-C3M65LMP.js +0 -236
- package/dist/facets-SGS4HDCM.js +0 -117
- package/dist/feedback-256D3HOY.js +0 -115
- package/dist/feedback-record-FDOIZ3HV.js +0 -269
- package/dist/fetch-EODKEOLX.js +0 -204
- package/dist/fit-VEUYZEG6.js +0 -65
- package/dist/flows-RCOWB5BY.js +0 -250
- package/dist/fonts-33UOE4X3.js +0 -39
- package/dist/forecast-372Q6KQZ.js +0 -169
- package/dist/forecast-I3WRFKQL.js +0 -121
- package/dist/funnel-MLPPNJQK.js +0 -397
- package/dist/generate-JQIK3UYS.js +0 -263
- package/dist/get-AOHHMPZC.js +0 -59
- package/dist/get-SORMH25W.js +0 -82
- package/dist/google-JHTOX6WM.js +0 -3270
- package/dist/google-ads-CNREZMRN.js +0 -198
- package/dist/history-D5UQTJ4H.js +0 -102
- package/dist/history-VNLS2TKB.js +0 -69
- package/dist/history-ZE7OQGDR.js +0 -153
- package/dist/hubspot-WGP36QI3.js +0 -782
- package/dist/ideas-4F5JG4UV.js +0 -45
- package/dist/images-Q5MZ75SL.js +0 -92
- package/dist/ingest-52X3B37O.js +0 -123
- package/dist/ingest-NXISET6E.js +0 -27
- package/dist/insights-XY6II7TX.js +0 -132
- package/dist/inspect-JD4WLZ57.js +0 -192
- package/dist/intent-5QUPPZNI.js +0 -95
- package/dist/keyword-gap-IG3EFLDH.js +0 -130
- package/dist/keyword-metrics-DDW4MSLX.js +0 -200
- package/dist/keywords-for-site-3UM6THUN.js +0 -131
- package/dist/landing-EAEMVCED.js +0 -28
- package/dist/languages-LNHWSCMT.js +0 -40
- package/dist/leads-MITJNZWB.js +0 -115
- package/dist/learn-VLUC2TXW.js +0 -207
- package/dist/line-item-writes-HLQYQ4KG.js +0 -211
- package/dist/line-items-64KIKPCB.js +0 -107
- package/dist/link-NNSG5YQ4.js +0 -67
- package/dist/linkedin-JYN5LGP2.js +0 -1330
- package/dist/linkedin-person-OPCUWPLI.js +0 -139
- package/dist/list-5U4Z3PWU.js +0 -306
- package/dist/list-7S4KTZNU.js +0 -154
- package/dist/list-VQQICPK3.js +0 -67
- package/dist/locations-64JNCQID.js +0 -69
- package/dist/locations-KVAAO7LD.js +0 -40
- package/dist/log-63ZVYC6L.js +0 -95
- package/dist/make-7ITIZUJI.js +0 -1367
- package/dist/map-MTR4V7KE.js +0 -436
- package/dist/mcp-HKMQLXBC.js +0 -729
- package/dist/media-sources-ZBSBTB4C.js +0 -35
- package/dist/members-MTRJ3ZRS.js +0 -47
- package/dist/metrics-MXGA3EFS.js +0 -152
- package/dist/models-Z6SUHWKI.js +0 -155
- package/dist/normalize-SAKXSFEX.js +0 -144
- package/dist/options-L7B3SDIX.js +0 -125
- package/dist/organization-FFRNHVC5.js +0 -949
- package/dist/performance-AJA7YGOO.js +0 -5565
- package/dist/performance-F72KFQU5.js +0 -27
- package/dist/pixels-H642RPK4.js +0 -62
- package/dist/promoted-tweet-writes-32RAOXQR.js +0 -183
- package/dist/promoted-tweets-KMLFRWDN.js +0 -119
- package/dist/publish-FOSPQ2BE.js +0 -344
- package/dist/query-FT2BA3WH.js +0 -62
- package/dist/reddit-5PYYZNBJ.js +0 -29
- package/dist/refresh-AOHTPXU4.js +0 -97
- package/dist/release-G2UKFAQY.js +0 -63
- package/dist/relevant-pages-OCHLUV5K.js +0 -99
- package/dist/remove-K5C2URJE.js +0 -53
- package/dist/reopen-PWROABUC.js +0 -66
- package/dist/rerun-CVJYCCNK.js +0 -96
- package/dist/research-KLWC3JBI.js +0 -75
- package/dist/research-Z3OJXOS4.js +0 -265
- package/dist/reset-3QL7IOHF.js +0 -57
- package/dist/reset-GPO4MCSM.js +0 -57
- package/dist/resolve-7SW7FZ7Q.js +0 -124
- package/dist/retry-HNCUDQ7S.js +0 -63
- package/dist/retry-NVMOGTZD.js +0 -65
- package/dist/revenue-HDJFYUEB.js +0 -91
- package/dist/rules-RYHWD4HA.js +0 -99
- package/dist/rules-add-EMDFBYDA.js +0 -465
- package/dist/run-2XRDPVHX.js +0 -71
- package/dist/run-PXHQKRY5.js +0 -69
- package/dist/scaffold-ad-RJAXMKOX.js +0 -1513
- package/dist/scaffold-static-ad-4HLSHPJI.js +0 -1011
- package/dist/scaffold-video-UH6OOIQW.js +0 -885
- package/dist/schedule-WT22OEBF.js +0 -64
- package/dist/scheduled-agents-BLIDNRFX.js +0 -55
- package/dist/schema-FUCZHUNV.js +0 -135
- package/dist/schema-NSXMRNWM.js +0 -121
- package/dist/search-S5O3L4KX.js +0 -177
- package/dist/select-ISIQXRPF.js +0 -110
- package/dist/set-prompt-MAQN5CYY.js +0 -199
- package/dist/setup-links-HANLAGD2.js +0 -144
- package/dist/shopify-PKWH7WXV.js +0 -3980
- package/dist/site-GADKB2RP.js +0 -180
- package/dist/sources-CA7JLF4P.js +0 -30
- package/dist/sources-HUXVRGDH.js +0 -457
- package/dist/stale-2A33KEE7.js +0 -90
- package/dist/status-5JTRE3OM.js +0 -65
- package/dist/studio-6ZXUKA4G.js +0 -49
- package/dist/sync-RJFMKM6D.js +0 -57
- package/dist/sync-definition-AKZUCLEV.js +0 -70
- package/dist/tags-B2EXVMNS.js +0 -23
- package/dist/tags-JUIKSERD.js +0 -227
- package/dist/tags-LP6I7GY4.js +0 -26
- package/dist/tags-UHD43CAG.js +0 -23
- package/dist/tags-WJFCPOP7.js +0 -23
- package/dist/targeting-criteria-2LKBD5IH.js +0 -113
- package/dist/targets-O5JYFOCY.js +0 -106
- package/dist/testimonials-P63TKNJ2.js +0 -32
- package/dist/themes-R3A6IVQN.js +0 -95
- package/dist/top-companies-F7DUMWXA.js +0 -111
- package/dist/transcript-4RFSQA5U.js +0 -165
- package/dist/translate-WOJFJRAC.js +0 -603
- package/dist/triggers-4MHFN3VV.js +0 -144
- package/dist/unlink-5AXBQOIL.js +0 -70
- package/dist/unstage-SIBXT25Y.js +0 -88
- package/dist/update-4BDOO53L.js +0 -101
- package/dist/update-NNEMJQ4D.js +0 -155
- package/dist/update-O76YSKXB.js +0 -192
- package/dist/update-YS4QI2KP.js +0 -66
- package/dist/upload-XVV3HQ5W.js +0 -130
- package/dist/url-options-YZ6UG3NY.js +0 -131
- package/dist/url-params-XL5URMTG.js +0 -101
- package/dist/validate-42Q7X2KK.js +0 -125
- package/dist/videos-HMKEY5WY.js +0 -41
- package/dist/viewer-check-4XFEWEH3.js +0 -83
- package/dist/web-PYG3AOYS.js +0 -173
- package/dist/winning-ads-74BKOBVN.js +0 -86
- package/dist/write-commands-43GTQIR6.js +0 -1525
- package/dist/x-6WSV55RN.js +0 -47
- /package/dist/{account-2HJ4GKHN.js.map → account-IG3U6UXZ.js.map} +0 -0
- /package/dist/{account-MTMCQQYH.js.map → account-JCQYOGJD.js.map} +0 -0
- /package/dist/{account-reads-X36NPCX5.js.map → account-reads-LOCJMS35.js.map} +0 -0
- /package/dist/{account-users-FJ63HUJT.js.map → account-users-AZPQPHD3.js.map} +0 -0
- /package/dist/{account-writes-FZ3KCJZY.js.map → account-writes-BSSKSTZ2.js.map} +0 -0
- /package/dist/{accounts-VYQINKID.js.map → accounts-2PZV6VRS.js.map} +0 -0
- /package/dist/{accounts-PLZTPM52.js.map → accounts-5I6USVT7.js.map} +0 -0
- /package/dist/{actions-NKCYYR7Q.js.map → actions-TSNXITQM.js.map} +0 -0
- /package/dist/{activecampaign-LQHDIHN5.js.map → activecampaign-2RKR6P74.js.map} +0 -0
- /package/dist/{ad-group-writes-XGG3WQEO.js.map → ad-group-writes-KMB3OMJG.js.map} +0 -0
- /package/dist/{ad-groups-GZIPUN64.js.map → ad-groups-E67CNQS4.js.map} +0 -0
- /package/dist/{ad-writes-2VTRWQLW.js.map → ad-writes-FNMKNFUN.js.map} +0 -0
- /package/dist/{add-HLBKTI3H.js.map → add-ENUFKN5V.js.map} +0 -0
- /package/dist/{add-6EHN5G6X.js.map → add-SRHNKSJT.js.map} +0 -0
- /package/dist/{ads-LNWALF6G.js.map → ads-4LASBP4G.js.map} +0 -0
- /package/dist/{ads-CWXQLZCC.js.map → ads-X33452HM.js.map} +0 -0
- /package/dist/{advertisers-YMIPR2QG.js.map → advertisers-XO5EJXR5.js.map} +0 -0
- /package/dist/{analytics-6VAB2VYM.js.map → analytics-AZTZVHVA.js.map} +0 -0
- /package/dist/{analytics-37M6Z37U.js.map → analytics-ED3NBGJJ.js.map} +0 -0
- /package/dist/{animate-DM4OUJMR.js.map → animate-OWXAT2RK.js.map} +0 -0
- /package/dist/{assign-V25HMGMU.js.map → assign-SIXEBHRW.js.map} +0 -0
- /package/dist/{audience-size-FKNAK4QD.js.map → audience-size-ACNA4JIX.js.map} +0 -0
- /package/dist/{audiences-7D5VPOWF.js.map → audiences-3R574STZ.js.map} +0 -0
- /package/dist/{audit-6VVUMMYL.js.map → audit-K5BEYW7G.js.map} +0 -0
- /package/dist/{autocomplete-NETVGJRC.js.map → autocomplete-XIYI56SU.js.map} +0 -0
- /package/dist/{avatars-HH4LOUA3.js.map → avatars-C5CUPLIV.js.map} +0 -0
- /package/dist/{bid-pricing-SCTUSHFI.js.map → bid-pricing-2UF6O2K6.js.map} +0 -0
- /package/dist/{brand-FTPQYYDU.js.map → brand-ATWMTJFS.js.map} +0 -0
- /package/dist/{brief-MCKNRSWM.js.map → brief-A65JXAER.js.map} +0 -0
- /package/dist/{campaign-groups-ZNKBTXPV.js.map → campaign-groups-F5C7C7NG.js.map} +0 -0
- /package/dist/{campaign-writes-5TWXZ44R.js.map → campaign-writes-TNW7KKQQ.js.map} +0 -0
- /package/dist/{campaign-writes-H22P6YPW.js.map → campaign-writes-Z2J24SUZ.js.map} +0 -0
- /package/dist/{campaigns-265JXD2Z.js.map → campaigns-43OS6EUG.js.map} +0 -0
- /package/dist/{campaigns-E64SHT67.js.map → campaigns-TQZXAMWE.js.map} +0 -0
- /package/dist/{campaigns-GYNO5P22.js.map → campaigns-XTNWM3VV.js.map} +0 -0
- /package/dist/{canvas-E4ZT2K7I.js.map → canvas-UGO5IHCA.js.map} +0 -0
- /package/dist/{capabilities-RVNBW4OL.js.map → capabilities-XHPLFYH2.js.map} +0 -0
- /package/dist/{catalog-DPUQBZZ7.js.map → catalog-7LINLVVY.js.map} +0 -0
- /package/dist/{catalogs-SBXFAD3X.js.map → catalogs-IR22RGZD.js.map} +0 -0
- /package/dist/{changes-HXVZUJMH.js.map → changes-JAGWBHQC.js.map} +0 -0
- /package/dist/{chatgpt-UXJPCGZU.js.map → chatgpt-NE2RBMFK.js.map} +0 -0
- /package/dist/{chats-4SQSGOFC.js.map → chats-QFZ4DGI7.js.map} +0 -0
- /package/dist/{check-4WC2RLDR.js.map → check-AEMZGF5G.js.map} +0 -0
- /package/dist/{chunk-ZL43WZBX.js.map → chunk-34JTMTPJ.js.map} +0 -0
- /package/dist/{chunk-WLA7CA4G.js.map → chunk-3C42N42Q.js.map} +0 -0
- /package/dist/{chunk-RHEWQB5O.js.map → chunk-3EUITH4J.js.map} +0 -0
- /package/dist/{chunk-RP36XHWT.js.map → chunk-4IRJ5JXA.js.map} +0 -0
- /package/dist/{chunk-D4NK7SPT.js.map → chunk-4QGNRCSE.js.map} +0 -0
- /package/dist/{chunk-UT77RVVU.js.map → chunk-4XFP43NH.js.map} +0 -0
- /package/dist/{chunk-I6JPTDKR.js.map → chunk-5EHSDRMJ.js.map} +0 -0
- /package/dist/{chunk-ZEUAJAKN.js.map → chunk-5IFFPSEN.js.map} +0 -0
- /package/dist/{chunk-P3VY5JEM.js.map → chunk-64ALJ6TJ.js.map} +0 -0
- /package/dist/{chunk-F5UU5PAE.js.map → chunk-6KGMWAUL.js.map} +0 -0
- /package/dist/{chunk-JAC6JVCI.js.map → chunk-6OIKNJ7G.js.map} +0 -0
- /package/dist/{chunk-6KWT3Z35.js.map → chunk-6ZUGN27V.js.map} +0 -0
- /package/dist/{chunk-QYKZ3FVE.js.map → chunk-7MWELLCN.js.map} +0 -0
- /package/dist/{chunk-TNZUMU55.js.map → chunk-7UFV6H7J.js.map} +0 -0
- /package/dist/{chunk-4D73PLXU.js.map → chunk-B3CDNANO.js.map} +0 -0
- /package/dist/{chunk-AYEWXTSF.js.map → chunk-B3LSWNUR.js.map} +0 -0
- /package/dist/{chunk-6I7N2WYU.js.map → chunk-BIHU5GCE.js.map} +0 -0
- /package/dist/{chunk-EOMY5SUJ.js.map → chunk-BNI5DAB7.js.map} +0 -0
- /package/dist/{chunk-YDGBWP3I.js.map → chunk-CISE4DOX.js.map} +0 -0
- /package/dist/{chunk-CKIDKN6H.js.map → chunk-CVWYS7SE.js.map} +0 -0
- /package/dist/{chunk-FVDC6AKZ.js.map → chunk-CXRS5YLB.js.map} +0 -0
- /package/dist/{chunk-JY3OJBKZ.js.map → chunk-E5H7JIWB.js.map} +0 -0
- /package/dist/{chunk-SXYEIZND.js.map → chunk-EI6R7GKQ.js.map} +0 -0
- /package/dist/{chunk-ZKYJYBDR.js.map → chunk-F743MUNY.js.map} +0 -0
- /package/dist/{chunk-J4JY435Z.js.map → chunk-FEVA2MNA.js.map} +0 -0
- /package/dist/{chunk-3I66ZQTI.js.map → chunk-FJXSVDWW.js.map} +0 -0
- /package/dist/{chunk-QK3HMAVU.js.map → chunk-G6J6AWTE.js.map} +0 -0
- /package/dist/{chunk-XYNQMRNX.js.map → chunk-GCZK4BMB.js.map} +0 -0
- /package/dist/{chunk-LODEDXCD.js.map → chunk-GKIYKOJW.js.map} +0 -0
- /package/dist/{chunk-3SEXQVMX.js.map → chunk-H4OVNGUK.js.map} +0 -0
- /package/dist/{chunk-MELSTI6W.js.map → chunk-HWOOMK5A.js.map} +0 -0
- /package/dist/{chunk-XLG3SJ3K.js.map → chunk-IABSARSS.js.map} +0 -0
- /package/dist/{chunk-Z4TWYYM3.js.map → chunk-IAOKMWUF.js.map} +0 -0
- /package/dist/{chunk-DYTBVVQX.js.map → chunk-ICEYCLRU.js.map} +0 -0
- /package/dist/{chunk-WOE4TZHJ.js.map → chunk-JBNT444M.js.map} +0 -0
- /package/dist/{chunk-SWPJZJTY.js.map → chunk-K3HZVRBJ.js.map} +0 -0
- /package/dist/{chunk-DNZVBP2W.js.map → chunk-KCZY5Y4E.js.map} +0 -0
- /package/dist/{chunk-PXGR3VGW.js.map → chunk-KTO2Y3DI.js.map} +0 -0
- /package/dist/{chunk-GN7K3NPI.js.map → chunk-LDFM37DM.js.map} +0 -0
- /package/dist/{chunk-JLLGXYOZ.js.map → chunk-LHC6OHQ6.js.map} +0 -0
- /package/dist/{chunk-ANV42DGJ.js.map → chunk-LMSV7NQY.js.map} +0 -0
- /package/dist/{chunk-XJ2GXHU4.js.map → chunk-LPDHNMOY.js.map} +0 -0
- /package/dist/{chunk-4S5ZAG4S.js.map → chunk-METHLFNZ.js.map} +0 -0
- /package/dist/{chunk-5UEBOBLO.js.map → chunk-MI3HAKXY.js.map} +0 -0
- /package/dist/{chunk-NBWZVBDG.js.map → chunk-P6FMQHJJ.js.map} +0 -0
- /package/dist/{chunk-4EGXO63N.js.map → chunk-PT73IEI6.js.map} +0 -0
- /package/dist/{chunk-TARINRA4.js.map → chunk-Q6LCL67T.js.map} +0 -0
- /package/dist/{chunk-IRINY4B2.js.map → chunk-RFGO4DHJ.js.map} +0 -0
- /package/dist/{chunk-MEK7SMWO.js.map → chunk-RMTM22JO.js.map} +0 -0
- /package/dist/{chunk-G4VG6ZV3.js.map → chunk-S2L2A2ZN.js.map} +0 -0
- /package/dist/{chunk-T7SOINEA.js.map → chunk-SA3P64PQ.js.map} +0 -0
- /package/dist/{chunk-MZPS46OR.js.map → chunk-SIKCVWM3.js.map} +0 -0
- /package/dist/{chunk-T62SKL4T.js.map → chunk-SIOLRCLE.js.map} +0 -0
- /package/dist/{chunk-TBIDT7FG.js.map → chunk-TK6BXI5A.js.map} +0 -0
- /package/dist/{chunk-VOUCQ2YW.js.map → chunk-V4UJERGL.js.map} +0 -0
- /package/dist/{chunk-IGIACW2B.js.map → chunk-V6NFLQKX.js.map} +0 -0
- /package/dist/{chunk-EQAEWL6A.js.map → chunk-VISKG4IA.js.map} +0 -0
- /package/dist/{chunk-VVMRSEW6.js.map → chunk-WJ6KKTIU.js.map} +0 -0
- /package/dist/{chunk-WFJ7KR5K.js.map → chunk-WPZTFSED.js.map} +0 -0
- /package/dist/{chunk-TNHIYELA.js.map → chunk-X5UMVG4S.js.map} +0 -0
- /package/dist/{chunk-AI2SKWZE.js.map → chunk-X7ROPKZT.js.map} +0 -0
- /package/dist/{chunk-EH34RWKR.js.map → chunk-XDJZH2JV.js.map} +0 -0
- /package/dist/{chunk-KIXVHP2C.js.map → chunk-XU6XQPNM.js.map} +0 -0
- /package/dist/{chunk-SNWFM2DB.js.map → chunk-YKFGXS26.js.map} +0 -0
- /package/dist/{chunk-HBDWE7WK.js.map → chunk-YQB66YKJ.js.map} +0 -0
- /package/dist/{chunk-H6CS7VSO.js.map → chunk-YSTAPNQP.js.map} +0 -0
- /package/dist/{chunk-6FLUNQHT.js.map → chunk-ZSLZOUGC.js.map} +0 -0
- /package/dist/{claim-G4MRH7Q7.js.map → claim-R6OG5IHM.js.map} +0 -0
- /package/dist/{companies-TV5SX7IW.js.map → companies-M36P2XXN.js.map} +0 -0
- /package/dist/{company-W2N3H7AG.js.map → company-NQAS3QF6.js.map} +0 -0
- /package/dist/{complete-CTS2VDY5.js.map → complete-FJHCHRYO.js.map} +0 -0
- /package/dist/{connect-64CFSYYE.js.map → connect-TEWDGN6C.js.map} +0 -0
- /package/dist/{conversation-T57OY4L4.js.map → conversation-UC7PXJQ3.js.map} +0 -0
- /package/dist/{conversion-report-RB2MU7UD.js.map → conversion-report-R4KJI4VA.js.map} +0 -0
- /package/dist/{conversion-upload-command-HFZYKVXA.js.map → conversion-upload-command-WCLWA27O.js.map} +0 -0
- /package/dist/{conversion-writes-56AIPXPK.js.map → conversion-writes-XIQEIDPS.js.map} +0 -0
- /package/dist/{conversions-P75BZDDN.js.map → conversions-D7P3KVQK.js.map} +0 -0
- /package/dist/{conversions-NRX76ZIT.js.map → conversions-RMBQNW3T.js.map} +0 -0
- /package/dist/{create-YKV66SQ6.js.map → create-GMZHI4BK.js.map} +0 -0
- /package/dist/{create-2IFLWXCE.js.map → create-J2AICQFF.js.map} +0 -0
- /package/dist/{create-2ZM3SAMX.js.map → create-RVR33UQM.js.map} +0 -0
- /package/dist/{create-I6AVOYOS.js.map → create-VXHOWOVI.js.map} +0 -0
- /package/dist/{creatives-CSXTXOTD.js.map → creatives-SLKM5XNE.js.map} +0 -0
- /package/dist/{creatives-4HMWWE4O.js.map → creatives-YMFRT6SE.js.map} +0 -0
- /package/dist/{credentials-YQND7EIL.js.map → credentials-T3IID6QG.js.map} +0 -0
- /package/dist/{critique-EBQKUWBV.js.map → critique-2Y53EQ3S.js.map} +0 -0
- /package/dist/{critique-ABUU725C.js.map → critique-SMLSUHY2.js.map} +0 -0
- /package/dist/{crm-4GXVHO4R.js.map → crm-E35C36E3.js.map} +0 -0
- /package/dist/{crm-G2QOW4WY.js.map → crm-TPV4H4KN.js.map} +0 -0
- /package/dist/{currency-CHBV6WIO.js.map → currency-BY647ZB7.js.map} +0 -0
- /package/dist/{customers-SNDSWS2C.js.map → customers-PH376T52.js.map} +0 -0
- /package/dist/{delete-WSWCPQ4R.js.map → delete-4MNN3QXP.js.map} +0 -0
- /package/dist/{delete-YE3ZJKGK.js.map → delete-7PEW3V6J.js.map} +0 -0
- /package/dist/{delete-AXECUWUU.js.map → delete-TRONZNM2.js.map} +0 -0
- /package/dist/{demographics-UPLQV4VW.js.map → demographics-EZXWOSZE.js.map} +0 -0
- /package/dist/{discard-D3SPLQP2.js.map → discard-PHO5BKEZ.js.map} +0 -0
- /package/dist/{discover-ZU2DAV23.js.map → discover-TAJUFO5R.js.map} +0 -0
- /package/dist/{domain-OXNE56NK.js.map → domain-7GNF7QHV.js.map} +0 -0
- /package/dist/{download-DGVEUXKX.js.map → download-A4EYH6VD.js.map} +0 -0
- /package/dist/{draft-2SMIRPNZ.js.map → draft-NQG5RBSF.js.map} +0 -0
- /package/dist/{draft-L7EN5TZD.js.map → draft-PA3L7VG6.js.map} +0 -0
- /package/dist/{draft-2YTMB4YM.js.map → draft-QQWTEXVT.js.map} +0 -0
- /package/dist/{draft-R7BNWMBR.js.map → draft-RGSDXFFT.js.map} +0 -0
- /package/dist/{draft-EWGNZUU4.js.map → draft-SKEGKHIK.js.map} +0 -0
- /package/dist/{experiments-C3M65LMP.js.map → experiments-DEUWFSDQ.js.map} +0 -0
- /package/dist/{facets-SGS4HDCM.js.map → facets-KWT2NAGR.js.map} +0 -0
- /package/dist/{feedback-256D3HOY.js.map → feedback-A56L3VWN.js.map} +0 -0
- /package/dist/{feedback-record-FDOIZ3HV.js.map → feedback-record-FE4P5MKS.js.map} +0 -0
- /package/dist/{fetch-EODKEOLX.js.map → fetch-M5U4E5IE.js.map} +0 -0
- /package/dist/{fit-VEUYZEG6.js.map → fit-AYFRRDAN.js.map} +0 -0
- /package/dist/{flows-RCOWB5BY.js.map → flows-QKR7JW6H.js.map} +0 -0
- /package/dist/{fonts-33UOE4X3.js.map → fonts-RUHNGL7R.js.map} +0 -0
- /package/dist/{forecast-I3WRFKQL.js.map → forecast-V7IPL6EC.js.map} +0 -0
- /package/dist/{forecast-372Q6KQZ.js.map → forecast-VOND3WVO.js.map} +0 -0
- /package/dist/{funnel-MLPPNJQK.js.map → funnel-WNVS53CO.js.map} +0 -0
- /package/dist/{generate-JQIK3UYS.js.map → generate-SW5KLHXG.js.map} +0 -0
- /package/dist/{get-AOHHMPZC.js.map → get-AJNPJIX6.js.map} +0 -0
- /package/dist/{get-SORMH25W.js.map → get-ZLRSDJM6.js.map} +0 -0
- /package/dist/{google-JHTOX6WM.js.map → google-VYARAUQH.js.map} +0 -0
- /package/dist/{google-ads-CNREZMRN.js.map → google-ads-3PIHLIIF.js.map} +0 -0
- /package/dist/{history-ZE7OQGDR.js.map → history-34E26WGP.js.map} +0 -0
- /package/dist/{history-VNLS2TKB.js.map → history-7DF5HFJT.js.map} +0 -0
- /package/dist/{history-D5UQTJ4H.js.map → history-LWAKFSHW.js.map} +0 -0
- /package/dist/{hubspot-WGP36QI3.js.map → hubspot-HH7KVQU5.js.map} +0 -0
- /package/dist/{ideas-4F5JG4UV.js.map → ideas-VFZXVUFZ.js.map} +0 -0
- /package/dist/{images-Q5MZ75SL.js.map → images-LB4E2F5I.js.map} +0 -0
- /package/dist/{ingest-NXISET6E.js.map → ingest-LRUKF3EK.js.map} +0 -0
- /package/dist/{ingest-52X3B37O.js.map → ingest-VZ77AODJ.js.map} +0 -0
- /package/dist/{insights-XY6II7TX.js.map → insights-YVV5MHPQ.js.map} +0 -0
- /package/dist/{inspect-JD4WLZ57.js.map → inspect-X6XU4CXL.js.map} +0 -0
- /package/dist/{intent-5QUPPZNI.js.map → intent-GIAQDMHF.js.map} +0 -0
- /package/dist/{keyword-gap-IG3EFLDH.js.map → keyword-gap-NZF75XGF.js.map} +0 -0
- /package/dist/{keyword-metrics-DDW4MSLX.js.map → keyword-metrics-P546E6KW.js.map} +0 -0
- /package/dist/{keywords-for-site-3UM6THUN.js.map → keywords-for-site-AEFJ5BTU.js.map} +0 -0
- /package/dist/{landing-EAEMVCED.js.map → landing-RKO3LUST.js.map} +0 -0
- /package/dist/{languages-LNHWSCMT.js.map → languages-GGNN7FEK.js.map} +0 -0
- /package/dist/{leads-MITJNZWB.js.map → leads-OVYF2EKX.js.map} +0 -0
- /package/dist/{learn-VLUC2TXW.js.map → learn-UWJ24ZD5.js.map} +0 -0
- /package/dist/{line-item-writes-HLQYQ4KG.js.map → line-item-writes-46K4NKPJ.js.map} +0 -0
- /package/dist/{line-items-64KIKPCB.js.map → line-items-YRSGOQFS.js.map} +0 -0
- /package/dist/{link-NNSG5YQ4.js.map → link-XXRDZQFM.js.map} +0 -0
- /package/dist/{linkedin-JYN5LGP2.js.map → linkedin-W4OWO6QA.js.map} +0 -0
- /package/dist/{linkedin-person-OPCUWPLI.js.map → linkedin-person-SQTWLIN5.js.map} +0 -0
- /package/dist/{list-7S4KTZNU.js.map → list-E6WPSAQK.js.map} +0 -0
- /package/dist/{list-5U4Z3PWU.js.map → list-S34STWB3.js.map} +0 -0
- /package/dist/{list-VQQICPK3.js.map → list-XERZMEWU.js.map} +0 -0
- /package/dist/{locations-64JNCQID.js.map → locations-7RYEWKJO.js.map} +0 -0
- /package/dist/{locations-KVAAO7LD.js.map → locations-BU4ZGWAS.js.map} +0 -0
- /package/dist/{log-63ZVYC6L.js.map → log-CDN4H2JY.js.map} +0 -0
- /package/dist/{make-7ITIZUJI.js.map → make-JE7V2RWR.js.map} +0 -0
- /package/dist/{map-MTR4V7KE.js.map → map-SPSJ532D.js.map} +0 -0
- /package/dist/{mcp-HKMQLXBC.js.map → mcp-PBPHIS4Q.js.map} +0 -0
- /package/dist/{media-sources-ZBSBTB4C.js.map → media-sources-MZL4XML4.js.map} +0 -0
- /package/dist/{members-MTRJ3ZRS.js.map → members-RDNSONMW.js.map} +0 -0
- /package/dist/{metrics-MXGA3EFS.js.map → metrics-Z75Q2FHP.js.map} +0 -0
- /package/dist/{models-Z6SUHWKI.js.map → models-X2IXXAD6.js.map} +0 -0
- /package/dist/{normalize-SAKXSFEX.js.map → normalize-4KL73UBE.js.map} +0 -0
- /package/dist/{options-L7B3SDIX.js.map → options-7MN5WH3J.js.map} +0 -0
- /package/dist/{organization-FFRNHVC5.js.map → organization-NJT4G355.js.map} +0 -0
- /package/dist/{performance-F72KFQU5.js.map → performance-PG5T4D7M.js.map} +0 -0
- /package/dist/{performance-AJA7YGOO.js.map → performance-SB2KLMTO.js.map} +0 -0
- /package/dist/{pixels-H642RPK4.js.map → pixels-DBSPNHIE.js.map} +0 -0
- /package/dist/{promoted-tweet-writes-32RAOXQR.js.map → promoted-tweet-writes-PCWFF2EG.js.map} +0 -0
- /package/dist/{promoted-tweets-KMLFRWDN.js.map → promoted-tweets-ZSXREC4V.js.map} +0 -0
- /package/dist/{publish-FOSPQ2BE.js.map → publish-FIYZNQYO.js.map} +0 -0
- /package/dist/{query-FT2BA3WH.js.map → query-NMQKS4MY.js.map} +0 -0
- /package/dist/{reddit-5PYYZNBJ.js.map → reddit-7WRZ5B3I.js.map} +0 -0
- /package/dist/{refresh-AOHTPXU4.js.map → refresh-IKHSUY3E.js.map} +0 -0
- /package/dist/{release-G2UKFAQY.js.map → release-JCKOGRTY.js.map} +0 -0
- /package/dist/{relevant-pages-OCHLUV5K.js.map → relevant-pages-JRIDJL4L.js.map} +0 -0
- /package/dist/{remove-K5C2URJE.js.map → remove-KE63VJ3M.js.map} +0 -0
- /package/dist/{reopen-PWROABUC.js.map → reopen-4YSAVTOS.js.map} +0 -0
- /package/dist/{rerun-CVJYCCNK.js.map → rerun-K5SQ6GAQ.js.map} +0 -0
- /package/dist/{research-KLWC3JBI.js.map → research-OFHOHRFD.js.map} +0 -0
- /package/dist/{research-Z3OJXOS4.js.map → research-ORXD6AV4.js.map} +0 -0
- /package/dist/{reset-GPO4MCSM.js.map → reset-4CLSOD77.js.map} +0 -0
- /package/dist/{reset-3QL7IOHF.js.map → reset-BN4FDUZB.js.map} +0 -0
- /package/dist/{resolve-7SW7FZ7Q.js.map → resolve-F6QVMQGX.js.map} +0 -0
- /package/dist/{retry-NVMOGTZD.js.map → retry-JGAJF6CN.js.map} +0 -0
- /package/dist/{retry-HNCUDQ7S.js.map → retry-NJUIX2QT.js.map} +0 -0
- /package/dist/{revenue-HDJFYUEB.js.map → revenue-BYGHXTYJ.js.map} +0 -0
- /package/dist/{rules-RYHWD4HA.js.map → rules-MWTPVJTK.js.map} +0 -0
- /package/dist/{rules-add-EMDFBYDA.js.map → rules-add-3MJRAYXB.js.map} +0 -0
- /package/dist/{run-2XRDPVHX.js.map → run-CXD7RKYN.js.map} +0 -0
- /package/dist/{run-PXHQKRY5.js.map → run-NDJSLZNE.js.map} +0 -0
- /package/dist/{scaffold-ad-RJAXMKOX.js.map → scaffold-ad-2N7H7ACP.js.map} +0 -0
- /package/dist/{scaffold-static-ad-4HLSHPJI.js.map → scaffold-static-ad-R7T766AD.js.map} +0 -0
- /package/dist/{scaffold-video-UH6OOIQW.js.map → scaffold-video-22HVSFRR.js.map} +0 -0
- /package/dist/{schedule-WT22OEBF.js.map → schedule-ZEREUVXT.js.map} +0 -0
- /package/dist/{scheduled-agents-BLIDNRFX.js.map → scheduled-agents-5URJWW2E.js.map} +0 -0
- /package/dist/{schema-FUCZHUNV.js.map → schema-NQ7DXUHX.js.map} +0 -0
- /package/dist/{schema-NSXMRNWM.js.map → schema-U6GAKTQZ.js.map} +0 -0
- /package/dist/{search-S5O3L4KX.js.map → search-T5JFYDCZ.js.map} +0 -0
- /package/dist/{select-ISIQXRPF.js.map → select-SDFGLXMV.js.map} +0 -0
- /package/dist/{set-prompt-MAQN5CYY.js.map → set-prompt-JI5W6VPR.js.map} +0 -0
- /package/dist/{setup-links-HANLAGD2.js.map → setup-links-TOL7BFBE.js.map} +0 -0
- /package/dist/{shopify-PKWH7WXV.js.map → shopify-QXOGNIVU.js.map} +0 -0
- /package/dist/{site-GADKB2RP.js.map → site-NJDIUQY6.js.map} +0 -0
- /package/dist/{sources-HUXVRGDH.js.map → sources-EMUT5MV7.js.map} +0 -0
- /package/dist/{sources-CA7JLF4P.js.map → sources-M4IJL4H7.js.map} +0 -0
- /package/dist/{stale-2A33KEE7.js.map → stale-YYJNWLIE.js.map} +0 -0
- /package/dist/{status-5JTRE3OM.js.map → status-UZJGIDRI.js.map} +0 -0
- /package/dist/{studio-6ZXUKA4G.js.map → studio-OV2ZY5W3.js.map} +0 -0
- /package/dist/{sync-RJFMKM6D.js.map → sync-T3E7SP7B.js.map} +0 -0
- /package/dist/{sync-definition-AKZUCLEV.js.map → sync-definition-TLY4FQKC.js.map} +0 -0
- /package/dist/{tags-WJFCPOP7.js.map → tags-DPI3CAPB.js.map} +0 -0
- /package/dist/{tags-LP6I7GY4.js.map → tags-DS3W4EDB.js.map} +0 -0
- /package/dist/{tags-JUIKSERD.js.map → tags-HSUBVXPJ.js.map} +0 -0
- /package/dist/{tags-UHD43CAG.js.map → tags-WP7W57FY.js.map} +0 -0
- /package/dist/{tags-B2EXVMNS.js.map → tags-WWZFKW3Y.js.map} +0 -0
- /package/dist/{targeting-criteria-2LKBD5IH.js.map → targeting-criteria-PICDCHEV.js.map} +0 -0
- /package/dist/{targets-O5JYFOCY.js.map → targets-WOMHJXY7.js.map} +0 -0
- /package/dist/{testimonials-P63TKNJ2.js.map → testimonials-LDL66SSG.js.map} +0 -0
- /package/dist/{themes-R3A6IVQN.js.map → themes-RRLYZ46U.js.map} +0 -0
- /package/dist/{top-companies-F7DUMWXA.js.map → top-companies-RBRWAW27.js.map} +0 -0
- /package/dist/{transcript-4RFSQA5U.js.map → transcript-V6LZKOKQ.js.map} +0 -0
- /package/dist/{translate-WOJFJRAC.js.map → translate-53TPL46A.js.map} +0 -0
- /package/dist/{triggers-4MHFN3VV.js.map → triggers-DDV73LZ4.js.map} +0 -0
- /package/dist/{unlink-5AXBQOIL.js.map → unlink-PLS3GA5V.js.map} +0 -0
- /package/dist/{unstage-SIBXT25Y.js.map → unstage-GSWMVEVP.js.map} +0 -0
- /package/dist/{update-NNEMJQ4D.js.map → update-CIMCN33A.js.map} +0 -0
- /package/dist/{update-4BDOO53L.js.map → update-KK7QO2KE.js.map} +0 -0
- /package/dist/{update-O76YSKXB.js.map → update-X2H3GZ4I.js.map} +0 -0
- /package/dist/{update-YS4QI2KP.js.map → update-XNV6KHYK.js.map} +0 -0
- /package/dist/{upload-XVV3HQ5W.js.map → upload-OL2S2OSA.js.map} +0 -0
- /package/dist/{url-options-YZ6UG3NY.js.map → url-options-2TQCGD2W.js.map} +0 -0
- /package/dist/{url-params-XL5URMTG.js.map → url-params-QNSGNQ6N.js.map} +0 -0
- /package/dist/{validate-42Q7X2KK.js.map → validate-KC3UA552.js.map} +0 -0
- /package/dist/{videos-HMKEY5WY.js.map → videos-GBD36TD2.js.map} +0 -0
- /package/dist/{viewer-check-4XFEWEH3.js.map → viewer-check-LQUD2OYO.js.map} +0 -0
- /package/dist/{web-PYG3AOYS.js.map → web-K3L2BKAH.js.map} +0 -0
- /package/dist/{winning-ads-74BKOBVN.js.map → winning-ads-X3VYALHK.js.map} +0 -0
- /package/dist/{write-commands-43GTQIR6.js.map → write-commands-XUOCRBME.js.map} +0 -0
- /package/dist/{x-6WSV55RN.js.map → x-65WPQWOP.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/index.js","../../canvas-contract/src/adPlacements.ts","../../canvas-contract/src/adRead.ts","../../canvas-contract/src/castName.ts","../../canvas-contract/src/adPlatformFormats.ts","../../canvas-contract/src/registry.ts","../../canvas-contract/src/credits.ts","../../canvas-contract/src/videoCost.ts","../../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/766ad107c42df28eeadaf0ac2f9089c8a9e200f6ba0b2b1a817b8d536cbdcc49/node_modules/safe-stable-stringify/esm/wrapper.js","../../canvas-contract/src/canonical.ts","../../canvas-contract/src/clipWeight.ts","../../canvas-contract/src/frameRealism.ts","../../canvas-contract/src/nodeCost.ts","../../canvas-contract/src/personRealism.ts","../../canvas-contract/src/validateParams.ts","../../canvas-contract/src/videoBlueprint.ts"],"sourcesContent":["'use strict'\n\nconst { hasOwnProperty } = Object.prototype\n\nconst stringify = configure()\n\n// @ts-expect-error\nstringify.configure = configure\n// @ts-expect-error\nstringify.stringify = stringify\n\n// @ts-expect-error\nstringify.default = stringify\n\n// @ts-expect-error used for named export\nexports.stringify = stringify\n// @ts-expect-error used for named export\nexports.configure = configure\n\nmodule.exports = stringify\n\n// eslint-disable-next-line no-control-regex\nconst strEscapeSequencesRegExp = /[\\u0000-\\u001f\\u0022\\u005c\\ud800-\\udfff]/\n\n// Escape C0 control characters, double quotes, the backslash and every code\n// unit with a numeric value in the inclusive range 0xD800 to 0xDFFF.\nfunction strEscape (str) {\n // Some magic numbers that worked out fine while benchmarking with v8 8.0\n if (str.length < 5000 && !strEscapeSequencesRegExp.test(str)) {\n return `\"${str}\"`\n }\n return JSON.stringify(str)\n}\n\nfunction sort (array, comparator) {\n // Insertion sort is very efficient for small input sizes, but it has a bad\n // worst case complexity. Thus, use native array sort for bigger values.\n if (array.length > 2e2 || comparator) {\n return array.sort(comparator)\n }\n for (let i = 1; i < array.length; i++) {\n const currentValue = array[i]\n let position = i\n while (position !== 0 && array[position - 1] > currentValue) {\n array[position] = array[position - 1]\n position--\n }\n array[position] = currentValue\n }\n return array\n}\n\nconst typedArrayPrototypeGetSymbolToStringTag =\n Object.getOwnPropertyDescriptor(\n Object.getPrototypeOf(\n Object.getPrototypeOf(\n new Int8Array()\n )\n ),\n Symbol.toStringTag\n ).get\n\nfunction isTypedArrayWithEntries (value) {\n return typedArrayPrototypeGetSymbolToStringTag.call(value) !== undefined && value.length !== 0\n}\n\nfunction stringifyTypedArray (array, separator, maximumBreadth) {\n if (array.length < maximumBreadth) {\n maximumBreadth = array.length\n }\n const whitespace = separator === ',' ? '' : ' '\n let res = `\"0\":${whitespace}${array[0]}`\n for (let i = 1; i < maximumBreadth; i++) {\n res += `${separator}\"${i}\":${whitespace}${array[i]}`\n }\n return res\n}\n\nfunction getCircularValueOption (options) {\n if (hasOwnProperty.call(options, 'circularValue')) {\n const circularValue = options.circularValue\n if (typeof circularValue === 'string') {\n return `\"${circularValue}\"`\n }\n if (circularValue == null) {\n return circularValue\n }\n if (circularValue === Error || circularValue === TypeError) {\n return {\n toString () {\n throw new TypeError('Converting circular structure to JSON')\n }\n }\n }\n throw new TypeError('The \"circularValue\" argument must be of type string or the value null or undefined')\n }\n return '\"[Circular]\"'\n}\n\nfunction getDeterministicOption (options) {\n let value\n if (hasOwnProperty.call(options, 'deterministic')) {\n value = options.deterministic\n if (typeof value !== 'boolean' && typeof value !== 'function') {\n throw new TypeError('The \"deterministic\" argument must be of type boolean or comparator function')\n }\n }\n return value === undefined ? true : value\n}\n\nfunction getBooleanOption (options, key) {\n let value\n if (hasOwnProperty.call(options, key)) {\n value = options[key]\n if (typeof value !== 'boolean') {\n throw new TypeError(`The \"${key}\" argument must be of type boolean`)\n }\n }\n return value === undefined ? true : value\n}\n\nfunction getPositiveIntegerOption (options, key) {\n let value\n if (hasOwnProperty.call(options, key)) {\n value = options[key]\n if (typeof value !== 'number') {\n throw new TypeError(`The \"${key}\" argument must be of type number`)\n }\n if (!Number.isInteger(value)) {\n throw new TypeError(`The \"${key}\" argument must be an integer`)\n }\n if (value < 1) {\n throw new RangeError(`The \"${key}\" argument must be >= 1`)\n }\n }\n return value === undefined ? Infinity : value\n}\n\nfunction getItemCount (number) {\n if (number === 1) {\n return '1 item'\n }\n return `${number} items`\n}\n\nfunction getUniqueReplacerSet (replacerArray) {\n const replacerSet = new Set()\n for (const value of replacerArray) {\n if (typeof value === 'string' || typeof value === 'number') {\n replacerSet.add(String(value))\n }\n }\n return replacerSet\n}\n\nfunction getStrictOption (options) {\n if (hasOwnProperty.call(options, 'strict')) {\n const value = options.strict\n if (typeof value !== 'boolean') {\n throw new TypeError('The \"strict\" argument must be of type boolean')\n }\n if (value) {\n return (value) => {\n let message = `Object can not safely be stringified. Received type ${typeof value}`\n if (typeof value !== 'function') message += ` (${value.toString()})`\n throw new Error(message)\n }\n }\n }\n}\n\nfunction configure (options) {\n options = { ...options }\n const fail = getStrictOption(options)\n if (fail) {\n if (options.bigint === undefined) {\n options.bigint = false\n }\n if (!('circularValue' in options)) {\n options.circularValue = Error\n }\n }\n const circularValue = getCircularValueOption(options)\n const bigint = getBooleanOption(options, 'bigint')\n const deterministic = getDeterministicOption(options)\n const comparator = typeof deterministic === 'function' ? deterministic : undefined\n const maximumDepth = getPositiveIntegerOption(options, 'maximumDepth')\n const maximumBreadth = getPositiveIntegerOption(options, 'maximumBreadth')\n\n function stringifyFnReplacer (key, parent, stack, replacer, spacer, indentation) {\n let value = parent[key]\n\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n value = replacer.call(parent, key, value)\n\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n\n let res = ''\n let join = ','\n const originalIndentation = indentation\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n if (spacer !== '') {\n indentation += spacer\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n }\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `${join}\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n if (spacer !== '') {\n res += `\\n${originalIndentation}`\n }\n stack.pop()\n return `[${res}]`\n }\n\n let keys = Object.keys(value)\n const keyLength = keys.length\n if (keyLength === 0) {\n return '{}'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Object]\"'\n }\n let whitespace = ''\n let separator = ''\n if (spacer !== '') {\n indentation += spacer\n join = `,\\n${indentation}`\n whitespace = ' '\n }\n const maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth)\n if (deterministic && !isTypedArrayWithEntries(value)) {\n keys = sort(keys, comparator)\n }\n stack.push(value)\n for (let i = 0; i < maximumPropertiesToStringify; i++) {\n const key = keys[i]\n const tmp = stringifyFnReplacer(key, value, stack, replacer, spacer, indentation)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}:${whitespace}${tmp}`\n separator = join\n }\n }\n if (keyLength > maximumBreadth) {\n const removedKeys = keyLength - maximumBreadth\n res += `${separator}\"...\":${whitespace}\"${getItemCount(removedKeys)} not stringified\"`\n separator = join\n }\n if (spacer !== '' && separator.length > 1) {\n res = `\\n${indentation}${res}\\n${originalIndentation}`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringifyArrayReplacer (key, value, stack, replacer, spacer, indentation) {\n if (typeof value === 'object' && value !== null && typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n }\n\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n\n const originalIndentation = indentation\n let res = ''\n let join = ','\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n if (spacer !== '') {\n indentation += spacer\n res += `\\n${indentation}`\n join = `,\\n${indentation}`\n }\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `${join}\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n if (spacer !== '') {\n res += `\\n${originalIndentation}`\n }\n stack.pop()\n return `[${res}]`\n }\n stack.push(value)\n let whitespace = ''\n if (spacer !== '') {\n indentation += spacer\n join = `,\\n${indentation}`\n whitespace = ' '\n }\n let separator = ''\n for (const key of replacer) {\n const tmp = stringifyArrayReplacer(key, value[key], stack, replacer, spacer, indentation)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}:${whitespace}${tmp}`\n separator = join\n }\n }\n if (spacer !== '' && separator.length > 1) {\n res = `\\n${indentation}${res}\\n${originalIndentation}`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringifyIndent (key, value, stack, spacer, indentation) {\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again.\n if (typeof value !== 'object') {\n return stringifyIndent(key, value, stack, spacer, indentation)\n }\n if (value === null) {\n return 'null'\n }\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n const originalIndentation = indentation\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n indentation += spacer\n let res = `\\n${indentation}`\n const join = `,\\n${indentation}`\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n res += join\n }\n const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `${join}\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n res += `\\n${originalIndentation}`\n stack.pop()\n return `[${res}]`\n }\n\n let keys = Object.keys(value)\n const keyLength = keys.length\n if (keyLength === 0) {\n return '{}'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Object]\"'\n }\n indentation += spacer\n const join = `,\\n${indentation}`\n let res = ''\n let separator = ''\n let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth)\n if (isTypedArrayWithEntries(value)) {\n res += stringifyTypedArray(value, join, maximumBreadth)\n keys = keys.slice(value.length)\n maximumPropertiesToStringify -= value.length\n separator = join\n }\n if (deterministic) {\n keys = sort(keys, comparator)\n }\n stack.push(value)\n for (let i = 0; i < maximumPropertiesToStringify; i++) {\n const key = keys[i]\n const tmp = stringifyIndent(key, value[key], stack, spacer, indentation)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}: ${tmp}`\n separator = join\n }\n }\n if (keyLength > maximumBreadth) {\n const removedKeys = keyLength - maximumBreadth\n res += `${separator}\"...\": \"${getItemCount(removedKeys)} not stringified\"`\n separator = join\n }\n if (separator !== '') {\n res = `\\n${indentation}${res}\\n${originalIndentation}`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringifySimple (key, value, stack) {\n switch (typeof value) {\n case 'string':\n return strEscape(value)\n case 'object': {\n if (value === null) {\n return 'null'\n }\n if (typeof value.toJSON === 'function') {\n value = value.toJSON(key)\n // Prevent calling `toJSON` again\n if (typeof value !== 'object') {\n return stringifySimple(key, value, stack)\n }\n if (value === null) {\n return 'null'\n }\n }\n if (stack.indexOf(value) !== -1) {\n return circularValue\n }\n\n let res = ''\n\n const hasLength = value.length !== undefined\n if (hasLength && Array.isArray(value)) {\n if (value.length === 0) {\n return '[]'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Array]\"'\n }\n stack.push(value)\n const maximumValuesToStringify = Math.min(value.length, maximumBreadth)\n let i = 0\n for (; i < maximumValuesToStringify - 1; i++) {\n const tmp = stringifySimple(String(i), value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n res += ','\n }\n const tmp = stringifySimple(String(i), value[i], stack)\n res += tmp !== undefined ? tmp : 'null'\n if (value.length - 1 > maximumBreadth) {\n const removedKeys = value.length - maximumBreadth - 1\n res += `,\"... ${getItemCount(removedKeys)} not stringified\"`\n }\n stack.pop()\n return `[${res}]`\n }\n\n let keys = Object.keys(value)\n const keyLength = keys.length\n if (keyLength === 0) {\n return '{}'\n }\n if (maximumDepth < stack.length + 1) {\n return '\"[Object]\"'\n }\n let separator = ''\n let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth)\n if (hasLength && isTypedArrayWithEntries(value)) {\n res += stringifyTypedArray(value, ',', maximumBreadth)\n keys = keys.slice(value.length)\n maximumPropertiesToStringify -= value.length\n separator = ','\n }\n if (deterministic) {\n keys = sort(keys, comparator)\n }\n stack.push(value)\n for (let i = 0; i < maximumPropertiesToStringify; i++) {\n const key = keys[i]\n const tmp = stringifySimple(key, value[key], stack)\n if (tmp !== undefined) {\n res += `${separator}${strEscape(key)}:${tmp}`\n separator = ','\n }\n }\n if (keyLength > maximumBreadth) {\n const removedKeys = keyLength - maximumBreadth\n res += `${separator}\"...\":\"${getItemCount(removedKeys)} not stringified\"`\n }\n stack.pop()\n return `{${res}}`\n }\n case 'number':\n return isFinite(value) ? String(value) : fail ? fail(value) : 'null'\n case 'boolean':\n return value === true ? 'true' : 'false'\n case 'undefined':\n return undefined\n case 'bigint':\n if (bigint) {\n return String(value)\n }\n // fallthrough\n default:\n return fail ? fail(value) : undefined\n }\n }\n\n function stringify (value, replacer, space) {\n if (arguments.length > 1) {\n let spacer = ''\n if (typeof space === 'number') {\n spacer = ' '.repeat(Math.min(space, 10))\n } else if (typeof space === 'string') {\n spacer = space.slice(0, 10)\n }\n if (replacer != null) {\n if (typeof replacer === 'function') {\n return stringifyFnReplacer('', { '': value }, [], replacer, spacer, '')\n }\n if (Array.isArray(replacer)) {\n return stringifyArrayReplacer('', value, [], getUniqueReplacerSet(replacer), spacer, '')\n }\n }\n if (spacer.length !== 0) {\n return stringifyIndent('', value, [], spacer, '')\n }\n }\n return stringifySimple('', value, [])\n }\n\n return stringify\n}\n","/**\n * Where an ad runs → the sizes it must be delivered in, and what each placement's interface covers.\n *\n * One registry for every platform Baker publishes to, so the sizes a static ad is made in come\n * from its destination (the ad set's placements, or the platforms named) rather than a preset\n * remembered by hand, and every delivered size is checked against the interface of the\n * placement it actually runs in. Each placement cites the platform's own spec; the date the\n * numbers were last checked is recorded in `docs/marketing-intelligence.md` (Ad sizes).\n *\n * Fractions are of the frame: `safe` is the margin a design keeps at each edge, `cover` the part\n * an interface really draws over (a word there is not seen), with `rail` the column of buttons\n * down the lower right of a full-screen vertical feed. Meta's Reels and Stories numbers are\n * calibrated on hand-labelled audits (`platform-safe-area.ts` in the CLI records how); the\n * others are the platforms' published safe-zone guides, not yet calibrated.\n *\n * Pure data and pure functions.\n */\n\nexport const AD_PLATFORMS = [\n \"meta\",\n \"google_display\",\n \"google_pmax\",\n \"google_demandgen\",\n \"google_search\",\n \"youtube\",\n \"linkedin\",\n \"tiktok\",\n \"x\",\n \"reddit\",\n \"pinterest\",\n \"snapchat\",\n \"chatgpt\",\n] as const;\nexport type AdPlatform = (typeof AD_PLATFORMS)[number];\n\n/**\n * The size a platform's ad is designed in first, the others re-laid out from it: the picture its\n * main placement shows largest (owner decision, Oct 2026). Always one of the platform's required sizes.\n */\nexport const AD_PLATFORM_LEAD: Record<AdPlatform, string> = {\n meta: \"4:5\",\n google_display: \"1:1\",\n google_pmax: \"1:1\",\n google_demandgen: \"1:1\",\n google_search: \"1:1\",\n youtube: \"1.91:1\",\n linkedin: \"1:1\",\n tiktok: \"9:16\",\n x: \"1.91:1\",\n reddit: \"1:1\",\n pinterest: \"2:3\",\n snapchat: \"9:16\",\n chatgpt: \"1:1\",\n};\n\n/** How a person names the platform. */\nexport const AD_PLATFORM_NAMES: Record<AdPlatform, string> = {\n meta: \"Meta\",\n google_display: \"Google Display\",\n google_pmax: \"Performance Max\",\n google_demandgen: \"Demand Gen\",\n google_search: \"Google Search\",\n youtube: \"YouTube\",\n linkedin: \"LinkedIn\",\n tiktok: \"TikTok\",\n x: \"X\",\n reddit: \"Reddit\",\n pinterest: \"Pinterest\",\n snapchat: \"Snapchat\",\n chatgpt: \"ChatGPT\",\n};\n\nexport type EdgeShares = { top: number; bottom: number; left: number; right: number };\n/** A column of buttons down the right side: `width` wide, from `from` of the height down. */\nexport type ButtonRail = { width: number; from: number };\n/** The part of the frame an interface draws over. */\nexport type InterfaceCover = { top: number; bottom: number; rail?: ButtonRail };\n\nexport type PlacementSize = { width: number; height: number; required: boolean };\n\nexport type AdPlacement = {\n id: string;\n platform: AdPlatform;\n name: string;\n sizes: readonly PlacementSize[];\n /** The margin a design keeps at each edge. */\n safe: EdgeShares;\n /** What the interface covers; absent when nothing is drawn over the picture. */\n cover?: InterfaceCover;\n /** The margin kept around `cover.rail`: an element there is close (a note), not covered. */\n railMargin?: ButtonRail;\n /** A rule the platform enforces on the picture, said where it applies. */\n rule?: string;\n /** Run only when named by its id: naming the platform leaves it out (a size the platform's ads rarely need). */\n optIn?: true;\n source: string;\n};\n\nconst FEED_MARGIN: EdgeShares = { top: 0.04, bottom: 0.04, left: 0.04, right: 0.04 };\nconst size = (width: number, height: number, required = true): PlacementSize => ({ width, height, required });\n\nexport const AD_PLACEMENTS: readonly AdPlacement[] = [\n {\n id: \"meta_feed\",\n platform: \"meta\",\n name: \"Facebook and Instagram feeds\",\n sizes: [size(1080, 1350), size(1080, 1080, false)],\n safe: FEED_MARGIN,\n source: \"https://www.facebook.com/business/ads-guide/update/image/instagram-feed\",\n },\n {\n id: \"meta_stories\",\n platform: \"meta\",\n name: \"Facebook and Instagram Stories\",\n sizes: [size(1080, 1920)],\n safe: { top: 0.16, bottom: 0.22, left: 0.04, right: 0.04 },\n cover: { top: 0.09, bottom: 0.15 },\n source: \"https://www.facebook.com/business/ads-guide/update/image/instagram-story\",\n },\n {\n id: \"meta_reels\",\n platform: \"meta\",\n name: \"Facebook and Instagram Reels\",\n sizes: [size(1080, 1920)],\n safe: { top: 0.16, bottom: 0.37, left: 0.04, right: 0.04 },\n cover: { top: 0.09, bottom: 0.32, rail: { width: 0.08, from: 0.6 } },\n railMargin: { width: 0.1, from: 0.55 },\n source: \"https://www.facebook.com/business/ads-guide/update/image/instagram-reels\",\n },\n {\n id: \"meta_right_column\",\n platform: \"meta\",\n name: \"Facebook right column, Marketplace and search results\",\n sizes: [size(1080, 1080), size(1200, 628, false)],\n safe: FEED_MARGIN,\n optIn: true,\n source: \"https://www.facebook.com/business/ads-guide/update/image/facebook-right-column\",\n },\n {\n id: \"google_display_responsive\",\n platform: \"google_display\",\n name: \"Responsive display ads (Google Display Network)\",\n sizes: [size(1200, 628), size(1200, 1200), size(900, 1600, false)],\n safe: FEED_MARGIN,\n rule: \"Text may cover at most 20% of the image; Google crops up to 5% from each side.\",\n source: \"https://support.google.com/google-ads/answer/9823397\",\n },\n {\n id: \"google_display_banners\",\n platform: \"google_display\",\n name: \"Uploaded display banners\",\n sizes: [\n size(300, 250),\n size(728, 90),\n size(320, 50),\n size(336, 280, false),\n size(300, 600, false),\n size(160, 600, false),\n size(320, 100, false),\n size(970, 250, false),\n ],\n safe: FEED_MARGIN,\n rule: \"Each banner is exactly its pixel size, 150 KB at most.\",\n source: \"https://support.google.com/google-ads/answer/7031480\",\n },\n {\n id: \"google_pmax\",\n platform: \"google_pmax\",\n name: \"Performance Max asset group\",\n sizes: [size(1200, 628), size(1200, 1200), size(960, 1200, false)],\n safe: FEED_MARGIN,\n rule: \"Google crops up to 5% from each side; keep text and logos off the edges.\",\n source: \"https://support.google.com/google-ads/answer/13676244\",\n },\n {\n id: \"google_demandgen\",\n platform: \"google_demandgen\",\n name: \"Demand Gen (YouTube, Discover, Gmail)\",\n sizes: [size(1200, 628), size(1200, 1200), size(960, 1200, false)],\n safe: FEED_MARGIN,\n source: \"https://support.google.com/google-ads/answer/13547298\",\n },\n {\n id: \"google_search_images\",\n platform: \"google_search\",\n name: \"Image assets on Search ads\",\n sizes: [size(1200, 1200), size(1200, 628, false)],\n safe: FEED_MARGIN,\n rule: \"No overlaid text, logos or buttons on the image.\",\n source: \"https://support.google.com/google-ads/answer/12118270\",\n },\n {\n id: \"youtube_feed\",\n platform: \"youtube\",\n name: \"YouTube home and watch-next feeds\",\n sizes: [size(1200, 628), size(1200, 1200, false)],\n safe: FEED_MARGIN,\n source: \"https://support.google.com/google-ads/answer/13547298\",\n },\n {\n id: \"youtube_shorts\",\n platform: \"youtube\",\n name: \"YouTube Shorts\",\n sizes: [size(1080, 1920)],\n safe: { top: 0.12, bottom: 0.35, left: 0.05, right: 0.05 },\n cover: { top: 0.08, bottom: 0.3, rail: { width: 0.14, from: 0.45 } },\n railMargin: { width: 0.16, from: 0.4 },\n source: \"https://support.google.com/youtube/answer/10059070\",\n },\n {\n id: \"linkedin_feed\",\n platform: \"linkedin\",\n name: \"LinkedIn feed (single image)\",\n sizes: [size(1200, 1200), size(1200, 627, false), size(720, 900, false)],\n safe: FEED_MARGIN,\n source: \"https://www.linkedin.com/help/lms/answer/a426534\",\n },\n {\n id: \"tiktok_feed\",\n platform: \"tiktok\",\n name: \"TikTok For You feed\",\n sizes: [size(1080, 1920)],\n safe: { top: 0.1, bottom: 0.3, left: 0.06, right: 0.06 },\n cover: { top: 0.07, bottom: 0.25, rail: { width: 0.13, from: 0.45 } },\n railMargin: { width: 0.15, from: 0.4 },\n source: \"https://ads.tiktok.com/help/article/tiktok-ads-safe-zone\",\n },\n {\n id: \"x_timeline\",\n platform: \"x\",\n name: \"X timeline (image and website card)\",\n sizes: [size(1200, 628), size(1200, 1200, false)],\n safe: FEED_MARGIN,\n source: \"https://business.x.com/en/help/campaign-setup/creative-ad-specifications\",\n },\n {\n id: \"reddit_feed\",\n platform: \"reddit\",\n name: \"Reddit feed and conversation pages\",\n sizes: [size(1080, 1080), size(1080, 1350, false), size(1200, 628, false)],\n safe: FEED_MARGIN,\n source: \"https://business.reddithelp.com/s/article/image-ad-specs\",\n },\n {\n id: \"pinterest_feed\",\n platform: \"pinterest\",\n name: \"Pinterest home feed and search (standard pin)\",\n sizes: [size(1000, 1500), size(1000, 1000, false)],\n safe: FEED_MARGIN,\n source: \"https://help.pinterest.com/en/business/article/pinterest-product-specs\",\n },\n {\n id: \"snapchat_snap_ads\",\n platform: \"snapchat\",\n name: \"Snapchat Snap Ads\",\n sizes: [size(1080, 1920)],\n safe: { top: 0.11, bottom: 0.21, left: 0.04, right: 0.04 },\n cover: { top: 0.08, bottom: 0.18 },\n source: \"https://businesshelp.snapchat.com/s/article/single-image-video-specs\",\n },\n {\n id: \"chatgpt_card\",\n platform: \"chatgpt\",\n name: \"ChatGPT sponsored card\",\n sizes: [size(1200, 1200)],\n safe: FEED_MARGIN,\n rule: \"The card shows a square of the image; keep everything that matters inside it.\",\n source: \"https://help.openai.com/en/articles/chatgpt-ads\",\n },\n];\n\nconst RATIOS: ReadonlyArray<[string, number]> = [\n [\"1:1\", 1],\n [\"4:5\", 4 / 5],\n [\"9:16\", 9 / 16],\n [\"16:9\", 16 / 9],\n [\"1.91:1\", 1.91],\n [\"2:3\", 2 / 3],\n [\"3:4\", 3 / 4],\n [\"4:3\", 4 / 3],\n];\n\n/** A size's name: the usual ratio it is (within 1%), else its exact pixels (`728x90`). */\nexport function ratioLabel(width: number, height: number): string {\n const r = width / height;\n const known = RATIOS.find(([, value]) => Math.abs(Math.log(r / value)) < 0.01);\n return known ? known[0] : `${width}x${height}`;\n}\n\nexport type DeliveredFormat = {\n /** A ratio (`4:5`) the static pipeline makes, or exact pixels (`728x90`) for a fixed banner. */\n format: string;\n width: number;\n height: number;\n /** The placements that run this size. */\n placements: string[];\n};\n\nexport type DeliveryPlan = {\n /** The size designed first, the others re-laid out from it: the first platform's lead. */\n lead: string;\n /** The ratios made from the one chosen picture, lead first. */\n formats: DeliveredFormat[];\n /** Fixed-pixel banners the destination requires, made apart (a picture re-laid out cannot reach 728x90). */\n banners: DeliveredFormat[];\n /** The placements a delivered size serves. */\n placements: string[];\n /** Names that are no platform here. */\n unknown: string[];\n /** Sizes asked for that no placement named shows. */\n refused: Array<{ format: string; why: string }>;\n /** Placements a narrower ask leaves without a size of theirs: they show a cropped picture. */\n cropped: string[];\n};\n\n/**\n * Every placement of these platforms, or the placements named themselves. A platform's opt-in\n * placements come only when named by their id.\n */\nexport function placementsFor(names: readonly string[]): { placements: AdPlacement[]; unknown: string[] } {\n const placements: AdPlacement[] = [];\n const unknown: string[] = [];\n for (const raw of names) {\n const name = raw.trim().toLowerCase();\n if (!name) continue;\n const found = AD_PLACEMENTS.filter((p) => p.id === name || (p.platform === name && !p.optIn));\n if (found.length === 0) unknown.push(raw.trim());\n for (const p of found) if (!placements.includes(p)) placements.push(p);\n }\n return { placements, unknown };\n}\n\n/** Adds one placement's size to the list it belongs in, merged with the same format already there. */\nfunction addSize(into: DeliveredFormat[], format: string, size: PlacementSize, placement: string): void {\n const existing = into.find((f) => f.format === format);\n if (!existing) {\n into.push({ format, width: size.width, height: size.height, placements: [placement] });\n return;\n }\n if (!existing.placements.includes(placement)) existing.placements.push(placement);\n if (size.width > existing.width) Object.assign(existing, { width: size.width, height: size.height });\n}\n\n/** The lead of the first name: its platform's, or the first required size of a placement named by id. */\nfunction leadOf(names: readonly string[]): string | undefined {\n for (const raw of names) {\n const name = raw.trim().toLowerCase();\n if (name in AD_PLATFORM_LEAD) return AD_PLATFORM_LEAD[name as AdPlatform];\n const placement = AD_PLACEMENTS.find((p) => p.id === name);\n const first = placement?.sizes.find((s) => s.required);\n if (first) return ratioLabel(first.width, first.height);\n }\n return undefined;\n}\n\nfunction leadFirst(formats: DeliveredFormat[], lead: string | undefined): DeliveredFormat[] {\n const at = formats.findIndex((f) => f.format === lead);\n return at <= 0 ? formats : [formats[at] as DeliveredFormat, ...formats.filter((_, i) => i !== at)];\n}\n\n/**\n * The sizes an ad running in these platforms (or placements) is delivered in, lead first: every\n * required size of their placements, unioned. `asked` replaces that set with exactly the sizes\n * named: each must be shown by some placement (else `refused`), and a placement left with none of\n * its sizes is `cropped`, so a narrower ask is honoured and says what it costs.\n */\nexport function deliveryPlan(names: readonly string[], asked?: readonly string[]): DeliveryPlan {\n const { placements, unknown } = placementsFor(names);\n const { required, shown, banners } = sizesOf(placements);\n const { formats, refused } =\n asked && asked.length > 0 ? askedSizes(asked, shown, placements) : { formats: required, refused: [] };\n const platformLead = leadOf(names);\n const lead = formats.some((f) => f.format === platformLead) ? platformLead : formats[0]?.format;\n const delivered = leadFirst(formats, lead);\n const served = new Set(delivered.flatMap((f) => f.placements));\n return {\n lead: lead ?? \"\",\n formats: delivered,\n banners,\n placements: placements.map((p) => p.id).filter((id) => served.has(id)),\n unknown,\n refused,\n cropped: placements.filter((p) => ratioSized(p) && !served.has(p.id)).map((p) => p.id),\n };\n}\n\n/** The placements' sizes by kind: the required ratios, every ratio they show, the required banners. */\nfunction sizesOf(placements: readonly AdPlacement[]) {\n const required: DeliveredFormat[] = [];\n const shown: DeliveredFormat[] = [];\n const banners: DeliveredFormat[] = [];\n for (const placement of placements) {\n for (const s of placement.sizes) {\n const format = ratioLabel(s.width, s.height);\n if (isBanner(format)) {\n if (s.required) addSize(banners, format, s, placement.id);\n continue;\n }\n addSize(shown, format, s, placement.id);\n if (s.required) addSize(required, format, s, placement.id);\n }\n }\n return { required, shown, banners };\n}\n\n/** Exactly the sizes asked for, each one some placement shows; the rest refused with why. */\nfunction askedSizes(asked: readonly string[], shown: readonly DeliveredFormat[], placements: readonly AdPlacement[]) {\n const where = [...new Set(placements.map((p) => AD_PLATFORM_NAMES[p.platform]))].join(\" or \") || \"No placement named\";\n const formats: DeliveredFormat[] = [];\n const refused: DeliveryPlan[\"refused\"] = [];\n for (const format of new Set(asked.map((f) => f.trim()))) {\n const found = shown.find((f) => f.format === format);\n if (found) formats.push(found);\n else refused.push({ format, why: `${where} shows no ${format} picture` });\n }\n return { formats, refused };\n}\n\nconst isBanner = (format: string) => format.includes(\"x\");\n/** A placement that runs a picture re-laid out, not only fixed-pixel banners. */\nconst ratioSized = (p: AdPlacement) => p.sizes.some((s) => s.required && !isBanner(ratioLabel(s.width, s.height)));\n\n/**\n * What the interfaces of these vertical placements cover together: the larger share at each\n * edge, the wider and longer button rail. Null when none of them draws over the picture.\n */\nexport function verticalCover(\n placementIds: readonly string[],\n): (InterfaceCover & { safe: EdgeShares; railMargin?: ButtonRail }) | null {\n const covering = AD_PLACEMENTS.filter((p) => placementIds.includes(p.id) && p.cover);\n if (covering.length === 0) return null;\n const max = (pick: (p: AdPlacement) => number | undefined) => Math.max(...covering.map((p) => pick(p) ?? 0));\n const rails = covering.filter((p) => p.cover?.rail);\n const margins = covering.filter((p) => p.railMargin);\n return {\n top: max((p) => p.cover?.top),\n bottom: max((p) => p.cover?.bottom),\n ...(rails.length > 0\n ? {\n rail: {\n width: max((p) => p.cover?.rail?.width),\n from: Math.min(...rails.map((p) => p.cover?.rail?.from ?? 1)),\n },\n }\n : {}),\n ...(margins.length > 0\n ? {\n railMargin: {\n width: max((p) => p.railMargin?.width),\n from: Math.min(...margins.map((p) => p.railMargin?.from ?? 1)),\n },\n }\n : {}),\n safe: {\n top: max((p) => p.safe.top),\n bottom: max((p) => p.safe.bottom),\n left: max((p) => p.safe.left),\n right: max((p) => p.safe.right),\n },\n };\n}\n","/**\n * How a static ad is read to be rebuilt: the focus the describe pass adds to the backend's\n * Visual Architect prompt, and the pass that picks the identity-critical elements a rebuild must\n * ground in real assets. Shared by the CLI, which reads a company's own picture, and the backend,\n * which reads each library ad once for every company (`adLibrary/referenceReads.ts`).\n */\n\n/**\n * The version of a library ad's stored read: bump it when the focus, the select pass or the\n * describe schema changes, so every ad is read again in the new shape.\n */\nexport const AD_READ_VERSION = \"1\";\n\nexport const AD_DESCRIBE_FOCUS =\n \"FIRST, WHY THIS AD WINS, in layers, in `why_it_wins` { disguise (what it pretends to be: a note, a tweet, a \" +\n \"newspaper, a chat, a plain ad), voice (who speaks, and how), trigger (the emotion or need it pulls: a free gift, a \" +\n \"hidden loss, status, curiosity), attention (what stops the scroll), logic (why it convinces: reciprocity, social \" +\n \"proof, a comparison, a price anchor) }, one short phrase each; and in `load_bearing` the 1-4 elements it stops \" +\n \"working without (never decoration), each { element, needs: what it takes to carry it } (a free gift, a real peer's \" +\n \"face, priced tiers, a native disguise). THEN the LAYOUT: the column/row grid, which region holds what (describe each by what fills it and where it \" +\n \"sits, never by percentages or pixel figures), any panel splits, and for EVERY text block its string verbatim, \" +\n \"its size relative to the other text (x_large | large | medium | small), weight, case, colour in words, and \" +\n \"placement, including small bottom-corner fine print, and whether it is lettered on something in the scene \" +\n \"(`surface`). Also: the EXPRESSION and emotion of every person/animal (capture exaggerated or AI-edited faces), \" +\n \"the ad_intent, logos by brand, and all visible text verbatim. \" +\n \"The TYPOGRAPHY as a first-class identity signal: for EVERY distinct typeface record a `fonts` entry (which text \" +\n \"blocks use it, its classification, a best-guess family or close lookalike, its weight/case/styling), and whether \" +\n \"the advertiser's LOGO appears in more than one lockup (a square/icon MARK and a horizontal WORDMARK are two \" +\n \"assets: capture BOTH). Capture as a photographer would describe it in words (phone or studio, the height and \" +\n \"angle, the light and its direction), never as lens or exposure figures. \" +\n \"CRITICAL: name the MECHANISM, the one device that makes THIS ad work on a stranger rather than a generic ad \" +\n \"(VERBAL: a rhyme, pun, repetition, antithesis; VISUAL: an unexpected crop or scale, a visual gag, a before/after \" +\n \"or comparison, bold negative space; STRUCTURAL: an unusual hook, order or reveal). Record every device in \" +\n \"`winning_mechanisms` as { kind: verbal|visual|structural, device, why_it_works } and the strongest one in \" +\n \"`mechanism`. And read WHO the ad is for, in `audience`: the viewer it speaks to, their awareness stage, how warm \" +\n \"they must already be, and whether the copy only works if they already know this brand or offer \" +\n \"(`presumes_brand_knowledge`), so a rebuild for a different audience knows what to change\";\n\nexport const AD_SELECT_SYSTEM =\n \"You identify the MAIN, identity-critical visual elements of an advertisement from its JSON blueprint — the things \" +\n \"a faithful reproduction must supply as REAL reference images instead of letting a model invent them. Output ONLY a \" +\n 'JSON object of the form { \"elements\": [ ... ] }, no prose.';\n\nexport const AD_SELECT_PROMPT =\n \"AD BLUEPRINT (from image_describe):\\n{{blueprint}}\\n\\n\" +\n \"From this blueprint, list ONLY the elements that are prominent, important, and identity-bearing — the ones a \" +\n \"reproduction must ground in a real asset:\\n\" +\n '- the brand logo/wordmark (from brands_logos with function_in_image = advertiser_brand) -> type \"logo\". A brand ' +\n \"often ships its logo in TWO lockups — a square/icon MARK and a horizontal WORDMARK — and an ad may use both (e.g. \" +\n \"an icon in a product mock plus the wordmark in the sign-off). When more than one distinct lockup of the SAME \" +\n \"advertiser appears, emit a SEPARATE logo element for each (label them by lockup, e.g. LOGO_MARK and LOGO_WORDMARK) \" +\n \"so the reproduction can drop the right file in each slot instead of stretching one logo to cover both.\\n\" +\n \"- trust/rating/certification/app-store/review badges (brands_logos with function_in_image = trust_badge | \" +\n 'review_platform | certification_or_seal | app_store_badge | payment_method) -> type \"badge\"\\n' +\n '- a showcased/hero product or package (a foreground entry in subjects that the ad is selling) -> type \"product\"\\n' +\n \"- a foreground person (from people) — keep it when its identity matters OR it is the emotional/hero focal \" +\n 'point of the ad, even a generic one with no brand identity -> type \"person\". Describe them as a castable, ' +\n \"invented everyday person (age band, look, wardrobe, expression) — never the source person's identity: unless \" +\n \"a company avatar is cast, the render draws this person from your words alone\\n\" +\n \"- a foreground animal/character (from subjects) — keep it when it carries a specific expression OR it is the \" +\n 'emotional/hero focal point, even a generic one -> type \"animal\"\\n' +\n \" (For an animal: a free-generated muzzle or teeth reads as AI and grows artifacts — malformed mouths, \" +\n \"foam — so the emotional hero needs the STRONGEST real grounding, not the weakest; \\\"it's just a generic \" +\n 'dog/person\" is never a reason to drop either.)\\n\\n' +\n \"DROP background extras, decorative props, generic scenery, and anything small or incidental. Keep at most ~6. \" +\n \"If there are none, return an empty list.\\n\\n\" +\n 'For each kept element return: { \"type\": one of logo|product|person|animal|badge, \"label\": a short ' +\n 'UPPER_SNAKE_CASE name (e.g. LOGO, PRODUCT, HERO_DOG, TRUSTPILOT), \"description\": a concrete reusable description ' +\n \"to source/shoot the real asset (include the exact expression for a living subject, and its castable attributes \" +\n \"— breed/species for an animal, apparent age band, apparent origin/ethnicity, and wardrobe/setting for a person — \" +\n 'so it can be recast to fit OUR audience/market), \"expression\": the facial ' +\n 'expression for a living subject or null, \"reason\": why it is identity-critical, \"locator\": the blueprint entry ' +\n 'this element came from as { \"collection\": one of \"subjects\" | \"people\" | \"brands_logos\", \"index\": its 0-based ' +\n \"position in that array } (people -> people; logos/badges -> brands_logos; products/animals/objects -> subjects). \" +\n \"Output ONLY the JSON object.\";\n","/**\n * Take the cast's NAME out of the prompts, leaving the person in.\n *\n * Gemini refuses \"real people's names or likenesses\" — one filter covering both — and an\n * agent writes prompts the way a person would: \"Carmen on camera, relaxed and\n * reassuring\". Observed on a real ad: five clips rendered, the sixth came back\n * CONTENT_POLICY_BLOCKED, and the only thing separating them was luck, because every one\n * of them named her.\n *\n * The name buys the model nothing. The face arrives as a reference image and the identity\n * sheet carries the description; the name is decoration that happens to trip a filter. So\n * it is replaced rather than removed — a brief that reads \"on camera, relaxed\" with no\n * subject at all is a worse prompt than one that says who is in shot.\n *\n * Whole words only, and case-insensitively: \"Carmen\" goes, \"carmengarcia\" stays.\n */\nexport function withoutCastName(text: string, names: readonly string[]): string {\n let out = text;\n for (const name of names) {\n const token = name.trim();\n if (token.length < 3) continue;\n const pattern = new RegExp(`(?<![\\\\p{L}\\\\p{N}])${escapeForPattern(token)}(?![\\\\p{L}\\\\p{N}])`, \"giu\");\n out = out.replace(pattern, \"the person in the reference\");\n }\n return out;\n}\n\nfunction escapeForPattern(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","/**\n * Ad-platform → aspect-ratio presets for the `image_aspect_adapt` node.\n *\n * A creative is authored at ONE base ratio; fanning it out to every placement\n * a platform expects is mechanical, but the ratio set is easy to misremember.\n * These presets name the platform once and expand to the canonical set, so the\n * agent (and the node) never hand-list ratios from memory.\n *\n * Only **on-grid** ratios (a subset of the node's `ASPECT_ADAPT_FORMATS`) are\n * emitted — the node renders those directly, and formats that already match the\n * source ratio pass through free. Off-grid targets a platform also accepts\n * (e.g. Google's 1.91:1 landscape) are recorded in `offGrid` for a follow-up\n * `baker images crop` pass; they are NOT rendered by the adapt node.\n *\n * Shared by the CLI node (cost estimate) and the backend handler (expansion),\n * so both price and run a `platform` request identically.\n */\n\nexport const AD_FORMAT_PLATFORMS = [\n \"meta_feed\",\n \"meta_feed_stories\",\n \"meta_all\",\n \"linkedin\",\n \"google_search\",\n \"google_demandgen\",\n \"tiktok\",\n \"youtube\",\n] as const;\n\nexport type AdFormatPlatform = (typeof AD_FORMAT_PLATFORMS)[number];\n\nexport type AdPlatformPreset = {\n /** On-grid target ratios the adapt node renders (source-matching ones pass through free). */\n readonly formats: readonly string[];\n /** Ratios the platform also accepts that the node can't render directly — crop from the nearest rendered format. */\n readonly offGrid?: readonly string[];\n /** One-line, agent-facing description of the set. */\n readonly note: string;\n};\n\nexport const AD_PLATFORM_FORMAT_PRESETS: Record<AdFormatPlatform, AdPlatformPreset> = {\n meta_feed: { formats: [\"4:5\"], note: \"Meta/Instagram feed static.\" },\n meta_feed_stories: { formats: [\"4:5\", \"9:16\"], note: \"Meta feed + Stories/Reels.\" },\n meta_all: { formats: [\"4:5\", \"9:16\", \"1:1\"], note: \"Meta feed + Stories/Reels + square.\" },\n linkedin: { formats: [\"1:1\"], note: \"LinkedIn single-image feed (square).\" },\n google_search: {\n // Search image assets: 1:1 is the required one, 1.91:1 the optional landscape.\n // 16:9 is rendered only as the crop source for that landscape — Search never serves 16:9 itself.\n formats: [\"1:1\", \"16:9\"],\n offGrid: [\"1.91:1\"],\n note: \"Google Search image assets (the image extension on a text ad); 1:1 required, 1.91:1 landscape — crop that from the rendered 16:9. Stage 3+ per campaign.\",\n },\n google_demandgen: {\n // Renders 16:9 too so the off-grid 1.91:1 landscape has a native source to crop from.\n formats: [\"1:1\", \"4:5\", \"16:9\"],\n offGrid: [\"1.91:1\"],\n note: \"Google Demand Gen; also wants 1.91:1 landscape — crop that from the rendered 16:9.\",\n },\n tiktok: { formats: [\"9:16\"], note: \"TikTok full-screen vertical.\" },\n youtube: { formats: [\"16:9\"], note: \"YouTube in-stream / companion display.\" },\n};\n\n/** The canonical on-grid ratio set the node should render for a platform. */\nexport function platformFormats(platform: AdFormatPlatform): readonly string[] {\n return AD_PLATFORM_FORMAT_PRESETS[platform].formats;\n}\n\n/**\n * The target ratios an `image_aspect_adapt` node renders: a `platform` preset\n * expanded to its canonical set, or the explicit `formats` list. The CLI (cost\n * estimate) and the backend (dispatch) both resolve through this one function\n * so they price and run a `platform` request identically.\n */\nexport function resolveAdaptFormats(params: {\n formats?: readonly string[];\n platform?: AdFormatPlatform;\n}): readonly string[] {\n if (params.platform) return platformFormats(params.platform);\n return params.formats ?? [];\n}\n","/**\n * Model registry — single source of truth for per-model capabilities.\n *\n * Curated for the ad-creative use case. The canvas-engine runs inside the\n * controlled E2B sandbox (see `packages/e2b-template/src/template.ts`); we\n * expose a small, opinionated set of models rather than the full provider\n * catalogue. Param names here are CANONICAL — one name per concept across\n * all models. Provider-specific shapes get translated at the backend adapter\n * layer.\n *\n * Consumed by:\n * - the engine's pre-run validator (`validateModelParams`)\n * - the dashboard model picker (param controls + input slot icons)\n * - the backend handlers (defence-in-depth, when wired)\n */\n\nimport { AD_FORMAT_PLATFORMS } from \"./adPlatformFormats\";\n\nexport type ParamSchema =\n | { kind: \"string\"; enum?: readonly string[]; maxLength?: number }\n | { kind: \"number\"; enum?: readonly number[]; min?: number; max?: number; integer?: boolean }\n | { kind: \"boolean\" }\n | { kind: \"json\" };\n\nexport type InputKind = \"image\" | \"video\" | \"audio\";\n\n/**\n * A single input slot the model can consume. `mimes` is the set of MIME types\n * the provider accepts for that kind — used by Stage 3 pre-flight MIME\n * enforcement (a mime mismatch between source output and sink accepted set is\n * a `mime_not_accepted` validation error).\n */\ntype InputSpec = {\n kind: InputKind;\n mimes?: readonly string[];\n /**\n * How many assets the provider accepts in this slot. Read off the live\n * schemas, where the spread is wide and consequential: gpt-image-2 takes 16\n * references, the Gemini image models 14, and Recraft exactly ONE. A caller who\n * wires four references to Recraft is not slightly over — they get a\n * pre-dispatch 400 for every take in the batch.\n *\n * Absent = the provider advertises no cap we have confirmed. Absent means\n * UNGATED, never \"one\": guessing a ceiling refuses renders that would have\n * worked, and a refusal you invented is worse than a limit you never had.\n */\n max?: number;\n};\n\n/** Who serves a model. `google-interactions` is Google's own API (Omni), not OpenRouter. */\nexport type ModelProvider =\n | \"openrouter\"\n | \"replicate\"\n | \"google-interactions\"\n | \"elevenlabs\"\n | \"fal\"\n | \"groq\"\n | \"deepgram\";\n\n/** A provider and the id the model goes by on that provider's wire. */\nexport type ProviderRoute = { provider: ModelProvider; wireModel: string };\n\n/** A route as written in the registry: an absent `wireModel` means the registry id IS the wire id. */\ntype RouteSpec = { provider: ModelProvider; wireModel?: string };\n\n/** Published $/second for a clip, silent and with sound, with per-resolution overrides. */\nexport type VideoSecondRate = {\n silent: number;\n audio: number;\n byResolution?: Readonly<Record<string, { silent: number; audio: number }>>;\n};\n\n/**\n * Pricing that lives in a formula rather than in a number on the entry: a token\n * count derived from the frame (Seedance, Omni) or a per-unit rate on units only the\n * provider measures (ElevenLabs characters, lipsync minutes). The formula itself is\n * in `videoCost.ts` / `nodeCost.ts`; naming it here is what makes a model's price\n * findable from its entry.\n */\nexport type BillingFormula =\n | \"seedance-2.0\"\n | \"seedance-2.5\"\n | \"gemini-omni\"\n | \"elevenlabs-characters\"\n | \"elevenlabs-music-seconds\"\n | \"elevenlabs-sound-effect-seconds\"\n | \"elevenlabs-voice-convert-minutes\"\n | \"lipsync-minutes\"\n | \"video-background-remove-frames\"\n | \"image-background-remove-call\"\n | \"transcription\";\n\n/**\n * How a model is priced. `usage` is explicit, not a missing price: the provider\n * reports what the call cost afterwards (every OpenRouter text, vision and image\n * call), so there is no number to quote up front.\n */\nexport type ModelBilling =\n | { kind: \"usage\" }\n | {\n kind: \"per_second\";\n usd: VideoSecondRate;\n /** Seconds billed however short the clip is, where the provider bills a floor. */\n minBilledSeconds?: number;\n }\n | { kind: \"formula\"; formula: BillingFormula };\n\nconst OPENROUTER_ROUTE: RouteSpec = { provider: \"openrouter\" };\nconst USAGE_BILLED: ModelBilling = { kind: \"usage\" };\n\n/**\n * Some providers bill a floor regardless of how short the clip is. Measured,\n * not published: a 4s Wan 2.7 clip billed $0.50 against a $0.10/s rate, and a 3s\n * HappyHorse clip billed $0.494 against $0.0988/s, both exactly five seconds'\n * worth. Declared per model (`minBilledSeconds`), because it was only OBSERVED on\n * the two Alibaba models.\n */\nexport const MIN_BILLED_SECONDS = 5;\n\n/**\n * The fal route Seedance clips are re-rendered on when ByteDance's face filter\n * refuses a reference-guided one: Seedance 2.5 under a licence that takes faces,\n * whichever Seedance tier was asked for. See `convex/lib/falSeedance.ts`.\n */\nexport const SEEDANCE_FACE_RECOVERY_ROUTE: ProviderRoute = {\n provider: \"fal\",\n wireModel: \"bytedance/seedance-2.5/reference-to-video\",\n};\n\ntype ModelSpec = {\n /** Human label shown in the model picker. */\n label: string;\n /** The provider that serves this model and its id there. */\n route: RouteSpec;\n /** How a call is priced; see `ModelBilling`. */\n billing: ModelBilling;\n /** A second route the backend falls back to for a refusal the first route cannot serve. */\n recoveryRoute?: ProviderRoute;\n /** Input slots the canvas MUST wire up for this model to run. */\n inputs: readonly InputSpec[];\n /**\n * Input slots the model can use if provided but does not require. The UI\n * shows icons for these as drop-targets; the validator does not require\n * them.\n */\n optional_inputs?: readonly InputSpec[];\n /** Canonical param names that MUST be present. */\n required: readonly string[];\n /** Allowed params keyed by canonical name + per-param schema. */\n params: Readonly<Record<string, ParamSchema>>;\n};\n\nexport type NodeKind =\n | \"text_generate\"\n | \"image_aspect_adapt\"\n | \"image_describe\"\n | \"image_generate\"\n | \"image_reference_sheet\"\n | \"image_select\"\n | \"video_generate\"\n | \"video_deconstruct\"\n | \"video_lipsync\"\n | \"tts\"\n | \"audio_voice_convert\"\n | \"music\"\n | \"dialogue\"\n | \"sound_effect\";\n\n// ---------------------------------------------------------------------------\n// Shared enums\n// ---------------------------------------------------------------------------\n\nconst OPENROUTER_IMAGE_AR = [\"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"4:5\", \"5:4\", \"9:16\", \"16:9\", \"21:9\"] as const;\nconst OPENROUTER_IMAGE_AR_EXTREME = [...OPENROUTER_IMAGE_AR, \"1:4\", \"4:1\", \"1:8\", \"8:1\"] as const;\n\n// gpt-image-2 accepts a NARROWER ratio set than every other image model here —\n// notably no 4:5 or 5:4, which are the Meta/Instagram feed portrait formats.\n// OpenRouter rejects an unlisted ratio with a pre-dispatch 400\n// (\"aspect_ratio: not supported. Accepted: 1:1, 3:2, 2:3, 4:3, 3:4, 16:9, 9:16,\n// 21:9, auto\"), so portrait ad formats must come from `image_aspect_adapt` on a\n// Gemini model rather than straight out of gpt-image-2.\n// Source: GET /api/v1/images/models/openai/gpt-image-2/endpoints.\nconst OPENROUTER_IMAGE_AR_GPT = [\"1:1\", \"2:3\", \"3:2\", \"3:4\", \"4:3\", \"9:16\", \"16:9\", \"21:9\"] as const;\n\n// ---------------------------------------------------------------------------\n// Hard provider ceilings.\n//\n// Every number below is quoted from the provider's own schema, not from a blog\n// post or from memory, and each one is a failure we would otherwise only find by\n// paying for it: an over-length prompt is a 4xx AFTER the batch is open and the\n// tiles are spinning, which reads to the user as \"it broke, try again\" and gets\n// retried identically. Declared here, the same request is refused for free with\n// the number to cut to.\n//\n// Sources (re-check these before editing a number):\n// OpenAI openai/openai-openapi `CreateImageRequest.prompt` — \"32000\n// characters for the GPT image models\".\n// Recraft API appendix — 10,000 characters for the V4/V4.1 family (the 1,000\n// everyone quotes is the retired V2/V3 limit).\n// Replicate GET /v1/models/bytedance/seedance-2.0 → `prompt.maxLength: 4000`.\n// Kling API reference — prompt and negative_prompt cap at 2,500 each.\n// Vertex Veo reference — `seed` is a uint32, \"accepted range 0-4294967295\".\n// ---------------------------------------------------------------------------\nconst GPT_IMAGE_PROMPT_MAX = 32_000;\nconst RECRAFT_PROMPT_MAX = 10_000;\nconst SEEDANCE_PROMPT_MAX = 4_000;\nconst KLING_PROMPT_MAX = 2_500;\n/** Vertex (Veo) and BytePlus (Seedance 2.5) both type `seed` as a uint32. */\nconst UINT32_MAX = 4_294_967_295;\nconst VEO_SEED_MAX = UINT32_MAX;\n\n// Reference-image ceilings, from `input_references` on each model's live\n// endpoint schema (GET /api/v1/images/models/{id}/endpoints) and from\n// Replicate's `reference_images` description for Seedance.\nconst GPT_IMAGE_MAX_REFERENCES = 16;\nconst GEMINI_IMAGE_MAX_REFERENCES = 14;\nconst RECRAFT_MAX_REFERENCES = 1;\nconst SEEDANCE_MAX_REFERENCES = 9;\n\nconst OPENROUTER_IMAGE_SIZE = [\"1K\", \"2K\", \"4K\"] as const;\n/**\n * `0.5K` is our CANONICAL spelling of the half-size tier; OpenRouter's wire enum\n * calls it `512`, and the backend adapter translates it in `buildImageGenBody`.\n * Sending `0.5K` straight through is a request-schema 400, so the translation is\n * not optional — but the canonical spelling stays `0.5K` so canvases already\n * authored against it keep running.\n *\n * Exported so the engine node schemas and the studio param schema build their\n * enums from this rather than hand-copying the list a fifth time.\n */\nexport const OPENROUTER_IMAGE_SIZES = [\"0.5K\", ...OPENROUTER_IMAGE_SIZE] as const;\nconst OPENROUTER_IMAGE_SIZE_EXTENDED = OPENROUTER_IMAGE_SIZES;\n\n// Nano Banana 2 Lite renders at ONE size. `GET /api/v1/images/models/\n// google/gemini-3.1-flash-lite-image/endpoints` reports `resolution: [\"1K\"]` on\n// both its Google Vertex and Google AI Studio endpoints, and asking for 2K or 4K\n// is a hard 400 (\"resolution: not supported. Accepted: 1K\") — verified live.\nconst GEMINI_LITE_IMAGE_SIZE = [\"1K\"] as const;\n\n// OpenRouter's unified image API forwards a `quality` knob. Only gpt-image actually\n// honors it: OpenRouter's per-endpoint schema lists it for gpt-image and NOT for the\n// Gemini image models, which return an identically-priced 200 whether it is sent or\n// not. So it is declared only on the models that use it — an inert knob elsewhere.\nconst OPENROUTER_IMAGE_QUALITY = [\"auto\", \"low\", \"medium\", \"high\"] as const;\n\n// gpt-image-2.5 is the same model surface as gpt-image-2 in every respect but this: the\n// quality ladder gained two rungs above `high`. Same ratios, same 16 references, same\n// per-token price. Note the price is per OUTPUT TOKEN, so the rungs are not free —\n// a `max` render bills more tokens than a `high` one at an identical rate.\n// Source: GET /api/v1/images/models/openai/gpt-image-2.5-sunburst/endpoints.\nconst OPENROUTER_IMAGE_QUALITY_25 = [\"auto\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\n// Images from ONE call: one request and one wait for N candidates of the same brief. Not\n// cheaper: measured on 2026-09-30, gpt-image-2.5 at n=3 billed exactly 3x n=1, the prompt\n// tokens tripled too. Declared only where a live call proved the model honours it: the\n// Gemini image models refuse it outright (\"n: must be exactly 1\"), and a model that\n// silently returned one image would leave a pick with nothing to choose. OpenRouter's\n// ceiling is 10. Read it through `maxImagesPerCall`.\n// Source: https://openrouter.ai/docs/guides/overview/multimodal/image-generation;\n// probes in scripts/creative-evals/.out/probes (n3-*.json).\nconst OPENROUTER_IMAGE_N: ParamSchema = { kind: \"number\", integer: true, min: 1, max: 10 };\n\n// Recraft renders a NARROWER ratio set than the rest of the image roster, and\n// notably has no 4:5 / 5:4 — the Meta and Instagram feed portrait formats. It was\n// declared here with the full OpenRouter set, so asking the vector model for the\n// single most common portrait ad shape was a pre-dispatch 400 on every take.\n// Portrait vector work has to snap to 3:4 (which it now does) or be adapted\n// afterwards through `image_aspect_adapt`.\n// Source: GET /api/v1/images/models/recraft/recraft-v4.1-pro-vector/endpoints.\nconst RECRAFT_IMAGE_AR = [\"1:1\", \"4:3\", \"3:4\", \"16:9\", \"9:16\"] as const;\n\n// Seedance renders EVERY whole second from 4 to 15 — no gaps.\n//\n// Both sources agree: Replicate's schema declares `duration` as an integer with\n// `minimum: -1, maximum: 15` (-1 meaning \"you pick\"), and OpenRouter's catalogue\n// reports `supported_durations: [4…15]`. Take the set from them and nowhere else.\n// A gate stricter than the provider costs no 400 to reveal it, so it silently\n// narrows what the product can make until someone reads the schema.\nexport const SEEDANCE_DURATIONS = [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] as const;\n\n// ---------------------------------------------------------------------------\n// Seedance 2.5 — the long-form, multimodal-reference tier.\n//\n// A DIFFERENT model from 2.0 in every dimension that matters here, and reached a\n// different way: 2.0 is routed through Replicate, 2.5 through OpenRouter's video\n// gateway (provider `seed`), where it is a first-class entry. Every number below\n// is read off `GET /api/v1/videos/models → bytedance/seedance-2.5`, not from the\n// 2.0 entry beside it — they disagree on three of the four gated sets.\n//\n// The trades against 2.0, so a caller can pick on purpose:\n// - LENGTH: every whole second 4-30, against 2.0's 4-15. This is the reason to\n// reach for it — a 30s clip is a whole ad, not a beat.\n// - REFERENCES: up to 50 assets, and they are not all images — 30 images, 10\n// videos, 10 audio. Video references are what make edit/extend possible at\n// all, and no other curated model takes a non-image reference.\n// - RESOLUTION: 480p/720p ONLY. 2.0 goes to 1080p and 4K; 2.5 does not on this\n// route (the higher tiers are a separate upscale product), so a hero beat\n// that must be 1080p still belongs on 2.0 or Veo.\n// - SHAPE: no 9:21. 2.0 has it, 2.5 stops at 21:9.\n// ---------------------------------------------------------------------------\n\n/** Every whole second from 4 to 30 — `supported_durations`, no gaps. */\nexport const SEEDANCE_25_DURATIONS = [\n 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,\n] as const;\n\n/** `supported_aspect_ratios`. Narrower than 2.0's — no 9:21. */\nexport const SEEDANCE_25_ASPECT_RATIOS = [\"1:1\", \"3:4\", \"9:16\", \"4:3\", \"16:9\", \"21:9\"] as const;\n\n/**\n * `supported_resolutions`. Deliberately NOT widened to 1080p/4K: those are real\n * Seedance tiers but they are not on this route, and asking for one is a\n * provider 400 after the batch is open.\n */\nexport const SEEDANCE_25_RESOLUTIONS = [\"480p\", \"720p\"] as const;\n\n/**\n * The multimodal reference budget: 50 assets total, split by kind.\n *\n * Per-kind rather than one number, because the provider enforces them\n * separately — eleven audio clips is refused even with nothing else wired. The\n * split is BytePlus's own published Omni Reference limit and matches the model\n * description's \"up to 50 image, video, and audio reference assets\".\n */\nexport const SEEDANCE_25_MAX_IMAGE_REFERENCES = 30;\nexport const SEEDANCE_25_MAX_VIDEO_REFERENCES = 10;\nexport const SEEDANCE_25_MAX_AUDIO_REFERENCES = 10;\n\n// Kling accepts ANY whole second from 3 to 15 (OpenRouter\n// GET /api/v1/videos/models), gaps included.\nexport const KLING_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] as const;\n\n// ---------------------------------------------------------------------------\n// Gemini Omni Flash — length is PROMPTED, not parameterised.\n//\n// Omni takes no `duration` field anywhere in its request (every spelling, at\n// every nesting level, is rejected with `Unknown parameter`). It does honour a\n// length asked for IN THE PROMPT: verified live, \"exactly 3 seconds\" returned\n// 3.008s and \"exactly 6 seconds\" returned 6.016s, against a 10.005s default when\n// the prompt names no length.\n//\n// So `duration` IS a canvas param for this model — the backend adapter translates\n// it into a prompt directive instead of a body field, exactly the canonical-name /\n// provider-shape split this registry is built on.\n// ---------------------------------------------------------------------------\n\n/**\n * Clip lengths Omni renders. Outside this range it does NOT fail — it silently\n * snaps (2s came back 3.008s, 15s came back 10.005s), which is worse than a\n * rejection: you are billed for the length you got, not the one you asked for.\n * Gate it here so the snap can't happen unnoticed.\n */\nexport const GEMINI_OMNI_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10] as const;\n\n/** What Omni renders when the prompt names no length — its ceiling, not its floor. */\nexport const GEMINI_OMNI_DEFAULT_SECONDS = 10;\n\n/** The only aspect ratios Omni accepts; anything else is a pre-dispatch 400. */\nexport const GEMINI_OMNI_ASPECT_RATIOS = [\"16:9\", \"9:16\"] as const;\n\n/**\n * The resolutions Omni 1.1 renders, cheapest first.\n *\n * **1.1 ONLY.** This is the capability that separates the two Omni entries, and\n * the reason they ARE two entries rather than one rolling key: the preview\n * (`google/gemini-omni-flash`) has no resolution knob at all and renders every\n * clip at 720p, so a canvas asking it for 360p is asking for something it does\n * not do. Do NOT add this enum to the legacy entry to \"keep them consistent\" —\n * the inconsistency is the fact being recorded.\n *\n * Read off the API's own enumeration, which is also where the lowercase `4k`\n * comes from: `1080p` and `4K` (the spelling Veo takes) are two different\n * strings and only one of them is accepted here.\n *\n * Cheapest first because `snapToSupported` in the studio lane falls back to the\n * FIRST entry when the current pick is unavailable — landing a model switch on\n * the dearest tier is the expensive direction of that mistake.\n *\n * 360p is the reason this list matters. It renders at exactly a third of the\n * 720p token rate, which makes it the tier for trying a brief out: five drafts\n * at 360p cost less than two takes at 720p, and the composition, pacing and\n * audio you are judging all survive the smaller frame. 1080p and 4K are\n * upscales of the same render, so they are worth paying for on the take you\n * keep, not on the ones you are choosing between.\n */\nexport const GEMINI_OMNI_RESOLUTIONS = [\"360p\", \"720p\", \"1080p\", \"4k\"] as const;\n\n/**\n * Image mimes allowed on an Omni `image` input part. Deliberately the narrow\n * intersection of Gemini's documented image inputs and what we have actually\n * rendered with (PNG, verified end-to-end). `image/gif` is excluded because it\n * is absent from Gemini's documented input set — we have NOT observed a refusal,\n * so this is a conservative gate, and conservative is the free direction: an\n * over-narrow list fails in `baker canvas validate` at no cost, whereas an\n * over-wide one fails at dispatch after the call is billed.\n */\nexport const GEMINI_OMNI_IMAGE_MIMES = [\"image/png\", \"image/jpeg\", \"image/webp\"] as const;\n\n// Grok Imagine goes down to a single second — the only model we carry that does.\n// Its listing advertises up to 15s, but REFERENCE-to-video (the only way an\n// avatar reaches it) is capped at 10 and refuses anything longer with a 400:\n// \"Duration 15s exceeds the maximum allowed for reference-to-video, which is\n// 10s.\" Measured. Capped here rather than documented, because the ceiling only\n// shows up on the route we actually use.\nexport const GROK_IMAGINE_DURATIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] as const;\n\n// Wan 2.7 starts at 2s and caps at 10, shorter than the rest.\nexport const WAN_27_DURATIONS = [2, 3, 4, 5, 6, 7, 8, 9, 10] as const;\n\nexport const HAPPYHORSE_DURATIONS = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] as const;\n\n// Wan 3.0 renders 2–30s, three times 2.7's ceiling — every whole second, no gaps.\nexport const WAN_30_DURATIONS = [\n 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,\n] as const;\n\n// Grok Imagine 1.5 advertises 1–15s. Unlike the older Grok there is no\n// reference-to-video route to cap it on, because 1.5 does not have one.\nexport const GROK_IMAGINE_15_DURATIONS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] as const;\n\n// Runway Gen-4.5: 2–10s.\nexport const RUNWAY_45_DURATIONS = [2, 3, 4, 5, 6, 7, 8, 9, 10] as const;\n\n// ElevenLabs `output_format` values the pipeline supports. Constrained to the\n// mp3 family: the backend handlers label every stored audio asset audio/mpeg,\n// so pcm/opus/ulaw would be saved under a wrong mime and break downstream\n// ffmpeg/composition steps. Widen only together with mime handling.\nexport const ELEVENLABS_OUTPUT_FORMATS = [\n \"mp3_22050_32\",\n \"mp3_44100_32\",\n \"mp3_44100_64\",\n \"mp3_44100_96\",\n \"mp3_44100_128\",\n \"mp3_44100_192\",\n] as const;\n\n// Hard validation bounds derived from the backend's per-node cost cap\n// (MAX_CANVAS_NODE_COST_USD = $10): anything above these always dies at\n// dispatch with `cost_limit_exceeded`, so reject it at validation instead.\n// tts/dialogue: $10 / $0.00022 per character. music: $10 / $0.022 per second.\nexport const ELEVENLABS_MAX_TEXT_CHARS = 45_454;\nexport const ELEVENLABS_MAX_MUSIC_LENGTH_MS = 454_545;\n\n/**\n * The Eleven Music ENGINE both music routes run on.\n *\n * Separate from the route names in the registry below — `elevenlabs/music-v1`\n * selects compose and `elevenlabs/video-background-music-v1` selects\n * video-to-music, and canvases already name those, so they keep their names.\n * This is the `model_id` that rides on the wire, which was implicitly `music_v1`\n * (the provider default) until it was measured.\n *\n * Measured on a real client cut before switching — the same three clips, the\n * same brief, only `model_id` different. Over the 25s carrying speech, v1's\n * level wandered **16.3 dB** while v2 held **3.9 dB**; that wander is what a bed\n * disappearing and reappearing under a voice sounds like, and it is what sent an\n * agent round the \"too quiet\" → raise it → \"demasiado alta\" loop. v2 also sits\n * 1.7 dB further out of the 200 Hz–3 kHz speech band, so it masks the voice\n * less, and ends at -32 dBFS where v1 collapses to -50 dB (that fade is what\n * made the tail read as empty). Against it: v2 plays ~5x the note attacks.\n * Judged by ear on both renders before this was changed.\n */\nexport const ELEVENLABS_MUSIC_ENGINE = \"music_v2\";\n\n// ---------------------------------------------------------------------------\n// Accepted-mime sets — keyed by provider transport, not by model.\n// ---------------------------------------------------------------------------\n\nconst OPENROUTER_IMAGE_MIMES = [\"image/png\", \"image/jpeg\", \"image/webp\", \"image/gif\"] as const;\n// Non-image reference assets, today only Seedance 2.5. Kept narrow on purpose:\n// these ride to the provider as a plain URL it has to fetch and decode itself,\n// and an exotic container is a refusal after the clip is queued. MP4/MOV and the\n// mp3 family are what the rest of this pipeline already produces (R2 renders,\n// ElevenLabs speech and music), so the set is exactly what we can actually wire.\nconst OPENROUTER_VIDEO_REFERENCE_MIMES = [\"video/mp4\", \"video/quicktime\", \"video/webm\"] as const;\n// MP3 and WAV only, and the exclusion is the load-bearing part: Seedance refuses\n// an M4A outright (\"the parameter audio format specified in the request is not\n// valid\"), verified live against a real Mux audio rendition. That matters because\n// M4A is exactly what the video library holds — every Mux `audio-only` rendition\n// is one — so the obvious source of a soundtrack in this product is the one\n// format the model will not read.\nconst OPENROUTER_AUDIO_REFERENCE_MIMES = [\"audio/mpeg\", \"audio/mp3\", \"audio/wav\"] as const;\nconst REPLICATE_IMAGE_MIMES = [\"image/png\", \"image/jpeg\", \"image/webp\"] as const;\nconst REPLICATE_VIDEO_MIMES = [\"video/mp4\", \"video/webm\", \"video/quicktime\"] as const;\n// Formats both Mux (frame extraction) and Gemini (multimodal analysis) accept.\nconst DECONSTRUCT_VIDEO_MIMES = [\"video/mp4\", \"video/webm\", \"video/quicktime\"] as const;\nconst REPLICATE_AUDIO_MIMES = [\"audio/wav\", \"audio/mpeg\", \"audio/mp3\"] as const;\n\n// ---------------------------------------------------------------------------\n// Registry\n// ---------------------------------------------------------------------------\n\n/**\n * Canonical, ordered list of `image_generate` model ids. Single source of truth\n * shared by the backend HTTP boundary (`z.enum`) and the CLI `studio generate`\n * command, so the accepted-model set can never drift between them. These MUST\n * stay in sync with the keys of `MODEL_REGISTRY.image_generate` below — the\n * `_assertImageGenerateModelsMatchRegistry` type guard enforces it at compile time.\n */\nexport const IMAGE_GENERATE_MODELS = [\n \"openai/gpt-image-2.5-sunburst\",\n \"openai/gpt-image-2\",\n \"google/gemini-3.1-flash-image\",\n \"google/gemini-3.1-flash-lite-image\",\n \"google/gemini-3-pro-image\",\n \"recraft/recraft-v4.1-pro-vector\",\n] as const;\n\n/**\n * Default image-generation model when a caller doesn't specify one — Nano Banana\n * flash (`google/gemini-3.1-flash-image`): fast iteration, reference\n * editing, and extreme aspect ratios.\n * The `(typeof IMAGE_GENERATE_MODELS)[number]` annotation guarantees at compile\n * time that the default is one of the accepted models. Consumed by the backend\n * `/api/studio/generate` handler so the literal lives in exactly one place.\n */\nexport const DEFAULT_IMAGE_GENERATE_MODEL: (typeof IMAGE_GENERATE_MODELS)[number] = \"google/gemini-3.1-flash-image\";\n\n/**\n * The image model a picture OpenAI's safety system refused is drawn on once more. OpenAI's\n * moderation refuses a picture that shows a real person (Zernio, Oct 2026: a meme template, every\n * render a 400 \"rejected by the safety system\"); Nano Banana draws the same brief and references.\n */\nexport const IMAGE_SAFETY_FALLBACK_MODEL: (typeof IMAGE_GENERATE_MODELS)[number] = \"google/gemini-3.1-flash-image\";\n\n/** The model to draw a refused picture on instead of `model`, or null when its refusal has no other road. */\nexport function imageSafetyFallbackFor(model: string): (typeof IMAGE_GENERATE_MODELS)[number] | null {\n return model.startsWith(\"openai/\") ? IMAGE_SAFETY_FALLBACK_MODEL : null;\n}\n\n/**\n * The price tier of a picture from each image model. Nano Banana Pro renders about three\n * times what the other image models do per picture (measured $0.13 a 2K image), so it is\n * quoted at its own rate. Keyed by every curated id: a new model cannot ship unclassified.\n */\nconst IMAGE_PRICE_TIER: Readonly<Record<(typeof IMAGE_GENERATE_MODELS)[number], \"pro\" | \"standard\">> = {\n \"openai/gpt-image-2.5-sunburst\": \"standard\",\n \"openai/gpt-image-2\": \"standard\",\n \"google/gemini-3.1-flash-image\": \"standard\",\n \"google/gemini-3.1-flash-lite-image\": \"standard\",\n \"google/gemini-3-pro-image\": \"pro\",\n \"recraft/recraft-v4.1-pro-vector\": \"standard\",\n};\n\n/** Credits quoted up front per picture at each price tier (the picture is billed on usage afterwards). */\nexport const IMAGE_TIER_CREDITS = { pro: 20, standard: 5 } as const;\n\n/** The up-front quote of one picture from `model`: Pro's rate for a Pro image model, the plain rate otherwise (an unknown id too). */\nexport function imagePictureCredits(model: string): number {\n const tier =\n (IMAGE_PRICE_TIER as Readonly<Record<string, \"pro\" | \"standard\">>)[canonicalModelId(model)] ?? \"standard\";\n return IMAGE_TIER_CREDITS[tier];\n}\n\n/**\n * Canonical, ordered list of `video_generate` model ids — a deliberately SMALL,\n * curated roster (not a Higgsfield-style catalog). Each slot earns its place as\n * \"the best model for a specific job\":\n * - `google/gemini-omni-1.1-flash` — DEFAULT. Native audio + reference images in\n * one call, 3-10s, and a real quality dial: 360p / 720p / 1080p / 4k at\n * ~$0.034 / $0.101 / $0.152 / $0.304 per second, billed for the seconds it\n * renders. Only a length outside 3-10s or a 1:1 frame still forces a beat off\n * it.\n * - `google/gemini-omni-flash` — LEGACY. The 1.1 preview: 720p only, at the same\n * per-second rate, so it is strictly 1.1 minus the quality dial. Kept so\n * stored canvases re-run verbatim; never pick it for new work.\n * - `bytedance/seedance-2.0` — identity/product workhorse (cheap, strong i2v),\n * and the only Seedance tier that reaches 1080p/4K.\n * - `bytedance/seedance-2.5` — LONG-FORM and MULTIMODAL: 4-30s in one render,\n * and the only curated model that takes video and audio references, so\n * edit/extend and audio-driven beats exist here or nowhere. Capped at 720p.\n * - `google/veo-3.1` — photoreal cine ceiling + real-face fallback (dodges the\n * ByteDance real-person filter).\n * - `google/veo-3.1-fast` — cheap Veo iteration tier.\n * - `kwaivgi/kling-v3.0-pro` — motion-transfer / dynamic multi-shot beats.\n * Kept in sync with the keys of `MODEL_REGISTRY.video_generate` by the\n * `video_generate lists exactly the keys` invariant in `registry.test.ts`.\n */\nexport const VIDEO_GENERATE_MODELS = [\n \"bytedance/seedance-2.0\",\n \"bytedance/seedance-2.5\",\n \"google/gemini-omni-1.1-flash\",\n \"google/gemini-omni-flash\",\n \"google/veo-3.1\",\n \"google/veo-3.1-fast\",\n \"google/veo-3.1-lite\",\n \"kwaivgi/kling-v3.0-pro\",\n \"x-ai/grok-imagine-video\",\n \"x-ai/grok-imagine-video-1.5\",\n \"alibaba/wan-2.7\",\n \"alibaba/wan-3.0\",\n \"runway/gen-4.5\",\n \"alibaba/happyhorse-1.1\",\n] as const;\n\n/**\n * Default video-generation model when a caller doesn't specify one — Gemini Omni\n * Flash. It wins the default slot because it is the only curated model that\n * returns picture AND synchronized audio from a single call, takes reference\n * images, and bills ~$0.101 per second at 720p (a 5s clip ~$0.51, vs ~$2.50 for\n * the same on Seedance) — or a third of that at 360p. Kept as a named constant\n * (not a hardcoded string at call sites) per the model-catalog rule; the CLI\n * scaffolder's scored router can override it per brief, and does — a photoreal\n * on-camera cast still routes to Veo, and a length outside 3-10s must leave this\n * default behind. A beat needing 1080p no longer has to: 1.1 renders it here.\n */\nexport const DEFAULT_VIDEO_GENERATE_MODEL: (typeof VIDEO_GENERATE_MODELS)[number] = \"google/gemini-omni-1.1-flash\";\n\n/**\n * Which models can do REFERENCE-to-video — images used as visual guidance\n * rather than as the exact opening frame. This is the capability an avatar\n * needs: \"here is who she is, now invent a shot of her\".\n *\n * This list is an explicit allow-list, and every entry on it was MEASURED —\n * the model cards are unreliable in both directions, so nothing is here or\n * absent on the strength of documentation alone.\n *\n * Reaching references three different ways: Seedance 2.0 through Replicate,\n * whose wrapper takes `reference_images`; Gemini Omni Flash through Google's own\n * Interactions API, which declares `reference_to_video` as a first-class task;\n * and Seedance 2.5 THROUGH OpenRouter, where `input_references` is a real,\n * honoured field and the submit is reported back as an `r2v` task. So\n * \"OpenRouter means frame-only\" is no longer true as a blanket rule — which is\n * exactly why this stays an allow-list rather than a guess about the route.\n *\n * The avatar entries were probed with a real identity sheet through OpenRouter's\n * `input_references` channel:\n * - `x-ai/grok-imagine-video` — IN. Preserved the face, honoured the requested\n * 9:16, built a new scene from the prompt. Cheapest of them. No audio.\n * - `alibaba/wan-2.7` — IN. Same identity quality and the only one with native\n * audio, so it is the talking-head option — in landscape only.\n * - `alibaba/happyhorse-1.1` — IN. Correct ratio, strong identity, no audio.\n * - `alibaba/wan-2.6`, `minimax/hailuo-2.3` — OUT. They accept the reference and\n * then animate the sheet ITSELF, labels and grid included: they read\n * `input_references` as \"the image to move\", not as identity guidance.\n *\n * Veo and Kling remain frame-only: `GET /api/v1/videos/models` reports\n * `supported_frame_images: [\"first_frame\", \"last_frame\"]` for both and advertises\n * no reference capability at all. OpenRouter's generic body still DEFINES\n * `input_references`, so sending them there is accepted and then quietly produces\n * a request with no usable image conditioning — every clip in the batch, every\n * time. Veo additionally REJECTS an identity sheet handed to it as a first frame\n * (Vertex flags a grid of face close-ups), so its avatar path is always an\n * ordinary in-scene still. Gate on this instead of discovering it one billed\n * refusal at a time.\n */\nexport const REFERENCE_TO_VIDEO_MODELS = [\n \"bytedance/seedance-2.0\",\n \"bytedance/seedance-2.5\",\n \"google/gemini-omni-1.1-flash\",\n \"google/gemini-omni-flash\",\n \"x-ai/grok-imagine-video\",\n \"alibaba/wan-2.7\",\n \"alibaba/happyhorse-1.1\",\n] as const;\n\nexport function supportsReferenceToVideo(model: string): boolean {\n return (REFERENCE_TO_VIDEO_MODELS as readonly string[]).includes(model);\n}\n\n/**\n * Reference-to-video models that accept a HUMAN likeness.\n *\n * Seedance is the exception that forces this second list: it does reference-to-\n * video, and it refuses every request whose reference contains a photoreal face.\n * Routing an avatar to it is a guaranteed, instantaneous failure.\n *\n * IMPORTANT — this list is NOT \"the models that can put an avatar in a clip\".\n * It is the models that can do it **from the identity sheet alone**. An avatar\n * also reaches video the other way: generate a still of them, then animate that\n * still, and there the face is carried by the frame so every frame-capable\n * model qualifies — Veo 3.1 included, and it is excellent at it. Gate on this\n * list only when there is no opening frame to animate.\n */\nexport const AVATAR_VIDEO_MODELS = [\"x-ai/grok-imagine-video\", \"alibaba/wan-2.7\", \"alibaba/happyhorse-1.1\"] as const;\n\nexport function supportsAvatarVideo(model: string): boolean {\n return (AVATAR_VIDEO_MODELS as readonly string[]).includes(model);\n}\n\n/**\n * Models that must never be handed an avatar, by EITHER route.\n *\n * A denylist rather than an allowlist, on purpose. The list above is only the\n * models that take an identity sheet DIRECTLY; every frame-capable model can\n * also carry an avatar the other way — generate an in-scene still of them first,\n * then animate that still, where the face is an ordinary photograph and no\n * reference channel is needed. Veo 3.1 does this beautifully (measured: 9:16,\n * native audio, identity intact). Restricting avatars to the reference-capable\n * three ruled out the best-looking route on no evidence at all.\n *\n * The two entries here are the ones that actually refused:\n * - Seedance classifies pixels, not provenance: it rejects a photoreal face as\n * a reference AND would as a frame, whoever generated it.\n * - Veo 3.1 Lite returned `completed with no output (content may have been\n * filtered)` on the very still Veo 3.1 animated happily from the same URL. A\n * model that swallows the request and bills for nothing is worse than one\n * that errors, so it stays out of avatar work until that changes.\n */\nexport const AVATAR_BLOCKED_VIDEO_MODELS = [\"bytedance/seedance\", \"google/veo-3.1-lite\"] as const;\n\nexport function canCarryAvatar(model: string): boolean {\n return !AVATAR_BLOCKED_VIDEO_MODELS.some((blocked) => model.startsWith(blocked));\n}\n\n/**\n * Default for a clip that has to carry an avatar's face. Grok Imagine measured\n * best on the three things that decide it — identity retention, honouring the\n * requested aspect ratio, and cost — so it is the default; `alibaba/wan-2.7` is\n * the swap when the clip needs native audio.\n */\nexport const DEFAULT_AVATAR_VIDEO_MODEL: (typeof AVATAR_VIDEO_MODELS)[number] = \"x-ai/grok-imagine-video\";\n\n/** Ratios an avatar clip can be rendered in directly, per model, as measured. */\nexport function avatarVideoSupportsVertical(model: string): boolean {\n return model !== \"alibaba/wan-2.7\";\n}\n\n/**\n * Gemini Omni is reached through Google's own Interactions API rather than the\n * OpenRouter video gateway (it is absent from OpenRouter's catalogue entirely).\n * The backend dispatcher branches on this, and the cost/validation layers use it\n * to apply Omni's fixed-output rules.\n */\nexport function isGeminiOmniModel(model: string): boolean {\n return model.startsWith(\"google/gemini-omni\");\n}\n\n/**\n * The catalogue id of the Omni PREVIEW, which is a different model from 1.1 in\n * the two ways that cost money: it has no `resolution` (720p only) and it bills\n * its whole 10s window whatever length it renders.\n *\n * Named rather than spelled inline because the two ids differ by four characters\n * and `startsWith(\"google/gemini-omni\")` matches both — the routing, quoting and\n * param layers all have to tell them apart, and a hand-written comparison that\n * gets it backwards fails silently in the expensive direction.\n */\nexport const GEMINI_OMNI_PREVIEW_MODEL = \"google/gemini-omni-flash\";\n\n/** True for the legacy Omni preview specifically, not for 1.1. */\nexport function isGeminiOmniPreviewModel(model: string): boolean {\n return model === GEMINI_OMNI_PREVIEW_MODEL;\n}\n\n/**\n * Seedance 2.5, which is a DIFFERENT provider route from 2.0 despite the shared\n * family name: 2.5 goes through OpenRouter's video gateway, 2.0 through Replicate.\n *\n * An exact id rather than a prefix, and it earns the extra strictness: a\n * `startsWith(\"bytedance/seedance\")` test here would silently route 2.5 into the\n * Replicate wrapper, which has no video or audio references, no 30s durations and\n * a 4,000-character prompt cap this model does not have — a request that half\n * works is far harder to spot than one that does not.\n */\nexport function isSeedance25Model(model: string): boolean {\n return model === \"bytedance/seedance-2.5\";\n}\n\n/**\n * Which models take a SECOND conditioning image as the clip's closing frame, so\n * the model interpolates real in-shot motion between two authored keyframes.\n *\n * Omni does not: its Interactions API takes ONE image, and a second is dropped\n * silently. That matters to the SCAFFOLDER more than to the render — an end\n * keyframe it will never use is a billed `image_generate` for nothing — so this\n * gates whether the closing frame is generated at all, not just whether it is\n * wired.\n *\n * An allow-list, like `REFERENCE_TO_VIDEO_MODELS`: an unknown model is assumed\n * NOT to take one, because the cost of guessing wrong that way is a slightly\n * looser clip, while guessing the other way bills an image every clip.\n */\nexport const LAST_FRAME_TO_VIDEO_MODELS = [\n \"bytedance/seedance-2.0\",\n \"bytedance/seedance-2.5\",\n \"google/veo-3.1\",\n \"google/veo-3.1-fast\",\n \"kwaivgi/kling-v3.0-pro\",\n] as const;\n\nexport function supportsLastFrame(model: string): boolean {\n return (LAST_FRAME_TO_VIDEO_MODELS as readonly string[]).includes(model);\n}\n\n/**\n * Whether a model reads a reference of a kind that is NOT an image.\n *\n * Derived from the registry's own optional input slots rather than kept as a\n * second allow-list, because — unlike image references — there is no ambiguity to\n * resolve: Veo and Kling declare an optional image slot for their FRAMES, so an\n * image slot cannot tell you whether the model does reference-to-video, but a\n * video or audio slot exists on exactly the models that read one.\n *\n * What they unlock, and why they are worth the plumbing: a VIDEO reference is how\n * edit and extend are expressed at all (there is no separate endpoint — you hand\n * the clip back in as a reference), and an AUDIO reference is what makes a beat\n * cut to a track or a voiceover instead of inventing its own timing. Only\n * Seedance 2.5 takes either today.\n */\nexport function supportsReferenceKind(model: string, kind: InputKind): boolean {\n return inputSlot(\"video_generate\", model, kind) !== undefined;\n}\n\n/**\n * The curated video models that read a reference of this kind, in roster order.\n *\n * Exists so a caller that has to CHOOSE one — the Studio, when a marketer picks a\n * clip to build on and the current model cannot — names it by capability rather\n * than by hardcoding an id at the call site, which is the rule this registry is\n * the source of truth for.\n */\nexport function videoModelsSupportingReferenceKind(kind: InputKind): string[] {\n return VIDEO_GENERATE_MODELS.filter((model) => supportsReferenceKind(model, kind));\n}\n\nexport const MODEL_REGISTRY: Readonly<Record<NodeKind, Readonly<Record<string, ModelSpec>>>> = {\n text_generate: {\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n system: { kind: \"string\" },\n response_format: { kind: \"string\", enum: [\"text\", \"json_object\"] },\n web_search: { kind: \"boolean\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n system: { kind: \"string\" },\n response_format: { kind: \"string\", enum: [\"text\", \"json_object\"] },\n web_search: { kind: \"boolean\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n },\n\n image_describe: {\n // Vision extraction — the Visual Architect system prompt lives on the\n // backend, so there is no `prompt` param; `focus` appends emphasis only.\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest, Vision)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n focus: { kind: \"string\" },\n context: { kind: \"string\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest, Vision)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n focus: { kind: \"string\" },\n context: { kind: \"string\" },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n },\n\n image_select: {\n // Vision judgement — the selection contract (numbered images, JSON\n // response) is baked into the backend prompt; `prompt` carries only the\n // selection criteria. `count` has an engine-side default of 1, so it is\n // not registry-required.\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest, Vision)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n count: { kind: \"number\", min: 1 },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest, Vision)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n count: { kind: \"number\", min: 1 },\n temperature: { kind: \"number\", min: 0, max: 2 },\n max_tokens: { kind: \"number\", min: 1 },\n },\n },\n },\n\n image_generate: {\n // `seed` is omitted on every entry — OpenRouter's `image_config` schema\n // has no `seed` slot for image-gen (different from video-gen), so passing\n // it would be a silent no-op.\n // The direct image model, not the `gpt-5.4-image-2` chat model that emitted\n // images as a side effect. Notable capability gaps vs the Gemini entries:\n // no `image_size` (OpenAI picks the pixel dimensions from the ratio, and a\n // `resolution` is silently ignored) and the narrower `..._AR_GPT` ratio set.\n \"openai/gpt-image-2.5-sunburst\": {\n // Identical to the gpt-image-2 entry below except for the quality ladder and `n`\n // (several images from one call) — the ratio set, the 16-reference ceiling, the missing `image_size` and the reasons\n // `background` / `output_compression` stay undeclared all carry over unchanged.\n label: \"OpenAI GPT Image 2.5\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES, max: GPT_IMAGE_MAX_REFERENCES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\", maxLength: GPT_IMAGE_PROMPT_MAX },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_GPT },\n quality: { kind: \"string\", enum: OPENROUTER_IMAGE_QUALITY_25 },\n n: OPENROUTER_IMAGE_N,\n },\n },\n \"openai/gpt-image-2\": {\n // Its live endpoint also advertises `background` (auto|opaque) and\n // `output_compression` (0-100), which we deliberately do not declare. Not an\n // oversight: a registry param is a promise the whole system keeps — the\n // canvas node schema, the dashboard control, the CLI flag and the cost model\n // all have to carry it — and neither knob changes what the picture IS.\n // Declaring them would widen four surfaces to expose a file-size dial.\n label: \"OpenAI GPT Image 2\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES, max: GPT_IMAGE_MAX_REFERENCES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\", maxLength: GPT_IMAGE_PROMPT_MAX },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_GPT },\n quality: { kind: \"string\", enum: OPENROUTER_IMAGE_QUALITY },\n },\n },\n // The GA Nano Banana ids (2026-06-18). Same surface as the preview ids they replace\n // — read off GET /api/v1/images/models/google/gemini-3.1-flash-image/endpoints and\n // .../gemini-3-pro-image/endpoints — which is why those ids are plain aliases of\n // these (`MODEL_ALIASES`): a canvas moves between them unchanged.\n \"google/gemini-3.1-flash-image\": {\n label: \"Google Gemini 3.1 Flash Image (Nano Banana 2)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES, max: GEMINI_IMAGE_MAX_REFERENCES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_EXTREME },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE_EXTENDED },\n },\n },\n \"google/gemini-3-pro-image\": {\n label: \"Google Gemini 3 Pro Image (Nano Banana Pro)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES, max: GEMINI_IMAGE_MAX_REFERENCES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n // No `quality`: OpenRouter's per-endpoint schema lists it for gpt-image and for\n // NO Gemini image model, pro included. It is accepted-then-dropped, so declaring\n // it invites the scaffolder to emit a param that does nothing.\n },\n },\n \"google/gemini-3.1-flash-lite-image\": {\n // Nano Banana 2 Lite. Same Gemini image family as the flash tier — same\n // extreme aspect-ratio set, same reference editing — at HALF the output-token\n // price ($0.00003 vs $0.00006 per output image token), which makes it the\n // cheap-iteration tier for image work the way `veo-3.1-fast` is for video.\n //\n // The one thing it gives up is resolution: it renders 1K and nothing else.\n // That is a hard provider 400, not a soft clamp, so it is gated here rather\n // than discovered at dispatch. A 2K/4K hero frame belongs on the flash or pro\n // tier. Unlike gpt-image it keeps 4:5 and 5:4, so Meta/Instagram portrait\n // formats still come straight out of it.\n //\n // Reached through the normal OpenRouter image gateway (Google Vertex and\n // Google AI Studio both serve it) — no direct-provider exception needed.\n // Source: GET /api/v1/images/models/google/gemini-3.1-flash-lite-image/endpoints.\n label: \"Google Gemini 3.1 Flash Lite Image\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES, max: GEMINI_IMAGE_MAX_REFERENCES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_EXTREME },\n image_size: { kind: \"string\", enum: GEMINI_LITE_IMAGE_SIZE },\n },\n },\n \"recraft/recraft-v4.1-pro-vector\": {\n // The vector/logo tier, and the odd one out of this roster in three ways.\n // All three are read off its live endpoint schema, and all three are the\n // kind of fact that only shows up as a billed 400 if it is guessed:\n // - it renders FIVE ratios (no 4:5 / 5:4 / 2:3 / 3:2 / 21:9), so portrait\n // ad shapes snap to 3:4 rather than being sent as-is;\n // - it has NO resolution knob (`supported_parameters` lists none), so\n // `image_size` is refused here instead of accepted and ignored;\n // - it takes exactly ONE reference image, against 14-16 everywhere else.\n // Its palette levers are real but arrive as provider passthrough\n // (`controls`), which is why they are `json` rather than typed enums; the\n // backend adapter builds that block in `buildImageGenBody`.\n label: \"Recraft v4.1 Pro Vector\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES, max: RECRAFT_MAX_REFERENCES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\", maxLength: RECRAFT_PROMPT_MAX },\n aspect_ratio: { kind: \"string\", enum: RECRAFT_IMAGE_AR },\n strength: { kind: \"number\", min: 0, max: 1 },\n rgb_colors: { kind: \"json\" },\n background_rgb_color: { kind: \"json\" },\n },\n },\n },\n\n image_reference_sheet: {\n // Multi-view subject reference sheets (turnaround grids). The sheet prompt\n // is baked into the backend handler — params here are semantic levers\n // only. Both models consume MULTIPLE reference images via the `references`\n // input slot (required: a sheet without source images is just image_generate).\n \"google/gemini-3-pro-image\": {\n label: \"Google Gemini 3 Pro Image (Nano Banana Pro)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"subject_description\", \"subject_type\"],\n params: {\n subject_description: { kind: \"string\" },\n subject_type: { kind: \"string\", enum: [\"character\", \"person\", \"product\", \"location\"] },\n views: { kind: \"json\" },\n style: { kind: \"string\" },\n prompt_override: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n },\n },\n \"google/gemini-3.1-flash-image\": {\n label: \"Google Gemini 3.1 Flash Image (Nano Banana 2)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"subject_description\", \"subject_type\"],\n params: {\n subject_description: { kind: \"string\" },\n subject_type: { kind: \"string\", enum: [\"character\", \"person\", \"product\", \"location\"] },\n views: { kind: \"json\" },\n style: { kind: \"string\" },\n prompt_override: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: OPENROUTER_IMAGE_AR_EXTREME },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE_EXTENDED },\n },\n },\n },\n\n image_aspect_adapt: {\n // Multi-format adaptation of one creative. The recomposition prompt is\n // baked into the backend handler. The target ratios come from EITHER an\n // explicit `formats` list OR a `platform` preset that expands to the\n // canonical set; exactly one of the two is required — that \"one of\" gate,\n // and per-element ratio validation, live in the node's Zod schema (the\n // registry can't express \"one of\" or gate array elements), so `formats`\n // is not listed as registry-required. The source creative is a required\n // input slot. `copy` (the exact lines the ad carries) and `safe_areas` (per\n // format, the fractions each edge's interface covers) are set by the static\n // scaffold so the reframe keeps every word, once, where the platform shows it.\n \"google/gemini-3-pro-image\": {\n label: \"Google Gemini 3 Pro Image (Nano Banana Pro)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n formats: { kind: \"json\" },\n platform: { kind: \"string\", enum: AD_FORMAT_PLATFORMS },\n guidance: { kind: \"string\" },\n copy: { kind: \"json\" },\n safe_areas: { kind: \"json\" },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE },\n },\n },\n \"google/gemini-3.1-flash-image\": {\n label: \"Google Gemini 3.1 Flash Image (Nano Banana 2)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [],\n params: {\n formats: { kind: \"json\" },\n platform: { kind: \"string\", enum: AD_FORMAT_PLATFORMS },\n guidance: { kind: \"string\" },\n copy: { kind: \"json\" },\n safe_areas: { kind: \"json\" },\n image_size: { kind: \"string\", enum: OPENROUTER_IMAGE_SIZE_EXTENDED },\n },\n },\n },\n\n video_generate: {\n \"bytedance/seedance-2.0\": {\n // Routed via Replicate's official `bytedance/seedance-2.0` model. NOTE:\n // ByteDance's upstream likeness filter blocks photoreal human faces on ANY\n // reseller, and it does NOT care whether the person is real: it classifies\n // pixels, so an AI-generated face that looks photographic is refused\n // exactly like a photograph (E005 / content_policy_blocked). Confirmed in\n // production against faces we generated ourselves. The only escape is Veo\n // — NOT a synthetic presenter, which an earlier version of this note\n // wrongly recommended and which sends you round the same loop.\n label: \"ByteDance Seedance 2.0\",\n route: { provider: \"replicate\" },\n billing: { kind: \"formula\", formula: \"seedance-2.0\" },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: REPLICATE_IMAGE_MIMES, max: SEEDANCE_MAX_REFERENCES }],\n required: [\"prompt\"],\n params: {\n // Replicate's Seedance wrapper hard-caps the prompt at 4000 chars; gate\n // it here so an over-length prompt fails validate (free) not the billed call.\n prompt: { kind: \"string\", maxLength: SEEDANCE_PROMPT_MAX },\n aspect_ratio: {\n kind: \"string\",\n enum: [\"1:1\", \"3:4\", \"9:16\", \"4:3\", \"16:9\", \"21:9\", \"9:21\"],\n },\n resolution: { kind: \"string\", enum: [\"480p\", \"720p\", \"1080p\", \"4k\"] },\n duration: { kind: \"number\", enum: SEEDANCE_DURATIONS },\n // Replicate types this `integer`, and a fractional seed is a schema\n // rejection rather than a rounded one. No range is advertised, so none is\n // invented — see `InputSpec.max` on why absent must stay ungated.\n seed: { kind: \"number\", integer: true },\n generate_audio: { kind: \"boolean\" },\n },\n },\n \"bytedance/seedance-2.5\": {\n // Seedance 2.5 — the LONG-FORM, MULTIMODAL tier, and the only curated video\n // model reached through OpenRouter that is not frame-only.\n //\n // Routed through OpenRouter's video gateway (provider `seed`), NOT through\n // Replicate like 2.0 — the gateway carries the multimodal reference surface\n // 2.5 exists for, and Replicate's 2.0 wrapper only has `reference_images`.\n // The backend branches on the exact 2.0 id for the Replicate path, so this\n // model must never be folded into a `startsWith(\"bytedance/seedance\")`\n // routing test: that is one character away from sending 2.5 to a wrapper\n // that cannot express half of what it is being asked to do.\n //\n // Same upstream likeness filter as 2.0 — ByteDance classifies PIXELS, so an\n // AI-generated face that reads photographic is refused exactly like a\n // photograph (content_policy_blocked). A reference-guided clip refused that\n // way is re-rendered on fal, which serves the same model under a licence that\n // takes faces; a frame-started one is reported, never moved to another model.\n //\n // No published prompt cap on this route, so none is invented: OpenRouter's\n // request schema declares no `maxLength` and the model is sold on long,\n // multi-shot briefs. A ceiling we made up would refuse the exact prompts\n // this tier exists to render.\n label: \"ByteDance Seedance 2.5\",\n route: OPENROUTER_ROUTE,\n billing: { kind: \"formula\", formula: \"seedance-2.5\" },\n recoveryRoute: SEEDANCE_FACE_RECOVERY_ROUTE,\n inputs: [],\n optional_inputs: [\n { kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES, max: SEEDANCE_25_MAX_IMAGE_REFERENCES },\n { kind: \"video\", mimes: OPENROUTER_VIDEO_REFERENCE_MIMES, max: SEEDANCE_25_MAX_VIDEO_REFERENCES },\n { kind: \"audio\", mimes: OPENROUTER_AUDIO_REFERENCE_MIMES, max: SEEDANCE_25_MAX_AUDIO_REFERENCES },\n ],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: SEEDANCE_25_ASPECT_RATIOS },\n resolution: { kind: \"string\", enum: SEEDANCE_25_RESOLUTIONS },\n duration: { kind: \"number\", enum: SEEDANCE_25_DURATIONS },\n seed: { kind: \"number\", integer: true, min: 0, max: UINT32_MAX },\n generate_audio: { kind: \"boolean\" },\n // A visible AI watermark on an ad creative is a defect, and this is the\n // only curated model that lets us turn one off: `watermark` is named in\n // the model's own `allowed_passthrough_parameters`, so it rides as a\n // top-level body field exactly like Kling's `cfg_scale` does.\n watermark: { kind: \"boolean\" },\n },\n },\n \"google/gemini-omni-1.1-flash\": {\n // Google Gemini Omni 1.1 Flash — the DEFAULT video model. Natively\n // multimodal: it reasons over text + images and renders video WITH\n // synchronized audio in one call, and it is the only curated model that\n // takes reference images through its own first-party API (task\n // `reference_to_video`).\n //\n // It is a SEPARATE entry from `google/gemini-omni-flash` (the preview),\n // not a rolling upgrade of it, because the two do not render the same\n // things: 1.1 takes a `resolution` and the preview does not, and 1.1 bills\n // the seconds it renders where the preview bills its whole 10s window. One\n // shared key would have to promise the union of those, which means a canvas\n // could ask the preview for 360p and be quoted a third of what it charges.\n //\n // NOT on OpenRouter. `GET /api/v1/videos/models` lists 17 video models and\n // no Gemini Omni at either version, so this is the sanctioned direct-provider\n // exception (see `convex/lib/geminiOmni.ts`): Google's Interactions API,\n // `POST /v1beta/interactions`. Its own `generateContent` endpoint refuses it\n // (\"This model only supports Interactions API\"), so the Veo `predictLongRunning`\n // shape does not apply either.\n //\n // The param set below is deliberately short and was read off the live API,\n // not off the docs — the knobs absent here are rejected with a pre-dispatch\n // 400 (`Unknown parameter '<name>'`): no `seed`, no `negative_prompt`, no\n // `generate_audio`, no `person_generation` / `enhance_prompt` /\n // `conditioning_scale`. Audio is always on and cannot be turned off.\n // Widening this list does not widen the model; it just moves a free\n // validation error into a billed one.\n //\n // `duration` is the odd one out: Omni has no duration FIELD at any nesting\n // level, but it honours a length named in the prompt (3-10s), so the adapter\n // turns this param into a prompt directive. It is a real, billable knob.\n //\n // NO VIDEO INPUT SLOT, and that is a gate on our project rather than a gap\n // in the model or a mistake in how we ask. 1.1 advertises video references,\n // `edit` and `extend`, and every request carrying a video comes back 400\n // `content_blocked`.\n //\n // The controlled version, run through the shape Google's own docs use\n // (`{\"type\":\"document\",\"uri\":<Files API uri>}`, no generation_config),\n // changing only the uploaded file: an IMAGE returns 200 and renders a clip;\n // a VIDEO returns `content_blocked`. Same route, same structure. So the\n // request shape is right and video input specifically is refused. Also\n // measured across inline base64, all three tasks, video AND text output,\n // synthetic clips, Omni's own output, real camera footage, and both our\n // keys. Full probe log: `.context/omni-1.1-measurements.md`.\n //\n // Adding `{ kind: \"video\", mimes: … }` below is the ONE line that turns the\n // whole feature on — the \"Build on\" control, the reference picker taking an\n // MP4, the drop target and the source-clip cost premium are all driven off\n // this slot. Add it the day the 400 stops, not before: until then it offers\n // a control whose every use is refused.\n label: \"Google Gemini Omni 1.1 Flash\",\n route: { provider: \"google-interactions\", wireModel: \"gemini-omni-1.1-flash\" },\n billing: { kind: \"formula\", formula: \"gemini-omni\" },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: GEMINI_OMNI_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: GEMINI_OMNI_ASPECT_RATIOS },\n resolution: { kind: \"string\", enum: GEMINI_OMNI_RESOLUTIONS },\n duration: { kind: \"number\", enum: GEMINI_OMNI_DURATIONS },\n },\n },\n \"google/gemini-omni-flash\": {\n // LEGACY — the Omni PREVIEW (`gemini-omni-flash-preview`), superseded by\n // `google/gemini-omni-1.1-flash` above. Kept so canvases authored before 1.1\n // still validate and re-run unchanged (`baker canvas run --slug` restores a\n // recorded canvas verbatim, so dropping this model would break every stored\n // creative that used it). Don't reach for it in new work.\n //\n // Its param surface is the ORIGINAL one on purpose, and the omission that\n // matters is `resolution`. This model renders 720p / 24fps and nothing else.\n //\n // It does NOT reject the field, which is the trap and the reason this is\n // enforced here rather than left to the provider: asked for `360p` it\n // returns HTTP 200, a 1280x720 clip, and a bill of 17,376 video tokens —\n // the 720p rate, three times the 5,793 that tier costs on 1.1. Accepted,\n // ignored, and charged for. Copying 1.1's enum across to make the two\n // entries match would hand a canvas a quality dial that does nothing and a\n // quote a third of the real charge.\n label: \"Google Gemini Omni Flash (legacy preview)\",\n route: { provider: \"google-interactions\", wireModel: \"gemini-omni-flash-preview\" },\n billing: { kind: \"formula\", formula: \"gemini-omni\" },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: GEMINI_OMNI_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: GEMINI_OMNI_ASPECT_RATIOS },\n duration: { kind: \"number\", enum: GEMINI_OMNI_DURATIONS },\n },\n },\n \"google/veo-3.1\": {\n // Photoreal CINE CEILING + the real-face fallback (Veo generates adult\n // humans from a keyframe, dodging ByteDance's real-person filter). Same\n // OpenRouter google-vertex routing as the fast tier; the quality dial is\n // `resolution: 1080p` + `generate_audio` + a real `negative_prompt`, not a\n // separate provider knob. Reach for this for hero beats and any clip that\n // must carry a real human likeness.\n label: \"Google Veo 3.1\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n // Veo prices 4K far above the base tier, and 4K is a selectable resolution,\n // so folding it into the base rate under-quotes the dearest clip we can make.\n // A QUOTE only: the charge is the usage OpenRouter reports for the call.\n usd: { silent: 0.2, audio: 0.4, byResolution: { \"4K\": { silent: 0.4, audio: 0.6 } } },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n negative_prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\"] },\n resolution: { kind: \"string\", enum: [\"720p\", \"1080p\", \"4K\"] },\n duration: { kind: \"number\", enum: [4, 6, 8] },\n // Vertex declares `seed` a uint32: \"accepted range 0-4294967295\".\n seed: { kind: \"number\", integer: true, min: 0, max: VEO_SEED_MAX },\n generate_audio: { kind: \"boolean\" },\n person_generation: { kind: \"string\", enum: [\"allow_all\", \"allow_adult\"] },\n enhance_prompt: { kind: \"boolean\" },\n conditioning_scale: { kind: \"number\" },\n },\n },\n \"kwaivgi/kling-v3.0-pro\": {\n // Motion-transfer / dynamic multi-shot beats. Reachable through the default\n // OpenRouter gateway (generic video body — no google-vertex block), so it\n // needs no direct-provider exception. `cfg_scale` trades prompt adherence\n // vs motion freedom; higher = closer to prompt.\n //\n // Params below are the ones OpenRouter actually advertises for this model\n // (GET /api/v1/videos/models). Three were wrong before and each was a free\n // 400 or a silently unsupported knob: it renders 720p ONLY (1080p was\n // offered and rejected), it takes ANY duration from 3-15s (we allowed just\n // 5 and 10), and it does not support `seed` at all.\n label: \"Kling 3.0\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n // One flat rate across every resolution and mode.\n usd: { silent: 0.112, audio: 0.168 },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n // Kling caps the prompt shorter than Seedance; gate it here so an\n // over-length prompt fails validate (free) not the billed call. Its\n // negative prompt is a SEPARATE 2,500 budget, not a shared one.\n prompt: { kind: \"string\", maxLength: KLING_PROMPT_MAX },\n negative_prompt: { kind: \"string\", maxLength: KLING_PROMPT_MAX },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\", \"1:1\"] },\n resolution: { kind: \"string\", enum: [\"720p\"] },\n duration: { kind: \"number\", enum: KLING_DURATIONS },\n generate_audio: { kind: \"boolean\" },\n cfg_scale: { kind: \"number\", min: 0, max: 1 },\n },\n },\n \"x-ai/grok-imagine-video\": {\n // The avatar workhorse. Measured best of the reference-capable models on\n // identity retention AND aspect-ratio obedience, at the lowest rate of any\n // video model we carry ($0.05/s at 480p). No audio at all — `generate_audio`\n // is absent from its OpenRouter listing, so a talking head goes to Wan 2.7.\n // NOTE: `x-ai/grok-imagine-video-1.5` is NOT a drop-in upgrade — it is\n // described as plain image-to-video and drops the reference conditioning\n // this entry exists for.\n label: \"Grok Imagine Video\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n usd: {\n silent: 0.07,\n audio: 0.07,\n byResolution: { \"480p\": { silent: 0.05, audio: 0.05 }, \"720p\": { silent: 0.07, audio: 0.07 } },\n },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\", \"1:1\", \"4:3\", \"3:4\", \"3:2\", \"2:3\"] },\n resolution: { kind: \"string\", enum: [\"480p\", \"720p\"] },\n duration: { kind: \"number\", enum: GROK_IMAGINE_DURATIONS },\n },\n },\n \"alibaba/wan-2.7\": {\n // Reference-to-video AND native audio — the only model we carry with both,\n // which makes it the landscape talking-head option.\n //\n // LANDSCAPE ONLY, measured. It advertises 9:16, 1:1, 4:3 and 3:4, and\n // delivers 16:9 regardless: asked for vertical via `aspect_ratio: \"9:16\"`\n // it returned 1280x720, and asked again via an explicit\n // `size: \"720x1280\"` from its own `supported_sizes` it returned 1280x720\n // again. The enum below is therefore what it DOES, not what it claims, so\n // nobody pays for a vertical clip that comes back landscape. For a vertical\n // avatar clip use `x-ai/grok-imagine-video` (silent) or animate a generated\n // still with `google/veo-3.1-lite` (native audio, honours 9:16).\n label: \"Alibaba Wan 2.7\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n // Flat $0.10/s across resolutions and modes, audio included.\n usd: { silent: 0.1, audio: 0.1 },\n minBilledSeconds: MIN_BILLED_SECONDS,\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n negative_prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\"] },\n resolution: { kind: \"string\", enum: [\"720p\", \"1080p\"] },\n duration: { kind: \"number\", enum: WAN_27_DURATIONS },\n seed: { kind: \"number\" },\n generate_audio: { kind: \"boolean\" },\n },\n },\n \"x-ai/grok-imagine-video-1.5\": {\n // NOT a replacement for the entry above, and deliberately absent from\n // `AVATAR_VIDEO_MODELS` and `REFERENCE_TO_VIDEO_MODELS`: OpenRouter describes the\n // older Grok as \"text-, image-, and reference-conditioned\" and 1.5 as taking \"an\n // optional starting image\". Reference conditioning is the whole reason Grok carries\n // avatars — it is what holds a face from the identity sheet — so swapping them\n // would quietly cost every avatar clip its likeness.\n //\n // What it adds over the older one: 1080p, and 15s rather than 10.\n label: \"Grok Imagine Video 1.5\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n // `cents_per_video_output_second_*`: 8c, 14c and 25c. No audio, so both\n // columns are the same rate rather than one being wrong.\n usd: {\n silent: 0.14,\n audio: 0.14,\n byResolution: {\n \"480p\": { silent: 0.08, audio: 0.08 },\n \"720p\": { silent: 0.14, audio: 0.14 },\n \"1080p\": { silent: 0.25, audio: 0.25 },\n },\n },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\", \"1:1\", \"4:3\", \"3:4\", \"3:2\", \"2:3\"] },\n resolution: { kind: \"string\", enum: [\"480p\", \"720p\", \"1080p\"] },\n duration: { kind: \"number\", enum: GROK_IMAGINE_15_DURATIONS },\n },\n },\n \"alibaba/wan-3.0\": {\n // 2.7's successor on every axis that matters: 2–30s against 2–10, 1080p and 480p\n // as well as 720p, and it keeps the native audio that made 2.7 the landscape\n // talking-head option.\n //\n // The ratios are what it ADVERTISES. 2.7 advertised five and delivered 16:9 for\n // all of them — measured, twice, which is why its enum here is a single value. That\n // was a different model and this one is not gated on its predecessor's lie, but\n // the first vertical clip anyone renders here is worth looking at before a campaign\n // is built on it.\n //\n // No `last_frame`: 2.7 takes one and 3.0 does not, so a canvas that ends a shot on\n // a chosen frame stays on 2.7.\n label: \"Alibaba Wan 3.0\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n // Priced per resolution where 2.7 was flat, and the rate still includes\n // audio: there is no separate audio SKU. `duration_seconds_480p|720p|1080p`.\n usd: {\n silent: 0.1,\n audio: 0.1,\n byResolution: {\n \"480p\": { silent: 0.05, audio: 0.05 },\n \"720p\": { silent: 0.1, audio: 0.1 },\n \"1080p\": { silent: 0.2, audio: 0.2 },\n },\n },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\", \"1:1\", \"4:3\", \"3:4\"] },\n resolution: { kind: \"string\", enum: [\"480p\", \"720p\", \"1080p\"] },\n duration: { kind: \"number\", enum: WAN_30_DURATIONS },\n seed: { kind: \"number\" },\n generate_audio: { kind: \"boolean\" },\n },\n },\n \"runway/gen-4.5\": {\n // One resolution, two shapes, and silent — `generate_audio: false` in its listing,\n // so a talking head belongs on Wan or Omni. First frame only, no reference.\n label: \"Runway Gen-4.5\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n // One flat rate, one resolution: `cents_per_second_output: 12`. Silent.\n usd: { silent: 0.12, audio: 0.12 },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\"] },\n resolution: { kind: \"string\", enum: [\"720p\"] },\n duration: { kind: \"number\", enum: RUNWAY_45_DURATIONS },\n seed: { kind: \"number\" },\n },\n },\n \"alibaba/happyhorse-1.1\": {\n // Third reference-capable option: strong identity, correct ratios, no audio.\n // First-frame only (no `last_frame`), so it cannot close a beat on a\n // specified end pose the way Wan and Veo can.\n label: \"Alibaba HappyHorse 1.1\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n usd: { silent: 0.1278, audio: 0.1278, byResolution: { \"720p\": { silent: 0.0988, audio: 0.0988 } } },\n minBilledSeconds: MIN_BILLED_SECONDS,\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\", \"1:1\", \"4:3\", \"3:4\", \"21:9\", \"9:21\"] },\n resolution: { kind: \"string\", enum: [\"720p\", \"1080p\"] },\n duration: { kind: \"number\", enum: HAPPYHORSE_DURATIONS },\n seed: { kind: \"number\" },\n },\n },\n \"google/veo-3.1-lite\": {\n // The cheapest way to animate a still that carries a real face: same Veo\n // family and the same escape from ByteDance's filter, at $0.05/s with audio\n // at 720p against Veo 3.1's $0.40. That 8x is the difference between an\n // avatar clip you iterate on and one you think twice about.\n label: \"Google Veo 3.1 Lite\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n usd: { silent: 0.05, audio: 0.08, byResolution: { \"720p\": { silent: 0.03, audio: 0.05 } } },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n negative_prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\"] },\n resolution: { kind: \"string\", enum: [\"720p\", \"1080p\"] },\n duration: { kind: \"number\", enum: [4, 6, 8] },\n seed: { kind: \"number\" },\n generate_audio: { kind: \"boolean\" },\n person_generation: { kind: \"string\", enum: [\"allow_all\", \"allow_adult\"] },\n enhance_prompt: { kind: \"boolean\" },\n conditioning_scale: { kind: \"number\" },\n },\n },\n \"google/veo-3.1-fast\": {\n // Cheap test/iteration model. Forwarded by the backend via\n // `provider.options.google-vertex.parameters` (camelCased on the wire).\n label: \"Google Veo 3.1 Fast\",\n route: OPENROUTER_ROUTE,\n billing: {\n kind: \"per_second\",\n usd: {\n silent: 0.1,\n audio: 0.12,\n byResolution: { \"720p\": { silent: 0.08, audio: 0.1 }, \"4K\": { silent: 0.25, audio: 0.3 } },\n },\n },\n inputs: [],\n optional_inputs: [{ kind: \"image\", mimes: OPENROUTER_IMAGE_MIMES }],\n required: [\"prompt\"],\n params: {\n prompt: { kind: \"string\" },\n negative_prompt: { kind: \"string\" },\n aspect_ratio: { kind: \"string\", enum: [\"16:9\", \"9:16\"] },\n resolution: { kind: \"string\", enum: [\"720p\", \"1080p\", \"4K\"] },\n duration: { kind: \"number\", enum: [4, 6, 8] },\n seed: { kind: \"number\", integer: true, min: 0, max: VEO_SEED_MAX },\n generate_audio: { kind: \"boolean\" },\n // Image-to-video and EU/UK/CH/MENA regions cap this at `allow_adult`;\n // `allow_all` is text-to-video only. Allow both so an image-conditioned\n // Veo clip (the real-face fallback) validates.\n person_generation: { kind: \"string\", enum: [\"allow_all\", \"allow_adult\"] },\n enhance_prompt: { kind: \"boolean\" },\n conditioning_scale: { kind: \"number\" },\n },\n },\n },\n\n video_deconstruct: {\n // Replication-grade video extraction — the forensic system prompts live on\n // the backend; `focus` appends emphasis only. Frames ride on a throwaway\n // Mux asset; analysis runs on Gemini with the video as a file part.\n \"~google/gemini-flash-latest\": {\n label: \"Google Gemini Flash (latest, Video)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"video\", mimes: DECONSTRUCT_VIDEO_MIMES }],\n required: [],\n params: {\n mode: { kind: \"string\", enum: [\"full\", \"index\"] },\n language: { kind: \"string\" },\n max_scenes: { kind: \"number\", min: 1, max: 60 },\n focus: { kind: \"string\" },\n start_s: { kind: \"number\", min: 0 },\n end_s: { kind: \"number\", min: 0 },\n max_clip_s: { kind: \"number\", min: 1, max: 60 },\n transcriber: { kind: \"string\", enum: [\"groq\", \"deepgram\"] },\n // Real visual shot-cut timestamps (seconds) from local PySceneDetect;\n // scene boundaries snap onto them so frames never straddle a hard cut.\n // Shape (number[]) is enforced by the node + backend Zod schemas.\n shot_cuts: { kind: \"json\" },\n },\n },\n \"~google/gemini-pro-latest\": {\n label: \"Google Gemini Pro (latest, Video)\",\n route: OPENROUTER_ROUTE,\n billing: USAGE_BILLED,\n inputs: [{ kind: \"video\", mimes: DECONSTRUCT_VIDEO_MIMES }],\n required: [],\n params: {\n mode: { kind: \"string\", enum: [\"full\", \"index\"] },\n language: { kind: \"string\" },\n max_scenes: { kind: \"number\", min: 1, max: 60 },\n focus: { kind: \"string\" },\n start_s: { kind: \"number\", min: 0 },\n end_s: { kind: \"number\", min: 0 },\n max_clip_s: { kind: \"number\", min: 1, max: 60 },\n transcriber: { kind: \"string\", enum: [\"groq\", \"deepgram\"] },\n // See gemini-flash-latest above — local PySceneDetect shot-cut timestamps.\n shot_cuts: { kind: \"json\" },\n },\n },\n },\n\n video_lipsync: {\n // Formerly `fal/veed-lipsync`, which named a provider and a model it had stopped\n // running on; that id stays accepted through `MODEL_ALIASES`.\n \"replicate/sync-lipsync-2\": {\n label: \"Sync Labs Lipsync 2 (Replicate)\",\n route: { provider: \"replicate\", wireModel: \"sync/lipsync-2\" },\n billing: { kind: \"formula\", formula: \"lipsync-minutes\" },\n inputs: [\n { kind: \"video\", mimes: REPLICATE_VIDEO_MIMES },\n { kind: \"audio\", mimes: REPLICATE_AUDIO_MIMES },\n ],\n required: [],\n params: {},\n },\n },\n\n tts: {\n \"elevenlabs/eleven_v3\": {\n // eleven_v3 does NOT yet support context stitching\n // (previous_text/next_text/*_request_ids). ElevenLabs returns a clean\n // `unsupported_model` 400 if you pass them.\n label: \"ElevenLabs Eleven v3\",\n route: { provider: \"elevenlabs\", wireModel: \"eleven_v3\" },\n billing: { kind: \"formula\", formula: \"elevenlabs-characters\" },\n inputs: [],\n required: [\"text\", \"voice\"],\n params: {\n text: { kind: \"string\", maxLength: ELEVENLABS_MAX_TEXT_CHARS },\n voice: { kind: \"string\" },\n language_code: { kind: \"string\" },\n stability: { kind: \"number\", min: 0, max: 1 },\n similarity_boost: { kind: \"number\", min: 0, max: 1 },\n voice_settings: { kind: \"json\" },\n seed: { kind: \"number\", min: 0, max: 4_294_967_295 },\n pronunciation_dictionary_locators: { kind: \"json\" },\n apply_text_normalization: { kind: \"string\", enum: [\"auto\", \"on\", \"off\"] },\n apply_language_text_normalization: { kind: \"boolean\" },\n with_timestamps: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n\n audio_voice_convert: {\n \"elevenlabs/eleven_multilingual_sts_v2\": {\n // Speech-to-speech / Voice Changer: re-voice an existing audio clip in the\n // TARGET voice, preserving timing/prosody. Used to normalize a talking-head\n // clip's native (generator-chosen) voice into ONE consistent brand voice.\n label: \"ElevenLabs Voice Changer (multilingual STS v2)\",\n route: { provider: \"elevenlabs\", wireModel: \"eleven_multilingual_sts_v2\" },\n billing: { kind: \"formula\", formula: \"elevenlabs-voice-convert-minutes\" },\n inputs: [{ kind: \"audio\", mimes: REPLICATE_AUDIO_MIMES }],\n required: [\"voice\"],\n params: {\n voice: { kind: \"string\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n remove_background_noise: { kind: \"boolean\" },\n },\n },\n },\n\n music: {\n \"elevenlabs/music-v1\": {\n label: \"ElevenLabs Music v1 (Compose)\",\n route: { provider: \"elevenlabs\", wireModel: ELEVENLABS_MUSIC_ENGINE },\n billing: { kind: \"formula\", formula: \"elevenlabs-music-seconds\" },\n inputs: [],\n required: [],\n params: {\n prompt: { kind: \"string\" },\n composition_plan: { kind: \"json\" },\n music_length_ms: { kind: \"number\", min: 3000, max: ELEVENLABS_MAX_MUSIC_LENGTH_MS },\n seed: { kind: \"number\" },\n force_instrumental: { kind: \"boolean\" },\n respect_sections_durations: { kind: \"boolean\" },\n with_timestamps: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n \"elevenlabs/video-background-music-v1\": {\n label: \"ElevenLabs Video Background Music v1\",\n route: { provider: \"elevenlabs\", wireModel: ELEVENLABS_MUSIC_ENGINE },\n billing: { kind: \"formula\", formula: \"elevenlabs-music-seconds\" },\n inputs: [{ kind: \"video\", mimes: REPLICATE_VIDEO_MIMES }],\n required: [],\n params: {\n description: { kind: \"string\" },\n tags: { kind: \"json\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n\n dialogue: {\n \"elevenlabs/eleven_v3\": {\n label: \"ElevenLabs Eleven v3 (Dialogue)\",\n route: { provider: \"elevenlabs\", wireModel: \"eleven_v3\" },\n billing: { kind: \"formula\", formula: \"elevenlabs-characters\" },\n inputs: [],\n required: [\"inputs\"],\n params: {\n inputs: { kind: \"json\" },\n language_code: { kind: \"string\" },\n settings: { kind: \"json\" },\n seed: { kind: \"number\", min: 0, max: 4_294_967_295 },\n apply_text_normalization: { kind: \"string\", enum: [\"auto\", \"on\", \"off\"] },\n with_timestamps: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n\n sound_effect: {\n \"elevenlabs/eleven_text_to_sound_v2\": {\n label: \"ElevenLabs Text-to-Sound v2\",\n route: { provider: \"elevenlabs\", wireModel: \"eleven_text_to_sound_v2\" },\n billing: { kind: \"formula\", formula: \"elevenlabs-sound-effect-seconds\" },\n inputs: [],\n required: [\"text\"],\n params: {\n text: { kind: \"string\" },\n duration_seconds: { kind: \"number\", min: 0.5, max: 30 },\n prompt_influence: { kind: \"number\", min: 0, max: 1 },\n loop: { kind: \"boolean\" },\n output_format: { kind: \"string\", enum: ELEVENLABS_OUTPUT_FORMATS },\n },\n },\n },\n};\n\n// ---------------------------------------------------------------------------\n// Legacy ids\n// ---------------------------------------------------------------------------\n\n/**\n * Ids that stored canvases still carry, mapped to the registered id they now mean.\n *\n * Two kinds of entry. The `fal/*` ids named the wrong thing: all three were priced and\n * labelled on fal.ai and have run on Replicate models since. The image ids were\n * SUPERSEDED: the Gemini previews by their GA releases (2026-06-18, same surface), and\n * GPT-5.4 Image 2 by GPT Image 2.5 Sunburst, the precision tier of the same OpenAI line —\n * which renders no 4:5/5:4 and has no size dial, so its old params are fitted on the way\n * in (`canonicalModelParams`).\n *\n * They are aliases rather than deletions because `baker canvas run --slug` restores a\n * recorded canvas verbatim, Studio batches and older CLIs send the id they were written\n * with, and a canvas is never edited behind its author's back. The id is resolved at\n * the doors a node or request comes in through (validation, the backend dispatcher, the\n * Studio request); the canvas file and its cache key keep the id they were written with.\n */\nexport const MODEL_ALIASES: Readonly<Record<string, string>> = {\n \"fal/veed-lipsync\": \"replicate/sync-lipsync-2\",\n \"fal/veed-video-background-removal\": \"replicate/birefnet-video\",\n \"fal/birefnet-v2\": \"replicate/birefnet\",\n \"google/gemini-3.1-flash-image-preview\": \"google/gemini-3.1-flash-image\",\n \"google/gemini-3-pro-image-preview\": \"google/gemini-3-pro-image\",\n \"openai/gpt-5.4-image-2\": \"openai/gpt-image-2.5-sunburst\",\n};\n\n/**\n * What a retired id was called, for describing work it made before it retired:\n * it runs on its alias now, but a past batch was made by this model.\n */\nexport const RETIRED_MODEL_LABELS: Readonly<Record<string, string>> = {\n \"google/gemini-3.1-flash-image-preview\": \"Google Gemini 3.1 Flash Image (Preview)\",\n \"google/gemini-3-pro-image-preview\": \"Google Gemini 3 Pro Image (Preview)\",\n \"openai/gpt-5.4-image-2\": \"OpenAI GPT-5.4 Image 2\",\n};\n\n/** The registered id a model id means: itself, or what its legacy alias now points at. */\nexport function canonicalModelId(model: string): string {\n // Own keys only, so a prototype name (\"toString\") is never read as an alias. Not\n // `Object.hasOwn`: the backend typechecks this package under `lib: ES2021`.\n return Object.keys(MODEL_ALIASES).includes(model) ? (MODEL_ALIASES[model] as string) : model;\n}\n\n/** A legacy id together with the id it stands for, for building node param enums. */\nexport function modelIdsAccepted(canonical: string): [string, ...string[]] {\n return [canonical, ...Object.keys(MODEL_ALIASES).filter((legacy) => MODEL_ALIASES[legacy] === canonical)];\n}\n\n/** The registry entry a model id means for `kind`, legacy ids included; undefined when nothing registers it. */\nfunction modelSpec(kind: NodeKind, model: string): ModelSpec | undefined {\n return MODEL_REGISTRY[kind]?.[canonicalModelId(model)];\n}\n\n/**\n * The legacy ids whose successor takes a NARROWER surface than they did. Every other\n * alias's successor takes exactly what the old id took, so a value it refuses was always\n * wrong and stays refused rather than being quietly snapped into something valid.\n */\nconst NARROWED_ALIASES: readonly string[] = [\"openai/gpt-5.4-image-2\"];\n\n/**\n * A node's params as the model its id now means will take them.\n *\n * Unchanged for an id that is not an alias. For a legacy id the model is swapped for its\n * successor; where that successor's surface is narrower (`NARROWED_ALIASES`), the shape,\n * size and quality asked of the old model are fitted to what it renders — snapped to the\n * nearest it has, or dropped when it has no such dial — so a stored canvas re-runs rather\n * than failing validation for a param its author wrote against a model we no longer call\n * (GPT-5.4 Image 2's 4:5 and 2K, for one).\n */\nexport function canonicalModelParams<P extends Record<string, unknown>>(kind: NodeKind, params: P): P {\n const model = params.model;\n if (typeof model !== \"string\" || canonicalModelId(model) === model) return params;\n const successor = canonicalModelId(model);\n if (!NARROWED_ALIASES.includes(model)) return { ...params, model: successor };\n const fitted: Record<string, unknown> = { ...params, model: successor };\n if (typeof fitted.aspect_ratio === \"string\") {\n fitted.aspect_ratio = nearestSupportedAspectRatio(kind, successor, fitted.aspect_ratio);\n }\n if (typeof fitted.image_size === \"string\") {\n fitted.image_size = supportsParam(kind, successor, \"image_size\")\n ? nearestSupportedImageSize(kind, successor, fitted.image_size)\n : undefined;\n }\n if (typeof fitted.quality === \"string\") {\n fitted.quality = bestSupportedQuality(kind, successor, fitted.quality);\n }\n return Object.fromEntries(Object.entries(fitted).filter(([, value]) => value !== undefined)) as P;\n}\n\n// ---------------------------------------------------------------------------\n// Service models: nodes with a provider model but no per-model param gate\n// ---------------------------------------------------------------------------\n\ntype ServiceModelSpec = { label: string; route: ProviderRoute; billing: ModelBilling };\n\n/**\n * Models behind nodes the registry does not validate param by param: each node runs\n * exactly one model, so there is no choice to gate, but there is still a provider,\n * a wire id and a price, and those belong here with every other model's.\n */\nexport const SERVICE_MODELS = {\n video_background_remove: {\n \"replicate/birefnet-video\": {\n label: \"BiRefNet Video (Replicate)\",\n route: { provider: \"replicate\", wireModel: \"sprited/birefnet-video\" },\n billing: { kind: \"formula\", formula: \"video-background-remove-frames\" },\n },\n },\n image_background_remove: {\n \"replicate/birefnet\": {\n label: \"BiRefNet (Replicate)\",\n route: { provider: \"replicate\", wireModel: \"men1scus/birefnet\" },\n billing: { kind: \"formula\", formula: \"image-background-remove-call\" },\n },\n },\n // Keyed by the `transcriber` param value, which is how a node picks between them.\n video_transcribe: {\n groq: {\n label: \"Groq Whisper Large v3 Turbo\",\n route: { provider: \"groq\", wireModel: \"whisper-large-v3-turbo\" },\n billing: { kind: \"formula\", formula: \"transcription\" },\n },\n deepgram: {\n label: \"Deepgram Nova-3\",\n route: { provider: \"deepgram\", wireModel: \"nova-3\" },\n billing: { kind: \"formula\", formula: \"transcription\" },\n },\n },\n} as const satisfies Record<string, Record<string, ServiceModelSpec>>;\n\n/** The one model a service node runs, looked up through `canonicalModelId`; throws for an id nothing registers. */\nexport function serviceRoute<N extends keyof typeof SERVICE_MODELS>(node: N, model: string): ProviderRoute {\n const models: Readonly<Record<string, ServiceModelSpec>> = SERVICE_MODELS[node];\n const spec = models[canonicalModelId(model)];\n if (!spec) throw new Error(`unknown model \"${model}\" for ${node}`);\n return spec.route;\n}\n\n/** The Whisper / Nova route a transcriber choice runs on. */\nexport function transcriberRoute(transcriber: \"groq\" | \"deepgram\"): ProviderRoute {\n return SERVICE_MODELS.video_transcribe[transcriber].route;\n}\n\n// ---------------------------------------------------------------------------\n// Provider routes\n// ---------------------------------------------------------------------------\n\n/** The route a registered model runs on, or undefined when nothing registers it. Legacy ids resolve. */\nexport function routeOf(kind: NodeKind, model: string): ProviderRoute | undefined {\n const canonical = canonicalModelId(model);\n const spec = MODEL_REGISTRY[kind]?.[canonical];\n if (!spec) return undefined;\n return { provider: spec.route.provider, wireModel: spec.route.wireModel ?? canonical };\n}\n\n/**\n * The route a registered model runs on. Throws for an unknown id rather than\n * guessing one: a fallback here is how a stored canvas silently re-renders on a\n * model it was never rendered on.\n */\nexport function providerRoute(kind: NodeKind, model: string): ProviderRoute {\n const route = routeOf(kind, model);\n if (!route) throw new Error(`unknown model \"${model}\" for node \"${kind}\": it has no provider route`);\n return route;\n}\n\n/** The published per-second rate a video model is quoted at, or undefined when it is priced another way. */\nexport function perSecondBilling(model: string): { usd: VideoSecondRate; minBilledSeconds?: number } | undefined {\n const billing = MODEL_REGISTRY.video_generate[model]?.billing;\n return billing?.kind === \"per_second\" ? billing : undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Roles: which model does which job, named once\n// ---------------------------------------------------------------------------\n\n/**\n * Every job a scaffolder or backend path hands to a fixed model, named here so the\n * id lives in one place. Each is typed to the node kind it runs as, and a test checks\n * the id is registered for that kind: a reference sheet asked of an image model\n * that is not a sheet model is an `unknown_model` node, found only when it runs.\n *\n * These are per-surface choices, not one default: `DEFAULT_IMAGE_GENERATE_MODEL` is\n * Gemini Flash for cheap, high-volume image work, while an ad's frames are pinned to\n * GPT Image 2.5 because each is the opening still a whole clip is built from.\n */\nexport const MODEL_ROLES = {\n /** Ad frames and static-ad plates: the most faithful text and identity reproduction. */\n adImage: { kind: \"image_generate\", model: \"openai/gpt-image-2.5-sunburst\" },\n /**\n * The multi-view reference sheet a recurring element is fused on. Gemini 3 Pro makes\n * the cleanest, best-labelled turnaround, worth it for the ONE reference every frame\n * of an ad grounds on.\n */\n referenceSheet: { kind: \"image_reference_sheet\", model: \"google/gemini-3-pro-image\" },\n /** Re-framing a static ad whose copy is baked into the pixels. */\n aspectAdapt: { kind: \"image_aspect_adapt\", model: \"google/gemini-3-pro-image\" },\n /**\n * The judge comparing candidate plates. Flash, not Pro: Pro measured 5 credits for\n * one pick, a tenth of the render it judges.\n */\n plateJudge: { kind: \"image_select\", model: \"~google/gemini-flash-latest\" },\n /**\n * The static-ad blueprint extraction, and the fit of a reference to a company (`winning-ads fit`).\n * Flash, not Pro: measured on 16 proven ads (dev, Oct 2026), Flash read as well, answered 11 describes\n * of 12 (Pro 8: its preview model stopped answers part-way) and 16 fits of 16 (Pro 15), at under half\n * the describe's cost and a fifth of the fit's; the fit kept or rejected the same ads 14 times of 15.\n * A describe takes ~10 s longer (40 s), a fit ~12 s less (10 s).\n */\n adDescribe: { kind: \"image_describe\", model: \"~google/gemini-flash-latest\" },\n /** The element-selection and layout passes over a blueprint. */\n blueprintAnalysis: { kind: \"text_generate\", model: \"~google/gemini-flash-latest\" },\n /**\n * The viewer an ad reaches, played before a static ad renders (`baker canvas viewer-check`):\n * says from the copy and the scene what is offered, to whom, and what to do next. Text\n * only and asked once per ad and viewer, so Flash; the calibration set (E8) decides.\n */\n viewerCheck: { kind: \"text_generate\", model: \"~google/gemini-flash-latest\" },\n /**\n * Picks the customer truths out of reviews, testimonials and threads (`baker research\n * customers`): returns exact spans the code then checks against the source. Text only and\n * one call per batch, so Flash.\n */\n customerInsights: { kind: \"text_generate\", model: \"~google/gemini-flash-latest\" },\n /**\n * The same viewer shown the FINISHED static ad at phone size for about three seconds, with no\n * brand and no brief: what is sold, whether it is for them, what to do next, what stopped them\n * (`glance-check.ts`). One small picture per run, so Flash.\n */\n glanceCheck: { kind: \"image_describe\", model: \"~google/gemini-flash-latest\" },\n /**\n * Reads every line of text and the logo of a finished static ad WITH its box, for the\n * copy and safe-area checks. Bench E10 (2026-09-30): word F1 0.994, box IoU 0.937, 4.3 s,\n * about $0.005 an image on `google/gemini-3.8-flash`, which this alias resolves to;\n * tesseract and PaddleOCR missed the 0.95 F1 gate.\n */\n textBoxReader: { kind: \"image_describe\", model: \"~google/gemini-flash-latest\" },\n /**\n * Reads where every person, face, animal and product sits in a static ad's picture, WITH its\n * box, so each size is cut around them and its words kept off faces. The same reader and grid\n * as `textBoxReader` (Gemini's `box_2d`), asked once per chosen picture.\n */\n subjectBoxReader: { kind: \"image_describe\", model: \"~google/gemini-flash-latest\" },\n /**\n * Compares one size of a finished static ad with its main size for what boxes cannot say: the\n * same product and people, nothing shown twice, nobody stretched, never the main picture boxed in\n * a bigger frame (`size-consistency.ts`). Flash: one small pair per drawn size; on 29 production\n * pairs asked twice it flagged none and named 4 of 4 planted defects (Oct 2026).\n */\n sizeMatch: { kind: \"image_describe\", model: \"~google/gemini-flash-latest\" },\n /**\n * Scene-by-scene video extraction. Flash: ~2-3x faster per call than Pro, which keeps\n * each per-scene step inside the action time budget.\n */\n videoDeconstruct: { kind: \"video_deconstruct\", model: \"~google/gemini-flash-latest\" },\n /** The backend `image_search` agent loop that picks search tools and queries. */\n imageSearch: { kind: \"text_generate\", model: \"~google/gemini-flash-latest\" },\n voiceover: { kind: \"tts\", model: \"elevenlabs/eleven_v3\" },\n soundEffect: { kind: \"sound_effect\", model: \"elevenlabs/eleven_text_to_sound_v2\" },\n musicBed: { kind: \"music\", model: \"elevenlabs/music-v1\" },\n /** Re-voices a talking clip's native audio into one consistent brand voice. */\n voiceConvert: { kind: \"audio_voice_convert\", model: \"elevenlabs/eleven_multilingual_sts_v2\" },\n /** The scored video router's candidates, one per job it can route to. */\n videoRouterWorkhorse: { kind: \"video_generate\", model: \"bytedance/seedance-2.0\" },\n videoRouterRealFace: { kind: \"video_generate\", model: \"google/veo-3.1\" },\n videoRouterRealFaceEconomy: { kind: \"video_generate\", model: \"google/veo-3.1-fast\" },\n videoRouterMotion: { kind: \"video_generate\", model: \"kwaivgi/kling-v3.0-pro\" },\n imageDefault: { kind: \"image_generate\", model: DEFAULT_IMAGE_GENERATE_MODEL },\n videoDefault: { kind: \"video_generate\", model: DEFAULT_VIDEO_GENERATE_MODEL },\n avatarVideo: { kind: \"video_generate\", model: DEFAULT_AVATAR_VIDEO_MODEL },\n} as const satisfies Record<string, { kind: NodeKind; model: string }>;\n\nexport type ModelRole = keyof typeof MODEL_ROLES;\n\nexport const AD_IMAGE_MODEL = MODEL_ROLES.adImage.model;\nexport const REFERENCE_SHEET_MODEL = MODEL_ROLES.referenceSheet.model;\nexport const ASPECT_ADAPT_MODEL = MODEL_ROLES.aspectAdapt.model;\nexport const PLATE_JUDGE_MODEL = MODEL_ROLES.plateJudge.model;\nexport const AD_DESCRIBE_MODEL = MODEL_ROLES.adDescribe.model;\nexport const BLUEPRINT_ANALYSIS_MODEL = MODEL_ROLES.blueprintAnalysis.model;\nexport const VIEWER_CHECK_MODEL = MODEL_ROLES.viewerCheck.model;\nexport const CUSTOMER_INSIGHTS_MODEL = MODEL_ROLES.customerInsights.model;\nexport const GLANCE_CHECK_MODEL = MODEL_ROLES.glanceCheck.model;\nexport const TEXT_BOX_READER_MODEL = MODEL_ROLES.textBoxReader.model;\nexport const SUBJECT_BOX_READER_MODEL = MODEL_ROLES.subjectBoxReader.model;\nexport const SIZE_MATCH_MODEL = MODEL_ROLES.sizeMatch.model;\nexport const VIDEO_DECONSTRUCT_MODEL = MODEL_ROLES.videoDeconstruct.model;\nexport const IMAGE_SEARCH_MODEL = MODEL_ROLES.imageSearch.model;\nexport const VOICEOVER_MODEL = MODEL_ROLES.voiceover.model;\nexport const SOUND_EFFECT_MODEL = MODEL_ROLES.soundEffect.model;\nexport const MUSIC_BED_MODEL = MODEL_ROLES.musicBed.model;\nexport const VOICE_CONVERT_MODEL = MODEL_ROLES.voiceConvert.model;\n\n/**\n * Whether `model` is registered for `kind` (legacy ids included). The question a\n * caller asks before trusting a model id it did not pick itself: a flag, a stored\n * rebuild context.\n */\nexport function isRegisteredModel(kind: NodeKind, model: string): boolean {\n return MODEL_REGISTRY[kind]?.[canonicalModelId(model)] !== undefined;\n}\n\n/**\n * Every ratio at least one curated image model renders, in first-seen order. What a\n * requested ad format can be when the plate is rendered for it; the chosen model then\n * snaps to its nearest (`nearestSupportedAspectRatio`).\n */\nexport function imageGenerateAspectRatios(): string[] {\n const seen = new Set<string>();\n for (const model of IMAGE_GENERATE_MODELS) {\n for (const ratio of supportedAspectRatios(\"image_generate\", model) ?? []) seen.add(ratio);\n }\n return [...seen];\n}\n\n// ---------------------------------------------------------------------------\n// Capability lookups\n// ---------------------------------------------------------------------------\n//\n// Scaffolders build node params for whatever model the caller picked, and the\n// curated models do NOT agree on what they accept: gpt-image-2 has no\n// `image_size` and no 4:5/5:4, Gemini flash goes down to 0.5K and out to 8:1.\n// Reading the registry keeps that knowledge in one place instead of a per-model\n// `if` at every site that emits an `image_generate` node.\n\n/** Whether a model accepts a canonical param at all — false for unknown models. */\n/**\n * Models whose output ALWAYS carries an audio track, with no knob to turn it off.\n *\n * Needed because \"no `generate_audio` param\" means two opposite things in this\n * registry: Omni rejects the param because audio is always on and cannot be\n * disabled, while `alibaba/wan-2.6` rejects it because it has no audio at all.\n * A caller reading only `generateAudio` cannot tell them apart — and would read\n * the DEFAULT video model, which always speaks, as silent.\n */\nconst ALWAYS_AUDIO_VIDEO_MODELS = [\"google/gemini-omni-1.1-flash\", \"google/gemini-omni-flash\"] as const;\n\n/**\n * Whether a rendered clip has a voice on it — the question anything doing\n * post-processing on the audio has to answer before it spends money.\n *\n * `generateAudio` is what the batch RECORDED, which is `undefined` whenever the\n * model exposes no such param; that is why the model has to be consulted too.\n */\nexport function clipCarriesAudio(model: string, generateAudio: boolean | undefined): boolean {\n if ((ALWAYS_AUDIO_VIDEO_MODELS as readonly string[]).includes(model)) return true;\n if (!supportsParam(\"video_generate\", model, \"generate_audio\")) return false;\n return generateAudio === true;\n}\n\nexport function supportsParam(kind: NodeKind, model: string, param: string): boolean {\n return modelSpec(kind, model)?.params[param] !== undefined;\n}\n\n/**\n * How long a prompt this model reads, or undefined when it advertises no cap.\n *\n * Undefined is a real answer and must not be treated as zero or as a default —\n * the Gemini image models publish no character limit, and inventing one would\n * refuse briefs that render fine today.\n */\n/**\n * The clip length the Studio asks for when the caller pins none.\n *\n * Distinct from `DEFAULT_VIDEO_DURATION_S` in `videoCost`, which is what the\n * PRICE falls back to for a clip that never declared a length. This one is a\n * product choice about what to render, and the two only look alike today.\n */\nexport const DEFAULT_CLIP_DURATION_S = 5;\n\n/**\n * What a clip gets when nobody pins a length, given whether anyone speaks in it.\n *\n * Five seconds is enough to show something and nowhere near enough to SAY something.\n * A line written for an ad is a full sentence, and delivered inside five seconds it comes\n * out rushed — the words land on top of each other, the mouth runs ahead of the meaning,\n * and the take is unusable however good the picture is. Eight is the floor where a\n * sentence can be spoken at the pace a person would actually use.\n *\n * Silent clips keep the five: b-roll, a product turning, a logo landing. They are not\n * saying anything, so the extra seconds buy nothing and cost real money — a clip is\n * billed by the second.\n */\nexport function clipSecondsFor({ speaks, spokenWords }: { speaks: boolean; spokenWords?: number }): number {\n if (!speaks) return DEFAULT_CLIP_DURATION_S;\n // Sized to the script, because the model does not run over when the line is too long —\n // it speeds up, and the take comes back with syllables swallowed and endings clipped.\n // Measured on a real one: 40 words asked for in 8s is 5 words a second against a\n // natural 2.5, and it read as the avatar mumbling.\n const needed = Math.ceil((spokenWords ?? 0) / SPOKEN_WORDS_PER_SECOND);\n return Math.max(SPOKEN_CLIP_DURATION_S, needed);\n}\n\n/** Unhurried ad delivery, ~150 wpm. The natural rate, not the fastest intelligible one. */\nexport const SPOKEN_WORDS_PER_SECOND = 2.5;\n\n/**\n * A quote that opens or closes a spoken line, rather than an apostrophe inside a word.\n *\n * Position decides, not the character. A bare `'` used to count as a delimiter wherever it\n * appeared, so two ordinary possessives paired up and the DIRECTION between them was read\n * as speech: \"Marta's kitchen \\u2026 about the family's energy bill\" scored 14 words of dialogue\n * in a brief where nobody had spoken yet, which lengthened a clip billed by the second and\n * told the agent a silent b-roll brief had a line in it.\n *\n * So a delimiter is flanked-checked \\u2014 a quote opening or closing a line never has a letter\n * on its inner side, and the apostrophe in `Marta's` always does. That check has to be made\n * on BOTH sides of the capture, and missing the second half is its own bug: barring the\n * apostrophe from the line's CONTENT as well left an English line unmatchable, because the\n * first contraction ended the run before it reached eight characters. `\"We'll cut your bill\n * in half\"` scored zero \\u2014 read as nobody speaking, which drops the clip to the bare floor\n * and silences the two hints that exist to catch exactly that.\n *\n * Hence the alternation: any non-quote character, or an apostrophe with a letter on both\n * sides. The branches are disjoint, so there is nothing for the engine to backtrack over.\n */\nconst SPOKEN_LINE =\n /(?<![\\p{L}\\p{N}])['\"\\u201c\\u201d\\u2018\\u2019]((?:[^'\"\\u201c\\u201d\\u2018\\u2019]|(?<=\\p{L})['\\u2019](?=\\p{L})){8,})['\"\\u201c\\u201d\\u2018\\u2019](?![\\p{L}\\p{N}])/gu;\n\n/**\n * The words a motion brief asks to be SAID, which is the quoted part of it.\n *\n * The direction around the line (\"she walks in and says\") is performed, not spoken, and\n * counting it would shorten every line for no reason.\n */\nexport function spokenWordsIn(prompt: string | undefined): number {\n if (!prompt) return 0;\n const quoted = [...prompt.matchAll(SPOKEN_LINE)].map((m) => m[1] ?? \"\");\n const text = quoted.join(\" \").trim();\n return text ? text.split(/\\s+/).filter(Boolean).length : 0;\n}\n\n/** The floor for a clip with a line in it. See `clipSecondsFor`. */\nexport const SPOKEN_CLIP_DURATION_S = 8;\n\n/**\n * The clip length a request settles on when the caller pins none: the nearest\n * length the model renders to `preferred`, ties going to the shorter.\n *\n * Exported because two callers have to agree on it — the request that sends the\n * duration and the estimate that quotes its price. If the estimate leaves the\n * duration unset while the request resolves and sends one, the two quote\n * different clips, and the caller is told a number the charge never matches.\n */\nexport function nearestClipDuration(model: string, preferred: number): number {\n const schema = MODEL_REGISTRY.video_generate[model]?.params.duration;\n const allowed = schema?.kind === \"number\" ? schema.enum : undefined;\n if (!allowed?.length || allowed.includes(preferred)) return preferred;\n return [...allowed].sort((a, b) => Math.abs(a - preferred) - Math.abs(b - preferred) || a - b)[0] as number;\n}\n\n/**\n * Models that render no sound at all — `generate_audio: false` or absent on their\n * OpenRouter listing.\n *\n * Needed because \"no audio toggle\" means two opposite things. Omni has none because it\n * ALWAYS renders synchronized sound; Runway has none because it never renders any. The\n * Studio hid the same control for both, so a marketer saw nothing either way and found\n * out which kind they had picked by watching a silent clip they had already paid for.\n */\nconst SILENT_VIDEO_MODELS: ReadonlySet<string> = new Set([\n \"runway/gen-4.5\",\n \"x-ai/grok-imagine-video\",\n \"x-ai/grok-imagine-video-1.5\",\n \"alibaba/happyhorse-1.1\",\n]);\n\n/** What a model does about sound: the caller's choice, always on, or never. */\nexport type ClipAudioMode = \"toggle\" | \"always\" | \"never\";\n\n/** Whether this model renders sound, and whether the caller gets a say. */\nexport function clipAudioMode(model: string): ClipAudioMode {\n if (supportsParam(\"video_generate\", model, \"generate_audio\")) return \"toggle\";\n return SILENT_VIDEO_MODELS.has(model) ? \"never\" : \"always\";\n}\n\n/** Every clip length a model renders, ascending, or undefined when it declares no set. */\nexport function clipDurationsFor(model: string): number[] | undefined {\n const schema = MODEL_REGISTRY.video_generate[model]?.params.duration;\n const allowed = schema?.kind === \"number\" ? schema.enum : undefined;\n return allowed?.length ? [...allowed].sort((a, b) => a - b) : undefined;\n}\n\n/** The longest clip a model will render, or undefined when it declares no set. */\nexport function maxClipSeconds(model: string): number | undefined {\n const allowed = clipDurationsFor(model);\n return allowed ? (allowed[allowed.length - 1] as number) : undefined;\n}\n\n/** One clip's worth of script on a given model. */\nexport interface ScriptSplit {\n /** How many clips the line has to be broken into. */\n clips: number;\n /** Roughly how many words each should carry. */\n wordsPerClip: number;\n /** The longest single clip this model renders. */\n maxSeconds: number;\n}\n\n/**\n * How to break a script that outruns the model, or null when it fits in one clip.\n *\n * Gemini Omni stops at 10 seconds — about 25 words — and a real testimonial is longer\n * than that. Handed the whole thing it does not refuse and it does not truncate: it\n * rushes, which is the failure this exists to prevent. So a script that does not fit is\n * a SEQUENCE, and the number of pieces is arithmetic rather than judgement.\n */\nexport function splitScriptFor(words: number, model: string): ScriptSplit | null {\n const maxSeconds = maxClipSeconds(model);\n if (!maxSeconds) return null;\n const perClip = Math.floor(maxSeconds * SPOKEN_WORDS_PER_SECOND);\n if (words <= perClip) return null;\n const clips = Math.ceil(words / perClip);\n return { clips, wordsPerClip: Math.ceil(words / clips), maxSeconds };\n}\n\nexport function promptMaxLength(kind: NodeKind, model: string): number | undefined {\n const schema = modelSpec(kind, model)?.params.prompt;\n return schema?.kind === \"string\" ? schema.maxLength : undefined;\n}\n\n/**\n * The declared input slot of one kind, or undefined when the model has none.\n *\n * Reads the OPTIONAL slots first because that is where every generate model\n * declares references; the required slots cover the nodes (sheet, adapt) whose\n * source asset is mandatory.\n *\n * ABSENCE is the load-bearing answer here, and it is not the same as a slot with\n * no cap: `undefined` means the model does not read that kind at all, whereas a\n * slot whose `max` is undefined means it reads them with no ceiling we have\n * confirmed. Callers that need \"can it?\" must ask this, not `maxInputSlot`.\n */\nfunction inputSlot(kind: NodeKind, model: string, inputKind: InputKind): InputSpec | undefined {\n const spec = modelSpec(kind, model);\n return (\n spec?.optional_inputs?.find((input) => input.kind === inputKind) ??\n spec?.inputs.find((input) => input.kind === inputKind)\n );\n}\n\n/** How many assets of one kind the model's slot takes; undefined = no cap advertised. */\nexport function maxInputSlot(kind: NodeKind, model: string, inputKind: InputKind): number | undefined {\n return inputSlot(kind, model, inputKind)?.max;\n}\n\n/**\n * How many images this model takes in its reference slot, or undefined when no\n * cap is advertised.\n */\nexport function maxInputReferences(kind: NodeKind, model: string): number | undefined {\n return maxInputSlot(kind, model, \"image\");\n}\n\n/**\n * Every quality step any image model in this registry declares, worst to best.\n *\n * Exported because the CLI's `image_generate` node schema needs a zod enum and had been\n * carrying its own copy — one that stopped at `high` and was never widened when the 2.5\n * ladder gained `xhigh` and `max`. That second copy did not merely drift, it BLOCKED the\n * ad path outright: `scaffold-ad` pins gpt-image-2.5, `bestSupportedQuality` correctly\n * returned `xhigh` for it, and every ad scaffolded then failed its own validation before\n * a single node ran. Which model may use which step is still decided per model, by\n * `validateModelParams` against this registry — this list only says what the word can be.\n */\nexport const IMAGE_QUALITY_STEPS = [\"auto\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\n/**\n * How many images one call to this model returns at most: its `n` ceiling, or 1 for a\n * model that declares no `n`. One is a real answer, never \"unknown\": such a model is\n * sent no `n` and renders one image per call, so N variants from it are N calls.\n */\nexport function maxImagesPerCall(kind: NodeKind, model: string): number {\n const schema = modelSpec(kind, model)?.params.n;\n return schema?.kind === \"number\" && schema.max !== undefined ? schema.max : 1;\n}\n\n/** The quality steps a model accepts, or undefined when it has no `quality` enum. */\nexport function supportedQualities(kind: NodeKind, model: string): readonly string[] | undefined {\n const schema = modelSpec(kind, model)?.params.quality;\n return schema?.kind === \"string\" ? schema.enum : undefined;\n}\n\n/**\n * The quality step to send a model when you want `want`.\n *\n * Undefined when the model has no `quality` knob — Gemini's endpoints do not list one,\n * and the registry deliberately does not declare it, so emitting it fails validation\n * before the call. Otherwise the highest step at or below `want`: a scaffolder writes one\n * canvas for whichever model is pinned, and the older gpt-image entries stop at `high`,\n * where an undeclared value is `unknown_param` rather than a softer picture.\n */\nexport function bestSupportedQuality(kind: NodeKind, model: string, want: string): string | undefined {\n const supported = supportedQualities(kind, model);\n if (!supported) return undefined;\n if (supported.includes(want)) return want;\n // Ordered worst to best in the registry, so the last one at or below `want` wins.\n const ladder = supported.filter((step) => step !== \"auto\");\n const ceiling = ladder.indexOf(want);\n const reachable = ceiling === -1 ? ladder : ladder.slice(0, ceiling);\n return reachable[reachable.length - 1];\n}\n\n/** The ratios a model accepts, or undefined when it has no `aspect_ratio` enum. */\nexport function supportedAspectRatios(kind: NodeKind, model: string): readonly string[] | undefined {\n const schema = modelSpec(kind, model)?.params.aspect_ratio;\n return schema?.kind === \"string\" ? schema.enum : undefined;\n}\n\nfunction ratioValue(ratio: string): number | null {\n const [w, h] = ratio.split(\":\").map(Number);\n if (!w || !h || !Number.isFinite(w) || !Number.isFinite(h)) return null;\n return w / h;\n}\n\n/**\n * Snap a target ratio onto what `model` actually accepts, picking the closest\n * supported shape when the exact one is missing (4:5 → 3:4 on gpt-image-2).\n * Returns the target untouched when the model has no ratio enum or already\n * supports it, so callers can apply this unconditionally.\n */\nexport function nearestSupportedAspectRatio(kind: NodeKind, model: string, target: string): string {\n const supported = supportedAspectRatios(kind, model);\n if (!supported || supported.includes(target)) return target;\n const wanted = ratioValue(target);\n if (wanted === null) return target;\n let best = target;\n let bestDistance = Number.POSITIVE_INFINITY;\n for (const candidate of supported) {\n const value = ratioValue(candidate);\n if (value === null) continue;\n const distance = Math.abs(Math.log(value / wanted));\n if (distance < bestDistance) {\n bestDistance = distance;\n best = candidate;\n }\n }\n return best;\n}\n\n/** Size tiers a model accepts; undefined = the model has no `image_size` param. */\nfunction supportedImageSizes(kind: NodeKind, model: string): readonly string[] | undefined {\n const schema = modelSpec(kind, model)?.params.image_size;\n return schema?.kind === \"string\" ? schema.enum : undefined;\n}\n\nconst IMAGE_SIZE_ORDER = [\"0.5K\", \"1K\", \"2K\", \"4K\"];\n\n/**\n * Clamp a size tier into what the model actually renders — the\n * `nearestSupportedAspectRatio` treatment for size: snap rather than reject, so a\n * caller who asks a 1K-only model (Nano Banana 2 Lite) for the scaffold's default\n * 2K keyframe gets its best available render instead of a hard validation failure.\n *\n * It prefers to snap DOWN (the largest tier at or below the target), because\n * rendering bigger than asked for costs more than the caller agreed to. When the\n * model's FLOOR is above the target it returns that floor — the smallest thing it\n * can render — since there is no cheaper option to offer. No curated model has a\n * floor above `0.5K` today, so that branch is currently unreachable.\n */\nexport function nearestSupportedImageSize(kind: NodeKind, model: string, target: string): string {\n const supported = supportedImageSizes(kind, model);\n if (!supported || supported.includes(target)) return target;\n const wanted = IMAGE_SIZE_ORDER.indexOf(target);\n if (wanted < 0) return target;\n const ranked = supported\n .filter((s) => IMAGE_SIZE_ORDER.includes(s))\n .sort((a, b) => IMAGE_SIZE_ORDER.indexOf(a) - IMAGE_SIZE_ORDER.indexOf(b));\n if (ranked.length === 0) return target;\n const belowOrEqual = ranked.filter((s) => IMAGE_SIZE_ORDER.indexOf(s) <= wanted);\n return belowOrEqual.length > 0 ? (belowOrEqual[belowOrEqual.length - 1] as string) : (ranked[0] as string);\n}\n\n// NOTE: `IMAGE_GENERATE_MODELS` (above) must list exactly the keys of\n// `MODEL_REGISTRY.image_generate`. A compile-time check isn't possible —\n// MODEL_REGISTRY's `Record<string, ModelSpec>` annotation widens its keys to\n// `string` — so the invariant is enforced by `registry.test.ts` instead, which\n// keeps this module a pure, side-effect-free data export.\n","/**\n * The one conversion between provider dollars and Baker credits.\n *\n * Lives in its own module, imported by both `videoCost.ts` and `nodeCost.ts`,\n * so neither has to import the other for it (a cycle there leaves the constant\n * uninitialised for whichever module loads second).\n */\n\n/** Credits per USD of provider cost. The backend ledger reads this same constant. */\nexport const CREDITS_PER_USD = 100;\n\n/**\n * Whole credits for a USD amount: rounded UP, so a quote or a reported charge is\n * never under what the ledger records.\n *\n * The snap to 6 decimals first matters: `0.112 * 5 * 100` is 56.00000000000001\n * in IEEE-754, and a bare ceil turns an exact 56 into 57.\n *\n * The ledger itself stores exact fractional credits (`credits/utils.ts`), so this\n * is the rule for every WHOLE-credit figure: the engine's pre-run quote and the\n * `credits_charged` a node execution reports back.\n */\nexport function usdToCredits(usd: number): number {\n if (!(usd > 0)) return 0;\n return Math.ceil(Number((usd * CREDITS_PER_USD).toFixed(6)));\n}\n","/**\n * Per-model video cost, shared by everything that needs to say what a clip will\n * cost BEFORE it runs: the engine's pre-run estimate, the backend's per-request\n * cost cap, and the studio's prompt bar.\n *\n * It lives in the contract, next to the model registry, because a price is\n * per-model data exactly like a duration enum — and because the estimate and the\n * charge drifting apart is the failure this module exists to prevent. The engine\n * previously quoted a FLAT 50 credits for every clip regardless of duration,\n * resolution, or model, which under-quoted a 1080p 8s clip by roughly 10×.\n */\n\nimport { CREDITS_PER_USD, usdToCredits } from \"./credits\";\nimport { isGeminiOmniModel, isGeminiOmniPreviewModel, isSeedance25Model, perSecondBilling } from \"./registry\";\n\nexport { MIN_BILLED_SECONDS } from \"./registry\";\n\nexport { CREDITS_PER_USD };\n\n/**\n * The opening still an avatar clip renders before it animates anything.\n *\n * On the framed route a clip is TWO billed calls, not one: a gpt-image-2 frame\n * ($0.03 per image, OpenRouter's published `image_output` rate) and then the\n * clip itself. Quoting only the clip understates every avatar take, and a quote\n * shown before spending must never be under the charge.\n */\nexport const OPENING_FRAME_CREDITS = usdToCredits(0.03);\n\n/**\n * Seedance $/second by resolution. 4k bills at the 1080p rate as a conservative\n * floor until a real 4k rate exists.\n */\nexport const SEEDANCE_USD_PER_SECOND: Readonly<Record<string, number>> = {\n \"480p\": 0.18,\n \"720p\": 0.5,\n \"1080p\": 0.62,\n \"4k\": 0.62,\n};\n\n/** What the provider assumes when a clip does not pin a resolution. */\nexport const DEFAULT_VIDEO_RESOLUTION = \"720p\";\n\n/** What a clip costs when the model does not declare a duration. */\nexport const DEFAULT_VIDEO_DURATION_S = 5;\n\nexport function isSeedanceModel(model: string): boolean {\n return model.startsWith(\"bytedance/seedance\");\n}\n\n// ---------------------------------------------------------------------------\n// Seedance 2.5 — billed in VIDEO TOKENS, and the token count is a pure function\n// of the frame rather than a per-second sticker price.\n//\n// OpenRouter publishes `pricing_skus.video_tokens: 0.0000107` and no rate per\n// second. The conversion is exact and was checked against the advertised floor\n// on BOTH Seedance tiers before being written down:\n//\n// tokens = (width × height / 1024) × 24fps × seconds\n//\n// 2.5 cheapest frame 854×480 → 400.3125 × 24 × 0.0000107 = $0.102800/s,\n// against the model page's \"starting at $0.1028 per second\".\n// 2.0 cheapest frame 480×854 → 400.3125 × 24 × 0.0000007 = $0.067252/s,\n// against its page's \"from $0.06726/second\". Two independent hits, so the\n// formula is the provider's, not a coincidence of one rounding.\n//\n// Rates below are the DEAREST frame in each tier (21:9 is wider than 16:9 at the\n// same nominal resolution — 992×432 and 1112×834 are the real maxima), rounded\n// up. Quoting the 16:9 frame instead would under-quote a 21:9 clip, and this\n// module's whole rule is that the estimate must never land under the charge.\n//\n// Two things NOT to re-derive later: audio is free on this tier\n// (`video_tokens_without_audio` is the same 0.0000107, unlike every other model\n// here where sound is a higher rate), and a clip given a VIDEO reference bills at\n// 0.0000064 — cheaper, so ignoring it keeps the estimate conservative.\n// ---------------------------------------------------------------------------\n\n/** OpenRouter `pricing_skus.video_tokens` for `bytedance/seedance-2.5`. */\nexport const SEEDANCE_25_USD_PER_VIDEO_TOKEN = 0.0000107;\n\nexport const SEEDANCE_25_USD_PER_SECOND: Readonly<Record<string, number>> = {\n \"480p\": 0.1075,\n \"720p\": 0.2326,\n};\n\n/** The tier this model renders when a clip pins no resolution — its dearest, so an unpinned clip is never under-quoted. */\nconst SEEDANCE_25_FALLBACK_USD_PER_SECOND = 0.2326;\n\nexport function seedance25UsdPerSecond(resolution: string | undefined): number {\n return SEEDANCE_25_USD_PER_SECOND[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? SEEDANCE_25_FALLBACK_USD_PER_SECOND;\n}\n\n/** Rate for an unrecognised resolution — the 720p middle tier, never zero. */\nconst FALLBACK_USD_PER_SECOND = 0.5;\n\n/**\n * Seconds a clip is billed for: its length, or the floor its registry entry\n * declares (`minBilledSeconds`), whichever is longer. See `MIN_BILLED_SECONDS`.\n */\nfunction billedSeconds(model: string, duration: number): number {\n const floor = perSecondBilling(model)?.minBilledSeconds;\n return floor === undefined ? duration : Math.max(duration, floor);\n}\n\nexport function seedanceUsdPerSecond(resolution: string | undefined): number {\n return SEEDANCE_USD_PER_SECOND[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? FALLBACK_USD_PER_SECOND;\n}\n\n// ---------------------------------------------------------------------------\n// Gemini Omni Flash — billed in TOKENS, which come out to a clean per-second rate.\n//\n// Omni is the one model here priced by token rather than by second, but the two\n// reconcile exactly, and on 1.1 they reconcile PER RESOLUTION. Measured on the\n// live API, video output tokens are dead linear in both length and tier: 720p\n// returned 17,376 tokens for 3.008s and 34,752 for 6.016s, and holding the length\n// at 3s the four tiers returned 5,793 / 17,376 / 26,064 / 52,128 — exactly a\n// third, one, one and a half, and three times the 720p rate.\n//\n// The PREVIEW model (`google/gemini-omni-flash`) shares the per-second rate and\n// differs on the TIER, which is the one thing it has to be priced separately for.\n// It accepts a `resolution` and then IGNORES it: asked for 360p it returned a\n// 1280x720 clip and billed 17,376 tokens, the 720p rate, not the 5,793 that tier\n// costs. So it is quoted at 720p whatever was asked, because that is what it\n// renders — passing the requested tier through would quote a 360p request at a\n// third of its charge, which is the failure this module exists to prevent.\n//\n// Historical note, because the previous version of this file encoded it: the\n// preview USED to bill its whole ten-second window whatever length it returned\n// (a 3s and a 4s render both billing ~$1.034). Re-measured, that is gone — 3s\n// now bills 17,376 tokens and 6s 34,752, the same per-second line as 1.1. The\n// window quote came off with it; a flat ~$1.09 for a 3s clip would now be a 3.4x\n// OVER-quote, and being wrong in the safe direction is still being wrong.\n//\n// The one trap both share is the DEFAULT. Omni renders 10s when the prompt names\n// no length — its ceiling, not the module's usual 5s assumption — so an\n// unspecified clip must be quoted at 10s or it is under-quoted by half.\n// ---------------------------------------------------------------------------\n\n/** Google's published rate for Gemini Omni video OUTPUT tokens. */\nexport const GEMINI_OMNI_USD_PER_1M_VIDEO_TOKENS = 17.5;\n/** Video output tokens per second of 720p Omni footage (published, and measured). */\nexport const GEMINI_OMNI_VIDEO_TOKENS_PER_SECOND = 5_792;\n\n/**\n * What each resolution tier costs relative to 720p, measured rather than assumed.\n *\n * Keyed by the exact strings `GEMINI_OMNI_RESOLUTIONS` offers — including the\n * lowercase `4k`, which is the spelling Omni's API accepts and NOT the `4K` Veo\n * takes. A tier missing from this table falls back to 720p below, which is also\n * what the adapter renders when it sends no resolution at all.\n */\nexport const GEMINI_OMNI_RESOLUTION_MULTIPLIER: Readonly<Record<string, number>> = {\n \"360p\": 1 / 3,\n \"720p\": 1,\n \"1080p\": 1.5,\n \"4k\": 3,\n};\n\n/** What Omni renders when a request names no resolution. */\nexport const GEMINI_OMNI_DEFAULT_RESOLUTION = \"720p\";\n\n/**\n * Output tokens each Omni render spends on THINKING, billed at the video rate\n * alongside the picture.\n *\n * A flat allowance rather than a percentage, because that is what it measures as:\n * five renders spanning 3-6 seconds and all four tiers spent 300, 386, 461, 490\n * and 552 thought tokens — no correlation with either axis. So it is 0.6% of a 4K\n * clip and 8% of a 3s 360p draft, and a percentage margin would mis-size it at\n * both ends. 600 sits above every measurement.\n *\n * Without it the cheapest tier is the one that gets under-quoted, which is the\n * one rule this module has: a 3s 360p clip returned 5,793 video tokens and billed\n * $0.1088 against the $0.1014 its video alone predicts.\n */\nexport const GEMINI_OMNI_OVERHEAD_TOKENS = 600;\n\n/**\n * The length an un-timed Omni clip comes back at, on both models — its own\n * ceiling, not the module's usual 5s assumption. So it is the length to quote\n * when `duration` is unset.\n */\nexport const GEMINI_OMNI_WINDOW_SECONDS = 10;\n\n/**\n * USD per second of 720p Omni footage (~$0.101); multiply by the tier above for\n * the rest. Input tokens ($1.50/1M) are left out: a prompt plus a reference image\n * measured ~1.1k tokens — under a fifth of a cent, noise against the video\n * output, and far too small to push the estimate under the charge.\n */\nexport const GEMINI_OMNI_USD_PER_SECOND =\n (GEMINI_OMNI_VIDEO_TOKENS_PER_SECOND * GEMINI_OMNI_USD_PER_1M_VIDEO_TOKENS) / 1_000_000;\n\n/** USD per second of Omni footage at one resolution tier. */\nexport function geminiOmniUsdPerSecond(resolution: string | undefined): number {\n const multiplier = GEMINI_OMNI_RESOLUTION_MULTIPLIER[resolution ?? GEMINI_OMNI_DEFAULT_RESOLUTION] ?? 1;\n return GEMINI_OMNI_USD_PER_SECOND * multiplier;\n}\n\n/**\n * How much MORE a clip costs when it is built on a source clip.\n *\n * A measured ceiling, not a derived formula. One real render — 4s, 480p, one\n * source clip — returned 854x480 exactly as asked and then billed $0.8522\n * against the $0.4112 the per-second table predicts: 2.07x. The extra is not in\n * any published SKU, so it cannot be modelled; what IS certain is its direction,\n * and this module's one rule is that an estimate must never land under the\n * charge. Rounded up from the single measurement rather than fitted to it.\n *\n * Re-measure before trusting this to be tight. It is deliberately loose.\n */\nexport const VIDEO_SOURCE_COST_MULTIPLIER = 2.5;\n\n// ---------------------------------------------------------------------------\n// Seedance 2.5 through fal — the route that renders human faces.\n//\n// fal publishes the same token formula as OpenRouter and charges exactly twice\n// per token ($0.0214 per 1,000 against $0.0107), which is why it is the recovery\n// and not the main road. Both apply the same 0.6 discount when a source clip is\n// wired, and neither charges for image or audio references.\n//\n// tokens = (width x height x (input_video_seconds + output_seconds) x 24) / 1024\n//\n// The input-video term is fal's own, and it is why a clip built on a long source\n// costs more than its own length suggests.\n// ---------------------------------------------------------------------------\n\n/** fal's published rate for this model, per 1,000 video tokens. */\nexport const FAL_SEEDANCE_USD_PER_1K_TOKENS = 0.0214;\n\n/**\n * What a fal render REALLY cost, from the billable units it reports back.\n *\n * fal's `x-fal-billable-units` header is the render's video-token count in\n * thousands — the same unit its price is quoted in — so the charge is one\n * multiplication rather than a re-derivation of the frame. Prefer this to\n * `falSeedanceUsdPerSecond` whenever a response is in hand: the estimate quotes\n * the DEAREST frame of the tier on purpose, which is right for a quote and about\n * 3% too high as a charge (a measured 4s/480p clip billed 38.83 units against the\n * 40.18 the widest frame predicts).\n */\nexport function falSeedanceUsdFromBillableUnits(units: number): number {\n return units * FAL_SEEDANCE_USD_PER_1K_TOKENS;\n}\n\n/** Both routes discount a render that is guided by a source clip. */\nexport const SEEDANCE_SOURCE_CLIP_DISCOUNT = 0.6;\n\n/** Frame dimensions per resolution tier, widest shape first — the dearest frame in each. */\nconst SEEDANCE_DEAREST_FRAME: Readonly<Record<string, { width: number; height: number }>> = {\n \"480p\": { width: 992, height: 432 },\n \"720p\": { width: 1112, height: 834 },\n};\n\n/**\n * What one fal render costs, from fal's own formula.\n *\n * Quoted on the DEAREST frame of the tier for the same reason the OpenRouter\n * table is: a 21:9 clip is wider than a 16:9 one at the same nominal resolution,\n * and quoting the narrow one under-quotes the wide one.\n */\nexport function falSeedanceUsdPerSecond(resolution: string | undefined, buildsOnSourceClip = false): number {\n const frame = SEEDANCE_DEAREST_FRAME[resolution ?? DEFAULT_VIDEO_RESOLUTION] ?? SEEDANCE_DEAREST_FRAME[\"720p\"];\n const tokensPerSecond = ((frame?.width ?? 1112) * (frame?.height ?? 834) * 24) / 1024;\n const rate = (tokensPerSecond * FAL_SEEDANCE_USD_PER_1K_TOKENS) / 1000;\n return buildsOnSourceClip ? rate * SEEDANCE_SOURCE_CLIP_DISCOUNT : rate;\n}\n\nexport interface VideoCostInput {\n model: string;\n duration?: number;\n resolution?: string;\n generateAudio?: boolean;\n /**\n * Whether the clip is built on an existing clip. Costs more than the per-second\n * table says — see `VIDEO_SOURCE_COST_MULTIPLIER`.\n */\n buildsOnSourceClip?: boolean;\n /**\n * Whether the request carries reference IMAGES, which is what decides the route\n * — and therefore the price.\n *\n * A reference image MIGHT contain a face, and a face sends the render to fal at\n * twice the price. Nothing can tell in advance which images have faces, so a\n * request that carries any is quoted at the dearer route. Over-quoting a\n * product shot is the cheap mistake; under-quoting every clip with a person in\n * it is the one this module exists to prevent.\n */\n mayRouteToFal?: boolean;\n}\n\n/**\n * What one Omni clip costs, for either version.\n *\n * The preview ignores the tier and renders 720p, so it is quoted at 720p whatever\n * was asked — honouring the request would quote a 360p clip at a third of its\n * charge, on the one model where asking for 360p changes nothing. `isGeminiOmniModel`\n * matches both ids, so the version test lives here rather than beside the caller.\n */\nfunction geminiOmniCostUsd(model: string, duration: number | undefined, resolution: string | undefined): number {\n const tier = isGeminiOmniPreviewModel(model) ? GEMINI_OMNI_DEFAULT_RESOLUTION : resolution;\n const footage = geminiOmniUsdPerSecond(tier) * (duration ?? GEMINI_OMNI_WINDOW_SECONDS);\n return footage + (GEMINI_OMNI_OVERHEAD_TOKENS * GEMINI_OMNI_USD_PER_1M_VIDEO_TOKENS) / 1_000_000;\n}\n\n/**\n * Seedance 2.0 through Replicate or, for a clip that may be refused as a face\n * and recovered, the fal route, whichever is dearer. The recovery renders 2.5\n * whichever Seedance was asked for and drops a tier 2.5 does not have (1080p,\n * 4k) so fal picks its own, priced here at its dearest frame. At 480p that route\n * costs more than Replicate's 2.0 rate.\n */\nfunction seedance20CostUsd(resolution: string | undefined, seconds: number, mayRouteToFal: boolean): number {\n const viaReplicate = seedanceUsdPerSecond(resolution) * seconds;\n if (!mayRouteToFal) return viaReplicate;\n const falTier = resolution === \"480p\" || resolution === \"720p\" ? resolution : undefined;\n return Math.max(viaReplicate, falSeedanceUsdPerSecond(falTier) * seconds);\n}\n\n/**\n * USD estimate for one clip.\n *\n * Veo and Kling bill by provider usage reported in the response, so their true\n * cost is not knowable up front. Rather than quote a flat number that is wrong\n * in the DANGEROUS direction (too low), they are estimated at the most expensive\n * known per-second rate — an over-estimate scales with the clip, and a user who\n * is quoted more than they are charged is never the one who gets hurt.\n */\nexport function estimateVideoCostUsd(input: VideoCostInput): number {\n const { model, duration, resolution, generateAudio, buildsOnSourceClip } = input;\n const seconds = billedSeconds(model, duration ?? DEFAULT_VIDEO_DURATION_S);\n const sourceClipPremium = buildsOnSourceClip ? VIDEO_SOURCE_COST_MULTIPLIER : 1;\n // Omni defaults to its 10s CEILING when the prompt names no length, not to the\n // 5s this module assumes elsewhere — so it resolves its own default before the\n // shared one, or every un-timed clip is quoted at half what it bills. That is\n // the only special case left: 1.1 bills the seconds it renders and the tier it\n // renders them at, both linear and both measured (see the constants above).\n if (isGeminiOmniModel(model)) return geminiOmniCostUsd(model, duration, resolution);\n // 2.5 before the family test, or it would be priced off the Replicate table for\n // 2.0 — which quotes 720p at $0.50/s against its real $0.2326, more than double.\n if (isSeedance25Model(model)) {\n const viaOpenRouter = seedance25UsdPerSecond(resolution) * seconds * sourceClipPremium;\n if (!input.mayRouteToFal) return viaOpenRouter;\n // Either route can serve this clip and only the face filter decides which, so\n // the quote is the DEARER of the two rather than simply the fal one: fal\n // DISCOUNTS a source-clip render while the measured OpenRouter premium raises\n // it, so on that one combination the fal number is the lower of the two and\n // quoting it would land the estimate under the charge.\n return Math.max(viaOpenRouter, falSeedanceUsdPerSecond(resolution, buildsOnSourceClip) * seconds);\n }\n if (isSeedanceModel(model)) return seedance20CostUsd(resolution, seconds, input.mayRouteToFal === true);\n\n // Published per-second SKUs live on each model's registry entry (`billing`).\n const published = perSecondBilling(model)?.usd;\n if (published) {\n const rate = (resolution ? published.byResolution?.[resolution] : undefined) ?? published;\n return (generateAudio ? rate.audio : rate.silent) * seconds;\n }\n\n // Unknown model: quote the dearest rate we know. Over-quoting is the safe\n // direction — a user charged less than they were told is never the one hurt.\n const dearestKnownRate = Math.max(...Object.values(SEEDANCE_USD_PER_SECOND));\n return dearestKnownRate * seconds;\n}\n\n/** The same estimate in credits, through the one rounding rule (`usdToCredits`). */\nexport function estimateVideoCredits(input: VideoCostInput): number {\n return usdToCredits(estimateVideoCostUsd(input));\n}\n","import cjsModule from '../index.js'\n\nexport const configure = cjsModule.configure\n\nexport const stringify = cjsModule\nexport default cjsModule\n","import stableStringify from \"safe-stable-stringify\";\n\n/**\n * Deterministic JSON encoding for cache keys.\n *\n * Rules (locked — drift breaks all caches):\n * 1. Object keys sorted alphabetically (codepoint order, locale-independent).\n * 2. No whitespace.\n * 3. `undefined` values and entries are dropped (not serialized as null).\n * 4. Strings are NFC-normalized before encoding.\n * 5. Numbers use the shortest representation (V8 default; we don't post-process).\n * 6. `NaN` and `±Infinity` throw — explicit reject, never silently encode.\n * 7. Arrays preserve order.\n */\nexport function canonicalize(value: unknown): string {\n const normalized = normalizeForCanonical(value);\n const out = stableStringify(normalized);\n if (out === undefined) {\n throw new Error(\"canonicalize: value serialized to undefined (top-level undefined?)\");\n }\n return out;\n}\n\nfunction normalizeForCanonical(value: unknown): unknown {\n if (value === null) return null;\n if (typeof value === \"string\") return value.normalize(\"NFC\");\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) {\n throw new Error(`canonicalize: non-finite number ${value}`);\n }\n return value;\n }\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"bigint\") {\n throw new Error(\"canonicalize: bigint not supported\");\n }\n if (Array.isArray(value)) {\n return value.map(normalizeForCanonical);\n }\n if (typeof value === \"object\") {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n if (v === undefined) continue;\n out[k.normalize(\"NFC\")] = normalizeForCanonical(v);\n }\n return out;\n }\n // undefined, function, symbol — drop\n return undefined;\n}\n","/**\n * Whether a clip will be small enough for us to ingest.\n *\n * A finished clip is fetched and held in memory to be hashed and uploaded, inside a\n * Convex action capped at 512 MB. Ask for one big enough and the action dies with\n * \"ran out of memory\" — after the provider has rendered and charged for it, and the\n * user is told \"this one didn't come back, run it again\", which retries into the same\n * wall. Observed on the first 30s/1080p clip anyone rendered, which is a combination\n * that only became possible when Wan 3.0 was added.\n *\n * The rate is measured across three real clips at 720p, and it moves a lot with the\n * content: 8s/9.5 MB (1.19 MB/s), 15s/19.0 MB (1.27), 15s/31.9 MB (2.13). The worst of\n * them is the one used, because underestimating is what produces the crash this exists\n * to prevent — a busy 30s shot is not an unusual ad, it is the normal one.\n */\n\n/** MB per second at 720p — the heaviest of three measured clips, not the average. */\nconst MB_PER_SECOND_720P = 2.13;\n\n/** Pixel count relative to 720p, which sets how the rate scales. */\nconst RESOLUTION_WEIGHT: Readonly<Record<string, number>> = {\n \"360p\": 0.25,\n \"480p\": 0.44,\n \"720p\": 1,\n \"1080p\": 2.25,\n \"4k\": 9,\n \"4K\": 9,\n};\n\n/**\n * What one action can hold.\n *\n * Convex caps an action at 512 MB and the file is live more than once — the fetched body\n * and the upload body at least — so the ceiling on the FILE is well under half of that.\n * 120 MB refuses the 30s/1080p clip that actually crashed (≈144 MB at the measured worst\n * rate) while leaving 30s at 720p and 15s at 1080p alone, which is where real ads sit.\n *\n * This is a stopgap with a number in it. The real fix is ingesting without holding the\n * file at all, and then this constant goes away.\n */\nexport const MAX_CLIP_INGEST_MB = 120;\n\n/** Roughly how many MB a clip of this shape will weigh. */\nexport function estimateClipMb(durationSeconds: number, resolution: string | undefined): number {\n const weight = RESOLUTION_WEIGHT[resolution ?? \"720p\"] ?? 1;\n return durationSeconds * MB_PER_SECOND_720P * weight;\n}\n\n/** The refusal, or null when the clip is small enough to ingest. */\nexport function clipTooHeavyToIngest(\n durationSeconds: number | undefined,\n resolution: string | undefined,\n): string | null {\n if (!durationSeconds) return null;\n const mb = estimateClipMb(durationSeconds, resolution);\n if (mb <= MAX_CLIP_INGEST_MB) return null;\n const fits = Math.floor(MAX_CLIP_INGEST_MB / (estimateClipMb(1, resolution) || 1));\n return `A ${durationSeconds}s clip at ${resolution ?? \"720p\"} comes to roughly ${Math.round(mb)} MB, more than the ${MAX_CLIP_INGEST_MB} MB we can take in — it would render, bill, and then fail on the way into the library. Shorten it to about ${fits}s at this resolution, or drop the resolution and keep the length.`;\n}\n","/**\n * What a generated frame is not allowed to invent.\n *\n * Every clause here was bought with a render. They lived in the ad scaffolder, which is\n * where they were learned — and that is exactly why a storyboard generated through Studio\n * came back with an electricity bill printed backwards and a customer resting her elbows on\n * the solar panel she was supposed to be praising. The rules existed; the route around them\n * did not know about them. So they live here, in the contract both routes already import,\n * rather than in whichever one happened to hit the defect first.\n *\n * Pure string composition: no model, no request, nothing to mock.\n */\nexport function frameRealismDirection(\n opts: { currency?: string; role?: string; readableText?: \"allowed\" | \"forbidden\" } = {},\n): string {\n return (\n \" Everything obeys real-world physics: paper, card and screens are OPAQUE with nothing showing through from behind,\" +\n \" every object is at believable real-world scale next to the people handling it, and every object has its\" +\n \" real-world form and construction — a phone has ONE screen and it is on the front.\" +\n // The worst of the three failures behind this, because the viewer reads the number: a\n // model invents one whenever a screen or a document is in shot, and it contradicts the\n // script it sits under. Frames simply do not get legible text; the captions carry the\n // numbers.\n //\n // Default ON, and asked for explicitly rather than inferred: an ad frame with no\n // person in it still sits under a script for an invented number to argue with. Only a\n // plain Studio picture opts out — it has no script, and it may BE the poster somebody\n // asked for, which the model picker sells GPT Image 2.5 on being able to render.\n (opts.readableText === \"allowed\"\n ? \"\"\n : \" NO readable text or numbers anywhere in frame — phone screens, documents and signage stay illegible or out of\" +\n \" focus, because any figure the model invents will contradict the script.\") +\n // Measured: one finished ad reported malformed hands or limbs in 8 of 12 sampled frames;\n // another, a woman with an extra right arm and an unattached hand gripping a panel.\n // Fiddly work at close range is where a video model breaks, every time.\n \" Hands are kept simple: no close-up of fingers manipulating small parts, no hand gripping the edge of an object,\" +\n \" and each person has exactly TWO arms and TWO legs, all attached and all visible or all out of frame.\" +\n \" Anyone working does so the way the trade actually does it: nobody stands or kneels on the equipment being\" +\n \" installed, nothing is fitted overhanging an edge or floating unsupported, and every part rests on the\" +\n \" structure that would really carry it.\" +\n // The newest clause, and the one no route had. A testimonial came back with the customer\n // repairing the panel herself: nothing said she was not the installer, so the model cast\n // her as one. Who someone IS in the picture has to be stated, or it is guessed.\n (opts.role\n ? ` The person on camera is ${opts.role} — they are shown as that and never doing somebody else's job.`\n : \"\") +\n (opts.currency ? ` If a currency is unavoidably visible it is ${opts.currency}.` : \"\")\n );\n}\n","/**\n * What a canvas node costs, in ONE place: the engine's pre-run quote (the CLI\n * node `cost` functions), the backend's per-request cost cap, and the backend's\n * charge all read these rates.\n *\n * Two kinds of number live here and they must not be confused:\n *\n * - RATES and the per-unit charge helpers (`ttsCharactersUsd`, `transcriptionUsd`,\n * …). The backend charges with these on the units the provider actually\n * measured (ElevenLabs' `x-character-count`, Groq's transcribed seconds), so a\n * charge is always rate x real units.\n * - ESTIMATES (`estimateNodeCostUsd`), which fill in the units nobody knows yet\n * with a stated default (30s of music, one minute of lipsync). Those defaults\n * are the same ones the backend falls back to when the provider reports\n * nothing, so a quote and a charge describe the same assumption.\n *\n * Usage-billed nodes (every OpenRouter text/vision/image call) have no rate: the\n * provider reports what the call cost afterwards. `estimateNodeCostUsd` returns\n * null for them and callers keep their own coarse quote.\n */\n\nimport { CREDITS_PER_USD, usdToCredits } from \"./credits\";\nimport { estimateVideoCostUsd, isSeedanceModel } from \"./videoCost\";\n\nexport { CREDITS_PER_USD, usdToCredits } from \"./credits\";\n\n// ---------------------------------------------------------------------------\n// Provider rates. Doc comments carry the pricing source; `credits/COSTS.md` in\n// the backend is the human-readable registry of the same numbers.\n// ---------------------------------------------------------------------------\n\n/**\n * ElevenLabs TTS & Dialogue, billed per character (`x-character-count`, or the\n * total `inputs[].text` length for dialogue, which returns no billing header).\n * Creator tier: $22/month for 100K credits = $0.00022 per character.\n * https://elevenlabs.io/pricing\n */\nexport const ELEVENLABS_USD_PER_CHARACTER = 0.00022;\n\n/**\n * ElevenLabs Music (`/v1/music/detailed`, `/v1/music/video-to-music`): ~100\n * credits per second of audio at $0.00022 = $0.022/s. UNVERIFIED for\n * `music_v2`; see the note on the backend constant's history in COSTS.md.\n */\nexport const ELEVENLABS_MUSIC_USD_PER_SECOND = 0.022;\n\n/** ElevenLabs Sound Effects (`/v1/sound-generation`), same credit ratio as music. */\nexport const ELEVENLABS_SOUND_EFFECT_USD_PER_SECOND = 0.022;\n\n/** ElevenLabs Voice Changer (speech-to-speech): ~1000 characters per minute of source audio. */\nexport const ELEVENLABS_STS_USD_PER_MINUTE = 1000 * ELEVENLABS_USD_PER_CHARACTER;\n\n/**\n * Lipsync, per minute of output. Named for the fal/VEED endpoint it was priced\n * on; the node now runs Sync Labs `lipsync-2` on Replicate and this rate has\n * not been re-verified against that model.\n */\nexport const FALAI_LIPSYNC_PER_MIN_USD = 0.4;\n\n/**\n * Video background removal, per 30 frames: $0.012 with edge refinement, $0.008\n * without (fal VEED fast pricing; the node now runs on Replicate).\n */\nexport const FALAI_VIDEO_BG_REMOVE_REFINED_USD_PER_30_FRAMES = 0.012;\nexport const FALAI_VIDEO_BG_REMOVE_FAST_USD_PER_30_FRAMES = 0.008;\n\n/** Image background removal: a flat per-call telemetry estimate. */\nexport const FALAI_IMAGE_BG_REMOVE_USD_PER_CALL = 0.001;\n\n/** Groq Whisper Large v3 Turbo: $0.04 per hour transcribed, 10s minimum per request. */\nexport const GROQ_WHISPER_COST_PER_HOUR = 0.04;\nexport const GROQ_WHISPER_MINIMUM_SECONDS = 10;\n\n/** Deepgram Nova-3 pre-recorded: $0.0043 per minute. https://deepgram.com/pricing */\nexport const DEEPGRAM_NOVA3_COST_PER_MINUTE = 0.0043;\n\n/** Firecrawl `/v2/scrape`: one credit ($0.001) per request, billed whether or not the page came back. */\nexport const FIRECRAWL_COST_PER_SCRAPE = 0.001;\n\n/**\n * Every rate above plus the credit conversion, as one object: what the\n * backend's `credits/constants.ts` reads, so the ledger and this module cannot\n * carry two copies of a price.\n */\nexport const canvasNodeRates = {\n CREDITS_PER_USD,\n DEEPGRAM_NOVA3_COST_PER_MINUTE,\n ELEVENLABS_MUSIC_USD_PER_SECOND,\n ELEVENLABS_SOUND_EFFECT_USD_PER_SECOND,\n ELEVENLABS_STS_USD_PER_MINUTE,\n ELEVENLABS_USD_PER_CHARACTER,\n FALAI_IMAGE_BG_REMOVE_USD_PER_CALL,\n FALAI_LIPSYNC_PER_MIN_USD,\n FALAI_VIDEO_BG_REMOVE_FAST_USD_PER_30_FRAMES,\n FALAI_VIDEO_BG_REMOVE_REFINED_USD_PER_30_FRAMES,\n FIRECRAWL_COST_PER_SCRAPE,\n GROQ_WHISPER_COST_PER_HOUR,\n GROQ_WHISPER_MINIMUM_SECONDS,\n} as const;\n\n// ---------------------------------------------------------------------------\n// Defaults for units nobody knows before the call. Shared with the backend's\n// own fallbacks so a quote and a charge assume the same thing.\n// ---------------------------------------------------------------------------\n\n/** Music length when neither `music_length_ms` nor the scored clip's length is known. */\nexport const DEFAULT_MUSIC_SECONDS = 30;\n/** Sound-effect length when `duration_seconds` is unset (the model picks its own). */\nexport const DEFAULT_SOUND_EFFECT_SECONDS = 5;\n/** Footage length assumed for background removal when the clip carries no duration. */\nexport const DEFAULT_BACKGROUND_REMOVE_SECONDS = 30;\n/** Audio length assumed for a quote when a transcription or voice conversion input carries no duration. */\nconst DEFAULT_MEDIA_SECONDS = 60;\n\n// ---------------------------------------------------------------------------\n// Per-unit charges on MEASURED units.\n// ---------------------------------------------------------------------------\n\nexport function ttsCharactersUsd(characters: number): number {\n return characters * ELEVENLABS_USD_PER_CHARACTER;\n}\n\nexport function musicSecondsUsd(seconds: number): number {\n return seconds * ELEVENLABS_MUSIC_USD_PER_SECOND;\n}\n\nexport function soundEffectSecondsUsd(seconds: number): number {\n return seconds * ELEVENLABS_SOUND_EFFECT_USD_PER_SECOND;\n}\n\n/** Billed minutes for a voice conversion: the source length, never under a tenth of a minute. */\nexport function voiceConvertMinutes(durationMs: number): number {\n return Math.max(durationMs / 60_000, 0.1);\n}\n\nexport function voiceConvertUsd(minutes: number): number {\n return minutes * ELEVENLABS_STS_USD_PER_MINUTE;\n}\n\n/**\n * Billed minutes for a lipsync: the provider returns no output duration, and the\n * output is bounded by the longer input, so that is what is billed. One minute\n * when neither input carries a duration.\n */\nexport function lipsyncMinutes(audioMs: number | undefined, videoMs: number | undefined): number {\n const durationMs = Math.max(audioMs ?? 0, videoMs ?? 0);\n return durationMs > 0 ? durationMs / 60_000 : 1;\n}\n\nexport function lipsyncUsd(minutes: number): number {\n return minutes * FALAI_LIPSYNC_PER_MIN_USD;\n}\n\n/** Frames billed for background removal: 30fps assumed, at least one 30-frame unit. */\nexport function backgroundRemoveFrames(durationSeconds: number | undefined): number {\n return Math.max(30, Math.ceil((durationSeconds ?? DEFAULT_BACKGROUND_REMOVE_SECONDS) * 30));\n}\n\nexport function videoBackgroundRemoveUsd(durationSeconds: number | undefined, edgeRefinement: boolean): number {\n const unit = edgeRefinement\n ? FALAI_VIDEO_BG_REMOVE_REFINED_USD_PER_30_FRAMES\n : FALAI_VIDEO_BG_REMOVE_FAST_USD_PER_30_FRAMES;\n return (backgroundRemoveFrames(durationSeconds) / 30) * unit;\n}\n\n/** Transcription cost by provider: Groq floors at 10s, Deepgram bills strictly per minute; nothing transcribed costs nothing. */\nexport function transcriptionUsd(transcriber: \"groq\" | \"deepgram\", seconds: number): number {\n if (seconds <= 0) return 0;\n if (transcriber === \"deepgram\") return (seconds / 60) * DEEPGRAM_NOVA3_COST_PER_MINUTE;\n return (Math.max(seconds, GROQ_WHISPER_MINIMUM_SECONDS) / 3600) * GROQ_WHISPER_COST_PER_HOUR;\n}\n\n// ---------------------------------------------------------------------------\n// Pre-dispatch estimates.\n// ---------------------------------------------------------------------------\n\nexport interface NodeCostInput {\n nodeType: string;\n /** Raw params as sent to the backend; read defensively (they arrive pre-validation). */\n params: unknown;\n /** Wired input refs, when known. Durations on them sharpen the estimate. */\n inputs?: unknown;\n /**\n * The caller already knows the cheap video route refuses these references and\n * sends the clip straight to fal. A routing decision, never a provider param.\n */\n preferFal?: boolean;\n}\n\ntype Bag = Record<string, unknown>;\n\nfunction asBag(value: unknown): Bag {\n return value && typeof value === \"object\" && !Array.isArray(value) ? (value as Bag) : {};\n}\n\nfunction num(value: unknown): number | undefined {\n return typeof value === \"number\" && Number.isFinite(value) ? value : undefined;\n}\n\n/** `duration_ms` off a wired ref, top level or mirrored in `metadata`. */\nfunction inputDurationMs(inputs: Bag, slot: string): number | undefined {\n const ref = asBag(inputs[slot]);\n return num(ref.duration_ms) ?? num(asBag(ref.metadata).duration_ms);\n}\n\nfunction slotCount(inputs: Bag, slot: string): number {\n const value = inputs[slot];\n if (Array.isArray(value)) return value.length;\n return value ? 1 : 0;\n}\n\nfunction textLength(value: unknown): number {\n return typeof value === \"string\" ? value.length : 0;\n}\n\nfunction estimateVideoGenerateUsd(params: Bag, inputs: Bag, preferFal: boolean): number | null {\n const model = params.model;\n if (typeof model !== \"string\") return null;\n // A reference-guided Seedance clip with no opening frame is exactly the request\n // the workflow recovers on fal when the likeness filter refuses it, so it is\n // quoted at whichever route is dearer (see `videoBlockRecovery` in the backend).\n const referenceOnly = slotCount(inputs, \"references\") > 0 && !inputs.first_frame;\n return estimateVideoCostUsd({\n model,\n duration: num(params.duration),\n resolution: typeof params.resolution === \"string\" ? params.resolution : undefined,\n generateAudio: typeof params.generate_audio === \"boolean\" ? params.generate_audio : undefined,\n buildsOnSourceClip: slotCount(inputs, \"video_references\") > 0,\n mayRouteToFal: isSeedanceModel(model) && (preferFal || referenceOnly),\n });\n}\n\nfunction estimateMusicUsd(params: Bag, inputs: Bag): number {\n const pinnedMs = num(params.music_length_ms);\n const scoredMs =\n params.model === \"elevenlabs/video-background-music-v1\" ? inputDurationMs(inputs, \"video\") : undefined;\n const seconds = (pinnedMs ?? scoredMs ?? DEFAULT_MUSIC_SECONDS * 1000) / 1000;\n return musicSecondsUsd(seconds);\n}\n\nfunction estimateDialogueUsd(params: Bag): number | null {\n if (!Array.isArray(params.inputs)) return null;\n const characters = params.inputs.reduce<number>((sum, line) => sum + textLength(asBag(line).text), 0);\n return ttsCharactersUsd(characters);\n}\n\n/**\n * Pre-dispatch provider-cost estimate for one node execution, in USD, or null\n * when only the provider's response can say (usage-billed nodes).\n */\nexport function estimateNodeCostUsd(input: NodeCostInput): number | null {\n const params = asBag(input.params);\n const inputs = asBag(input.inputs);\n switch (input.nodeType) {\n case \"video_generate\":\n return estimateVideoGenerateUsd(params, inputs, input.preferFal === true);\n case \"tts\":\n return typeof params.text === \"string\" ? ttsCharactersUsd(params.text.length) : null;\n case \"dialogue\":\n return estimateDialogueUsd(params);\n case \"music\":\n return estimateMusicUsd(params, inputs);\n case \"sound_effect\":\n return soundEffectSecondsUsd(num(params.duration_seconds) ?? DEFAULT_SOUND_EFFECT_SECONDS);\n case \"audio_voice_convert\": {\n const ms = inputDurationMs(inputs, \"audio\") ?? DEFAULT_MEDIA_SECONDS * 1000;\n return voiceConvertUsd(voiceConvertMinutes(ms));\n }\n case \"video_lipsync\":\n return lipsyncUsd(lipsyncMinutes(inputDurationMs(inputs, \"audio\"), inputDurationMs(inputs, \"video\")));\n case \"video_background_remove\": {\n const ms = inputDurationMs(inputs, \"video\");\n return videoBackgroundRemoveUsd(ms === undefined ? undefined : ms / 1000, params.edge_refinement !== false);\n }\n case \"image_background_remove\":\n return FALAI_IMAGE_BG_REMOVE_USD_PER_CALL;\n case \"video_transcribe\": {\n const ms = inputDurationMs(inputs, \"video\") ?? DEFAULT_MEDIA_SECONDS * 1000;\n return transcriptionUsd(params.transcriber === \"deepgram\" ? \"deepgram\" : \"groq\", ms / 1000);\n }\n case \"ingest\":\n return params.strategy === \"firecrawl\" ? FIRECRAWL_COST_PER_SCRAPE : 0;\n case \"voice_select\":\n case \"load_artifact\":\n case \"save_artifact\":\n case \"resize\":\n case \"crop\":\n return 0;\n default:\n return null;\n }\n}\n\n/** `estimateNodeCostUsd` in whole credits, or null when the node is usage-billed. */\nexport function estimateNodeCredits(input: NodeCostInput): number | null {\n const usd = estimateNodeCostUsd(input);\n return usd === null ? null : usdToCredits(usd);\n}\n","/**\n * How an invented person is photographed so they read as somebody real.\n *\n * One wording for every place a face is invented — an avatar's casting portrait in the\n * backend, a described person in a video ad in the CLI — because the face invented there\n * is the face every later frame copies. Judged blind side by side, a candid phone photo of\n * an ordinary person in their own world beat the old ID-photo framing (squared to camera,\n * flat light, grey seamless) 6 of 6, and once in an ad it beat it 6 of 6 again (AV1,\n * scripts/creative-evals/avatar-realism.mjs).\n */\n\n/**\n * The camera is a phone, because that is what real people's photos are taken on. Named,\n * because \"a real photo\" alone still comes back with a professional camera's creamy\n * background blur and compressed perspective — tells a viewer reads as \"produced\".\n */\nexport const PHONE_CAMERA =\n \"Shot on a phone, an iPhone or a Samsung Galaxy, with the main camera in the default photo mode (not portrait mode): slightly wide angle, held by a friend about a metre away or at arm's length, the background mostly in focus the way phone photos are, the phone's own processing — HDR evening out a bright window, a touch of over-sharpening, smoothed noise in the shadows, punchy everyday colour. Slightly imperfect framing. Not a professional camera: no bokeh or creamy background blur, no lens compression, no studio or flash lighting, no colour grade.\";\n\nexport const REAL_SKIN =\n \"Real skin and a real face: visible pores, fine lines, uneven tone, small marks, stray hairs, slight asymmetry. Clothes with real creases.\";\n\nconst NOT_A_MODEL =\n \"Not stock photography, not a model or an influencer: no beauty retouching, no glowing or plastic skin, no perfectly symmetrical features.\";\n\n/** A candid phone portrait of one invented ordinary person: the face a sheet is fused from. */\nexport function candidPersonPortraitPrompt(p: { subject: string; wardrobe?: string; setting?: string }): string {\n return [\n `An unretouched candid phone photo of one ordinary, real person: ${p.subject}`,\n p.wardrobe?.trim() ? `Wearing: ${p.wardrobe.trim()}` : null,\n `Where: ${p.setting?.trim() || \"an everyday place that fits who they are, in daylight\"}, available light only. They look toward the lens mid-conversation with a relaxed, unposed expression. Framed from the head to mid-torso, face clearly visible.`,\n PHONE_CAMERA,\n REAL_SKIN,\n NOT_A_MODEL,\n \"No text, logos or watermarks. One person only.\",\n ]\n .filter((line): line is string => line !== null)\n .join(\"\\n\");\n}\n","import { clipTooHeavyToIngest } from \"./clipWeight.ts\";\nimport {\n canonicalModelId,\n canonicalModelParams,\n type InputKind,\n MODEL_REGISTRY,\n type NodeKind,\n type ParamSchema,\n} from \"./registry\";\n\ntype ModelValidationError =\n | { code: \"unknown_model\"; message: string }\n | { code: \"missing_required_param\"; param: string; message: string }\n | { code: \"unknown_param\"; param: string; message: string }\n | { code: \"invalid_value\"; param: string; message: string }\n | { code: \"missing_input\"; input: InputKind; message: string }\n // Not about one param: every value can be legal and the FILE still be too big to take\n // in, which only shows up after the clip has rendered and billed.\n | { code: \"clip_too_heavy\"; message: string };\n\ntype ModelValidationResult = { ok: true } | { ok: false; errors: ModelValidationError[] };\n\n// Derived from `MODEL_REGISTRY` (the canonical source of truth) rather than a\n// hand-maintained list — adding a kind to the registry forces it here too, so\n// the guard can never silently go stale. `Object.keys` matches own keys only,\n// so inherited prototype names (\"toString\" etc.) correctly return false; it also\n// stays ES2021-clean (the backend typechecks this package under `lib: ES2021`,\n// which rules out `Object.hasOwn`).\nfunction isManagedNodeKind(nodeType: string): nodeType is NodeKind {\n return Object.keys(MODEL_REGISTRY).includes(nodeType);\n}\n\n/**\n * Validate canvas params against the per-model spec. Use for any node whose\n * `nodeType` is one of the managed kinds (image_generate / video_generate /\n * video_lipsync / tts). Nodes outside this set fall back to their generic Zod\n * schema only.\n *\n * `model` is the canonical `<provider>/<model>` id from `params.model`.\n *\n * The `model` field itself is always allowed and not validated as a param.\n */\nfunction checkRequiredParams(\n spec: { required: readonly string[] },\n params: Record<string, unknown>,\n model: string,\n): ModelValidationError[] {\n const errors: ModelValidationError[] = [];\n for (const req of spec.required) {\n if (params[req] === undefined || params[req] === null) {\n errors.push({\n code: \"missing_required_param\",\n param: req,\n message: `missing required param \"${req}\" for model \"${model}\"`,\n });\n }\n }\n return errors;\n}\n\nfunction checkParamValues(\n spec: { params: Record<string, ParamSchema> },\n params: Record<string, unknown>,\n model: string,\n): ModelValidationError[] {\n const errors: ModelValidationError[] = [];\n for (const [key, value] of Object.entries(params)) {\n if (key === \"model\") continue;\n if (value === undefined) continue;\n const schema = spec.params[key];\n if (!schema) {\n errors.push({\n code: \"unknown_param\",\n param: key,\n message: `param \"${key}\" is not supported by model \"${model}\"`,\n });\n continue;\n }\n const valueErr = validateValue(key, value, schema, model);\n if (valueErr) errors.push(valueErr);\n }\n return errors;\n}\n\nexport function validateModelParams(\n nodeType: NodeKind,\n model: string,\n params: Record<string, unknown>,\n): ModelValidationResult {\n // A legacy id validates as the model it stands for, with the params fitted to it\n // exactly as the backend will send them (see `MODEL_ALIASES`).\n const spec = MODEL_REGISTRY[nodeType][canonicalModelId(model)];\n if (!spec) {\n return {\n ok: false,\n errors: [{ code: \"unknown_model\", message: `unknown model \"${model}\" for node \"${nodeType}\"` }],\n };\n }\n\n const fitted = canonicalModelParams(nodeType, { ...params, model });\n const errors = [...checkRequiredParams(spec, fitted, model), ...checkParamValues(spec, fitted, model)];\n if (errors.length > 0) return { ok: false, errors };\n\n // Size, after the params are known to be legal. Every value here can be individually\n // valid and still produce a file too big to take in — the clip renders, bills, and then\n // runs the ingest action out of memory. This is the free gate before the paid one.\n if (nodeType === \"video_generate\") {\n const tooHeavy = clipTooHeavyToIngest(\n typeof params.duration === \"number\" ? params.duration : undefined,\n typeof params.resolution === \"string\" ? params.resolution : undefined,\n );\n if (tooHeavy) return { ok: false, errors: [{ code: \"clip_too_heavy\", message: tooHeavy }] };\n }\n return { ok: true };\n}\n\n/**\n * Validate that every REQUIRED input slot the model declares is wired up.\n * `providedKinds` is the set of input kinds the canvas supplies (e.g.\n * [\"video\", \"audio\"]). Optional input slots are not checked — they only\n * affect UI rendering, not run validity.\n */\nexport function validateModelInputs(\n nodeType: NodeKind,\n model: string,\n providedKinds: readonly InputKind[],\n): ModelValidationResult {\n const spec = MODEL_REGISTRY[nodeType][canonicalModelId(model)];\n if (!spec) {\n return {\n ok: false,\n errors: [{ code: \"unknown_model\", message: `unknown model \"${model}\" for node \"${nodeType}\"` }],\n };\n }\n const have = new Set(providedKinds);\n const errors: ModelValidationError[] = [];\n for (const inputSpec of spec.inputs) {\n if (!have.has(inputSpec.kind)) {\n errors.push({\n code: \"missing_input\",\n input: inputSpec.kind,\n message: `model \"${model}\" requires input of kind \"${inputSpec.kind}\"`,\n });\n }\n }\n if (errors.length > 0) return { ok: false, errors };\n return { ok: true };\n}\n\nfunction validateStringValue(\n key: string,\n value: unknown,\n schema: Extract<ParamSchema, { kind: \"string\" }>,\n model: string,\n): ModelValidationError | null {\n if (typeof value !== \"string\") {\n return { code: \"invalid_value\", param: key, message: `${key}: expected string, got ${typeof value}` };\n }\n if (schema.enum && !schema.enum.includes(value)) {\n return {\n code: \"invalid_value\",\n param: key,\n message: `${key}: \"${value}\" not allowed by \"${model}\" (allowed: ${schema.enum.join(\", \")})`,\n };\n }\n if (schema.maxLength !== undefined && value.length > schema.maxLength) {\n return {\n code: \"invalid_value\",\n param: key,\n message: `${key}: ${value.length} characters exceeds max ${schema.maxLength} for \"${model}\"`,\n };\n }\n return null;\n}\n\nfunction validateNumberValue(\n key: string,\n value: unknown,\n schema: Extract<ParamSchema, { kind: \"number\" }>,\n model: string,\n): ModelValidationError | null {\n if (typeof value !== \"number\" || Number.isNaN(value)) {\n return { code: \"invalid_value\", param: key, message: `${key}: expected number, got ${typeof value}` };\n }\n if (schema.enum && !schema.enum.includes(value)) {\n return {\n code: \"invalid_value\",\n param: key,\n message: `${key}: ${value} not allowed by \"${model}\" (allowed: ${schema.enum.join(\", \")})`,\n };\n }\n // A fractional seed is a schema rejection at Replicate and at Vertex, not a\n // rounded one — so it is worth its own check rather than hiding inside a range.\n if (schema.integer && !Number.isInteger(value)) {\n return { code: \"invalid_value\", param: key, message: `${key}: ${value} must be a whole number` };\n }\n if (schema.min !== undefined && value < schema.min) {\n return { code: \"invalid_value\", param: key, message: `${key}: ${value} below min ${schema.min}` };\n }\n if (schema.max !== undefined && value > schema.max) {\n return { code: \"invalid_value\", param: key, message: `${key}: ${value} above max ${schema.max}` };\n }\n return null;\n}\n\nfunction validateValue(key: string, value: unknown, schema: ParamSchema, model: string): ModelValidationError | null {\n switch (schema.kind) {\n case \"string\":\n return validateStringValue(key, value, schema, model);\n case \"number\":\n return validateNumberValue(key, value, schema, model);\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n return { code: \"invalid_value\", param: key, message: `${key}: expected boolean, got ${typeof value}` };\n }\n return null;\n case \"json\":\n return null;\n default: {\n const _exhaustive: never = schema satisfies never;\n return _exhaustive;\n }\n }\n}\n\nexport { isManagedNodeKind };\n","import { z } from \"zod\";\n\n/**\n * The video blueprint: the one description of an ad that every video path agrees on.\n *\n * Three places produce or read it. The backend's `video_deconstruct` node writes it from a\n * reference video, `scaffold-ad` compiles a written spec into it, and the CLI's video\n * scaffolder reads either one and builds the canvas. Kept here so all three name the same\n * fields: a field the scaffolder reads and neither producer writes is a feature nobody can\n * reach, and a field a producer writes under another name is one the scaffolder silently\n * ignores.\n *\n * TOLERANT on purpose. Every field is optional and every object keeps the keys it does not\n * name (`.loose()`): a deconstruct is a model's reading of a video, a degraded answer must\n * still scaffold, and blueprints written by older deconstructs sit in client workspaces as\n * `prompt.json` and must keep parsing. The producers hold their own stricter schemas for\n * what they write; this is the shape the scaffolder can rely on.\n */\n\nconst FrameAssetSchema = z.object({ url: z.string().optional() }).loose().optional();\n\nexport const BlueprintDialogueLineSchema = z\n .object({\n speaker: z.string().optional(),\n line: z.string().optional(),\n // Absolute seconds on the source timeline (the deconstruct emits both).\n start_s: z.number().optional(),\n end_s: z.number().optional(),\n delivery: z.string().optional(),\n voice_description: z.string().optional(),\n // DECON-supplied: is this speaker's FACE visibly speaking in THIS scene? Element\n // presence alone can't answer that — a founder pictured in a polaroid close-up is\n // \"present\" yet the line is voiceover, and treating it as on-camera produced a\n // native Seedance lip-sync clip of a still photograph. `false` pins the line to\n // the VO path; absent keeps the presence-based decision (old blueprints).\n on_camera: z.boolean().optional(),\n })\n .loose();\n\nconst SfxSchema = z\n .object({\n at_s: z.number().optional(),\n duration_s: z.number().optional(),\n sound_effect_prompt: z.string().optional(),\n description: z.string().optional(),\n })\n .loose();\n\n// One constituent stream of a composited scene (split panel / PIP inset / keyed\n// presenter). Each region becomes its own generated clip; the scaffold stacks or\n// overlays them into the scene's picture.\nexport const CompositionRegionSchema = z\n .object({\n // full | top | bottom | left | right | inset\n panel: z.string().optional(),\n // 9-grid anchor for an `inset` presenter box.\n position: z.string().optional(),\n is_presenter: z.boolean().optional(),\n // The cast id shown/speaking in this region (routes lip-sync + element refs).\n cast_ref: z.string().optional(),\n // What the region's content IS: camera | screen_capture | static_graphic |\n // generated. Authoritative for routing when present (regex-over-prose fallback\n // otherwise): screen_capture/static_graphic are rebuilt from REAL surfaces on the\n // overlay layer, never AI-generated.\n kind: z.string().optional(),\n // Opaque id naming the SPECIFIC on-screen document/note/app-state this\n // screen_capture region shows. Two scenes share it only when they show the SAME\n // recording continuing (scrolling/typing/waiting within it) — a genuinely\n // DIFFERENT document/note/recording (a source video splicing two screen captures)\n // gets a different id. Breaks a persistent-layout run into separate surface stubs\n // instead of asking the operator for one screenshot that can't cover both.\n surface_id: z.string().optional(),\n // Camera bubble(s)/inset(s) embedded INSIDE this region's surface (a Loom-style\n // presenter bubble inside a screen recording) — video-in-video the reproduction\n // must re-composite, not paint into the surface.\n nested: z.array(z.object({}).loose()).optional(),\n summary: z.string().optional(),\n frame_prompt: z.string().optional(),\n motion_prompt: z.string().optional(),\n })\n .loose();\n\nexport const SceneCompositionSchema = z\n .object({\n // full_frame (default) | split_screen | pip | keyed_overlay\n layout: z.string().optional(),\n // split_screen only: vertical (top/bottom) | horizontal (left/right).\n split_axis: z.string().optional(),\n regions: z.array(CompositionRegionSchema).optional(),\n })\n .loose();\n\nconst CameraMotionSchema = z.object({ movement: z.string().optional(), detail: z.string().optional() }).loose();\nconst TranscriptWordSchema = z.object({ text: z.string().optional() }).loose();\n\n/**\n * How a scene's picture should be produced, when the producer already knows.\n *\n * Set by a producer that authored the scene rather than read it off a video: `scaffold-ad`\n * marks its closing beat `brand_card`, because it wrote that beat to be a flat brand plate.\n * Without the field the scaffolder can only guess from the prose, which made the WORDING of\n * a prompt a routing contract — the plate's description had to contain one of the words the\n * guess looked for, and an edit that dropped them sent the closing card to a photograph.\n * A deconstructed scene never carries it, and the guess is still what routes those.\n */\nexport const SCENE_ROUTE_HINTS = [\"brand_card\"] as const;\nexport type SceneRouteHint = (typeof SCENE_ROUTE_HINTS)[number];\n\nexport const VideoSceneSchema = z\n .object({\n start_s: z.number().optional(),\n end_s: z.number().optional(),\n duration_s: z.number().optional(),\n summary: z.string().optional(),\n action_detail: z.string().optional(),\n // The scene's spatial layout. Absent/full_frame ⇒ one uncut shot (default path).\n // A layered layout (split_screen/pip/keyed_overlay) with regions ⇒ the scaffold\n // builds one clip per region and stacks/overlays them into the scene picture.\n composition: SceneCompositionSchema.optional(),\n // The capture \"look\" for this scene — selected from the ad-native shoot-mode\n // grammar (the CLI's scaffold/lib/shoot-modes.ts). When absent the scaffold\n // auto-derives a UGC/product mode; a human can override per scene by setting this.\n shoot_mode: z.string().optional(),\n // Diegetic ambient the clip's native audio should carry (no music). When\n // absent the scene falls back to its shoot mode's default ambience.\n ambient: z.string().optional(),\n camera_motion: CameraMotionSchema.optional(),\n start_frame_prompt: z.string().optional(),\n end_frame_prompt: z.string().optional(),\n motion_prompt: z.string().optional(),\n // The scene's role in the ad's persuasion arc (DECON-supplied); drives the\n // script re-craft checklist. Inferred from position when absent.\n narrative_role: z.string().optional(),\n // See `SceneRouteHint`.\n route_hint: z.enum(SCENE_ROUTE_HINTS).optional(),\n // DECON-supplied on the HOOK scene: the engineered physical/emotional state that\n // makes the first frame stop the scroll (sweaty/breathless/urgent …). Injected\n // into the hook's start-frame description so the generator renders that state,\n // not a calm influencer (CCA-11).\n hook_mechanic: z\n .object({ mechanic: z.string().optional(), why_it_stops_scroll: z.string().optional() })\n .loose()\n .optional(),\n // DECON-supplied per-scene location (so a gym hook isn't flattened to \"home\").\n scene_setting: z.string().optional(),\n // How this scene cuts to the next (DECON-supplied). A recognized non-cut type\n // (fade/whip/zoom/dissolve/swipe) is reproduced as an ffmpeg xfade at the\n // boundary; cut/match_cut/none/other stay hard cuts. The last scene's value is\n // ignored (nothing follows it).\n transition_out: z.object({ type: z.string().optional(), description: z.string().optional() }).loose().optional(),\n dialogue: z.array(BlueprintDialogueLineSchema).optional(),\n sfx: z.array(SfxSchema).optional(),\n // Parsed element by element where they are read (`BlueprintOverlaySchema`,\n // `BlueprintFloatingElementSchema`), so one malformed graphic never rejects the scene.\n overlays: z.array(z.unknown()).optional(),\n floating_elements: z.array(z.unknown()).optional(),\n // DECON-supplied: how much the picture itself moves within the shot. Gates the\n // flash-hold optimization — a sub-2s b-roll flash with REAL subject motion\n // (pouring, spreading, hands working) must stay a real clip; freezing it turns\n // a montage into a slideshow. Absent (old blueprints) keeps the cheap still.\n motion_level: z.enum([\"static\", \"subtle\", \"dynamic\"]).optional(),\n transcript_slice: z.array(TranscriptWordSchema).optional(),\n start_frame_asset: FrameAssetSchema,\n end_frame_asset: FrameAssetSchema,\n // DECON-supplied: true when this scene is a length-split CONTINUATION of the\n // previous one (the SAME physical shot, broken up only because it exceeded the\n // clip ceiling). The scaffold then shares the splice keyframe — this scene's\n // start frame IS the previous scene's end frame — so the join is seamless.\n continues_previous: z.boolean().optional(),\n })\n .loose();\n\nexport const VideoBlueprintSchema = z\n .object({\n source: z.object({ aspect_ratio: z.string().optional(), duration_s: z.number().optional() }).loose().optional(),\n global: z\n .object({\n music: z\n .object({\n present: z.boolean().optional(),\n music_prompt: z.string().optional(),\n // Absolute second the music enters in the reference (the bed often\n // kicks in mid-ad, after the hook). We start the regenerated track here\n // instead of at 0 so the timing matches.\n starts_at_s: z.number().optional(),\n // Populated by the deconstruct when AudD (Shazam-style) recognizes the\n // reference track. We never reuse it — only style the regenerated bed.\n identified_track: z\n .object({ title: z.string().optional(), artist: z.string().optional() })\n .loose()\n .nullish(),\n })\n .loose()\n .optional(),\n cast: z\n .array(\n z\n .object({\n id: z.string().optional(),\n description: z.string().optional(),\n // The deconstruct's note on the target-market localization (e.g. \"native\n // French speaker\") — read to derive the spoken-track language code.\n market_localization_note: z.string().optional(),\n })\n .loose(),\n )\n .optional(),\n voiceover: z\n .object({\n // on_camera | mixed → mouths are on screen (lip-sync candidates);\n // voiceover | none → narration over the picture (no lip-sync).\n mode: z.string().optional(),\n // Which variety of the language the speech is in. Stated because the model\n // picks one otherwise: ads set in Spain came back in Latin American Spanish,\n // and the pinned peninsular voice could not undo it — the re-voicing is\n // speech-to-speech, so it carries the accent across and swaps only the timbre.\n accent: z.string().optional(),\n voice_description: z.string().optional(),\n persona: z.string().optional(),\n })\n .loose()\n .optional(),\n // Visual palette — read only to colour a clean brand-card/CTA plate (the\n // first hex is the dominant brand colour); never to drive frame generation.\n style: z\n .object({ palette: z.array(z.object({ hex: z.string().optional() }).loose()).optional() })\n .loose()\n .optional(),\n // Written by `scaffold-ad` (the deconstruct names its own fields, e.g. `branding.brand_name`):\n // the whole script as one string, where the ad is set, and the brand it closes on.\n transcript: z.string().optional(),\n market: z.string().optional(),\n branding: z.object({ name: z.string().optional(), logo_path: z.string().optional() }).loose().optional(),\n })\n .loose()\n .optional(),\n // Written by `scaffold-ad`: what the beats add up to, so a short ad is caught before it renders.\n estimated_duration_s: z.number().optional(),\n scenes: z.array(VideoSceneSchema).min(1),\n })\n .loose();\n\nconst OverlayStyleSchema = z\n .object({ color_hex: z.string().optional(), background: z.string().optional(), size: z.string().optional() })\n .loose();\n\n/** One on-screen text overlay of a scene (an entry of `scene.overlays`). */\nexport const BlueprintOverlaySchema = z\n .object({\n text: z.string().optional(),\n appears_at_s: z.number().optional(),\n duration_s: z.number().optional(),\n position: z.string().optional(),\n role: z.string().optional(),\n animation: z.string().optional(),\n animation_detail: z.string().optional(),\n style: OverlayStyleSchema.optional(),\n })\n .loose();\n\n/** One non-text graphic of a scene (an entry of `scene.floating_elements`). */\nexport const BlueprintFloatingElementSchema = z\n .object({\n kind: z.string().optional(),\n description: z.string().optional(),\n brand_name: z.string().nullish(),\n what_it_represents: z.string().optional(),\n appears_at_s: z.number().optional(),\n duration_s: z.number().optional(),\n position: z.string().optional(),\n })\n .loose();\n\nexport type VideoBlueprint = z.infer<typeof VideoBlueprintSchema>;\nexport type VideoScene = z.infer<typeof VideoSceneSchema>;\nexport type BlueprintDialogueLine = z.infer<typeof BlueprintDialogueLineSchema>;\nexport type CompositionRegion = z.infer<typeof CompositionRegionSchema>;\nexport type SceneComposition = z.infer<typeof SceneCompositionSchema>;\nexport type BlueprintOverlay = z.infer<typeof BlueprintOverlaySchema>;\nexport type BlueprintFloatingElement = z.infer<typeof BlueprintFloatingElementSchema>;\n"],"mappings":";;;;;;AAAA;AAAA;AAAA;AAEA,QAAM,EAAE,eAAe,IAAI,OAAO;AAElC,QAAM,YAAYA,WAAU;AAG5B,cAAU,YAAYA;AAEtB,cAAU,YAAY;AAGtB,cAAU,UAAU;AAGpB,YAAQ,YAAY;AAEpB,YAAQ,YAAYA;AAEpB,WAAO,UAAU;AAGjB,QAAM,2BAA2B;AAIjC,aAAS,UAAW,KAAK;AAEvB,UAAI,IAAI,SAAS,OAAQ,CAAC,yBAAyB,KAAK,GAAG,GAAG;AAC5D,eAAO,IAAI,GAAG;AAAA,MAChB;AACA,aAAO,KAAK,UAAU,GAAG;AAAA,IAC3B;AAEA,aAAS,KAAM,OAAO,YAAY;AAGhC,UAAI,MAAM,SAAS,OAAO,YAAY;AACpC,eAAO,MAAM,KAAK,UAAU;AAAA,MAC9B;AACA,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAM,eAAe,MAAM,CAAC;AAC5B,YAAI,WAAW;AACf,eAAO,aAAa,KAAK,MAAM,WAAW,CAAC,IAAI,cAAc;AAC3D,gBAAM,QAAQ,IAAI,MAAM,WAAW,CAAC;AACpC;AAAA,QACF;AACA,cAAM,QAAQ,IAAI;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAEA,QAAM,0CACJ,OAAO;AAAA,MACL,OAAO;AAAA,QACL,OAAO;AAAA,UACL,IAAI,UAAU;AAAA,QAChB;AAAA,MACF;AAAA,MACA,OAAO;AAAA,IACT,EAAE;AAEJ,aAAS,wBAAyB,OAAO;AACvC,aAAO,wCAAwC,KAAK,KAAK,MAAM,UAAa,MAAM,WAAW;AAAA,IAC/F;AAEA,aAAS,oBAAqB,OAAO,WAAW,gBAAgB;AAC9D,UAAI,MAAM,SAAS,gBAAgB;AACjC,yBAAiB,MAAM;AAAA,MACzB;AACA,YAAM,aAAa,cAAc,MAAM,KAAK;AAC5C,UAAI,MAAM,OAAO,UAAU,GAAG,MAAM,CAAC,CAAC;AACtC,eAAS,IAAI,GAAG,IAAI,gBAAgB,KAAK;AACvC,eAAO,GAAG,SAAS,IAAI,CAAC,KAAK,UAAU,GAAG,MAAM,CAAC,CAAC;AAAA,MACpD;AACA,aAAO;AAAA,IACT;AAEA,aAAS,uBAAwB,SAAS;AACxC,UAAI,eAAe,KAAK,SAAS,eAAe,GAAG;AACjD,cAAM,gBAAgB,QAAQ;AAC9B,YAAI,OAAO,kBAAkB,UAAU;AACrC,iBAAO,IAAI,aAAa;AAAA,QAC1B;AACA,YAAI,iBAAiB,MAAM;AACzB,iBAAO;AAAA,QACT;AACA,YAAI,kBAAkB,SAAS,kBAAkB,WAAW;AAC1D,iBAAO;AAAA,YACL,WAAY;AACV,oBAAM,IAAI,UAAU,uCAAuC;AAAA,YAC7D;AAAA,UACF;AAAA,QACF;AACA,cAAM,IAAI,UAAU,oFAAoF;AAAA,MAC1G;AACA,aAAO;AAAA,IACT;AAEA,aAAS,uBAAwB,SAAS;AACxC,UAAI;AACJ,UAAI,eAAe,KAAK,SAAS,eAAe,GAAG;AACjD,gBAAQ,QAAQ;AAChB,YAAI,OAAO,UAAU,aAAa,OAAO,UAAU,YAAY;AAC7D,gBAAM,IAAI,UAAU,6EAA6E;AAAA,QACnG;AAAA,MACF;AACA,aAAO,UAAU,SAAY,OAAO;AAAA,IACtC;AAEA,aAAS,iBAAkB,SAAS,KAAK;AACvC,UAAI;AACJ,UAAI,eAAe,KAAK,SAAS,GAAG,GAAG;AACrC,gBAAQ,QAAQ,GAAG;AACnB,YAAI,OAAO,UAAU,WAAW;AAC9B,gBAAM,IAAI,UAAU,QAAQ,GAAG,oCAAoC;AAAA,QACrE;AAAA,MACF;AACA,aAAO,UAAU,SAAY,OAAO;AAAA,IACtC;AAEA,aAAS,yBAA0B,SAAS,KAAK;AAC/C,UAAI;AACJ,UAAI,eAAe,KAAK,SAAS,GAAG,GAAG;AACrC,gBAAQ,QAAQ,GAAG;AACnB,YAAI,OAAO,UAAU,UAAU;AAC7B,gBAAM,IAAI,UAAU,QAAQ,GAAG,mCAAmC;AAAA,QACpE;AACA,YAAI,CAAC,OAAO,UAAU,KAAK,GAAG;AAC5B,gBAAM,IAAI,UAAU,QAAQ,GAAG,+BAA+B;AAAA,QAChE;AACA,YAAI,QAAQ,GAAG;AACb,gBAAM,IAAI,WAAW,QAAQ,GAAG,yBAAyB;AAAA,QAC3D;AAAA,MACF;AACA,aAAO,UAAU,SAAY,WAAW;AAAA,IAC1C;AAEA,aAAS,aAAc,QAAQ;AAC7B,UAAI,WAAW,GAAG;AAChB,eAAO;AAAA,MACT;AACA,aAAO,GAAG,MAAM;AAAA,IAClB;AAEA,aAAS,qBAAsB,eAAe;AAC5C,YAAM,cAAc,oBAAI,IAAI;AAC5B,iBAAW,SAAS,eAAe;AACjC,YAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1D,sBAAY,IAAI,OAAO,KAAK,CAAC;AAAA,QAC/B;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,aAAS,gBAAiB,SAAS;AACjC,UAAI,eAAe,KAAK,SAAS,QAAQ,GAAG;AAC1C,cAAM,QAAQ,QAAQ;AACtB,YAAI,OAAO,UAAU,WAAW;AAC9B,gBAAM,IAAI,UAAU,+CAA+C;AAAA,QACrE;AACA,YAAI,OAAO;AACT,iBAAO,CAACC,WAAU;AAChB,gBAAI,UAAU,uDAAuD,OAAOA,MAAK;AACjF,gBAAI,OAAOA,WAAU,WAAY,YAAW,KAAKA,OAAM,SAAS,CAAC;AACjE,kBAAM,IAAI,MAAM,OAAO;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,aAASD,WAAW,SAAS;AAC3B,gBAAU,EAAE,GAAG,QAAQ;AACvB,YAAM,OAAO,gBAAgB,OAAO;AACpC,UAAI,MAAM;AACR,YAAI,QAAQ,WAAW,QAAW;AAChC,kBAAQ,SAAS;AAAA,QACnB;AACA,YAAI,EAAE,mBAAmB,UAAU;AACjC,kBAAQ,gBAAgB;AAAA,QAC1B;AAAA,MACF;AACA,YAAM,gBAAgB,uBAAuB,OAAO;AACpD,YAAM,SAAS,iBAAiB,SAAS,QAAQ;AACjD,YAAM,gBAAgB,uBAAuB,OAAO;AACpD,YAAM,aAAa,OAAO,kBAAkB,aAAa,gBAAgB;AACzE,YAAM,eAAe,yBAAyB,SAAS,cAAc;AACrE,YAAM,iBAAiB,yBAAyB,SAAS,gBAAgB;AAEzE,eAAS,oBAAqB,KAAK,QAAQ,OAAO,UAAU,QAAQ,aAAa;AAC/E,YAAI,QAAQ,OAAO,GAAG;AAEtB,YAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,OAAO,MAAM,WAAW,YAAY;AACrF,kBAAQ,MAAM,OAAO,GAAG;AAAA,QAC1B;AACA,gBAAQ,SAAS,KAAK,QAAQ,KAAK,KAAK;AAExC,gBAAQ,OAAO,OAAO;AAAA,UACpB,KAAK;AACH,mBAAO,UAAU,KAAK;AAAA,UACxB,KAAK,UAAU;AACb,gBAAI,UAAU,MAAM;AAClB,qBAAO;AAAA,YACT;AACA,gBAAI,MAAM,QAAQ,KAAK,MAAM,IAAI;AAC/B,qBAAO;AAAA,YACT;AAEA,gBAAI,MAAM;AACV,gBAAI,OAAO;AACX,kBAAM,sBAAsB;AAE5B,gBAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,kBAAI,MAAM,WAAW,GAAG;AACtB,uBAAO;AAAA,cACT;AACA,kBAAI,eAAe,MAAM,SAAS,GAAG;AACnC,uBAAO;AAAA,cACT;AACA,oBAAM,KAAK,KAAK;AAChB,kBAAI,WAAW,IAAI;AACjB,+BAAe;AACf,uBAAO;AAAA,EAAK,WAAW;AACvB,uBAAO;AAAA,EAAM,WAAW;AAAA,cAC1B;AACA,oBAAM,2BAA2B,KAAK,IAAI,MAAM,QAAQ,cAAc;AACtE,kBAAI,IAAI;AACR,qBAAO,IAAI,2BAA2B,GAAG,KAAK;AAC5C,sBAAME,OAAM,oBAAoB,OAAO,CAAC,GAAG,OAAO,OAAO,UAAU,QAAQ,WAAW;AACtF,uBAAOA,SAAQ,SAAYA,OAAM;AACjC,uBAAO;AAAA,cACT;AACA,oBAAM,MAAM,oBAAoB,OAAO,CAAC,GAAG,OAAO,OAAO,UAAU,QAAQ,WAAW;AACtF,qBAAO,QAAQ,SAAY,MAAM;AACjC,kBAAI,MAAM,SAAS,IAAI,gBAAgB;AACrC,sBAAM,cAAc,MAAM,SAAS,iBAAiB;AACpD,uBAAO,GAAG,IAAI,QAAQ,aAAa,WAAW,CAAC;AAAA,cACjD;AACA,kBAAI,WAAW,IAAI;AACjB,uBAAO;AAAA,EAAK,mBAAmB;AAAA,cACjC;AACA,oBAAM,IAAI;AACV,qBAAO,IAAI,GAAG;AAAA,YAChB;AAEA,gBAAI,OAAO,OAAO,KAAK,KAAK;AAC5B,kBAAM,YAAY,KAAK;AACvB,gBAAI,cAAc,GAAG;AACnB,qBAAO;AAAA,YACT;AACA,gBAAI,eAAe,MAAM,SAAS,GAAG;AACnC,qBAAO;AAAA,YACT;AACA,gBAAI,aAAa;AACjB,gBAAI,YAAY;AAChB,gBAAI,WAAW,IAAI;AACjB,6BAAe;AACf,qBAAO;AAAA,EAAM,WAAW;AACxB,2BAAa;AAAA,YACf;AACA,kBAAM,+BAA+B,KAAK,IAAI,WAAW,cAAc;AACvE,gBAAI,iBAAiB,CAAC,wBAAwB,KAAK,GAAG;AACpD,qBAAO,KAAK,MAAM,UAAU;AAAA,YAC9B;AACA,kBAAM,KAAK,KAAK;AAChB,qBAAS,IAAI,GAAG,IAAI,8BAA8B,KAAK;AACrD,oBAAMC,OAAM,KAAK,CAAC;AAClB,oBAAM,MAAM,oBAAoBA,MAAK,OAAO,OAAO,UAAU,QAAQ,WAAW;AAChF,kBAAI,QAAQ,QAAW;AACrB,uBAAO,GAAG,SAAS,GAAG,UAAUA,IAAG,CAAC,IAAI,UAAU,GAAG,GAAG;AACxD,4BAAY;AAAA,cACd;AAAA,YACF;AACA,gBAAI,YAAY,gBAAgB;AAC9B,oBAAM,cAAc,YAAY;AAChC,qBAAO,GAAG,SAAS,SAAS,UAAU,IAAI,aAAa,WAAW,CAAC;AACnE,0BAAY;AAAA,YACd;AACA,gBAAI,WAAW,MAAM,UAAU,SAAS,GAAG;AACzC,oBAAM;AAAA,EAAK,WAAW,GAAG,GAAG;AAAA,EAAK,mBAAmB;AAAA,YACtD;AACA,kBAAM,IAAI;AACV,mBAAO,IAAI,GAAG;AAAA,UAChB;AAAA,UACA,KAAK;AACH,mBAAO,SAAS,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI;AAAA,UAChE,KAAK;AACH,mBAAO,UAAU,OAAO,SAAS;AAAA,UACnC,KAAK;AACH,mBAAO;AAAA,UACT,KAAK;AACH,gBAAI,QAAQ;AACV,qBAAO,OAAO,KAAK;AAAA,YACrB;AAAA;AAAA,UAEF;AACE,mBAAO,OAAO,KAAK,KAAK,IAAI;AAAA,QAChC;AAAA,MACF;AAEA,eAAS,uBAAwB,KAAK,OAAO,OAAO,UAAU,QAAQ,aAAa;AACjF,YAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,OAAO,MAAM,WAAW,YAAY;AACrF,kBAAQ,MAAM,OAAO,GAAG;AAAA,QAC1B;AAEA,gBAAQ,OAAO,OAAO;AAAA,UACpB,KAAK;AACH,mBAAO,UAAU,KAAK;AAAA,UACxB,KAAK,UAAU;AACb,gBAAI,UAAU,MAAM;AAClB,qBAAO;AAAA,YACT;AACA,gBAAI,MAAM,QAAQ,KAAK,MAAM,IAAI;AAC/B,qBAAO;AAAA,YACT;AAEA,kBAAM,sBAAsB;AAC5B,gBAAI,MAAM;AACV,gBAAI,OAAO;AAEX,gBAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,kBAAI,MAAM,WAAW,GAAG;AACtB,uBAAO;AAAA,cACT;AACA,kBAAI,eAAe,MAAM,SAAS,GAAG;AACnC,uBAAO;AAAA,cACT;AACA,oBAAM,KAAK,KAAK;AAChB,kBAAI,WAAW,IAAI;AACjB,+BAAe;AACf,uBAAO;AAAA,EAAK,WAAW;AACvB,uBAAO;AAAA,EAAM,WAAW;AAAA,cAC1B;AACA,oBAAM,2BAA2B,KAAK,IAAI,MAAM,QAAQ,cAAc;AACtE,kBAAI,IAAI;AACR,qBAAO,IAAI,2BAA2B,GAAG,KAAK;AAC5C,sBAAMD,OAAM,uBAAuB,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,OAAO,UAAU,QAAQ,WAAW;AAC5F,uBAAOA,SAAQ,SAAYA,OAAM;AACjC,uBAAO;AAAA,cACT;AACA,oBAAM,MAAM,uBAAuB,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,OAAO,UAAU,QAAQ,WAAW;AAC5F,qBAAO,QAAQ,SAAY,MAAM;AACjC,kBAAI,MAAM,SAAS,IAAI,gBAAgB;AACrC,sBAAM,cAAc,MAAM,SAAS,iBAAiB;AACpD,uBAAO,GAAG,IAAI,QAAQ,aAAa,WAAW,CAAC;AAAA,cACjD;AACA,kBAAI,WAAW,IAAI;AACjB,uBAAO;AAAA,EAAK,mBAAmB;AAAA,cACjC;AACA,oBAAM,IAAI;AACV,qBAAO,IAAI,GAAG;AAAA,YAChB;AACA,kBAAM,KAAK,KAAK;AAChB,gBAAI,aAAa;AACjB,gBAAI,WAAW,IAAI;AACjB,6BAAe;AACf,qBAAO;AAAA,EAAM,WAAW;AACxB,2BAAa;AAAA,YACf;AACA,gBAAI,YAAY;AAChB,uBAAWC,QAAO,UAAU;AAC1B,oBAAM,MAAM,uBAAuBA,MAAK,MAAMA,IAAG,GAAG,OAAO,UAAU,QAAQ,WAAW;AACxF,kBAAI,QAAQ,QAAW;AACrB,uBAAO,GAAG,SAAS,GAAG,UAAUA,IAAG,CAAC,IAAI,UAAU,GAAG,GAAG;AACxD,4BAAY;AAAA,cACd;AAAA,YACF;AACA,gBAAI,WAAW,MAAM,UAAU,SAAS,GAAG;AACzC,oBAAM;AAAA,EAAK,WAAW,GAAG,GAAG;AAAA,EAAK,mBAAmB;AAAA,YACtD;AACA,kBAAM,IAAI;AACV,mBAAO,IAAI,GAAG;AAAA,UAChB;AAAA,UACA,KAAK;AACH,mBAAO,SAAS,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI;AAAA,UAChE,KAAK;AACH,mBAAO,UAAU,OAAO,SAAS;AAAA,UACnC,KAAK;AACH,mBAAO;AAAA,UACT,KAAK;AACH,gBAAI,QAAQ;AACV,qBAAO,OAAO,KAAK;AAAA,YACrB;AAAA;AAAA,UAEF;AACE,mBAAO,OAAO,KAAK,KAAK,IAAI;AAAA,QAChC;AAAA,MACF;AAEA,eAAS,gBAAiB,KAAK,OAAO,OAAO,QAAQ,aAAa;AAChE,gBAAQ,OAAO,OAAO;AAAA,UACpB,KAAK;AACH,mBAAO,UAAU,KAAK;AAAA,UACxB,KAAK,UAAU;AACb,gBAAI,UAAU,MAAM;AAClB,qBAAO;AAAA,YACT;AACA,gBAAI,OAAO,MAAM,WAAW,YAAY;AACtC,sBAAQ,MAAM,OAAO,GAAG;AAExB,kBAAI,OAAO,UAAU,UAAU;AAC7B,uBAAO,gBAAgB,KAAK,OAAO,OAAO,QAAQ,WAAW;AAAA,cAC/D;AACA,kBAAI,UAAU,MAAM;AAClB,uBAAO;AAAA,cACT;AAAA,YACF;AACA,gBAAI,MAAM,QAAQ,KAAK,MAAM,IAAI;AAC/B,qBAAO;AAAA,YACT;AACA,kBAAM,sBAAsB;AAE5B,gBAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,kBAAI,MAAM,WAAW,GAAG;AACtB,uBAAO;AAAA,cACT;AACA,kBAAI,eAAe,MAAM,SAAS,GAAG;AACnC,uBAAO;AAAA,cACT;AACA,oBAAM,KAAK,KAAK;AAChB,6BAAe;AACf,kBAAIC,OAAM;AAAA,EAAK,WAAW;AAC1B,oBAAMC,QAAO;AAAA,EAAM,WAAW;AAC9B,oBAAM,2BAA2B,KAAK,IAAI,MAAM,QAAQ,cAAc;AACtE,kBAAI,IAAI;AACR,qBAAO,IAAI,2BAA2B,GAAG,KAAK;AAC5C,sBAAMH,OAAM,gBAAgB,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,OAAO,QAAQ,WAAW;AAC3E,gBAAAE,QAAOF,SAAQ,SAAYA,OAAM;AACjC,gBAAAE,QAAOC;AAAA,cACT;AACA,oBAAM,MAAM,gBAAgB,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,OAAO,QAAQ,WAAW;AAC3E,cAAAD,QAAO,QAAQ,SAAY,MAAM;AACjC,kBAAI,MAAM,SAAS,IAAI,gBAAgB;AACrC,sBAAM,cAAc,MAAM,SAAS,iBAAiB;AACpD,gBAAAA,QAAO,GAAGC,KAAI,QAAQ,aAAa,WAAW,CAAC;AAAA,cACjD;AACA,cAAAD,QAAO;AAAA,EAAK,mBAAmB;AAC/B,oBAAM,IAAI;AACV,qBAAO,IAAIA,IAAG;AAAA,YAChB;AAEA,gBAAI,OAAO,OAAO,KAAK,KAAK;AAC5B,kBAAM,YAAY,KAAK;AACvB,gBAAI,cAAc,GAAG;AACnB,qBAAO;AAAA,YACT;AACA,gBAAI,eAAe,MAAM,SAAS,GAAG;AACnC,qBAAO;AAAA,YACT;AACA,2BAAe;AACf,kBAAM,OAAO;AAAA,EAAM,WAAW;AAC9B,gBAAI,MAAM;AACV,gBAAI,YAAY;AAChB,gBAAI,+BAA+B,KAAK,IAAI,WAAW,cAAc;AACrE,gBAAI,wBAAwB,KAAK,GAAG;AAClC,qBAAO,oBAAoB,OAAO,MAAM,cAAc;AACtD,qBAAO,KAAK,MAAM,MAAM,MAAM;AAC9B,8CAAgC,MAAM;AACtC,0BAAY;AAAA,YACd;AACA,gBAAI,eAAe;AACjB,qBAAO,KAAK,MAAM,UAAU;AAAA,YAC9B;AACA,kBAAM,KAAK,KAAK;AAChB,qBAAS,IAAI,GAAG,IAAI,8BAA8B,KAAK;AACrD,oBAAMD,OAAM,KAAK,CAAC;AAClB,oBAAM,MAAM,gBAAgBA,MAAK,MAAMA,IAAG,GAAG,OAAO,QAAQ,WAAW;AACvE,kBAAI,QAAQ,QAAW;AACrB,uBAAO,GAAG,SAAS,GAAG,UAAUA,IAAG,CAAC,KAAK,GAAG;AAC5C,4BAAY;AAAA,cACd;AAAA,YACF;AACA,gBAAI,YAAY,gBAAgB;AAC9B,oBAAM,cAAc,YAAY;AAChC,qBAAO,GAAG,SAAS,WAAW,aAAa,WAAW,CAAC;AACvD,0BAAY;AAAA,YACd;AACA,gBAAI,cAAc,IAAI;AACpB,oBAAM;AAAA,EAAK,WAAW,GAAG,GAAG;AAAA,EAAK,mBAAmB;AAAA,YACtD;AACA,kBAAM,IAAI;AACV,mBAAO,IAAI,GAAG;AAAA,UAChB;AAAA,UACA,KAAK;AACH,mBAAO,SAAS,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI;AAAA,UAChE,KAAK;AACH,mBAAO,UAAU,OAAO,SAAS;AAAA,UACnC,KAAK;AACH,mBAAO;AAAA,UACT,KAAK;AACH,gBAAI,QAAQ;AACV,qBAAO,OAAO,KAAK;AAAA,YACrB;AAAA;AAAA,UAEF;AACE,mBAAO,OAAO,KAAK,KAAK,IAAI;AAAA,QAChC;AAAA,MACF;AAEA,eAAS,gBAAiB,KAAK,OAAO,OAAO;AAC3C,gBAAQ,OAAO,OAAO;AAAA,UACpB,KAAK;AACH,mBAAO,UAAU,KAAK;AAAA,UACxB,KAAK,UAAU;AACb,gBAAI,UAAU,MAAM;AAClB,qBAAO;AAAA,YACT;AACA,gBAAI,OAAO,MAAM,WAAW,YAAY;AACtC,sBAAQ,MAAM,OAAO,GAAG;AAExB,kBAAI,OAAO,UAAU,UAAU;AAC7B,uBAAO,gBAAgB,KAAK,OAAO,KAAK;AAAA,cAC1C;AACA,kBAAI,UAAU,MAAM;AAClB,uBAAO;AAAA,cACT;AAAA,YACF;AACA,gBAAI,MAAM,QAAQ,KAAK,MAAM,IAAI;AAC/B,qBAAO;AAAA,YACT;AAEA,gBAAI,MAAM;AAEV,kBAAM,YAAY,MAAM,WAAW;AACnC,gBAAI,aAAa,MAAM,QAAQ,KAAK,GAAG;AACrC,kBAAI,MAAM,WAAW,GAAG;AACtB,uBAAO;AAAA,cACT;AACA,kBAAI,eAAe,MAAM,SAAS,GAAG;AACnC,uBAAO;AAAA,cACT;AACA,oBAAM,KAAK,KAAK;AAChB,oBAAM,2BAA2B,KAAK,IAAI,MAAM,QAAQ,cAAc;AACtE,kBAAI,IAAI;AACR,qBAAO,IAAI,2BAA2B,GAAG,KAAK;AAC5C,sBAAMD,OAAM,gBAAgB,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK;AACtD,uBAAOA,SAAQ,SAAYA,OAAM;AACjC,uBAAO;AAAA,cACT;AACA,oBAAM,MAAM,gBAAgB,OAAO,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK;AACtD,qBAAO,QAAQ,SAAY,MAAM;AACjC,kBAAI,MAAM,SAAS,IAAI,gBAAgB;AACrC,sBAAM,cAAc,MAAM,SAAS,iBAAiB;AACpD,uBAAO,SAAS,aAAa,WAAW,CAAC;AAAA,cAC3C;AACA,oBAAM,IAAI;AACV,qBAAO,IAAI,GAAG;AAAA,YAChB;AAEA,gBAAI,OAAO,OAAO,KAAK,KAAK;AAC5B,kBAAM,YAAY,KAAK;AACvB,gBAAI,cAAc,GAAG;AACnB,qBAAO;AAAA,YACT;AACA,gBAAI,eAAe,MAAM,SAAS,GAAG;AACnC,qBAAO;AAAA,YACT;AACA,gBAAI,YAAY;AAChB,gBAAI,+BAA+B,KAAK,IAAI,WAAW,cAAc;AACrE,gBAAI,aAAa,wBAAwB,KAAK,GAAG;AAC/C,qBAAO,oBAAoB,OAAO,KAAK,cAAc;AACrD,qBAAO,KAAK,MAAM,MAAM,MAAM;AAC9B,8CAAgC,MAAM;AACtC,0BAAY;AAAA,YACd;AACA,gBAAI,eAAe;AACjB,qBAAO,KAAK,MAAM,UAAU;AAAA,YAC9B;AACA,kBAAM,KAAK,KAAK;AAChB,qBAAS,IAAI,GAAG,IAAI,8BAA8B,KAAK;AACrD,oBAAMC,OAAM,KAAK,CAAC;AAClB,oBAAM,MAAM,gBAAgBA,MAAK,MAAMA,IAAG,GAAG,KAAK;AAClD,kBAAI,QAAQ,QAAW;AACrB,uBAAO,GAAG,SAAS,GAAG,UAAUA,IAAG,CAAC,IAAI,GAAG;AAC3C,4BAAY;AAAA,cACd;AAAA,YACF;AACA,gBAAI,YAAY,gBAAgB;AAC9B,oBAAM,cAAc,YAAY;AAChC,qBAAO,GAAG,SAAS,UAAU,aAAa,WAAW,CAAC;AAAA,YACxD;AACA,kBAAM,IAAI;AACV,mBAAO,IAAI,GAAG;AAAA,UAChB;AAAA,UACA,KAAK;AACH,mBAAO,SAAS,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI;AAAA,UAChE,KAAK;AACH,mBAAO,UAAU,OAAO,SAAS;AAAA,UACnC,KAAK;AACH,mBAAO;AAAA,UACT,KAAK;AACH,gBAAI,QAAQ;AACV,qBAAO,OAAO,KAAK;AAAA,YACrB;AAAA;AAAA,UAEF;AACE,mBAAO,OAAO,KAAK,KAAK,IAAI;AAAA,QAChC;AAAA,MACF;AAEA,eAASG,WAAW,OAAO,UAAU,OAAO;AAC1C,YAAI,UAAU,SAAS,GAAG;AACxB,cAAI,SAAS;AACb,cAAI,OAAO,UAAU,UAAU;AAC7B,qBAAS,IAAI,OAAO,KAAK,IAAI,OAAO,EAAE,CAAC;AAAA,UACzC,WAAW,OAAO,UAAU,UAAU;AACpC,qBAAS,MAAM,MAAM,GAAG,EAAE;AAAA,UAC5B;AACA,cAAI,YAAY,MAAM;AACpB,gBAAI,OAAO,aAAa,YAAY;AAClC,qBAAO,oBAAoB,IAAI,EAAE,IAAI,MAAM,GAAG,CAAC,GAAG,UAAU,QAAQ,EAAE;AAAA,YACxE;AACA,gBAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,qBAAO,uBAAuB,IAAI,OAAO,CAAC,GAAG,qBAAqB,QAAQ,GAAG,QAAQ,EAAE;AAAA,YACzF;AAAA,UACF;AACA,cAAI,OAAO,WAAW,GAAG;AACvB,mBAAO,gBAAgB,IAAI,OAAO,CAAC,GAAG,QAAQ,EAAE;AAAA,UAClD;AAAA,QACF;AACA,eAAO,gBAAgB,IAAI,OAAO,CAAC,CAAC;AAAA,MACtC;AAEA,aAAOA;AAAA,IACT;AAAA;AAAA;;;AC9lBO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOO,IAAM,mBAA+C;AAAA,EAC1D,MAAM;AAAA,EACN,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,GAAG;AAAA,EACH,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AACX;AAGO,IAAM,oBAAgD;AAAA,EAC3D,MAAM;AAAA,EACN,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,GAAG;AAAA,EACH,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AACX;AA4BA,IAAM,cAA0B,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK;AACnF,IAAM,OAAO,CAAC,OAAe,QAAgB,WAAW,UAAyB,EAAE,OAAO,QAAQ,SAAS;AAEpG,IAAM,gBAAwC;AAAA,EACnD;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,IACjD,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC;AAAA,IACxB,MAAM,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK;AAAA,IACzD,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,IACjC,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC;AAAA,IACxB,MAAM,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK;AAAA,IACzD,OAAO,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,EAAE,OAAO,MAAM,MAAM,IAAI,EAAE;AAAA,IACnE,YAAY,EAAE,OAAO,KAAK,MAAM,KAAK;AAAA,IACrC,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,MAAM,KAAK,CAAC;AAAA,IACjE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,MACL,KAAK,KAAK,GAAG;AAAA,MACb,KAAK,KAAK,EAAE;AAAA,MACZ,KAAK,KAAK,EAAE;AAAA,MACZ,KAAK,KAAK,KAAK,KAAK;AAAA,MACpB,KAAK,KAAK,KAAK,KAAK;AAAA,MACpB,KAAK,KAAK,KAAK,KAAK;AAAA,MACpB,KAAK,KAAK,KAAK,KAAK;AAAA,MACpB,KAAK,KAAK,KAAK,KAAK;AAAA,IACtB;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,MAAM,KAAK,CAAC;AAAA,IACjE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,MAAM,KAAK,CAAC;AAAA,IACjE,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,IAChD,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,IAChD,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC;AAAA,IACxB,MAAM,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK;AAAA,IACzD,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK,MAAM,EAAE,OAAO,MAAM,MAAM,KAAK,EAAE;AAAA,IACnE,YAAY,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACrC,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,GAAG,KAAK,KAAK,KAAK,KAAK,CAAC;AAAA,IACvE,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC;AAAA,IACxB,MAAM,EAAE,KAAK,KAAK,QAAQ,KAAK,MAAM,MAAM,OAAO,KAAK;AAAA,IACvD,OAAO,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,EAAE,OAAO,MAAM,MAAM,KAAK,EAAE;AAAA,IACpE,YAAY,EAAE,OAAO,MAAM,MAAM,IAAI;AAAA,IACrC,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,GAAG,GAAG,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,IAChD,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,MAAM,KAAK,GAAG,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,IACzE,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,KAAM,IAAI,GAAG,KAAK,KAAM,KAAM,KAAK,CAAC;AAAA,IACjD,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC;AAAA,IACxB,MAAM,EAAE,KAAK,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK;AAAA,IACzD,OAAO,EAAE,KAAK,MAAM,QAAQ,KAAK;AAAA,IACjC,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO,CAAC,KAAK,MAAM,IAAI,CAAC;AAAA,IACxB,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,EACV;AACF;AAEA,IAAM,SAA0C;AAAA,EAC9C,CAAC,OAAO,CAAC;AAAA,EACT,CAAC,OAAO,IAAI,CAAC;AAAA,EACb,CAAC,QAAQ,IAAI,EAAE;AAAA,EACf,CAAC,QAAQ,KAAK,CAAC;AAAA,EACf,CAAC,UAAU,IAAI;AAAA,EACf,CAAC,OAAO,IAAI,CAAC;AAAA,EACb,CAAC,OAAO,IAAI,CAAC;AAAA,EACb,CAAC,OAAO,IAAI,CAAC;AACf;AAGO,SAAS,WAAW,OAAe,QAAwB;AAChE,QAAM,IAAI,QAAQ;AAClB,QAAM,QAAQ,OAAO,KAAK,CAAC,CAAC,EAAE,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI;AAC7E,SAAO,QAAQ,MAAM,CAAC,IAAI,GAAG,KAAK,IAAI,MAAM;AAC9C;AAgCO,SAAS,cAAc,OAA4E;AACxG,QAAM,aAA4B,CAAC;AACnC,QAAM,UAAoB,CAAC;AAC3B,aAAW,OAAO,OAAO;AACvB,UAAM,OAAO,IAAI,KAAK,EAAE,YAAY;AACpC,QAAI,CAAC,KAAM;AACX,UAAM,QAAQ,cAAc,OAAO,CAAC,MAAM,EAAE,OAAO,QAAS,EAAE,aAAa,QAAQ,CAAC,EAAE,KAAM;AAC5F,QAAI,MAAM,WAAW,EAAG,SAAQ,KAAK,IAAI,KAAK,CAAC;AAC/C,eAAW,KAAK,MAAO,KAAI,CAAC,WAAW,SAAS,CAAC,EAAG,YAAW,KAAK,CAAC;AAAA,EACvE;AACA,SAAO,EAAE,YAAY,QAAQ;AAC/B;AAGA,SAAS,QAAQ,MAAyB,QAAgBC,OAAqB,WAAyB;AACtG,QAAM,WAAW,KAAK,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AACrD,MAAI,CAAC,UAAU;AACb,SAAK,KAAK,EAAE,QAAQ,OAAOA,MAAK,OAAO,QAAQA,MAAK,QAAQ,YAAY,CAAC,SAAS,EAAE,CAAC;AACrF;AAAA,EACF;AACA,MAAI,CAAC,SAAS,WAAW,SAAS,SAAS,EAAG,UAAS,WAAW,KAAK,SAAS;AAChF,MAAIA,MAAK,QAAQ,SAAS,MAAO,QAAO,OAAO,UAAU,EAAE,OAAOA,MAAK,OAAO,QAAQA,MAAK,OAAO,CAAC;AACrG;AAGA,SAAS,OAAO,OAA8C;AAC5D,aAAW,OAAO,OAAO;AACvB,UAAM,OAAO,IAAI,KAAK,EAAE,YAAY;AACpC,QAAI,QAAQ,iBAAkB,QAAO,iBAAiB,IAAkB;AACxE,UAAM,YAAY,cAAc,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI;AACzD,UAAM,QAAQ,WAAW,MAAM,KAAK,CAAC,MAAM,EAAE,QAAQ;AACrD,QAAI,MAAO,QAAO,WAAW,MAAM,OAAO,MAAM,MAAM;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,UAAU,SAA4B,MAA6C;AAC1F,QAAM,KAAK,QAAQ,UAAU,CAAC,MAAM,EAAE,WAAW,IAAI;AACrD,SAAO,MAAM,IAAI,UAAU,CAAC,QAAQ,EAAE,GAAsB,GAAG,QAAQ,OAAO,CAAC,GAAG,MAAM,MAAM,EAAE,CAAC;AACnG;AAQO,SAAS,aAAa,OAA0B,OAAyC;AAC9F,QAAM,EAAE,YAAY,QAAQ,IAAI,cAAc,KAAK;AACnD,QAAM,EAAE,UAAU,OAAO,QAAQ,IAAI,QAAQ,UAAU;AACvD,QAAM,EAAE,SAAS,QAAQ,IACvB,SAAS,MAAM,SAAS,IAAI,WAAW,OAAO,OAAO,UAAU,IAAI,EAAE,SAAS,UAAU,SAAS,CAAC,EAAE;AACtG,QAAM,eAAe,OAAO,KAAK;AACjC,QAAM,OAAO,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,YAAY,IAAI,eAAe,QAAQ,CAAC,GAAG;AACzF,QAAM,YAAY,UAAU,SAAS,IAAI;AACzC,QAAM,SAAS,IAAI,IAAI,UAAU,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;AAC7D,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,SAAS;AAAA,IACT;AAAA,IACA,YAAY,WAAW,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,CAAC,OAAO,OAAO,IAAI,EAAE,CAAC;AAAA,IACrE;AAAA,IACA;AAAA,IACA,SAAS,WAAW,OAAO,CAAC,MAAM,WAAW,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,EACvF;AACF;AAGA,SAAS,QAAQ,YAAoC;AACnD,QAAM,WAA8B,CAAC;AACrC,QAAM,QAA2B,CAAC;AAClC,QAAM,UAA6B,CAAC;AACpC,aAAW,aAAa,YAAY;AAClC,eAAW,KAAK,UAAU,OAAO;AAC/B,YAAM,SAAS,WAAW,EAAE,OAAO,EAAE,MAAM;AAC3C,UAAI,SAAS,MAAM,GAAG;AACpB,YAAI,EAAE,SAAU,SAAQ,SAAS,QAAQ,GAAG,UAAU,EAAE;AACxD;AAAA,MACF;AACA,cAAQ,OAAO,QAAQ,GAAG,UAAU,EAAE;AACtC,UAAI,EAAE,SAAU,SAAQ,UAAU,QAAQ,GAAG,UAAU,EAAE;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,EAAE,UAAU,OAAO,QAAQ;AACpC;AAGA,SAAS,WAAW,OAA0B,OAAmC,YAAoC;AACnH,QAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,WAAW,IAAI,CAAC,MAAM,kBAAkB,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,KAAK;AACjG,QAAM,UAA6B,CAAC;AACpC,QAAM,UAAmC,CAAC;AAC1C,aAAW,UAAU,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,GAAG;AACxD,UAAM,QAAQ,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AACnD,QAAI,MAAO,SAAQ,KAAK,KAAK;AAAA,QACxB,SAAQ,KAAK,EAAE,QAAQ,KAAK,GAAG,KAAK,aAAa,MAAM,WAAW,CAAC;AAAA,EAC1E;AACA,SAAO,EAAE,SAAS,QAAQ;AAC5B;AAEA,IAAM,WAAW,CAAC,WAAmB,OAAO,SAAS,GAAG;AAExD,IAAM,aAAa,CAAC,MAAmB,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,SAAS,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAM1G,SAAS,cACd,cACyE;AACzE,QAAM,WAAW,cAAc,OAAO,CAAC,MAAM,aAAa,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK;AACnF,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,MAAM,CAAC,SAAiD,KAAK,IAAI,GAAG,SAAS,IAAI,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3G,QAAM,QAAQ,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI;AAClD,QAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,UAAU;AACnD,SAAO;AAAA,IACL,KAAK,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG;AAAA,IAC5B,QAAQ,IAAI,CAAC,MAAM,EAAE,OAAO,MAAM;AAAA,IAClC,GAAI,MAAM,SAAS,IACf;AAAA,MACE,MAAM;AAAA,QACJ,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,MAAM,KAAK;AAAA,QACtC,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,MAAM,QAAQ,CAAC,CAAC;AAAA,MAC9D;AAAA,IACF,IACA,CAAC;AAAA,IACL,GAAI,QAAQ,SAAS,IACjB;AAAA,MACE,YAAY;AAAA,QACV,OAAO,IAAI,CAAC,MAAM,EAAE,YAAY,KAAK;AAAA,QACrC,MAAM,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,YAAY,QAAQ,CAAC,CAAC;AAAA,MAC/D;AAAA,IACF,IACA,CAAC;AAAA,IACL,MAAM;AAAA,MACJ,KAAK,IAAI,CAAC,MAAM,EAAE,KAAK,GAAG;AAAA,MAC1B,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,MAAM;AAAA,MAChC,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI;AAAA,MAC5B,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,KAAK;AAAA,IAChC;AAAA,EACF;AACF;;;AC/bO,IAAM,oBACX;AAwBK,IAAM,mBACX;AAIK,IAAM,mBACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC5BK,SAAS,gBAAgB,MAAc,OAAkC;AAC9E,MAAI,MAAM;AACV,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,KAAK,KAAK;AACxB,QAAI,MAAM,SAAS,EAAG;AACtB,UAAM,UAAU,IAAI,OAAO,sBAAsB,iBAAiB,KAAK,CAAC,sBAAsB,KAAK;AACnG,UAAM,IAAI,QAAQ,SAAS,6BAA6B;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAuB;AAC/C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;;;ACXO,IAAM,sBAAsB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaO,IAAM,6BAAyE;AAAA,EACpF,WAAW,EAAE,SAAS,CAAC,KAAK,GAAG,MAAM,8BAA8B;AAAA,EACnE,mBAAmB,EAAE,SAAS,CAAC,OAAO,MAAM,GAAG,MAAM,6BAA6B;AAAA,EAClF,UAAU,EAAE,SAAS,CAAC,OAAO,QAAQ,KAAK,GAAG,MAAM,sCAAsC;AAAA,EACzF,UAAU,EAAE,SAAS,CAAC,KAAK,GAAG,MAAM,uCAAuC;AAAA,EAC3E,eAAe;AAAA;AAAA;AAAA,IAGb,SAAS,CAAC,OAAO,MAAM;AAAA,IACvB,SAAS,CAAC,QAAQ;AAAA,IAClB,MAAM;AAAA,EACR;AAAA,EACA,kBAAkB;AAAA;AAAA,IAEhB,SAAS,CAAC,OAAO,OAAO,MAAM;AAAA,IAC9B,SAAS,CAAC,QAAQ;AAAA,IAClB,MAAM;AAAA,EACR;AAAA,EACA,QAAQ,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,+BAA+B;AAAA,EAClE,SAAS,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,yCAAyC;AAC/E;AAGO,SAAS,gBAAgB,UAA+C;AAC7E,SAAO,2BAA2B,QAAQ,EAAE;AAC9C;AAQO,SAAS,oBAAoB,QAGd;AACpB,MAAI,OAAO,SAAU,QAAO,gBAAgB,OAAO,QAAQ;AAC3D,SAAO,OAAO,WAAW,CAAC;AAC5B;;;AC4BA,IAAM,mBAA8B,EAAE,UAAU,aAAa;AAC7D,IAAM,eAA6B,EAAE,MAAM,QAAQ;AAS5C,IAAM,qBAAqB;AAO3B,IAAM,+BAA8C;AAAA,EACzD,UAAU;AAAA,EACV,WAAW;AACb;AA6CA,IAAM,sBAAsB,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,QAAQ,QAAQ,MAAM;AACpG,IAAM,8BAA8B,CAAC,GAAG,qBAAqB,OAAO,OAAO,OAAO,KAAK;AASvF,IAAM,0BAA0B,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,QAAQ,QAAQ,MAAM;AAqB1F,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB;AAC3B,IAAM,sBAAsB;AAC5B,IAAM,mBAAmB;AAEzB,IAAM,aAAa;AACnB,IAAM,eAAe;AAKrB,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AACpC,IAAM,yBAAyB;AAC/B,IAAM,0BAA0B;AAEhC,IAAM,wBAAwB,CAAC,MAAM,MAAM,IAAI;AAWxC,IAAM,yBAAyB,CAAC,QAAQ,GAAG,qBAAqB;AACvE,IAAM,iCAAiC;AAMvC,IAAM,yBAAyB,CAAC,IAAI;AAMpC,IAAM,2BAA2B,CAAC,QAAQ,OAAO,UAAU,MAAM;AAOjE,IAAM,8BAA8B,CAAC,QAAQ,OAAO,UAAU,QAAQ,SAAS,KAAK;AAUpF,IAAM,qBAAkC,EAAE,MAAM,UAAU,SAAS,MAAM,KAAK,GAAG,KAAK,GAAG;AASzF,IAAM,mBAAmB,CAAC,OAAO,OAAO,OAAO,QAAQ,MAAM;AAStD,IAAM,qBAAqB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAwBpE,IAAM,wBAAwB;AAAA,EACnC;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AACpG;AAGO,IAAM,4BAA4B,CAAC,OAAO,OAAO,QAAQ,OAAO,QAAQ,MAAM;AAO9E,IAAM,0BAA0B,CAAC,QAAQ,MAAM;AAU/C,IAAM,mCAAmC;AACzC,IAAM,mCAAmC;AACzC,IAAM,mCAAmC;AAIzC,IAAM,kBAAkB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAsBpE,IAAM,wBAAwB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAMtD,IAAM,4BAA4B,CAAC,QAAQ,MAAM;AA2BjD,IAAM,0BAA0B,CAAC,QAAQ,QAAQ,SAAS,IAAI;AAW9D,IAAM,0BAA0B,CAAC,aAAa,cAAc,YAAY;AAQxE,IAAM,yBAAyB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAG7D,IAAM,mBAAmB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAEpD,IAAM,uBAAuB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAGzE,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAC1G;AAIO,IAAM,4BAA4B,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAGpF,IAAM,sBAAsB,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE;AAMvD,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,IAAM,4BAA4B;AAClC,IAAM,iCAAiC;AAqBvC,IAAM,0BAA0B;AAMvC,IAAM,yBAAyB,CAAC,aAAa,cAAc,cAAc,WAAW;AAMpF,IAAM,mCAAmC,CAAC,aAAa,mBAAmB,YAAY;AAOtF,IAAM,mCAAmC,CAAC,cAAc,aAAa,WAAW;AAChF,IAAM,wBAAwB,CAAC,aAAa,cAAc,YAAY;AACtE,IAAM,wBAAwB,CAAC,aAAa,cAAc,iBAAiB;AAE3E,IAAM,0BAA0B,CAAC,aAAa,cAAc,iBAAiB;AAC7E,IAAM,wBAAwB,CAAC,aAAa,cAAc,WAAW;AAa9D,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUO,IAAM,+BAAuE;AAmBpF,IAAM,mBAAiG;AAAA,EACrG,iCAAiC;AAAA,EACjC,sBAAsB;AAAA,EACtB,iCAAiC;AAAA,EACjC,sCAAsC;AAAA,EACtC,6BAA6B;AAAA,EAC7B,mCAAmC;AACrC;AAGO,IAAM,qBAAqB,EAAE,KAAK,IAAI,UAAU,EAAE;AAGlD,SAAS,oBAAoB,OAAuB;AACzD,QAAM,OACH,iBAAkE,iBAAiB,KAAK,CAAC,KAAK;AACjG,SAAO,mBAAmB,IAAI;AAChC;AA0BO,IAAM,wBAAwB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaO,IAAM,+BAAuE;AAwC7E,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,yBAAyB,OAAwB;AAC/D,SAAQ,0BAAgD,SAAS,KAAK;AACxE;AAqDO,IAAM,6BAAmE;AAazE,SAAS,kBAAkB,OAAwB;AACxD,SAAO,MAAM,WAAW,oBAAoB;AAC9C;AAYO,IAAM,4BAA4B;AAGlC,SAAS,yBAAyB,OAAwB;AAC/D,SAAO,UAAU;AACnB;AAYO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,UAAU;AACnB;AAgBO,IAAM,6BAA6B;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,kBAAkB,OAAwB;AACxD,SAAQ,2BAAiD,SAAS,KAAK;AACzE;AAiCO,IAAM,iBAAkF;AAAA,EAC7F,eAAe;AAAA,IACb,+BAA+B;AAAA,MAC7B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,iBAAiB,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,aAAa,EAAE;AAAA,QACjE,YAAY,EAAE,MAAM,UAAU;AAAA,QAC9B,aAAa,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC9C,YAAY,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,MACvC;AAAA,IACF;AAAA,IACA,6BAA6B;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,iBAAiB,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,aAAa,EAAE;AAAA,QACjE,YAAY,EAAE,MAAM,UAAU;AAAA,QAC9B,aAAa,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC9C,YAAY,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAgB;AAAA;AAAA;AAAA,IAGd,6BAA6B;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,SAAS,EAAE,MAAM,SAAS;AAAA,QAC1B,aAAa,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC9C,YAAY,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,MACvC;AAAA,IACF;AAAA,IACA,+BAA+B;AAAA,MAC7B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,SAAS,EAAE,MAAM,SAAS;AAAA,QAC1B,aAAa,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC9C,YAAY,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,IAKZ,+BAA+B;AAAA,MAC7B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,OAAO,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,QAChC,aAAa,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC9C,YAAY,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,MACvC;AAAA,IACF;AAAA,IACA,6BAA6B;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,OAAO,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,QAChC,aAAa,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC9C,YAAY,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAQd,iCAAiC;AAAA;AAAA;AAAA;AAAA,MAI/B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,KAAK,yBAAyB,CAAC;AAAA,MACjG,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,UAAU,WAAW,qBAAqB;AAAA,QAC1D,cAAc,EAAE,MAAM,UAAU,MAAM,wBAAwB;AAAA,QAC9D,SAAS,EAAE,MAAM,UAAU,MAAM,4BAA4B;AAAA,QAC7D,GAAG;AAAA,MACL;AAAA,IACF;AAAA,IACA,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOpB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,KAAK,yBAAyB,CAAC;AAAA,MACjG,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,UAAU,WAAW,qBAAqB;AAAA,QAC1D,cAAc,EAAE,MAAM,UAAU,MAAM,wBAAwB;AAAA,QAC9D,SAAS,EAAE,MAAM,UAAU,MAAM,yBAAyB;AAAA,MAC5D;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA,iCAAiC;AAAA,MAC/B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,KAAK,4BAA4B,CAAC;AAAA,MACpG,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,4BAA4B;AAAA,QAClE,YAAY,EAAE,MAAM,UAAU,MAAM,+BAA+B;AAAA,MACrE;AAAA,IACF;AAAA,IACA,6BAA6B;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,KAAK,4BAA4B,CAAC;AAAA,MACpG,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,oBAAoB;AAAA,QAC1D,YAAY,EAAE,MAAM,UAAU,MAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA,MAI5D;AAAA,IACF;AAAA,IACA,sCAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAepC,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,KAAK,4BAA4B,CAAC;AAAA,MACpG,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,4BAA4B;AAAA,QAClE,YAAY,EAAE,MAAM,UAAU,MAAM,uBAAuB;AAAA,MAC7D;AAAA,IACF;AAAA,IACA,mCAAmC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYjC,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,KAAK,uBAAuB,CAAC;AAAA,MAC/F,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,UAAU,WAAW,mBAAmB;AAAA,QACxD,cAAc,EAAE,MAAM,UAAU,MAAM,iBAAiB;AAAA,QACvD,UAAU,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC3C,YAAY,EAAE,MAAM,OAAO;AAAA,QAC3B,sBAAsB,EAAE,MAAM,OAAO;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,IAKrB,6BAA6B;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC,uBAAuB,cAAc;AAAA,MAChD,QAAQ;AAAA,QACN,qBAAqB,EAAE,MAAM,SAAS;AAAA,QACtC,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,aAAa,UAAU,WAAW,UAAU,EAAE;AAAA,QACrF,OAAO,EAAE,MAAM,OAAO;AAAA,QACtB,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,iBAAiB,EAAE,MAAM,SAAS;AAAA,QAClC,cAAc,EAAE,MAAM,UAAU,MAAM,oBAAoB;AAAA,QAC1D,YAAY,EAAE,MAAM,UAAU,MAAM,sBAAsB;AAAA,MAC5D;AAAA,IACF;AAAA,IACA,iCAAiC;AAAA,MAC/B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC,uBAAuB,cAAc;AAAA,MAChD,QAAQ;AAAA,QACN,qBAAqB,EAAE,MAAM,SAAS;AAAA,QACtC,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,aAAa,UAAU,WAAW,UAAU,EAAE;AAAA,QACrF,OAAO,EAAE,MAAM,OAAO;AAAA,QACtB,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,iBAAiB,EAAE,MAAM,SAAS;AAAA,QAClC,cAAc,EAAE,MAAM,UAAU,MAAM,4BAA4B;AAAA,QAClE,YAAY,EAAE,MAAM,UAAU,MAAM,+BAA+B;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAWlB,6BAA6B;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,SAAS,EAAE,MAAM,OAAO;AAAA,QACxB,UAAU,EAAE,MAAM,UAAU,MAAM,oBAAoB;AAAA,QACtD,UAAU,EAAE,MAAM,SAAS;AAAA,QAC3B,MAAM,EAAE,MAAM,OAAO;AAAA,QACrB,YAAY,EAAE,MAAM,OAAO;AAAA,QAC3B,YAAY,EAAE,MAAM,UAAU,MAAM,sBAAsB;AAAA,MAC5D;AAAA,IACF;AAAA,IACA,iCAAiC;AAAA,MAC/B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MACzD,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,SAAS,EAAE,MAAM,OAAO;AAAA,QACxB,UAAU,EAAE,MAAM,UAAU,MAAM,oBAAoB;AAAA,QACtD,UAAU,EAAE,MAAM,SAAS;AAAA,QAC3B,MAAM,EAAE,MAAM,OAAO;AAAA,QACrB,YAAY,EAAE,MAAM,OAAO;AAAA,QAC3B,YAAY,EAAE,MAAM,UAAU,MAAM,+BAA+B;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAgB;AAAA,IACd,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASxB,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,YAAY;AAAA,MAC/B,SAAS,EAAE,MAAM,WAAW,SAAS,eAAe;AAAA,MACpD,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,KAAK,wBAAwB,CAAC;AAAA,MAC/F,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA;AAAA;AAAA,QAGN,QAAQ,EAAE,MAAM,UAAU,WAAW,oBAAoB;AAAA,QACzD,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,MAAM,CAAC,OAAO,OAAO,QAAQ,OAAO,QAAQ,QAAQ,MAAM;AAAA,QAC5D;AAAA,QACA,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,SAAS,IAAI,EAAE;AAAA,QACpE,UAAU,EAAE,MAAM,UAAU,MAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA,QAIrD,MAAM,EAAE,MAAM,UAAU,SAAS,KAAK;AAAA,QACtC,gBAAgB,EAAE,MAAM,UAAU;AAAA,MACpC;AAAA,IACF;AAAA,IACA,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAsBxB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS,EAAE,MAAM,WAAW,SAAS,eAAe;AAAA,MACpD,eAAe;AAAA,MACf,QAAQ,CAAC;AAAA,MACT,iBAAiB;AAAA,QACf,EAAE,MAAM,SAAS,OAAO,wBAAwB,KAAK,iCAAiC;AAAA,QACtF,EAAE,MAAM,SAAS,OAAO,kCAAkC,KAAK,iCAAiC;AAAA,QAChG,EAAE,MAAM,SAAS,OAAO,kCAAkC,KAAK,iCAAiC;AAAA,MAClG;AAAA,MACA,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,QAChE,YAAY,EAAE,MAAM,UAAU,MAAM,wBAAwB;AAAA,QAC5D,UAAU,EAAE,MAAM,UAAU,MAAM,sBAAsB;AAAA,QACxD,MAAM,EAAE,MAAM,UAAU,SAAS,MAAM,KAAK,GAAG,KAAK,WAAW;AAAA,QAC/D,gBAAgB,EAAE,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAKlC,WAAW,EAAE,MAAM,UAAU;AAAA,MAC/B;AAAA,IACF;AAAA,IACA,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAoD9B,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,uBAAuB,WAAW,wBAAwB;AAAA,MAC7E,SAAS,EAAE,MAAM,WAAW,SAAS,cAAc;AAAA,MACnD,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,CAAC;AAAA,MACnE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,QAChE,YAAY,EAAE,MAAM,UAAU,MAAM,wBAAwB;AAAA,QAC5D,UAAU,EAAE,MAAM,UAAU,MAAM,sBAAsB;AAAA,MAC1D;AAAA,IACF;AAAA,IACA,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiB1B,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,uBAAuB,WAAW,4BAA4B;AAAA,MACjF,SAAS,EAAE,MAAM,WAAW,SAAS,cAAc;AAAA,MACnD,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,CAAC;AAAA,MACnE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,QAChE,UAAU,EAAE,MAAM,UAAU,MAAM,sBAAsB;AAAA,MAC1D;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOhB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA;AAAA;AAAA;AAAA,QAIN,KAAK,EAAE,QAAQ,KAAK,OAAO,KAAK,cAAc,EAAE,MAAM,EAAE,QAAQ,KAAK,OAAO,IAAI,EAAE,EAAE;AAAA,MACtF;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,iBAAiB,EAAE,MAAM,SAAS;AAAA,QAClC,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,MAAM,EAAE;AAAA,QACvD,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,SAAS,IAAI,EAAE;AAAA,QAC5D,UAAU,EAAE,MAAM,UAAU,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA;AAAA,QAE5C,MAAM,EAAE,MAAM,UAAU,SAAS,MAAM,KAAK,GAAG,KAAK,aAAa;AAAA,QACjE,gBAAgB,EAAE,MAAM,UAAU;AAAA,QAClC,mBAAmB,EAAE,MAAM,UAAU,MAAM,CAAC,aAAa,aAAa,EAAE;AAAA,QACxE,gBAAgB,EAAE,MAAM,UAAU;AAAA,QAClC,oBAAoB,EAAE,MAAM,SAAS;AAAA,MACvC;AAAA,IACF;AAAA,IACA,0BAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWxB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA;AAAA,QAEN,KAAK,EAAE,QAAQ,OAAO,OAAO,MAAM;AAAA,MACrC;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA;AAAA;AAAA;AAAA,QAIN,QAAQ,EAAE,MAAM,UAAU,WAAW,iBAAiB;AAAA,QACtD,iBAAiB,EAAE,MAAM,UAAU,WAAW,iBAAiB;AAAA,QAC/D,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,KAAK,EAAE;AAAA,QAC9D,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,EAAE;AAAA,QAC7C,UAAU,EAAE,MAAM,UAAU,MAAM,gBAAgB;AAAA,QAClD,gBAAgB,EAAE,MAAM,UAAU;AAAA,QAClC,WAAW,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,2BAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQzB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,UACH,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,cAAc,EAAE,QAAQ,EAAE,QAAQ,MAAM,OAAO,KAAK,GAAG,QAAQ,EAAE,QAAQ,MAAM,OAAO,KAAK,EAAE;AAAA,QAC/F;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,OAAO,OAAO,OAAO,OAAO,KAAK,EAAE;AAAA,QAC1F,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,MAAM,EAAE;AAAA,QACrD,UAAU,EAAE,MAAM,UAAU,MAAM,uBAAuB;AAAA,MAC3D;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYjB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA;AAAA,QAEN,KAAK,EAAE,QAAQ,KAAK,OAAO,IAAI;AAAA,QAC/B,kBAAkB;AAAA,MACpB;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,iBAAiB,EAAE,MAAM,SAAS;AAAA,QAClC,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,EAAE;AAAA,QAC/C,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,OAAO,EAAE;AAAA,QACtD,UAAU,EAAE,MAAM,UAAU,MAAM,iBAAiB;AAAA,QACnD,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,gBAAgB,EAAE,MAAM,UAAU;AAAA,MACpC;AAAA,IACF;AAAA,IACA,+BAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAS7B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA;AAAA;AAAA,QAGN,KAAK;AAAA,UACH,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,cAAc;AAAA,YACZ,QAAQ,EAAE,QAAQ,MAAM,OAAO,KAAK;AAAA,YACpC,QAAQ,EAAE,QAAQ,MAAM,OAAO,KAAK;AAAA,YACpC,SAAS,EAAE,QAAQ,MAAM,OAAO,KAAK;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,OAAO,OAAO,OAAO,OAAO,KAAK,EAAE;AAAA,QAC1F,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,OAAO,EAAE;AAAA,QAC9D,UAAU,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,MAC9D;AAAA,IACF;AAAA,IACA,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAajB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA;AAAA;AAAA,QAGN,KAAK;AAAA,UACH,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,cAAc;AAAA,YACZ,QAAQ,EAAE,QAAQ,MAAM,OAAO,KAAK;AAAA,YACpC,QAAQ,EAAE,QAAQ,KAAK,OAAO,IAAI;AAAA,YAClC,SAAS,EAAE,QAAQ,KAAK,OAAO,IAAI;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,OAAO,OAAO,KAAK,EAAE;AAAA,QAC5E,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,OAAO,EAAE;AAAA,QAC9D,UAAU,EAAE,MAAM,UAAU,MAAM,iBAAiB;AAAA,QACnD,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,gBAAgB,EAAE,MAAM,UAAU;AAAA,MACpC;AAAA,IACF;AAAA,IACA,kBAAkB;AAAA;AAAA;AAAA,MAGhB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA;AAAA,QAEN,KAAK,EAAE,QAAQ,MAAM,OAAO,KAAK;AAAA,MACnC;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,MAAM,EAAE;AAAA,QACvD,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,MAAM,EAAE;AAAA,QAC7C,UAAU,EAAE,MAAM,UAAU,MAAM,oBAAoB;AAAA,QACtD,MAAM,EAAE,MAAM,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,IACA,0BAA0B;AAAA;AAAA;AAAA;AAAA,MAIxB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA,QACN,KAAK,EAAE,QAAQ,QAAQ,OAAO,QAAQ,cAAc,EAAE,QAAQ,EAAE,QAAQ,QAAQ,OAAO,OAAO,EAAE,EAAE;AAAA,QAClG,kBAAkB;AAAA,MACpB;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,QAAQ,OAAO,OAAO,OAAO,QAAQ,MAAM,EAAE;AAAA,QAC5F,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,OAAO,EAAE;AAAA,QACtD,UAAU,EAAE,MAAM,UAAU,MAAM,qBAAqB;AAAA,QACvD,MAAM,EAAE,MAAM,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,IACA,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,MAKrB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA,QACN,KAAK,EAAE,QAAQ,MAAM,OAAO,MAAM,cAAc,EAAE,QAAQ,EAAE,QAAQ,MAAM,OAAO,KAAK,EAAE,EAAE;AAAA,MAC5F;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,iBAAiB,EAAE,MAAM,SAAS;AAAA,QAClC,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,MAAM,EAAE;AAAA,QACvD,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,OAAO,EAAE;AAAA,QACtD,UAAU,EAAE,MAAM,UAAU,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA,QAC5C,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,gBAAgB,EAAE,MAAM,UAAU;AAAA,QAClC,mBAAmB,EAAE,MAAM,UAAU,MAAM,CAAC,aAAa,aAAa,EAAE;AAAA,QACxE,gBAAgB,EAAE,MAAM,UAAU;AAAA,QAClC,oBAAoB,EAAE,MAAM,SAAS;AAAA,MACvC;AAAA,IACF;AAAA,IACA,uBAAuB;AAAA;AAAA;AAAA,MAGrB,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,QACP,MAAM;AAAA,QACN,KAAK;AAAA,UACH,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,cAAc,EAAE,QAAQ,EAAE,QAAQ,MAAM,OAAO,IAAI,GAAG,MAAM,EAAE,QAAQ,MAAM,OAAO,IAAI,EAAE;AAAA,QAC3F;AAAA,MACF;AAAA,MACA,QAAQ,CAAC;AAAA,MACT,iBAAiB,CAAC,EAAE,MAAM,SAAS,OAAO,uBAAuB,CAAC;AAAA,MAClE,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,iBAAiB,EAAE,MAAM,SAAS;AAAA,QAClC,cAAc,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,MAAM,EAAE;AAAA,QACvD,YAAY,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,SAAS,IAAI,EAAE;AAAA,QAC5D,UAAU,EAAE,MAAM,UAAU,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA,QAC5C,MAAM,EAAE,MAAM,UAAU,SAAS,MAAM,KAAK,GAAG,KAAK,aAAa;AAAA,QACjE,gBAAgB,EAAE,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA,QAIlC,mBAAmB,EAAE,MAAM,UAAU,MAAM,CAAC,aAAa,aAAa,EAAE;AAAA,QACxE,gBAAgB,EAAE,MAAM,UAAU;AAAA,QAClC,oBAAoB,EAAE,MAAM,SAAS;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBAAmB;AAAA;AAAA;AAAA;AAAA,IAIjB,+BAA+B;AAAA,MAC7B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,CAAC;AAAA,MAC1D,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,MAAM,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,OAAO,EAAE;AAAA,QAChD,UAAU,EAAE,MAAM,SAAS;AAAA,QAC3B,YAAY,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,GAAG;AAAA,QAC9C,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,SAAS,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,QAClC,OAAO,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,QAChC,YAAY,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,GAAG;AAAA,QAC9C,aAAa,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,UAAU,EAAE;AAAA;AAAA;AAAA;AAAA,QAI1D,WAAW,EAAE,MAAM,OAAO;AAAA,MAC5B;AAAA,IACF;AAAA,IACA,6BAA6B;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,wBAAwB,CAAC;AAAA,MAC1D,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,MAAM,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,OAAO,EAAE;AAAA,QAChD,UAAU,EAAE,MAAM,SAAS;AAAA,QAC3B,YAAY,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,GAAG;AAAA,QAC9C,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,SAAS,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,QAClC,OAAO,EAAE,MAAM,UAAU,KAAK,EAAE;AAAA,QAChC,YAAY,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,GAAG;AAAA,QAC9C,aAAa,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,UAAU,EAAE;AAAA;AAAA,QAE1D,WAAW,EAAE,MAAM,OAAO;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAe;AAAA;AAAA;AAAA,IAGb,4BAA4B;AAAA,MAC1B,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,aAAa,WAAW,iBAAiB;AAAA,MAC5D,SAAS,EAAE,MAAM,WAAW,SAAS,kBAAkB;AAAA,MACvD,QAAQ;AAAA,QACN,EAAE,MAAM,SAAS,OAAO,sBAAsB;AAAA,QAC9C,EAAE,MAAM,SAAS,OAAO,sBAAsB;AAAA,MAChD;AAAA,MACA,UAAU,CAAC;AAAA,MACX,QAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAAA,EAEA,KAAK;AAAA,IACH,wBAAwB;AAAA;AAAA;AAAA;AAAA,MAItB,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,cAAc,WAAW,YAAY;AAAA,MACxD,SAAS,EAAE,MAAM,WAAW,SAAS,wBAAwB;AAAA,MAC7D,QAAQ,CAAC;AAAA,MACT,UAAU,CAAC,QAAQ,OAAO;AAAA,MAC1B,QAAQ;AAAA,QACN,MAAM,EAAE,MAAM,UAAU,WAAW,0BAA0B;AAAA,QAC7D,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,eAAe,EAAE,MAAM,SAAS;AAAA,QAChC,WAAW,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QAC5C,kBAAkB,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QACnD,gBAAgB,EAAE,MAAM,OAAO;AAAA,QAC/B,MAAM,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,WAAc;AAAA,QACnD,mCAAmC,EAAE,MAAM,OAAO;AAAA,QAClD,0BAA0B,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,MAAM,KAAK,EAAE;AAAA,QACxE,mCAAmC,EAAE,MAAM,UAAU;AAAA,QACrD,iBAAiB,EAAE,MAAM,UAAU;AAAA,QACnC,eAAe,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,qBAAqB;AAAA,IACnB,yCAAyC;AAAA;AAAA;AAAA;AAAA,MAIvC,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,cAAc,WAAW,6BAA6B;AAAA,MACzE,SAAS,EAAE,MAAM,WAAW,SAAS,mCAAmC;AAAA,MACxE,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,sBAAsB,CAAC;AAAA,MACxD,UAAU,CAAC,OAAO;AAAA,MAClB,QAAQ;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,eAAe,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,QACjE,yBAAyB,EAAE,MAAM,UAAU;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO;AAAA,IACL,uBAAuB;AAAA,MACrB,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,cAAc,WAAW,wBAAwB;AAAA,MACpE,SAAS,EAAE,MAAM,WAAW,SAAS,2BAA2B;AAAA,MAChE,QAAQ,CAAC;AAAA,MACT,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,SAAS;AAAA,QACzB,kBAAkB,EAAE,MAAM,OAAO;AAAA,QACjC,iBAAiB,EAAE,MAAM,UAAU,KAAK,KAAM,KAAK,+BAA+B;AAAA,QAClF,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,oBAAoB,EAAE,MAAM,UAAU;AAAA,QACtC,4BAA4B,EAAE,MAAM,UAAU;AAAA,QAC9C,iBAAiB,EAAE,MAAM,UAAU;AAAA,QACnC,eAAe,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,MACnE;AAAA,IACF;AAAA,IACA,wCAAwC;AAAA,MACtC,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,cAAc,WAAW,wBAAwB;AAAA,MACpE,SAAS,EAAE,MAAM,WAAW,SAAS,2BAA2B;AAAA,MAChE,QAAQ,CAAC,EAAE,MAAM,SAAS,OAAO,sBAAsB,CAAC;AAAA,MACxD,UAAU,CAAC;AAAA,MACX,QAAQ;AAAA,QACN,aAAa,EAAE,MAAM,SAAS;AAAA,QAC9B,MAAM,EAAE,MAAM,OAAO;AAAA,QACrB,eAAe,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU;AAAA,IACR,wBAAwB;AAAA,MACtB,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,cAAc,WAAW,YAAY;AAAA,MACxD,SAAS,EAAE,MAAM,WAAW,SAAS,wBAAwB;AAAA,MAC7D,QAAQ,CAAC;AAAA,MACT,UAAU,CAAC,QAAQ;AAAA,MACnB,QAAQ;AAAA,QACN,QAAQ,EAAE,MAAM,OAAO;AAAA,QACvB,eAAe,EAAE,MAAM,SAAS;AAAA,QAChC,UAAU,EAAE,MAAM,OAAO;AAAA,QACzB,MAAM,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,WAAc;AAAA,QACnD,0BAA0B,EAAE,MAAM,UAAU,MAAM,CAAC,QAAQ,MAAM,KAAK,EAAE;AAAA,QACxE,iBAAiB,EAAE,MAAM,UAAU;AAAA,QACnC,eAAe,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc;AAAA,IACZ,sCAAsC;AAAA,MACpC,OAAO;AAAA,MACP,OAAO,EAAE,UAAU,cAAc,WAAW,0BAA0B;AAAA,MACtE,SAAS,EAAE,MAAM,WAAW,SAAS,kCAAkC;AAAA,MACvE,QAAQ,CAAC;AAAA,MACT,UAAU,CAAC,MAAM;AAAA,MACjB,QAAQ;AAAA,QACN,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,kBAAkB,EAAE,MAAM,UAAU,KAAK,KAAK,KAAK,GAAG;AAAA,QACtD,kBAAkB,EAAE,MAAM,UAAU,KAAK,GAAG,KAAK,EAAE;AAAA,QACnD,MAAM,EAAE,MAAM,UAAU;AAAA,QACxB,eAAe,EAAE,MAAM,UAAU,MAAM,0BAA0B;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACF;AAsBO,IAAM,gBAAkD;AAAA,EAC7D,oBAAoB;AAAA,EACpB,qCAAqC;AAAA,EACrC,mBAAmB;AAAA,EACnB,yCAAyC;AAAA,EACzC,qCAAqC;AAAA,EACrC,0BAA0B;AAC5B;AAaO,SAAS,iBAAiB,OAAuB;AAGtD,SAAO,OAAO,KAAK,aAAa,EAAE,SAAS,KAAK,IAAK,cAAc,KAAK,IAAe;AACzF;AAGO,SAAS,iBAAiB,WAA0C;AACzE,SAAO,CAAC,WAAW,GAAG,OAAO,KAAK,aAAa,EAAE,OAAO,CAAC,WAAW,cAAc,MAAM,MAAM,SAAS,CAAC;AAC1G;AAGA,SAAS,UAAU,MAAgB,OAAsC;AACvE,SAAO,eAAe,IAAI,IAAI,iBAAiB,KAAK,CAAC;AACvD;AAOA,IAAM,mBAAsC,CAAC,wBAAwB;AAY9D,SAAS,qBAAwD,MAAgB,QAAc;AACpG,QAAM,QAAQ,OAAO;AACrB,MAAI,OAAO,UAAU,YAAY,iBAAiB,KAAK,MAAM,MAAO,QAAO;AAC3E,QAAM,YAAY,iBAAiB,KAAK;AACxC,MAAI,CAAC,iBAAiB,SAAS,KAAK,EAAG,QAAO,EAAE,GAAG,QAAQ,OAAO,UAAU;AAC5E,QAAM,SAAkC,EAAE,GAAG,QAAQ,OAAO,UAAU;AACtE,MAAI,OAAO,OAAO,iBAAiB,UAAU;AAC3C,WAAO,eAAe,4BAA4B,MAAM,WAAW,OAAO,YAAY;AAAA,EACxF;AACA,MAAI,OAAO,OAAO,eAAe,UAAU;AACzC,WAAO,aAAa,cAAc,MAAM,WAAW,YAAY,IAC3D,0BAA0B,MAAM,WAAW,OAAO,UAAU,IAC5D;AAAA,EACN;AACA,MAAI,OAAO,OAAO,YAAY,UAAU;AACtC,WAAO,UAAU,qBAAqB,MAAM,WAAW,OAAO,OAAO;AAAA,EACvE;AACA,SAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAC7F;AAgFO,SAAS,iBAAiB,OAAgF;AAC/G,QAAM,UAAU,eAAe,eAAe,KAAK,GAAG;AACtD,SAAO,SAAS,SAAS,eAAe,UAAU;AACpD;AAgBO,IAAM,cAAc;AAAA;AAAA,EAEzB,SAAS,EAAE,MAAM,kBAAkB,OAAO,gCAAgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM1E,gBAAgB,EAAE,MAAM,yBAAyB,OAAO,4BAA4B;AAAA;AAAA,EAEpF,aAAa,EAAE,MAAM,sBAAsB,OAAO,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9E,YAAY,EAAE,MAAM,gBAAgB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzE,YAAY,EAAE,MAAM,kBAAkB,OAAO,8BAA8B;AAAA;AAAA,EAE3E,mBAAmB,EAAE,MAAM,iBAAiB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjF,aAAa,EAAE,MAAM,iBAAiB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3E,kBAAkB,EAAE,MAAM,iBAAiB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhF,aAAa,EAAE,MAAM,kBAAkB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO5E,eAAe,EAAE,MAAM,kBAAkB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9E,kBAAkB,EAAE,MAAM,kBAAkB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjF,WAAW,EAAE,MAAM,kBAAkB,OAAO,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1E,kBAAkB,EAAE,MAAM,qBAAqB,OAAO,8BAA8B;AAAA;AAAA,EAEpF,aAAa,EAAE,MAAM,iBAAiB,OAAO,8BAA8B;AAAA,EAC3E,WAAW,EAAE,MAAM,OAAO,OAAO,uBAAuB;AAAA,EACxD,aAAa,EAAE,MAAM,gBAAgB,OAAO,qCAAqC;AAAA,EACjF,UAAU,EAAE,MAAM,SAAS,OAAO,sBAAsB;AAAA;AAAA,EAExD,cAAc,EAAE,MAAM,uBAAuB,OAAO,wCAAwC;AAAA;AAAA,EAE5F,sBAAsB,EAAE,MAAM,kBAAkB,OAAO,yBAAyB;AAAA,EAChF,qBAAqB,EAAE,MAAM,kBAAkB,OAAO,iBAAiB;AAAA,EACvE,4BAA4B,EAAE,MAAM,kBAAkB,OAAO,sBAAsB;AAAA,EACnF,mBAAmB,EAAE,MAAM,kBAAkB,OAAO,yBAAyB;AAAA,EAC7E,cAAc,EAAE,MAAM,kBAAkB,OAAO,6BAA6B;AAAA,EAC5E,cAAc,EAAE,MAAM,kBAAkB,OAAO,6BAA6B;AAAA,EAC5E,aAAa,EAAE,MAAM,kBAAkB,OAAO,2BAA2B;AAC3E;AAIO,IAAM,iBAAiB,YAAY,QAAQ;AAC3C,IAAM,wBAAwB,YAAY,eAAe;AACzD,IAAM,qBAAqB,YAAY,YAAY;AACnD,IAAM,oBAAoB,YAAY,WAAW;AACjD,IAAM,oBAAoB,YAAY,WAAW;AACjD,IAAM,2BAA2B,YAAY,kBAAkB;AAC/D,IAAM,qBAAqB,YAAY,YAAY;AACnD,IAAM,0BAA0B,YAAY,iBAAiB;AAC7D,IAAM,qBAAqB,YAAY,YAAY;AACnD,IAAM,wBAAwB,YAAY,cAAc;AACxD,IAAM,2BAA2B,YAAY,iBAAiB;AAC9D,IAAM,mBAAmB,YAAY,UAAU;AAC/C,IAAM,0BAA0B,YAAY,iBAAiB;AAC7D,IAAM,qBAAqB,YAAY,YAAY;AACnD,IAAM,kBAAkB,YAAY,UAAU;AAC9C,IAAM,qBAAqB,YAAY,YAAY;AACnD,IAAM,kBAAkB,YAAY,SAAS;AAC7C,IAAM,sBAAsB,YAAY,aAAa;AAOrD,SAAS,kBAAkB,MAAgB,OAAwB;AACxE,SAAO,eAAe,IAAI,IAAI,iBAAiB,KAAK,CAAC,MAAM;AAC7D;AAOO,SAAS,4BAAsC;AACpD,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,SAAS,uBAAuB;AACzC,eAAW,SAAS,sBAAsB,kBAAkB,KAAK,KAAK,CAAC,EAAG,MAAK,IAAI,KAAK;AAAA,EAC1F;AACA,SAAO,CAAC,GAAG,IAAI;AACjB;AAqCO,SAAS,cAAc,MAAgB,OAAe,OAAwB;AACnF,SAAO,UAAU,MAAM,KAAK,GAAG,OAAO,KAAK,MAAM;AACnD;AAgBO,IAAM,0BAA0B;AA0BhC,IAAM,0BAA0B;AAsBvC,IAAM,cACJ,WAAC,oLAA8J,IAAE;AAQ5J,SAAS,cAAc,QAAoC;AAChE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,SAAS,CAAC,GAAG,OAAO,SAAS,WAAW,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE;AACtE,QAAM,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK;AACnC,SAAO,OAAO,KAAK,MAAM,KAAK,EAAE,OAAO,OAAO,EAAE,SAAS;AAC3D;AAGO,IAAM,yBAAyB;AAW/B,SAAS,oBAAoB,OAAe,WAA2B;AAC5E,QAAM,SAAS,eAAe,eAAe,KAAK,GAAG,OAAO;AAC5D,QAAM,UAAU,QAAQ,SAAS,WAAW,OAAO,OAAO;AAC1D,MAAI,CAAC,SAAS,UAAU,QAAQ,SAAS,SAAS,EAAG,QAAO;AAC5D,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,IAAI,IAAI,SAAS,IAAI,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI,CAAC,EAAE,CAAC;AAClG;AAWA,IAAM,sBAA2C,oBAAI,IAAI;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAMM,SAAS,cAAc,OAA8B;AAC1D,MAAI,cAAc,kBAAkB,OAAO,gBAAgB,EAAG,QAAO;AACrE,SAAO,oBAAoB,IAAI,KAAK,IAAI,UAAU;AACpD;AAGO,SAAS,iBAAiB,OAAqC;AACpE,QAAM,SAAS,eAAe,eAAe,KAAK,GAAG,OAAO;AAC5D,QAAM,UAAU,QAAQ,SAAS,WAAW,OAAO,OAAO;AAC1D,SAAO,SAAS,SAAS,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,IAAI;AAChE;AAGO,SAAS,eAAe,OAAmC;AAChE,QAAM,UAAU,iBAAiB,KAAK;AACtC,SAAO,UAAW,QAAQ,QAAQ,SAAS,CAAC,IAAe;AAC7D;AAoBO,SAAS,eAAe,OAAe,OAAmC;AAC/E,QAAM,aAAa,eAAe,KAAK;AACvC,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,UAAU,KAAK,MAAM,aAAa,uBAAuB;AAC/D,MAAI,SAAS,QAAS,QAAO;AAC7B,QAAM,QAAQ,KAAK,KAAK,QAAQ,OAAO;AACvC,SAAO,EAAE,OAAO,cAAc,KAAK,KAAK,QAAQ,KAAK,GAAG,WAAW;AACrE;AAEO,SAAS,gBAAgB,MAAgB,OAAmC;AACjF,QAAM,SAAS,UAAU,MAAM,KAAK,GAAG,OAAO;AAC9C,SAAO,QAAQ,SAAS,WAAW,OAAO,YAAY;AACxD;AAcA,SAAS,UAAU,MAAgB,OAAe,WAA6C;AAC7F,QAAM,OAAO,UAAU,MAAM,KAAK;AAClC,SACE,MAAM,iBAAiB,KAAK,CAAC,UAAU,MAAM,SAAS,SAAS,KAC/D,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,SAAS,SAAS;AAEzD;AAGO,SAAS,aAAa,MAAgB,OAAe,WAA0C;AACpG,SAAO,UAAU,MAAM,OAAO,SAAS,GAAG;AAC5C;AAMO,SAAS,mBAAmB,MAAgB,OAAmC;AACpF,SAAO,aAAa,MAAM,OAAO,OAAO;AAC1C;AA0BO,SAAS,mBAAmB,MAAgB,OAA8C;AAC/F,QAAM,SAAS,UAAU,MAAM,KAAK,GAAG,OAAO;AAC9C,SAAO,QAAQ,SAAS,WAAW,OAAO,OAAO;AACnD;AAWO,SAAS,qBAAqB,MAAgB,OAAe,MAAkC;AACpG,QAAM,YAAY,mBAAmB,MAAM,KAAK;AAChD,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI,UAAU,SAAS,IAAI,EAAG,QAAO;AAErC,QAAM,SAAS,UAAU,OAAO,CAAC,SAAS,SAAS,MAAM;AACzD,QAAM,UAAU,OAAO,QAAQ,IAAI;AACnC,QAAM,YAAY,YAAY,KAAK,SAAS,OAAO,MAAM,GAAG,OAAO;AACnE,SAAO,UAAU,UAAU,SAAS,CAAC;AACvC;AAGO,SAAS,sBAAsB,MAAgB,OAA8C;AAClG,QAAM,SAAS,UAAU,MAAM,KAAK,GAAG,OAAO;AAC9C,SAAO,QAAQ,SAAS,WAAW,OAAO,OAAO;AACnD;AAEA,SAAS,WAAW,OAA8B;AAChD,QAAM,CAAC,GAAG,CAAC,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI,MAAM;AAC1C,MAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO;AACnE,SAAO,IAAI;AACb;AAQO,SAAS,4BAA4B,MAAgB,OAAe,QAAwB;AACjG,QAAM,YAAY,sBAAsB,MAAM,KAAK;AACnD,MAAI,CAAC,aAAa,UAAU,SAAS,MAAM,EAAG,QAAO;AACrD,QAAM,SAAS,WAAW,MAAM;AAChC,MAAI,WAAW,KAAM,QAAO;AAC5B,MAAI,OAAO;AACX,MAAI,eAAe,OAAO;AAC1B,aAAW,aAAa,WAAW;AACjC,UAAM,QAAQ,WAAW,SAAS;AAClC,QAAI,UAAU,KAAM;AACpB,UAAM,WAAW,KAAK,IAAI,KAAK,IAAI,QAAQ,MAAM,CAAC;AAClD,QAAI,WAAW,cAAc;AAC3B,qBAAe;AACf,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,oBAAoB,MAAgB,OAA8C;AACzF,QAAM,SAAS,UAAU,MAAM,KAAK,GAAG,OAAO;AAC9C,SAAO,QAAQ,SAAS,WAAW,OAAO,OAAO;AACnD;AAEA,IAAM,mBAAmB,CAAC,QAAQ,MAAM,MAAM,IAAI;AAc3C,SAAS,0BAA0B,MAAgB,OAAe,QAAwB;AAC/F,QAAM,YAAY,oBAAoB,MAAM,KAAK;AACjD,MAAI,CAAC,aAAa,UAAU,SAAS,MAAM,EAAG,QAAO;AACrD,QAAM,SAAS,iBAAiB,QAAQ,MAAM;AAC9C,MAAI,SAAS,EAAG,QAAO;AACvB,QAAM,SAAS,UACZ,OAAO,CAAC,MAAM,iBAAiB,SAAS,CAAC,CAAC,EAC1C,KAAK,CAAC,GAAG,MAAM,iBAAiB,QAAQ,CAAC,IAAI,iBAAiB,QAAQ,CAAC,CAAC;AAC3E,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,QAAM,eAAe,OAAO,OAAO,CAAC,MAAM,iBAAiB,QAAQ,CAAC,KAAK,MAAM;AAC/E,SAAO,aAAa,SAAS,IAAK,aAAa,aAAa,SAAS,CAAC,IAAgB,OAAO,CAAC;AAChG;;;ACp5EO,IAAM,kBAAkB;AAaxB,SAAS,aAAa,KAAqB;AAChD,MAAI,EAAE,MAAM,GAAI,QAAO;AACvB,SAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,QAAQ,CAAC,CAAC,CAAC;AAC7D;;;ACEO,IAAM,wBAAwB,aAAa,IAAI;AAM/C,IAAM,0BAA4D;AAAA,EACvE,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AACR;AAGO,IAAM,2BAA2B;AAGjC,IAAM,2BAA2B;AAEjC,SAAS,gBAAgB,OAAwB;AACtD,SAAO,MAAM,WAAW,oBAAoB;AAC9C;AAgCO,IAAM,6BAA+D;AAAA,EAC1E,QAAQ;AAAA,EACR,QAAQ;AACV;AAGA,IAAM,sCAAsC;AAErC,SAAS,uBAAuB,YAAwC;AAC7E,SAAO,2BAA2B,cAAc,wBAAwB,KAAK;AAC/E;AAGA,IAAM,0BAA0B;AAMhC,SAAS,cAAc,OAAe,UAA0B;AAC9D,QAAM,QAAQ,iBAAiB,KAAK,GAAG;AACvC,SAAO,UAAU,SAAY,WAAW,KAAK,IAAI,UAAU,KAAK;AAClE;AAEO,SAAS,qBAAqB,YAAwC;AAC3E,SAAO,wBAAwB,cAAc,wBAAwB,KAAK;AAC5E;AAiCO,IAAM,sCAAsC;AAE5C,IAAM,sCAAsC;AAU5C,IAAM,oCAAsE;AAAA,EACjF,QAAQ,IAAI;AAAA,EACZ,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AACR;AAGO,IAAM,iCAAiC;AAgBvC,IAAM,8BAA8B;AAOpC,IAAM,6BAA6B;AAQnC,IAAM,6BACV,sCAAsC,sCAAuC;AAGzE,SAAS,uBAAuB,YAAwC;AAC7E,QAAM,aAAa,kCAAkC,cAAc,8BAA8B,KAAK;AACtG,SAAO,6BAA6B;AACtC;AAcO,IAAM,+BAA+B;AAiBrC,IAAM,iCAAiC;AAkBvC,IAAM,gCAAgC;AAG7C,IAAM,yBAAsF;AAAA,EAC1F,QAAQ,EAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,EAClC,QAAQ,EAAE,OAAO,MAAM,QAAQ,IAAI;AACrC;AASO,SAAS,wBAAwB,YAAgC,qBAAqB,OAAe;AAC1G,QAAM,QAAQ,uBAAuB,cAAc,wBAAwB,KAAK,uBAAuB,MAAM;AAC7G,QAAM,mBAAoB,OAAO,SAAS,SAAS,OAAO,UAAU,OAAO,KAAM;AACjF,QAAM,OAAQ,kBAAkB,iCAAkC;AAClE,SAAO,qBAAqB,OAAO,gCAAgC;AACrE;AAiCA,SAAS,kBAAkB,OAAe,UAA8B,YAAwC;AAC9G,QAAM,OAAO,yBAAyB,KAAK,IAAI,iCAAiC;AAChF,QAAM,UAAU,uBAAuB,IAAI,KAAK,YAAY;AAC5D,SAAO,UAAW,8BAA8B,sCAAuC;AACzF;AASA,SAAS,kBAAkB,YAAgC,SAAiB,eAAgC;AAC1G,QAAM,eAAe,qBAAqB,UAAU,IAAI;AACxD,MAAI,CAAC,cAAe,QAAO;AAC3B,QAAM,UAAU,eAAe,UAAU,eAAe,SAAS,aAAa;AAC9E,SAAO,KAAK,IAAI,cAAc,wBAAwB,OAAO,IAAI,OAAO;AAC1E;AAWO,SAAS,qBAAqB,OAA+B;AAClE,QAAM,EAAE,OAAO,UAAU,YAAY,eAAe,mBAAmB,IAAI;AAC3E,QAAM,UAAU,cAAc,OAAO,YAAY,wBAAwB;AACzE,QAAM,oBAAoB,qBAAqB,+BAA+B;AAM9E,MAAI,kBAAkB,KAAK,EAAG,QAAO,kBAAkB,OAAO,UAAU,UAAU;AAGlF,MAAI,kBAAkB,KAAK,GAAG;AAC5B,UAAM,gBAAgB,uBAAuB,UAAU,IAAI,UAAU;AACrE,QAAI,CAAC,MAAM,cAAe,QAAO;AAMjC,WAAO,KAAK,IAAI,eAAe,wBAAwB,YAAY,kBAAkB,IAAI,OAAO;AAAA,EAClG;AACA,MAAI,gBAAgB,KAAK,EAAG,QAAO,kBAAkB,YAAY,SAAS,MAAM,kBAAkB,IAAI;AAGtG,QAAM,YAAY,iBAAiB,KAAK,GAAG;AAC3C,MAAI,WAAW;AACb,UAAM,QAAQ,aAAa,UAAU,eAAe,UAAU,IAAI,WAAc;AAChF,YAAQ,gBAAgB,KAAK,QAAQ,KAAK,UAAU;AAAA,EACtD;AAIA,QAAM,mBAAmB,KAAK,IAAI,GAAG,OAAO,OAAO,uBAAuB,CAAC;AAC3E,SAAO,mBAAmB;AAC5B;AAGO,SAAS,qBAAqB,OAA+B;AAClE,SAAO,aAAa,qBAAqB,KAAK,CAAC;AACjD;;;AChXA,eAAsB;AAEf,IAAM,YAAY,SAAAC,QAAU;AAGnC,IAAO,kBAAQ,SAAAC;;;ACSR,SAAS,aAAa,OAAwB;AACnD,QAAM,aAAa,sBAAsB,KAAK;AAC9C,QAAM,MAAM,gBAAgB,UAAU;AACtC,MAAI,QAAQ,QAAW;AACrB,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,OAAyB;AACtD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,UAAU,KAAK;AAC3D,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,OAAO,SAAS,KAAK,GAAG;AAC3B,YAAM,IAAI,MAAM,mCAAmC,KAAK,EAAE;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAW,QAAO;AACvC,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,qBAAqB;AAAA,EACxC;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC1C,UAAI,MAAM,OAAW;AACrB,UAAI,EAAE,UAAU,KAAK,CAAC,IAAI,sBAAsB,CAAC;AAAA,IACnD;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;AChCA,IAAM,qBAAqB;AAG3B,IAAM,oBAAsD;AAAA,EAC1D,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AACR;AAaO,IAAM,qBAAqB;AAG3B,SAAS,eAAe,iBAAyB,YAAwC;AAC9F,QAAM,SAAS,kBAAkB,cAAc,MAAM,KAAK;AAC1D,SAAO,kBAAkB,qBAAqB;AAChD;AAGO,SAAS,qBACd,iBACA,YACe;AACf,MAAI,CAAC,gBAAiB,QAAO;AAC7B,QAAM,KAAK,eAAe,iBAAiB,UAAU;AACrD,MAAI,MAAM,mBAAoB,QAAO;AACrC,QAAM,OAAO,KAAK,MAAM,sBAAsB,eAAe,GAAG,UAAU,KAAK,EAAE;AACjF,SAAO,KAAK,eAAe,aAAa,cAAc,MAAM,qBAAqB,KAAK,MAAM,EAAE,CAAC,sBAAsB,kBAAkB,mHAA8G,IAAI;AAC3P;;;AC9CO,SAAS,sBACd,OAAqF,CAAC,GAC9E;AACR,SACE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAYC,KAAK,iBAAiB,YACnB,KACA;AAAA;AAAA;AAAA,EAKJ;AAAA;AAAA;AAAA,GAQC,KAAK,OACF,4BAA4B,KAAK,IAAI,wEACrC,OACH,KAAK,WAAW,+CAA+C,KAAK,QAAQ,MAAM;AAEvF;;;ACXO,IAAM,+BAA+B;AAOrC,IAAM,kCAAkC;AAGxC,IAAM,yCAAyC;AAG/C,IAAM,gCAAgC,MAAO;AAO7C,IAAM,4BAA4B;AAMlC,IAAM,kDAAkD;AACxD,IAAM,+CAA+C;AAGrD,IAAM,qCAAqC;AAG3C,IAAM,6BAA6B;AACnC,IAAM,+BAA+B;AAGrC,IAAM,iCAAiC;AAGvC,IAAM,4BAA4B;AA6BlC,IAAM,wBAAwB;AAE9B,IAAM,+BAA+B;AAErC,IAAM,oCAAoC;AAEjD,IAAM,wBAAwB;AAMvB,SAAS,iBAAiB,YAA4B;AAC3D,SAAO,aAAa;AACtB;AAEO,SAAS,gBAAgB,SAAyB;AACvD,SAAO,UAAU;AACnB;AAEO,SAAS,sBAAsB,SAAyB;AAC7D,SAAO,UAAU;AACnB;AAGO,SAAS,oBAAoB,YAA4B;AAC9D,SAAO,KAAK,IAAI,aAAa,KAAQ,GAAG;AAC1C;AAEO,SAAS,gBAAgB,SAAyB;AACvD,SAAO,UAAU;AACnB;AAOO,SAAS,eAAe,SAA6B,SAAqC;AAC/F,QAAM,aAAa,KAAK,IAAI,WAAW,GAAG,WAAW,CAAC;AACtD,SAAO,aAAa,IAAI,aAAa,MAAS;AAChD;AAEO,SAAS,WAAW,SAAyB;AAClD,SAAO,UAAU;AACnB;AAGO,SAAS,uBAAuB,iBAA6C;AAClF,SAAO,KAAK,IAAI,IAAI,KAAK,MAAM,mBAAmB,qCAAqC,EAAE,CAAC;AAC5F;AAEO,SAAS,yBAAyB,iBAAqC,gBAAiC;AAC7G,QAAM,OAAO,iBACT,kDACA;AACJ,SAAQ,uBAAuB,eAAe,IAAI,KAAM;AAC1D;AAGO,SAAS,iBAAiB,aAAkC,SAAyB;AAC1F,MAAI,WAAW,EAAG,QAAO;AACzB,MAAI,gBAAgB,WAAY,QAAQ,UAAU,KAAM;AACxD,SAAQ,KAAK,IAAI,SAAS,4BAA4B,IAAI,OAAQ;AACpE;AAqBA,SAAS,MAAM,OAAqB;AAClC,SAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAgB,CAAC;AACzF;AAEA,SAAS,IAAI,OAAoC;AAC/C,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAGA,SAAS,gBAAgB,QAAa,MAAkC;AACtE,QAAM,MAAM,MAAM,OAAO,IAAI,CAAC;AAC9B,SAAO,IAAI,IAAI,WAAW,KAAK,IAAI,MAAM,IAAI,QAAQ,EAAE,WAAW;AACpE;AAEA,SAAS,UAAU,QAAa,MAAsB;AACpD,QAAM,QAAQ,OAAO,IAAI;AACzB,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM;AACvC,SAAO,QAAQ,IAAI;AACrB;AAEA,SAAS,WAAW,OAAwB;AAC1C,SAAO,OAAO,UAAU,WAAW,MAAM,SAAS;AACpD;AAEA,SAAS,yBAAyB,QAAa,QAAa,WAAmC;AAC7F,QAAM,QAAQ,OAAO;AACrB,MAAI,OAAO,UAAU,SAAU,QAAO;AAItC,QAAM,gBAAgB,UAAU,QAAQ,YAAY,IAAI,KAAK,CAAC,OAAO;AACrE,SAAO,qBAAqB;AAAA,IAC1B;AAAA,IACA,UAAU,IAAI,OAAO,QAAQ;AAAA,IAC7B,YAAY,OAAO,OAAO,eAAe,WAAW,OAAO,aAAa;AAAA,IACxE,eAAe,OAAO,OAAO,mBAAmB,YAAY,OAAO,iBAAiB;AAAA,IACpF,oBAAoB,UAAU,QAAQ,kBAAkB,IAAI;AAAA,IAC5D,eAAe,gBAAgB,KAAK,MAAM,aAAa;AAAA,EACzD,CAAC;AACH;AAEA,SAAS,iBAAiB,QAAa,QAAqB;AAC1D,QAAM,WAAW,IAAI,OAAO,eAAe;AAC3C,QAAM,WACJ,OAAO,UAAU,yCAAyC,gBAAgB,QAAQ,OAAO,IAAI;AAC/F,QAAM,WAAW,YAAY,YAAY,wBAAwB,OAAQ;AACzE,SAAO,gBAAgB,OAAO;AAChC;AAEA,SAAS,oBAAoB,QAA4B;AACvD,MAAI,CAAC,MAAM,QAAQ,OAAO,MAAM,EAAG,QAAO;AAC1C,QAAM,aAAa,OAAO,OAAO,OAAe,CAAC,KAAK,SAAS,MAAM,WAAW,MAAM,IAAI,EAAE,IAAI,GAAG,CAAC;AACpG,SAAO,iBAAiB,UAAU;AACpC;AAMO,SAAS,oBAAoB,OAAqC;AACvE,QAAM,SAAS,MAAM,MAAM,MAAM;AACjC,QAAM,SAAS,MAAM,MAAM,MAAM;AACjC,UAAQ,MAAM,UAAU;AAAA,IACtB,KAAK;AACH,aAAO,yBAAyB,QAAQ,QAAQ,MAAM,cAAc,IAAI;AAAA,IAC1E,KAAK;AACH,aAAO,OAAO,OAAO,SAAS,WAAW,iBAAiB,OAAO,KAAK,MAAM,IAAI;AAAA,IAClF,KAAK;AACH,aAAO,oBAAoB,MAAM;AAAA,IACnC,KAAK;AACH,aAAO,iBAAiB,QAAQ,MAAM;AAAA,IACxC,KAAK;AACH,aAAO,sBAAsB,IAAI,OAAO,gBAAgB,KAAK,4BAA4B;AAAA,IAC3F,KAAK,uBAAuB;AAC1B,YAAM,KAAK,gBAAgB,QAAQ,OAAO,KAAK,wBAAwB;AACvE,aAAO,gBAAgB,oBAAoB,EAAE,CAAC;AAAA,IAChD;AAAA,IACA,KAAK;AACH,aAAO,WAAW,eAAe,gBAAgB,QAAQ,OAAO,GAAG,gBAAgB,QAAQ,OAAO,CAAC,CAAC;AAAA,IACtG,KAAK,2BAA2B;AAC9B,YAAM,KAAK,gBAAgB,QAAQ,OAAO;AAC1C,aAAO,yBAAyB,OAAO,SAAY,SAAY,KAAK,KAAM,OAAO,oBAAoB,KAAK;AAAA,IAC5G;AAAA,IACA,KAAK;AACH,aAAO;AAAA,IACT,KAAK,oBAAoB;AACvB,YAAM,KAAK,gBAAgB,QAAQ,OAAO,KAAK,wBAAwB;AACvE,aAAO,iBAAiB,OAAO,gBAAgB,aAAa,aAAa,QAAQ,KAAK,GAAI;AAAA,IAC5F;AAAA,IACA,KAAK;AACH,aAAO,OAAO,aAAa,cAAc,4BAA4B;AAAA,IACvE,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAGO,SAAS,oBAAoB,OAAqC;AACvE,QAAM,MAAM,oBAAoB,KAAK;AACrC,SAAO,QAAQ,OAAO,OAAO,aAAa,GAAG;AAC/C;;;ACzRO,IAAM,eACX;AAEK,IAAM,YACX;AAEF,IAAM,cACJ;AAGK,SAAS,2BAA2B,GAAqE;AAC9G,SAAO;AAAA,IACL,mEAAmE,EAAE,OAAO;AAAA,IAC5E,EAAE,UAAU,KAAK,IAAI,YAAY,EAAE,SAAS,KAAK,CAAC,KAAK;AAAA,IACvD,UAAU,EAAE,SAAS,KAAK,KAAK,uDAAuD;AAAA,IACtF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EACG,OAAO,CAAC,SAAyB,SAAS,IAAI,EAC9C,KAAK,IAAI;AACd;;;ACVA,SAAS,kBAAkB,UAAwC;AACjE,SAAO,OAAO,KAAK,cAAc,EAAE,SAAS,QAAQ;AACtD;AAYA,SAAS,oBACP,MACA,QACA,OACwB;AACxB,QAAM,SAAiC,CAAC;AACxC,aAAW,OAAO,KAAK,UAAU;AAC/B,QAAI,OAAO,GAAG,MAAM,UAAa,OAAO,GAAG,MAAM,MAAM;AACrD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS,2BAA2B,GAAG,gBAAgB,KAAK;AAAA,MAC9D,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBACP,MACA,QACA,OACwB;AACxB,QAAM,SAAiC,CAAC;AACxC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,QAAQ,QAAS;AACrB,QAAI,UAAU,OAAW;AACzB,UAAM,SAAS,KAAK,OAAO,GAAG;AAC9B,QAAI,CAAC,QAAQ;AACX,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS,UAAU,GAAG,gCAAgC,KAAK;AAAA,MAC7D,CAAC;AACD;AAAA,IACF;AACA,UAAM,WAAW,cAAc,KAAK,OAAO,QAAQ,KAAK;AACxD,QAAI,SAAU,QAAO,KAAK,QAAQ;AAAA,EACpC;AACA,SAAO;AACT;AAEO,SAAS,oBACd,UACA,OACA,QACuB;AAGvB,QAAM,OAAO,eAAe,QAAQ,EAAE,iBAAiB,KAAK,CAAC;AAC7D,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ,CAAC,EAAE,MAAM,iBAAiB,SAAS,kBAAkB,KAAK,eAAe,QAAQ,IAAI,CAAC;AAAA,IAChG;AAAA,EACF;AAEA,QAAM,SAAS,qBAAqB,UAAU,EAAE,GAAG,QAAQ,MAAM,CAAC;AAClE,QAAM,SAAS,CAAC,GAAG,oBAAoB,MAAM,QAAQ,KAAK,GAAG,GAAG,iBAAiB,MAAM,QAAQ,KAAK,CAAC;AACrG,MAAI,OAAO,SAAS,EAAG,QAAO,EAAE,IAAI,OAAO,OAAO;AAKlD,MAAI,aAAa,kBAAkB;AACjC,UAAM,WAAW;AAAA,MACf,OAAO,OAAO,aAAa,WAAW,OAAO,WAAW;AAAA,MACxD,OAAO,OAAO,eAAe,WAAW,OAAO,aAAa;AAAA,IAC9D;AACA,QAAI,SAAU,QAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,EAAE,MAAM,kBAAkB,SAAS,SAAS,CAAC,EAAE;AAAA,EAC5F;AACA,SAAO,EAAE,IAAI,KAAK;AACpB;AAQO,SAAS,oBACd,UACA,OACA,eACuB;AACvB,QAAM,OAAO,eAAe,QAAQ,EAAE,iBAAiB,KAAK,CAAC;AAC7D,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ,CAAC,EAAE,MAAM,iBAAiB,SAAS,kBAAkB,KAAK,eAAe,QAAQ,IAAI,CAAC;AAAA,IAChG;AAAA,EACF;AACA,QAAM,OAAO,IAAI,IAAI,aAAa;AAClC,QAAM,SAAiC,CAAC;AACxC,aAAW,aAAa,KAAK,QAAQ;AACnC,QAAI,CAAC,KAAK,IAAI,UAAU,IAAI,GAAG;AAC7B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,UAAU;AAAA,QACjB,SAAS,UAAU,KAAK,6BAA6B,UAAU,IAAI;AAAA,MACrE,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,OAAO,SAAS,EAAG,QAAO,EAAE,IAAI,OAAO,OAAO;AAClD,SAAO,EAAE,IAAI,KAAK;AACpB;AAEA,SAAS,oBACP,KACA,OACA,QACA,OAC6B;AAC7B,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,EAAE,MAAM,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG,0BAA0B,OAAO,KAAK,GAAG;AAAA,EACtG;AACA,MAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,SAAS,KAAK,GAAG;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,GAAG,GAAG,MAAM,KAAK,qBAAqB,KAAK,eAAe,OAAO,KAAK,KAAK,IAAI,CAAC;AAAA,IAC3F;AAAA,EACF;AACA,MAAI,OAAO,cAAc,UAAa,MAAM,SAAS,OAAO,WAAW;AACrE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,GAAG,GAAG,KAAK,MAAM,MAAM,2BAA2B,OAAO,SAAS,SAAS,KAAK;AAAA,IAC3F;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBACP,KACA,OACA,QACA,OAC6B;AAC7B,MAAI,OAAO,UAAU,YAAY,OAAO,MAAM,KAAK,GAAG;AACpD,WAAO,EAAE,MAAM,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG,0BAA0B,OAAO,KAAK,GAAG;AAAA,EACtG;AACA,MAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,SAAS,KAAK,GAAG;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,SAAS,GAAG,GAAG,KAAK,KAAK,oBAAoB,KAAK,eAAe,OAAO,KAAK,KAAK,IAAI,CAAC;AAAA,IACzF;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,CAAC,OAAO,UAAU,KAAK,GAAG;AAC9C,WAAO,EAAE,MAAM,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG,KAAK,KAAK,0BAA0B;AAAA,EACjG;AACA,MAAI,OAAO,QAAQ,UAAa,QAAQ,OAAO,KAAK;AAClD,WAAO,EAAE,MAAM,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG,KAAK,KAAK,cAAc,OAAO,GAAG,GAAG;AAAA,EAClG;AACA,MAAI,OAAO,QAAQ,UAAa,QAAQ,OAAO,KAAK;AAClD,WAAO,EAAE,MAAM,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG,KAAK,KAAK,cAAc,OAAO,GAAG,GAAG;AAAA,EAClG;AACA,SAAO;AACT;AAEA,SAAS,cAAc,KAAa,OAAgB,QAAqB,OAA4C;AACnH,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,oBAAoB,KAAK,OAAO,QAAQ,KAAK;AAAA,IACtD,KAAK;AACH,aAAO,oBAAoB,KAAK,OAAO,QAAQ,KAAK;AAAA,IACtD,KAAK;AACH,UAAI,OAAO,UAAU,WAAW;AAC9B,eAAO,EAAE,MAAM,iBAAiB,OAAO,KAAK,SAAS,GAAG,GAAG,2BAA2B,OAAO,KAAK,GAAG;AAAA,MACvG;AACA,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,SAAS;AACP,YAAM,cAAqB;AAC3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC/NA,SAAS,SAAS;AAmBlB,IAAM,mBAAmB,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS;AAE5E,IAAM,8BAA8B,EACxC,OAAO;AAAA,EACN,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE1B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvC,WAAW,EAAE,QAAQ,EAAE,SAAS;AAClC,CAAC,EACA,MAAM;AAET,IAAM,YAAY,EACf,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,qBAAqB,EAAE,OAAO,EAAE,SAAS;AAAA,EACzC,aAAa,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC,EACA,MAAM;AAKF,IAAM,0BAA0B,EACpC,OAAO;AAAA;AAAA,EAEN,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE3B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,cAAc,EAAE,QAAQ,EAAE,SAAS;AAAA;AAAA,EAEnC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAIhC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,SAAS;AAAA,EAC/C,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,eAAe,EAAE,OAAO,EAAE,SAAS;AACrC,CAAC,EACA,MAAM;AAEF,IAAM,yBAAyB,EACnC,OAAO;AAAA;AAAA,EAEN,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE5B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,SAAS,EAAE,MAAM,uBAAuB,EAAE,SAAS;AACrD,CAAC,EACA,MAAM;AAET,IAAM,qBAAqB,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,GAAG,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM;AAC9G,IAAM,uBAAuB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM;AAYtE,IAAM,oBAAoB,CAAC,YAAY;AAGvC,IAAM,mBAAmB,EAC7B,OAAO;AAAA,EACN,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,OAAO,EAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAInC,aAAa,uBAAuB,SAAS;AAAA;AAAA;AAAA;AAAA,EAI7C,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA,EAGhC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,eAAe,mBAAmB,SAAS;AAAA,EAC3C,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAAA,EACxC,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACtC,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA,EAGnC,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAEpC,YAAY,EAAE,KAAK,iBAAiB,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAK/C,eAAe,EACZ,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,GAAG,qBAAqB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EACtF,MAAM,EACN,SAAS;AAAA;AAAA,EAEZ,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKnC,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS;AAAA,EAC/G,UAAU,EAAE,MAAM,2BAA2B,EAAE,SAAS;AAAA,EACxD,KAAK,EAAE,MAAM,SAAS,EAAE,SAAS;AAAA;AAAA;AAAA,EAGjC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACxC,mBAAmB,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKjD,cAAc,EAAE,KAAK,CAAC,UAAU,UAAU,SAAS,CAAC,EAAE,SAAS;AAAA,EAC/D,kBAAkB,EAAE,MAAM,oBAAoB,EAAE,SAAS;AAAA,EACzD,mBAAmB;AAAA,EACnB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKjB,oBAAoB,EAAE,QAAQ,EAAE,SAAS;AAC3C,CAAC,EACA,MAAM;AAEF,IAAM,uBAAuB,EACjC,OAAO;AAAA,EACN,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,GAAG,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS;AAAA,EAC9G,QAAQ,EACL,OAAO;AAAA,IACN,OAAO,EACJ,OAAO;AAAA,MACN,SAAS,EAAE,QAAQ,EAAE,SAAS;AAAA,MAC9B,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,MAIlC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA,MAGjC,kBAAkB,EACf,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,GAAG,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EACtE,MAAM,EACN,QAAQ;AAAA,IACb,CAAC,EACA,MAAM,EACN,SAAS;AAAA,IACZ,MAAM,EACH;AAAA,MACC,EACG,OAAO;AAAA,QACN,IAAI,EAAE,OAAO,EAAE,SAAS;AAAA,QACxB,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA,QAGjC,0BAA0B,EAAE,OAAO,EAAE,SAAS;AAAA,MAChD,CAAC,EACA,MAAM;AAAA,IACX,EACC,SAAS;AAAA,IACZ,WAAW,EACR,OAAO;AAAA;AAAA;AAAA,MAGN,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,MAK1B,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,MAC5B,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA,MACvC,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,CAAC,EACA,MAAM,EACN,SAAS;AAAA;AAAA;AAAA,IAGZ,OAAO,EACJ,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EACxF,MAAM,EACN,SAAS;AAAA;AAAA;AAAA,IAGZ,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,IAChC,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,IAC5B,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,GAAG,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS;AAAA,EACzG,CAAC,EACA,MAAM,EACN,SAAS;AAAA;AAAA,EAEZ,sBAAsB,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1C,QAAQ,EAAE,MAAM,gBAAgB,EAAE,IAAI,CAAC;AACzC,CAAC,EACA,MAAM;AAET,IAAM,qBAAqB,EACxB,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,GAAG,YAAY,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAC3G,MAAM;AAGF,IAAM,yBAAyB,EACnC,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACtC,OAAO,mBAAmB,SAAS;AACrC,CAAC,EACA,MAAM;AAGF,IAAM,iCAAiC,EAC3C,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,YAAY,EAAE,OAAO,EAAE,QAAQ;AAAA,EAC/B,oBAAoB,EAAE,OAAO,EAAE,SAAS;AAAA,EACxC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,UAAU,EAAE,OAAO,EAAE,SAAS;AAChC,CAAC,EACA,MAAM;","names":["configure","value","tmp","key","res","join","stringify","size","cjsModule","cjsModule"]}
|