@koda-sl/baker-cli 0.545.0 → 0.546.0-dev.a72c87f73

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.
Files changed (859) hide show
  1. package/dist/account-IG3U6UXZ.js +82 -0
  2. package/dist/account-IGWCS2VJ.js +82 -0
  3. package/dist/account-reads-LOCJMS35.js +219 -0
  4. package/dist/account-users-H4VP43RZ.js +64 -0
  5. package/dist/account-writes-BSSKSTZ2.js +68 -0
  6. package/dist/accounts-C4PNBT5X.js +701 -0
  7. package/dist/accounts-GPTG4XW5.js +80 -0
  8. package/dist/actions-F7YO5I27.js +55 -0
  9. package/dist/activecampaign-S4E46SA6.js +938 -0
  10. package/dist/ad-group-writes-KMB3OMJG.js +172 -0
  11. package/dist/ad-groups-E67CNQS4.js +70 -0
  12. package/dist/ad-writes-FNMKNFUN.js +176 -0
  13. package/dist/add-LROKBWW4.js +107 -0
  14. package/dist/add-SG5XWFRN.js +305 -0
  15. package/dist/ads-4LASBP4G.js +79 -0
  16. package/dist/ads-7ICT2D4M.js +48 -0
  17. package/dist/advertisers-IQMTOR4D.js +123 -0
  18. package/dist/analytics-6DSJ6WHO.js +2437 -0
  19. package/dist/analytics-D6S5LW2F.js +447 -0
  20. package/dist/animate-OWXAT2RK.js +480 -0
  21. package/dist/assign-TMG6FDLW.js +80 -0
  22. package/dist/audience-size-KPJOSG5W.js +76 -0
  23. package/dist/audiences-3R574STZ.js +280 -0
  24. package/dist/audit-35TDKIGY.js +154 -0
  25. package/dist/autocomplete-T63KPKRZ.js +114 -0
  26. package/dist/avatars-AVK4S3HS.js +38 -0
  27. package/dist/bid-pricing-O5IK37CL.js +103 -0
  28. package/dist/brand-SG6VOHF4.js +22 -0
  29. package/dist/brief-RWA6MXTN.js +543 -0
  30. package/dist/campaign-groups-SSZISPJ5.js +99 -0
  31. package/dist/campaign-writes-74KDZ7RR.js +168 -0
  32. package/dist/campaign-writes-Z2J24SUZ.js +176 -0
  33. package/dist/campaigns-43OS6EUG.js +78 -0
  34. package/dist/campaigns-B5TSL3UD.js +113 -0
  35. package/dist/campaigns-TFNPOQEW.js +111 -0
  36. package/dist/canvas-4LSM4Y5I.js +46 -0
  37. package/dist/capabilities-CTKSS7AI.js +147 -0
  38. package/dist/catalog-7LINLVVY.js +66 -0
  39. package/dist/catalogs-IR22RGZD.js +130 -0
  40. package/dist/changes-JAGWBHQC.js +143 -0
  41. package/dist/chatgpt-NE2RBMFK.js +47 -0
  42. package/dist/chats-6TRVVEBG.js +449 -0
  43. package/dist/check-DZGMLLRL.js +107 -0
  44. package/dist/chunk-2DQC4XSN.js +224 -0
  45. package/dist/chunk-3BWT5YDD.js +57 -0
  46. package/dist/chunk-3EUITH4J.js +638 -0
  47. package/dist/chunk-3J5ZTJGN.js +163 -0
  48. package/dist/chunk-3OFLYMPK.js +547 -0
  49. package/dist/chunk-4IRJ5JXA.js +46 -0
  50. package/dist/chunk-5IFFPSEN.js +225 -0
  51. package/dist/chunk-5YNGVEX2.js +23 -0
  52. package/dist/chunk-64ALJ6TJ.js +274 -0
  53. package/dist/chunk-6OIKNJ7G.js +26 -0
  54. package/dist/chunk-7L3Z2GDZ.js +61 -0
  55. package/dist/chunk-7LYJVM7L.js +377 -0
  56. package/dist/chunk-7UFV6H7J.js +167 -0
  57. package/dist/chunk-AGVLJLOT.js +203 -0
  58. package/dist/chunk-B3CDNANO.js +843 -0
  59. package/dist/chunk-BNI5DAB7.js +783 -0
  60. package/dist/chunk-BRT5IG7N.js +438 -0
  61. package/dist/chunk-CXRS5YLB.js +150 -0
  62. package/dist/chunk-CY6EPTJA.js +191 -0
  63. package/dist/chunk-CZ4Q3I25.js +2209 -0
  64. package/dist/chunk-E5H7JIWB.js +3510 -0
  65. package/dist/chunk-EGW3D3RW.js +207 -0
  66. package/dist/chunk-EPLSDHBT.js +8954 -0
  67. package/dist/chunk-F2VUMTCJ.js +103 -0
  68. package/dist/chunk-F3CZFUXZ.js +3187 -0
  69. package/dist/chunk-F3CZFUXZ.js.map +1 -0
  70. package/dist/chunk-FLF2CIL2.js +66 -0
  71. package/dist/chunk-FM4YT7QA.js +156 -0
  72. package/dist/chunk-FUIPDGGH.js +197 -0
  73. package/dist/chunk-G47B4DOH.js +910 -0
  74. package/dist/chunk-G6J6AWTE.js +5471 -0
  75. package/dist/chunk-GCZK4BMB.js +5368 -0
  76. package/dist/chunk-GVYJOHX5.js +455 -0
  77. package/dist/chunk-H4CLWLYF.js +4269 -0
  78. package/dist/chunk-H4CLWLYF.js.map +1 -0
  79. package/dist/chunk-ICEYCLRU.js +679 -0
  80. package/dist/chunk-IDFTXHRQ.js +275 -0
  81. package/dist/chunk-J2RUOIME.js +494 -0
  82. package/dist/chunk-JBNT444M.js +285 -0
  83. package/dist/chunk-K4IPXVVC.js +430 -0
  84. package/dist/chunk-K4IPXVVC.js.map +1 -0
  85. package/dist/chunk-KAUP6ONR.js +89 -0
  86. package/dist/chunk-KTO2Y3DI.js +1646 -0
  87. package/dist/chunk-KVYXHWX2.js +249 -0
  88. package/dist/chunk-L7AJMZ6Z.js +24026 -0
  89. package/dist/chunk-L7AJMZ6Z.js.map +1 -0
  90. package/dist/chunk-LDFM37DM.js +148 -0
  91. package/dist/chunk-LHC6OHQ6.js +857 -0
  92. package/dist/chunk-LQOJBPKV.js +142 -0
  93. package/dist/chunk-METHLFNZ.js +63 -0
  94. package/dist/chunk-MGOSJSDV.js +51 -0
  95. package/dist/chunk-O34P4WD5.js +604 -0
  96. package/dist/chunk-O5V2KBI4.js +387 -0
  97. package/dist/chunk-OO7Y2NMT.js +685 -0
  98. package/dist/chunk-P3AHGZH2.js +170 -0
  99. package/dist/chunk-P6FMQHJJ.js +131 -0
  100. package/dist/chunk-Q6LCL67T.js +1518 -0
  101. package/dist/chunk-Q7G5CWH6.js +169 -0
  102. package/dist/chunk-RA73BVUX.js +392 -0
  103. package/dist/chunk-S6ZCFRL5.js +19 -0
  104. package/dist/chunk-SIKCVWM3.js +76 -0
  105. package/dist/chunk-SIWXWRAD.js +831 -0
  106. package/dist/chunk-UKIS6BLM.js +7800 -0
  107. package/dist/chunk-UKIS6BLM.js.map +1 -0
  108. package/dist/chunk-UNIJPTDU.js +344 -0
  109. package/dist/chunk-UXFRUYTR.js +91 -0
  110. package/dist/chunk-V4UJERGL.js +64 -0
  111. package/dist/chunk-W46BM7HF.js +334 -0
  112. package/dist/chunk-WH7CATSZ.js +930 -0
  113. package/dist/chunk-WM2PLENG.js +1902 -0
  114. package/dist/chunk-XU6XQPNM.js +1919 -0
  115. package/dist/chunk-YKFGXS26.js +228 -0
  116. package/dist/chunk-YQB66YKJ.js +98 -0
  117. package/dist/chunk-YZKZQXRX.js +297 -0
  118. package/dist/chunk-ZDHWB32Y.js +91 -0
  119. package/dist/chunk-ZOYNCIRB.js +479 -0
  120. package/dist/claim-PTCFUZM2.js +200 -0
  121. package/dist/cli.js +31 -31
  122. package/dist/companies-STCBOG5Z.js +198 -0
  123. package/dist/company-4CE7CGNC.js +308 -0
  124. package/dist/complete-R4A7LBOQ.js +84 -0
  125. package/dist/connect-4VLRGTAM.js +45 -0
  126. package/dist/conversation-JS52LHCZ.js +96 -0
  127. package/dist/conversion-report-R4KJI4VA.js +127 -0
  128. package/dist/conversion-upload-command-WCLWA27O.js +439 -0
  129. package/dist/conversion-writes-XIQEIDPS.js +122 -0
  130. package/dist/conversions-IYEF6WZP.js +140 -0
  131. package/dist/conversions-RMBQNW3T.js +78 -0
  132. package/dist/create-6I7SRQHV.js +135 -0
  133. package/dist/create-JYBMK5JH.js +210 -0
  134. package/dist/create-MPUAOJQB.js +62 -0
  135. package/dist/create-W7L5B374.js +239 -0
  136. package/dist/creatives-EPXJ2PDV.js +223 -0
  137. package/dist/creatives-PP6Z2T6Z.js +58 -0
  138. package/dist/credentials-R4BZ76RD.js +290 -0
  139. package/dist/critique-ICVRILIZ.js +232 -0
  140. package/dist/critique-OTIGYFZU.js +1451 -0
  141. package/dist/crm-5JFMA2YB.js +227 -0
  142. package/dist/crm-PRTHRLXM.js +323 -0
  143. package/dist/currency-BY647ZB7.js +88 -0
  144. package/dist/customers-5EWPVKJV.js +65 -0
  145. package/dist/delete-5EWH2SQQ.js +57 -0
  146. package/dist/delete-V2FBPIN7.js +69 -0
  147. package/dist/delete-ZWUCKXI5.js +67 -0
  148. package/dist/demographics-2YCVAAPH.js +141 -0
  149. package/dist/discard-N7K3UQ7M.js +69 -0
  150. package/dist/discover-TAJUFO5R.js +172 -0
  151. package/dist/domain-YYTNWNSF.js +101 -0
  152. package/dist/download-JMJRYJ37.js +172 -0
  153. package/dist/draft-KQACMPH2.js +313 -0
  154. package/dist/draft-PENVOYCI.js +220 -0
  155. package/dist/draft-RGSDXFFT.js +408 -0
  156. package/dist/draft-SKEGKHIK.js +288 -0
  157. package/dist/draft-UOMHLIVY.js +342 -0
  158. package/dist/engine/index.js +8 -8
  159. package/dist/experiments-W5D7ERVJ.js +236 -0
  160. package/dist/facets-FUNOZ6JS.js +117 -0
  161. package/dist/feedback-OVZFH7UV.js +115 -0
  162. package/dist/feedback-record-DKDR3XHH.js +269 -0
  163. package/dist/fetch-QKP23NSX.js +204 -0
  164. package/dist/fit-PZPU2IZZ.js +65 -0
  165. package/dist/flows-GBMZJX4R.js +250 -0
  166. package/dist/fonts-2YY5465Q.js +39 -0
  167. package/dist/forecast-7B75GCRH.js +121 -0
  168. package/dist/forecast-VOND3WVO.js +169 -0
  169. package/dist/funnel-G4CMJ2C4.js +397 -0
  170. package/dist/generate-SW5KLHXG.js +263 -0
  171. package/dist/get-44VNCDBQ.js +59 -0
  172. package/dist/get-ZPJFKFHL.js +82 -0
  173. package/dist/google-VYARAUQH.js +3270 -0
  174. package/dist/google-ads-BKDTCXUS.js +198 -0
  175. package/dist/history-7DF5HFJT.js +69 -0
  176. package/dist/history-NEKVFRGQ.js +102 -0
  177. package/dist/history-YU6HH574.js +153 -0
  178. package/dist/hubspot-Q3ZQODAX.js +782 -0
  179. package/dist/ideas-75LW4KBY.js +45 -0
  180. package/dist/images-7FS4KEGU.js +92 -0
  181. package/dist/ingest-MHH5OQP4.js +27 -0
  182. package/dist/ingest-S5OS6WIU.js +123 -0
  183. package/dist/insights-YVV5MHPQ.js +132 -0
  184. package/dist/inspect-PIFZILBU.js +192 -0
  185. package/dist/inspiration-KL27O45N.js +53 -0
  186. package/dist/intent-GIAQDMHF.js +95 -0
  187. package/dist/keyword-gap-NZF75XGF.js +130 -0
  188. package/dist/keyword-metrics-H5M5I3N4.js +200 -0
  189. package/dist/keywords-for-site-RILBDULX.js +131 -0
  190. package/dist/landing-H5KY6F7K.js +28 -0
  191. package/dist/languages-GGNN7FEK.js +40 -0
  192. package/dist/leads-WCWH4C73.js +115 -0
  193. package/dist/learn-RUZUBNQZ.js +207 -0
  194. package/dist/line-item-writes-5Z3AEUV2.js +211 -0
  195. package/dist/line-items-IYSM2NEA.js +107 -0
  196. package/dist/link-KRNL5O7Z.js +67 -0
  197. package/dist/linkedin-GZIYAH4C.js +1330 -0
  198. package/dist/linkedin-person-PMXUBPVL.js +139 -0
  199. package/dist/list-ALQGX6JI.js +67 -0
  200. package/dist/list-I37IE3NN.js +154 -0
  201. package/dist/list-JD5T6CGQ.js +306 -0
  202. package/dist/locations-7RYEWKJO.js +69 -0
  203. package/dist/locations-BU4ZGWAS.js +40 -0
  204. package/dist/log-JWUFDOG6.js +95 -0
  205. package/dist/make-QCGOTYNW.js +1367 -0
  206. package/dist/map-EYKEY4VA.js +436 -0
  207. package/dist/mcp-P2PZCFFJ.js +729 -0
  208. package/dist/media-sources-UUNS3LES.js +35 -0
  209. package/dist/members-XTW5F5N5.js +47 -0
  210. package/dist/metrics-Z75Q2FHP.js +152 -0
  211. package/dist/models-X2IXXAD6.js +155 -0
  212. package/dist/normalize-P2UQIQOX.js +144 -0
  213. package/dist/options-2OK4LBAD.js +125 -0
  214. package/dist/organization-I5AIPZEH.js +949 -0
  215. package/dist/performance-4UPNHWC2.js +5565 -0
  216. package/dist/performance-H5FJQBOP.js +27 -0
  217. package/dist/pixels-DBSPNHIE.js +62 -0
  218. package/dist/promoted-tweet-writes-V5N5JDYQ.js +183 -0
  219. package/dist/promoted-tweets-ZSNBS3QQ.js +119 -0
  220. package/dist/publish-M6U72N3H.js +344 -0
  221. package/dist/query-NMQKS4MY.js +62 -0
  222. package/dist/reddit-AZMVTHPR.js +29 -0
  223. package/dist/refresh-42TJTJSN.js +97 -0
  224. package/dist/release-VT6TNWUV.js +63 -0
  225. package/dist/relevant-pages-JRIDJL4L.js +99 -0
  226. package/dist/remove-YW25PRT4.js +53 -0
  227. package/dist/reopen-WGTMBOHK.js +66 -0
  228. package/dist/rerun-O7P5LMC4.js +96 -0
  229. package/dist/research-IQWYPRBV.js +265 -0
  230. package/dist/research-WYNVU26K.js +75 -0
  231. package/dist/reset-4YPVS6QU.js +57 -0
  232. package/dist/reset-NF6K4NHK.js +57 -0
  233. package/dist/resolve-GB4ORVSB.js +124 -0
  234. package/dist/retry-LKJVOXVX.js +65 -0
  235. package/dist/retry-W3NSNNDV.js +63 -0
  236. package/dist/revenue-KHUWJPMJ.js +91 -0
  237. package/dist/rules-HMAONF3A.js +99 -0
  238. package/dist/rules-add-BP5XSD23.js +465 -0
  239. package/dist/run-EBCP5VIQ.js +71 -0
  240. package/dist/run-QP7JP2H4.js +69 -0
  241. package/dist/scaffold-ad-JVDV7FET.js +1513 -0
  242. package/dist/scaffold-static-ad-VD3KXMHT.js +1011 -0
  243. package/dist/scaffold-video-X3YR6APK.js +885 -0
  244. package/dist/schedule-7OKUUJHO.js +64 -0
  245. package/dist/scheduled-agents-N6FDAL7K.js +55 -0
  246. package/dist/schema-6O6CJTT5.js +135 -0
  247. package/dist/scrape-U6DIREQ2.js +2241 -0
  248. package/dist/scrape-U6DIREQ2.js.map +1 -0
  249. package/dist/search-WGOCL2KW.js +177 -0
  250. package/dist/select-6PVDRJQJ.js +110 -0
  251. package/dist/set-prompt-EDM7CPME.js +199 -0
  252. package/dist/setup-links-Z2KIKKJM.js +144 -0
  253. package/dist/shopify-AANLSYQY.js +3980 -0
  254. package/dist/site-6HHZJW2S.js +180 -0
  255. package/dist/sources-72AAZL4C.js +30 -0
  256. package/dist/sources-VRWQ65G6.js +457 -0
  257. package/dist/stale-KO6NQVR4.js +90 -0
  258. package/dist/status-QRO7U5K2.js +65 -0
  259. package/dist/studio-OV2ZY5W3.js +49 -0
  260. package/dist/sync-AQZ7JYEG.js +57 -0
  261. package/dist/sync-definition-OKSJA6MA.js +70 -0
  262. package/dist/tags-5GFUNIIK.js +23 -0
  263. package/dist/tags-DIFC2HFB.js +23 -0
  264. package/dist/tags-M26JKN2F.js +23 -0
  265. package/dist/tags-QFEG7LJV.js +26 -0
  266. package/dist/tags-ZWYUQYWT.js +227 -0
  267. package/dist/targeting-criteria-UQMPM2K5.js +113 -0
  268. package/dist/targets-YCVILKKZ.js +106 -0
  269. package/dist/testimonials-SJQJDEK4.js +32 -0
  270. package/dist/themes-RRLYZ46U.js +95 -0
  271. package/dist/top-companies-LPYM65KX.js +111 -0
  272. package/dist/transcript-D2IQWUSP.js +165 -0
  273. package/dist/translate-CPDFHEI4.js +603 -0
  274. package/dist/triggers-543HDVJK.js +144 -0
  275. package/dist/unlink-DQGU7K7V.js +70 -0
  276. package/dist/unstage-7UQU4MQT.js +88 -0
  277. package/dist/update-DGIBKKIB.js +155 -0
  278. package/dist/update-FEZ3EVTA.js +66 -0
  279. package/dist/update-QF6WBJU7.js +101 -0
  280. package/dist/update-RY3GU5QI.js +192 -0
  281. package/dist/upload-VMDGQ4HS.js +130 -0
  282. package/dist/url-options-2TQCGD2W.js +131 -0
  283. package/dist/url-params-LMC2DRHP.js +101 -0
  284. package/dist/validate-TLWEN4IL.js +125 -0
  285. package/dist/videos-GFOHRAJ7.js +41 -0
  286. package/dist/view-ZT3SAZKQ.js +121 -0
  287. package/dist/view-ZT3SAZKQ.js.map +1 -0
  288. package/dist/viewer-check-EKDFC7LQ.js +83 -0
  289. package/dist/web-L7LF6FLF.js +173 -0
  290. package/dist/winning-ads-RUS4NE5C.js +86 -0
  291. package/dist/write-commands-2JYDSXAX.js +1525 -0
  292. package/dist/x-HLZUSGJT.js +47 -0
  293. package/package.json +1 -1
  294. package/dist/account-2HJ4GKHN.js +0 -82
  295. package/dist/account-6GKPLNDY.js +0 -82
  296. package/dist/account-reads-X36NPCX5.js +0 -219
  297. package/dist/account-users-FGL3DZES.js +0 -64
  298. package/dist/account-writes-FZ3KCJZY.js +0 -68
  299. package/dist/accounts-PKSW3DBQ.js +0 -80
  300. package/dist/accounts-S5C6MZFO.js +0 -701
  301. package/dist/actions-ARN3OFB7.js +0 -55
  302. package/dist/activecampaign-3YJC3H2R.js +0 -938
  303. package/dist/ad-group-writes-XGG3WQEO.js +0 -172
  304. package/dist/ad-groups-GZIPUN64.js +0 -70
  305. package/dist/ad-writes-2VTRWQLW.js +0 -176
  306. package/dist/add-CNYKQD7B.js +0 -107
  307. package/dist/add-IABKHM5N.js +0 -305
  308. package/dist/ads-LNWALF6G.js +0 -79
  309. package/dist/ads-UXHJCUTX.js +0 -48
  310. package/dist/advertisers-UT7EJ6YS.js +0 -123
  311. package/dist/analytics-COUVH7MV.js +0 -447
  312. package/dist/analytics-EHUUNMGZ.js +0 -2437
  313. package/dist/animate-DM4OUJMR.js +0 -480
  314. package/dist/assign-FWT5QQDF.js +0 -80
  315. package/dist/audience-size-YI2RLIG7.js +0 -76
  316. package/dist/audiences-7D5VPOWF.js +0 -280
  317. package/dist/audit-BPRRCIWN.js +0 -154
  318. package/dist/autocomplete-OD6SHZZH.js +0 -114
  319. package/dist/avatars-FFFPCH6D.js +0 -38
  320. package/dist/bid-pricing-JF557IO2.js +0 -103
  321. package/dist/brand-ZUYJWKI3.js +0 -22
  322. package/dist/brief-CJDBD5GJ.js +0 -543
  323. package/dist/campaign-groups-VCT6ZH66.js +0 -99
  324. package/dist/campaign-writes-H22P6YPW.js +0 -176
  325. package/dist/campaign-writes-YOHDMYDT.js +0 -168
  326. package/dist/campaigns-265JXD2Z.js +0 -78
  327. package/dist/campaigns-7EGRZ3V6.js +0 -113
  328. package/dist/campaigns-ORK5BYAM.js +0 -111
  329. package/dist/canvas-FW5F3KZJ.js +0 -46
  330. package/dist/capabilities-ISW7XT44.js +0 -147
  331. package/dist/catalog-DPUQBZZ7.js +0 -66
  332. package/dist/catalogs-SBXFAD3X.js +0 -130
  333. package/dist/changes-HXVZUJMH.js +0 -143
  334. package/dist/chatgpt-UXJPCGZU.js +0 -47
  335. package/dist/chats-FH3DQNYD.js +0 -449
  336. package/dist/check-QC5RHS3Z.js +0 -107
  337. package/dist/chunk-2AC5GJHC.js +0 -455
  338. package/dist/chunk-2VSUMGJV.js +0 -89
  339. package/dist/chunk-4D73PLXU.js +0 -843
  340. package/dist/chunk-4S5ZAG4S.js +0 -63
  341. package/dist/chunk-5MMJPUBH.js +0 -387
  342. package/dist/chunk-5Y2XPKW2.js +0 -156
  343. package/dist/chunk-6HCYCMIH.js +0 -61
  344. package/dist/chunk-6R2BQ6FK.js +0 -344
  345. package/dist/chunk-7P74QKVC.js +0 -297
  346. package/dist/chunk-7SJU6PQ7.js +0 -604
  347. package/dist/chunk-A37TIYFD.js +0 -91
  348. package/dist/chunk-A6NVGPCZ.js +0 -479
  349. package/dist/chunk-AK7CL5IW.js +0 -334
  350. package/dist/chunk-AOT3UZBM.js +0 -930
  351. package/dist/chunk-D2ZAZGQH.js +0 -547
  352. package/dist/chunk-DYTBVVQX.js +0 -679
  353. package/dist/chunk-EB76M4ZH.js +0 -19
  354. package/dist/chunk-EBWOLUII.js +0 -24026
  355. package/dist/chunk-EBWOLUII.js.map +0 -1
  356. package/dist/chunk-EOMY5SUJ.js +0 -783
  357. package/dist/chunk-EY5WWPPZ.js +0 -1902
  358. package/dist/chunk-EZKT5YGX.js +0 -23
  359. package/dist/chunk-FVDC6AKZ.js +0 -150
  360. package/dist/chunk-GN7K3NPI.js +0 -148
  361. package/dist/chunk-GQAKWQAV.js +0 -224
  362. package/dist/chunk-HBDWE7WK.js +0 -98
  363. package/dist/chunk-HETNOUE4.js +0 -377
  364. package/dist/chunk-HFAT5S5B.js +0 -170
  365. package/dist/chunk-HQ3I2QVT.js +0 -275
  366. package/dist/chunk-IN5UCEJD.js +0 -91
  367. package/dist/chunk-JAC6JVCI.js +0 -26
  368. package/dist/chunk-JLLGXYOZ.js +0 -857
  369. package/dist/chunk-JY3OJBKZ.js +0 -3510
  370. package/dist/chunk-KBZRG6IK.js +0 -429
  371. package/dist/chunk-KBZRG6IK.js.map +0 -1
  372. package/dist/chunk-KCRBAMFU.js +0 -392
  373. package/dist/chunk-KIXVHP2C.js +0 -1919
  374. package/dist/chunk-KTY7H44G.js +0 -831
  375. package/dist/chunk-LKOMEXUB.js +0 -51
  376. package/dist/chunk-LVKAMWKJ.js +0 -163
  377. package/dist/chunk-LWCGQNVU.js +0 -685
  378. package/dist/chunk-MCJ5I5LR.js +0 -3187
  379. package/dist/chunk-MCJ5I5LR.js.map +0 -1
  380. package/dist/chunk-MSMTG6OC.js +0 -4269
  381. package/dist/chunk-MSMTG6OC.js.map +0 -1
  382. package/dist/chunk-MZPS46OR.js +0 -76
  383. package/dist/chunk-N4AIJQ4W.js +0 -438
  384. package/dist/chunk-NBWZVBDG.js +0 -131
  385. package/dist/chunk-OKB2EAJH.js +0 -8954
  386. package/dist/chunk-OT2MN5UR.js +0 -169
  387. package/dist/chunk-OZR3KUJ3.js +0 -57
  388. package/dist/chunk-P3VY5JEM.js +0 -274
  389. package/dist/chunk-PXGR3VGW.js +0 -1646
  390. package/dist/chunk-QK3HMAVU.js +0 -5471
  391. package/dist/chunk-R65V26HH.js +0 -7770
  392. package/dist/chunk-R65V26HH.js.map +0 -1
  393. package/dist/chunk-RHEWQB5O.js +0 -638
  394. package/dist/chunk-RP36XHWT.js +0 -46
  395. package/dist/chunk-RXOQZA4K.js +0 -66
  396. package/dist/chunk-SEHJ7Y7J.js +0 -207
  397. package/dist/chunk-SNWFM2DB.js +0 -228
  398. package/dist/chunk-TAGRKRFI.js +0 -103
  399. package/dist/chunk-TARINRA4.js +0 -1518
  400. package/dist/chunk-TNZUMU55.js +0 -167
  401. package/dist/chunk-TP2NS5SG.js +0 -191
  402. package/dist/chunk-UOXC3XA5.js +0 -494
  403. package/dist/chunk-UQA6Z23M.js +0 -142
  404. package/dist/chunk-VOUCQ2YW.js +0 -64
  405. package/dist/chunk-WJ5AHR4K.js +0 -2209
  406. package/dist/chunk-WOE4TZHJ.js +0 -285
  407. package/dist/chunk-XYNQMRNX.js +0 -5368
  408. package/dist/chunk-YEISVDKW.js +0 -203
  409. package/dist/chunk-YNLWSP5E.js +0 -910
  410. package/dist/chunk-ZEUAJAKN.js +0 -225
  411. package/dist/chunk-ZUUVWWB5.js +0 -197
  412. package/dist/chunk-ZVAZFHH7.js +0 -249
  413. package/dist/claim-FBL5VBYZ.js +0 -200
  414. package/dist/companies-URRCAJZE.js +0 -198
  415. package/dist/company-LDCNUPHZ.js +0 -308
  416. package/dist/complete-3UGPO444.js +0 -84
  417. package/dist/connect-M5KPZQWE.js +0 -45
  418. package/dist/conversation-S7YANZJR.js +0 -96
  419. package/dist/conversion-report-RB2MU7UD.js +0 -127
  420. package/dist/conversion-upload-command-HFZYKVXA.js +0 -439
  421. package/dist/conversion-writes-56AIPXPK.js +0 -122
  422. package/dist/conversions-NRX76ZIT.js +0 -78
  423. package/dist/conversions-QZL4DSJO.js +0 -140
  424. package/dist/create-56PJRLMA.js +0 -62
  425. package/dist/create-OE5MRW3X.js +0 -210
  426. package/dist/create-RL7PRIDY.js +0 -239
  427. package/dist/create-Y6YVJ5L4.js +0 -135
  428. package/dist/creatives-ESVH63AP.js +0 -223
  429. package/dist/creatives-URHXATY6.js +0 -58
  430. package/dist/credentials-O6QSB7ZR.js +0 -290
  431. package/dist/critique-EWJBOCXQ.js +0 -1451
  432. package/dist/critique-PTGGXRFG.js +0 -232
  433. package/dist/crm-F6RGNQH5.js +0 -323
  434. package/dist/crm-GLPOO22Q.js +0 -227
  435. package/dist/currency-CHBV6WIO.js +0 -88
  436. package/dist/customers-Q76FCWYO.js +0 -65
  437. package/dist/delete-ODFDZCL3.js +0 -57
  438. package/dist/delete-OVMPDGWQ.js +0 -69
  439. package/dist/delete-XN7N4S4H.js +0 -67
  440. package/dist/demographics-IY5RI55Z.js +0 -141
  441. package/dist/discard-GKIA5FML.js +0 -69
  442. package/dist/discover-ZU2DAV23.js +0 -172
  443. package/dist/domain-WGXA7OXV.js +0 -101
  444. package/dist/download-DYYNUGLX.js +0 -172
  445. package/dist/draft-EWGNZUU4.js +0 -288
  446. package/dist/draft-EX2I6UJB.js +0 -313
  447. package/dist/draft-GKI6MB7L.js +0 -342
  448. package/dist/draft-R7BNWMBR.js +0 -408
  449. package/dist/draft-VYIRZO3E.js +0 -220
  450. package/dist/experiments-6DOKWFH4.js +0 -236
  451. package/dist/facets-ZU5DT2QW.js +0 -117
  452. package/dist/feedback-RIUBM557.js +0 -115
  453. package/dist/feedback-record-3VVAUCOH.js +0 -269
  454. package/dist/fetch-T6TZCU74.js +0 -204
  455. package/dist/fit-YPOHTM7Y.js +0 -65
  456. package/dist/flows-CKVEZFF2.js +0 -250
  457. package/dist/fonts-3J3UVZ2E.js +0 -39
  458. package/dist/forecast-372Q6KQZ.js +0 -169
  459. package/dist/forecast-JEAFUR2O.js +0 -121
  460. package/dist/funnel-FBTNPTS7.js +0 -397
  461. package/dist/generate-JQIK3UYS.js +0 -263
  462. package/dist/get-5N5FCGNH.js +0 -59
  463. package/dist/get-EXHUQT65.js +0 -82
  464. package/dist/google-JHTOX6WM.js +0 -3270
  465. package/dist/google-ads-ZAYRCG2D.js +0 -198
  466. package/dist/history-4ULZ4BVV.js +0 -153
  467. package/dist/history-6J3XRNTZ.js +0 -102
  468. package/dist/history-VNLS2TKB.js +0 -69
  469. package/dist/hubspot-ZEHWWJHK.js +0 -782
  470. package/dist/ideas-SB6546GI.js +0 -45
  471. package/dist/images-LEZYVE7R.js +0 -92
  472. package/dist/ingest-4OOTCOLO.js +0 -123
  473. package/dist/ingest-KNJCCIBG.js +0 -27
  474. package/dist/insights-XY6II7TX.js +0 -132
  475. package/dist/inspect-MHKEYNIC.js +0 -192
  476. package/dist/inspiration-CSN3AXDD.js +0 -53
  477. package/dist/intent-5QUPPZNI.js +0 -95
  478. package/dist/keyword-gap-IG3EFLDH.js +0 -130
  479. package/dist/keyword-metrics-EL7MO3H6.js +0 -200
  480. package/dist/keywords-for-site-I7KJLZ2I.js +0 -131
  481. package/dist/landing-Z3QGJYM3.js +0 -28
  482. package/dist/languages-LNHWSCMT.js +0 -40
  483. package/dist/leads-WQCTZYKT.js +0 -115
  484. package/dist/learn-6KW6TUVL.js +0 -207
  485. package/dist/line-item-writes-B2KSP36W.js +0 -211
  486. package/dist/line-items-3ICE5DBI.js +0 -107
  487. package/dist/link-QRQ34ZDH.js +0 -67
  488. package/dist/linkedin-D4RKHQPS.js +0 -1330
  489. package/dist/linkedin-person-Y5TCUOXS.js +0 -139
  490. package/dist/list-6HZVHA6T.js +0 -154
  491. package/dist/list-CHYJ53JD.js +0 -306
  492. package/dist/list-XAMJSOGI.js +0 -67
  493. package/dist/locations-64JNCQID.js +0 -69
  494. package/dist/locations-KVAAO7LD.js +0 -40
  495. package/dist/log-PLXGA74X.js +0 -95
  496. package/dist/make-EP4YSN26.js +0 -1367
  497. package/dist/map-CAFMAMPP.js +0 -436
  498. package/dist/mcp-DDWSXLU7.js +0 -729
  499. package/dist/media-sources-J5FXYPV5.js +0 -35
  500. package/dist/members-ZA7S5KWP.js +0 -47
  501. package/dist/metrics-MXGA3EFS.js +0 -152
  502. package/dist/models-Z6SUHWKI.js +0 -155
  503. package/dist/normalize-ZHM2ZVXZ.js +0 -144
  504. package/dist/options-JTMDZECY.js +0 -125
  505. package/dist/organization-5OJEJEQV.js +0 -949
  506. package/dist/performance-AHVTOYTM.js +0 -5565
  507. package/dist/performance-S273NSUB.js +0 -27
  508. package/dist/pixels-H642RPK4.js +0 -62
  509. package/dist/promoted-tweet-writes-UF6LYMH4.js +0 -183
  510. package/dist/promoted-tweets-Z4GG6D7P.js +0 -119
  511. package/dist/publish-YQ6MHS7P.js +0 -344
  512. package/dist/query-FT2BA3WH.js +0 -62
  513. package/dist/reddit-YWYRZBL2.js +0 -29
  514. package/dist/refresh-TEXTTECA.js +0 -97
  515. package/dist/release-3JDETBZI.js +0 -63
  516. package/dist/relevant-pages-OCHLUV5K.js +0 -99
  517. package/dist/remove-KZTSU4K2.js +0 -53
  518. package/dist/reopen-GIJSFNDH.js +0 -66
  519. package/dist/rerun-6UZNOPUG.js +0 -96
  520. package/dist/research-TMKG4NQJ.js +0 -75
  521. package/dist/research-XA2IJ2XV.js +0 -265
  522. package/dist/reset-7VL6WJLE.js +0 -57
  523. package/dist/reset-HLZ6JHGY.js +0 -57
  524. package/dist/resolve-H2QW3U5Y.js +0 -124
  525. package/dist/retry-MIZ67MPP.js +0 -65
  526. package/dist/retry-WSWW6EJT.js +0 -63
  527. package/dist/revenue-LTU7HRT2.js +0 -91
  528. package/dist/rules-BGBCUUPH.js +0 -99
  529. package/dist/rules-add-SZT2MSOD.js +0 -465
  530. package/dist/run-FHGT4UQ7.js +0 -69
  531. package/dist/run-XUDGECLL.js +0 -71
  532. package/dist/scaffold-ad-VXNO3SQP.js +0 -1513
  533. package/dist/scaffold-static-ad-FT55VV3T.js +0 -1011
  534. package/dist/scaffold-video-V7WX5AWZ.js +0 -885
  535. package/dist/schedule-BNRLEFMZ.js +0 -64
  536. package/dist/scheduled-agents-MAXXXJ7W.js +0 -55
  537. package/dist/schema-YADPD54K.js +0 -135
  538. package/dist/scrape-3PWNMK4D.js +0 -2241
  539. package/dist/scrape-3PWNMK4D.js.map +0 -1
  540. package/dist/search-56ORG4PL.js +0 -177
  541. package/dist/select-DON4DMNM.js +0 -110
  542. package/dist/set-prompt-J22TUCRU.js +0 -199
  543. package/dist/setup-links-CHODCBYH.js +0 -144
  544. package/dist/shopify-FCYU4AR6.js +0 -3980
  545. package/dist/site-BF3Q26W5.js +0 -180
  546. package/dist/sources-SLCYAWTZ.js +0 -457
  547. package/dist/sources-VHHC6YQM.js +0 -30
  548. package/dist/stale-GLVTL2ZK.js +0 -90
  549. package/dist/status-E3RA644P.js +0 -65
  550. package/dist/studio-6ZXUKA4G.js +0 -49
  551. package/dist/sync-6QCDDJMO.js +0 -57
  552. package/dist/sync-definition-DXNHGY5E.js +0 -70
  553. package/dist/tags-AMZSQJJ2.js +0 -26
  554. package/dist/tags-KW7PG2TR.js +0 -23
  555. package/dist/tags-MGV5KG6I.js +0 -23
  556. package/dist/tags-TM27EIAL.js +0 -23
  557. package/dist/tags-VWGKVGZD.js +0 -227
  558. package/dist/targeting-criteria-FT3G4HAW.js +0 -113
  559. package/dist/targets-XLVHWO6Z.js +0 -106
  560. package/dist/testimonials-INXY7CXU.js +0 -32
  561. package/dist/themes-R3A6IVQN.js +0 -95
  562. package/dist/top-companies-MNX3GBCP.js +0 -111
  563. package/dist/transcript-GIAOWCTO.js +0 -165
  564. package/dist/translate-JEQ4K4AH.js +0 -603
  565. package/dist/triggers-KDXLDZ23.js +0 -144
  566. package/dist/unlink-PNBSDLBQ.js +0 -70
  567. package/dist/unstage-X2PDLT5O.js +0 -88
  568. package/dist/update-4JGHSQVZ.js +0 -66
  569. package/dist/update-4XUQN4LK.js +0 -101
  570. package/dist/update-TJTDFWER.js +0 -155
  571. package/dist/update-URU4TO2F.js +0 -192
  572. package/dist/upload-TO5EPTVD.js +0 -130
  573. package/dist/url-options-YZ6UG3NY.js +0 -131
  574. package/dist/url-params-533CWJH3.js +0 -101
  575. package/dist/validate-XF6HU7D4.js +0 -125
  576. package/dist/videos-KYZ4CUOB.js +0 -41
  577. package/dist/view-VFZUL5UL.js +0 -121
  578. package/dist/view-VFZUL5UL.js.map +0 -1
  579. package/dist/viewer-check-U5GUU34Z.js +0 -83
  580. package/dist/web-ZYMSMIV6.js +0 -173
  581. package/dist/winning-ads-BCN5RVAE.js +0 -86
  582. package/dist/write-commands-PZZ72PNL.js +0 -1525
  583. package/dist/x-DLEZYTAU.js +0 -47
  584. /package/dist/{account-2HJ4GKHN.js.map → account-IG3U6UXZ.js.map} +0 -0
  585. /package/dist/{account-6GKPLNDY.js.map → account-IGWCS2VJ.js.map} +0 -0
  586. /package/dist/{account-reads-X36NPCX5.js.map → account-reads-LOCJMS35.js.map} +0 -0
  587. /package/dist/{account-users-FGL3DZES.js.map → account-users-H4VP43RZ.js.map} +0 -0
  588. /package/dist/{account-writes-FZ3KCJZY.js.map → account-writes-BSSKSTZ2.js.map} +0 -0
  589. /package/dist/{accounts-S5C6MZFO.js.map → accounts-C4PNBT5X.js.map} +0 -0
  590. /package/dist/{accounts-PKSW3DBQ.js.map → accounts-GPTG4XW5.js.map} +0 -0
  591. /package/dist/{actions-ARN3OFB7.js.map → actions-F7YO5I27.js.map} +0 -0
  592. /package/dist/{activecampaign-3YJC3H2R.js.map → activecampaign-S4E46SA6.js.map} +0 -0
  593. /package/dist/{ad-group-writes-XGG3WQEO.js.map → ad-group-writes-KMB3OMJG.js.map} +0 -0
  594. /package/dist/{ad-groups-GZIPUN64.js.map → ad-groups-E67CNQS4.js.map} +0 -0
  595. /package/dist/{ad-writes-2VTRWQLW.js.map → ad-writes-FNMKNFUN.js.map} +0 -0
  596. /package/dist/{add-CNYKQD7B.js.map → add-LROKBWW4.js.map} +0 -0
  597. /package/dist/{add-IABKHM5N.js.map → add-SG5XWFRN.js.map} +0 -0
  598. /package/dist/{ads-LNWALF6G.js.map → ads-4LASBP4G.js.map} +0 -0
  599. /package/dist/{ads-UXHJCUTX.js.map → ads-7ICT2D4M.js.map} +0 -0
  600. /package/dist/{advertisers-UT7EJ6YS.js.map → advertisers-IQMTOR4D.js.map} +0 -0
  601. /package/dist/{analytics-EHUUNMGZ.js.map → analytics-6DSJ6WHO.js.map} +0 -0
  602. /package/dist/{analytics-COUVH7MV.js.map → analytics-D6S5LW2F.js.map} +0 -0
  603. /package/dist/{animate-DM4OUJMR.js.map → animate-OWXAT2RK.js.map} +0 -0
  604. /package/dist/{assign-FWT5QQDF.js.map → assign-TMG6FDLW.js.map} +0 -0
  605. /package/dist/{audience-size-YI2RLIG7.js.map → audience-size-KPJOSG5W.js.map} +0 -0
  606. /package/dist/{audiences-7D5VPOWF.js.map → audiences-3R574STZ.js.map} +0 -0
  607. /package/dist/{audit-BPRRCIWN.js.map → audit-35TDKIGY.js.map} +0 -0
  608. /package/dist/{autocomplete-OD6SHZZH.js.map → autocomplete-T63KPKRZ.js.map} +0 -0
  609. /package/dist/{avatars-FFFPCH6D.js.map → avatars-AVK4S3HS.js.map} +0 -0
  610. /package/dist/{bid-pricing-JF557IO2.js.map → bid-pricing-O5IK37CL.js.map} +0 -0
  611. /package/dist/{brand-ZUYJWKI3.js.map → brand-SG6VOHF4.js.map} +0 -0
  612. /package/dist/{brief-CJDBD5GJ.js.map → brief-RWA6MXTN.js.map} +0 -0
  613. /package/dist/{campaign-groups-VCT6ZH66.js.map → campaign-groups-SSZISPJ5.js.map} +0 -0
  614. /package/dist/{campaign-writes-YOHDMYDT.js.map → campaign-writes-74KDZ7RR.js.map} +0 -0
  615. /package/dist/{campaign-writes-H22P6YPW.js.map → campaign-writes-Z2J24SUZ.js.map} +0 -0
  616. /package/dist/{campaigns-265JXD2Z.js.map → campaigns-43OS6EUG.js.map} +0 -0
  617. /package/dist/{campaigns-7EGRZ3V6.js.map → campaigns-B5TSL3UD.js.map} +0 -0
  618. /package/dist/{campaigns-ORK5BYAM.js.map → campaigns-TFNPOQEW.js.map} +0 -0
  619. /package/dist/{canvas-FW5F3KZJ.js.map → canvas-4LSM4Y5I.js.map} +0 -0
  620. /package/dist/{capabilities-ISW7XT44.js.map → capabilities-CTKSS7AI.js.map} +0 -0
  621. /package/dist/{catalog-DPUQBZZ7.js.map → catalog-7LINLVVY.js.map} +0 -0
  622. /package/dist/{catalogs-SBXFAD3X.js.map → catalogs-IR22RGZD.js.map} +0 -0
  623. /package/dist/{changes-HXVZUJMH.js.map → changes-JAGWBHQC.js.map} +0 -0
  624. /package/dist/{chatgpt-UXJPCGZU.js.map → chatgpt-NE2RBMFK.js.map} +0 -0
  625. /package/dist/{chats-FH3DQNYD.js.map → chats-6TRVVEBG.js.map} +0 -0
  626. /package/dist/{check-QC5RHS3Z.js.map → check-DZGMLLRL.js.map} +0 -0
  627. /package/dist/{chunk-GQAKWQAV.js.map → chunk-2DQC4XSN.js.map} +0 -0
  628. /package/dist/{chunk-OZR3KUJ3.js.map → chunk-3BWT5YDD.js.map} +0 -0
  629. /package/dist/{chunk-RHEWQB5O.js.map → chunk-3EUITH4J.js.map} +0 -0
  630. /package/dist/{chunk-LVKAMWKJ.js.map → chunk-3J5ZTJGN.js.map} +0 -0
  631. /package/dist/{chunk-D2ZAZGQH.js.map → chunk-3OFLYMPK.js.map} +0 -0
  632. /package/dist/{chunk-RP36XHWT.js.map → chunk-4IRJ5JXA.js.map} +0 -0
  633. /package/dist/{chunk-ZEUAJAKN.js.map → chunk-5IFFPSEN.js.map} +0 -0
  634. /package/dist/{chunk-EZKT5YGX.js.map → chunk-5YNGVEX2.js.map} +0 -0
  635. /package/dist/{chunk-P3VY5JEM.js.map → chunk-64ALJ6TJ.js.map} +0 -0
  636. /package/dist/{chunk-JAC6JVCI.js.map → chunk-6OIKNJ7G.js.map} +0 -0
  637. /package/dist/{chunk-6HCYCMIH.js.map → chunk-7L3Z2GDZ.js.map} +0 -0
  638. /package/dist/{chunk-HETNOUE4.js.map → chunk-7LYJVM7L.js.map} +0 -0
  639. /package/dist/{chunk-TNZUMU55.js.map → chunk-7UFV6H7J.js.map} +0 -0
  640. /package/dist/{chunk-YEISVDKW.js.map → chunk-AGVLJLOT.js.map} +0 -0
  641. /package/dist/{chunk-4D73PLXU.js.map → chunk-B3CDNANO.js.map} +0 -0
  642. /package/dist/{chunk-EOMY5SUJ.js.map → chunk-BNI5DAB7.js.map} +0 -0
  643. /package/dist/{chunk-N4AIJQ4W.js.map → chunk-BRT5IG7N.js.map} +0 -0
  644. /package/dist/{chunk-FVDC6AKZ.js.map → chunk-CXRS5YLB.js.map} +0 -0
  645. /package/dist/{chunk-TP2NS5SG.js.map → chunk-CY6EPTJA.js.map} +0 -0
  646. /package/dist/{chunk-WJ5AHR4K.js.map → chunk-CZ4Q3I25.js.map} +0 -0
  647. /package/dist/{chunk-JY3OJBKZ.js.map → chunk-E5H7JIWB.js.map} +0 -0
  648. /package/dist/{chunk-SEHJ7Y7J.js.map → chunk-EGW3D3RW.js.map} +0 -0
  649. /package/dist/{chunk-OKB2EAJH.js.map → chunk-EPLSDHBT.js.map} +0 -0
  650. /package/dist/{chunk-TAGRKRFI.js.map → chunk-F2VUMTCJ.js.map} +0 -0
  651. /package/dist/{chunk-RXOQZA4K.js.map → chunk-FLF2CIL2.js.map} +0 -0
  652. /package/dist/{chunk-5Y2XPKW2.js.map → chunk-FM4YT7QA.js.map} +0 -0
  653. /package/dist/{chunk-ZUUVWWB5.js.map → chunk-FUIPDGGH.js.map} +0 -0
  654. /package/dist/{chunk-YNLWSP5E.js.map → chunk-G47B4DOH.js.map} +0 -0
  655. /package/dist/{chunk-QK3HMAVU.js.map → chunk-G6J6AWTE.js.map} +0 -0
  656. /package/dist/{chunk-XYNQMRNX.js.map → chunk-GCZK4BMB.js.map} +0 -0
  657. /package/dist/{chunk-2AC5GJHC.js.map → chunk-GVYJOHX5.js.map} +0 -0
  658. /package/dist/{chunk-DYTBVVQX.js.map → chunk-ICEYCLRU.js.map} +0 -0
  659. /package/dist/{chunk-HQ3I2QVT.js.map → chunk-IDFTXHRQ.js.map} +0 -0
  660. /package/dist/{chunk-UOXC3XA5.js.map → chunk-J2RUOIME.js.map} +0 -0
  661. /package/dist/{chunk-WOE4TZHJ.js.map → chunk-JBNT444M.js.map} +0 -0
  662. /package/dist/{chunk-2VSUMGJV.js.map → chunk-KAUP6ONR.js.map} +0 -0
  663. /package/dist/{chunk-PXGR3VGW.js.map → chunk-KTO2Y3DI.js.map} +0 -0
  664. /package/dist/{chunk-ZVAZFHH7.js.map → chunk-KVYXHWX2.js.map} +0 -0
  665. /package/dist/{chunk-GN7K3NPI.js.map → chunk-LDFM37DM.js.map} +0 -0
  666. /package/dist/{chunk-JLLGXYOZ.js.map → chunk-LHC6OHQ6.js.map} +0 -0
  667. /package/dist/{chunk-UQA6Z23M.js.map → chunk-LQOJBPKV.js.map} +0 -0
  668. /package/dist/{chunk-4S5ZAG4S.js.map → chunk-METHLFNZ.js.map} +0 -0
  669. /package/dist/{chunk-LKOMEXUB.js.map → chunk-MGOSJSDV.js.map} +0 -0
  670. /package/dist/{chunk-7SJU6PQ7.js.map → chunk-O34P4WD5.js.map} +0 -0
  671. /package/dist/{chunk-5MMJPUBH.js.map → chunk-O5V2KBI4.js.map} +0 -0
  672. /package/dist/{chunk-LWCGQNVU.js.map → chunk-OO7Y2NMT.js.map} +0 -0
  673. /package/dist/{chunk-HFAT5S5B.js.map → chunk-P3AHGZH2.js.map} +0 -0
  674. /package/dist/{chunk-NBWZVBDG.js.map → chunk-P6FMQHJJ.js.map} +0 -0
  675. /package/dist/{chunk-TARINRA4.js.map → chunk-Q6LCL67T.js.map} +0 -0
  676. /package/dist/{chunk-OT2MN5UR.js.map → chunk-Q7G5CWH6.js.map} +0 -0
  677. /package/dist/{chunk-KCRBAMFU.js.map → chunk-RA73BVUX.js.map} +0 -0
  678. /package/dist/{chunk-EB76M4ZH.js.map → chunk-S6ZCFRL5.js.map} +0 -0
  679. /package/dist/{chunk-MZPS46OR.js.map → chunk-SIKCVWM3.js.map} +0 -0
  680. /package/dist/{chunk-KTY7H44G.js.map → chunk-SIWXWRAD.js.map} +0 -0
  681. /package/dist/{chunk-6R2BQ6FK.js.map → chunk-UNIJPTDU.js.map} +0 -0
  682. /package/dist/{chunk-A37TIYFD.js.map → chunk-UXFRUYTR.js.map} +0 -0
  683. /package/dist/{chunk-VOUCQ2YW.js.map → chunk-V4UJERGL.js.map} +0 -0
  684. /package/dist/{chunk-AK7CL5IW.js.map → chunk-W46BM7HF.js.map} +0 -0
  685. /package/dist/{chunk-AOT3UZBM.js.map → chunk-WH7CATSZ.js.map} +0 -0
  686. /package/dist/{chunk-EY5WWPPZ.js.map → chunk-WM2PLENG.js.map} +0 -0
  687. /package/dist/{chunk-KIXVHP2C.js.map → chunk-XU6XQPNM.js.map} +0 -0
  688. /package/dist/{chunk-SNWFM2DB.js.map → chunk-YKFGXS26.js.map} +0 -0
  689. /package/dist/{chunk-HBDWE7WK.js.map → chunk-YQB66YKJ.js.map} +0 -0
  690. /package/dist/{chunk-7P74QKVC.js.map → chunk-YZKZQXRX.js.map} +0 -0
  691. /package/dist/{chunk-IN5UCEJD.js.map → chunk-ZDHWB32Y.js.map} +0 -0
  692. /package/dist/{chunk-A6NVGPCZ.js.map → chunk-ZOYNCIRB.js.map} +0 -0
  693. /package/dist/{claim-FBL5VBYZ.js.map → claim-PTCFUZM2.js.map} +0 -0
  694. /package/dist/{companies-URRCAJZE.js.map → companies-STCBOG5Z.js.map} +0 -0
  695. /package/dist/{company-LDCNUPHZ.js.map → company-4CE7CGNC.js.map} +0 -0
  696. /package/dist/{complete-3UGPO444.js.map → complete-R4A7LBOQ.js.map} +0 -0
  697. /package/dist/{connect-M5KPZQWE.js.map → connect-4VLRGTAM.js.map} +0 -0
  698. /package/dist/{conversation-S7YANZJR.js.map → conversation-JS52LHCZ.js.map} +0 -0
  699. /package/dist/{conversion-report-RB2MU7UD.js.map → conversion-report-R4KJI4VA.js.map} +0 -0
  700. /package/dist/{conversion-upload-command-HFZYKVXA.js.map → conversion-upload-command-WCLWA27O.js.map} +0 -0
  701. /package/dist/{conversion-writes-56AIPXPK.js.map → conversion-writes-XIQEIDPS.js.map} +0 -0
  702. /package/dist/{conversions-QZL4DSJO.js.map → conversions-IYEF6WZP.js.map} +0 -0
  703. /package/dist/{conversions-NRX76ZIT.js.map → conversions-RMBQNW3T.js.map} +0 -0
  704. /package/dist/{create-Y6YVJ5L4.js.map → create-6I7SRQHV.js.map} +0 -0
  705. /package/dist/{create-OE5MRW3X.js.map → create-JYBMK5JH.js.map} +0 -0
  706. /package/dist/{create-56PJRLMA.js.map → create-MPUAOJQB.js.map} +0 -0
  707. /package/dist/{create-RL7PRIDY.js.map → create-W7L5B374.js.map} +0 -0
  708. /package/dist/{creatives-ESVH63AP.js.map → creatives-EPXJ2PDV.js.map} +0 -0
  709. /package/dist/{creatives-URHXATY6.js.map → creatives-PP6Z2T6Z.js.map} +0 -0
  710. /package/dist/{credentials-O6QSB7ZR.js.map → credentials-R4BZ76RD.js.map} +0 -0
  711. /package/dist/{critique-PTGGXRFG.js.map → critique-ICVRILIZ.js.map} +0 -0
  712. /package/dist/{critique-EWJBOCXQ.js.map → critique-OTIGYFZU.js.map} +0 -0
  713. /package/dist/{crm-GLPOO22Q.js.map → crm-5JFMA2YB.js.map} +0 -0
  714. /package/dist/{crm-F6RGNQH5.js.map → crm-PRTHRLXM.js.map} +0 -0
  715. /package/dist/{currency-CHBV6WIO.js.map → currency-BY647ZB7.js.map} +0 -0
  716. /package/dist/{customers-Q76FCWYO.js.map → customers-5EWPVKJV.js.map} +0 -0
  717. /package/dist/{delete-ODFDZCL3.js.map → delete-5EWH2SQQ.js.map} +0 -0
  718. /package/dist/{delete-OVMPDGWQ.js.map → delete-V2FBPIN7.js.map} +0 -0
  719. /package/dist/{delete-XN7N4S4H.js.map → delete-ZWUCKXI5.js.map} +0 -0
  720. /package/dist/{demographics-IY5RI55Z.js.map → demographics-2YCVAAPH.js.map} +0 -0
  721. /package/dist/{discard-GKIA5FML.js.map → discard-N7K3UQ7M.js.map} +0 -0
  722. /package/dist/{discover-ZU2DAV23.js.map → discover-TAJUFO5R.js.map} +0 -0
  723. /package/dist/{domain-WGXA7OXV.js.map → domain-YYTNWNSF.js.map} +0 -0
  724. /package/dist/{download-DYYNUGLX.js.map → download-JMJRYJ37.js.map} +0 -0
  725. /package/dist/{draft-EX2I6UJB.js.map → draft-KQACMPH2.js.map} +0 -0
  726. /package/dist/{draft-VYIRZO3E.js.map → draft-PENVOYCI.js.map} +0 -0
  727. /package/dist/{draft-R7BNWMBR.js.map → draft-RGSDXFFT.js.map} +0 -0
  728. /package/dist/{draft-EWGNZUU4.js.map → draft-SKEGKHIK.js.map} +0 -0
  729. /package/dist/{draft-GKI6MB7L.js.map → draft-UOMHLIVY.js.map} +0 -0
  730. /package/dist/{experiments-6DOKWFH4.js.map → experiments-W5D7ERVJ.js.map} +0 -0
  731. /package/dist/{facets-ZU5DT2QW.js.map → facets-FUNOZ6JS.js.map} +0 -0
  732. /package/dist/{feedback-RIUBM557.js.map → feedback-OVZFH7UV.js.map} +0 -0
  733. /package/dist/{feedback-record-3VVAUCOH.js.map → feedback-record-DKDR3XHH.js.map} +0 -0
  734. /package/dist/{fetch-T6TZCU74.js.map → fetch-QKP23NSX.js.map} +0 -0
  735. /package/dist/{fit-YPOHTM7Y.js.map → fit-PZPU2IZZ.js.map} +0 -0
  736. /package/dist/{flows-CKVEZFF2.js.map → flows-GBMZJX4R.js.map} +0 -0
  737. /package/dist/{fonts-3J3UVZ2E.js.map → fonts-2YY5465Q.js.map} +0 -0
  738. /package/dist/{forecast-JEAFUR2O.js.map → forecast-7B75GCRH.js.map} +0 -0
  739. /package/dist/{forecast-372Q6KQZ.js.map → forecast-VOND3WVO.js.map} +0 -0
  740. /package/dist/{funnel-FBTNPTS7.js.map → funnel-G4CMJ2C4.js.map} +0 -0
  741. /package/dist/{generate-JQIK3UYS.js.map → generate-SW5KLHXG.js.map} +0 -0
  742. /package/dist/{get-5N5FCGNH.js.map → get-44VNCDBQ.js.map} +0 -0
  743. /package/dist/{get-EXHUQT65.js.map → get-ZPJFKFHL.js.map} +0 -0
  744. /package/dist/{google-JHTOX6WM.js.map → google-VYARAUQH.js.map} +0 -0
  745. /package/dist/{google-ads-ZAYRCG2D.js.map → google-ads-BKDTCXUS.js.map} +0 -0
  746. /package/dist/{history-VNLS2TKB.js.map → history-7DF5HFJT.js.map} +0 -0
  747. /package/dist/{history-6J3XRNTZ.js.map → history-NEKVFRGQ.js.map} +0 -0
  748. /package/dist/{history-4ULZ4BVV.js.map → history-YU6HH574.js.map} +0 -0
  749. /package/dist/{hubspot-ZEHWWJHK.js.map → hubspot-Q3ZQODAX.js.map} +0 -0
  750. /package/dist/{ideas-SB6546GI.js.map → ideas-75LW4KBY.js.map} +0 -0
  751. /package/dist/{images-LEZYVE7R.js.map → images-7FS4KEGU.js.map} +0 -0
  752. /package/dist/{ingest-KNJCCIBG.js.map → ingest-MHH5OQP4.js.map} +0 -0
  753. /package/dist/{ingest-4OOTCOLO.js.map → ingest-S5OS6WIU.js.map} +0 -0
  754. /package/dist/{insights-XY6II7TX.js.map → insights-YVV5MHPQ.js.map} +0 -0
  755. /package/dist/{inspect-MHKEYNIC.js.map → inspect-PIFZILBU.js.map} +0 -0
  756. /package/dist/{inspiration-CSN3AXDD.js.map → inspiration-KL27O45N.js.map} +0 -0
  757. /package/dist/{intent-5QUPPZNI.js.map → intent-GIAQDMHF.js.map} +0 -0
  758. /package/dist/{keyword-gap-IG3EFLDH.js.map → keyword-gap-NZF75XGF.js.map} +0 -0
  759. /package/dist/{keyword-metrics-EL7MO3H6.js.map → keyword-metrics-H5M5I3N4.js.map} +0 -0
  760. /package/dist/{keywords-for-site-I7KJLZ2I.js.map → keywords-for-site-RILBDULX.js.map} +0 -0
  761. /package/dist/{landing-Z3QGJYM3.js.map → landing-H5KY6F7K.js.map} +0 -0
  762. /package/dist/{languages-LNHWSCMT.js.map → languages-GGNN7FEK.js.map} +0 -0
  763. /package/dist/{leads-WQCTZYKT.js.map → leads-WCWH4C73.js.map} +0 -0
  764. /package/dist/{learn-6KW6TUVL.js.map → learn-RUZUBNQZ.js.map} +0 -0
  765. /package/dist/{line-item-writes-B2KSP36W.js.map → line-item-writes-5Z3AEUV2.js.map} +0 -0
  766. /package/dist/{line-items-3ICE5DBI.js.map → line-items-IYSM2NEA.js.map} +0 -0
  767. /package/dist/{link-QRQ34ZDH.js.map → link-KRNL5O7Z.js.map} +0 -0
  768. /package/dist/{linkedin-D4RKHQPS.js.map → linkedin-GZIYAH4C.js.map} +0 -0
  769. /package/dist/{linkedin-person-Y5TCUOXS.js.map → linkedin-person-PMXUBPVL.js.map} +0 -0
  770. /package/dist/{list-XAMJSOGI.js.map → list-ALQGX6JI.js.map} +0 -0
  771. /package/dist/{list-6HZVHA6T.js.map → list-I37IE3NN.js.map} +0 -0
  772. /package/dist/{list-CHYJ53JD.js.map → list-JD5T6CGQ.js.map} +0 -0
  773. /package/dist/{locations-64JNCQID.js.map → locations-7RYEWKJO.js.map} +0 -0
  774. /package/dist/{locations-KVAAO7LD.js.map → locations-BU4ZGWAS.js.map} +0 -0
  775. /package/dist/{log-PLXGA74X.js.map → log-JWUFDOG6.js.map} +0 -0
  776. /package/dist/{make-EP4YSN26.js.map → make-QCGOTYNW.js.map} +0 -0
  777. /package/dist/{map-CAFMAMPP.js.map → map-EYKEY4VA.js.map} +0 -0
  778. /package/dist/{mcp-DDWSXLU7.js.map → mcp-P2PZCFFJ.js.map} +0 -0
  779. /package/dist/{media-sources-J5FXYPV5.js.map → media-sources-UUNS3LES.js.map} +0 -0
  780. /package/dist/{members-ZA7S5KWP.js.map → members-XTW5F5N5.js.map} +0 -0
  781. /package/dist/{metrics-MXGA3EFS.js.map → metrics-Z75Q2FHP.js.map} +0 -0
  782. /package/dist/{models-Z6SUHWKI.js.map → models-X2IXXAD6.js.map} +0 -0
  783. /package/dist/{normalize-ZHM2ZVXZ.js.map → normalize-P2UQIQOX.js.map} +0 -0
  784. /package/dist/{options-JTMDZECY.js.map → options-2OK4LBAD.js.map} +0 -0
  785. /package/dist/{organization-5OJEJEQV.js.map → organization-I5AIPZEH.js.map} +0 -0
  786. /package/dist/{performance-AHVTOYTM.js.map → performance-4UPNHWC2.js.map} +0 -0
  787. /package/dist/{performance-S273NSUB.js.map → performance-H5FJQBOP.js.map} +0 -0
  788. /package/dist/{pixels-H642RPK4.js.map → pixels-DBSPNHIE.js.map} +0 -0
  789. /package/dist/{promoted-tweet-writes-UF6LYMH4.js.map → promoted-tweet-writes-V5N5JDYQ.js.map} +0 -0
  790. /package/dist/{promoted-tweets-Z4GG6D7P.js.map → promoted-tweets-ZSNBS3QQ.js.map} +0 -0
  791. /package/dist/{publish-YQ6MHS7P.js.map → publish-M6U72N3H.js.map} +0 -0
  792. /package/dist/{query-FT2BA3WH.js.map → query-NMQKS4MY.js.map} +0 -0
  793. /package/dist/{reddit-YWYRZBL2.js.map → reddit-AZMVTHPR.js.map} +0 -0
  794. /package/dist/{refresh-TEXTTECA.js.map → refresh-42TJTJSN.js.map} +0 -0
  795. /package/dist/{release-3JDETBZI.js.map → release-VT6TNWUV.js.map} +0 -0
  796. /package/dist/{relevant-pages-OCHLUV5K.js.map → relevant-pages-JRIDJL4L.js.map} +0 -0
  797. /package/dist/{remove-KZTSU4K2.js.map → remove-YW25PRT4.js.map} +0 -0
  798. /package/dist/{reopen-GIJSFNDH.js.map → reopen-WGTMBOHK.js.map} +0 -0
  799. /package/dist/{rerun-6UZNOPUG.js.map → rerun-O7P5LMC4.js.map} +0 -0
  800. /package/dist/{research-XA2IJ2XV.js.map → research-IQWYPRBV.js.map} +0 -0
  801. /package/dist/{research-TMKG4NQJ.js.map → research-WYNVU26K.js.map} +0 -0
  802. /package/dist/{reset-7VL6WJLE.js.map → reset-4YPVS6QU.js.map} +0 -0
  803. /package/dist/{reset-HLZ6JHGY.js.map → reset-NF6K4NHK.js.map} +0 -0
  804. /package/dist/{resolve-H2QW3U5Y.js.map → resolve-GB4ORVSB.js.map} +0 -0
  805. /package/dist/{retry-MIZ67MPP.js.map → retry-LKJVOXVX.js.map} +0 -0
  806. /package/dist/{retry-WSWW6EJT.js.map → retry-W3NSNNDV.js.map} +0 -0
  807. /package/dist/{revenue-LTU7HRT2.js.map → revenue-KHUWJPMJ.js.map} +0 -0
  808. /package/dist/{rules-BGBCUUPH.js.map → rules-HMAONF3A.js.map} +0 -0
  809. /package/dist/{rules-add-SZT2MSOD.js.map → rules-add-BP5XSD23.js.map} +0 -0
  810. /package/dist/{run-XUDGECLL.js.map → run-EBCP5VIQ.js.map} +0 -0
  811. /package/dist/{run-FHGT4UQ7.js.map → run-QP7JP2H4.js.map} +0 -0
  812. /package/dist/{scaffold-ad-VXNO3SQP.js.map → scaffold-ad-JVDV7FET.js.map} +0 -0
  813. /package/dist/{scaffold-static-ad-FT55VV3T.js.map → scaffold-static-ad-VD3KXMHT.js.map} +0 -0
  814. /package/dist/{scaffold-video-V7WX5AWZ.js.map → scaffold-video-X3YR6APK.js.map} +0 -0
  815. /package/dist/{schedule-BNRLEFMZ.js.map → schedule-7OKUUJHO.js.map} +0 -0
  816. /package/dist/{scheduled-agents-MAXXXJ7W.js.map → scheduled-agents-N6FDAL7K.js.map} +0 -0
  817. /package/dist/{schema-YADPD54K.js.map → schema-6O6CJTT5.js.map} +0 -0
  818. /package/dist/{search-56ORG4PL.js.map → search-WGOCL2KW.js.map} +0 -0
  819. /package/dist/{select-DON4DMNM.js.map → select-6PVDRJQJ.js.map} +0 -0
  820. /package/dist/{set-prompt-J22TUCRU.js.map → set-prompt-EDM7CPME.js.map} +0 -0
  821. /package/dist/{setup-links-CHODCBYH.js.map → setup-links-Z2KIKKJM.js.map} +0 -0
  822. /package/dist/{shopify-FCYU4AR6.js.map → shopify-AANLSYQY.js.map} +0 -0
  823. /package/dist/{site-BF3Q26W5.js.map → site-6HHZJW2S.js.map} +0 -0
  824. /package/dist/{sources-VHHC6YQM.js.map → sources-72AAZL4C.js.map} +0 -0
  825. /package/dist/{sources-SLCYAWTZ.js.map → sources-VRWQ65G6.js.map} +0 -0
  826. /package/dist/{stale-GLVTL2ZK.js.map → stale-KO6NQVR4.js.map} +0 -0
  827. /package/dist/{status-E3RA644P.js.map → status-QRO7U5K2.js.map} +0 -0
  828. /package/dist/{studio-6ZXUKA4G.js.map → studio-OV2ZY5W3.js.map} +0 -0
  829. /package/dist/{sync-6QCDDJMO.js.map → sync-AQZ7JYEG.js.map} +0 -0
  830. /package/dist/{sync-definition-DXNHGY5E.js.map → sync-definition-OKSJA6MA.js.map} +0 -0
  831. /package/dist/{tags-KW7PG2TR.js.map → tags-5GFUNIIK.js.map} +0 -0
  832. /package/dist/{tags-MGV5KG6I.js.map → tags-DIFC2HFB.js.map} +0 -0
  833. /package/dist/{tags-TM27EIAL.js.map → tags-M26JKN2F.js.map} +0 -0
  834. /package/dist/{tags-AMZSQJJ2.js.map → tags-QFEG7LJV.js.map} +0 -0
  835. /package/dist/{tags-VWGKVGZD.js.map → tags-ZWYUQYWT.js.map} +0 -0
  836. /package/dist/{targeting-criteria-FT3G4HAW.js.map → targeting-criteria-UQMPM2K5.js.map} +0 -0
  837. /package/dist/{targets-XLVHWO6Z.js.map → targets-YCVILKKZ.js.map} +0 -0
  838. /package/dist/{testimonials-INXY7CXU.js.map → testimonials-SJQJDEK4.js.map} +0 -0
  839. /package/dist/{themes-R3A6IVQN.js.map → themes-RRLYZ46U.js.map} +0 -0
  840. /package/dist/{top-companies-MNX3GBCP.js.map → top-companies-LPYM65KX.js.map} +0 -0
  841. /package/dist/{transcript-GIAOWCTO.js.map → transcript-D2IQWUSP.js.map} +0 -0
  842. /package/dist/{translate-JEQ4K4AH.js.map → translate-CPDFHEI4.js.map} +0 -0
  843. /package/dist/{triggers-KDXLDZ23.js.map → triggers-543HDVJK.js.map} +0 -0
  844. /package/dist/{unlink-PNBSDLBQ.js.map → unlink-DQGU7K7V.js.map} +0 -0
  845. /package/dist/{unstage-X2PDLT5O.js.map → unstage-7UQU4MQT.js.map} +0 -0
  846. /package/dist/{update-TJTDFWER.js.map → update-DGIBKKIB.js.map} +0 -0
  847. /package/dist/{update-4JGHSQVZ.js.map → update-FEZ3EVTA.js.map} +0 -0
  848. /package/dist/{update-4XUQN4LK.js.map → update-QF6WBJU7.js.map} +0 -0
  849. /package/dist/{update-URU4TO2F.js.map → update-RY3GU5QI.js.map} +0 -0
  850. /package/dist/{upload-TO5EPTVD.js.map → upload-VMDGQ4HS.js.map} +0 -0
  851. /package/dist/{url-options-YZ6UG3NY.js.map → url-options-2TQCGD2W.js.map} +0 -0
  852. /package/dist/{url-params-533CWJH3.js.map → url-params-LMC2DRHP.js.map} +0 -0
  853. /package/dist/{validate-XF6HU7D4.js.map → validate-TLWEN4IL.js.map} +0 -0
  854. /package/dist/{videos-KYZ4CUOB.js.map → videos-GFOHRAJ7.js.map} +0 -0
  855. /package/dist/{viewer-check-U5GUU34Z.js.map → viewer-check-EKDFC7LQ.js.map} +0 -0
  856. /package/dist/{web-ZYMSMIV6.js.map → web-L7LF6FLF.js.map} +0 -0
  857. /package/dist/{winning-ads-BCN5RVAE.js.map → winning-ads-RUS4NE5C.js.map} +0 -0
  858. /package/dist/{write-commands-PZZ72PNL.js.map → write-commands-2JYDSXAX.js.map} +0 -0
  859. /package/dist/{x-DLEZYTAU.js.map → x-HLZUSGJT.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/landing/inspiration/scrape.ts","../src/engine/landing-library/proxyFailure.ts","../src/engine/landing-library/unreachable.ts","../src/engine/landing-library/blocked.ts","../src/engine/landing-library/run.ts","../../proxy/src/preflight.ts","../src/engine/landing-library/browser.ts","../src/engine/landing-library/usedCss.ts","../src/engine/landing-library/bundle.ts","../src/engine/landing-library/capture.ts","../src/engine/landing-library/escalation.ts","../src/engine/landing-library/fidelity.ts","../src/engine/landing-library/motion.ts","../src/engine/landing-library/motionTake.ts","../src/engine/landing-library/certificate.ts","../src/engine/landing-library/prepare.ts","../src/engine/landing-library/geometry.ts","../src/engine/landing-library/segment.ts","../src/engine/landing-library/renderBundle.ts","../src/engine/landing-library/report.ts","../src/engine/landing-library/types.ts","../src/commands/landing/inspiration/captureOut.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport {\n type CaptureFailureCode,\n CaptureFailureError,\n classifyCaptureFailure,\n} from \"../../../engine/landing-library/blocked.ts\";\nimport type { ScrapeManifest } from \"../../../engine/landing-library/run.ts\";\nimport { scrapeLanding } from \"../../../engine/landing-library/run.ts\";\nimport { captureBudgetMs, captureProxyCredentials } from \"../../../env.ts\";\nimport { writeJson } from \"../../../output.ts\";\nimport { registerSchema } from \"../../../schemas.ts\";\nimport { checkCaptureOut, findRepoRoot } from \"./captureOut.ts\";\nimport { INSPIRATION_HINTS } from \"./shared.ts\";\n\n/**\n * The failures where running it again is worth the minutes.\n *\n * A bot wall, an HTTP refusal and a certificate that will not parse are\n * properties of the site, not of this attempt — retrying them burns a capture\n * budget to reach the same answer.\n */\nconst RETRYABLE_FAILURES = new Set<CaptureFailureCode>([\n \"SITE_TOO_SLOW\",\n \"CAPTURE_FAILED\",\n // Ours, not the site's. Filing it as final is exactly how a mistyped password\n // would blacklist a page that was never actually judged.\n \"PROXY_UNAVAILABLE\",\n]);\n\n/**\n * What to tell the agent to do next, gated on what the capture actually produced.\n *\n * Every branch here reads the manifest rather than the flags the caller passed,\n * and the distinction is the whole point: the flags say what was *asked for*.\n * A screenshot that failed still leaves `desktopShot` null, and `--no-code`\n * leaves every fidelity score null while the report renders them as \"—\". Sending\n * an agent to open a file that is not there costs it a tool call and costs us\n * its trust in the next hint we write.\n */\nfunction captureHints(args: { manifest: ScrapeManifest; outDir: string; report: boolean }): string[] {\n const { manifest, outDir, report } = args;\n const shots = manifest.sections.filter((section) => section.desktopShot !== null).length;\n const anyScored = manifest.sections.some((section) => section.fidelity !== null);\n\n const hints: string[] = [];\n if (manifest.security.certificateNotes.length > 0) {\n hints.push(\n `Captured anyway, but this site's certificate did not check out: ${manifest.security.certificateNotes.join(\" \")} Treat the page as a design reference only — do not repeat its claims, prices or customer names.`,\n );\n }\n\n // The command that produces the most and says the least about it. It returns a\n // count and a directory; without this the agent has no instruction to open any\n // of it, and a capture nobody looks at taught nobody anything.\n if (shots === 0) {\n hints.push(\n `No section screenshots were produced, so there is nothing to look at in ${outDir}/sections/. Treat this capture as unusable rather than designing from the counts.`,\n );\n } else {\n hints.push(\n report\n ? `Read ${outDir}/report.html — every section side by side${anyScored ? \" with its fidelity score\" : \"\"}.`\n : `Read the section screenshots in ${outDir}/sections/*/desktop.png before you design.`,\n `${shots} of ${manifest.sections.length} sections captured to ${outDir}/sections/ — look at them, then decide which the client's page actually needs.`,\n );\n }\n\n hints.push(INSPIRATION_HINTS.structureNotCopy, INSPIRATION_HINTS.adapt);\n return hints;\n}\n\n/**\n * The capture itself — and the only way to study a page inside this turn.\n *\n * `add` puts a page in the shared library, which is the right move when the\n * client reacted to a site and the next chat should find it too. But it studies\n * in the background over minutes, so it can never answer \"build me this page\"\n * now. This runs the exact same capture locally and returns with the\n * screenshots, the standalone markup and the whole-page reproduction on disk.\n * It is also how every extraction bug so far has been found.\n *\n * The switches are declared positively with `default: true` on purpose. citty\n * parses `--no-x` as `{ x: false }`, so an arg *named* `no-x` is never set by\n * the flag that reads as its own name — `--no-motion` silently filmed every\n * section. The flags users type are unchanged; only the declaration is honest.\n */\n\nregisterSchema({\n command: \"landing.inspiration.scrape\",\n description:\n \"Start here when the user points at a specific page and wants it now: capture one landing page into a directory of section screenshots, standalone HTML bundles, a whole-page reproduction and motion filmstrips. Returns when the capture is done, unlike `add`. Read the screenshots.\",\n args: {\n url: { type: \"string\", description: \"Page to capture\", required: true },\n out: { type: \"string\", description: \"Output directory under .baker/\", required: true },\n mobile: { type: \"boolean\", description: \"Phone-viewport pass. `--no-mobile` to skip\", required: false },\n code: {\n type: \"boolean\",\n description: \"Standalone HTML+CSS bundles and fidelity scores. `--no-code` to segment and screenshot only\",\n required: false,\n },\n motion: {\n type: \"boolean\",\n description: \"Film sections that move. `--no-motion` to skip — the single biggest lever on runtime\",\n required: false,\n },\n report: { type: \"boolean\", description: \"Write report.html. `--no-report` to skip\", required: false },\n },\n});\n\nexport const scrapeCommand = defineCommand({\n meta: {\n name: \"scrape\",\n description:\n \"Capture a landing page to a directory, now. Example: baker landing inspiration scrape https://linear.app --out .baker/inspiration/linear.app\",\n },\n args: {\n url: { type: \"positional\", description: \"Page to capture\", required: true },\n out: { type: \"string\", description: \"Output directory, under .baker/\", required: true },\n mobile: {\n type: \"boolean\",\n description: \"Phone-viewport pass (--no-mobile to skip)\",\n required: false,\n default: true,\n },\n code: { type: \"boolean\", description: \"Bundles + fidelity (--no-code to skip)\", required: false, default: true },\n motion: {\n type: \"boolean\",\n description: \"Film moving sections (--no-motion to skip)\",\n required: false,\n default: true,\n },\n report: { type: \"boolean\", description: \"Write report.html (--no-report to skip)\", required: false, default: true },\n },\n run: async ({ args }) => {\n // Before the minutes, not after them: a capture that lands in a tracked\n // directory is paid for in every future clone of this workspace, and the\n // only moment that can still be changed for free is this one.\n const location = checkCaptureOut(args.out as string, {\n cwd: process.cwd(),\n repoRoot: findRepoRoot(process.cwd()),\n });\n if (!location.ok) {\n writeJson({ ok: false, error: location.error });\n process.exit(1);\n }\n\n try {\n const manifest = await scrapeLanding({\n url: args.url as string,\n outDir: args.out as string,\n mobile: args.mobile as boolean,\n code: args.code as boolean,\n motion: args.motion as boolean,\n report: args.report as boolean,\n // Both come from the environment, never from a flag — see their docs in\n // `src/env.ts`. Absent credentials this is the direct route only, which\n // is exactly the behaviour that shipped before the ladder existed.\n proxyCredentials: captureProxyCredentials(),\n budgetMs: captureBudgetMs() ?? undefined,\n // Progress goes to stderr so stdout stays a clean JSON envelope.\n onProgress: (message) => process.stderr.write(`${message}\\n`),\n });\n\n const scored = manifest.sections\n .map((section) => section.fidelity)\n .filter((value): value is number => value !== null)\n .sort((a, b) => a - b);\n\n writeJson({\n ok: true,\n data: {\n title: manifest.title,\n sections: manifest.sections.length,\n medianFidelity: scored.length > 0 ? scored[Math.floor(scored.length / 2)] : null,\n pageFidelity: manifest.page.fidelity,\n out: args.out as string,\n report: args.report ? `${args.out as string}/report.html` : null,\n // Never omitted, and that is the point: an envelope without it is a\n // capture that ran a build predating the ladder, which is otherwise\n // indistinguishable from one that took the direct route and is the\n // exact silence the E2B template rebuild is easy to forget about.\n capture_tier: manifest.captureTier,\n // Compact by default, but never omitted: a capture that could not\n // verify who served the page is worth less as evidence, and the\n // reader has to be told without going looking for it.\n certificate_verified: false,\n ...(manifest.security.certificateNotes.length > 0\n ? { certificate_notes: manifest.security.certificateNotes }\n : {}),\n },\n hints: captureHints({ manifest, outDir: args.out as string, report: args.report as boolean }),\n });\n } catch (error) {\n // Every capture failure is a refusal, not a crash: it leaves with a code\n // from the closed set and a sentence written for a person. Nothing here\n // may print what the browser said — `arcus.so` filed\n // `page.goto: net::ERR_SSL_PROTOCOL_ERROR` as its user-facing message\n // precisely because this branch only recognised one kind of failure and\n // handed the rest to the generic reporter.\n const failure = classifyCaptureFailure(error);\n // The diagnostic goes to stderr, where the ingest job logs it and stdout\n // stays a clean envelope. It is deliberately not in `error.message`.\n process.stderr.write(`[landing.inspiration.scrape] ${failure.code}: ${String(error)}\\n`);\n writeJson({\n ok: false,\n error: {\n code: failure.code,\n message: failure.message,\n // Which addresses were tried and what each was told. One rung means\n // the failure was final wherever we stood; three mean the page turned\n // us away from three different places, which is a fact about the page.\n // **Absent** means this Runtime is running a CLI that predates the\n // ladder — the one way the rollout fails without anything looking\n // wrong.\n ...(error instanceof CaptureFailureError && error.rungs.length > 0 ? { rungs: error.rungs } : {}),\n // Degrade, don't abort: one unreadable reference is never a reason to\n // abandon the job it was research for. `retryable` is the decision\n // the agent would otherwise have to guess at.\n fix: RETRYABLE_FAILURES.has(failure.code)\n ? {\n action: \"Retry once with --no-motion, which is roughly half the work.\",\n explanation:\n \"This looks temporary. If the second attempt fails too, carry on with the references you can reach and tell the user this one page was unavailable.\",\n retryable: true,\n }\n : {\n action: \"Do not retry this page — work from the references you can reach.\",\n explanation:\n \"This page cannot be read by an automated reader, and running it again will fail the same way. Tell the user this one page was unavailable and continue with the rest.\",\n retryable: false,\n },\n },\n });\n process.exit(1);\n }\n },\n});\n","import type { CaptureFailure } from \"./blocked.ts\";\n\n/**\n * Our route is broken — not the site.\n *\n * Kept apart from `describeUnreachableSite` on purpose. That function answers\n * \"whose fault is it that we never saw a page\", and every sentence in its table\n * blames the site. Worse, it claims *any* `net::` name it does not recognise\n * and files it as `SITE_UNREACHABLE`, which the corpus records as never worth\n * re-running. A tunnel that would not open is ours, so letting it fall through\n * there would permanently blacklist a perfectly good page because we mistyped a\n * password.\n *\n * A caveat measured against the live endpoints, and the reason the CONNECT\n * preflight in `@baker/proxy/preflight` exists: the *most likely* proxy failure\n * — rejected credentials — does not produce any of these codes. Chromium takes\n * the 407, waits for a credential it will never accept, and dies on the page\n * timeout, so Playwright reports a plain `Timeout 25000ms exceeded`. This\n * classifier catches the tunnel and auth-prompt cases; the preflight is what\n * catches a wrong password, before a browser is ever launched.\n */\n\n/**\n * `407` never comes from an origin server — only something speaking proxy\n * produces one — so matching it needs no \"was this attempt proxied\" flag.\n */\nexport const PROXY_STATUS = 407;\n\nconst PROXY_NET_ERRORS = [\n \"ERR_TUNNEL_CONNECTION_FAILED\",\n \"ERR_PROXY_CONNECTION_FAILED\",\n \"ERR_PROXY_AUTH_REQUESTED\",\n \"ERR_PROXY_CERTIFICATE_INVALID\",\n \"ERR_UNEXPECTED_PROXY_AUTH\",\n \"ERR_MANDATORY_PROXY_CONFIGURATION_FAILED\",\n \"ERR_HTTPS_PROXY_TUNNEL_RESPONSE_REDIRECT\",\n];\n\n/**\n * Deliberately says nothing about proxies.\n *\n * The reader is a marketer who added a page. \"How we reach the internet\" is not\n * a concept they have, cannot act on, and should never be handed. It is\n * retryable, and by the time they retry the route may well be fixed.\n */\nexport const PROXY_UNAVAILABLE_MESSAGE = \"We couldn't reach this page just now. Please try adding it again.\";\n\nexport function describeProxyFailure(error: unknown): CaptureFailure | null {\n const raw = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n if (!raw) return null;\n const netError = /net::(ERR_[A-Z0-9_]+)/.exec(raw)?.[1];\n if (!netError || !PROXY_NET_ERRORS.includes(netError)) return null;\n return { code: \"PROXY_UNAVAILABLE\", message: PROXY_UNAVAILABLE_MESSAGE };\n}\n","/**\n * Say why we never reached the page, in words a marketer can act on.\n *\n * `detectBlockedPage` needs a page to inspect. When the navigation itself fails\n * there is no page — Playwright throws, and its message is a call log\n * (`page.goto: net::ERR_SSL_PROTOCOL_ERROR at https://arcus.so/ Call log: …`).\n * That string used to travel intact to the inspiration page, because the ingest\n * job trusts any error envelope the CLI prints as product language. This turns\n * the one useful token in it — Chromium's `net::ERR_*` code — into a sentence,\n * so the envelope stays trustworthy and the user learns whose problem it is.\n */\n\n/**\n * Product-language reason a navigation never produced a page.\n *\n * The code is part of the answer, not a constant: a site that never answered\n * and a site that answered too slowly get the same *kind* of explanation but\n * not the same verdict — `SITE_TOO_SLOW` is worth running again and\n * `SITE_UNREACHABLE` is not, and the retry surface reads exactly this field to\n * decide. Returning one code with a too-slow sentence attached would put the\n * two back into one bucket by the back door.\n */\nexport interface UnreachableSite {\n code: \"SITE_UNREACHABLE\" | \"SITE_TOO_SLOW\";\n message: string;\n}\n\n/**\n * Chromium net errors, grouped by what the user should conclude.\n *\n * Prefix matches: `ERR_SSL_` covers the whole family without listing it, and a\n * code we have never seen still lands on the generic line rather than leaking.\n */\nconst NET_ERROR_REASONS: ReadonlyArray<{ prefixes: readonly string[]; message: string }> = [\n {\n prefixes: [\"ERR_NAME_NOT_RESOLVED\", \"ERR_NAME_RESOLUTION_FAILED\"],\n message: \"We couldn't find this site — check the address is spelled right.\",\n },\n {\n prefixes: [\"ERR_SSL_\", \"ERR_CERT_\", \"ERR_TLS_\", \"ERR_BAD_SSL_\"],\n message:\n \"This site's secure connection is broken, so no browser can open it — including ours. That's a fault on their side, not something you can fix here.\",\n },\n {\n prefixes: [\"ERR_TOO_MANY_REDIRECTS\"],\n message: \"This site kept redirecting us and never settled on a page.\",\n },\n {\n prefixes: [\"ERR_BLOCKED_BY_\", \"ERR_ACCESS_DENIED\"],\n message: \"This site refused our visit, so we couldn't read the page.\",\n },\n {\n prefixes: [\n \"ERR_CONNECTION_\",\n \"ERR_ADDRESS_UNREACHABLE\",\n \"ERR_EMPTY_RESPONSE\",\n \"ERR_NETWORK_CHANGED\",\n \"ERR_INTERNET_DISCONNECTED\",\n \"ERR_SOCKET_NOT_CONNECTED\",\n \"ERR_TIMED_OUT\",\n ],\n // No \"try again later\" here. This resolves to `SITE_UNREACHABLE`, which the\n // corpus files as not worth re-running, so inviting a retry would promise\n // something the retry surface then declines to do.\n message: \"This site didn't respond, so we couldn't read the page.\",\n },\n];\n\nconst GENERIC_UNREACHABLE = \"We couldn't open this site, so there was no page to study.\";\nconst TOO_SLOW = \"This site took too long to load, so we stopped waiting. Try again later.\";\n\n/**\n * Is this a \"we never got a page\" failure, and how do we say so?\n *\n * Returns null for anything else — a bug in our own capture must stay a crash\n * and reach the generic handler, not be dressed up as the site's fault.\n */\nexport function describeUnreachableSite(error: unknown): UnreachableSite | null {\n const raw = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n if (!raw) return null;\n\n const netError = /net::(ERR_[A-Z0-9_]+)/.exec(raw)?.[1];\n if (netError) {\n const reason = NET_ERROR_REASONS.find((candidate) =>\n candidate.prefixes.some((prefix) => netError.startsWith(prefix)),\n );\n return { code: \"SITE_UNREACHABLE\", message: reason?.message ?? GENERIC_UNREACHABLE };\n }\n\n // Playwright's own navigation timeout carries no net:: code. Checked after\n // the net:: table on purpose: an aborted TLS handshake can also end in a\n // timeout, and \"their certificate is broken\" is the more useful of the two\n // answers — and the more accurate verdict, since it will not fix itself.\n if (/Timeout \\d+ms exceeded/.test(raw) || raw.includes(\"page.goto: Timeout\")) {\n return { code: \"SITE_TOO_SLOW\", message: TOO_SLOW };\n }\n\n return null;\n}\n\n/**\n * Chromium's error name, or null — the one stable token in a Playwright call log.\n *\n * Exported so the escalation ladder can decide from the code itself rather than\n * from the sentence this module turns it into. A sentence is for a person; the\n * code is what says whether a different exit IP would change the answer.\n */\nexport function netErrorName(error: unknown): string | null {\n const raw = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n return raw ? (/net::(ERR_[A-Z0-9_]+)/.exec(raw)?.[1] ?? null) : null;\n}\n","/**\n * Refuse to study a page we were never actually shown.\n *\n * A bot filter's block page is still a page: it segments cleanly, it screenshots\n * beautifully, and it reproduces at fidelity 1.00 because there is nothing\n * dynamic about it. Magnific's is a full-bleed lava render that would classify\n * as a striking dark hero with a high craft score. Nothing downstream can tell\n * the difference — fidelity measures whether we copied the page correctly, not\n * whether it was the right page — so the check has to happen here, at capture.\n */\n\nimport { describeProxyFailure, PROXY_STATUS, PROXY_UNAVAILABLE_MESSAGE } from \"./proxyFailure.ts\";\nimport { describeUnreachableSite } from \"./unreachable.ts\";\n\nexport interface BlockedPage {\n code: \"HTTP_ERROR\" | \"BOT_CHALLENGE\" | \"PROXY_UNAVAILABLE\";\n /** Product-language reason; surfaces to the user verbatim. */\n message: string;\n}\n\n/**\n * Why a capture ended without a page.\n *\n * A closed set, and the only thing the ingest pipeline is allowed to file a\n * failure under. The two block codes come from `detectBlockedPage`; the rest\n * classify what the browser threw.\n */\nexport type CaptureFailureCode = BlockedPage[\"code\"] | \"SITE_UNREACHABLE\" | \"SITE_TOO_SLOW\" | \"CAPTURE_FAILED\";\n\nexport interface CaptureFailure {\n code: CaptureFailureCode;\n /** Product language, always. A marketer reads this; no engine internals. */\n message: string;\n}\n\n/**\n * Phrases that only appear on a block or challenge page.\n *\n * Deliberately specific. \"Access denied\" alone would match a page *about*\n * access control, so each phrase is one a real marketing page has no reason to\n * use as its title.\n */\nconst CHALLENGE_PHRASES = [\n \"just a moment\",\n \"attention required\",\n \"verify you are human\",\n \"checking your browser\",\n \"enable javascript and cookies to continue\",\n \"unusual traffic\",\n \"access denied\",\n \"you have been blocked\",\n \"request unsuccessful\",\n \"are you a robot\",\n \"security check\",\n \"ddos protection\",\n \"captcha\",\n];\n\n/** Vendors whose block pages we would otherwise happily catalogue. */\nconst CHALLENGE_MARKERS = [\"cf-browser-verification\", \"cf_chl_\", \"px-captcha\", \"_incapsula_\", \"distil_r_captcha\"];\n\nexport function detectBlockedPage(page: {\n status: number | null;\n title: string;\n bodyText: string;\n html?: string;\n}): BlockedPage | null {\n // Checked before the generic 4xx branch: only something speaking proxy\n // produces a 407, so it can never be the origin's opinion of us. Left to fall\n // through, it would be filed as HTTP_ERROR → `site_refused`, which is not\n // retryable — permanently blacklisting a good page over our own credentials.\n if (page.status === PROXY_STATUS) {\n return { code: \"PROXY_UNAVAILABLE\", message: PROXY_UNAVAILABLE_MESSAGE };\n }\n\n if (page.status !== null && page.status >= 400) {\n return {\n code: \"HTTP_ERROR\",\n message: `The site returned ${page.status} instead of the page — it may be blocking automated visits.`,\n };\n }\n\n // A challenge can arrive with a 200, so the status check alone is not enough.\n const haystack = `${page.title}\\n${page.bodyText.slice(0, 2000)}`.toLowerCase();\n const phrase = CHALLENGE_PHRASES.find((candidate) => haystack.includes(candidate));\n if (phrase) {\n return { code: \"BOT_CHALLENGE\", message: \"The site showed a security check instead of the page.\" };\n }\n\n const html = page.html?.toLowerCase() ?? \"\";\n if (CHALLENGE_MARKERS.some((marker) => html.includes(marker))) {\n return { code: \"BOT_CHALLENGE\", message: \"The site showed a security check instead of the page.\" };\n }\n\n return null;\n}\n\n/** Thrown by the capture so the caller can report it as a refusal, not a crash. */\nexport class BlockedPageError extends Error {\n readonly code: BlockedPage[\"code\"];\n\n constructor(blocked: BlockedPage) {\n super(blocked.message);\n this.name = \"BlockedPageError\";\n this.code = blocked.code;\n }\n}\n\n/**\n * Thrown when a verdict has already been reached and must not be re-derived.\n *\n * The escalation ladder decides *which* attempt's failure the page is recorded\n * under — deliberately never the proxy's, so our own broken route cannot\n * blacklist a good page. Re-classifying that decision from an error string\n * downstream would throw the choice away, so it travels as a value.\n */\n/** One rung, as reported outward: no credential, no host, no browser text. */\nexport interface RungReport {\n readonly tier: \"direct\" | \"datacenter\" | \"residential\";\n readonly code: string;\n readonly status: number | null;\n}\n\nexport class CaptureFailureError extends Error {\n readonly failure: CaptureFailure;\n /**\n * Which rungs were tried, and what each of them said.\n *\n * Carried out of the engine because nothing downstream could otherwise tell a\n * page refused from three different addresses apart from one refused once —\n * and those two call for opposite conclusions about whether to try again.\n *\n * It is also the only way to see the rollout fail silently. The E2B image\n * installs the CLI at build time, so until the template is rebuilt a Runtime\n * runs an older binary that ignores the credentials Convex hands it. That\n * capture returns an envelope with **no rungs at all** — indistinguishable,\n * from the outside, from a page that simply was not worth escalating.\n *\n * Deliberately thin: tier names and status codes only, so nothing here can\n * carry a credential or the raw browser text that once reached a user.\n */\n readonly rungs: readonly RungReport[];\n\n constructor(failure: CaptureFailure, rungs: readonly RungReport[] = []) {\n super(failure.message);\n this.name = \"CaptureFailureError\";\n this.failure = failure;\n this.rungs = rungs;\n }\n}\n\n/**\n * The same sentence the backend uses for a private address.\n *\n * Duplicated rather than shared because that copy lives in Convex and this one\n * runs in the sandbox, with no import path between them — the same reason the\n * challenge-phrase list is duplicated. Keep them in step by hand.\n */\nexport const LOCAL_ADDRESS_REFUSAL =\n \"That address only opens from inside your own network, so there is nothing there for us to read. A reference page has to be live on the web.\";\n\n/**\n * The failures that never reach Chromium, so never carry a `net::` code.\n *\n * `describeUnreachableSite` reads Chromium's vocabulary and covers every\n * navigation that got as far as the browser. These are the ones that did not:\n * Node's own socket and DNS errors, thrown before or around the browser rather\n * than by it. Kept as substrings because, unlike a `net::` name, they have no\n * single stable position in the message.\n */\nconst NODE_LEVEL_UNREACHABLE = [\"econnrefused\", \"enotfound\", \"getaddrinfo\"];\n\nconst UNREACHABLE_MESSAGE =\n \"We couldn't reach this page — the site didn't answer, or its security certificate isn't one we can read.\";\nconst TOO_SLOW_MESSAGE = \"This page took too long to load, so we stopped waiting for it.\";\nconst CAPTURE_FAILED_MESSAGE = \"We couldn't read this page.\";\n\n/**\n * Turn whatever the capture threw into something a person can be told.\n *\n * The reason this exists: `arcus.so` filed the string\n * `page.goto: net::ERR_SSL_PROTOCOL_ERROR at https://arcus.so/` as its\n * user-facing failure, because the only shape the ingest pipeline recognised\n * was \"the command printed an error envelope\", and every envelope's message was\n * trusted verbatim — including the one carrying a raw Playwright call. A closed\n * set of codes, each with its own sentence, is what stops the next raw string\n * reaching a marketer, and what lets a retry be *decided* rather than guessed:\n * a certificate that will not parse is not worth re-running, a timeout is.\n */\nexport function classifyCaptureFailure(error: unknown): CaptureFailure {\n // A verdict the ladder already reached. Re-deriving it from the message would\n // discard the choice of *which* attempt to blame.\n if (error instanceof CaptureFailureError) return error.failure;\n\n if (error instanceof BlockedPageError) {\n // Already product language, and more specific than anything invented here.\n return { code: error.code, message: error.message };\n }\n\n // Chromium's `net::` name is the one stable token in a Playwright call log,\n // and `describeUnreachableSite` turns it into a sentence that says *which*\n // fault it was — a name that would not resolve, a certificate no browser\n // would accept, a redirect loop. That is a better answer than one blanket\n // \"we couldn't reach it\", so it is asked first.\n // Asked BEFORE `describeUnreachableSite`, which claims any `net::` name it\n // does not recognise and blames the site for it. A tunnel that would not open\n // is ours, and filing it against the page makes the page unretryable forever.\n const proxyFailure = describeProxyFailure(error);\n if (proxyFailure) return proxyFailure;\n\n const unreachable = describeUnreachableSite(error);\n if (unreachable) return unreachable;\n\n const message = (error instanceof Error ? error.message : String(error)).toLowerCase();\n\n if (NODE_LEVEL_UNREACHABLE.some((marker) => message.includes(marker))) {\n return { code: \"SITE_UNREACHABLE\", message: UNREACHABLE_MESSAGE };\n }\n if (message.includes(\"timeout\") && message.includes(\"exceeded\")) {\n return { code: \"SITE_TOO_SLOW\", message: TOO_SLOW_MESSAGE };\n }\n\n return { code: \"CAPTURE_FAILED\", message: CAPTURE_FAILED_MESSAGE };\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ProxyCredentials, ProxyRoute, ProxyTier } from \"@baker/proxy\";\nimport { plannedRoutes, refuseNonPublicUrl } from \"@baker/proxy\";\n// Subpath, not the barrel: this reaches for `node:http`, which only a Node\n// runtime may bundle. The CLI is one; Convex's V8 runtime is not.\nimport { preflightProxyRoute } from \"@baker/proxy/preflight\";\nimport type { Browser, BrowserContext, Page } from \"playwright\";\nimport {\n BlockedPageError,\n CaptureFailureError,\n classifyCaptureFailure,\n detectBlockedPage,\n LOCAL_ADDRESS_REFUSAL,\n type RungReport,\n} from \"./blocked.ts\";\nimport { DESKTOP_VIEWPORT, launchBrowser, MOBILE_VIEWPORT, newPage } from \"./browser.ts\";\nimport { buildSectionBundle } from \"./bundle.ts\";\nimport { captureSection, captureSectionOnMobile } from \"./capture.ts\";\nimport type { CaptureSecurity } from \"./certificate.ts\";\nimport {\n type AttemptOutcome,\n ambiguousProxyTimeout,\n asProxyFailure,\n CAPTURE_RESERVE_MS,\n nextRoute,\n reportableFailure,\n} from \"./escalation.ts\";\nimport { scoreFidelity } from \"./fidelity.ts\";\nimport { collectMotion, isWorthFilming, type MotionDescriptor } from \"./motion.ts\";\nimport { captureMotionTake } from \"./motionTake.ts\";\nimport { blockConsentManagers, preparePage } from \"./prepare.ts\";\nimport { renderBundleToPng } from \"./renderBundle.ts\";\nimport { writeCaptureReport } from \"./report.ts\";\nimport { installPageRuntime, segmentPage } from \"./segment.ts\";\nimport { DEFAULT_SEGMENT_OPTIONS, type SectionCandidate } from \"./types.ts\";\nimport { netErrorName } from \"./unreachable.ts\";\nimport { perceptualHash } from \"./visualHash.ts\";\n\nexport interface ScrapeOptions {\n url: string;\n outDir: string;\n timeoutMs?: number;\n mobile?: boolean;\n /** Skip the reproduction bundle + fidelity pass (segmentation only). */\n code?: boolean;\n /** Skip filming sections that move. The single biggest lever on runtime. */\n motion?: boolean;\n /** Also write `report.html` — the side-by-side page you check the capture with. */\n report?: boolean;\n /**\n * Routes the capture may escalate to when a page refuses us. Absent means\n * direct only, which is exactly how this behaved before the ladder existed.\n */\n proxyCredentials?: ProxyCredentials;\n /**\n * Wall clock the whole capture may spend, from the first navigation.\n *\n * Distinct from `timeoutMs`, which bounds a single navigation. Without this\n * the ladder cannot tell whether it can afford the rung it is about to climb,\n * and would be killed mid-capture by the caller instead of declining.\n */\n budgetMs?: number;\n onProgress?: (message: string) => void;\n}\n\nexport interface ScrapedSection extends SectionCandidate {\n desktopShot: string | null;\n mobileShot: string | null;\n bundle: string | null;\n /** 0..1 re-render match; null when the bundle couldn't be rendered at all. */\n fidelity: number | null;\n fidelityNote?: string;\n cssStats?: { totalRules: number; keptRules: number; fontFaces: number; keyframes: number };\n motion: MotionDescriptor;\n /** Contact sheet of the section revealing itself; absent when it doesn't move. */\n motionFilmstrip: string | null;\n /** dHash of the desktop screenshot — how repeats of one site's chrome are found. */\n visualHash: string | null;\n}\n\nexport interface ScrapeManifest {\n url: string;\n finalUrl: string;\n title: string;\n documentHeight: number;\n viewport: { width: number; height: number };\n capturedAt: string;\n sections: ScrapedSection[];\n /** Whole-page reproduction, built by the same extractor rooted at `<body>`. */\n page: PageReproduction;\n /**\n * What we were served and what we chose not to check.\n *\n * On the manifest rather than only in a log because the manifest *is* the\n * captured record: anyone reading this capture later — an agent, the ingest\n * pipeline, a person opening the directory — is entitled to know the capture\n * did not validate the certificate before deciding what the page proves.\n */\n security: CaptureSecurity;\n /**\n * Which rung of the escalation ladder actually served this page.\n *\n * The whole of the ladder's observability, and deliberately a plain field\n * rather than a metric: Oxylabs bills per gigabyte and we cannot measure bytes\n * per capture, so the only honest question is *how much of the corpus needed a\n * paid exit at all* — and that is a count, on rows we already keep. `direct`\n * on nearly everything is the answer this feature is supposed to produce.\n */\n captureTier: CaptureTier;\n}\n\n/** The rung that served a capture. `direct` costs nothing and should dominate. */\nexport type CaptureTier = \"direct\" | ProxyTier;\n\nexport interface PageReproduction {\n bundle: string | null;\n fidelity: number | null;\n fidelityNote?: string;\n}\n\n/**\n * Rebuild the entire page as one standalone file.\n *\n * This is the honest end-to-end check on the extractor: a section can score\n * well while the page-level cascade it depended on quietly went missing, and\n * only reassembling the whole thing surfaces that. It is also the artifact to\n * hand over when the ask is \"reproduce this page\", rather than stitching\n * sixteen separately-scoped bundles back together and hoping their `:root`\n * blocks agree.\n */\nasync function reproducePage(args: {\n browser: Browser;\n page: Page;\n outDir: string;\n pageUrl: string;\n livePageShot: Buffer | null;\n}): Promise<PageReproduction> {\n const { browser, page, outDir, pageUrl, livePageShot } = args;\n const built = await buildSectionBundle(page, \"body\", pageUrl).catch(() => null);\n if (!built) return { bundle: null, fidelity: null };\n\n await writeFile(path.join(outDir, \"page.html\"), built.html);\n const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width, {\n wholePage: true,\n timeoutMs: 60_000,\n });\n if (!rendered || !livePageShot) return { bundle: \"page.html\", fidelity: null };\n\n await writeFile(path.join(outDir, \"page-rendered.png\"), rendered);\n const { score, note } = await scoreFidelity(livePageShot, rendered);\n return { bundle: \"page.html\", fidelity: score, ...(note ? { fidelityNote: note } : {}) };\n}\n\n/**\n * Capture one section: screenshot, reproduction bundle, and the fidelity score\n * that says how much to trust the bundle.\n */\nasync function captureOneSection(args: {\n browser: Browser;\n page: Page;\n candidate: SectionCandidate;\n sectionsDir: string;\n outDir: string;\n pageUrl: string;\n withCode: boolean;\n}): Promise<ScrapedSection> {\n const { browser, page, candidate, sectionsDir, outDir, pageUrl, withCode } = args;\n const dir = path.join(sectionsDir, String(candidate.index).padStart(2, \"0\"));\n await mkdir(dir, { recursive: true });\n\n const desktop = await captureSection(page, candidate);\n if (desktop) await writeFile(path.join(dir, \"desktop.png\"), desktop);\n const visualHash = desktop ? await perceptualHash(desktop) : null;\n\n const motion = await collectMotion(page, candidate.selector);\n\n const built = withCode ? await buildSectionBundle(page, candidate.selector, pageUrl) : null;\n let fidelity: number | null = null;\n let fidelityNote: string | undefined;\n\n if (built) {\n await writeFile(path.join(dir, \"section.html\"), built.html);\n const rendered = await renderBundleToPng(browser, built.html, DESKTOP_VIEWPORT.width);\n if (rendered && desktop) {\n await writeFile(path.join(dir, \"section-rendered.png\"), rendered);\n const result = await scoreFidelity(desktop, rendered);\n fidelity = result.score;\n fidelityNote = result.note;\n }\n }\n\n return {\n ...candidate,\n desktopShot: desktop ? path.relative(outDir, path.join(dir, \"desktop.png\")) : null,\n mobileShot: null,\n bundle: built ? path.relative(outDir, path.join(dir, \"section.html\")) : null,\n fidelity,\n ...(fidelityNote ? { fidelityNote } : {}),\n ...(built ? { cssStats: built.stats } : {}),\n motion,\n motionFilmstrip: null,\n visualHash,\n };\n}\n\n/**\n * Re-shoot every section on a phone viewport.\n *\n * Only the selector carries over from the desktop pass — the layout reflows, so\n * the measured rect is meaningless here.\n */\nasync function captureMobileShots(args: {\n browser: Browser;\n sections: ScrapedSection[];\n sectionsDir: string;\n outDir: string;\n pageUrl: string;\n timeoutMs: number;\n}): Promise<void> {\n const { browser, sections, sectionsDir, outDir, pageUrl, timeoutMs } = args;\n const mobile = await newPage(browser, MOBILE_VIEWPORT);\n try {\n await blockConsentManagers(mobile.page);\n await installPageRuntime(mobile.page);\n await preparePage(mobile.page, pageUrl, timeoutMs);\n for (const section of sections) {\n const shot = await captureSectionOnMobile(mobile.page, section);\n if (!shot) continue;\n const file = path.join(sectionsDir, String(section.index).padStart(2, \"0\"), \"mobile.png\");\n await writeFile(file, shot);\n section.mobileShot = path.relative(outDir, file);\n }\n } finally {\n await mobile.context.close();\n }\n}\n\n/**\n * How many sections film at once.\n *\n * Each take is a fresh context loading the whole page again — that is not\n * wasteful, it is the only way to catch an entrance animation before it fires,\n * since a section already scrolled past films as a still. But it means filming\n * costs one full page load *per moving section*, serially, and that dominates\n * everything else: measured on column.com, filming ran 145s → 556s of a 556s\n * capture, 74% of the run for 10 sections at ~40s each. That is what put the\n * page over the ingest's action budget and made it un-studiable.\n *\n * Takes are independent — separate contexts, no shared state — so overlapping\n * them is free correctness-wise. Three rather than all of them because each\n * holds a live Chromium context, and the sandbox this runs in is not large.\n */\nconst MOTION_CONCURRENCY = 3;\n\n/**\n * Film the sections that move.\n *\n * Gated on the descriptor rather than run everywhere: a motion take needs its\n * own page load with animation enabled, and on a static section it produces six\n * identical frames.\n */\nasync function captureMotionTakes(args: {\n browser: Browser;\n sections: ScrapedSection[];\n sectionsDir: string;\n outDir: string;\n pageUrl: string;\n log: (message: string) => void;\n}): Promise<void> {\n const { browser, sections, sectionsDir, outDir, pageUrl, log } = args;\n const moving = sections.filter((section) => isWorthFilming(section.motion));\n if (moving.length === 0) return;\n log(`filming ${moving.length} moving sections`);\n\n const filmOne = async (section: ScrapedSection): Promise<void> => {\n // One section that cannot be filmed must not cost the rest their takes.\n const take = await captureMotionTake(browser, pageUrl, section.selector).catch(() => null);\n if (!take) return;\n const dir = path.join(sectionsDir, String(section.index).padStart(2, \"0\"));\n const file = path.join(dir, \"motion-filmstrip.png\");\n await writeFile(file, take.filmstrip);\n section.motionFilmstrip = path.relative(outDir, file);\n log(` [${section.index}] ${section.motion.summary}`);\n };\n\n // A worker pool rather than fixed batches: a slow section holds up its own\n // worker, not the whole group.\n const queue = [...moving];\n await Promise.all(\n Array.from({ length: Math.min(MOTION_CONCURRENCY, queue.length) }, async () => {\n for (let next = queue.shift(); next; next = queue.shift()) {\n await filmOne(next);\n }\n }),\n );\n}\n\n/**\n * One attempt at getting a real page, over one specific route.\n *\n * Everything expensive happens *after* this returns, and that is what makes a\n * ladder affordable: a rung that gets refused costs one navigation and writes\n * nothing. On failure it closes its own browser, so climbing leaves nothing\n * behind.\n */\nasync function openPageVia(\n route: ProxyRoute,\n url: string,\n timeoutMs: number,\n): Promise<\n | {\n ok: true;\n browser: Browser;\n context: BrowserContext;\n page: Page;\n prepared: Awaited<ReturnType<typeof preparePage>>;\n }\n | { ok: false; outcome: AttemptOutcome }\n> {\n const startedAt = Date.now();\n const browser = await launchBrowser(route);\n // Hoisted so the failure path can still see it. The status is the *only*\n // signal that separates \"this site refuses automated visitors\" (403/429/451,\n // worth a different exit IP) from \"this page is gone\" (404, worth nothing),\n // and it is known here but thrown by the time `catch` runs. Reporting null\n // made every status-based escalation rule dead code.\n let status: number | null = null;\n try {\n const { context, page } = await newPage(browser, DESKTOP_VIEWPORT);\n await blockConsentManagers(page);\n await installPageRuntime(page);\n\n const prepared = await preparePage(page, url, timeoutMs);\n status = prepared.status;\n\n // Before anything is captured: were we actually shown the page? A bot\n // filter's block page segments and reproduces perfectly, so nothing\n // downstream can catch this — it has to be refused here.\n const blocked = detectBlockedPage({\n status: prepared.status,\n title: prepared.title,\n bodyText: prepared.bodyText,\n html: await page.content().catch(() => \"\"),\n });\n if (blocked) throw new BlockedPageError(blocked);\n\n return { ok: true, browser, context, page, prepared };\n } catch (error) {\n await browser.close().catch(() => undefined);\n return {\n ok: false,\n outcome: {\n route,\n failure: classifyCaptureFailure(error),\n status,\n netError: netErrorName(error),\n elapsedMs: Date.now() - startedAt,\n },\n };\n }\n}\n\ninterface OpenedPage {\n browser: Browser;\n context: BrowserContext;\n page: Page;\n prepared: Awaited<ReturnType<typeof preparePage>>;\n}\n\n/**\n * The passes that re-load the live page after the desktop context has closed.\n *\n * Grouped because they share one property that matters to cost: each re-opens\n * the page over whatever route won, so on an escalated run they are billed\n * bandwidth. Motion is the expensive one — it re-loads once per moving section,\n * three at a time — which is why an escalated run turns it off upstream.\n */\nasync function captureAlternateViews(args: {\n browser: Browser;\n sections: ScrapedSection[];\n sectionsDir: string;\n outDir: string;\n pageUrl: string;\n timeoutMs: number;\n withMobile: boolean;\n withMotion: boolean;\n log: (message: string) => void;\n}): Promise<void> {\n const { browser, sections, sectionsDir, outDir, pageUrl, timeoutMs, withMobile, withMotion, log } = args;\n\n if (withMobile) {\n log(\"capturing mobile\");\n await captureMobileShots({ browser, sections, sectionsDir, outDir, pageUrl, timeoutMs });\n }\n if (withMotion) {\n await captureMotionTakes({ browser, sections, sectionsDir, outDir, pageUrl, log });\n }\n}\n\n/**\n * Full-page shot plus the whole-page reproduction scored against it.\n *\n * The screenshot is written whether or not code extraction runs, because it is\n * the record of what we actually saw — the reproduction is only ever a\n * comparison against it.\n */\nasync function reproduceWholePage(args: {\n browser: Browser;\n page: Page;\n outDir: string;\n pageUrl: string;\n withCode: boolean;\n log: (message: string) => void;\n}): Promise<Awaited<ReturnType<typeof reproducePage>>> {\n const { browser, page, outDir, pageUrl, withCode, log } = args;\n\n const fullPage = await page.screenshot({ type: \"png\", fullPage: true }).catch(() => null);\n if (fullPage) await writeFile(path.join(outDir, \"full-page.png\"), fullPage);\n\n if (!withCode) return { bundle: null, fidelity: null };\n\n const reproduction = await reproducePage({ browser, page, outDir, pageUrl, livePageShot: fullPage });\n log(`page reproduction: ${reproduction.fidelity === null ? \"unavailable\" : reproduction.fidelity.toFixed(2)}`);\n return reproduction;\n}\n\n/** Segment the live page and capture each section it found, in page order. */\nasync function captureSections(args: {\n browser: Browser;\n page: Page;\n sectionsDir: string;\n outDir: string;\n pageUrl: string;\n withCode: boolean;\n log: (message: string) => void;\n}): Promise<ScrapedSection[]> {\n const { browser, page, sectionsDir, outDir, pageUrl, withCode, log } = args;\n\n log(\"segmenting\");\n const candidates = await segmentPage(page, DEFAULT_SEGMENT_OPTIONS);\n log(`found ${candidates.length} sections`);\n\n const sections: ScrapedSection[] = [];\n for (const candidate of candidates) {\n const section = await captureOneSection({\n browser,\n page,\n candidate,\n sectionsDir,\n outDir,\n pageUrl,\n withCode,\n });\n sections.push(section);\n log(\n ` [${candidate.index}] ${candidate.rect.width}x${candidate.rect.height}` +\n `${section.fidelity === null ? \"\" : ` fidelity=${section.fidelity.toFixed(2)}`}` +\n ` — ${candidate.textPreview.slice(0, 50)}`,\n );\n }\n return sections;\n}\n\n/** Strip an attempt down to what may safely leave the process. */\nfunction rungReport(outcome: AttemptOutcome): RungReport {\n return {\n tier: outcome.route.kind === \"proxy\" ? outcome.route.tier : \"direct\",\n code: outcome.failure.code,\n status: outcome.status,\n };\n}\n\n/**\n * Climb the ladder until some route yields a real page.\n *\n * Kept separate from the capture it feeds because the two fail differently.\n * Every exit from here is cheap — a refused rung costs one navigation and\n * writes nothing. Once this returns, the caller owns a page and there is no\n * going back: nothing downstream re-opens a route, which is exactly what keeps\n * the ladder's wall-clock arithmetic honest.\n *\n * On exhaustion it throws the failure worth *reporting*, which is not always\n * the last one — a broken proxy on rung two must never overwrite the site's own\n * verdict from rung one.\n */\n/**\n * Ask the proxy whether the timeout we just spent was its fault.\n *\n * Only ever reached after a navigation has already timed out, so the ~100ms\n * this costs is noise against the 25s just lost — and it buys the difference\n * between \"this site is slow\" and \"our credential is being refused\", which\n * Chromium will not tell us and which point in opposite directions: the first\n * ends the ladder, the second must not.\n *\n * A preflight that says the route is fine leaves the attempt exactly as it was.\n * The site really was slow, and that is still a final answer.\n */\nasync function resolveAmbiguousTimeout(\n outcome: AttemptOutcome,\n log: (message: string) => void,\n): Promise<AttemptOutcome> {\n if (!ambiguousProxyTimeout(outcome)) return outcome;\n\n const verdict = await preflightProxyRoute(outcome.route).catch(() => null);\n if (!verdict || verdict.usable) return outcome;\n\n log(`that timeout was our own route, not the site (${verdict.problem}) — carrying on up the ladder`);\n return asProxyFailure(outcome, verdict.problem);\n}\n\nasync function openViaLadder(args: {\n url: string;\n routes: readonly ProxyRoute[];\n timeoutMs: number;\n deadline: number | null;\n log: (message: string) => void;\n}): Promise<{ opened: OpenedPage; attempts: AttemptOutcome[]; tier: CaptureTier }> {\n const { url, routes, timeoutMs, deadline, log } = args;\n const attempts: AttemptOutcome[] = [];\n\n for (let route: ProxyRoute | null = routes[0] ?? { kind: \"direct\" }; route; ) {\n log(`loading ${url}${route.kind === \"proxy\" ? ` (retrying via ${route.tier})` : \"\"}`);\n const attempt = await openPageVia(route, url, timeoutMs);\n if (attempt.ok) {\n return { opened: attempt, attempts, tier: route.kind === \"proxy\" ? route.tier : \"direct\" };\n }\n\n attempts.push(await resolveAmbiguousTimeout(attempt.outcome, log));\n const decision = nextRoute({\n routes,\n attempts,\n remainingMs: deadline ? deadline - Date.now() : Number.POSITIVE_INFINITY,\n reserveMs: CAPTURE_RESERVE_MS,\n navTimeoutMs: timeoutMs,\n });\n if (!decision.next) {\n log(`giving up after ${attempts.length} attempt(s) — ${decision.reason}`);\n break;\n }\n route = decision.next;\n }\n\n throw new CaptureFailureError(reportableFailure(attempts), attempts.map(rungReport));\n}\n\nexport async function scrapeLanding(options: ScrapeOptions): Promise<ScrapeManifest> {\n const timeoutMs = options.timeoutMs ?? 45_000;\n const log = options.onProgress ?? (() => undefined);\n const sectionsDir = path.join(options.outDir, \"sections\");\n\n // Refused outright rather than bypassed: bypassing leaves a request that\n // still happens, just unproxied. `169.254.169.254` is the cloud metadata\n // endpoint every capture runner can route to, and nothing on this path\n // checked before now.\n const nonPublic = refuseNonPublicUrl(options.url);\n if (nonPublic) {\n throw new BlockedPageError({\n code: \"HTTP_ERROR\",\n message:\n nonPublic === \"unparseable\" ? \"That doesn't look like a web address we can open.\" : LOCAL_ADDRESS_REFUSAL,\n });\n }\n\n const { opened, attempts, tier } = await openViaLadder({\n url: options.url,\n routes: plannedRoutes(options.url, options.proxyCredentials ?? {}),\n timeoutMs,\n deadline: options.budgetMs ? Date.now() + options.budgetMs : null,\n log,\n });\n\n const { browser, context, page, prepared } = opened;\n const escalated = attempts.length > 0;\n // Filming re-loads the whole page once per moving section, three at a time —\n // over a metered exit that is the largest single cost in a capture, and it is\n // what the escalation just spent its budget getting past. An escalated run\n // trades the filmstrips for finishing at all.\n const withMotion = options.motion !== false && !escalated;\n\n // A second, deliberately unproxied browser for re-rendering extracted markup.\n // Fidelity scoring loads local HTML only; routing it through a paid exit would\n // bill us for looking at our own output.\n const renderBrowser = options.code === false ? null : await launchBrowser();\n\n try {\n // Created only once we know we have a real page, so a refusal leaves no\n // half-built output directory behind.\n await mkdir(sectionsDir, { recursive: true });\n\n const sections = await captureSections({\n browser: renderBrowser ?? browser,\n page,\n sectionsDir,\n outDir: options.outDir,\n pageUrl: prepared.finalUrl,\n withCode: options.code !== false,\n log,\n });\n\n const reproduction = await reproduceWholePage({\n browser: renderBrowser ?? browser,\n page,\n outDir: options.outDir,\n pageUrl: prepared.finalUrl,\n withCode: options.code !== false,\n log,\n });\n\n await context.close();\n\n await captureAlternateViews({\n browser,\n sections,\n sectionsDir,\n outDir: options.outDir,\n pageUrl: prepared.finalUrl,\n timeoutMs,\n withMobile: options.mobile !== false,\n withMotion,\n log,\n });\n\n const manifest: ScrapeManifest = {\n url: options.url,\n finalUrl: prepared.finalUrl,\n title: prepared.title,\n documentHeight: prepared.documentHeight,\n viewport: DESKTOP_VIEWPORT,\n capturedAt: new Date().toISOString(),\n sections,\n page: reproduction,\n security: prepared.security,\n captureTier: tier,\n };\n await writeFile(path.join(options.outDir, \"manifest.json\"), `${JSON.stringify(manifest, null, 2)}\\n`);\n if (options.report !== false) {\n const reportPath = await writeCaptureReport(manifest, options.outDir);\n log(`report: ${reportPath}`);\n }\n return manifest;\n } finally {\n await browser.close();\n if (renderBrowser) await renderBrowser.close();\n }\n}\n","import http from \"node:http\";\nimport type { ProxyRoute } from \"./route.ts\";\n\n/**\n * Ask the proxy whether it will actually carry us, before a browser tries.\n *\n * This exists because of a measured behaviour, not a theoretical one. Chromium\n * does **not** report a rejected proxy credential. Given a 407 on an HTTPS\n * navigation it waits for credentials that will never be accepted and then dies\n * on the page timeout, so Playwright reports:\n *\n * page.goto: Timeout 25000ms exceeded.\n *\n * — no `net::` code, no status. Every classifier downstream would therefore\n * read a wrong password as \"that site is slow\": it would blame the page, burn\n * the full navigation budget on every rung of every capture, and — because a\n * timeout is deliberately not an escalation signal — stop the ladder dead\n * without ever trying the tier that would have worked.\n *\n * A CONNECT asks the same question directly and gets a real answer. Measured\n * against the live endpoints: 407 in ~250ms (datacenter) and ~3.2s\n * (residential), versus 25s of silence through the browser.\n *\n * This is the one function in the package that touches the network. It uses\n * `node:http` only, so the package still has no external dependencies.\n */\n\nexport type PreflightProblem = \"auth\" | \"unreachable\" | \"timeout\";\n\nexport type PreflightResult = { usable: true } | { usable: false; problem: PreflightProblem };\n\n/** Pure half, so the decision is testable without a socket. */\nexport function classifyPreflightStatus(status: number | undefined): PreflightResult {\n if (status === 200) return { usable: true };\n // Only something speaking proxy produces a 407, so this can never be the\n // origin's opinion of us — it is always our own credentials.\n if (status === 407) return { usable: false, problem: \"auth\" };\n return { usable: false, problem: \"unreachable\" };\n}\n\nexport interface PreflightOptions {\n /**\n * Generous enough for a residential endpoint (measured ~3.2s to answer),\n * short enough that probing a dead route costs far less than the navigation\n * it replaces.\n */\n readonly timeoutMs?: number;\n /** Host:port the tunnel is requested for. Any public host answers alike. */\n readonly target?: string;\n}\n\nexport async function preflightProxyRoute(route: ProxyRoute, options: PreflightOptions = {}): Promise<PreflightResult> {\n // A direct route has nothing to authenticate against.\n if (route.kind !== \"proxy\") return { usable: true };\n\n const timeoutMs = options.timeoutMs ?? 8000;\n const target = options.target ?? \"example.com:443\";\n const endpoint = new URL(route.server);\n const auth = Buffer.from(`${route.username}:${route.password}`).toString(\"base64\");\n\n return await new Promise<PreflightResult>((resolve) => {\n const settle = (result: PreflightResult) => {\n request.destroy();\n resolve(result);\n };\n const request = http.request({\n host: endpoint.hostname,\n port: Number(endpoint.port),\n method: \"CONNECT\",\n path: target,\n headers: { \"Proxy-Authorization\": `Basic ${auth}`, Host: target },\n timeout: timeoutMs,\n });\n request.on(\"connect\", (response, socket) => {\n socket.destroy();\n settle(classifyPreflightStatus(response.statusCode));\n });\n // A refusal arrives as an ordinary response rather than a tunnel.\n request.on(\"response\", (response) => {\n response.destroy();\n settle(classifyPreflightStatus(response.statusCode));\n });\n request.on(\"timeout\", () => settle({ usable: false, problem: \"timeout\" }));\n request.on(\"error\", () => settle({ usable: false, problem: \"unreachable\" }));\n request.end();\n });\n}\n","import { createRequire } from \"node:module\";\nimport type { ProxyRoute } from \"@baker/proxy\";\nimport type { Browser, BrowserContext, Page } from \"playwright\";\n\n// Resolved at runtime rather than imported: inside the E2B sandbox the CLI is\n// installed globally and Playwright comes from the sandbox image, not from this\n// package's tarball. The split specifier keeps bundlers from rewriting it.\nconst require_ = createRequire(import.meta.url);\nconst pwSpecifier = [\"play\", \"wright\"].join(\"\");\n\nexport const DESKTOP_VIEWPORT = { width: 1440, height: 900 };\nexport const MOBILE_VIEWPORT = { width: 390, height: 844 };\n/** Retina, so section screenshots stay legible when an agent reads them. */\nexport const DEVICE_SCALE_FACTOR = 2;\n\n/**\n * A browser that reaches the internet by one specific route.\n *\n * The proxy is set at **launch**, not per context, and that is load-bearing\n * rather than incidental. `renderBundleToPng` re-renders extracted markup from\n * local `data:`/HTML to score fidelity — it must never egress, and certainly\n * never over a metered residential exit. Setting the route on the process means\n * the local renderer physically cannot leak onto a paid route, instead of that\n * being a flag someone has to remember at each `newPage` call site (there are\n * four, and a fifth will be added by someone who has not read this comment).\n *\n * So a capture runs up to two browsers: this one on the winning route, and a\n * second plain one for bundle rendering.\n */\nexport async function launchBrowser(route: ProxyRoute = { kind: \"direct\" }): Promise<Browser> {\n const playwright = require_(pwSpecifier) as typeof import(\"playwright\");\n return await playwright.chromium.launch({\n headless: true,\n args: [\"--hide-scrollbars\", \"--disable-blink-features=AutomationControlled\", \"--mute-audio\"],\n ...(route.kind === \"proxy\"\n ? { proxy: { server: route.server, username: route.username, password: route.password } }\n : {}),\n });\n}\n\nexport async function newPage(\n browser: Browser,\n viewport: { width: number; height: number },\n opts: { motion: boolean } = { motion: false },\n): Promise<{ context: BrowserContext; page: Page }> {\n const context = await browser.newContext({\n viewport,\n deviceScaleFactor: DEVICE_SCALE_FACTOR,\n // We read third-party marketing pages and send them nothing — no cookies we\n // own, no credentials, no form posts — so the usual reason to refuse a bad\n // certificate (an attacker between us and a session we care about) does not\n // apply. Refusing one instead makes a whole class of real sites permanently\n // uncapturable: `growthspree.com` and `arcus.so` both fail the handshake,\n // and `inspiration scrape` is the escalation the whole repo points agents at\n // when `WebFetch` fails, so it inheriting the same blind spot means there is\n // no route to those pages at all. Every capture therefore records that the\n // certificate was not validated — see `PrepareResult.security`.\n ignoreHTTPSErrors: true,\n // Still captures freeze motion so screenshots are reproducible; the motion\n // pass re-opens a context with animation enabled.\n reducedMotion: opts.motion ? \"no-preference\" : \"reduce\",\n userAgent:\n viewport.width < 500\n ? \"Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1\"\n : \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36\",\n });\n const page = await context.newPage();\n return { context, page };\n}\n","import type { Page } from \"playwright\";\n\n/**\n * Extract the CSS a single section actually depends on.\n *\n * The reference scraper throws styling away entirely — it keeps a nine-attribute\n * allowlist and encodes colour as data attributes — so none of this could be\n * ported. Everything here is new.\n *\n * The approach is \"ask the browser what matched\": walk every stylesheet rule and\n * keep the ones whose selector resolves inside the section. That beats parsing\n * CSS ourselves (no cascade to reimplement) and beats copying computed styles\n * onto every node (which loses media queries, hover states and keyframes).\n */\n\nexport interface UsedCss {\n css: string;\n /** Custom properties resolved against the section root, emitted as `:root`. */\n variables: string;\n /** Typography/colour the section inherits from ancestors we won't be copying. */\n inheritedSeed: string;\n /** Sheets we couldn't read in-page (CORS); fetched Node-side and appended. */\n unreadableHrefs: string[];\n stats: { totalRules: number; keptRules: number; fontFaces: number; keyframes: number };\n}\n\nexport async function collectUsedCss(page: Page, selector: string): Promise<UsedCss> {\n const collected = await page.evaluate(inPageCollectUsedCss, selector);\n\n // Cross-origin sheets (a CDN-hosted font or design system) throw on\n // `.cssRules`. Refetch them from Node, where the same-origin policy doesn't\n // apply, and append wholesale — we can't tell which of their rules matched,\n // and shipping a superset renders correctly.\n const extra: string[] = [];\n for (const href of collected.unreadableHrefs) {\n const text = await fetchStylesheet(page, href);\n if (text) extra.push(`/* ${href} */\\n${text}`);\n }\n\n return { ...collected, css: [collected.css, ...extra].filter(Boolean).join(\"\\n\\n\") };\n}\n\nasync function fetchStylesheet(page: Page, href: string): Promise<string | null> {\n try {\n const response = await page.request.get(href, { timeout: 10_000 });\n if (!response.ok()) return null;\n return await response.text();\n } catch {\n return null;\n }\n}\n\n/** Properties a section inherits rather than declares; without them a lifted\n * section renders in Times New Roman on a white page. */\nconst INHERITED_PROPERTIES = [\n \"color\",\n \"font-family\",\n \"font-size\",\n \"font-weight\",\n \"line-height\",\n \"letter-spacing\",\n \"text-align\",\n \"background-color\",\n \"-webkit-font-smoothing\",\n];\n\nconst inPageCollectUsedCss = (selector: string) => {\n const root = document.querySelector(selector);\n const empty = {\n css: \"\",\n variables: \"\",\n inheritedSeed: \"\",\n unreadableHrefs: [] as string[],\n stats: { totalRules: 0, keptRules: 0, fontFaces: 0, keyframes: 0 },\n };\n if (!root) return empty;\n\n const INHERITED = [\n \"color\",\n \"font-family\",\n \"font-size\",\n \"font-weight\",\n \"line-height\",\n \"letter-spacing\",\n \"text-align\",\n \"background-color\",\n \"-webkit-font-smoothing\",\n ];\n\n const unreadableHrefs: string[] = [];\n const kept: string[] = [];\n const fontFaces: string[] = [];\n const keyframesByName = new Map<string, string>();\n let totalRules = 0;\n // Counted separately from `kept.length`: a surviving `@media`/`@layer` block\n // is one entry in `kept` but may carry hundreds of style rules, so the array\n // length badly understates how much CSS came across.\n let keptStyleRules = 0;\n\n /**\n * Does this selector resolve inside the section?\n *\n * Pseudo-states and pseudo-elements are stripped first: `.btn:hover` never\n * matches a non-hovered element, but its rule is exactly the kind we want to\n * carry over. Descendant selectors work unchanged because `querySelector` on\n * the root still resolves ancestors against the whole document.\n */\n const matchesInSection = (selectorText: string) => {\n for (const part of selectorText.split(\",\")) {\n const base = part\n .replace(/::[a-zA-Z-]+(\\([^)]*\\))?/g, \"\")\n .replace(/:(hover|focus|focus-visible|focus-within|active|visited|target|checked|disabled)\\b/g, \"\")\n .trim();\n if (!base) continue;\n try {\n if (root.matches(base) || root.querySelector(base)) return true;\n } catch {\n // Selector syntax Chromium won't evaluate standalone (`:has()` variants,\n // vendor pseudo-elements). Keeping it is the safer failure.\n return true;\n }\n }\n return false;\n };\n\n const walk = (rules: CSSRuleList, sink: string[]) => {\n for (const rule of Array.from(rules)) {\n totalRules++;\n\n if (rule instanceof CSSStyleRule) {\n if (matchesInSection(rule.selectorText)) {\n sink.push(rule.cssText);\n keptStyleRules++;\n }\n continue;\n }\n if (rule instanceof CSSFontFaceRule) {\n fontFaces.push(rule.cssText);\n continue;\n }\n if (rule instanceof CSSKeyframesRule) {\n keyframesByName.set(rule.name, rule.cssText);\n continue;\n }\n // Grouping rules: recurse, and only emit the wrapper if something inside\n // survived — otherwise every page's full media-query set comes along.\n const grouping =\n rule instanceof CSSMediaRule ||\n rule instanceof CSSSupportsRule ||\n (typeof CSSLayerBlockRule !== \"undefined\" && rule instanceof CSSLayerBlockRule) ||\n (typeof CSSContainerRule !== \"undefined\" && rule instanceof CSSContainerRule);\n if (grouping) {\n const inner: string[] = [];\n walk((rule as CSSGroupingRule).cssRules, inner);\n if (inner.length === 0) continue;\n const condition = (rule as CSSMediaRule).conditionText ?? \"\";\n const prelude = rule instanceof CSSMediaRule ? `@media ${condition}` : rule.cssText.split(\"{\")[0]?.trim();\n sink.push(`${prelude} {\\n${inner.join(\"\\n\")}\\n}`);\n }\n }\n };\n\n for (const sheet of Array.from(document.styleSheets)) {\n // Never harvest our own instrumentation. `freezeMotion` injects an\n // `animation-play-state: paused !important` rule to hold the page still for\n // screenshots; copied into a bundle it pins every animation at its *first*\n // keyframe, so a section whose entrance fades in renders blank.\n const owner = sheet.ownerNode as Element | null;\n if (owner?.hasAttribute?.(\"data-baker-freeze\")) continue;\n try {\n walk(sheet.cssRules, kept);\n } catch {\n if (sheet.href) unreadableHrefs.push(sheet.href);\n }\n }\n\n // Only the keyframes actually referenced by surviving rules.\n const keptText = kept.join(\"\\n\");\n const usedKeyframes: string[] = [];\n for (const [name, text] of keyframesByName) {\n if (new RegExp(`(^|[\\\\s:,])${name}([\\\\s;,}]|$)`).test(keptText)) usedKeyframes.push(text);\n }\n\n // Resolve custom properties against the section root rather than tracing where\n // each was declared: a variable may be set on any ancestor, and we are lifting\n // the section away from all of them.\n const rootStyle = getComputedStyle(root);\n const variableDeclarations: string[] = [];\n for (const property of Array.from(rootStyle)) {\n if (!property.startsWith(\"--\")) continue;\n const value = rootStyle.getPropertyValue(property).trim();\n if (value) variableDeclarations.push(` ${property}: ${value};`);\n }\n\n const seed = INHERITED.map((property) => ` ${property}: ${rootStyle.getPropertyValue(property)};`).join(\"\\n\");\n\n return {\n css: [...fontFaces, ...usedKeyframes, ...kept].join(\"\\n\"),\n variables: variableDeclarations.length ? `:root {\\n${variableDeclarations.join(\"\\n\")}\\n}` : \"\",\n inheritedSeed: seed,\n unreadableHrefs,\n stats: {\n totalRules,\n keptRules: keptStyleRules,\n fontFaces: fontFaces.length,\n keyframes: usedKeyframes.length,\n },\n };\n};\n\nexport { INHERITED_PROPERTIES };\n","import type { Page } from \"playwright\";\nimport { collectUsedCss } from \"./usedCss.ts\";\n\n/**\n * Build a standalone HTML file that renders one section on its own.\n *\n * \"Standalone\" is the whole point: the file has to survive being opened with no\n * network, no parent page and no surrounding cascade, because that is the only\n * way to prove the extraction actually captured what makes the section look the\n * way it does. `verify.ts` re-renders this and scores the result.\n */\n\nexport interface SectionBundle {\n html: string;\n css: string;\n /** Absolute URLs the bundle still points at, for the asset pass. */\n assetUrls: string[];\n stats: { totalRules: number; keptRules: number; fontFaces: number; keyframes: number };\n}\n\nexport async function buildSectionBundle(page: Page, selector: string, pageUrl: string): Promise<SectionBundle> {\n const used = await collectUsedCss(page, selector);\n const extracted = await page.evaluate(inPageExtractMarkup, {\n selector,\n pageUrl,\n rootAttribute: SECTION_ROOT_ATTRIBUTE,\n });\n\n const css = [\n \"*, *::before, *::after { box-sizing: border-box; }\",\n \"html, body { margin: 0; padding: 0; }\",\n used.variables,\n `body {\\n${used.inheritedSeed}\\n}`,\n used.css,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n\n const html = `<!doctype html>\n<html ${extracted.rootAttributes}>\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Section from ${escapeHtml(extracted.host)}</title>\n<style>\n${css}\n</style>\n</head>\n<body ${extracted.bodyAttributes}>\n${wrapInLayoutContext(extracted.html, extracted.layoutContext)}\n</body>\n</html>\n`;\n\n return { html, css, assetUrls: extracted.assetUrls, stats: used.stats };\n}\n\nfunction escapeHtml(value: string): string {\n return value.replace(/[&<>\"]/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\" })[c] ?? c);\n}\n\ninterface AncestorFrame {\n tag: string;\n /** class / id / data-* only — enough for selectors to match, without inline layout. */\n attributes: string;\n containerType: string;\n containerName: string;\n}\n\ninterface LayoutContext {\n ancestors: AncestorFrame[];\n width: number;\n viewportWidth: number;\n}\n\n/** Marks the lifted section, so the renderer photographs it and not the scaffolding. */\nexport const SECTION_ROOT_ATTRIBUTE = \"data-baker-section-root\";\n\n/**\n * Rebuild the chain of ancestors the section hung from.\n *\n * A section is styled by far more than the rules that name it. Themes\n * (`.dark-section .heading`), design-system scopes, and `@container` queries all\n * resolve against ancestors that are by definition outside what we extracted, so\n * lifting a section bare silently drops them: Stripe's dark bands re-render\n * white with perfect layout, and a Tailwind v4 twelve-column grid collapses to a\n * single stacked column. Both look like the CSS extraction failed when in fact\n * the CSS was there with nothing to attach to.\n *\n * Recreating each ancestor as an empty element carrying its tag, `class`, `id`\n * and `data-*` makes every one of those selectors match again — one mechanism\n * instead of a special case per failure. Inline styles are deliberately *not*\n * copied: they carry transforms and absolute positioning that would move the\n * section rather than style it. `container-type` is the one exception, re-applied\n * from computed style because a query container has no other way to exist.\n *\n * Ancestor padding now sits inside the bundle, so the renderer photographs the\n * element tagged {@link SECTION_ROOT_ATTRIBUTE} rather than the outermost node.\n */\nfunction wrapInLayoutContext(html: string, context: LayoutContext): string {\n // The measured width pins the content column: a section that sat in a 1232px\n // container inside a 1440px page would otherwise re-render full-bleed.\n let wrapped =\n context.width > 0 && context.width < context.viewportWidth\n ? `<div style=\"width:${context.width}px;margin:0 auto;\">\\n${html}\\n</div>`\n : html;\n\n for (const ancestor of [...context.ancestors].reverse()) {\n const attributes = ancestor.attributes ? ` ${ancestor.attributes}` : \"\";\n const container =\n ancestor.containerType && ancestor.containerType !== \"normal\"\n ? `container-type:${ancestor.containerType};${\n ancestor.containerName && ancestor.containerName !== \"none\"\n ? `container-name:${ancestor.containerName};`\n : \"\"\n }`\n : \"\";\n wrapped = `<${ancestor.tag}${attributes} style=\"${NEUTRALIZED_ANCESTOR_STYLE}${container}\">\\n${wrapped}\\n</${ancestor.tag}>`;\n }\n\n return wrapped;\n}\n\n/**\n * Strip an ancestor's own layout while leaving it able to match selectors.\n *\n * The rebuilt ancestors exist to satisfy the cascade, not to lay anything out.\n * Left alone they do real damage: a grid or flex container that originally held\n * six children now holds one, so the section lands in the wrong track and picks\n * up padding that was never part of what we captured. Painting properties are\n * deliberately untouched — the background and colour of a themed wrapper are\n * exactly what we came for.\n */\nconst NEUTRALIZED_ANCESTOR_STYLE = [\n \"display:block !important\",\n \"position:static !important\",\n \"margin:0 !important\",\n \"padding:0 !important\",\n \"border:0 !important\",\n \"width:auto !important\",\n \"min-width:0 !important\",\n \"max-width:none !important\",\n \"height:auto !important\",\n \"min-height:0 !important\",\n \"max-height:none !important\",\n \"transform:none !important\",\n \"overflow:visible !important\",\n \"\",\n].join(\";\");\n\nconst inPageExtractMarkup = ({\n selector,\n pageUrl,\n rootAttribute,\n}: {\n selector: string;\n pageUrl: string;\n rootAttribute: string;\n}) => {\n const root = document.querySelector(selector);\n const emptyContext = { ancestors: [] as AncestorFrame[], width: 0, viewportWidth: 0 };\n\n /**\n * Carry `<html>`/`<body>` attributes across.\n *\n * Theme is the reason: sites signal light/dark with `class=\"dark\"` or\n * `data-theme` on the root, and design systems hang whole palettes off it.\n * Drop the attribute and the bundle silently renders the wrong theme — the\n * layout is right, every colour and themed image is wrong.\n */\n const serializeAttributes = (element: Element | null) => {\n if (!element) return \"\";\n return Array.from(element.attributes)\n .filter((attribute) => attribute.name !== \"style\")\n .map((attribute) => `${attribute.name}=\"${attribute.value.replace(/\"/g, \"&quot;\")}\"`)\n .join(\" \");\n };\n const rootAttributes = serializeAttributes(document.documentElement) || 'lang=\"en\"';\n const bodyAttributes = serializeAttributes(document.body);\n\n if (!root) {\n return {\n html: \"\",\n assetUrls: [] as string[],\n host: \"\",\n layoutContext: emptyContext,\n rootAttributes,\n bodyAttributes,\n };\n }\n\n // Every ancestor between <body> and the section, outermost first. <body> and\n // <html> are excluded because the bundle reproduces them as real elements.\n const ancestors: AncestorFrame[] = [];\n for (let ancestor = root.parentElement; ancestor && ancestor !== document.body; ) {\n const style = getComputedStyle(ancestor);\n ancestors.unshift({\n tag: /^[a-zA-Z][a-zA-Z0-9-]*$/.test(ancestor.tagName) ? ancestor.tagName.toLowerCase() : \"div\",\n attributes: Array.from(ancestor.attributes)\n .filter((a) => a.name === \"class\" || a.name === \"id\" || a.name.startsWith(\"data-\"))\n .map((a) => `${a.name}=\"${a.value.replace(/\"/g, \"&quot;\")}\"`)\n .join(\" \"),\n containerType: style.containerType,\n containerName: style.containerName,\n });\n ancestor = ancestor.parentElement;\n }\n\n const layoutContext = {\n ancestors,\n width: Math.round(root.getBoundingClientRect().width),\n viewportWidth: window.innerWidth,\n };\n\n const absolute = (value: string) => {\n try {\n return new URL(value, pageUrl).href;\n } catch {\n return value;\n }\n };\n\n // Clone first: the live DOM must not be mutated, since later passes\n // (mobile capture, motion) re-measure against it.\n const clone = root.cloneNode(true) as Element;\n clone.setAttribute(rootAttribute, \"\");\n const assetUrls = new Set<string>();\n\n for (const element of [clone, ...Array.from(clone.querySelectorAll(\"*\"))]) {\n for (const attribute of [\"src\", \"href\", \"poster\"]) {\n const value = element.getAttribute(attribute);\n if (!value || value.startsWith(\"data:\") || value.startsWith(\"#\")) continue;\n const url = absolute(value);\n element.setAttribute(attribute, url);\n if (attribute !== \"href\" || element.tagName === \"LINK\") assetUrls.add(url);\n }\n\n const srcset = element.getAttribute(\"srcset\");\n if (srcset) {\n element.setAttribute(\n \"srcset\",\n srcset\n .split(\",\")\n .map((candidate) => {\n const [url, descriptor] = candidate.trim().split(/\\s+/, 2);\n if (!url) return candidate;\n const resolved = absolute(url);\n assetUrls.add(resolved);\n return descriptor ? `${resolved} ${descriptor}` : resolved;\n })\n .join(\", \"),\n );\n }\n\n // Inline `background-image: url(...)` needs the same treatment; it is where\n // most hero imagery actually lives.\n const style = element.getAttribute(\"style\");\n if (style?.includes(\"url(\")) {\n element.setAttribute(\n \"style\",\n style.replace(/url\\((['\"]?)([^'\")]+)\\1\\)/g, (_match, quote: string, url: string) => {\n if (url.startsWith(\"data:\")) return `url(${quote}${url}${quote})`;\n const resolved = absolute(url);\n assetUrls.add(resolved);\n return `url(${quote}${resolved}${quote})`;\n }),\n );\n }\n }\n\n return {\n html: clone.outerHTML,\n assetUrls: Array.from(assetUrls),\n host: location.host,\n layoutContext,\n rootAttributes,\n bodyAttributes,\n };\n};\n","import type { Page } from \"playwright\";\nimport type { SectionCandidate } from \"./types.ts\";\n\n/**\n * A section screenshot is the artifact everything else is judged by, so prefer\n * the element's own box over a coordinate clip: the locator survives a reflow\n * between segmentation and capture, a stale rect does not.\n */\nexport async function captureSection(page: Page, section: SectionCandidate): Promise<Buffer | null> {\n const locator = page.locator(section.selector).first();\n\n if (await locator.count().catch(() => 0)) {\n const shot = await locator.screenshot({ type: \"png\", timeout: 15_000 }).catch(() => null);\n if (shot) return shot;\n }\n\n // Fall back to the geometry we already measured. Chromium rejects a clip that\n // runs past the document, so trim it first.\n const doc = await page.evaluate(() => ({\n width: Math.max(document.documentElement.scrollWidth, document.body?.scrollWidth ?? 0),\n height: Math.max(document.documentElement.scrollHeight, document.body?.scrollHeight ?? 0),\n }));\n const width = Math.min(section.rect.width, doc.width - section.rect.left);\n const height = Math.min(section.rect.height, doc.height - section.rect.top);\n if (width <= 0 || height <= 0) return null;\n\n return await page\n .screenshot({\n type: \"png\",\n clip: { x: section.rect.left, y: section.rect.top, width, height },\n timeout: 15_000,\n })\n .catch(() => null);\n}\n\n/**\n * Re-shoot a desktop-derived section on a mobile viewport.\n *\n * Layout reflows, so the desktop rect is meaningless here — only the selector\n * carries over. A section that doesn't exist on mobile (a desktop nav, a wide\n * comparison table) returns null rather than a misleading crop.\n */\nexport async function captureSectionOnMobile(page: Page, section: SectionCandidate): Promise<Buffer | null> {\n const locator = page.locator(section.selector).first();\n if (!(await locator.count().catch(() => 0))) return null;\n if (!(await locator.isVisible().catch(() => false))) return null;\n return await locator.screenshot({ type: \"png\", timeout: 15_000 }).catch(() => null);\n}\n","import type { BlockSignal, ProxyRoute } from \"@baker/proxy\";\nimport { isProxyFailure, nextPlannedRoute, shouldEscalate } from \"@baker/proxy\";\nimport type { CaptureFailure } from \"./blocked.ts\";\nimport { PROXY_UNAVAILABLE_MESSAGE } from \"./proxyFailure.ts\";\n\n/**\n * Deciding whether to try the same page over a more expensive route.\n *\n * The capture-side half of the ladder: `@baker/proxy` owns *what counts as a\n * block*, and this owns *whether we can afford to act on it*. Split that way\n * because the first question is shared with the image and ad-media fetchers,\n * while the budget arithmetic is specific to a capture that costs minutes.\n *\n * The invariant everything rests on: a rung is only ever retried when it failed\n * **before** any output was written — navigation, `preparePage`, and the block\n * check, which together cost one navigation timeout and produce nothing. Once a\n * rung is past that point it owns the run, whatever happens next. That is what\n * makes each extra rung — including the datacenter retries on a fresh exit IP —\n * cost one navigation rather than one capture.\n */\n\n/**\n * Wall clock a capture needs once it has a page, with filming already off.\n *\n * Deliberately generous, and deliberately a guess that says so: it is the one\n * number here not derived from a measurement. Erring long costs one page;\n * erring short spends the expensive rung and then dies mid-capture, which files\n * a fast page as slow. Tune it from the per-rung timings the ladder logs, not\n * from arithmetic.\n */\nexport const CAPTURE_RESERVE_MS = 180_000;\n\nexport interface AttemptOutcome {\n readonly route: ProxyRoute;\n readonly failure: CaptureFailure;\n /** Main-document status, when there was one. */\n readonly status: number | null;\n /** Chromium's `net::` name, when the navigation threw one. */\n readonly netError: string | null;\n readonly elapsedMs: number;\n}\n\nexport type LadderStop = \"escalate\" | \"site_fault_is_final\" | \"out_of_budget\" | \"ladder_exhausted\" | \"not_configured\";\n\n/** Translate a capture failure into the vocabulary the shared rule speaks. */\nexport function attemptSignal(outcome: AttemptOutcome): BlockSignal {\n const code = outcome.failure.code;\n return {\n challenge: code === \"BOT_CHALLENGE\",\n status: outcome.status,\n netError: outcome.netError,\n timedOut: code === \"SITE_TOO_SLOW\",\n };\n}\n\n/**\n * A timeout on a proxy rung, which is the one failure we cannot read.\n *\n * Chromium does not report a rejected proxy credential. Measured against a\n * proxy answering every CONNECT with 407: no `net::` name is produced at all,\n * the navigation simply runs out its budget and reports a plain timeout. That\n * collides with the genuinely slow site, and the collision is expensive —\n * `shouldEscalate` refuses to climb on a timeout (rightly: a slow site is\n * slower still over residential), so a wrong password in the *cheap* tier\n * silently disabled the expensive one for every blocked page, and the page was\n * then filed as though the site had been at fault.\n *\n * The direct route is excluded because nothing of ours can be at fault there,\n * and an attempt the origin answered is excluded because that answer is the\n * site's opinion however it arrived. What is left is merely ambiguous, and the\n * caller resolves it by asking the proxy directly — which takes ~100ms and only\n * ever happens on a path that has already lost a full navigation timeout.\n */\nexport function ambiguousProxyTimeout(outcome: AttemptOutcome): boolean {\n return (\n outcome.route.kind === \"proxy\" &&\n outcome.failure.code === \"SITE_TOO_SLOW\" &&\n outcome.status === null &&\n outcome.netError === null\n );\n}\n\n/** Re-file an attempt as our fault, once a preflight has confirmed it was. */\nexport function asProxyFailure(outcome: AttemptOutcome, problem: \"auth\" | \"unreachable\" | \"timeout\"): AttemptOutcome {\n return {\n ...outcome,\n failure: { code: \"PROXY_UNAVAILABLE\", message: PROXY_UNAVAILABLE_MESSAGE },\n // Borrowing Chromium's own vocabulary so `isProxyFailure` recognises this\n // without having to learn a second way of being told the same thing.\n netError: problem === \"auth\" ? \"ERR_PROXY_AUTH_REQUESTED\" : \"ERR_PROXY_CONNECTION_FAILED\",\n };\n}\n\nexport function nextRoute(args: {\n routes: readonly ProxyRoute[];\n attempts: readonly AttemptOutcome[];\n remainingMs: number;\n reserveMs: number;\n navTimeoutMs: number;\n}): { next: ProxyRoute | null; reason: LadderStop } {\n const last = args.attempts[args.attempts.length - 1];\n if (!last) return { next: null, reason: \"ladder_exhausted\" };\n\n // Our own broken route is not a verdict on the page. It must not end the run\n // — the next rung may well work — but it is not evidence of blocking either,\n // so it neither stops the ladder nor justifies climbing on its own.\n const brokenProxy = isProxyFailure(attemptSignal(last));\n if (!brokenProxy && !shouldEscalate(attemptSignal(last))) {\n return { next: null, reason: \"site_fault_is_final\" };\n }\n\n const next = nextPlannedRoute(\n args.routes,\n args.attempts.map((attempt) => ({\n tier: attempt.route.kind === \"proxy\" ? attempt.route.tier : \"direct\",\n proxyFailure: isProxyFailure(attemptSignal(attempt)),\n })),\n );\n if (!next) return { next: null, reason: args.routes.length === 1 ? \"not_configured\" : \"ladder_exhausted\" };\n\n // Reaching a page with no time left to capture it is the worst outcome\n // available: it spends the expensive rung and still produces nothing.\n if (args.remainingMs < args.reserveMs + args.navTimeoutMs) {\n return { next: null, reason: \"out_of_budget\" };\n }\n return { next, reason: \"escalate\" };\n}\n\n/**\n * Which attempt's failure the page should be recorded under.\n *\n * Three rules, in order, each earned:\n *\n * 1. **Never a proxy failure while a site verdict exists.** That is ours, and\n * filing it against the page is how a mistyped password blacklists a good\n * site. The first rung is always direct and always runs, so there is nearly\n * always something better to report.\n * 2. **Prefer a rung where the origin actually answered.** Observed live: a\n * protected site returned a clean 403 direct, then reset both paid rungs at\n * the socket. Reporting the last verdict said \"this site didn't respond\"\n * about a site that answered fine and said no — and filed it `unreachable`\n * (the site is down) instead of `refused` (the site turns us away), which\n * are different facts and read differently in the corpus.\n * 3. **Otherwise the most recent**, since with no answer anywhere the newest\n * observation is the least stale.\n *\n * Note this cannot simply prefer the *first* attempt: a WAF that null-routes\n * our own range but serves the datacenter exit tells us the most through a\n * later rung.\n */\nexport function reportableFailure(attempts: readonly AttemptOutcome[]): CaptureFailure {\n const siteVerdicts = attempts.filter((attempt) => !isProxyFailure(attemptSignal(attempt)));\n const chosen =\n siteVerdicts.find((attempt) => attempt.status !== null) ??\n siteVerdicts[siteVerdicts.length - 1] ??\n attempts[attempts.length - 1];\n if (!chosen) throw new Error(\"reportableFailure called with no attempts\");\n return chosen.failure;\n}\n","import sharp from \"sharp\";\n\n/**\n * How closely does the extracted bundle re-render the live section?\n *\n * This is the honesty gate for the whole library. Extraction can silently lose\n * a background image, a webfont, or a scroll-driven layout, and the result still\n * *looks* like valid HTML — only a pixel comparison catches it. The score is\n * stored per section so a consumer knows whether the code is a faithful copy or\n * a rough structural reference.\n */\n\n/** Coarse grid: we want \"is this the same design\", not a pixel-diff regression. */\nconst COMPARISON_SIZE = 32;\n\n/**\n * Mean absolute difference over greyscale samples, normalised to 0..1.\n * Exported separately from the image decoding so it can be tested directly.\n */\nexport function pixelSimilarity(a: Uint8Array, b: Uint8Array): number {\n const length = Math.min(a.length, b.length);\n if (length === 0) return 0;\n let total = 0;\n for (let i = 0; i < length; i++) {\n total += Math.abs((a[i] ?? 0) - (b[i] ?? 0));\n }\n return 1 - total / (length * 255);\n}\n\nexport interface FidelityResult {\n /** 0..1, where 1 is a pixel-identical re-render at this resolution. */\n score: number;\n liveSize: { width: number; height: number };\n renderedSize: { width: number; height: number };\n /** Set when the two renders disagree enough that the score needs context. */\n note?: string;\n}\n\nexport async function scoreFidelity(live: Buffer, rendered: Buffer): Promise<FidelityResult> {\n const [liveMeta, renderedMeta] = await Promise.all([sharp(live).metadata(), sharp(rendered).metadata()]);\n const liveSize = { width: liveMeta.width ?? 0, height: liveMeta.height ?? 0 };\n const renderedSize = { width: renderedMeta.width ?? 0, height: renderedMeta.height ?? 0 };\n\n const [livePixels, renderedPixels] = await Promise.all([toGreyGrid(live), toGreyGrid(rendered)]);\n const score = pixelSimilarity(livePixels, renderedPixels);\n\n // A large height difference means the bundle reflowed — usually a missing\n // font or a layout that depended on the page shell. Worth surfacing, because\n // the pixel score alone can stay deceptively high on a mostly-empty section.\n const heightRatio =\n liveSize.height > 0 && renderedSize.height > 0\n ? Math.min(liveSize.height, renderedSize.height) / Math.max(liveSize.height, renderedSize.height)\n : 0;\n\n return {\n score,\n liveSize,\n renderedSize,\n ...(heightRatio < 0.8\n ? { note: `height differs by ${Math.round((1 - heightRatio) * 100)}% — the bundle reflowed` }\n : {}),\n };\n}\n\n/** Normalise away size and colour so the comparison is about layout and tone. */\nasync function toGreyGrid(image: Buffer): Promise<Uint8Array> {\n const raw = await sharp(image).greyscale().resize(COMPARISON_SIZE, COMPARISON_SIZE, { fit: \"fill\" }).raw().toBuffer();\n return new Uint8Array(raw);\n}\n","import type { MotionKind } from \"@baker/landing-dna\";\nimport type { Page } from \"playwright\";\n\n/**\n * Describe how a section moves.\n *\n * Motion is half of why a modern landing feels good, and a still screenshot\n * throws all of it away. This reads the section's *rules* rather than its\n * computed styles on purpose: captures run with `prefers-reduced-motion: reduce`\n * so the page holds still, which means computed `animation-name` is frequently\n * `none` on exactly the elements we care about. The rules are there either way.\n */\n\nexport interface MotionEffect {\n /** Vocabulary the agent and the search facets share — `fade-up`, `lift`, `marquee`. */\n kind: string;\n selector: string;\n durationMs?: number;\n delayMs?: number;\n easing?: string;\n}\n\nexport interface MotionDescriptor {\n hasMotion: boolean;\n /** One line for a search result row. */\n summary: string;\n entrance: MotionEffect[];\n hover: MotionEffect[];\n scroll: MotionEffect[];\n loop: MotionEffect[];\n /** Motion driven by JS, detected by signature — `gsap`, `framer-motion`, `aos`. */\n libraries: string[];\n /** Whether the page bothers to turn its motion off for users who ask. */\n respectsReducedMotion: boolean;\n}\n\nexport const EMPTY_MOTION: MotionDescriptor = {\n hasMotion: false,\n // `none` rather than \"no motion\": it is the `MOTION_KINDS` member for this,\n // so a section with no movement is findable by the same facet as everything\n // else instead of being a special case only prose describes.\n summary: \"none\",\n entrance: [],\n hover: [],\n scroll: [],\n loop: [],\n libraries: [],\n respectsReducedMotion: false,\n};\n\n/**\n * Is there motion here that a still frame fails to convey?\n *\n * Hover states are deliberately excluded. Practically every section contains a\n * link that changes colour, so gating on `hasMotion` films the whole page and\n * yields six identical frames for most of it. What a filmstrip actually shows is\n * something that moves on its own — a reveal, a scroll effect, a loop.\n */\nexport function isWorthFilming(motion: MotionDescriptor): boolean {\n return motion.entrance.length + motion.scroll.length + motion.loop.length > 0;\n}\n\nexport async function collectMotion(page: Page, selector: string): Promise<MotionDescriptor> {\n const raw = await page.evaluate(inPageCollectMotion, selector).catch(() => null);\n if (!raw) return EMPTY_MOTION;\n return { ...raw, summary: summarizeMotion(raw) };\n}\n\n/** Hover kinds that move the element, as opposed to only recolouring it. */\nconst HOVER_TRANSFORMS = new Set([\"lift\", \"grow\", \"tilt\", \"shift\", \"spin\", \"shadow\", \"animate\"]);\n\n/**\n * Map one effect onto the shared search vocabulary.\n *\n * The raw kinds are two different things: hover effects carry a fixed set of our\n * own labels, while entrance/scroll/loop effects carry whatever the page named\n * its `@keyframes`. So the name is read first and the channel is the fallback.\n *\n * The channel fallbacks are deliberately coarse. An entrance animation on a\n * landing page is nearly always tied to the element scrolling into view, so\n * `scroll-reveal` is the honest generic answer; an unrecognised infinite\n * animation is most often a marquee. Both are broad rather than wrong, which is\n * the right failure for a facet.\n */\n/**\n * Checked in order, and **all** matches are kept.\n *\n * A keyframe called `fadeInUp` really is both a fade and a slide — the canonical\n * entrance animation does both at once — so forcing a single answer would make\n * the section unreachable by one of the two obvious searches for it. Over-\n * reporting is the right bias for a facet: it costs a slightly loose match,\n * where under-reporting costs the result entirely.\n */\nconst KEYFRAME_PATTERNS: ReadonlyArray<readonly [RegExp, MotionKind]> = [\n [/marquee|ticker|scroll(ing)?-?(x|left|right)/, \"marquee\"],\n [/parallax/, \"parallax\"],\n [/sticky|pin(ned)?/, \"sticky-pin\"],\n [/count(er|up)/, \"counter\"],\n [/zoom|scale|pulse|grow/, \"zoom\"],\n [/fade|opacity|appear/, \"fade\"],\n [/slide|translate|in-?(left|right|up|down)/, \"slide-in\"],\n];\n\nfunction toMotionKinds(kind: string, channel: \"entrance\" | \"hover\" | \"scroll\" | \"loop\"): MotionKind[] {\n if (channel === \"hover\") return [HOVER_TRANSFORMS.has(kind) ? \"hover-lift\" : \"fade\"];\n\n const name = kind.toLowerCase();\n const matched = KEYFRAME_PATTERNS.filter(([pattern]) => pattern.test(name)).map(([, motionKind]) => motionKind);\n if (matched.length > 0) return matched;\n\n return [channel === \"loop\" ? \"marquee\" : \"scroll-reveal\"];\n}\n\n/**\n * The motion facets this section can be found by.\n *\n * This is the whole point of the rewrite: the `--motion` filter matches against\n * the summary string, so unless the summary is written in `MOTION_KINDS` terms\n * the filter silently matches nothing. It used to emit `\"hover lift\"` with a\n * space while the taxonomy says `hover-lift`, so every documented example — the\n * family doc's own `--motion scroll-reveal` included — returned zero results.\n */\nexport function motionKindsOf(motion: Omit<MotionDescriptor, \"summary\">): MotionKind[] {\n const kinds = new Set<MotionKind>();\n const collect = (effects: MotionEffect[], channel: \"entrance\" | \"hover\" | \"scroll\" | \"loop\") => {\n for (const effect of effects) {\n for (const kind of toMotionKinds(effect.kind, channel)) kinds.add(kind);\n }\n };\n collect(motion.entrance, \"entrance\");\n collect(motion.hover, \"hover\");\n collect(motion.scroll, \"scroll\");\n collect(motion.loop, \"loop\");\n\n // A grid whose items enter on staggered delays is the thing people search for\n // by name, and it is invisible in any single effect — it only exists in the\n // spread of delays across several.\n const delays = new Set(motion.entrance.map((effect) => effect.delayMs ?? 0).filter((ms) => ms > 0));\n if (delays.size > 1) kinds.add(\"stagger\");\n\n return [...kinds];\n}\n\n/**\n * Collapse the descriptor into one line, written in the search vocabulary.\n *\n * Exported because it is pure and worth testing directly — it is also what the\n * `--motion` facet matches against, so its wording is a functional contract and\n * not just presentation.\n */\nexport function summarizeMotion(motion: Omit<MotionDescriptor, \"summary\">): string {\n const kinds = motionKindsOf(motion);\n if (kinds.length === 0 && motion.libraries.length === 0) return \"none\";\n\n // Widened deliberately: the facet terms lead, and the library credit is free\n // text appended after them.\n const parts: string[] = [...kinds];\n if (motion.libraries.length > 0) parts.push(`via ${motion.libraries.join(\"/\")}`);\n return parts.join(\", \") + (motion.respectsReducedMotion ? \"\" : \" (ignores reduced-motion)\");\n}\n\nconst inPageCollectMotion = (selector: string) => {\n const root = document.querySelector(selector);\n const empty = {\n hasMotion: false,\n entrance: [] as MotionEffect[],\n hover: [] as MotionEffect[],\n scroll: [] as MotionEffect[],\n loop: [] as MotionEffect[],\n libraries: [] as string[],\n respectsReducedMotion: false,\n };\n if (!root) return empty;\n\n const entrance: MotionEffect[] = [];\n const hover: MotionEffect[] = [];\n const scroll: MotionEffect[] = [];\n const loop: MotionEffect[] = [];\n const keyframesByName = new Map<string, string>();\n let respectsReducedMotion = false;\n\n const inSection = (selectorText: string) => {\n for (const part of selectorText.split(\",\")) {\n const base = part\n .replace(/::[a-zA-Z-]+(\\([^)]*\\))?/g, \"\")\n .replace(/:(hover|focus|focus-visible|focus-within|active|visited|target|checked|disabled)\\b/g, \"\")\n .trim();\n if (!base) continue;\n try {\n if (root.matches(base) || root.querySelector(base)) return true;\n } catch {\n return true;\n }\n }\n return false;\n };\n\n const toMs = (value: string) => {\n const first = value.split(\",\")[0]?.trim() ?? \"\";\n if (first.endsWith(\"ms\")) return Number.parseFloat(first);\n if (first.endsWith(\"s\")) return Number.parseFloat(first) * 1000;\n return undefined;\n };\n\n /** Name the shape of a keyframe set the way a designer would. */\n const classifyKeyframes = (body: string): string => {\n const text = body.toLowerCase();\n const fades = /opacity\\s*:\\s*0(\\.0+)?\\s*[;}]/.test(text);\n if (/translatey\\(\\s*-?\\d/.test(text)) {\n const upward = /translatey\\(\\s*(\\d|\\.)/.test(text);\n return fades ? (upward ? \"fade-up\" : \"fade-down\") : upward ? \"slide-up\" : \"slide-down\";\n }\n if (/translatex\\(\\s*-?\\d/.test(text)) return fades ? \"fade-in-x\" : \"slide-in-x\";\n if (/scale\\(/.test(text)) return fades ? \"fade-zoom\" : \"zoom\";\n if (/rotate\\(/.test(text)) return \"spin\";\n if (fades) return \"fade\";\n return \"animate\";\n };\n\n const classifyHover = (style: CSSStyleDeclaration): string | null => {\n const transform = style.transform ?? \"\";\n if (/translatey\\(\\s*-/i.test(transform)) return \"lift\";\n if (/scale\\(\\s*(1\\.\\d|[2-9])/i.test(transform)) return \"grow\";\n if (/rotate\\(/i.test(transform)) return \"tilt\";\n if (transform && transform !== \"none\") return \"shift\";\n if (style.boxShadow) return \"shadow\";\n if (style.opacity) return \"dim\";\n if (style.backgroundColor || style.color) return \"recolor\";\n return null;\n };\n\n const readStyleRule = (rule: CSSStyleRule, insideScrollTimeline: boolean) => {\n const style = rule.style;\n const isHover = /:hover\\b/.test(rule.selectorText);\n\n if (isHover) {\n const kind = classifyHover(style);\n // Scope hover rules to the section like everything else. Without this a\n // page-wide `a:hover { color }` is reported as motion belonging to every\n // section on the page, and the descriptor stops discriminating at all.\n if (!kind || !inSection(rule.selectorText)) return;\n hover.push({\n kind,\n selector: rule.selectorText.slice(0, 120),\n durationMs: toMs(style.transitionDuration ?? \"\"),\n easing: style.transitionTimingFunction || undefined,\n });\n return;\n }\n\n const animationName = style.animationName;\n if (!animationName || animationName === \"none\") return;\n if (!inSection(rule.selectorText)) return;\n\n const effect: MotionEffect = {\n kind: animationName,\n selector: rule.selectorText.slice(0, 120),\n durationMs: toMs(style.animationDuration ?? \"\"),\n delayMs: toMs(style.animationDelay ?? \"\"),\n easing: style.animationTimingFunction || undefined,\n };\n const infinite = (style.animationIterationCount ?? \"\").includes(\"infinite\");\n const scrollDriven = insideScrollTimeline || Boolean(style.getPropertyValue(\"animation-timeline\"));\n if (scrollDriven) scroll.push(effect);\n else if (infinite) loop.push(effect);\n else entrance.push(effect);\n };\n\n const walk = (rules: CSSRuleList, insideScrollTimeline: boolean) => {\n for (const rule of Array.from(rules)) {\n if (rule instanceof CSSKeyframesRule) {\n keyframesByName.set(rule.name, rule.cssText);\n continue;\n }\n if (rule instanceof CSSStyleRule) {\n try {\n readStyleRule(rule, insideScrollTimeline);\n } catch {\n // A rule Chromium can evaluate but whose selector we can't — skip it.\n }\n continue;\n }\n if (rule instanceof CSSMediaRule) {\n if (rule.conditionText.includes(\"prefers-reduced-motion\")) {\n respectsReducedMotion = true;\n // Its whole point is to switch motion off; harvesting it as \"motion\"\n // would describe the opposite of what the section does.\n continue;\n }\n walk(rule.cssRules, insideScrollTimeline);\n continue;\n }\n const grouping = rule as Partial<CSSGroupingRule>;\n if (grouping.cssRules) walk(grouping.cssRules, insideScrollTimeline);\n }\n };\n\n for (const sheet of Array.from(document.styleSheets)) {\n if ((sheet.ownerNode as Element | null)?.hasAttribute?.(\"data-baker-freeze\")) continue;\n try {\n walk(sheet.cssRules, false);\n } catch {\n // Cross-origin sheet; its motion is invisible to us and that is fine.\n }\n }\n\n // Resolve animation names into design vocabulary now that keyframes are known.\n for (const effect of [...entrance, ...loop, ...scroll]) {\n const body = keyframesByName.get(effect.kind);\n if (!body) continue;\n const classified = classifyKeyframes(body);\n effect.kind = loop.includes(effect) && classified.startsWith(\"slide\") ? \"marquee\" : classified;\n }\n\n // JS-driven motion leaves fingerprints even when the CSS says nothing.\n const libraries: string[] = [];\n const scoped = (window as unknown as Record<string, unknown>) ?? {};\n if (scoped.gsap || document.querySelector(\"[data-gsap]\")) libraries.push(\"gsap\");\n if (document.querySelector(\"[data-framer-name], [data-projection-id]\")) libraries.push(\"framer-motion\");\n if (document.querySelector(\"[data-aos]\")) libraries.push(\"aos\");\n if (scoped.Lenis || document.querySelector(\"[data-lenis]\")) libraries.push(\"lenis\");\n if (document.querySelector(\"[data-scroll], [data-scroll-container]\")) libraries.push(\"locomotive\");\n\n return {\n hasMotion: entrance.length + hover.length + scroll.length + loop.length + libraries.length > 0,\n entrance: entrance.slice(0, 12),\n hover: hover.slice(0, 12),\n scroll: scroll.slice(0, 12),\n loop: loop.slice(0, 12),\n libraries,\n respectsReducedMotion,\n };\n};\n","import type { Browser, Page } from \"playwright\";\nimport sharp from \"sharp\";\nimport { DESKTOP_VIEWPORT, newPage } from \"./browser.ts\";\nimport { blockConsentManagers, settleConsent, settleNavigation } from \"./prepare.ts\";\nimport { installPageRuntime } from \"./segment.ts\";\n\n/**\n * Film a section actually moving, then contact-sheet it.\n *\n * A video would be the obvious artifact and the wrong one: the consumer here is\n * an agent, which cannot watch one. Six stills laid out in reading order carry\n * the same information in a form it can read directly, and cost no ffmpeg.\n *\n * This runs on its own page, deliberately unfrozen and with reduced-motion off,\n * because the capture pass exists to hold the page *still* — the two cannot\n * share a context.\n */\n\n/** Milliseconds after the section enters view. Front-loaded: reveals resolve fast. */\nconst FRAME_TIMES_MS = [0, 120, 260, 450, 800, 1400];\nconst FRAME_WIDTH = 460;\nconst GRID_COLUMNS = 3;\nconst LABEL_HEIGHT = 22;\n\n/** Breathing room above the section, so it doesn't read as cropped at the top. */\nconst FRAME_MARGIN_PX = 16;\n\nexport interface MotionTake {\n filmstrip: Buffer;\n frameCount: number;\n}\n\nexport interface Rect {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/**\n * The section's box, trimmed to what the camera can actually see.\n *\n * Returns null for a box with nothing in it — Chromium rejects a zero-area or\n * out-of-frame clip, and one section failing to film must not take the run down.\n *\n * Computed once and reused for every frame. Re-measuring per frame would track\n * an element mid-`translateY`, which produces six differently-sized stills that\n * `composeFilmstrip` cannot lay out and, worse, holds the section still in the\n * one artifact whose entire job is to show it moving.\n */\nexport function clampToViewport(box: Rect, viewport: { width: number; height: number }): Rect | null {\n const left = Math.max(0, Math.min(box.left, viewport.width));\n const top = Math.max(0, Math.min(box.top, viewport.height));\n const width = Math.min(box.width - (left - box.left), viewport.width - left);\n const height = Math.min(box.height - (top - box.top), viewport.height - top);\n if (width < 1 || height < 1) return null;\n return { left, top, width, height };\n}\n\nexport async function captureMotionTake(\n browser: Browser,\n url: string,\n selector: string,\n timeoutMs = 45_000,\n): Promise<MotionTake | null> {\n const { context, page } = await newPage(browser, DESKTOP_VIEWPORT, { motion: true });\n try {\n await blockConsentManagers(page);\n await installPageRuntime(page);\n await page.goto(url, { waitUntil: \"domcontentloaded\", timeout: timeoutMs });\n // This pass opens its own context, so it meets any bot checkpoint fresh —\n // an unsettled one gets filmed instead of the section, six times over.\n await settleNavigation(page);\n await page.waitForLoadState(\"networkidle\", { timeout: 8_000 }).catch(() => undefined);\n // A first-party consent modal is fixed to the viewport, so it lands in every\n // single frame and the filmstrip shows a cookie banner instead of the motion.\n await settleConsent(page);\n\n const target = page.locator(selector).first();\n if (!(await target.count().catch(() => 0))) return null;\n\n // Park the section just below the fold so its entrance has not fired yet,\n // then bring it in — an already-revealed section films as a still.\n await page.evaluate((sectionSelector: string) => {\n const element = document.querySelector(sectionSelector);\n if (!element) return;\n const top = element.getBoundingClientRect().top + window.scrollY;\n window.scrollTo({ top: Math.max(0, top - window.innerHeight - 200), behavior: \"instant\" });\n }, selector);\n await page.waitForTimeout(600);\n\n const clip = await aimAtSection(page, selector);\n if (!clip) return null;\n await hideFloatingFurniture(page, selector);\n\n const frames: Buffer[] = [];\n let previous = 0;\n for (const time of FRAME_TIMES_MS) {\n await page.waitForTimeout(Math.max(0, time - previous));\n previous = time;\n const shot = await page\n .screenshot({\n type: \"png\",\n timeout: 10_000,\n clip: { x: clip.left, y: clip.top, width: clip.width, height: clip.height },\n })\n .catch(() => null);\n if (shot) frames.push(shot);\n }\n if (frames.length === 0) return null;\n\n return { filmstrip: await composeFilmstrip(frames), frameCount: frames.length };\n } catch {\n return null;\n } finally {\n await context.close();\n }\n}\n\n/**\n * Scroll the section under the camera and return the box to shoot.\n *\n * Two changes from what this used to do, both for the same reason: the filmstrip\n * was showing the whole 1440×900 viewport, so a reader saw the section's\n * neighbours moving and could not tell which thing the caption referred to. It\n * also fed the classifier a picture of three sections under a prompt asserting\n * it was one.\n *\n * So the section is aligned near the *top* of the viewport rather than centred —\n * centring guarantees a neighbour above and below is in shot — and the frames\n * are clipped to its own box. A section taller than the viewport is shown from\n * the top down, which is where an entrance is legible anyway.\n */\nasync function aimAtSection(page: Page, selector: string): Promise<Rect | null> {\n const box = await page.evaluate(\n ([sectionSelector, margin]) => {\n const element = document.querySelector(sectionSelector as string);\n if (!element) return null;\n const before = element.getBoundingClientRect();\n // `behavior: \"instant\"` is load-bearing, not tidiness. Marketing sites set\n // `html { scroll-behavior: smooth }` (factorialhr.com does), which makes a\n // plain `scrollTo` animate: the very next `getBoundingClientRect()` still\n // reports the old position, so the clip is measured against a viewport the\n // page has not reached yet. Three of four sections filmed nothing at all\n // before this was pinned — and the frames that did come out were shot\n // while the page was still gliding past, which is its own reason the old\n // filmstrips looked like they showed everything except the section.\n window.scrollTo({ top: Math.max(0, before.top + window.scrollY - (margin as number)), behavior: \"instant\" });\n const after = element.getBoundingClientRect();\n return {\n left: after.left,\n top: after.top - (margin as number),\n width: after.width,\n height: after.height + (margin as number),\n viewport: { width: window.innerWidth, height: window.innerHeight },\n };\n },\n [selector, FRAME_MARGIN_PX] as const,\n );\n if (!box) return null;\n return clampToViewport(box, box.viewport);\n}\n\n/**\n * Get the page's furniture out of the shot.\n *\n * A sticky navbar rides the viewport down and lands in every frame, so the\n * filmstrip for a mid-page section shows a header that is no part of it — the\n * same \"this shows more than the component\" confusion the clip fixes, in\n * miniature. The section itself and its own ancestors are exempt: when the\n * subject *is* the navbar, filming its entrance is exactly the point.\n *\n * `visibility` rather than `display`, so nothing reflows and the clip measured a\n * moment ago still points at the same pixels.\n */\nasync function hideFloatingFurniture(page: Page, selector: string): Promise<void> {\n await page.evaluate((sectionSelector: string) => {\n const target = document.querySelector(sectionSelector);\n if (!target) return;\n for (const element of Array.from(document.querySelectorAll<HTMLElement>(\"*\"))) {\n const position = getComputedStyle(element).position;\n if (position !== \"fixed\" && position !== \"sticky\") continue;\n if (element.contains(target) || target.contains(element) || element === target) continue;\n element.style.setProperty(\"visibility\", \"hidden\", \"important\");\n }\n }, selector);\n}\n\n/**\n * Lay the frames out as a labelled grid.\n *\n * The timestamps are the point — \"the cards stagger in over ~450ms\" is only\n * legible if each still says when it was taken.\n */\nasync function composeFilmstrip(frames: Buffer[]): Promise<Buffer> {\n const scaled = await Promise.all(frames.map((frame) => sharp(frame).resize({ width: FRAME_WIDTH }).png().toBuffer()));\n const first = await sharp(scaled[0]).metadata();\n const frameHeight = first.height ?? 300;\n const cellHeight = frameHeight + LABEL_HEIGHT;\n const rows = Math.ceil(scaled.length / GRID_COLUMNS);\n const width = FRAME_WIDTH * Math.min(GRID_COLUMNS, scaled.length);\n\n const composites = scaled.flatMap((frame, index) => {\n const column = index % GRID_COLUMNS;\n const row = Math.floor(index / GRID_COLUMNS);\n const label = Buffer.from(\n `<svg width=\"${FRAME_WIDTH}\" height=\"${LABEL_HEIGHT}\">\n <rect width=\"100%\" height=\"100%\" fill=\"#111827\"/>\n <text x=\"8\" y=\"15\" font-family=\"monospace\" font-size=\"12\" fill=\"#f9fafb\">+${FRAME_TIMES_MS[index] ?? 0}ms</text>\n </svg>`,\n );\n return [\n { input: label, left: column * FRAME_WIDTH, top: row * cellHeight },\n { input: frame, left: column * FRAME_WIDTH, top: row * cellHeight + LABEL_HEIGHT },\n ];\n });\n\n return await sharp({\n create: {\n width,\n height: cellHeight * rows,\n channels: 3,\n background: { r: 17, g: 24, b: 39 },\n },\n })\n .composite(composites)\n .png()\n .toBuffer();\n}\n","/**\n * What the capture browser was actually shown, security-wise.\n *\n * The capture launches with certificate checking **off** (`browser.ts`), which\n * is the right trade for a tool that reads third-party marketing pages and\n * transmits nothing to them — the alternative is that every site with a broken\n * chain is permanently uncapturable, including the ones an agent escalates to\n * `inspiration scrape` precisely because `WebFetch` already refused them.\n *\n * The price of that trade is that a capture can no longer claim the page was\n * served securely, so it must stop implying it. Every captured record carries\n * `certificateValidated: false` and, where the browser told us enough, the\n * specific things wrong with the certificate we were handed.\n */\n\nexport interface CertificateFacts {\n subjectName?: string;\n issuer?: string;\n protocol?: string;\n /** Unix seconds, as Playwright reports them. */\n validFrom?: number;\n validTo?: number;\n}\n\nexport interface CaptureSecurity {\n /**\n * Always false, and stated rather than omitted.\n *\n * A missing field reads as \"not applicable\"; an explicit `false` reads as the\n * decision it is. Anything downstream that wants to treat a capture as\n * evidence of a live, correctly-served page has to see this.\n */\n certificateValidated: false;\n certificate: CertificateFacts | null;\n /** Plain-language problems visible in the certificate we were served. */\n certificateNotes: string[];\n}\n\nfunction formatDate(unixSeconds: number): string {\n return new Date(unixSeconds * 1000).toLocaleDateString(\"en-GB\", {\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n });\n}\n\n/**\n * Why there is no \"issued for another site\" note here.\n *\n * There was one, and it was wrong about most of the web. Playwright's\n * `securityDetails()` returns the Common Name and **no SAN list** — its own\n * documentation says `subjectName` \"should only be used for informational\n * purposes\" — and which hosts a certificate covers has lived in the SAN\n * extension, not the CN, for years. Judging coverage from the CN alone therefore\n * fails on every site fronted by a CDN or serving several brands from one\n * certificate.\n *\n * Measured against six real sites, four would have been reported as serving\n * someone else's certificate while their SAN covered the host perfectly:\n *\n * | host | CN | SAN covers it |\n * |-------------------|---------------------------------------|---------------|\n * | www.hubspot.com | b115500f.sni.cloudflaressl.com | yes |\n * | www.atlassian.com | *.atlassian.net | yes |\n * | webflow.com | *.us-east-1-prod.kube.webflow.services| yes |\n * | www.notion.com | notion.com | yes |\n *\n * A note that fires on two thirds of healthy captures does not make anyone more\n * careful; it teaches the reader to skip the notes. The dates below stay because\n * `validFrom`/`validTo` are the whole fact, not one sample of a list — the\n * browser tells us everything needed to decide them.\n */\nexport function describeCapturedCertificate(\n details: CertificateFacts | null | undefined,\n now: number = Date.now(),\n): CaptureSecurity {\n if (!details) {\n return {\n certificateValidated: false,\n certificate: null,\n certificateNotes: [\"This page was served over an unencrypted connection, so nothing about it could be verified.\"],\n };\n }\n\n const notes: string[] = [];\n // Every problem, not the first: \"expired\" and \"not valid yet\" are different\n // facts about how much this capture is worth trusting, and stopping at one\n // would hide the other behind it.\n if (details.validTo !== undefined && details.validTo * 1000 < now) {\n notes.push(`The site's security certificate expired on ${formatDate(details.validTo)}.`);\n }\n if (details.validFrom !== undefined && details.validFrom * 1000 > now) {\n notes.push(`The site's security certificate is not valid until ${formatDate(details.validFrom)}.`);\n }\n\n return { certificateValidated: false, certificate: details, certificateNotes: notes };\n}\n","import type { Page, Response } from \"playwright\";\nimport { type CaptureSecurity, describeCapturedCertificate } from \"./certificate.ts\";\n\n/**\n * Get a freshly-navigated page into a state worth photographing: everything\n * lazy-loaded, fonts settled, nothing moving, no consent overlay in the way.\n */\n\n/**\n * A navigation destroyed the world mid-`evaluate`. Retryable, never fatal.\n *\n * `waitUntil: \"domcontentloaded\"` returns the moment the first HTML parses, so\n * anything the page decides *after* booting — a locale redirect, an apex→www\n * hop, a bot checkpoint handing over the real page — lands while we are inside\n * one of the long in-page passes below. Chromium tears the execution context\n * down and every pending `evaluate` rejects.\n *\n * Deliberately narrow. A `TypeError` in an injected snippet must keep throwing:\n * retrying it would run the same broken code twice and report the second\n * failure, which is strictly worse than reporting the first.\n */\nexport function isNavigationTeardown(error: unknown): boolean {\n const message = error instanceof Error ? error.message : typeof error === \"string\" ? error : \"\";\n return (\n message.includes(\"Execution context was destroyed\") ||\n message.includes(\"Cannot find context with specified id\") ||\n message.includes(\"frame was detached\") ||\n message.includes(\"has been closed\")\n );\n}\n\nconst CONSENT_SELECTORS = [\n \"#onetrust-accept-btn-handler\",\n \"#CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll\",\n \"button#didomi-notice-agree-button\",\n \"[aria-label='Accept all']\",\n \"[data-testid='uc-accept-all-button']\",\n \".cc-allow\",\n \".cookie-accept\",\n];\n\nconst CONSENT_TEXTS = [\"Accept all\", \"Accept All\", \"Allow all\", \"I agree\", \"Got it\", \"Aceptar todo\"];\n\n/**\n * Consent platforms, blocked at the network layer.\n *\n * Clicking the banner away is unreliable by design: several of these render\n * into a **closed** shadow root, where no locator — Playwright's included —\n * can reach the button. Webflow (Transcend) is the case that forced this.\n * Never loading the script is both robust and faster; the click pass below\n * stays as a fallback for first-party banners we can't block by host.\n */\nconst CONSENT_HOSTS = [\n \"transcend-cdn.com\",\n \"cookielaw.org\",\n \"onetrust.com\",\n \"cookiebot.com\",\n \"osano.com\",\n \"trustarc.com\",\n \"truste.com\",\n \"usercentrics.eu\",\n \"didomi.io\",\n \"privacy-center.org\",\n \"iubenda.com\",\n \"termly.io\",\n \"cookieyes.com\",\n \"sp-prod.net\",\n \"quantcast.com\",\n \"consensu.org\",\n \"ketch.com\",\n \"secureprivacy.ai\",\n \"civicuk.com\",\n];\n\n/**\n * Must be installed before navigation. Aborting rather than fulfilling is\n * deliberate — a stubbed 200 leaves some managers retrying in a loop.\n */\nexport async function blockConsentManagers(page: Page): Promise<void> {\n await page.route(\"**/*\", (route) => {\n let host = \"\";\n try {\n host = new URL(route.request().url()).host;\n } catch {\n return route.continue();\n }\n const isConsentVendor = CONSENT_HOSTS.some((vendor) => host === vendor || host.endsWith(`.${vendor}`));\n return isConsentVendor ? route.abort() : route.continue();\n });\n}\n\n/**\n * Swallow a rejection where failing is an expected outcome, not an error —\n * a page with no consent banner, or one that never reaches network idle.\n */\nconst ignore = (): undefined => undefined;\n\nexport interface PrepareResult {\n finalUrl: string;\n title: string;\n documentHeight: number;\n /** HTTP status of the main document; null when the browser didn't report one. */\n status: number | null;\n /** First ~2000 chars of visible text, for the blocked-page check. */\n bodyText: string;\n /**\n * What the capture was served, security-wise — and the standing admission\n * that it did not validate it. See `certificate.ts`.\n */\n security: CaptureSecurity;\n}\n\nexport async function preparePage(page: Page, url: string, timeoutMs: number): Promise<PrepareResult> {\n const documentStatus = trackMainDocumentStatus(page);\n try {\n const response = await page.goto(url, { waitUntil: \"domcontentloaded\", timeout: timeoutMs });\n\n // Before any in-page work: let the page finish deciding where it lives.\n await settleNavigation(page);\n\n // Best-effort: a page with a long-poll or an ad beacon never reaches\n // networkidle, and waiting the full timeout for it buys nothing.\n await page.waitForLoadState(\"networkidle\", { timeout: 8_000 }).catch(ignore);\n\n // Consent managers inject late and often only after first scroll, so sweep\n // on both sides of the scroll pass. A banner left standing covers the hero,\n // and every section screenshot inherits it.\n await dismissConsent(page, 4_000);\n await scrollThroughPage(page);\n await dismissConsent(page, 1_000);\n\n await acrossNavigation(page, () =>\n page.evaluate(async () => {\n await document.fonts.ready;\n }),\n );\n\n await freezeMotion(page);\n await unpinOverlays(page);\n\n const measured = await acrossNavigation(page, () =>\n page.evaluate(() => ({\n finalUrl: location.href,\n title: document.title,\n documentHeight: Math.max(document.documentElement.scrollHeight, document.body?.scrollHeight ?? 0),\n bodyText: (document.body?.innerText ?? \"\").slice(0, 2000),\n })),\n );\n // Read off the document we ended up on, not the one we asked for: a site\n // that hands over to another host serves that host's certificate, and\n // judging the destination by the hop's certificate describes neither.\n const served = documentStatus.lastResponse() ?? response;\n const certificate = await served?.securityDetails().catch(() => null);\n\n return {\n ...measured,\n status: documentStatus.last() ?? response?.status() ?? null,\n security: describeCapturedCertificate(certificate),\n };\n } finally {\n documentStatus.stop();\n }\n}\n\n/**\n * The status of the document we ended up on, not the one we asked for.\n *\n * `page.goto()` resolves against the *first* response, which for a challenged\n * site is the challenge. personio.com is the case that forced this: the apex\n * answers 429 with a Vercel checkpoint, that page reloads through a 308 to\n * `www`, which answers 429 with a second checkpoint, and only the fourth\n * document — a 200 — is the real 13,000px homepage. Judging blocked-ness on\n * `goto`'s 429 refuses a site that works perfectly; judging it on the last\n * document refuses only a checkpoint that never cleared, which is the actual\n * question. Redirects are skipped because a hop is not a destination.\n */\nfunction trackMainDocumentStatus(page: Page): {\n last: () => number | null;\n lastResponse: () => Response | null;\n stop: () => void;\n} {\n let status: number | null = null;\n let last: Response | null = null;\n const onResponse = (response: Response) => {\n const request = response.request();\n if (request.resourceType() !== \"document\" || request.frame() !== page.mainFrame()) return;\n const code = response.status();\n if (code >= 300 && code < 400) return;\n status = code;\n // Kept as well as its status: the certificate belongs to this response, and\n // `page.goto`'s own response is the checkpoint on a challenged site.\n last = response;\n };\n page.on(\"response\", onResponse);\n return { last: () => status, lastResponse: () => last, stop: () => page.off(\"response\", onResponse) };\n}\n\n/** No further main-frame navigation for this long ⇒ the page has settled. */\nconst NAVIGATION_QUIET_MS = 1_500;\n/** Ceiling on the settle, so a page that redirects in a loop can't stall the run. */\nconst NAVIGATION_SETTLE_BUDGET_MS = 20_000;\n\n/**\n * Wait until the page stops navigating.\n *\n * Everything below assumes a stable document: the lazy-load scroll alone holds\n * an `evaluate` open for up to ten seconds, and a redirect landing inside that\n * window rejects it with \"Execution context was destroyed\" — which, unguarded,\n * took down the whole capture and surfaced to the user verbatim.\n *\n * Costs a page that never redirects one quiet period. That is the right trade\n * against re-running a capture, and cheap beside the 8s networkidle wait that\n * already follows it.\n */\nexport async function settleNavigation(page: Page, budgetMs = NAVIGATION_SETTLE_BUDGET_MS): Promise<void> {\n let lastNavigatedAt = Date.now();\n const onNavigated = (frame: unknown) => {\n if (frame === page.mainFrame()) lastNavigatedAt = Date.now();\n };\n page.on(\"framenavigated\", onNavigated);\n try {\n const deadline = Date.now() + budgetMs;\n while (Date.now() < deadline && Date.now() - lastNavigatedAt < NAVIGATION_QUIET_MS) {\n await page.waitForTimeout(250);\n }\n } finally {\n page.off(\"framenavigated\", onNavigated);\n }\n}\n\n/**\n * Run in-page work that a navigation may interrupt, and survive it.\n *\n * The settle above catches the common case, but nothing bounds when a page\n * redirects — a market-selector or an A/B script can fire well after load. When\n * that happens the work was performed against a document that no longer exists,\n * so the answer is to wait for the new one and do it again, not to fail.\n */\nasync function acrossNavigation<T>(page: Page, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error) {\n if (!isNavigationTeardown(error)) throw error;\n await settleNavigation(page);\n return await run();\n }\n}\n\n/**\n * A cookie wall covers the hero and poisons both the screenshots and the\n * segmentation. Failure here is fine — plenty of pages have no banner.\n */\n/**\n * Keep sweeping until the consent banner is really gone.\n *\n * One pass is not enough. Several managers mount well after `networkidle`, and\n * others only after the first scroll — the capture path gets away with a single\n * early attempt purely because its lazy-load scroll happens to buy ten seconds\n * before the second. Anything that captures without that scroll (the motion\n * take) needs the waiting made explicit, or it films a cookie modal.\n */\nexport async function settleConsent(page: Page): Promise<void> {\n await dismissConsent(page, 4_000);\n await page.mouse.wheel(0, 400).catch(ignore);\n await page.waitForTimeout(1_500);\n await dismissConsent(page, 2_000);\n await page.evaluate(() => window.scrollTo(0, 0)).catch(ignore);\n}\n\nexport async function dismissConsent(page: Page, waitForBannerMs: number): Promise<void> {\n // Give a late-injecting manager a moment to mount before we decide it isn't\n // there. Racing all known selectors costs nothing when there is no banner.\n await page\n .locator(CONSENT_SELECTORS.join(\", \"))\n .first()\n .waitFor({ state: \"attached\", timeout: waitForBannerMs })\n .catch(ignore);\n\n for (const selector of CONSENT_SELECTORS) {\n const found = page.locator(selector).first();\n if (!(await found.count().catch(() => 0))) continue;\n await found.click({ timeout: 2_000, force: true }).catch(ignore);\n await page.waitForTimeout(400);\n return;\n }\n\n for (const text of CONSENT_TEXTS) {\n const button = page.getByRole(\"button\", { name: text, exact: false }).first();\n if (!(await button.count().catch(() => 0))) continue;\n if (!(await button.isVisible().catch(() => false))) continue;\n await button.click({ timeout: 2_000, force: true }).catch(ignore);\n await page.waitForTimeout(400);\n return;\n }\n}\n\n/**\n * Walk the whole page so lazy images and scroll-triggered content mount.\n *\n * The longest-held `evaluate` in the capture — up to ten seconds — which makes\n * it overwhelmingly the one a late redirect lands inside. This is exactly where\n * personio.com died.\n */\nasync function scrollThroughPage(page: Page): Promise<void> {\n await acrossNavigation(page, () =>\n page.evaluate(async () => {\n const step = 600;\n const pause = () => new Promise((resolve) => setTimeout(resolve, 250));\n for (let i = 0; i < 40; i++) {\n window.scrollBy(0, step);\n await pause();\n const reachedBottom = window.scrollY + window.innerHeight >= document.documentElement.scrollHeight - 2;\n if (reachedBottom) break;\n }\n window.scrollTo(0, 0);\n await pause();\n }),\n );\n await page.waitForTimeout(500);\n}\n\n/** How tall a top-anchored `fixed` element may be and still count as a header. */\nconst MAX_HEADER_HEIGHT = 220;\n\n/**\n * Return viewport-pinned elements to the document flow.\n *\n * This is the single highest-impact correctness fix in the capture path. A\n * `position: sticky` header travels with the viewport, so Playwright paints it\n * into *every* section screenshot it happens to be sitting over — and not\n * merely as a cosmetic band across the top: on a centred content column the\n * full-width header lands offset, and it covers the section's own heading. We\n * were shipping sections whose title had been erased by a navbar.\n *\n * `static` restores a sticky element's real in-flow position, so it appears\n * exactly once, where it belongs. `fixed` chrome (chat bubbles, cookie bars,\n * back-to-top buttons) has no in-flow position to restore, so it is hidden —\n * except a top-anchored header, which is real page design worth keeping and is\n * simply re-anchored into the document.\n */\nfunction inPageUnpinOverlays(maxHeaderHeight: number): void {\n window.scrollTo(0, 0);\n for (const element of Array.from(document.querySelectorAll<HTMLElement>(\"*\"))) {\n const position = getComputedStyle(element).position;\n\n if (position === \"sticky\") {\n element.style.setProperty(\"position\", \"static\", \"important\");\n continue;\n }\n if (position !== \"fixed\") continue;\n\n const rect = element.getBoundingClientRect();\n const isTopAnchoredHeader = rect.top <= 8 && rect.height > 0 && rect.height <= maxHeaderHeight;\n if (isTopAnchoredHeader) {\n element.style.setProperty(\"position\", \"absolute\", \"important\");\n element.style.setProperty(\"bottom\", \"auto\", \"important\");\n } else {\n element.style.setProperty(\"display\", \"none\", \"important\");\n }\n }\n}\n\nasync function unpinOverlays(page: Page): Promise<void> {\n await acrossNavigation(page, () => page.evaluate(inPageUnpinOverlays, MAX_HEADER_HEIGHT));\n await page.waitForTimeout(250);\n}\n\n/**\n * Stop the page moving. Carousels, counters and marquees otherwise make every\n * capture differ from the last, and a section screenshot taken mid-transition\n * shows a half-faded element.\n */\nasync function freezeMotion(page: Page): Promise<void> {\n await acrossNavigation(page, () =>\n page.evaluate(() => {\n const highestTimer = window.setTimeout(() => undefined, 0) as unknown as number;\n for (let id = 1; id <= highestTimer; id++) window.clearInterval(id);\n\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-baker-freeze\", \"true\");\n style.textContent = `*, *::before, *::after {\n animation-play-state: paused !important;\n animation-delay: 0s !important;\n transition: none !important;\n }`;\n document.head.appendChild(style);\n\n for (const video of Array.from(document.querySelectorAll(\"video\"))) {\n video.pause();\n }\n }),\n );\n await page.waitForTimeout(250);\n}\n","/**\n * Pure geometry for visual section segmentation.\n *\n * Every function here is injected into the scraped page verbatim via\n * `Function.prototype.toString()` (see `segment.ts`), so each one must be\n * **entirely self-contained**: no imports, no module-scope constants, no\n * references to anything outside its own body. Thresholds are inlined\n * deliberately for that reason — not by oversight.\n *\n * Ported from the `ad-to-landing` detailed scraper, whose tuning is the result\n * of running against a lot of real pages. Treat the numbers as data, not as\n * choices to revisit casually.\n */\n\nexport interface Band {\n top: number;\n bottom: number;\n}\n\n/**\n * Learn the page's own whitespace rhythm: the vertical gap below which two\n * stacked elements read as \"the same block\".\n *\n * A fixed threshold cannot serve both a dense enterprise page and an airy\n * luxury one, so we measure every gap between consecutive bands and take the\n * 75th percentile.\n */\nexport function adaptiveGapThreshold(bands: Band[]): number {\n const sorted = [...bands].sort((a, b) => a.top - b.top);\n const gaps: number[] = [];\n\n for (let i = 0; i < sorted.length - 1; i++) {\n const current = sorted[i];\n const next = sorted[i + 1];\n if (!current || !next) continue;\n if (next.top > current.bottom) {\n const gap = next.top - current.bottom;\n // A gap this wide is already a section break. Letting it into the sample\n // would drag the percentile up until the whole page reads as one band.\n if (gap < 200) gaps.push(gap);\n }\n }\n\n gaps.sort((a, b) => a - b);\n const p75 = gaps[Math.floor(gaps.length * 0.75)];\n if (p75 === undefined) return 15;\n return Math.max(10, Math.min(50, p75));\n}\n\n/**\n * Do two bands belong to the same visual block?\n *\n * Vertical axis only — horizontal position is deliberately ignored, which is\n * what makes a three-column feature row read as one section instead of three.\n * `margin` shrinks both bands slightly so elements that merely touch don't\n * count as overlapping.\n */\nexport function bandsCollide(a: Band, b: Band, margin: number, maxGap: number): boolean {\n const shrunkA = { top: a.top + margin, bottom: a.bottom - margin };\n const shrunkB = { top: b.top + margin, bottom: b.bottom - margin };\n\n const overlaps =\n (shrunkA.top <= shrunkB.bottom && shrunkA.bottom >= shrunkB.top) ||\n (shrunkB.top <= shrunkA.bottom && shrunkB.bottom >= shrunkA.top);\n if (overlaps) return true;\n\n const gap = Math.min(Math.abs(shrunkA.bottom - shrunkB.top), Math.abs(shrunkB.bottom - shrunkA.top));\n return gap <= maxGap;\n}\n\n/**\n * Should this group dissolve into its parent?\n *\n * A cluster with barely any content — a lone eyebrow line, a thin divider\n * strip — is not a section; it is a fragment of the section above or below it.\n * Promoting it to its parent re-attaches it. The parent-height ceiling stops\n * the promotion from running away and swallowing the whole page.\n */\nexport function shouldPromoteToParent(group: { childCount: number; height: number; parentHeight: number }): boolean {\n const isRunt = group.childCount < 3 || group.height < 80;\n return isRunt && group.parentHeight < 1600;\n}\n","import type { Page } from \"playwright\";\nimport { adaptiveGapThreshold, bandsCollide, shouldPromoteToParent } from \"./geometry.ts\";\nimport type { SectionCandidate, SegmentOptions } from \"./types.ts\";\n\n/**\n * Visual section segmentation.\n *\n * Landing pages built by Framer, Webflow and Next emit meaningless div soup —\n * `<section>`, landmarks and class names tell you nothing. So we ignore the\n * markup's opinion entirely and read the page the way an eye does: collect the\n * elements that actually carry content, then cluster them into bands separated\n * by whitespace.\n *\n * Ported from the `ad-to-landing` detailed scraper. Its thresholds are the\n * product of running against a lot of real pages; they are data, not choices.\n */\n\n/**\n * Prepare the page to host our in-page code. Must run **before** navigation:\n * Playwright injects init scripts through CDP ahead of the document, which both\n * guarantees availability and sidesteps the page's own CSP — a plain `eval` or\n * an injected `<script>` is blocked on plenty of real sites.\n *\n * Two things go in:\n *\n * 1. A `__name` shim. esbuild's `keepNames` (which `tsx` turns on) wraps every\n * named function in `__name(fn, \"fn\")`. That helper lives in the module\n * scope we just left behind when Playwright serialised the function, so\n * without the shim every in-page call dies with `__name is not defined`.\n * Shimming it here keeps us independent of how the CLI happens to be built.\n * 2. The unit-tested geometry from `geometry.ts`, stringified. This is why\n * those functions must be self-contained.\n */\nexport async function installPageRuntime(page: Page): Promise<void> {\n await page.addInitScript({\n content: `\n window.__name = window.__name || function (target) { return target; };\n window.__bakerGeom = {\n adaptiveGapThreshold: ${adaptiveGapThreshold.toString()},\n bandsCollide: ${bandsCollide.toString()},\n shouldPromoteToParent: ${shouldPromoteToParent.toString()},\n };`,\n });\n}\n\nexport async function segmentPage(page: Page, options: SegmentOptions): Promise<SectionCandidate[]> {\n return await page.evaluate(inPageSegment, options);\n}\n\n/**\n * Everything below runs inside the scraped page. Playwright serialises this\n * function, so it may not reference anything from module scope — every helper\n * is nested deliberately, and the shared geometry arrives via `window.__bakerGeom`.\n *\n * That constraint is also why this file carries a `noExcessiveCognitiveComplexity`\n * override in `biome.json`: the helpers below cannot be hoisted out into their\n * own functions without breaking serialisation. The parts that *can* live\n * outside — the geometry thresholds — already do, in `geometry.ts`, where they\n * are unit-tested.\n */\nconst inPageSegment = (options: SegmentOptions): SectionCandidate[] => {\n const geom = (window as unknown as { __bakerGeom: BakerGeom }).__bakerGeom;\n\n interface Band {\n top: number;\n bottom: number;\n }\n interface BakerGeom {\n adaptiveGapThreshold(bands: Band[]): number;\n bandsCollide(a: Band, b: Band, margin: number, maxGap: number): boolean;\n shouldPromoteToParent(g: { childCount: number; height: number; parentHeight: number }): boolean;\n }\n interface Leaf {\n element: Element;\n top: number;\n bottom: number;\n left: number;\n right: number;\n height: number;\n }\n interface Group {\n root: Element;\n top: number;\n bottom: number;\n left: number;\n right: number;\n height: number;\n leaves: Leaf[];\n /** Set once a group has proven un-mergeable, so it is never retried. */\n sealed: boolean;\n }\n\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n const docWidth = Math.max(document.documentElement.scrollWidth, document.body?.scrollWidth ?? 0);\n const docHeight = Math.max(document.documentElement.scrollHeight, document.body?.scrollHeight ?? 0);\n\n /** Document-absolute rect, clamped to the document box. */\n const rectOf = (element: Element) => {\n const r = element.getBoundingClientRect();\n const top = Math.max(0, Math.round(r.top + scrollY));\n const left = Math.max(0, Math.round(r.left + scrollX));\n return {\n top,\n left,\n bottom: Math.min(docHeight, Math.round(r.bottom + scrollY)),\n right: Math.min(docWidth, Math.round(r.right + scrollX)),\n };\n };\n\n /**\n * `display: contents` elements have no box of their own; borrow the union of\n * the children they lay out.\n */\n const syntheticRect = (element: Element) => {\n const children = Array.from(element.children);\n if (children.length === 0) return null;\n let top = Number.POSITIVE_INFINITY;\n let left = Number.POSITIVE_INFINITY;\n let bottom = Number.NEGATIVE_INFINITY;\n let right = Number.NEGATIVE_INFINITY;\n for (const child of children) {\n const r = rectOf(child);\n if (r.bottom - r.top <= 0 && r.right - r.left <= 0) continue;\n top = Math.min(top, r.top);\n left = Math.min(left, r.left);\n bottom = Math.max(bottom, r.bottom);\n right = Math.max(right, r.right);\n }\n if (!Number.isFinite(top) || !Number.isFinite(bottom)) return null;\n return { top, left, bottom, right };\n };\n\n const boxOf = (element: Element) => {\n const style = getComputedStyle(element);\n const r = style.display === \"contents\" ? syntheticRect(element) : rectOf(element);\n if (!r) return null;\n return { ...r, height: r.bottom - r.top, width: r.right - r.left };\n };\n\n /** Walks ancestors for the styles that hide a subtree outright. */\n const hasHiddenAncestor = (element: Element | null): boolean => {\n let current: Element | null = element;\n while (current && current !== document.documentElement) {\n const style = getComputedStyle(current);\n if (style.display === \"none\" || style.visibility === \"hidden\" || Number(style.opacity) === 0) return true;\n current = current.parentElement;\n }\n return false;\n };\n\n /**\n * The subtle one: an ancestor with `overflow: hidden` can clip an element out\n * of sight without any of its own styles changing. Off-screen carousel slides\n * and closed mobile menus live here — without this check they become phantom\n * sections stacked at the page edges.\n */\n const isClippedByAncestor = (element: Element, box: { top: number; bottom: number; left: number; right: number }) => {\n let parent = element.parentElement;\n while (parent && parent !== document.documentElement) {\n const style = getComputedStyle(parent);\n const clips =\n style.overflow === \"hidden\" ||\n style.overflowX === \"hidden\" ||\n style.overflowY === \"hidden\" ||\n style.overflow === \"clip\";\n if (clips) {\n const p = rectOf(parent);\n const intersects = box.left < p.right && box.right > p.left && box.top < p.bottom && box.bottom > p.top;\n if (!intersects) return true;\n }\n parent = parent.parentElement;\n }\n return false;\n };\n\n /**\n * Text owned by this element directly. A wrapper holding 40 words spread over\n * its descendants does not qualify — only the element the text node hangs off\n * does. This is what keeps the leaf set from collapsing into `<body>`.\n */\n const directText = (element: Element) => {\n let text = \"\";\n for (const node of Array.from(element.childNodes)) {\n if (node.nodeType === 3) text += node.textContent ?? \"\";\n }\n return text.trim();\n };\n\n /** Tags whose text content is code, not copy. */\n const NON_COPY_TAGS = new Set([\"SCRIPT\", \"STYLE\", \"NOSCRIPT\", \"TEMPLATE\"]);\n\n /**\n * Text a visitor would actually read.\n *\n * `Element.textContent` happily returns the contents of `<style>` and\n * JSON-LD `<script>` blocks, which page builders sprinkle throughout the\n * body — Webflow pages come back as walls of CSS, and every downstream\n * consumer (previews, copy extraction, the classifier) inherits the mess.\n */\n const visibleText = (root: Element) => {\n let text = \"\";\n const hiddenCache = new Map<Element, boolean>();\n const isHidden = (element: Element) => {\n const cached = hiddenCache.get(element);\n if (cached !== undefined) return cached;\n const style = getComputedStyle(element);\n const hidden = style.display === \"none\" || style.visibility === \"hidden\";\n hiddenCache.set(element, hidden);\n return hidden;\n };\n\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode: (node) => {\n let parent = node.parentElement;\n while (parent) {\n // JSON-LD blocks and SEO-only copy hide in `display:none` wrappers\n // all over builder output; they are markup, not something a visitor\n // ever reads.\n if (NON_COPY_TAGS.has(parent.tagName) || isHidden(parent)) return NodeFilter.FILTER_REJECT;\n if (parent === root) break;\n parent = parent.parentElement;\n }\n return NodeFilter.FILTER_ACCEPT;\n },\n });\n while (walker.nextNode() && text.length < 400) {\n text += ` ${walker.currentNode.textContent ?? \"\"}`;\n }\n return text.replace(/\\s+/g, \" \").trim();\n };\n\n const GRAPHIC_TAGS = new Set([\"img\", \"svg\", \"video\", \"picture\", \"canvas\", \"iframe\"]);\n\n const hasBackgroundImage = (element: Element) => {\n const bg = getComputedStyle(element).backgroundImage;\n return Boolean(bg) && bg !== \"none\" && bg.includes(\"url(\");\n };\n\n const isContentLeaf = (element: Element) => {\n const tag = element.tagName.toLowerCase();\n if (GRAPHIC_TAGS.has(tag)) return true;\n if (directText(element).length > 0) return true;\n return hasBackgroundImage(element);\n };\n\n /** nth-of-type path — stable enough to re-resolve on a second load. */\n const selectorFor = (element: Element): string => {\n const parts: string[] = [];\n let current: Element | null = element;\n while (current && current !== document.documentElement) {\n const tag = current.tagName.toLowerCase();\n if (tag === \"body\") {\n parts.unshift(\"body\");\n break;\n }\n const parent: Element | null = current.parentElement;\n if (!parent) {\n parts.unshift(tag);\n break;\n }\n const sameTag = Array.from(parent.children).filter((c) => c.tagName === current?.tagName);\n const position = sameTag.indexOf(current) + 1;\n parts.unshift(sameTag.length > 1 ? `${tag}:nth-of-type(${position})` : tag);\n current = parent;\n }\n return parts.join(\" > \");\n };\n\n // ---- 1. Collect the leaves that actually carry content -------------------\n\n const leaves: Leaf[] = [];\n const all = document.querySelectorAll(\"*\");\n const limit = Math.min(all.length, options.maxElements);\n\n for (let i = 0; i < limit; i++) {\n const element = all[i];\n if (!element) continue;\n const tag = element.tagName.toLowerCase();\n if (tag === \"script\" || tag === \"style\" || tag === \"noscript\" || tag === \"link\" || tag === \"head\") continue;\n if (!isContentLeaf(element)) continue;\n\n const box = boxOf(element);\n if (!box || box.height <= 0 || box.width <= 0) continue;\n // Taller than two viewports: this is page scaffolding, not a content leaf.\n if (box.height > options.maxSectionHeight) continue;\n if (hasHiddenAncestor(element)) continue;\n if (isClippedByAncestor(element, box)) continue;\n\n leaves.push({\n element,\n top: box.top,\n bottom: box.bottom,\n left: box.left,\n right: box.right,\n height: box.height,\n });\n }\n\n if (leaves.length === 0) return [];\n\n // ---- 2. Learn this page's whitespace rhythm ------------------------------\n\n const gapThreshold = geom.adaptiveGapThreshold(leaves.map((l) => ({ top: l.top, bottom: l.bottom })));\n\n // ---- 3. Cluster, climb to the common ancestor, repeat to a fixpoint ------\n\n const commonAncestor = (elements: Element[]): Element | null => {\n let ancestor: Element | null = elements[0] ?? null;\n while (ancestor && !elements.every((e) => ancestor?.contains(e))) {\n ancestor = ancestor.parentElement;\n }\n return ancestor;\n };\n\n /** Give up on a merge, and make sure we never retry it. */\n const abandon = (members: Group[]): Group[] => members.map((m) => ({ ...m, sealed: true }));\n\n /**\n * Climb from `start` until we reach an element whose box covers `bounds`.\n *\n * Returns null when there is no honest answer: we ran out of DOM, or the only\n * container big enough is taller than a section can be — meaning we've climbed\n * out of the section and into the page shell.\n */\n const findCoveringAncestor = (\n start: Element | null,\n bounds: { top: number; bottom: number; left: number; right: number },\n ): { element: Element; box: { top: number; bottom: number; left: number; right: number; height: number } } | null => {\n let element: Element | null = start;\n while (element) {\n const box = boxOf(element);\n if (!box) return null;\n if (box.height > options.maxSectionHeight) return null;\n const covers =\n box.top <= bounds.top && box.bottom >= bounds.bottom && box.left <= bounds.left && box.right >= bounds.right;\n if (covers) return { element, box };\n if (!element.parentElement || element.parentElement === document.documentElement) return null;\n element = element.parentElement;\n }\n return null;\n };\n\n /**\n * Try to merge a colliding bucket into the DOM node that contains all of it.\n *\n * Returns the members untouched-but-sealed when the merge would be a lie:\n * either no shared container covers them, or the one that does is so tall it\n * is clearly the page shell rather than a section. Accepting an overshoot\n * here is what collapses an entire page into a single \"section\".\n */\n const mergeBucket = (members: Group[]): Group[] => {\n const bounds = {\n top: Math.min(...members.map((m) => m.top)),\n bottom: Math.max(...members.map((m) => m.bottom)),\n left: Math.min(...members.map((m) => m.left)),\n right: Math.max(...members.map((m) => m.right)),\n };\n\n const covering = findCoveringAncestor(commonAncestor(members.map((m) => m.root)), bounds);\n if (!covering) return abandon(members);\n\n return [\n {\n root: covering.element,\n top: covering.box.top,\n bottom: covering.box.bottom,\n left: covering.box.left,\n right: covering.box.right,\n height: covering.box.height,\n leaves: members.flatMap((m) => m.leaves),\n sealed: false,\n },\n ];\n };\n\n const clusterOnce = (groups: Group[]): Group[] => {\n const buckets: Group[][] = [];\n for (const group of groups) {\n if (group.sealed) {\n buckets.push([group]);\n continue;\n }\n const target = buckets.find((bucket) =>\n bucket.some(\n (member) =>\n !member.sealed &&\n geom.bandsCollide(\n { top: member.top, bottom: member.bottom },\n { top: group.top, bottom: group.bottom },\n options.collisionMargin,\n gapThreshold,\n ),\n ),\n );\n if (target) target.push(group);\n else buckets.push([group]);\n }\n // Nothing merged — we've converged.\n if (buckets.length === groups.length) return groups;\n return buckets.flatMap((bucket) => (bucket.length === 1 ? [bucket[0] as Group] : mergeBucket(bucket)));\n };\n\n let groups: Group[] = leaves.map((leaf) => ({\n root: leaf.element,\n top: leaf.top,\n bottom: leaf.bottom,\n left: leaf.left,\n right: leaf.right,\n height: leaf.height,\n leaves: [leaf],\n sealed: false,\n }));\n\n for (let pass = 0; pass < 40; pass++) {\n const next = clusterOnce(groups);\n if (next.length === groups.length) break;\n groups = next;\n }\n\n // ---- 4. Dissolve runt groups into their parent --------------------------\n\n for (let pass = 0; pass < 10; pass++) {\n let promoted = false;\n groups = groups.map((group) => {\n const parent = group.root.parentElement;\n if (!parent || parent === document.documentElement || parent === document.body) return group;\n const parentBox = boxOf(parent);\n if (!parentBox) return group;\n if (\n !geom.shouldPromoteToParent({\n childCount: group.leaves.length,\n height: group.height,\n parentHeight: parentBox.height,\n })\n ) {\n return group;\n }\n promoted = true;\n return {\n ...group,\n root: parent,\n top: parentBox.top,\n bottom: parentBox.bottom,\n left: parentBox.left,\n right: parentBox.right,\n height: parentBox.height,\n };\n });\n if (!promoted) break;\n groups = clusterOnce(groups);\n }\n\n // ---- 5. Drop contained duplicates, order top-to-bottom ------------------\n\n /**\n * Two groups occupying the same box are the same section, however unrelated\n * their roots look. Builders routinely ship a wrapper plus an inner element\n * that measure identically, or a duplicate subtree for a responsive/animated\n * variant — containment alone doesn't catch the sibling case.\n */\n const sameBox = (a: Group, b: Group) =>\n Math.abs(a.top - b.top) <= 4 &&\n Math.abs(a.bottom - b.bottom) <= 4 &&\n Math.abs(a.left - b.left) <= 4 &&\n Math.abs(a.right - b.right) <= 4;\n\n /**\n * `outer` visually swallows `inner`.\n *\n * A group sitting entirely inside another's box is a column or a card, not a\n * section — and cropping to it yields a screenshot sliced through the middle\n * of the real section's heading.\n */\n const containsBox = (outer: Group, inner: Group) =>\n outer.top - 4 <= inner.top &&\n outer.bottom + 4 >= inner.bottom &&\n outer.left - 4 <= inner.left &&\n outer.right + 4 >= inner.right;\n\n const deduped: Group[] = [];\n // Largest box first, so the outer container is always seen before anything it\n // swallows — sorting by height alone lets a half-width column tie with its own\n // parent and survive as a sliced-through \"section\". Equal areas fall back to\n // whichever group actually gathered more content.\n const area = (g: Group) => (g.right - g.left) * g.height;\n for (const group of groups.slice().sort((a, b) => area(b) - area(a) || b.leaves.length - a.leaves.length)) {\n const duplicate = deduped.some(\n (kept) =>\n kept.root === group.root || kept.root.contains(group.root) || sameBox(kept, group) || containsBox(kept, group),\n );\n if (!duplicate) deduped.push(group);\n }\n\n return deduped\n .filter((group) => group.height > 0 && group.right - group.left > 0)\n .sort((a, b) => a.top - b.top)\n .map((group, index) => ({\n index,\n selector: selectorFor(group.root),\n rect: {\n top: group.top,\n left: group.left,\n width: group.right - group.left,\n height: group.height,\n },\n leafCount: group.leaves.length,\n textPreview: visibleText(group.root).slice(0, 200),\n }));\n};\n","import type { Browser } from \"playwright\";\nimport { newPage } from \"./browser.ts\";\nimport { SECTION_ROOT_ATTRIBUTE } from \"./bundle.ts\";\n\n/**\n * Render a standalone section bundle and photograph it, so the result can be\n * compared against the live section.\n *\n * The viewport must match the width the section was captured at — the bundle\n * carries the page's media queries, so rendering it narrower silently produces\n * a different (mobile) layout and the fidelity score would blame the extractor\n * for a difference we caused.\n */\n/**\n * Jump every animation to its final keyframe.\n *\n * A lifted section replays its entrance animation from scratch on load, and an\n * entrance almost always *starts* hidden — `opacity: 0`, `translateY(-100%)`.\n * Screenshotting a moment later therefore catches the section mid-reveal, or\n * still invisible, and the fidelity score blames the extractor for a difference\n * the replay caused. A 1ms duration with `forwards` completes each animation\n * instantly and holds the end state, which is the settled look the live capture\n * shows.\n */\nconst SETTLE_ANIMATIONS_CSS = `*, *::before, *::after {\n animation-play-state: running !important;\n animation-delay: 0s !important;\n animation-duration: 1ms !important;\n animation-iteration-count: 1 !important;\n animation-fill-mode: forwards !important;\n transition: none !important;\n}`;\n\nexport async function renderBundleToPng(\n browser: Browser,\n html: string,\n viewportWidth: number,\n options: { wholePage?: boolean; timeoutMs?: number } = {},\n): Promise<Buffer | null> {\n const { wholePage = false, timeoutMs = 20_000 } = options;\n const { context, page } = await newPage(browser, { width: viewportWidth, height: 900 });\n try {\n await page.setContent(html, { waitUntil: \"load\", timeout: timeoutMs });\n await page.addStyleTag({ content: SETTLE_ANIMATIONS_CSS });\n // Webfonts arrive after `load`; screenshotting first captures a fallback\n // face and costs ~15 points of fidelity on type-led sections.\n await page.evaluate(async () => {\n await document.fonts.ready;\n });\n await page.waitForTimeout(300);\n\n if (!wholePage) {\n // The section sits inside reconstructed ancestor wrappers, whose padding\n // is not part of what was captured live — so photograph the tagged\n // section itself, falling back to the outermost node for older bundles.\n for (const selector of [`[${SECTION_ROOT_ATTRIBUTE}]`, \"body > *\"]) {\n const target = page.locator(selector).first();\n if (!(await target.count())) continue;\n const shot = await target.screenshot({ type: \"png\", timeout: timeoutMs }).catch(() => null);\n if (shot) return shot;\n }\n }\n return await page.screenshot({ type: \"png\", fullPage: true }).catch(() => null);\n } catch {\n return null;\n } finally {\n await context.close();\n }\n}\n","import { writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { ScrapedSection, ScrapeManifest } from \"./run.ts\";\n\n/**\n * A page you open to check a capture with your own eyes.\n *\n * Fidelity is a number, and a number can be right while the capture is wrong —\n * a section can score 0.98 because it is mostly white space, or score badly for\n * a reason that turns out to be correct. Every extraction bug found so far was\n * found by putting the live crop next to the re-render and looking, so that\n * comparison is the artifact rather than a summary of it.\n *\n * Self-contained and offline: it references the sibling PNGs by relative path,\n * so the whole output directory can be zipped and opened anywhere.\n */\nexport async function writeCaptureReport(manifest: ScrapeManifest, outDir: string): Promise<string> {\n const file = path.join(outDir, \"report.html\");\n await writeFile(file, renderReport(manifest));\n return file;\n}\n\n/** Exported for testing — pure, and the escaping matters (page copy is untrusted). */\nexport function escapeHtml(value: string): string {\n return value.replace(\n /[&<>\"']/g,\n (character) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[character] ?? character,\n );\n}\n\n/** Green ≥0.95, amber ≥0.85, red below — the thresholds the notes use in prose. */\nexport function fidelityTone(fidelity: number | null): \"good\" | \"fair\" | \"poor\" | \"unknown\" {\n if (fidelity === null) return \"unknown\";\n if (fidelity >= 0.95) return \"good\";\n if (fidelity >= 0.85) return \"fair\";\n return \"poor\";\n}\n\nexport function medianFidelity(sections: readonly ScrapedSection[]): number | null {\n const scored = sections\n .map((section) => section.fidelity)\n .filter((value): value is number => value !== null)\n .sort((a, b) => a - b);\n return scored.length === 0 ? null : (scored[Math.floor(scored.length / 2)] ?? null);\n}\n\nfunction formatFidelity(fidelity: number | null): string {\n return fidelity === null ? \"—\" : fidelity.toFixed(2);\n}\n\nfunction renderSection(section: ScrapedSection): string {\n const tone = fidelityTone(section.fidelity);\n const rendered = section.bundle ? section.bundle.replace(/section\\.html$/, \"section-rendered.png\") : null;\n\n const shot = (label: string, src: string | null, note?: string) => {\n if (!src) return `<figure class=\"shot empty\"><figcaption>${label} — none</figcaption></figure>`;\n return `<figure class=\"shot\">\n <figcaption>${label}${note ? ` <span class=\"note\">${escapeHtml(note)}</span>` : \"\"}</figcaption>\n <a href=\"${escapeHtml(src)}\" target=\"_blank\" rel=\"noopener\"><img src=\"${escapeHtml(src)}\" alt=\"\" loading=\"lazy\"></a>\n </figure>`;\n };\n\n return `<section class=\"card\">\n <header>\n <h2><span class=\"index\">${String(section.index).padStart(2, \"0\")}</span> ${section.rect.width}×${section.rect.height}</h2>\n <span class=\"badge ${tone}\">fidelity ${formatFidelity(section.fidelity)}</span>\n ${section.fidelityNote ? `<span class=\"badge warn\">${escapeHtml(section.fidelityNote)}</span>` : \"\"}\n ${section.motion.hasMotion ? `<span class=\"badge motion\">${escapeHtml(section.motion.summary)}</span>` : \"\"}\n </header>\n <p class=\"preview\">${escapeHtml(section.textPreview.slice(0, 220)) || \"<em>no text</em>\"}</p>\n <div class=\"shots\">\n ${shot(\"Live\", section.desktopShot)}\n ${shot(\"Reproduction\", rendered, \"rendered from the extracted bundle\")}\n ${shot(\"Mobile\", section.mobileShot)}\n </div>\n ${section.motionFilmstrip ? `<div class=\"filmstrip\">${shot(\"Motion — six frames, left to right\", section.motionFilmstrip)}</div>` : \"\"}\n <footer>\n <code>${escapeHtml(section.selector)}</code>\n ${section.bundle ? `<a href=\"${escapeHtml(section.bundle)}\" target=\"_blank\" rel=\"noopener\">open the standalone bundle →</a>` : \"\"}\n </footer>\n </section>`;\n}\n\nfunction renderReport(manifest: ScrapeManifest): string {\n const median = medianFidelity(manifest.sections);\n // Count sections that animate on their own, not ones that merely have a link\n // with a hover colour — `hasMotion` is true for almost every section and would\n // report \"16 of 16 move\", which is technically true and completely useless.\n const moving = manifest.sections.filter((section) => section.motionFilmstrip !== null).length;\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Capture report — ${escapeHtml(manifest.title || manifest.url)}</title>\n<style>\n :root { color-scheme: light dark; --line: #e5e7eb; --muted: #6b7280; --bg: #fafafa; --card: #fff; }\n @media (prefers-color-scheme: dark) {\n :root { --line: #27272a; --muted: #a1a1aa; --bg: #09090b; --card: #131316; }\n }\n * { box-sizing: border-box; }\n body { margin: 0; padding: 24px; background: var(--bg);\n font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif; }\n h1 { margin: 0 0 4px; font-size: 20px; }\n a { color: inherit; }\n .sub { color: var(--muted); margin: 0 0 20px; }\n .stats { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 24px; }\n .stat { border: 1px solid var(--line); border-radius: 10px; padding: 8px 12px; background: var(--card); }\n .stat b { display: block; font-size: 18px; }\n .stat span { color: var(--muted); font-size: 12px; }\n .card { border: 1px solid var(--line); border-radius: 12px; background: var(--card);\n padding: 16px; margin-bottom: 16px; }\n .card header { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }\n .card h2 { font-size: 15px; margin: 0; font-weight: 600; }\n .index { display: inline-block; min-width: 26px; color: var(--muted); }\n .badge { font-size: 12px; padding: 2px 8px; border-radius: 999px; border: 1px solid var(--line); }\n .badge.good { background: #dcfce7; color: #166534; border-color: #bbf7d0; }\n .badge.fair { background: #fef3c7; color: #92400e; border-color: #fde68a; }\n .badge.poor { background: #fee2e2; color: #991b1b; border-color: #fecaca; }\n .badge.warn { background: #fee2e2; color: #991b1b; border-color: #fecaca; }\n .badge.motion { background: #ede9fe; color: #5b21b6; border-color: #ddd6fe; }\n .preview { color: var(--muted); margin: 0 0 12px; font-size: 13px; }\n .shots { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 12px; align-items: start; }\n .filmstrip { margin-top: 12px; }\n figure { margin: 0; }\n figcaption { font-size: 12px; color: var(--muted); margin-bottom: 4px; }\n figcaption .note { opacity: .75; }\n .shot img { width: 100%; height: auto; border: 1px solid var(--line); border-radius: 8px;\n background: #fff; display: block; }\n .shot.empty { border: 1px dashed var(--line); border-radius: 8px; padding: 20px; text-align: center; }\n .card footer { display: flex; justify-content: space-between; gap: 12px; margin-top: 12px;\n font-size: 12px; color: var(--muted); }\n code { font: 12px ui-monospace, SFMono-Regular, Menlo, monospace; word-break: break-all; }\n</style>\n</head>\n<body>\n<h1>${escapeHtml(manifest.title || \"Capture report\")}</h1>\n<p class=\"sub\"><a href=\"${escapeHtml(manifest.finalUrl)}\" target=\"_blank\" rel=\"noopener\">${escapeHtml(manifest.finalUrl)}</a> · captured ${escapeHtml(manifest.capturedAt)}</p>\n\n<div class=\"stats\">\n <div class=\"stat\"><b>${manifest.sections.length}</b><span>sections</span></div>\n <div class=\"stat\"><b>${formatFidelity(median)}</b><span>median fidelity</span></div>\n <div class=\"stat\"><b>${formatFidelity(manifest.page.fidelity)}</b><span>whole page</span></div>\n <div class=\"stat\"><b>${moving}</b><span>filmed moving</span></div>\n <div class=\"stat\"><b>${manifest.documentHeight}px</b><span>page height</span></div>\n</div>\n\n<section class=\"card\">\n <header>\n <h2>Whole page</h2>\n <span class=\"badge ${fidelityTone(manifest.page.fidelity)}\">fidelity ${formatFidelity(manifest.page.fidelity)}</span>\n </header>\n <p class=\"preview\">The same extractor rooted at &lt;body&gt; — one standalone file that should render like the original.</p>\n <div class=\"shots\">\n <figure class=\"shot\"><figcaption>Live</figcaption><a href=\"full-page.png\" target=\"_blank\" rel=\"noopener\"><img src=\"full-page.png\" alt=\"\" loading=\"lazy\"></a></figure>\n ${\n manifest.page.bundle\n ? `<figure class=\"shot\"><figcaption>Reproduction <span class=\"note\">from page.html</span></figcaption><a href=\"page-rendered.png\" target=\"_blank\" rel=\"noopener\"><img src=\"page-rendered.png\" alt=\"\" loading=\"lazy\"></a></figure>`\n : `<figure class=\"shot empty\"><figcaption>Reproduction — none</figcaption></figure>`\n }\n </div>\n</section>\n\n${manifest.sections.map(renderSection).join(\"\\n\")}\n</body>\n</html>\n`;\n}\n","/** Absolute, document-relative rectangle (not viewport-relative). */\nexport interface SectionRect {\n top: number;\n left: number;\n width: number;\n height: number;\n}\n\n/** One candidate section, as the in-page segmenter sees it. */\nexport interface SectionCandidate {\n /** Top-to-bottom reading order on the page. */\n index: number;\n /**\n * nth-of-type path to the section's root element. The stable handle we use to\n * re-screenshot on mobile, drive motion capture, and match the same section\n * across re-scrapes.\n */\n selector: string;\n rect: SectionRect;\n /** How many content leaves clustered into this section — a crude density signal. */\n leafCount: number;\n /** First ~200 chars of visible text, for logging and eyeball checks. */\n textPreview: string;\n}\n\nexport interface SegmentOptions {\n /**\n * Elements taller than this are treated as page scaffolding rather than\n * content, and never become a section on their own.\n */\n maxSectionHeight: number;\n /** Shrink applied to both ends of a band before testing overlap. */\n collisionMargin: number;\n /** Hard ceiling on elements walked, so a pathological page can't hang the run. */\n maxElements: number;\n}\n\nexport const DEFAULT_SEGMENT_OPTIONS: SegmentOptions = {\n maxSectionHeight: 2160,\n collisionMargin: 2,\n maxElements: 15_000,\n};\n","import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Where a capture is allowed to land.\n *\n * `scrape` writes tens of MB of lossless PNG — section shots, motion filmstrips\n * and a whole-page reproduction — and `--out` is free-form, so the directory is\n * the agent's choice. Inside a Company Workspace that choice decides whether the\n * capture is scratch or a permanent part of the repo: publish stages with\n * `git add -A`, the workspace history is force-cloned into every later session,\n * and the individual files are each under every size gate there is. `.baker/` is\n * gitignored precisely so a capture costs nothing; anywhere else in the\n * workspace is paid for forever.\n *\n * So the rule is scoped to the workspace, not to the machine: outside a git work\n * tree — a local debugging run against `/tmp` — any path is fine, because there\n * is no history to bloat.\n */\nconst SCRATCH_DIR = \".baker\";\n\nexport type CaptureOutCheck =\n | { ok: true }\n | {\n ok: false;\n error: {\n code: \"CAPTURE_OUT_NOT_SCRATCH\";\n message: string;\n fix: { action: \"retry_with_changes\"; explanation: string };\n retryable: false;\n };\n };\n\n/** Is `target` the directory `parent`, or somewhere beneath it? */\nfunction isWithin(parent: string, target: string): boolean {\n const relative = path.relative(parent, target);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\n/**\n * The nearest enclosing git work tree, or null when there is none.\n *\n * Walks for a `.git` entry rather than shelling out to `git rev-parse`: this\n * runs before every capture, and the answer is a directory lookup either way.\n */\nexport function findRepoRoot(from: string): string | null {\n let dir = path.resolve(from);\n for (;;) {\n if (existsSync(path.join(dir, \".git\"))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\nexport function checkCaptureOut(out: string, options: { cwd: string; repoRoot: string | null }): CaptureOutCheck {\n const { cwd, repoRoot } = options;\n const resolved = path.resolve(cwd, out);\n if (repoRoot === null || !isWithin(repoRoot, resolved)) return { ok: true };\n\n const scratch = path.join(repoRoot, SCRATCH_DIR);\n if (isWithin(scratch, resolved)) return { ok: true };\n\n // Name the exact path to retry with rather than the rule, so the fix is one\n // edit and not a re-reading of the docs.\n const suggestion = path.posix.join(SCRATCH_DIR, \"teardowns\", path.basename(resolved) || \"capture\");\n return {\n ok: false,\n error: {\n code: \"CAPTURE_OUT_NOT_SCRATCH\",\n message: `A capture has to be written to ${SCRATCH_DIR}/ inside this workspace. It is reference material for this turn, and anywhere else it becomes a permanent part of the client's files.`,\n fix: {\n action: \"retry_with_changes\",\n explanation: `Re-run with --out ${suggestion}.`,\n },\n retryable: false,\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,qBAAqB;;;AC0BvB,IAAM,eAAe;AAE5B,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,IAAM,4BAA4B;AAElC,SAAS,qBAAqB,OAAuC;AAC1E,QAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ;AACzF,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,WAAW,wBAAwB,KAAK,GAAG,IAAI,CAAC;AACtD,MAAI,CAAC,YAAY,CAAC,iBAAiB,SAAS,QAAQ,EAAG,QAAO;AAC9D,SAAO,EAAE,MAAM,qBAAqB,SAAS,0BAA0B;AACzE;;;ACpBA,IAAM,oBAAqF;AAAA,EACzF;AAAA,IACE,UAAU,CAAC,yBAAyB,4BAA4B;AAAA,IAChE,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,UAAU,CAAC,YAAY,aAAa,YAAY,cAAc;AAAA,IAC9D,SACE;AAAA,EACJ;AAAA,EACA;AAAA,IACE,UAAU,CAAC,wBAAwB;AAAA,IACnC,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,UAAU,CAAC,mBAAmB,mBAAmB;AAAA,IACjD,SAAS;AAAA,EACX;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAIA,SAAS;AAAA,EACX;AACF;AAEA,IAAM,sBAAsB;AAC5B,IAAM,WAAW;AAQV,SAAS,wBAAwB,OAAwC;AAC9E,QAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ;AACzF,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,WAAW,wBAAwB,KAAK,GAAG,IAAI,CAAC;AACtD,MAAI,UAAU;AACZ,UAAM,SAAS,kBAAkB;AAAA,MAAK,CAAC,cACrC,UAAU,SAAS,KAAK,CAAC,WAAW,SAAS,WAAW,MAAM,CAAC;AAAA,IACjE;AACA,WAAO,EAAE,MAAM,oBAAoB,SAAS,QAAQ,WAAW,oBAAoB;AAAA,EACrF;AAMA,MAAI,yBAAyB,KAAK,GAAG,KAAK,IAAI,SAAS,oBAAoB,GAAG;AAC5E,WAAO,EAAE,MAAM,iBAAiB,SAAS,SAAS;AAAA,EACpD;AAEA,SAAO;AACT;AASO,SAAS,aAAa,OAA+B;AAC1D,QAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ;AACzF,SAAO,MAAO,wBAAwB,KAAK,GAAG,IAAI,CAAC,KAAK,OAAQ;AAClE;;;ACpEA,IAAM,oBAAoB;AAAA,EACxB;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;AAGA,IAAM,oBAAoB,CAAC,2BAA2B,WAAW,cAAc,eAAe,kBAAkB;AAEzG,SAAS,kBAAkB,MAKX;AAKrB,MAAI,KAAK,WAAW,cAAc;AAChC,WAAO,EAAE,MAAM,qBAAqB,SAAS,0BAA0B;AAAA,EACzE;AAEA,MAAI,KAAK,WAAW,QAAQ,KAAK,UAAU,KAAK;AAC9C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,qBAAqB,KAAK,MAAM;AAAA,IAC3C;AAAA,EACF;AAGA,QAAM,WAAW,GAAG,KAAK,KAAK;AAAA,EAAK,KAAK,SAAS,MAAM,GAAG,GAAI,CAAC,GAAG,YAAY;AAC9E,QAAM,SAAS,kBAAkB,KAAK,CAAC,cAAc,SAAS,SAAS,SAAS,CAAC;AACjF,MAAI,QAAQ;AACV,WAAO,EAAE,MAAM,iBAAiB,SAAS,wDAAwD;AAAA,EACnG;AAEA,QAAM,OAAO,KAAK,MAAM,YAAY,KAAK;AACzC,MAAI,kBAAkB,KAAK,CAAC,WAAW,KAAK,SAAS,MAAM,CAAC,GAAG;AAC7D,WAAO,EAAE,MAAM,iBAAiB,SAAS,wDAAwD;AAAA,EACnG;AAEA,SAAO;AACT;AAGO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EACjC;AAAA,EAET,YAAY,SAAsB;AAChC,UAAM,QAAQ,OAAO;AACrB,SAAK,OAAO;AACZ,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;AAiBO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA;AAAA,EAET,YAAY,SAAyB,QAA+B,CAAC,GAAG;AACtE,UAAM,QAAQ,OAAO;AACrB,SAAK,OAAO;AACZ,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AACF;AASO,IAAM,wBACX;AAWF,IAAM,yBAAyB,CAAC,gBAAgB,aAAa,aAAa;AAE1E,IAAM,sBACJ;AACF,IAAM,mBAAmB;AACzB,IAAM,yBAAyB;AAcxB,SAAS,uBAAuB,OAAgC;AAGrE,MAAI,iBAAiB,oBAAqB,QAAO,MAAM;AAEvD,MAAI,iBAAiB,kBAAkB;AAErC,WAAO,EAAE,MAAM,MAAM,MAAM,SAAS,MAAM,QAAQ;AAAA,EACpD;AAUA,QAAM,eAAe,qBAAqB,KAAK;AAC/C,MAAI,aAAc,QAAO;AAEzB,QAAM,cAAc,wBAAwB,KAAK;AACjD,MAAI,YAAa,QAAO;AAExB,QAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAAG,YAAY;AAErF,MAAI,uBAAuB,KAAK,CAAC,WAAW,QAAQ,SAAS,MAAM,CAAC,GAAG;AACrE,WAAO,EAAE,MAAM,oBAAoB,SAAS,oBAAoB;AAAA,EAClE;AACA,MAAI,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,UAAU,GAAG;AAC/D,WAAO,EAAE,MAAM,iBAAiB,SAAS,iBAAiB;AAAA,EAC5D;AAEA,SAAO,EAAE,MAAM,kBAAkB,SAAS,uBAAuB;AACnE;;;AC/NA,SAAS,OAAO,aAAAA,kBAAiB;AACjC,OAAOC,WAAU;;;ACDjB,OAAO,UAAU;AAgCV,SAAS,wBAAwB,QAA6C;AACnF,MAAI,WAAW,IAAK,QAAO,EAAE,QAAQ,KAAK;AAG1C,MAAI,WAAW,IAAK,QAAO,EAAE,QAAQ,OAAO,SAAS,OAAO;AAC5D,SAAO,EAAE,QAAQ,OAAO,SAAS,cAAc;AACjD;AAaA,eAAsB,oBAAoB,OAAmB,UAA4B,CAAC,GAA6B;AAErH,MAAI,MAAM,SAAS,QAAS,QAAO,EAAE,QAAQ,KAAK;AAElD,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,WAAW,IAAI,IAAI,MAAM,MAAM;AACrC,QAAM,OAAO,OAAO,KAAK,GAAG,MAAM,QAAQ,IAAI,MAAM,QAAQ,EAAE,EAAE,SAAS,QAAQ;AAEjF,SAAO,MAAM,IAAI,QAAyB,CAAC,YAAY;AACrD,UAAM,SAAS,CAAC,WAA4B;AAC1C,cAAQ,QAAQ;AAChB,cAAQ,MAAM;AAAA,IAChB;AACA,UAAM,UAAU,KAAK,QAAQ;AAAA,MAC3B,MAAM,SAAS;AAAA,MACf,MAAM,OAAO,SAAS,IAAI;AAAA,MAC1B,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,uBAAuB,SAAS,IAAI,IAAI,MAAM,OAAO;AAAA,MAChE,SAAS;AAAA,IACX,CAAC;AACD,YAAQ,GAAG,WAAW,CAAC,UAAU,WAAW;AAC1C,aAAO,QAAQ;AACf,aAAO,wBAAwB,SAAS,UAAU,CAAC;AAAA,IACrD,CAAC;AAED,YAAQ,GAAG,YAAY,CAAC,aAAa;AACnC,eAAS,QAAQ;AACjB,aAAO,wBAAwB,SAAS,UAAU,CAAC;AAAA,IACrD,CAAC;AACD,YAAQ,GAAG,WAAW,MAAM,OAAO,EAAE,QAAQ,OAAO,SAAS,UAAU,CAAC,CAAC;AACzE,YAAQ,GAAG,SAAS,MAAM,OAAO,EAAE,QAAQ,OAAO,SAAS,cAAc,CAAC,CAAC;AAC3E,YAAQ,IAAI;AAAA,EACd,CAAC;AACH;;;ACtFA,SAAS,qBAAqB;AAO9B,IAAM,WAAW,cAAc,YAAY,GAAG;AAC9C,IAAM,cAAc,CAAC,QAAQ,QAAQ,EAAE,KAAK,EAAE;AAEvC,IAAM,mBAAmB,EAAE,OAAO,MAAM,QAAQ,IAAI;AACpD,IAAM,kBAAkB,EAAE,OAAO,KAAK,QAAQ,IAAI;AAElD,IAAM,sBAAsB;AAgBnC,eAAsB,cAAc,QAAoB,EAAE,MAAM,SAAS,GAAqB;AAC5F,QAAM,aAAa,SAAS,WAAW;AACvC,SAAO,MAAM,WAAW,SAAS,OAAO;AAAA,IACtC,UAAU;AAAA,IACV,MAAM,CAAC,qBAAqB,iDAAiD,cAAc;AAAA,IAC3F,GAAI,MAAM,SAAS,UACf,EAAE,OAAO,EAAE,QAAQ,MAAM,QAAQ,UAAU,MAAM,UAAU,UAAU,MAAM,SAAS,EAAE,IACtF,CAAC;AAAA,EACP,CAAC;AACH;AAEA,eAAsB,QACpB,SACA,UACA,OAA4B,EAAE,QAAQ,MAAM,GACM;AAClD,QAAM,UAAU,MAAM,QAAQ,WAAW;AAAA,IACvC;AAAA,IACA,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAUnB,mBAAmB;AAAA;AAAA;AAAA,IAGnB,eAAe,KAAK,SAAS,kBAAkB;AAAA,IAC/C,WACE,SAAS,QAAQ,MACb,4IACA;AAAA,EACR,CAAC;AACD,QAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,SAAO,EAAE,SAAS,KAAK;AACzB;;;AC1CA,eAAsB,eAAe,MAAY,UAAoC;AACnF,QAAM,YAAY,MAAM,KAAK,SAAS,sBAAsB,QAAQ;AAMpE,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,UAAU,iBAAiB;AAC5C,UAAM,OAAO,MAAM,gBAAgB,MAAM,IAAI;AAC7C,QAAI,KAAM,OAAM,KAAK,MAAM,IAAI;AAAA,EAAQ,IAAI,EAAE;AAAA,EAC/C;AAEA,SAAO,EAAE,GAAG,WAAW,KAAK,CAAC,UAAU,KAAK,GAAG,KAAK,EAAE,OAAO,OAAO,EAAE,KAAK,MAAM,EAAE;AACrF;AAEA,eAAe,gBAAgB,MAAY,MAAsC;AAC/E,MAAI;AACF,UAAM,WAAW,MAAM,KAAK,QAAQ,IAAI,MAAM,EAAE,SAAS,IAAO,CAAC;AACjE,QAAI,CAAC,SAAS,GAAG,EAAG,QAAO;AAC3B,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAgBA,IAAM,uBAAuB,CAAC,aAAqB;AACjD,QAAM,OAAO,SAAS,cAAc,QAAQ;AAC5C,QAAM,QAAQ;AAAA,IACZ,KAAK;AAAA,IACL,WAAW;AAAA,IACX,eAAe;AAAA,IACf,iBAAiB,CAAC;AAAA,IAClB,OAAO,EAAE,YAAY,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,EAAE;AAAA,EACnE;AACA,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,kBAA4B,CAAC;AACnC,QAAM,OAAiB,CAAC;AACxB,QAAM,YAAsB,CAAC;AAC7B,QAAM,kBAAkB,oBAAI,IAAoB;AAChD,MAAI,aAAa;AAIjB,MAAI,iBAAiB;AAUrB,QAAM,mBAAmB,CAAC,iBAAyB;AACjD,eAAW,QAAQ,aAAa,MAAM,GAAG,GAAG;AAC1C,YAAM,OAAO,KACV,QAAQ,6BAA6B,EAAE,EACvC,QAAQ,uFAAuF,EAAE,EACjG,KAAK;AACR,UAAI,CAAC,KAAM;AACX,UAAI;AACF,YAAI,KAAK,QAAQ,IAAI,KAAK,KAAK,cAAc,IAAI,EAAG,QAAO;AAAA,MAC7D,QAAQ;AAGN,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,CAAC,OAAoB,SAAmB;AACnD,eAAW,QAAQ,MAAM,KAAK,KAAK,GAAG;AACpC;AAEA,UAAI,gBAAgB,cAAc;AAChC,YAAI,iBAAiB,KAAK,YAAY,GAAG;AACvC,eAAK,KAAK,KAAK,OAAO;AACtB;AAAA,QACF;AACA;AAAA,MACF;AACA,UAAI,gBAAgB,iBAAiB;AACnC,kBAAU,KAAK,KAAK,OAAO;AAC3B;AAAA,MACF;AACA,UAAI,gBAAgB,kBAAkB;AACpC,wBAAgB,IAAI,KAAK,MAAM,KAAK,OAAO;AAC3C;AAAA,MACF;AAGA,YAAM,WACJ,gBAAgB,gBAChB,gBAAgB,mBACf,OAAO,sBAAsB,eAAe,gBAAgB,qBAC5D,OAAO,qBAAqB,eAAe,gBAAgB;AAC9D,UAAI,UAAU;AACZ,cAAM,QAAkB,CAAC;AACzB,aAAM,KAAyB,UAAU,KAAK;AAC9C,YAAI,MAAM,WAAW,EAAG;AACxB,cAAM,YAAa,KAAsB,iBAAiB;AAC1D,cAAM,UAAU,gBAAgB,eAAe,UAAU,SAAS,KAAK,KAAK,QAAQ,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK;AACxG,aAAK,KAAK,GAAG,OAAO;AAAA,EAAO,MAAM,KAAK,IAAI,CAAC;AAAA,EAAK;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,KAAK,SAAS,WAAW,GAAG;AAKpD,UAAM,QAAQ,MAAM;AACpB,QAAI,OAAO,eAAe,mBAAmB,EAAG;AAChD,QAAI;AACF,WAAK,MAAM,UAAU,IAAI;AAAA,IAC3B,QAAQ;AACN,UAAI,MAAM,KAAM,iBAAgB,KAAK,MAAM,IAAI;AAAA,IACjD;AAAA,EACF;AAGA,QAAM,WAAW,KAAK,KAAK,IAAI;AAC/B,QAAM,gBAA0B,CAAC;AACjC,aAAW,CAAC,MAAM,IAAI,KAAK,iBAAiB;AAC1C,QAAI,IAAI,OAAO,cAAc,IAAI,cAAc,EAAE,KAAK,QAAQ,EAAG,eAAc,KAAK,IAAI;AAAA,EAC1F;AAKA,QAAM,YAAY,iBAAiB,IAAI;AACvC,QAAM,uBAAiC,CAAC;AACxC,aAAW,YAAY,MAAM,KAAK,SAAS,GAAG;AAC5C,QAAI,CAAC,SAAS,WAAW,IAAI,EAAG;AAChC,UAAM,QAAQ,UAAU,iBAAiB,QAAQ,EAAE,KAAK;AACxD,QAAI,MAAO,sBAAqB,KAAK,KAAK,QAAQ,KAAK,KAAK,GAAG;AAAA,EACjE;AAEA,QAAM,OAAO,UAAU,IAAI,CAAC,aAAa,KAAK,QAAQ,KAAK,UAAU,iBAAiB,QAAQ,CAAC,GAAG,EAAE,KAAK,IAAI;AAE7G,SAAO;AAAA,IACL,KAAK,CAAC,GAAG,WAAW,GAAG,eAAe,GAAG,IAAI,EAAE,KAAK,IAAI;AAAA,IACxD,WAAW,qBAAqB,SAAS;AAAA,EAAY,qBAAqB,KAAK,IAAI,CAAC;AAAA,KAAQ;AAAA,IAC5F,eAAe;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA,WAAW;AAAA,MACX,WAAW,UAAU;AAAA,MACrB,WAAW,cAAc;AAAA,IAC3B;AAAA,EACF;AACF;;;AC5LA,eAAsB,mBAAmB,MAAY,UAAkB,SAAyC;AAC9G,QAAM,OAAO,MAAM,eAAe,MAAM,QAAQ;AAChD,QAAM,YAAY,MAAM,KAAK,SAAS,qBAAqB;AAAA,IACzD;AAAA,IACA;AAAA,IACA,eAAe;AAAA,EACjB,CAAC;AAED,QAAM,MAAM;AAAA,IACV;AAAA,IACA;AAAA,IACA,KAAK;AAAA,IACL;AAAA,EAAW,KAAK,aAAa;AAAA;AAAA,IAC7B,KAAK;AAAA,EACP,EACG,OAAO,OAAO,EACd,KAAK,MAAM;AAEd,QAAM,OAAO;AAAA,QACP,UAAU,cAAc;AAAA;AAAA;AAAA;AAAA,sBAIV,WAAW,UAAU,IAAI,CAAC;AAAA;AAAA,EAE9C,GAAG;AAAA;AAAA;AAAA,QAGG,UAAU,cAAc;AAAA,EAC9B,oBAAoB,UAAU,MAAM,UAAU,aAAa,CAAC;AAAA;AAAA;AAAA;AAK5D,SAAO,EAAE,MAAM,KAAK,WAAW,UAAU,WAAW,OAAO,KAAK,MAAM;AACxE;AAEA,SAAS,WAAW,OAAuB;AACzC,SAAO,MAAM,QAAQ,WAAW,CAAC,OAAO,EAAE,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,SAAS,GAAG,CAAC,KAAK,CAAC;AAC5G;AAiBO,IAAM,yBAAyB;AAuBtC,SAAS,oBAAoB,MAAc,SAAgC;AAGzE,MAAI,UACF,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,QAAQ,gBACzC,qBAAqB,QAAQ,KAAK;AAAA,EAAwB,IAAI;AAAA,UAC9D;AAEN,aAAW,YAAY,CAAC,GAAG,QAAQ,SAAS,EAAE,QAAQ,GAAG;AACvD,UAAM,aAAa,SAAS,aAAa,IAAI,SAAS,UAAU,KAAK;AACrE,UAAM,YACJ,SAAS,iBAAiB,SAAS,kBAAkB,WACjD,kBAAkB,SAAS,aAAa,IACtC,SAAS,iBAAiB,SAAS,kBAAkB,SACjD,kBAAkB,SAAS,aAAa,MACxC,EACN,KACA;AACN,cAAU,IAAI,SAAS,GAAG,GAAG,UAAU,WAAW,0BAA0B,GAAG,SAAS;AAAA,EAAO,OAAO;AAAA,IAAO,SAAS,GAAG;AAAA,EAC3H;AAEA,SAAO;AACT;AAYA,IAAM,6BAA6B;AAAA,EACjC;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,EAAE,KAAK,GAAG;AAEV,IAAM,sBAAsB,CAAC;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AACF,MAIM;AACJ,QAAM,OAAO,SAAS,cAAc,QAAQ;AAC5C,QAAM,eAAe,EAAE,WAAW,CAAC,GAAsB,OAAO,GAAG,eAAe,EAAE;AAUpF,QAAM,sBAAsB,CAAC,YAA4B;AACvD,QAAI,CAAC,QAAS,QAAO;AACrB,WAAO,MAAM,KAAK,QAAQ,UAAU,EACjC,OAAO,CAAC,cAAc,UAAU,SAAS,OAAO,EAChD,IAAI,CAAC,cAAc,GAAG,UAAU,IAAI,KAAK,UAAU,MAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG,EACnF,KAAK,GAAG;AAAA,EACb;AACA,QAAM,iBAAiB,oBAAoB,SAAS,eAAe,KAAK;AACxE,QAAM,iBAAiB,oBAAoB,SAAS,IAAI;AAExD,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW,CAAC;AAAA,MACZ,MAAM;AAAA,MACN,eAAe;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAIA,QAAM,YAA6B,CAAC;AACpC,WAAS,WAAW,KAAK,eAAe,YAAY,aAAa,SAAS,QAAQ;AAChF,UAAM,QAAQ,iBAAiB,QAAQ;AACvC,cAAU,QAAQ;AAAA,MAChB,KAAK,0BAA0B,KAAK,SAAS,OAAO,IAAI,SAAS,QAAQ,YAAY,IAAI;AAAA,MACzF,YAAY,MAAM,KAAK,SAAS,UAAU,EACvC,OAAO,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,SAAS,QAAQ,EAAE,KAAK,WAAW,OAAO,CAAC,EACjF,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG,EAC3D,KAAK,GAAG;AAAA,MACX,eAAe,MAAM;AAAA,MACrB,eAAe,MAAM;AAAA,IACvB,CAAC;AACD,eAAW,SAAS;AAAA,EACtB;AAEA,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA,OAAO,KAAK,MAAM,KAAK,sBAAsB,EAAE,KAAK;AAAA,IACpD,eAAe,OAAO;AAAA,EACxB;AAEA,QAAM,WAAW,CAAC,UAAkB;AAClC,QAAI;AACF,aAAO,IAAI,IAAI,OAAO,OAAO,EAAE;AAAA,IACjC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAIA,QAAM,QAAQ,KAAK,UAAU,IAAI;AACjC,QAAM,aAAa,eAAe,EAAE;AACpC,QAAM,YAAY,oBAAI,IAAY;AAElC,aAAW,WAAW,CAAC,OAAO,GAAG,MAAM,KAAK,MAAM,iBAAiB,GAAG,CAAC,CAAC,GAAG;AACzE,eAAW,aAAa,CAAC,OAAO,QAAQ,QAAQ,GAAG;AACjD,YAAM,QAAQ,QAAQ,aAAa,SAAS;AAC5C,UAAI,CAAC,SAAS,MAAM,WAAW,OAAO,KAAK,MAAM,WAAW,GAAG,EAAG;AAClE,YAAM,MAAM,SAAS,KAAK;AAC1B,cAAQ,aAAa,WAAW,GAAG;AACnC,UAAI,cAAc,UAAU,QAAQ,YAAY,OAAQ,WAAU,IAAI,GAAG;AAAA,IAC3E;AAEA,UAAM,SAAS,QAAQ,aAAa,QAAQ;AAC5C,QAAI,QAAQ;AACV,cAAQ;AAAA,QACN;AAAA,QACA,OACG,MAAM,GAAG,EACT,IAAI,CAAC,cAAc;AAClB,gBAAM,CAAC,KAAK,UAAU,IAAI,UAAU,KAAK,EAAE,MAAM,OAAO,CAAC;AACzD,cAAI,CAAC,IAAK,QAAO;AACjB,gBAAM,WAAW,SAAS,GAAG;AAC7B,oBAAU,IAAI,QAAQ;AACtB,iBAAO,aAAa,GAAG,QAAQ,IAAI,UAAU,KAAK;AAAA,QACpD,CAAC,EACA,KAAK,IAAI;AAAA,MACd;AAAA,IACF;AAIA,UAAM,QAAQ,QAAQ,aAAa,OAAO;AAC1C,QAAI,OAAO,SAAS,MAAM,GAAG;AAC3B,cAAQ;AAAA,QACN;AAAA,QACA,MAAM,QAAQ,8BAA8B,CAAC,QAAQ,OAAe,QAAgB;AAClF,cAAI,IAAI,WAAW,OAAO,EAAG,QAAO,OAAO,KAAK,GAAG,GAAG,GAAG,KAAK;AAC9D,gBAAM,WAAW,SAAS,GAAG;AAC7B,oBAAU,IAAI,QAAQ;AACtB,iBAAO,OAAO,KAAK,GAAG,QAAQ,GAAG,KAAK;AAAA,QACxC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ,WAAW,MAAM,KAAK,SAAS;AAAA,IAC/B,MAAM,SAAS;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC9QA,eAAsB,eAAe,MAAY,SAAmD;AAClG,QAAM,UAAU,KAAK,QAAQ,QAAQ,QAAQ,EAAE,MAAM;AAErD,MAAI,MAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,CAAC,GAAG;AACxC,UAAM,OAAO,MAAM,QAAQ,WAAW,EAAE,MAAM,OAAO,SAAS,KAAO,CAAC,EAAE,MAAM,MAAM,IAAI;AACxF,QAAI,KAAM,QAAO;AAAA,EACnB;AAIA,QAAM,MAAM,MAAM,KAAK,SAAS,OAAO;AAAA,IACrC,OAAO,KAAK,IAAI,SAAS,gBAAgB,aAAa,SAAS,MAAM,eAAe,CAAC;AAAA,IACrF,QAAQ,KAAK,IAAI,SAAS,gBAAgB,cAAc,SAAS,MAAM,gBAAgB,CAAC;AAAA,EAC1F,EAAE;AACF,QAAM,QAAQ,KAAK,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,QAAQ,KAAK,IAAI;AACxE,QAAM,SAAS,KAAK,IAAI,QAAQ,KAAK,QAAQ,IAAI,SAAS,QAAQ,KAAK,GAAG;AAC1E,MAAI,SAAS,KAAK,UAAU,EAAG,QAAO;AAEtC,SAAO,MAAM,KACV,WAAW;AAAA,IACV,MAAM;AAAA,IACN,MAAM,EAAE,GAAG,QAAQ,KAAK,MAAM,GAAG,QAAQ,KAAK,KAAK,OAAO,OAAO;AAAA,IACjE,SAAS;AAAA,EACX,CAAC,EACA,MAAM,MAAM,IAAI;AACrB;AASA,eAAsB,uBAAuB,MAAY,SAAmD;AAC1G,QAAM,UAAU,KAAK,QAAQ,QAAQ,QAAQ,EAAE,MAAM;AACrD,MAAI,CAAE,MAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,CAAC,EAAI,QAAO;AACpD,MAAI,CAAE,MAAM,QAAQ,UAAU,EAAE,MAAM,MAAM,KAAK,EAAI,QAAO;AAC5D,SAAO,MAAM,QAAQ,WAAW,EAAE,MAAM,OAAO,SAAS,KAAO,CAAC,EAAE,MAAM,MAAM,IAAI;AACpF;;;ACjBO,IAAM,qBAAqB;AAe3B,SAAS,cAAc,SAAsC;AAClE,QAAM,OAAO,QAAQ,QAAQ;AAC7B,SAAO;AAAA,IACL,WAAW,SAAS;AAAA,IACpB,QAAQ,QAAQ;AAAA,IAChB,UAAU,QAAQ;AAAA,IAClB,UAAU,SAAS;AAAA,EACrB;AACF;AAoBO,SAAS,sBAAsB,SAAkC;AACtE,SACE,QAAQ,MAAM,SAAS,WACvB,QAAQ,QAAQ,SAAS,mBACzB,QAAQ,WAAW,QACnB,QAAQ,aAAa;AAEzB;AAGO,SAAS,eAAe,SAAyB,SAA6D;AACnH,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,EAAE,MAAM,qBAAqB,SAAS,0BAA0B;AAAA;AAAA;AAAA,IAGzE,UAAU,YAAY,SAAS,6BAA6B;AAAA,EAC9D;AACF;AAEO,SAAS,UAAU,MAM0B;AAClD,QAAM,OAAO,KAAK,SAAS,KAAK,SAAS,SAAS,CAAC;AACnD,MAAI,CAAC,KAAM,QAAO,EAAE,MAAM,MAAM,QAAQ,mBAAmB;AAK3D,QAAM,cAAc,eAAe,cAAc,IAAI,CAAC;AACtD,MAAI,CAAC,eAAe,CAAC,eAAe,cAAc,IAAI,CAAC,GAAG;AACxD,WAAO,EAAE,MAAM,MAAM,QAAQ,sBAAsB;AAAA,EACrD;AAEA,QAAM,OAAO;AAAA,IACX,KAAK;AAAA,IACL,KAAK,SAAS,IAAI,CAAC,aAAa;AAAA,MAC9B,MAAM,QAAQ,MAAM,SAAS,UAAU,QAAQ,MAAM,OAAO;AAAA,MAC5D,cAAc,eAAe,cAAc,OAAO,CAAC;AAAA,IACrD,EAAE;AAAA,EACJ;AACA,MAAI,CAAC,KAAM,QAAO,EAAE,MAAM,MAAM,QAAQ,KAAK,OAAO,WAAW,IAAI,mBAAmB,mBAAmB;AAIzG,MAAI,KAAK,cAAc,KAAK,YAAY,KAAK,cAAc;AACzD,WAAO,EAAE,MAAM,MAAM,QAAQ,gBAAgB;AAAA,EAC/C;AACA,SAAO,EAAE,MAAM,QAAQ,WAAW;AACpC;AAwBO,SAAS,kBAAkB,UAAqD;AACrF,QAAM,eAAe,SAAS,OAAO,CAAC,YAAY,CAAC,eAAe,cAAc,OAAO,CAAC,CAAC;AACzF,QAAM,SACJ,aAAa,KAAK,CAAC,YAAY,QAAQ,WAAW,IAAI,KACtD,aAAa,aAAa,SAAS,CAAC,KACpC,SAAS,SAAS,SAAS,CAAC;AAC9B,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,2CAA2C;AACxE,SAAO,OAAO;AAChB;;;AC9JA,OAAO,WAAW;AAalB,IAAM,kBAAkB;AAMjB,SAAS,gBAAgB,GAAe,GAAuB;AACpE,QAAM,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM;AAC1C,MAAI,WAAW,EAAG,QAAO;AACzB,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,aAAS,KAAK,KAAK,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC,KAAK,EAAE;AAAA,EAC7C;AACA,SAAO,IAAI,SAAS,SAAS;AAC/B;AAWA,eAAsB,cAAc,MAAc,UAA2C;AAC3F,QAAM,CAAC,UAAU,YAAY,IAAI,MAAM,QAAQ,IAAI,CAAC,MAAM,IAAI,EAAE,SAAS,GAAG,MAAM,QAAQ,EAAE,SAAS,CAAC,CAAC;AACvG,QAAM,WAAW,EAAE,OAAO,SAAS,SAAS,GAAG,QAAQ,SAAS,UAAU,EAAE;AAC5E,QAAM,eAAe,EAAE,OAAO,aAAa,SAAS,GAAG,QAAQ,aAAa,UAAU,EAAE;AAExF,QAAM,CAAC,YAAY,cAAc,IAAI,MAAM,QAAQ,IAAI,CAAC,WAAW,IAAI,GAAG,WAAW,QAAQ,CAAC,CAAC;AAC/F,QAAM,QAAQ,gBAAgB,YAAY,cAAc;AAKxD,QAAM,cACJ,SAAS,SAAS,KAAK,aAAa,SAAS,IACzC,KAAK,IAAI,SAAS,QAAQ,aAAa,MAAM,IAAI,KAAK,IAAI,SAAS,QAAQ,aAAa,MAAM,IAC9F;AAEN,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,cAAc,MACd,EAAE,MAAM,qBAAqB,KAAK,OAAO,IAAI,eAAe,GAAG,CAAC,+BAA0B,IAC1F,CAAC;AAAA,EACP;AACF;AAGA,eAAe,WAAW,OAAoC;AAC5D,QAAM,MAAM,MAAM,MAAM,KAAK,EAAE,UAAU,EAAE,OAAO,iBAAiB,iBAAiB,EAAE,KAAK,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS;AACpH,SAAO,IAAI,WAAW,GAAG;AAC3B;;;AChCO,IAAM,eAAiC;AAAA,EAC5C,WAAW;AAAA;AAAA;AAAA;AAAA,EAIX,SAAS;AAAA,EACT,UAAU,CAAC;AAAA,EACX,OAAO,CAAC;AAAA,EACR,QAAQ,CAAC;AAAA,EACT,MAAM,CAAC;AAAA,EACP,WAAW,CAAC;AAAA,EACZ,uBAAuB;AACzB;AAUO,SAAS,eAAe,QAAmC;AAChE,SAAO,OAAO,SAAS,SAAS,OAAO,OAAO,SAAS,OAAO,KAAK,SAAS;AAC9E;AAEA,eAAsB,cAAc,MAAY,UAA6C;AAC3F,QAAM,MAAM,MAAM,KAAK,SAAS,qBAAqB,QAAQ,EAAE,MAAM,MAAM,IAAI;AAC/E,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,EAAE,GAAG,KAAK,SAAS,gBAAgB,GAAG,EAAE;AACjD;AAGA,IAAM,mBAAmB,oBAAI,IAAI,CAAC,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,UAAU,SAAS,CAAC;AAwB/F,IAAM,oBAAkE;AAAA,EACtE,CAAC,+CAA+C,SAAS;AAAA,EACzD,CAAC,YAAY,UAAU;AAAA,EACvB,CAAC,oBAAoB,YAAY;AAAA,EACjC,CAAC,gBAAgB,SAAS;AAAA,EAC1B,CAAC,yBAAyB,MAAM;AAAA,EAChC,CAAC,uBAAuB,MAAM;AAAA,EAC9B,CAAC,4CAA4C,UAAU;AACzD;AAEA,SAAS,cAAc,MAAc,SAAiE;AACpG,MAAI,YAAY,QAAS,QAAO,CAAC,iBAAiB,IAAI,IAAI,IAAI,eAAe,MAAM;AAEnF,QAAM,OAAO,KAAK,YAAY;AAC9B,QAAM,UAAU,kBAAkB,OAAO,CAAC,CAAC,OAAO,MAAM,QAAQ,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,UAAU,MAAM,UAAU;AAC9G,MAAI,QAAQ,SAAS,EAAG,QAAO;AAE/B,SAAO,CAAC,YAAY,SAAS,YAAY,eAAe;AAC1D;AAWO,SAAS,cAAc,QAAyD;AACrF,QAAM,QAAQ,oBAAI,IAAgB;AAClC,QAAM,UAAU,CAAC,SAAyB,YAAsD;AAC9F,eAAW,UAAU,SAAS;AAC5B,iBAAW,QAAQ,cAAc,OAAO,MAAM,OAAO,EAAG,OAAM,IAAI,IAAI;AAAA,IACxE;AAAA,EACF;AACA,UAAQ,OAAO,UAAU,UAAU;AACnC,UAAQ,OAAO,OAAO,OAAO;AAC7B,UAAQ,OAAO,QAAQ,QAAQ;AAC/B,UAAQ,OAAO,MAAM,MAAM;AAK3B,QAAM,SAAS,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC,WAAW,OAAO,WAAW,CAAC,EAAE,OAAO,CAAC,OAAO,KAAK,CAAC,CAAC;AAClG,MAAI,OAAO,OAAO,EAAG,OAAM,IAAI,SAAS;AAExC,SAAO,CAAC,GAAG,KAAK;AAClB;AASO,SAAS,gBAAgB,QAAmD;AACjF,QAAM,QAAQ,cAAc,MAAM;AAClC,MAAI,MAAM,WAAW,KAAK,OAAO,UAAU,WAAW,EAAG,QAAO;AAIhE,QAAM,QAAkB,CAAC,GAAG,KAAK;AACjC,MAAI,OAAO,UAAU,SAAS,EAAG,OAAM,KAAK,OAAO,OAAO,UAAU,KAAK,GAAG,CAAC,EAAE;AAC/E,SAAO,MAAM,KAAK,IAAI,KAAK,OAAO,wBAAwB,KAAK;AACjE;AAEA,IAAM,sBAAsB,CAAC,aAAqB;AAChD,QAAM,OAAO,SAAS,cAAc,QAAQ;AAC5C,QAAM,QAAQ;AAAA,IACZ,WAAW;AAAA,IACX,UAAU,CAAC;AAAA,IACX,OAAO,CAAC;AAAA,IACR,QAAQ,CAAC;AAAA,IACT,MAAM,CAAC;AAAA,IACP,WAAW,CAAC;AAAA,IACZ,uBAAuB;AAAA,EACzB;AACA,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,WAA2B,CAAC;AAClC,QAAM,QAAwB,CAAC;AAC/B,QAAM,SAAyB,CAAC;AAChC,QAAM,OAAuB,CAAC;AAC9B,QAAM,kBAAkB,oBAAI,IAAoB;AAChD,MAAI,wBAAwB;AAE5B,QAAM,YAAY,CAAC,iBAAyB;AAC1C,eAAW,QAAQ,aAAa,MAAM,GAAG,GAAG;AAC1C,YAAM,OAAO,KACV,QAAQ,6BAA6B,EAAE,EACvC,QAAQ,uFAAuF,EAAE,EACjG,KAAK;AACR,UAAI,CAAC,KAAM;AACX,UAAI;AACF,YAAI,KAAK,QAAQ,IAAI,KAAK,KAAK,cAAc,IAAI,EAAG,QAAO;AAAA,MAC7D,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,CAAC,UAAkB;AAC9B,UAAM,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,KAAK;AAC7C,QAAI,MAAM,SAAS,IAAI,EAAG,QAAO,OAAO,WAAW,KAAK;AACxD,QAAI,MAAM,SAAS,GAAG,EAAG,QAAO,OAAO,WAAW,KAAK,IAAI;AAC3D,WAAO;AAAA,EACT;AAGA,QAAM,oBAAoB,CAAC,SAAyB;AAClD,UAAM,OAAO,KAAK,YAAY;AAC9B,UAAM,QAAQ,gCAAgC,KAAK,IAAI;AACvD,QAAI,sBAAsB,KAAK,IAAI,GAAG;AACpC,YAAM,SAAS,yBAAyB,KAAK,IAAI;AACjD,aAAO,QAAS,SAAS,YAAY,cAAe,SAAS,aAAa;AAAA,IAC5E;AACA,QAAI,sBAAsB,KAAK,IAAI,EAAG,QAAO,QAAQ,cAAc;AACnE,QAAI,UAAU,KAAK,IAAI,EAAG,QAAO,QAAQ,cAAc;AACvD,QAAI,WAAW,KAAK,IAAI,EAAG,QAAO;AAClC,QAAI,MAAO,QAAO;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,CAAC,UAA8C;AACnE,UAAM,YAAY,MAAM,aAAa;AACrC,QAAI,oBAAoB,KAAK,SAAS,EAAG,QAAO;AAChD,QAAI,2BAA2B,KAAK,SAAS,EAAG,QAAO;AACvD,QAAI,YAAY,KAAK,SAAS,EAAG,QAAO;AACxC,QAAI,aAAa,cAAc,OAAQ,QAAO;AAC9C,QAAI,MAAM,UAAW,QAAO;AAC5B,QAAI,MAAM,QAAS,QAAO;AAC1B,QAAI,MAAM,mBAAmB,MAAM,MAAO,QAAO;AACjD,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,CAAC,MAAoB,yBAAkC;AAC3E,UAAM,QAAQ,KAAK;AACnB,UAAM,UAAU,WAAW,KAAK,KAAK,YAAY;AAEjD,QAAI,SAAS;AACX,YAAM,OAAO,cAAc,KAAK;AAIhC,UAAI,CAAC,QAAQ,CAAC,UAAU,KAAK,YAAY,EAAG;AAC5C,YAAM,KAAK;AAAA,QACT;AAAA,QACA,UAAU,KAAK,aAAa,MAAM,GAAG,GAAG;AAAA,QACxC,YAAY,KAAK,MAAM,sBAAsB,EAAE;AAAA,QAC/C,QAAQ,MAAM,4BAA4B;AAAA,MAC5C,CAAC;AACD;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM;AAC5B,QAAI,CAAC,iBAAiB,kBAAkB,OAAQ;AAChD,QAAI,CAAC,UAAU,KAAK,YAAY,EAAG;AAEnC,UAAM,SAAuB;AAAA,MAC3B,MAAM;AAAA,MACN,UAAU,KAAK,aAAa,MAAM,GAAG,GAAG;AAAA,MACxC,YAAY,KAAK,MAAM,qBAAqB,EAAE;AAAA,MAC9C,SAAS,KAAK,MAAM,kBAAkB,EAAE;AAAA,MACxC,QAAQ,MAAM,2BAA2B;AAAA,IAC3C;AACA,UAAM,YAAY,MAAM,2BAA2B,IAAI,SAAS,UAAU;AAC1E,UAAM,eAAe,wBAAwB,QAAQ,MAAM,iBAAiB,oBAAoB,CAAC;AACjG,QAAI,aAAc,QAAO,KAAK,MAAM;AAAA,aAC3B,SAAU,MAAK,KAAK,MAAM;AAAA,QAC9B,UAAS,KAAK,MAAM;AAAA,EAC3B;AAEA,QAAM,OAAO,CAAC,OAAoB,yBAAkC;AAClE,eAAW,QAAQ,MAAM,KAAK,KAAK,GAAG;AACpC,UAAI,gBAAgB,kBAAkB;AACpC,wBAAgB,IAAI,KAAK,MAAM,KAAK,OAAO;AAC3C;AAAA,MACF;AACA,UAAI,gBAAgB,cAAc;AAChC,YAAI;AACF,wBAAc,MAAM,oBAAoB;AAAA,QAC1C,QAAQ;AAAA,QAER;AACA;AAAA,MACF;AACA,UAAI,gBAAgB,cAAc;AAChC,YAAI,KAAK,cAAc,SAAS,wBAAwB,GAAG;AACzD,kCAAwB;AAGxB;AAAA,QACF;AACA,aAAK,KAAK,UAAU,oBAAoB;AACxC;AAAA,MACF;AACA,YAAM,WAAW;AACjB,UAAI,SAAS,SAAU,MAAK,SAAS,UAAU,oBAAoB;AAAA,IACrE;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,KAAK,SAAS,WAAW,GAAG;AACpD,QAAK,MAAM,WAA8B,eAAe,mBAAmB,EAAG;AAC9E,QAAI;AACF,WAAK,MAAM,UAAU,KAAK;AAAA,IAC5B,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,aAAW,UAAU,CAAC,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG;AACtD,UAAM,OAAO,gBAAgB,IAAI,OAAO,IAAI;AAC5C,QAAI,CAAC,KAAM;AACX,UAAM,aAAa,kBAAkB,IAAI;AACzC,WAAO,OAAO,KAAK,SAAS,MAAM,KAAK,WAAW,WAAW,OAAO,IAAI,YAAY;AAAA,EACtF;AAGA,QAAM,YAAsB,CAAC;AAC7B,QAAM,SAAU,UAAiD,CAAC;AAClE,MAAI,OAAO,QAAQ,SAAS,cAAc,aAAa,EAAG,WAAU,KAAK,MAAM;AAC/E,MAAI,SAAS,cAAc,0CAA0C,EAAG,WAAU,KAAK,eAAe;AACtG,MAAI,SAAS,cAAc,YAAY,EAAG,WAAU,KAAK,KAAK;AAC9D,MAAI,OAAO,SAAS,SAAS,cAAc,cAAc,EAAG,WAAU,KAAK,OAAO;AAClF,MAAI,SAAS,cAAc,wCAAwC,EAAG,WAAU,KAAK,YAAY;AAEjG,SAAO;AAAA,IACL,WAAW,SAAS,SAAS,MAAM,SAAS,OAAO,SAAS,KAAK,SAAS,UAAU,SAAS;AAAA,IAC7F,UAAU,SAAS,MAAM,GAAG,EAAE;AAAA,IAC9B,OAAO,MAAM,MAAM,GAAG,EAAE;AAAA,IACxB,QAAQ,OAAO,MAAM,GAAG,EAAE;AAAA,IAC1B,MAAM,KAAK,MAAM,GAAG,EAAE;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AACF;;;AC3UA,OAAOC,YAAW;;;ACqClB,SAAS,WAAW,aAA6B;AAC/C,SAAO,IAAI,KAAK,cAAc,GAAI,EAAE,mBAAmB,SAAS;AAAA,IAC9D,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,EACR,CAAC;AACH;AA4BO,SAAS,4BACd,SACA,MAAc,KAAK,IAAI,GACN;AACjB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL,sBAAsB;AAAA,MACtB,aAAa;AAAA,MACb,kBAAkB,CAAC,6FAA6F;AAAA,IAClH;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC;AAIzB,MAAI,QAAQ,YAAY,UAAa,QAAQ,UAAU,MAAO,KAAK;AACjE,UAAM,KAAK,8CAA8C,WAAW,QAAQ,OAAO,CAAC,GAAG;AAAA,EACzF;AACA,MAAI,QAAQ,cAAc,UAAa,QAAQ,YAAY,MAAO,KAAK;AACrE,UAAM,KAAK,sDAAsD,WAAW,QAAQ,SAAS,CAAC,GAAG;AAAA,EACnG;AAEA,SAAO,EAAE,sBAAsB,OAAO,aAAa,SAAS,kBAAkB,MAAM;AACtF;;;AC3EO,SAAS,qBAAqB,OAAyB;AAC5D,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ;AAC7F,SACE,QAAQ,SAAS,iCAAiC,KAClD,QAAQ,SAAS,uCAAuC,KACxD,QAAQ,SAAS,oBAAoB,KACrC,QAAQ,SAAS,iBAAiB;AAEtC;AAEA,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,gBAAgB,CAAC,cAAc,cAAc,aAAa,WAAW,UAAU,cAAc;AAWnG,IAAM,gBAAgB;AAAA,EACpB;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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMA,eAAsB,qBAAqB,MAA2B;AACpE,QAAM,KAAK,MAAM,QAAQ,CAAC,UAAU;AAClC,QAAI,OAAO;AACX,QAAI;AACF,aAAO,IAAI,IAAI,MAAM,QAAQ,EAAE,IAAI,CAAC,EAAE;AAAA,IACxC,QAAQ;AACN,aAAO,MAAM,SAAS;AAAA,IACxB;AACA,UAAM,kBAAkB,cAAc,KAAK,CAAC,WAAW,SAAS,UAAU,KAAK,SAAS,IAAI,MAAM,EAAE,CAAC;AACrG,WAAO,kBAAkB,MAAM,MAAM,IAAI,MAAM,SAAS;AAAA,EAC1D,CAAC;AACH;AAMA,IAAM,SAAS,MAAiB;AAiBhC,eAAsB,YAAY,MAAY,KAAa,WAA2C;AACpG,QAAM,iBAAiB,wBAAwB,IAAI;AACnD,MAAI;AACF,UAAM,WAAW,MAAM,KAAK,KAAK,KAAK,EAAE,WAAW,oBAAoB,SAAS,UAAU,CAAC;AAG3F,UAAM,iBAAiB,IAAI;AAI3B,UAAM,KAAK,iBAAiB,eAAe,EAAE,SAAS,IAAM,CAAC,EAAE,MAAM,MAAM;AAK3E,UAAM,eAAe,MAAM,GAAK;AAChC,UAAM,kBAAkB,IAAI;AAC5B,UAAM,eAAe,MAAM,GAAK;AAEhC,UAAM;AAAA,MAAiB;AAAA,MAAM,MAC3B,KAAK,SAAS,YAAY;AACxB,cAAM,SAAS,MAAM;AAAA,MACvB,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,IAAI;AACvB,UAAM,cAAc,IAAI;AAExB,UAAM,WAAW,MAAM;AAAA,MAAiB;AAAA,MAAM,MAC5C,KAAK,SAAS,OAAO;AAAA,QACnB,UAAU,SAAS;AAAA,QACnB,OAAO,SAAS;AAAA,QAChB,gBAAgB,KAAK,IAAI,SAAS,gBAAgB,cAAc,SAAS,MAAM,gBAAgB,CAAC;AAAA,QAChG,WAAW,SAAS,MAAM,aAAa,IAAI,MAAM,GAAG,GAAI;AAAA,MAC1D,EAAE;AAAA,IACJ;AAIA,UAAM,SAAS,eAAe,aAAa,KAAK;AAChD,UAAM,cAAc,MAAM,QAAQ,gBAAgB,EAAE,MAAM,MAAM,IAAI;AAEpE,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ,eAAe,KAAK,KAAK,UAAU,OAAO,KAAK;AAAA,MACvD,UAAU,4BAA4B,WAAW;AAAA,IACnD;AAAA,EACF,UAAE;AACA,mBAAe,KAAK;AAAA,EACtB;AACF;AAcA,SAAS,wBAAwB,MAI/B;AACA,MAAI,SAAwB;AAC5B,MAAI,OAAwB;AAC5B,QAAM,aAAa,CAAC,aAAuB;AACzC,UAAM,UAAU,SAAS,QAAQ;AACjC,QAAI,QAAQ,aAAa,MAAM,cAAc,QAAQ,MAAM,MAAM,KAAK,UAAU,EAAG;AACnF,UAAM,OAAO,SAAS,OAAO;AAC7B,QAAI,QAAQ,OAAO,OAAO,IAAK;AAC/B,aAAS;AAGT,WAAO;AAAA,EACT;AACA,OAAK,GAAG,YAAY,UAAU;AAC9B,SAAO,EAAE,MAAM,MAAM,QAAQ,cAAc,MAAM,MAAM,MAAM,MAAM,KAAK,IAAI,YAAY,UAAU,EAAE;AACtG;AAGA,IAAM,sBAAsB;AAE5B,IAAM,8BAA8B;AAcpC,eAAsB,iBAAiB,MAAY,WAAW,6BAA4C;AACxG,MAAI,kBAAkB,KAAK,IAAI;AAC/B,QAAM,cAAc,CAAC,UAAmB;AACtC,QAAI,UAAU,KAAK,UAAU,EAAG,mBAAkB,KAAK,IAAI;AAAA,EAC7D;AACA,OAAK,GAAG,kBAAkB,WAAW;AACrC,MAAI;AACF,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,WAAO,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,IAAI,kBAAkB,qBAAqB;AAClF,YAAM,KAAK,eAAe,GAAG;AAAA,IAC/B;AAAA,EACF,UAAE;AACA,SAAK,IAAI,kBAAkB,WAAW;AAAA,EACxC;AACF;AAUA,eAAe,iBAAoB,MAAY,KAAmC;AAChF,MAAI;AACF,WAAO,MAAM,IAAI;AAAA,EACnB,SAAS,OAAO;AACd,QAAI,CAAC,qBAAqB,KAAK,EAAG,OAAM;AACxC,UAAM,iBAAiB,IAAI;AAC3B,WAAO,MAAM,IAAI;AAAA,EACnB;AACF;AAeA,eAAsB,cAAc,MAA2B;AAC7D,QAAM,eAAe,MAAM,GAAK;AAChC,QAAM,KAAK,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,MAAM;AAC3C,QAAM,KAAK,eAAe,IAAK;AAC/B,QAAM,eAAe,MAAM,GAAK;AAChC,QAAM,KAAK,SAAS,MAAM,OAAO,SAAS,GAAG,CAAC,CAAC,EAAE,MAAM,MAAM;AAC/D;AAEA,eAAsB,eAAe,MAAY,iBAAwC;AAGvF,QAAM,KACH,QAAQ,kBAAkB,KAAK,IAAI,CAAC,EACpC,MAAM,EACN,QAAQ,EAAE,OAAO,YAAY,SAAS,gBAAgB,CAAC,EACvD,MAAM,MAAM;AAEf,aAAW,YAAY,mBAAmB;AACxC,UAAM,QAAQ,KAAK,QAAQ,QAAQ,EAAE,MAAM;AAC3C,QAAI,CAAE,MAAM,MAAM,MAAM,EAAE,MAAM,MAAM,CAAC,EAAI;AAC3C,UAAM,MAAM,MAAM,EAAE,SAAS,KAAO,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM;AAC/D,UAAM,KAAK,eAAe,GAAG;AAC7B;AAAA,EACF;AAEA,aAAW,QAAQ,eAAe;AAChC,UAAM,SAAS,KAAK,UAAU,UAAU,EAAE,MAAM,MAAM,OAAO,MAAM,CAAC,EAAE,MAAM;AAC5E,QAAI,CAAE,MAAM,OAAO,MAAM,EAAE,MAAM,MAAM,CAAC,EAAI;AAC5C,QAAI,CAAE,MAAM,OAAO,UAAU,EAAE,MAAM,MAAM,KAAK,EAAI;AACpD,UAAM,OAAO,MAAM,EAAE,SAAS,KAAO,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM;AAChE,UAAM,KAAK,eAAe,GAAG;AAC7B;AAAA,EACF;AACF;AASA,eAAe,kBAAkB,MAA2B;AAC1D,QAAM;AAAA,IAAiB;AAAA,IAAM,MAC3B,KAAK,SAAS,YAAY;AACxB,YAAM,OAAO;AACb,YAAM,QAAQ,MAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG,CAAC;AACrE,eAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,eAAO,SAAS,GAAG,IAAI;AACvB,cAAM,MAAM;AACZ,cAAM,gBAAgB,OAAO,UAAU,OAAO,eAAe,SAAS,gBAAgB,eAAe;AACrG,YAAI,cAAe;AAAA,MACrB;AACA,aAAO,SAAS,GAAG,CAAC;AACpB,YAAM,MAAM;AAAA,IACd,CAAC;AAAA,EACH;AACA,QAAM,KAAK,eAAe,GAAG;AAC/B;AAGA,IAAM,oBAAoB;AAkB1B,SAAS,oBAAoB,iBAA+B;AAC1D,SAAO,SAAS,GAAG,CAAC;AACpB,aAAW,WAAW,MAAM,KAAK,SAAS,iBAA8B,GAAG,CAAC,GAAG;AAC7E,UAAM,WAAW,iBAAiB,OAAO,EAAE;AAE3C,QAAI,aAAa,UAAU;AACzB,cAAQ,MAAM,YAAY,YAAY,UAAU,WAAW;AAC3D;AAAA,IACF;AACA,QAAI,aAAa,QAAS;AAE1B,UAAM,OAAO,QAAQ,sBAAsB;AAC3C,UAAM,sBAAsB,KAAK,OAAO,KAAK,KAAK,SAAS,KAAK,KAAK,UAAU;AAC/E,QAAI,qBAAqB;AACvB,cAAQ,MAAM,YAAY,YAAY,YAAY,WAAW;AAC7D,cAAQ,MAAM,YAAY,UAAU,QAAQ,WAAW;AAAA,IACzD,OAAO;AACL,cAAQ,MAAM,YAAY,WAAW,QAAQ,WAAW;AAAA,IAC1D;AAAA,EACF;AACF;AAEA,eAAe,cAAc,MAA2B;AACtD,QAAM,iBAAiB,MAAM,MAAM,KAAK,SAAS,qBAAqB,iBAAiB,CAAC;AACxF,QAAM,KAAK,eAAe,GAAG;AAC/B;AAOA,eAAe,aAAa,MAA2B;AACrD,QAAM;AAAA,IAAiB;AAAA,IAAM,MAC3B,KAAK,SAAS,MAAM;AAClB,YAAM,eAAe,OAAO,WAAW,MAAM,QAAW,CAAC;AACzD,eAAS,KAAK,GAAG,MAAM,cAAc,KAAM,QAAO,cAAc,EAAE;AAElE,YAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,YAAM,aAAa,qBAAqB,MAAM;AAC9C,YAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAKpB,eAAS,KAAK,YAAY,KAAK;AAE/B,iBAAW,SAAS,MAAM,KAAK,SAAS,iBAAiB,OAAO,CAAC,GAAG;AAClE,cAAM,MAAM;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,KAAK,eAAe,GAAG;AAC/B;;;AC9WO,SAAS,qBAAqB,OAAuB;AAC1D,QAAM,SAAS,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG;AACtD,QAAM,OAAiB,CAAC;AAExB,WAAS,IAAI,GAAG,IAAI,OAAO,SAAS,GAAG,KAAK;AAC1C,UAAM,UAAU,OAAO,CAAC;AACxB,UAAM,OAAO,OAAO,IAAI,CAAC;AACzB,QAAI,CAAC,WAAW,CAAC,KAAM;AACvB,QAAI,KAAK,MAAM,QAAQ,QAAQ;AAC7B,YAAM,MAAM,KAAK,MAAM,QAAQ;AAG/B,UAAI,MAAM,IAAK,MAAK,KAAK,GAAG;AAAA,IAC9B;AAAA,EACF;AAEA,OAAK,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACzB,QAAM,MAAM,KAAK,KAAK,MAAM,KAAK,SAAS,IAAI,CAAC;AAC/C,MAAI,QAAQ,OAAW,QAAO;AAC9B,SAAO,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC;AACvC;AAUO,SAAS,aAAa,GAAS,GAAS,QAAgB,QAAyB;AACtF,QAAM,UAAU,EAAE,KAAK,EAAE,MAAM,QAAQ,QAAQ,EAAE,SAAS,OAAO;AACjE,QAAM,UAAU,EAAE,KAAK,EAAE,MAAM,QAAQ,QAAQ,EAAE,SAAS,OAAO;AAEjE,QAAM,WACH,QAAQ,OAAO,QAAQ,UAAU,QAAQ,UAAU,QAAQ,OAC3D,QAAQ,OAAO,QAAQ,UAAU,QAAQ,UAAU,QAAQ;AAC9D,MAAI,SAAU,QAAO;AAErB,QAAM,MAAM,KAAK,IAAI,KAAK,IAAI,QAAQ,SAAS,QAAQ,GAAG,GAAG,KAAK,IAAI,QAAQ,SAAS,QAAQ,GAAG,CAAC;AACnG,SAAO,OAAO;AAChB;AAUO,SAAS,sBAAsB,OAA8E;AAClH,QAAM,SAAS,MAAM,aAAa,KAAK,MAAM,SAAS;AACtD,SAAO,UAAU,MAAM,eAAe;AACxC;;;AChDA,eAAsB,mBAAmB,MAA2B;AAClE,QAAM,KAAK,cAAc;AAAA,IACvB,SAAS;AAAA;AAAA;AAAA,gCAGmB,qBAAqB,SAAS,CAAC;AAAA,wBACvC,aAAa,SAAS,CAAC;AAAA,iCACd,sBAAsB,SAAS,CAAC;AAAA;AAAA,EAE/D,CAAC;AACH;AAEA,eAAsB,YAAY,MAAY,SAAsD;AAClG,SAAO,MAAM,KAAK,SAAS,eAAe,OAAO;AACnD;AAaA,IAAM,gBAAgB,CAAC,YAAgD;AACrE,QAAM,OAAQ,OAAiD;AA+B/D,QAAM,UAAU,OAAO;AACvB,QAAM,UAAU,OAAO;AACvB,QAAM,WAAW,KAAK,IAAI,SAAS,gBAAgB,aAAa,SAAS,MAAM,eAAe,CAAC;AAC/F,QAAM,YAAY,KAAK,IAAI,SAAS,gBAAgB,cAAc,SAAS,MAAM,gBAAgB,CAAC;AAGlG,QAAM,SAAS,CAAC,YAAqB;AACnC,UAAM,IAAI,QAAQ,sBAAsB;AACxC,UAAM,MAAM,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,MAAM,OAAO,CAAC;AACnD,UAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,OAAO,OAAO,CAAC;AACrD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,QAAQ,KAAK,IAAI,WAAW,KAAK,MAAM,EAAE,SAAS,OAAO,CAAC;AAAA,MAC1D,OAAO,KAAK,IAAI,UAAU,KAAK,MAAM,EAAE,QAAQ,OAAO,CAAC;AAAA,IACzD;AAAA,EACF;AAMA,QAAM,gBAAgB,CAAC,YAAqB;AAC1C,UAAM,WAAW,MAAM,KAAK,QAAQ,QAAQ;AAC5C,QAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAI,MAAM,OAAO;AACjB,QAAI,OAAO,OAAO;AAClB,QAAI,SAAS,OAAO;AACpB,QAAI,QAAQ,OAAO;AACnB,eAAW,SAAS,UAAU;AAC5B,YAAM,IAAI,OAAO,KAAK;AACtB,UAAI,EAAE,SAAS,EAAE,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAG;AACpD,YAAM,KAAK,IAAI,KAAK,EAAE,GAAG;AACzB,aAAO,KAAK,IAAI,MAAM,EAAE,IAAI;AAC5B,eAAS,KAAK,IAAI,QAAQ,EAAE,MAAM;AAClC,cAAQ,KAAK,IAAI,OAAO,EAAE,KAAK;AAAA,IACjC;AACA,QAAI,CAAC,OAAO,SAAS,GAAG,KAAK,CAAC,OAAO,SAAS,MAAM,EAAG,QAAO;AAC9D,WAAO,EAAE,KAAK,MAAM,QAAQ,MAAM;AAAA,EACpC;AAEA,QAAM,QAAQ,CAAC,YAAqB;AAClC,UAAM,QAAQ,iBAAiB,OAAO;AACtC,UAAM,IAAI,MAAM,YAAY,aAAa,cAAc,OAAO,IAAI,OAAO,OAAO;AAChF,QAAI,CAAC,EAAG,QAAO;AACf,WAAO,EAAE,GAAG,GAAG,QAAQ,EAAE,SAAS,EAAE,KAAK,OAAO,EAAE,QAAQ,EAAE,KAAK;AAAA,EACnE;AAGA,QAAM,oBAAoB,CAAC,YAAqC;AAC9D,QAAI,UAA0B;AAC9B,WAAO,WAAW,YAAY,SAAS,iBAAiB;AACtD,YAAM,QAAQ,iBAAiB,OAAO;AACtC,UAAI,MAAM,YAAY,UAAU,MAAM,eAAe,YAAY,OAAO,MAAM,OAAO,MAAM,EAAG,QAAO;AACrG,gBAAU,QAAQ;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAQA,QAAM,sBAAsB,CAAC,SAAkB,QAAsE;AACnH,QAAI,SAAS,QAAQ;AACrB,WAAO,UAAU,WAAW,SAAS,iBAAiB;AACpD,YAAM,QAAQ,iBAAiB,MAAM;AACrC,YAAM,QACJ,MAAM,aAAa,YACnB,MAAM,cAAc,YACpB,MAAM,cAAc,YACpB,MAAM,aAAa;AACrB,UAAI,OAAO;AACT,cAAM,IAAI,OAAO,MAAM;AACvB,cAAM,aAAa,IAAI,OAAO,EAAE,SAAS,IAAI,QAAQ,EAAE,QAAQ,IAAI,MAAM,EAAE,UAAU,IAAI,SAAS,EAAE;AACpG,YAAI,CAAC,WAAY,QAAO;AAAA,MAC1B;AACA,eAAS,OAAO;AAAA,IAClB;AACA,WAAO;AAAA,EACT;AAOA,QAAM,aAAa,CAAC,YAAqB;AACvC,QAAI,OAAO;AACX,eAAW,QAAQ,MAAM,KAAK,QAAQ,UAAU,GAAG;AACjD,UAAI,KAAK,aAAa,EAAG,SAAQ,KAAK,eAAe;AAAA,IACvD;AACA,WAAO,KAAK,KAAK;AAAA,EACnB;AAGA,QAAM,gBAAgB,oBAAI,IAAI,CAAC,UAAU,SAAS,YAAY,UAAU,CAAC;AAUzE,QAAM,cAAc,CAAC,SAAkB;AACrC,QAAI,OAAO;AACX,UAAM,cAAc,oBAAI,IAAsB;AAC9C,UAAM,WAAW,CAAC,YAAqB;AACrC,YAAM,SAAS,YAAY,IAAI,OAAO;AACtC,UAAI,WAAW,OAAW,QAAO;AACjC,YAAM,QAAQ,iBAAiB,OAAO;AACtC,YAAM,SAAS,MAAM,YAAY,UAAU,MAAM,eAAe;AAChE,kBAAY,IAAI,SAAS,MAAM;AAC/B,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,SAAS,iBAAiB,MAAM,WAAW,WAAW;AAAA,MACnE,YAAY,CAAC,SAAS;AACpB,YAAI,SAAS,KAAK;AAClB,eAAO,QAAQ;AAIb,cAAI,cAAc,IAAI,OAAO,OAAO,KAAK,SAAS,MAAM,EAAG,QAAO,WAAW;AAC7E,cAAI,WAAW,KAAM;AACrB,mBAAS,OAAO;AAAA,QAClB;AACA,eAAO,WAAW;AAAA,MACpB;AAAA,IACF,CAAC;AACD,WAAO,OAAO,SAAS,KAAK,KAAK,SAAS,KAAK;AAC7C,cAAQ,IAAI,OAAO,YAAY,eAAe,EAAE;AAAA,IAClD;AACA,WAAO,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,EACxC;AAEA,QAAM,eAAe,oBAAI,IAAI,CAAC,OAAO,OAAO,SAAS,WAAW,UAAU,QAAQ,CAAC;AAEnF,QAAM,qBAAqB,CAAC,YAAqB;AAC/C,UAAM,KAAK,iBAAiB,OAAO,EAAE;AACrC,WAAO,QAAQ,EAAE,KAAK,OAAO,UAAU,GAAG,SAAS,MAAM;AAAA,EAC3D;AAEA,QAAM,gBAAgB,CAAC,YAAqB;AAC1C,UAAM,MAAM,QAAQ,QAAQ,YAAY;AACxC,QAAI,aAAa,IAAI,GAAG,EAAG,QAAO;AAClC,QAAI,WAAW,OAAO,EAAE,SAAS,EAAG,QAAO;AAC3C,WAAO,mBAAmB,OAAO;AAAA,EACnC;AAGA,QAAM,cAAc,CAAC,YAA6B;AAChD,UAAM,QAAkB,CAAC;AACzB,QAAI,UAA0B;AAC9B,WAAO,WAAW,YAAY,SAAS,iBAAiB;AACtD,YAAM,MAAM,QAAQ,QAAQ,YAAY;AACxC,UAAI,QAAQ,QAAQ;AAClB,cAAM,QAAQ,MAAM;AACpB;AAAA,MACF;AACA,YAAM,SAAyB,QAAQ;AACvC,UAAI,CAAC,QAAQ;AACX,cAAM,QAAQ,GAAG;AACjB;AAAA,MACF;AACA,YAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,SAAS,OAAO;AACxF,YAAM,WAAW,QAAQ,QAAQ,OAAO,IAAI;AAC5C,YAAM,QAAQ,QAAQ,SAAS,IAAI,GAAG,GAAG,gBAAgB,QAAQ,MAAM,GAAG;AAC1E,gBAAU;AAAA,IACZ;AACA,WAAO,MAAM,KAAK,KAAK;AAAA,EACzB;AAIA,QAAM,SAAiB,CAAC;AACxB,QAAM,MAAM,SAAS,iBAAiB,GAAG;AACzC,QAAM,QAAQ,KAAK,IAAI,IAAI,QAAQ,QAAQ,WAAW;AAEtD,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,UAAM,UAAU,IAAI,CAAC;AACrB,QAAI,CAAC,QAAS;AACd,UAAM,MAAM,QAAQ,QAAQ,YAAY;AACxC,QAAI,QAAQ,YAAY,QAAQ,WAAW,QAAQ,cAAc,QAAQ,UAAU,QAAQ,OAAQ;AACnG,QAAI,CAAC,cAAc,OAAO,EAAG;AAE7B,UAAM,MAAM,MAAM,OAAO;AACzB,QAAI,CAAC,OAAO,IAAI,UAAU,KAAK,IAAI,SAAS,EAAG;AAE/C,QAAI,IAAI,SAAS,QAAQ,iBAAkB;AAC3C,QAAI,kBAAkB,OAAO,EAAG;AAChC,QAAI,oBAAoB,SAAS,GAAG,EAAG;AAEvC,WAAO,KAAK;AAAA,MACV;AAAA,MACA,KAAK,IAAI;AAAA,MACT,QAAQ,IAAI;AAAA,MACZ,MAAM,IAAI;AAAA,MACV,OAAO,IAAI;AAAA,MACX,QAAQ,IAAI;AAAA,IACd,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO,CAAC;AAIjC,QAAM,eAAe,KAAK,qBAAqB,OAAO,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,QAAQ,EAAE,OAAO,EAAE,CAAC;AAIpG,QAAM,iBAAiB,CAAC,aAAwC;AAC9D,QAAI,WAA2B,SAAS,CAAC,KAAK;AAC9C,WAAO,YAAY,CAAC,SAAS,MAAM,CAAC,MAAM,UAAU,SAAS,CAAC,CAAC,GAAG;AAChE,iBAAW,SAAS;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,CAAC,YAA8B,QAAQ,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,QAAQ,KAAK,EAAE;AAS1F,QAAM,uBAAuB,CAC3B,OACA,WACmH;AACnH,QAAI,UAA0B;AAC9B,WAAO,SAAS;AACd,YAAM,MAAM,MAAM,OAAO;AACzB,UAAI,CAAC,IAAK,QAAO;AACjB,UAAI,IAAI,SAAS,QAAQ,iBAAkB,QAAO;AAClD,YAAM,SACJ,IAAI,OAAO,OAAO,OAAO,IAAI,UAAU,OAAO,UAAU,IAAI,QAAQ,OAAO,QAAQ,IAAI,SAAS,OAAO;AACzG,UAAI,OAAQ,QAAO,EAAE,SAAS,IAAI;AAClC,UAAI,CAAC,QAAQ,iBAAiB,QAAQ,kBAAkB,SAAS,gBAAiB,QAAO;AACzF,gBAAU,QAAQ;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAUA,QAAM,cAAc,CAAC,YAA8B;AACjD,UAAM,SAAS;AAAA,MACb,KAAK,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAAA,MAC1C,QAAQ,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,MAChD,MAAM,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAAA,MAC5C,OAAO,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,IAChD;AAEA,UAAM,WAAW,qBAAqB,eAAe,QAAQ,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,MAAM;AACxF,QAAI,CAAC,SAAU,QAAO,QAAQ,OAAO;AAErC,WAAO;AAAA,MACL;AAAA,QACE,MAAM,SAAS;AAAA,QACf,KAAK,SAAS,IAAI;AAAA,QAClB,QAAQ,SAAS,IAAI;AAAA,QACrB,MAAM,SAAS,IAAI;AAAA,QACnB,OAAO,SAAS,IAAI;AAAA,QACpB,QAAQ,SAAS,IAAI;AAAA,QACrB,QAAQ,QAAQ,QAAQ,CAAC,MAAM,EAAE,MAAM;AAAA,QACvC,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc,CAACC,YAA6B;AAChD,UAAM,UAAqB,CAAC;AAC5B,eAAW,SAASA,SAAQ;AAC1B,UAAI,MAAM,QAAQ;AAChB,gBAAQ,KAAK,CAAC,KAAK,CAAC;AACpB;AAAA,MACF;AACA,YAAM,SAAS,QAAQ;AAAA,QAAK,CAAC,WAC3B,OAAO;AAAA,UACL,CAAC,WACC,CAAC,OAAO,UACR,KAAK;AAAA,YACH,EAAE,KAAK,OAAO,KAAK,QAAQ,OAAO,OAAO;AAAA,YACzC,EAAE,KAAK,MAAM,KAAK,QAAQ,MAAM,OAAO;AAAA,YACvC,QAAQ;AAAA,YACR;AAAA,UACF;AAAA,QACJ;AAAA,MACF;AACA,UAAI,OAAQ,QAAO,KAAK,KAAK;AAAA,UACxB,SAAQ,KAAK,CAAC,KAAK,CAAC;AAAA,IAC3B;AAEA,QAAI,QAAQ,WAAWA,QAAO,OAAQ,QAAOA;AAC7C,WAAO,QAAQ,QAAQ,CAAC,WAAY,OAAO,WAAW,IAAI,CAAC,OAAO,CAAC,CAAU,IAAI,YAAY,MAAM,CAAE;AAAA,EACvG;AAEA,MAAI,SAAkB,OAAO,IAAI,CAAC,UAAU;AAAA,IAC1C,MAAM,KAAK;AAAA,IACX,KAAK,KAAK;AAAA,IACV,QAAQ,KAAK;AAAA,IACb,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,QAAQ,CAAC,IAAI;AAAA,IACb,QAAQ;AAAA,EACV,EAAE;AAEF,WAAS,OAAO,GAAG,OAAO,IAAI,QAAQ;AACpC,UAAM,OAAO,YAAY,MAAM;AAC/B,QAAI,KAAK,WAAW,OAAO,OAAQ;AACnC,aAAS;AAAA,EACX;AAIA,WAAS,OAAO,GAAG,OAAO,IAAI,QAAQ;AACpC,QAAI,WAAW;AACf,aAAS,OAAO,IAAI,CAAC,UAAU;AAC7B,YAAM,SAAS,MAAM,KAAK;AAC1B,UAAI,CAAC,UAAU,WAAW,SAAS,mBAAmB,WAAW,SAAS,KAAM,QAAO;AACvF,YAAM,YAAY,MAAM,MAAM;AAC9B,UAAI,CAAC,UAAW,QAAO;AACvB,UACE,CAAC,KAAK,sBAAsB;AAAA,QAC1B,YAAY,MAAM,OAAO;AAAA,QACzB,QAAQ,MAAM;AAAA,QACd,cAAc,UAAU;AAAA,MAC1B,CAAC,GACD;AACA,eAAO;AAAA,MACT;AACA,iBAAW;AACX,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM;AAAA,QACN,KAAK,UAAU;AAAA,QACf,QAAQ,UAAU;AAAA,QAClB,MAAM,UAAU;AAAA,QAChB,OAAO,UAAU;AAAA,QACjB,QAAQ,UAAU;AAAA,MACpB;AAAA,IACF,CAAC;AACD,QAAI,CAAC,SAAU;AACf,aAAS,YAAY,MAAM;AAAA,EAC7B;AAUA,QAAM,UAAU,CAAC,GAAU,MACzB,KAAK,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,KAC3B,KAAK,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,KACjC,KAAK,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,KAC7B,KAAK,IAAI,EAAE,QAAQ,EAAE,KAAK,KAAK;AASjC,QAAM,cAAc,CAAC,OAAc,UACjC,MAAM,MAAM,KAAK,MAAM,OACvB,MAAM,SAAS,KAAK,MAAM,UAC1B,MAAM,OAAO,KAAK,MAAM,QACxB,MAAM,QAAQ,KAAK,MAAM;AAE3B,QAAM,UAAmB,CAAC;AAK1B,QAAM,OAAO,CAAC,OAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE;AAClD,aAAW,SAAS,OAAO,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,SAAS,EAAE,OAAO,MAAM,GAAG;AACzG,UAAM,YAAY,QAAQ;AAAA,MACxB,CAAC,SACC,KAAK,SAAS,MAAM,QAAQ,KAAK,KAAK,SAAS,MAAM,IAAI,KAAK,QAAQ,MAAM,KAAK,KAAK,YAAY,MAAM,KAAK;AAAA,IACjH;AACA,QAAI,CAAC,UAAW,SAAQ,KAAK,KAAK;AAAA,EACpC;AAEA,SAAO,QACJ,OAAO,CAAC,UAAU,MAAM,SAAS,KAAK,MAAM,QAAQ,MAAM,OAAO,CAAC,EAClE,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAC5B,IAAI,CAAC,OAAO,WAAW;AAAA,IACtB;AAAA,IACA,UAAU,YAAY,MAAM,IAAI;AAAA,IAChC,MAAM;AAAA,MACJ,KAAK,MAAM;AAAA,MACX,MAAM,MAAM;AAAA,MACZ,OAAO,MAAM,QAAQ,MAAM;AAAA,MAC3B,QAAQ,MAAM;AAAA,IAChB;AAAA,IACA,WAAW,MAAM,OAAO;AAAA,IACxB,aAAa,YAAY,MAAM,IAAI,EAAE,MAAM,GAAG,GAAG;AAAA,EACnD,EAAE;AACN;;;AJ1eA,IAAM,iBAAiB,CAAC,GAAG,KAAK,KAAK,KAAK,KAAK,IAAI;AACnD,IAAM,cAAc;AACpB,IAAM,eAAe;AACrB,IAAM,eAAe;AAGrB,IAAM,kBAAkB;AAyBjB,SAAS,gBAAgB,KAAW,UAA0D;AACnG,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,SAAS,KAAK,CAAC;AAC3D,QAAM,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,SAAS,MAAM,CAAC;AAC1D,QAAM,QAAQ,KAAK,IAAI,IAAI,SAAS,OAAO,IAAI,OAAO,SAAS,QAAQ,IAAI;AAC3E,QAAM,SAAS,KAAK,IAAI,IAAI,UAAU,MAAM,IAAI,MAAM,SAAS,SAAS,GAAG;AAC3E,MAAI,QAAQ,KAAK,SAAS,EAAG,QAAO;AACpC,SAAO,EAAE,MAAM,KAAK,OAAO,OAAO;AACpC;AAEA,eAAsB,kBACpB,SACA,KACA,UACA,YAAY,MACgB;AAC5B,QAAM,EAAE,SAAS,KAAK,IAAI,MAAM,QAAQ,SAAS,kBAAkB,EAAE,QAAQ,KAAK,CAAC;AACnF,MAAI;AACF,UAAM,qBAAqB,IAAI;AAC/B,UAAM,mBAAmB,IAAI;AAC7B,UAAM,KAAK,KAAK,KAAK,EAAE,WAAW,oBAAoB,SAAS,UAAU,CAAC;AAG1E,UAAM,iBAAiB,IAAI;AAC3B,UAAM,KAAK,iBAAiB,eAAe,EAAE,SAAS,IAAM,CAAC,EAAE,MAAM,MAAM,MAAS;AAGpF,UAAM,cAAc,IAAI;AAExB,UAAM,SAAS,KAAK,QAAQ,QAAQ,EAAE,MAAM;AAC5C,QAAI,CAAE,MAAM,OAAO,MAAM,EAAE,MAAM,MAAM,CAAC,EAAI,QAAO;AAInD,UAAM,KAAK,SAAS,CAAC,oBAA4B;AAC/C,YAAM,UAAU,SAAS,cAAc,eAAe;AACtD,UAAI,CAAC,QAAS;AACd,YAAM,MAAM,QAAQ,sBAAsB,EAAE,MAAM,OAAO;AACzD,aAAO,SAAS,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,OAAO,cAAc,GAAG,GAAG,UAAU,UAAU,CAAC;AAAA,IAC3F,GAAG,QAAQ;AACX,UAAM,KAAK,eAAe,GAAG;AAE7B,UAAM,OAAO,MAAM,aAAa,MAAM,QAAQ;AAC9C,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,sBAAsB,MAAM,QAAQ;AAE1C,UAAM,SAAmB,CAAC;AAC1B,QAAI,WAAW;AACf,eAAW,QAAQ,gBAAgB;AACjC,YAAM,KAAK,eAAe,KAAK,IAAI,GAAG,OAAO,QAAQ,CAAC;AACtD,iBAAW;AACX,YAAM,OAAO,MAAM,KAChB,WAAW;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,MAAM,EAAE,GAAG,KAAK,MAAM,GAAG,KAAK,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,MAC5E,CAAC,EACA,MAAM,MAAM,IAAI;AACnB,UAAI,KAAM,QAAO,KAAK,IAAI;AAAA,IAC5B;AACA,QAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,WAAO,EAAE,WAAW,MAAM,iBAAiB,MAAM,GAAG,YAAY,OAAO,OAAO;AAAA,EAChF,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,UAAM,QAAQ,MAAM;AAAA,EACtB;AACF;AAgBA,eAAe,aAAa,MAAY,UAAwC;AAC9E,QAAM,MAAM,MAAM,KAAK;AAAA,IACrB,CAAC,CAAC,iBAAiB,MAAM,MAAM;AAC7B,YAAM,UAAU,SAAS,cAAc,eAAyB;AAChE,UAAI,CAAC,QAAS,QAAO;AACrB,YAAM,SAAS,QAAQ,sBAAsB;AAS7C,aAAO,SAAS,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,MAAM,OAAO,UAAW,MAAiB,GAAG,UAAU,UAAU,CAAC;AAC3G,YAAM,QAAQ,QAAQ,sBAAsB;AAC5C,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,KAAK,MAAM,MAAO;AAAA,QAClB,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM,SAAU;AAAA,QACxB,UAAU,EAAE,OAAO,OAAO,YAAY,QAAQ,OAAO,YAAY;AAAA,MACnE;AAAA,IACF;AAAA,IACA,CAAC,UAAU,eAAe;AAAA,EAC5B;AACA,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,gBAAgB,KAAK,IAAI,QAAQ;AAC1C;AAcA,eAAe,sBAAsB,MAAY,UAAiC;AAChF,QAAM,KAAK,SAAS,CAAC,oBAA4B;AAC/C,UAAM,SAAS,SAAS,cAAc,eAAe;AACrD,QAAI,CAAC,OAAQ;AACb,eAAW,WAAW,MAAM,KAAK,SAAS,iBAA8B,GAAG,CAAC,GAAG;AAC7E,YAAM,WAAW,iBAAiB,OAAO,EAAE;AAC3C,UAAI,aAAa,WAAW,aAAa,SAAU;AACnD,UAAI,QAAQ,SAAS,MAAM,KAAK,OAAO,SAAS,OAAO,KAAK,YAAY,OAAQ;AAChF,cAAQ,MAAM,YAAY,cAAc,UAAU,WAAW;AAAA,IAC/D;AAAA,EACF,GAAG,QAAQ;AACb;AAQA,eAAe,iBAAiB,QAAmC;AACjE,QAAM,SAAS,MAAM,QAAQ,IAAI,OAAO,IAAI,CAAC,UAAUC,OAAM,KAAK,EAAE,OAAO,EAAE,OAAO,YAAY,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AACpH,QAAM,QAAQ,MAAMA,OAAM,OAAO,CAAC,CAAC,EAAE,SAAS;AAC9C,QAAM,cAAc,MAAM,UAAU;AACpC,QAAM,aAAa,cAAc;AACjC,QAAM,OAAO,KAAK,KAAK,OAAO,SAAS,YAAY;AACnD,QAAM,QAAQ,cAAc,KAAK,IAAI,cAAc,OAAO,MAAM;AAEhE,QAAM,aAAa,OAAO,QAAQ,CAAC,OAAO,UAAU;AAClD,UAAM,SAAS,QAAQ;AACvB,UAAM,MAAM,KAAK,MAAM,QAAQ,YAAY;AAC3C,UAAM,QAAQ,OAAO;AAAA,MACnB,eAAe,WAAW,aAAa,YAAY;AAAA;AAAA,qFAE4B,eAAe,KAAK,KAAK,CAAC;AAAA;AAAA,IAE3G;AACA,WAAO;AAAA,MACL,EAAE,OAAO,OAAO,MAAM,SAAS,aAAa,KAAK,MAAM,WAAW;AAAA,MAClE,EAAE,OAAO,OAAO,MAAM,SAAS,aAAa,KAAK,MAAM,aAAa,aAAa;AAAA,IACnF;AAAA,EACF,CAAC;AAED,SAAO,MAAMA,OAAM;AAAA,IACjB,QAAQ;AAAA,MACN;AAAA,MACA,QAAQ,aAAa;AAAA,MACrB,UAAU;AAAA,MACV,YAAY,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG;AAAA,IACpC;AAAA,EACF,CAAC,EACE,UAAU,UAAU,EACpB,IAAI,EACJ,SAAS;AACd;;;AK5MA,IAAM,wBAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAS9B,eAAsB,kBACpB,SACA,MACA,eACA,UAAuD,CAAC,GAChC;AACxB,QAAM,EAAE,YAAY,OAAO,YAAY,IAAO,IAAI;AAClD,QAAM,EAAE,SAAS,KAAK,IAAI,MAAM,QAAQ,SAAS,EAAE,OAAO,eAAe,QAAQ,IAAI,CAAC;AACtF,MAAI;AACF,UAAM,KAAK,WAAW,MAAM,EAAE,WAAW,QAAQ,SAAS,UAAU,CAAC;AACrE,UAAM,KAAK,YAAY,EAAE,SAAS,sBAAsB,CAAC;AAGzD,UAAM,KAAK,SAAS,YAAY;AAC9B,YAAM,SAAS,MAAM;AAAA,IACvB,CAAC;AACD,UAAM,KAAK,eAAe,GAAG;AAE7B,QAAI,CAAC,WAAW;AAId,iBAAW,YAAY,CAAC,IAAI,sBAAsB,KAAK,UAAU,GAAG;AAClE,cAAM,SAAS,KAAK,QAAQ,QAAQ,EAAE,MAAM;AAC5C,YAAI,CAAE,MAAM,OAAO,MAAM,EAAI;AAC7B,cAAM,OAAO,MAAM,OAAO,WAAW,EAAE,MAAM,OAAO,SAAS,UAAU,CAAC,EAAE,MAAM,MAAM,IAAI;AAC1F,YAAI,KAAM,QAAO;AAAA,MACnB;AAAA,IACF;AACA,WAAO,MAAM,KAAK,WAAW,EAAE,MAAM,OAAO,UAAU,KAAK,CAAC,EAAE,MAAM,MAAM,IAAI;AAAA,EAChF,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,UAAM,QAAQ,MAAM;AAAA,EACtB;AACF;;;ACpEA,SAAS,iBAAiB;AAC1B,OAAO,UAAU;AAejB,eAAsB,mBAAmB,UAA0B,QAAiC;AAClG,QAAM,OAAO,KAAK,KAAK,QAAQ,aAAa;AAC5C,QAAM,UAAU,MAAM,aAAa,QAAQ,CAAC;AAC5C,SAAO;AACT;AAGO,SAASC,YAAW,OAAuB;AAChD,SAAO,MAAM;AAAA,IACX;AAAA,IACA,CAAC,eAAe,EAAE,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,UAAU,KAAK,QAAQ,GAAG,SAAS,KAAK;AAAA,EACzG;AACF;AAGO,SAAS,aAAa,UAA+D;AAC1F,MAAI,aAAa,KAAM,QAAO;AAC9B,MAAI,YAAY,KAAM,QAAO;AAC7B,MAAI,YAAY,KAAM,QAAO;AAC7B,SAAO;AACT;AAEO,SAAS,eAAe,UAAoD;AACjF,QAAM,SAAS,SACZ,IAAI,CAAC,YAAY,QAAQ,QAAQ,EACjC,OAAO,CAAC,UAA2B,UAAU,IAAI,EACjD,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACvB,SAAO,OAAO,WAAW,IAAI,OAAQ,OAAO,KAAK,MAAM,OAAO,SAAS,CAAC,CAAC,KAAK;AAChF;AAEA,SAAS,eAAe,UAAiC;AACvD,SAAO,aAAa,OAAO,WAAM,SAAS,QAAQ,CAAC;AACrD;AAEA,SAAS,cAAc,SAAiC;AACtD,QAAM,OAAO,aAAa,QAAQ,QAAQ;AAC1C,QAAM,WAAW,QAAQ,SAAS,QAAQ,OAAO,QAAQ,kBAAkB,sBAAsB,IAAI;AAErG,QAAM,OAAO,CAAC,OAAe,KAAoB,SAAkB;AACjE,QAAI,CAAC,IAAK,QAAO,0CAA0C,KAAK;AAChE,WAAO;AAAA,sBACW,KAAK,GAAG,OAAO,uBAAuBA,YAAW,IAAI,CAAC,YAAY,EAAE;AAAA,mBACvEA,YAAW,GAAG,CAAC,8CAA8CA,YAAW,GAAG,CAAC;AAAA;AAAA,EAE7F;AAEA,SAAO;AAAA;AAAA,gCAEuB,OAAO,QAAQ,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,WAAW,QAAQ,KAAK,KAAK,OAAI,QAAQ,KAAK,MAAM;AAAA,2BAC/F,IAAI,cAAc,eAAe,QAAQ,QAAQ,CAAC;AAAA,QACrE,QAAQ,eAAe,4BAA4BA,YAAW,QAAQ,YAAY,CAAC,YAAY,EAAE;AAAA,QACjG,QAAQ,OAAO,YAAY,8BAA8BA,YAAW,QAAQ,OAAO,OAAO,CAAC,YAAY,EAAE;AAAA;AAAA,yBAExFA,YAAW,QAAQ,YAAY,MAAM,GAAG,GAAG,CAAC,KAAK,kBAAkB;AAAA;AAAA,QAEpF,KAAK,QAAQ,QAAQ,WAAW,CAAC;AAAA,QACjC,KAAK,gBAAgB,UAAU,oCAAoC,CAAC;AAAA,QACpE,KAAK,UAAU,QAAQ,UAAU,CAAC;AAAA;AAAA,MAEpC,QAAQ,kBAAkB,0BAA0B,KAAK,2CAAsC,QAAQ,eAAe,CAAC,WAAW,EAAE;AAAA;AAAA,cAE5HA,YAAW,QAAQ,QAAQ,CAAC;AAAA,QAClC,QAAQ,SAAS,YAAYA,YAAW,QAAQ,MAAM,CAAC,2EAAsE,EAAE;AAAA;AAAA;AAGvI;AAEA,SAAS,aAAa,UAAkC;AACtD,QAAM,SAAS,eAAe,SAAS,QAAQ;AAI/C,QAAM,SAAS,SAAS,SAAS,OAAO,CAAC,YAAY,QAAQ,oBAAoB,IAAI,EAAE;AAEvF,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,+BAKiBA,YAAW,SAAS,SAAS,SAAS,GAAG,CAAC;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,MA0C9DA,YAAW,SAAS,SAAS,gBAAgB,CAAC;AAAA,0BAC1BA,YAAW,SAAS,QAAQ,CAAC,oCAAoCA,YAAW,SAAS,QAAQ,CAAC,sBAAmBA,YAAW,SAAS,UAAU,CAAC;AAAA;AAAA;AAAA,yBAGjJ,SAAS,SAAS,MAAM;AAAA,yBACxB,eAAe,MAAM,CAAC;AAAA,yBACtB,eAAe,SAAS,KAAK,QAAQ,CAAC;AAAA,yBACtC,MAAM;AAAA,yBACN,SAAS,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAMvB,aAAa,SAAS,KAAK,QAAQ,CAAC,cAAc,eAAe,SAAS,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MAM3G,SAAS,KAAK,SACV,mOACA,uFACN;AAAA;AAAA;AAAA;AAAA,EAIF,SAAS,SAAS,IAAI,aAAa,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA;AAIjD;;;ACnIO,IAAM,0BAA0C;AAAA,EACrD,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,aAAa;AACf;;;AhB0FA,eAAe,cAAc,MAMC;AAC5B,QAAM,EAAE,SAAS,MAAM,QAAQ,SAAS,aAAa,IAAI;AACzD,QAAM,QAAQ,MAAM,mBAAmB,MAAM,QAAQ,OAAO,EAAE,MAAM,MAAM,IAAI;AAC9E,MAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,MAAM,UAAU,KAAK;AAElD,QAAMC,WAAUC,MAAK,KAAK,QAAQ,WAAW,GAAG,MAAM,IAAI;AAC1D,QAAM,WAAW,MAAM,kBAAkB,SAAS,MAAM,MAAM,iBAAiB,OAAO;AAAA,IACpF,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AACD,MAAI,CAAC,YAAY,CAAC,aAAc,QAAO,EAAE,QAAQ,aAAa,UAAU,KAAK;AAE7E,QAAMD,WAAUC,MAAK,KAAK,QAAQ,mBAAmB,GAAG,QAAQ;AAChE,QAAM,EAAE,OAAO,KAAK,IAAI,MAAM,cAAc,cAAc,QAAQ;AAClE,SAAO,EAAE,QAAQ,aAAa,UAAU,OAAO,GAAI,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC,EAAG;AACzF;AAMA,eAAe,kBAAkB,MAQL;AAC1B,QAAM,EAAE,SAAS,MAAM,WAAW,aAAa,QAAQ,SAAS,SAAS,IAAI;AAC7E,QAAM,MAAMA,MAAK,KAAK,aAAa,OAAO,UAAU,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AAC3E,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AAEpC,QAAM,UAAU,MAAM,eAAe,MAAM,SAAS;AACpD,MAAI,QAAS,OAAMD,WAAUC,MAAK,KAAK,KAAK,aAAa,GAAG,OAAO;AACnE,QAAM,aAAa,UAAU,MAAM,eAAe,OAAO,IAAI;AAE7D,QAAM,SAAS,MAAM,cAAc,MAAM,UAAU,QAAQ;AAE3D,QAAM,QAAQ,WAAW,MAAM,mBAAmB,MAAM,UAAU,UAAU,OAAO,IAAI;AACvF,MAAI,WAA0B;AAC9B,MAAI;AAEJ,MAAI,OAAO;AACT,UAAMD,WAAUC,MAAK,KAAK,KAAK,cAAc,GAAG,MAAM,IAAI;AAC1D,UAAM,WAAW,MAAM,kBAAkB,SAAS,MAAM,MAAM,iBAAiB,KAAK;AACpF,QAAI,YAAY,SAAS;AACvB,YAAMD,WAAUC,MAAK,KAAK,KAAK,sBAAsB,GAAG,QAAQ;AAChE,YAAM,SAAS,MAAM,cAAc,SAAS,QAAQ;AACpD,iBAAW,OAAO;AAClB,qBAAe,OAAO;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,aAAa,UAAUA,MAAK,SAAS,QAAQA,MAAK,KAAK,KAAK,aAAa,CAAC,IAAI;AAAA,IAC9E,YAAY;AAAA,IACZ,QAAQ,QAAQA,MAAK,SAAS,QAAQA,MAAK,KAAK,KAAK,cAAc,CAAC,IAAI;AAAA,IACxE;AAAA,IACA,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,QAAQ,EAAE,UAAU,MAAM,MAAM,IAAI,CAAC;AAAA,IACzC;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA,EACF;AACF;AAQA,eAAe,mBAAmB,MAOhB;AAChB,QAAM,EAAE,SAAS,UAAU,aAAa,QAAQ,SAAS,UAAU,IAAI;AACvE,QAAM,SAAS,MAAM,QAAQ,SAAS,eAAe;AACrD,MAAI;AACF,UAAM,qBAAqB,OAAO,IAAI;AACtC,UAAM,mBAAmB,OAAO,IAAI;AACpC,UAAM,YAAY,OAAO,MAAM,SAAS,SAAS;AACjD,eAAW,WAAW,UAAU;AAC9B,YAAM,OAAO,MAAM,uBAAuB,OAAO,MAAM,OAAO;AAC9D,UAAI,CAAC,KAAM;AACX,YAAM,OAAOA,MAAK,KAAK,aAAa,OAAO,QAAQ,KAAK,EAAE,SAAS,GAAG,GAAG,GAAG,YAAY;AACxF,YAAMD,WAAU,MAAM,IAAI;AAC1B,cAAQ,aAAaC,MAAK,SAAS,QAAQ,IAAI;AAAA,IACjD;AAAA,EACF,UAAE;AACA,UAAM,OAAO,QAAQ,MAAM;AAAA,EAC7B;AACF;AAiBA,IAAM,qBAAqB;AAS3B,eAAe,mBAAmB,MAOhB;AAChB,QAAM,EAAE,SAAS,UAAU,aAAa,QAAQ,SAAS,IAAI,IAAI;AACjE,QAAM,SAAS,SAAS,OAAO,CAAC,YAAY,eAAe,QAAQ,MAAM,CAAC;AAC1E,MAAI,OAAO,WAAW,EAAG;AACzB,MAAI,WAAW,OAAO,MAAM,kBAAkB;AAE9C,QAAM,UAAU,OAAO,YAA2C;AAEhE,UAAM,OAAO,MAAM,kBAAkB,SAAS,SAAS,QAAQ,QAAQ,EAAE,MAAM,MAAM,IAAI;AACzF,QAAI,CAAC,KAAM;AACX,UAAM,MAAMA,MAAK,KAAK,aAAa,OAAO,QAAQ,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AACzE,UAAM,OAAOA,MAAK,KAAK,KAAK,sBAAsB;AAClD,UAAMD,WAAU,MAAM,KAAK,SAAS;AACpC,YAAQ,kBAAkBC,MAAK,SAAS,QAAQ,IAAI;AACpD,QAAI,MAAM,QAAQ,KAAK,KAAK,QAAQ,OAAO,OAAO,EAAE;AAAA,EACtD;AAIA,QAAM,QAAQ,CAAC,GAAG,MAAM;AACxB,QAAM,QAAQ;AAAA,IACZ,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,oBAAoB,MAAM,MAAM,EAAE,GAAG,YAAY;AAC7E,eAAS,OAAO,MAAM,MAAM,GAAG,MAAM,OAAO,MAAM,MAAM,GAAG;AACzD,cAAM,QAAQ,IAAI;AAAA,MACpB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAUA,eAAe,YACb,OACA,KACA,WAUA;AACA,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,UAAU,MAAM,cAAc,KAAK;AAMzC,MAAI,SAAwB;AAC5B,MAAI;AACF,UAAM,EAAE,SAAS,KAAK,IAAI,MAAM,QAAQ,SAAS,gBAAgB;AACjE,UAAM,qBAAqB,IAAI;AAC/B,UAAM,mBAAmB,IAAI;AAE7B,UAAM,WAAW,MAAM,YAAY,MAAM,KAAK,SAAS;AACvD,aAAS,SAAS;AAKlB,UAAM,UAAU,kBAAkB;AAAA,MAChC,QAAQ,SAAS;AAAA,MACjB,OAAO,SAAS;AAAA,MAChB,UAAU,SAAS;AAAA,MACnB,MAAM,MAAM,KAAK,QAAQ,EAAE,MAAM,MAAM,EAAE;AAAA,IAC3C,CAAC;AACD,QAAI,QAAS,OAAM,IAAI,iBAAiB,OAAO;AAE/C,WAAO,EAAE,IAAI,MAAM,SAAS,SAAS,MAAM,SAAS;AAAA,EACtD,SAAS,OAAO;AACd,UAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAC3C,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,QACP;AAAA,QACA,SAAS,uBAAuB,KAAK;AAAA,QACrC;AAAA,QACA,UAAU,aAAa,KAAK;AAAA,QAC5B,WAAW,KAAK,IAAI,IAAI;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;AAiBA,eAAe,sBAAsB,MAUnB;AAChB,QAAM,EAAE,SAAS,UAAU,aAAa,QAAQ,SAAS,WAAW,YAAY,YAAY,IAAI,IAAI;AAEpG,MAAI,YAAY;AACd,QAAI,kBAAkB;AACtB,UAAM,mBAAmB,EAAE,SAAS,UAAU,aAAa,QAAQ,SAAS,UAAU,CAAC;AAAA,EACzF;AACA,MAAI,YAAY;AACd,UAAM,mBAAmB,EAAE,SAAS,UAAU,aAAa,QAAQ,SAAS,IAAI,CAAC;AAAA,EACnF;AACF;AASA,eAAe,mBAAmB,MAOqB;AACrD,QAAM,EAAE,SAAS,MAAM,QAAQ,SAAS,UAAU,IAAI,IAAI;AAE1D,QAAM,WAAW,MAAM,KAAK,WAAW,EAAE,MAAM,OAAO,UAAU,KAAK,CAAC,EAAE,MAAM,MAAM,IAAI;AACxF,MAAI,SAAU,OAAMD,WAAUC,MAAK,KAAK,QAAQ,eAAe,GAAG,QAAQ;AAE1E,MAAI,CAAC,SAAU,QAAO,EAAE,QAAQ,MAAM,UAAU,KAAK;AAErD,QAAM,eAAe,MAAM,cAAc,EAAE,SAAS,MAAM,QAAQ,SAAS,cAAc,SAAS,CAAC;AACnG,MAAI,sBAAsB,aAAa,aAAa,OAAO,gBAAgB,aAAa,SAAS,QAAQ,CAAC,CAAC,EAAE;AAC7G,SAAO;AACT;AAGA,eAAe,gBAAgB,MAQD;AAC5B,QAAM,EAAE,SAAS,MAAM,aAAa,QAAQ,SAAS,UAAU,IAAI,IAAI;AAEvE,MAAI,YAAY;AAChB,QAAM,aAAa,MAAM,YAAY,MAAM,uBAAuB;AAClE,MAAI,SAAS,WAAW,MAAM,WAAW;AAEzC,QAAM,WAA6B,CAAC;AACpC,aAAW,aAAa,YAAY;AAClC,UAAM,UAAU,MAAM,kBAAkB;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,aAAS,KAAK,OAAO;AACrB;AAAA,MACE,MAAM,UAAU,KAAK,KAAK,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,MAAM,GAClE,QAAQ,aAAa,OAAO,KAAK,aAAa,QAAQ,SAAS,QAAQ,CAAC,CAAC,EAAE,WACxE,UAAU,YAAY,MAAM,GAAG,EAAE,CAAC;AAAA,IAC5C;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,WAAW,SAAqC;AACvD,SAAO;AAAA,IACL,MAAM,QAAQ,MAAM,SAAS,UAAU,QAAQ,MAAM,OAAO;AAAA,IAC5D,MAAM,QAAQ,QAAQ;AAAA,IACtB,QAAQ,QAAQ;AAAA,EAClB;AACF;AA2BA,eAAe,wBACb,SACA,KACyB;AACzB,MAAI,CAAC,sBAAsB,OAAO,EAAG,QAAO;AAE5C,QAAM,UAAU,MAAM,oBAAoB,QAAQ,KAAK,EAAE,MAAM,MAAM,IAAI;AACzE,MAAI,CAAC,WAAW,QAAQ,OAAQ,QAAO;AAEvC,MAAI,iDAAiD,QAAQ,OAAO,oCAA+B;AACnG,SAAO,eAAe,SAAS,QAAQ,OAAO;AAChD;AAEA,eAAe,cAAc,MAMsD;AACjF,QAAM,EAAE,KAAK,QAAQ,WAAW,UAAU,IAAI,IAAI;AAClD,QAAM,WAA6B,CAAC;AAEpC,WAAS,QAA2B,OAAO,CAAC,KAAK,EAAE,MAAM,SAAS,GAAG,SAAS;AAC5E,QAAI,WAAW,GAAG,GAAG,MAAM,SAAS,UAAU,kBAAkB,MAAM,IAAI,MAAM,EAAE,EAAE;AACpF,UAAM,UAAU,MAAM,YAAY,OAAO,KAAK,SAAS;AACvD,QAAI,QAAQ,IAAI;AACd,aAAO,EAAE,QAAQ,SAAS,UAAU,MAAM,MAAM,SAAS,UAAU,MAAM,OAAO,SAAS;AAAA,IAC3F;AAEA,aAAS,KAAK,MAAM,wBAAwB,QAAQ,SAAS,GAAG,CAAC;AACjE,UAAM,WAAW,UAAU;AAAA,MACzB;AAAA,MACA;AAAA,MACA,aAAa,WAAW,WAAW,KAAK,IAAI,IAAI,OAAO;AAAA,MACvD,WAAW;AAAA,MACX,cAAc;AAAA,IAChB,CAAC;AACD,QAAI,CAAC,SAAS,MAAM;AAClB,UAAI,mBAAmB,SAAS,MAAM,sBAAiB,SAAS,MAAM,EAAE;AACxE;AAAA,IACF;AACA,YAAQ,SAAS;AAAA,EACnB;AAEA,QAAM,IAAI,oBAAoB,kBAAkB,QAAQ,GAAG,SAAS,IAAI,UAAU,CAAC;AACrF;AAEA,eAAsB,cAAc,SAAiD;AACnF,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,MAAM,QAAQ,eAAe,MAAM;AACzC,QAAM,cAAcA,MAAK,KAAK,QAAQ,QAAQ,UAAU;AAMxD,QAAM,YAAY,mBAAmB,QAAQ,GAAG;AAChD,MAAI,WAAW;AACb,UAAM,IAAI,iBAAiB;AAAA,MACzB,MAAM;AAAA,MACN,SACE,cAAc,gBAAgB,sDAAsD;AAAA,IACxF,CAAC;AAAA,EACH;AAEA,QAAM,EAAE,QAAQ,UAAU,KAAK,IAAI,MAAM,cAAc;AAAA,IACrD,KAAK,QAAQ;AAAA,IACb,QAAQ,cAAc,QAAQ,KAAK,QAAQ,oBAAoB,CAAC,CAAC;AAAA,IACjE;AAAA,IACA,UAAU,QAAQ,WAAW,KAAK,IAAI,IAAI,QAAQ,WAAW;AAAA,IAC7D;AAAA,EACF,CAAC;AAED,QAAM,EAAE,SAAS,SAAS,MAAM,SAAS,IAAI;AAC7C,QAAM,YAAY,SAAS,SAAS;AAKpC,QAAM,aAAa,QAAQ,WAAW,SAAS,CAAC;AAKhD,QAAM,gBAAgB,QAAQ,SAAS,QAAQ,OAAO,MAAM,cAAc;AAE1E,MAAI;AAGF,UAAM,MAAM,aAAa,EAAE,WAAW,KAAK,CAAC;AAE5C,UAAM,WAAW,MAAM,gBAAgB;AAAA,MACrC,SAAS,iBAAiB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB,UAAU,QAAQ,SAAS;AAAA,MAC3B;AAAA,IACF,CAAC;AAED,UAAM,eAAe,MAAM,mBAAmB;AAAA,MAC5C,SAAS,iBAAiB;AAAA,MAC1B;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB,UAAU,QAAQ,SAAS;AAAA,MAC3B;AAAA,IACF,CAAC;AAED,UAAM,QAAQ,MAAM;AAEpB,UAAM,sBAAsB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,YAAY,QAAQ,WAAW;AAAA,MAC/B;AAAA,MACA;AAAA,IACF,CAAC;AAED,UAAM,WAA2B;AAAA,MAC/B,KAAK,QAAQ;AAAA,MACb,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS;AAAA,MAChB,gBAAgB,SAAS;AAAA,MACzB,UAAU;AAAA,MACV,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC;AAAA,MACA,MAAM;AAAA,MACN,UAAU,SAAS;AAAA,MACnB,aAAa;AAAA,IACf;AACA,UAAMD,WAAUC,MAAK,KAAK,QAAQ,QAAQ,eAAe,GAAG,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AACpG,QAAI,QAAQ,WAAW,OAAO;AAC5B,YAAM,aAAa,MAAM,mBAAmB,UAAU,QAAQ,MAAM;AACpE,UAAI,WAAW,UAAU,EAAE;AAAA,IAC7B;AACA,WAAO;AAAA,EACT,UAAE;AACA,UAAM,QAAQ,MAAM;AACpB,QAAI,cAAe,OAAM,cAAc,MAAM;AAAA,EAC/C;AACF;;;AiBroBA,SAAS,kBAAkB;AAC3B,OAAOC,WAAU;AAkBjB,IAAM,cAAc;AAepB,SAAS,SAAS,QAAgB,QAAyB;AACzD,QAAM,WAAWA,MAAK,SAAS,QAAQ,MAAM;AAC7C,SAAO,aAAa,MAAO,CAAC,SAAS,WAAW,IAAI,KAAK,CAACA,MAAK,WAAW,QAAQ;AACpF;AAQO,SAAS,aAAa,MAA6B;AACxD,MAAI,MAAMA,MAAK,QAAQ,IAAI;AAC3B,aAAS;AACP,QAAI,WAAWA,MAAK,KAAK,KAAK,MAAM,CAAC,EAAG,QAAO;AAC/C,UAAM,SAASA,MAAK,QAAQ,GAAG;AAC/B,QAAI,WAAW,IAAK,QAAO;AAC3B,UAAM;AAAA,EACR;AACF;AAEO,SAAS,gBAAgB,KAAa,SAAoE;AAC/G,QAAM,EAAE,KAAK,SAAS,IAAI;AAC1B,QAAM,WAAWA,MAAK,QAAQ,KAAK,GAAG;AACtC,MAAI,aAAa,QAAQ,CAAC,SAAS,UAAU,QAAQ,EAAG,QAAO,EAAE,IAAI,KAAK;AAE1E,QAAM,UAAUA,MAAK,KAAK,UAAU,WAAW;AAC/C,MAAI,SAAS,SAAS,QAAQ,EAAG,QAAO,EAAE,IAAI,KAAK;AAInD,QAAM,aAAaA,MAAK,MAAM,KAAK,aAAa,aAAaA,MAAK,SAAS,QAAQ,KAAK,SAAS;AACjG,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,kCAAkC,WAAW;AAAA,MACtD,KAAK;AAAA,QACH,QAAQ;AAAA,QACR,aAAa,qBAAqB,UAAU;AAAA,MAC9C;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AACF;;;ArBzDA,IAAM,qBAAqB,oBAAI,IAAwB;AAAA,EACrD;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AACF,CAAC;AAYD,SAAS,aAAa,MAA+E;AACnG,QAAM,EAAE,UAAU,QAAQ,OAAO,IAAI;AACrC,QAAM,QAAQ,SAAS,SAAS,OAAO,CAAC,YAAY,QAAQ,gBAAgB,IAAI,EAAE;AAClF,QAAM,YAAY,SAAS,SAAS,KAAK,CAAC,YAAY,QAAQ,aAAa,IAAI;AAE/E,QAAM,QAAkB,CAAC;AACzB,MAAI,SAAS,SAAS,iBAAiB,SAAS,GAAG;AACjD,UAAM;AAAA,MACJ,mEAAmE,SAAS,SAAS,iBAAiB,KAAK,GAAG,CAAC;AAAA,IACjH;AAAA,EACF;AAKA,MAAI,UAAU,GAAG;AACf,UAAM;AAAA,MACJ,2EAA2E,MAAM;AAAA,IACnF;AAAA,EACF,OAAO;AACL,UAAM;AAAA,MACJ,SACI,QAAQ,MAAM,iDAA4C,YAAY,6BAA6B,EAAE,MACrG,mCAAmC,MAAM;AAAA,MAC7C,GAAG,KAAK,OAAO,SAAS,SAAS,MAAM,yBAAyB,MAAM;AAAA,IACxE;AAAA,EACF;AAEA,QAAM,KAAK,kBAAkB,kBAAkB,kBAAkB,KAAK;AACtE,SAAO;AACT;AAkBA,eAAe;AAAA,EACb,SAAS;AAAA,EACT,aACE;AAAA,EACF,MAAM;AAAA,IACJ,KAAK,EAAE,MAAM,UAAU,aAAa,mBAAmB,UAAU,KAAK;AAAA,IACtE,KAAK,EAAE,MAAM,UAAU,aAAa,kCAAkC,UAAU,KAAK;AAAA,IACrF,QAAQ,EAAE,MAAM,WAAW,aAAa,8CAA8C,UAAU,MAAM;AAAA,IACtG,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ;AAAA,IACA,QAAQ,EAAE,MAAM,WAAW,aAAa,4CAA4C,UAAU,MAAM;AAAA,EACtG;AACF,CAAC;AAEM,IAAM,gBAAgB,cAAc;AAAA,EACzC,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aACE;AAAA,EACJ;AAAA,EACA,MAAM;AAAA,IACJ,KAAK,EAAE,MAAM,cAAc,aAAa,mBAAmB,UAAU,KAAK;AAAA,IAC1E,KAAK,EAAE,MAAM,UAAU,aAAa,mCAAmC,UAAU,KAAK;AAAA,IACtF,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA,MAAM,EAAE,MAAM,WAAW,aAAa,0CAA0C,UAAU,OAAO,SAAS,KAAK;AAAA,IAC/G,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,SAAS;AAAA,IACX;AAAA,IACA,QAAQ,EAAE,MAAM,WAAW,aAAa,2CAA2C,UAAU,OAAO,SAAS,KAAK;AAAA,EACpH;AAAA,EACA,KAAK,OAAO,EAAE,KAAK,MAAM;AAIvB,UAAMC,YAAW,gBAAgB,KAAK,KAAe;AAAA,MACnD,KAAK,QAAQ,IAAI;AAAA,MACjB,UAAU,aAAa,QAAQ,IAAI,CAAC;AAAA,IACtC,CAAC;AACD,QAAI,CAACA,UAAS,IAAI;AAChB,gBAAU,EAAE,IAAI,OAAO,OAAOA,UAAS,MAAM,CAAC;AAC9C,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,cAAc;AAAA,QACnC,KAAK,KAAK;AAAA,QACV,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA,QACb,MAAM,KAAK;AAAA,QACX,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA;AAAA;AAAA;AAAA,QAIb,kBAAkB,wBAAwB;AAAA,QAC1C,UAAU,gBAAgB,KAAK;AAAA;AAAA,QAE/B,YAAY,CAAC,YAAY,QAAQ,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,MAC9D,CAAC;AAED,YAAM,SAAS,SAAS,SACrB,IAAI,CAAC,YAAY,QAAQ,QAAQ,EACjC,OAAO,CAAC,UAA2B,UAAU,IAAI,EACjD,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAEvB,gBAAU;AAAA,QACR,IAAI;AAAA,QACJ,MAAM;AAAA,UACJ,OAAO,SAAS;AAAA,UAChB,UAAU,SAAS,SAAS;AAAA,UAC5B,gBAAgB,OAAO,SAAS,IAAI,OAAO,KAAK,MAAM,OAAO,SAAS,CAAC,CAAC,IAAI;AAAA,UAC5E,cAAc,SAAS,KAAK;AAAA,UAC5B,KAAK,KAAK;AAAA,UACV,QAAQ,KAAK,SAAS,GAAG,KAAK,GAAa,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,UAK5D,cAAc,SAAS;AAAA;AAAA;AAAA;AAAA,UAIvB,sBAAsB;AAAA,UACtB,GAAI,SAAS,SAAS,iBAAiB,SAAS,IAC5C,EAAE,mBAAmB,SAAS,SAAS,iBAAiB,IACxD,CAAC;AAAA,QACP;AAAA,QACA,OAAO,aAAa,EAAE,UAAU,QAAQ,KAAK,KAAe,QAAQ,KAAK,OAAkB,CAAC;AAAA,MAC9F,CAAC;AAAA,IACH,SAAS,OAAO;AAOd,YAAM,UAAU,uBAAuB,KAAK;AAG5C,cAAQ,OAAO,MAAM,gCAAgC,QAAQ,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,CAAI;AACvF,gBAAU;AAAA,QACR,IAAI;AAAA,QACJ,OAAO;AAAA,UACL,MAAM,QAAQ;AAAA,UACd,SAAS,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAOjB,GAAI,iBAAiB,uBAAuB,MAAM,MAAM,SAAS,IAAI,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,UAI/F,KAAK,mBAAmB,IAAI,QAAQ,IAAI,IACpC;AAAA,YACE,QAAQ;AAAA,YACR,aACE;AAAA,YACF,WAAW;AAAA,UACb,IACA;AAAA,YACE,QAAQ;AAAA,YACR,aACE;AAAA,YACF,WAAW;AAAA,UACb;AAAA,QACN;AAAA,MACF,CAAC;AACD,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF,CAAC;","names":["writeFile","path","sharp","groups","sharp","escapeHtml","writeFile","path","path","location"]}