hyperframes 0.8.184 → 0.8.186

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 (314) hide show
  1. package/dist/{add-5ZTD3MUZ.js → add-UGK7AZI6.js} +14 -14
  2. package/dist/{agentPromptGenerator-VIIPZCJ3.js → agentPromptGenerator-KYO5MKTW.js} +1 -1
  3. package/dist/{animatedGifPrep-AGASIWVA.js → animatedGifPrep-HPZPSB43.js} +9 -9
  4. package/dist/api.js +18 -18
  5. package/dist/{asset-LSTEMPIB.js → asset-X2GTFWOY.js} +2 -2
  6. package/dist/{assetCataloger-BKBMNL3A.js → assetCataloger-5NWEG4IU.js} +9 -9
  7. package/dist/audio-7PBM5F3H.js +2317 -0
  8. package/dist/{auth-MJWKYK77.js → auth-WABSMO46.js} +1 -1
  9. package/dist/{autoUpdate-2GGDKYR2.js → autoUpdate-6SCMLTSC.js} +2 -2
  10. package/dist/{backgroundChecks-7GRX5VQY.js → backgroundChecks-XOGPAAR3.js} +3 -3
  11. package/dist/backgroundChecksWorker.js +3 -3
  12. package/dist/{batchRender-BCV2LELR.js → batchRender-VR6IA77K.js} +5 -5
  13. package/dist/{beats-7BCFRBAL.js → beats-3IWXLMSC.js} +7 -7
  14. package/dist/{benchmark-2R6CN5MQ.js → benchmark-2SSYATCX.js} +10 -10
  15. package/dist/{browser-6AFGOI7G.js → browser-PMRN345D.js} +3 -3
  16. package/dist/{bundleWithLocalizedFonts-2EGPA5ZO.js → bundleWithLocalizedFonts-TT32MZBO.js} +2 -2
  17. package/dist/{capture-HOIAW6MO.js → capture-4VD6AKUJ.js} +13 -13
  18. package/dist/{capture-HA2UHLIU.js → capture-BDGYTE57.js} +2 -2
  19. package/dist/{captureCompositionFrame-4236FVWJ.js → captureCompositionFrame-5FVLAETA.js} +17 -13
  20. package/dist/{catalog-A6CZAWW4.js → catalog-HUYZO5D7.js} +14 -14
  21. package/dist/{catch-up-TNA4DJOA.js → catch-up-SSGTR2ZT.js} +4 -4
  22. package/dist/{check-5E5U2EQZ.js → check-JWUWHGM2.js} +34 -34
  23. package/dist/{checkBrowser-FNINXBMZ.js → checkBrowser-X7G6YNR7.js} +31 -31
  24. package/dist/{chunk-UJKUB2LH.js → chunk-22QKQDEE.js} +11 -11
  25. package/dist/{chunk-2PVE4WS2.js → chunk-27H2363S.js} +33 -6
  26. package/dist/{chunk-2ULXZ4PG.js → chunk-2II34JPM.js} +154 -21
  27. package/dist/{chunk-3QVMJ7GX.js → chunk-2PZZMAME.js} +11 -10
  28. package/dist/{chunk-X3CG5YQA.js → chunk-3YHGQJI6.js} +3 -3
  29. package/dist/{chunk-EEP5Y5IE.js → chunk-46HEFGXJ.js} +1 -1
  30. package/dist/{chunk-DWUGKEHR.js → chunk-4AFNEKU7.js} +1 -1
  31. package/dist/{chunk-R2BFTECP.js → chunk-4NTW45W5.js} +3 -3
  32. package/dist/{chunk-7HJALUIO.js → chunk-4XFFJAWS.js} +1 -1
  33. package/dist/{chunk-SN7KI5JA.js → chunk-5ZMIVTHN.js} +2 -2
  34. package/dist/{chunk-QL2PNIXC.js → chunk-5ZMXGNGC.js} +24 -16
  35. package/dist/{chunk-UKOTVJFV.js → chunk-6IOBAOU7.js} +1 -1
  36. package/dist/{chunk-JIUTXKWA.js → chunk-77QM6YRQ.js} +2 -1
  37. package/dist/{chunk-ES426XRJ.js → chunk-7AUMTARQ.js} +3 -3
  38. package/dist/{chunk-5CS4T6C6.js → chunk-7L37AB57.js} +1 -1
  39. package/dist/{chunk-RGXVEYHI.js → chunk-7M7TMM4S.js} +81 -10
  40. package/dist/{chunk-3TXNNBI2.js → chunk-7MLFYMFB.js} +2 -2
  41. package/dist/{chunk-MFAETWIF.js → chunk-7MVODWQF.js} +1 -1
  42. package/dist/{chunk-WHPN2TIT.js → chunk-ACLABKEF.js} +6 -6
  43. package/dist/{chunk-YMS5FOMC.js → chunk-B2A56S5C.js} +1 -1
  44. package/dist/{chunk-YALM6XN4.js → chunk-BRTDLVK3.js} +3 -3
  45. package/dist/{chunk-VDM3FEDP.js → chunk-DQZMJS2P.js} +1 -1
  46. package/dist/{chunk-PSKEKWVU.js → chunk-DTXDQ6OP.js} +1 -1
  47. package/dist/{chunk-Q33P4EAC.js → chunk-EZINX6HH.js} +3 -3
  48. package/dist/{chunk-3MDJIWOV.js → chunk-FCWFV4P7.js} +75 -35
  49. package/dist/{chunk-ABZYYUUH.js → chunk-FRLTKTOR.js} +1 -1
  50. package/dist/{chunk-E32ZQ2WO.js → chunk-GTMBII7X.js} +1 -1
  51. package/dist/{chunk-YOZPQCSR.js → chunk-HOFX63F2.js} +3 -3
  52. package/dist/{chunk-LRGYPXHF.js → chunk-HZ7M2MZA.js} +1 -1
  53. package/dist/{chunk-TYXH3EKP.js → chunk-I5JRXMCV.js} +16 -1
  54. package/dist/{chunk-LLC4CS6I.js → chunk-ID5AJ4L3.js} +3 -3
  55. package/dist/{chunk-FGJEUV4S.js → chunk-K6KBOORN.js} +48 -4
  56. package/dist/{chunk-EM7C7H7S.js → chunk-KNLSYCI5.js} +7 -7
  57. package/dist/{chunk-4N4P3ZWL.js → chunk-LDW3KVGK.js} +2 -2
  58. package/dist/{chunk-OLZENUPI.js → chunk-LLFQA7XF.js} +1 -1
  59. package/dist/chunk-LLMSX6V6.js +17 -0
  60. package/dist/{chunk-5UDRPPN2.js → chunk-MY6CVBDD.js} +7 -4
  61. package/dist/{chunk-7NRI7HYX.js → chunk-NPDPDEPP.js} +1 -1
  62. package/dist/{chunk-BCHSTE7U.js → chunk-PEIV2SOG.js} +1 -1
  63. package/dist/{chunk-ADDHW2FS.js → chunk-Q447CX26.js} +82 -12
  64. package/dist/{chunk-YWNJTZGN.js → chunk-R6IGQ5NO.js} +2 -2
  65. package/dist/{chunk-YWHCXIMD.js → chunk-RFJ6SX4U.js} +5 -5
  66. package/dist/{chunk-J3QM7AHP.js → chunk-RNZEQTWZ.js} +2 -2
  67. package/dist/{chunk-SAX7HQ5E.js → chunk-ROWEDRVX.js} +1 -1
  68. package/dist/{chunk-PFYWVUHA.js → chunk-RPUIMFHF.js} +1 -1
  69. package/dist/{chunk-OYLO6TYK.js → chunk-RUOG4VB7.js} +1 -1
  70. package/dist/{chunk-UNNXFKVG.js → chunk-RVZNSKRH.js} +2 -2
  71. package/dist/{chunk-VNVQGDPC.js → chunk-T4RP55P2.js} +1 -1
  72. package/dist/{chunk-GDEV42FA.js → chunk-TH7J3JZ5.js} +524 -42
  73. package/dist/{chunk-VHZ6DL3M.js → chunk-TMK4Q7JA.js} +10 -7
  74. package/dist/{chunk-74JMKLVU.js → chunk-TQ2RRB5V.js} +1 -1
  75. package/dist/{chunk-ICJEAFPD.js → chunk-U4BMRIE6.js} +16 -7
  76. package/dist/{chunk-HR23IKLZ.js → chunk-U7QTMRLW.js} +2 -2
  77. package/dist/{chunk-KN46TGHV.js → chunk-UAJCTEK2.js} +1 -1
  78. package/dist/{chunk-CXABAXB3.js → chunk-UJZT6HNN.js} +1 -1
  79. package/dist/chunk-UOZX5W5T.js +3852 -0
  80. package/dist/{chunk-FFJ5TDRD.js → chunk-VHBBV5DH.js} +10 -3
  81. package/dist/{chunk-ZRHO6YMM.js → chunk-WHMFW5ET.js} +4 -4
  82. package/dist/{chunk-WTFUDNW2.js → chunk-WLHNIIXU.js} +3 -3
  83. package/dist/{chunk-ZOCHDXDG.js → chunk-Y2M6XSNK.js} +1 -1
  84. package/dist/{chunk-2XA7KXQO.js → chunk-YNH6ERDL.js} +2 -2
  85. package/dist/{chunk-JB6ARMQS.js → chunk-YQICCAVA.js} +1 -1
  86. package/dist/{chunk-7MB2ZAQF.js → chunk-YRAJDFIN.js} +1 -1
  87. package/dist/{chunk-IWTNTUPQ.js → chunk-Z5233OAN.js} +11 -13
  88. package/dist/{chunk-TE427YID.js → chunk-ZKBW7NU2.js} +2 -2
  89. package/dist/{chunk-4KKKBEP3.js → chunk-ZVBEGBII.js} +3 -3
  90. package/dist/{clean-HGASSMWI.js → clean-IM2JIAUT.js} +18 -18
  91. package/dist/cli.js +53 -53
  92. package/dist/{cloud-JPDVNXHN.js → cloud-6IPBCJSX.js} +4 -4
  93. package/dist/{cloudrun-AMMGSDRP.js → cloudrun-MWZ6S2I2.js} +7 -7
  94. package/dist/commands/contrast-audit.browser.js +1 -2
  95. package/dist/commands/layout-audit.browser.js +196 -0
  96. package/dist/{compare-LHHVHUN3.js → compare-WD7A2TV5.js} +28 -28
  97. package/dist/{compiler-Q3N6QXMT.js → compiler-2EKSMC3I.js} +6 -6
  98. package/dist/{component-D72J32Q7.js → component-JKALWH36.js} +3 -3
  99. package/dist/{compositions-UQRJ5ROG.js → compositions-643NAG4A.js} +13 -13
  100. package/dist/{delete-P42VIDDA.js → delete-EASPXKHQ.js} +2 -2
  101. package/dist/{deploy-WZTH57O4.js → deploy-CDKCQ5MX.js} +1 -1
  102. package/dist/{deterministicFonts-VQ5UBMXY.js → deterministicFonts-EGAAE7QL.js} +3 -3
  103. package/dist/{dist-DYS24AMA.js → dist-F6FOKRSU.js} +10 -4
  104. package/dist/{dist-SENYPQGW.js → dist-LM7AVHOU.js} +3 -3
  105. package/dist/docs/data-attributes.md +1 -1
  106. package/dist/{doctor-KEJIG2SK.js → doctor-7XUVYDJQ.js} +13 -13
  107. package/dist/{events-CYKSNR7N.js → events-5TTPYBKG.js} +3 -3
  108. package/dist/{events-UZXFQPMT.js → events-TULV6D3G.js} +3 -3
  109. package/dist/{feedback-LXNQF7CA.js → feedback-4FTPWM6P.js} +8 -8
  110. package/dist/{ffmpeg-BYHON577.js → ffmpeg-MP7ZVYLZ.js} +9 -9
  111. package/dist/{figma-EIQ35PS6.js → figma-B7LFWYKO.js} +3 -3
  112. package/dist/fontLocalizeCli.js +12 -12
  113. package/dist/{get-CC2YL7QO.js → get-F7W4AQ2V.js} +2 -2
  114. package/dist/{gpuPolicy-VFSACUQV.js → gpuPolicy-NSNVDFXC.js} +9 -9
  115. package/dist/{grade-compare-TUQL7IV2.js → grade-compare-6QXDTLS2.js} +29 -29
  116. package/dist/{gsapParserAcorn-7NCK2LVT.js → gsapParserAcorn-SKODXC2N.js} +2 -2
  117. package/dist/{help-ROROO5K6.js → help-RJAA4O74.js} +1 -1
  118. package/dist/{history-PNELYLXX.js → history-OOQBDVV5.js} +6 -6
  119. package/dist/hyperframe.manifest.json +1 -1
  120. package/dist/hyperframe.runtime.iife.js +67 -67
  121. package/dist/hyperframes-player.global.js +1 -1
  122. package/dist/{info-4FZTH6AS.js → info-5OGGYYLO.js} +9 -9
  123. package/dist/{init-I43GHHVP.js → init-DM3TJKW2.js} +68 -50
  124. package/dist/{inspect-IT4TYIZ3.js → inspect-FECQCLS5.js} +29 -29
  125. package/dist/{installer-CWOJVK5K.js → installer-WOG4VORV.js} +7 -7
  126. package/dist/{keyframes-3FBOGVD4.js → keyframes-SZHWUF5Y.js} +7 -7
  127. package/dist/{lambda-H3V32I7M.js → lambda-JG2ZRGMC.js} +9 -9
  128. package/dist/{layout-BZ5LYJ5C.js → layout-7ACF7ZKC.js} +29 -29
  129. package/dist/{lint-ZTNSGP2S.js → lint-ZCQGMILV.js} +9 -9
  130. package/dist/{lintProject-C2ONSH2U.js → lintProject-JATQKR64.js} +3 -3
  131. package/dist/{list-XM4GWJYY.js → list-MH2X3Y2T.js} +2 -2
  132. package/dist/{login-H6HYKMWX.js → login-CK46WX5U.js} +4 -4
  133. package/dist/{manager-TWVDSJXO.js → manager-GXTPNJVW.js} +10 -10
  134. package/dist/{media-treatment-N7MY5NXB.js → media-treatment-EH2AT34Z.js} +15 -15
  135. package/dist/{models-WEMIMYBD.js → models-D5XP2UK6.js} +13 -13
  136. package/dist/{motionShot-RHICTVPU.js → motionShot-UR7D3SRQ.js} +16 -16
  137. package/dist/{normalize-4UDISLPL.js → normalize-3AYFSN2F.js} +1 -1
  138. package/dist/{normalize-audio-ZFUZCJE3.js → normalize-audio-635JOR5W.js} +4 -4
  139. package/dist/{open-IBJ4FL3G.js → open-6WE5WFVM.js} +14 -14
  140. package/dist/{parakeetRunner-XXO4WSLR.js → parakeetRunner-STHZPG32.js} +14 -14
  141. package/dist/{pipeline-6ML3LUVK.js → pipeline-LVEKRETU.js} +10 -10
  142. package/dist/{play-RV4NAVF5.js → play-W6TDW4FE.js} +21 -21
  143. package/dist/{preflight-R3DEFMLA.js → preflight-LIMQXLR7.js} +10 -10
  144. package/dist/{present-5TBJGE6B.js → present-RX5QX6UR.js} +17 -17
  145. package/dist/{preview-FLKZ5CXJ.js → preview-KIWTWK63.js} +20 -20
  146. package/dist/{producer-7XYSPVKH.js → producer-TSNKSCUM.js} +1 -1
  147. package/dist/{projectConfig-TBU2VWZX.js → projectConfig-NCP7JRH4.js} +9 -9
  148. package/dist/{publication-CWWUJYJ5.js → publication-5W5UZWGC.js} +4 -4
  149. package/dist/{publish-FSNE4FEB.js → publish-7WR4XJ6I.js} +11 -11
  150. package/dist/{remove-background-MDFWRWCT.js → remove-background-43JGBRWQ.js} +11 -11
  151. package/dist/{render-F4JQ553X.js → render-456HCO6O.js} +31 -31
  152. package/dist/{render-LWZKXCLY.js → render-7T44HIM6.js} +5 -5
  153. package/dist/{render-DBGQZAZT.js → render-WHMLYIOI.js} +18 -30
  154. package/dist/{render-batch-PU7NMLIJ.js → render-batch-LURBJTBV.js} +5 -5
  155. package/dist/renderSetupWorker.js +3 -3
  156. package/dist/{resolver-RUBGFXPC.js → resolver-MBIW4VC4.js} +6 -6
  157. package/dist/{sherpa-X2TBNO6P.js → sherpa-5J2AALED.js} +13 -13
  158. package/dist/skills/hyperframes/SKILL.md +52 -174
  159. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/FRAME.md +289 -0
  160. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/caption-skin.html +220 -0
  161. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
  162. package/dist/skills/hyperframes/assets/frame-presets/blockframe/FRAME.md +275 -0
  163. package/dist/skills/hyperframes/assets/frame-presets/blockframe/caption-skin.html +223 -0
  164. package/dist/skills/hyperframes/assets/frame-presets/blockframe/frame-showcase.html +1347 -0
  165. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/FRAME.md +307 -0
  166. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/caption-skin.html +222 -0
  167. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/frame-showcase.html +1372 -0
  168. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/FRAME.md +275 -0
  169. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/caption-skin.html +229 -0
  170. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/frame-showcase.html +1140 -0
  171. package/dist/skills/hyperframes/assets/frame-presets/broadside/FRAME.md +284 -0
  172. package/dist/skills/hyperframes/assets/frame-presets/broadside/caption-skin.html +224 -0
  173. package/dist/skills/hyperframes/assets/frame-presets/broadside/frame-showcase.html +1166 -0
  174. package/dist/skills/hyperframes/assets/frame-presets/capsule/FRAME.md +284 -0
  175. package/dist/skills/hyperframes/assets/frame-presets/capsule/caption-skin.html +223 -0
  176. package/dist/skills/hyperframes/assets/frame-presets/capsule/frame-showcase.html +1465 -0
  177. package/dist/skills/hyperframes/assets/frame-presets/cartesian/FRAME.md +278 -0
  178. package/dist/skills/hyperframes/assets/frame-presets/cartesian/caption-skin.html +221 -0
  179. package/dist/skills/hyperframes/assets/frame-presets/cartesian/frame-showcase.html +1263 -0
  180. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/FRAME.md +265 -0
  181. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/caption-skin.html +237 -0
  182. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
  183. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/FRAME.md +277 -0
  184. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/caption-skin.html +223 -0
  185. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-400.woff2 +0 -0
  186. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-700.woff2 +0 -0
  187. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-400.woff2 +0 -0
  188. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-700.woff2 +0 -0
  189. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-400.woff2 +0 -0
  190. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-700.woff2 +0 -0
  191. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-eb-garamond.txt +93 -0
  192. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-inter.txt +93 -0
  193. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-jetbrains-mono.txt +93 -0
  194. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/frame-showcase.html +1438 -0
  195. package/dist/skills/hyperframes/assets/frame-presets/coral/FRAME.md +314 -0
  196. package/dist/skills/hyperframes/assets/frame-presets/coral/caption-skin.html +225 -0
  197. package/dist/skills/hyperframes/assets/frame-presets/coral/frame-showcase.html +1268 -0
  198. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/FRAME.md +333 -0
  199. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/caption-skin.html +226 -0
  200. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/frame-showcase.html +1330 -0
  201. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/FRAME.md +274 -0
  202. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/caption-skin.html +229 -0
  203. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/frame-showcase.html +1444 -0
  204. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/FRAME.md +265 -0
  205. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/caption-skin.html +222 -0
  206. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/frame-showcase.html +1273 -0
  207. package/dist/skills/hyperframes/references/captions.md +46 -0
  208. package/dist/skills/hyperframes/references/film.md +47 -0
  209. package/dist/skills/hyperframes/references/format.md +157 -0
  210. package/dist/skills/hyperframes/references/look.md +69 -0
  211. package/dist/skills/hyperframes/references/motion.md +94 -0
  212. package/dist/skills/hyperframes/references/overlays.md +39 -0
  213. package/dist/skills/hyperframes/references/plugin-installation.md +3 -3
  214. package/dist/skills/hyperframes/references/review.md +51 -0
  215. package/dist/skills/hyperframes/references/runtimes.md +43 -0
  216. package/dist/skills/hyperframes/references/skill-lifecycle.md +21 -13
  217. package/dist/skills/hyperframes/references/sound.md +43 -0
  218. package/dist/skills/hyperframes/references/spec.md +76 -0
  219. package/dist/skills/hyperframes/references/story.md +103 -0
  220. package/dist/skills/hyperframes/references/storyboard-format.md +30 -22
  221. package/dist/skills/hyperframes/references/storyboard.md +36 -0
  222. package/dist/skills/hyperframes/references/types/3d.md +25 -0
  223. package/dist/skills/hyperframes/references/types/character.md +20 -0
  224. package/dist/skills/hyperframes/references/types/data.md +19 -0
  225. package/dist/skills/hyperframes/references/types/explainer.md +34 -0
  226. package/dist/skills/hyperframes/references/types/launch.md +31 -0
  227. package/dist/skills/hyperframes/references/types/music.md +24 -0
  228. package/dist/skills/hyperframes/references/types/vertical.md +23 -0
  229. package/dist/skills/hyperframes/scripts/bake-basemap.mjs +324 -0
  230. package/dist/skills/hyperframes/scripts/lib/main-module.test.mjs +1 -6
  231. package/dist/skills/hyperframes/scripts/locate.mjs +228 -0
  232. package/dist/skills/hyperframes-cli/SKILL.md +76 -179
  233. package/dist/skills/hyperframes-cli/references/beats.md +1 -1
  234. package/dist/skills/hyperframes-cli/references/cloud.md +2 -2
  235. package/dist/skills/hyperframes-cli/references/cloudrun.md +1 -1
  236. package/dist/skills/hyperframes-cli/references/conventions.md +17 -0
  237. package/dist/skills/hyperframes-cli/references/feedback.md +14 -0
  238. package/dist/skills/hyperframes-cli/references/init-and-scaffold.md +11 -7
  239. package/dist/skills/hyperframes-cli/references/lambda.md +1 -1
  240. package/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +19 -8
  241. package/dist/skills/hyperframes-cli/references/preview-render.md +8 -2
  242. package/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +8 -0
  243. package/dist/skills/media-use/SKILL.md +47 -91
  244. package/dist/skills/media-use/audio/references/bgm.md +1 -1
  245. package/dist/skills/media-use/audio/references/captions/authoring.md +1 -2
  246. package/dist/skills/media-use/audio/references/captions/motion.md +5 -5
  247. package/dist/skills/media-use/audio/references/tts.md +0 -3
  248. package/dist/skills/media-use/audio/scripts/audio.mjs +5 -6
  249. package/dist/skills/media-use/audio/scripts/carve.mjs +560 -0
  250. package/dist/skills/media-use/audio/scripts/carve.test.mjs +254 -0
  251. package/dist/skills/media-use/audio/scripts/extract-audio-data.py +199 -0
  252. package/dist/skills/media-use/references/local.md +24 -0
  253. package/dist/skills/media-use/references/memory.md +4 -4
  254. package/dist/skills/media-use/references/mixing.md +71 -0
  255. package/dist/skills/media-use/references/operations.md +1 -1
  256. package/dist/skills/media-use/scripts/compatibility.test.mjs +1 -56
  257. package/dist/skills/media-use/scripts/lib/prefs-store.mjs +1 -1
  258. package/dist/skills/media-use/scripts/lib/recipe-store.mjs +1 -1
  259. package/dist/skills/media-use/scripts/prefs.mjs +2 -3
  260. package/dist/skills/media-use/scripts/recipe.mjs +1 -3
  261. package/dist/{skills-WHKMWO2D.js → skills-UHOXOGGF.js} +20 -13
  262. package/dist/{skillsUpdateCheck-XQGZGJJG.js → skillsUpdateCheck-PDZIFUJE.js} +3 -3
  263. package/dist/{snapshot-M4NUUSNU.js → snapshot-PFV7ALLH.js} +462 -100
  264. package/dist/{src-4UYM2K3S.js → src-DCVSEODX.js} +8 -8
  265. package/dist/{src-6MSC62U2.js → src-XK5YIR6L.js} +11 -11
  266. package/dist/{staticProjectServer-ERDTFP45.js → staticProjectServer-4IE4G4JO.js} +17 -17
  267. package/dist/studio/assets/{hyperframes-player-DEncBxR7.js → hyperframes-player-B_skzvYC.js} +1 -1
  268. package/dist/studio/assets/{index-Cc22mgvY.js → index-CgLbvCUo.js} +1 -1
  269. package/dist/studio/assets/{index-BABXr78Q.js → index-Dn5FAk2e.js} +99 -99
  270. package/dist/studio/index.html +1 -1
  271. package/dist/{studio-api-SAKD3VKC.js → studio-api-JMWYU7KF.js} +11 -11
  272. package/dist/{studioServer-IRI7EVOM.js → studioServer-BWLSTGIG.js} +50 -49
  273. package/dist/{telemetry-F4XADVAF.js → telemetry-JCU3AV7W.js} +3 -3
  274. package/dist/templates/_shared/AGENTS.md +14 -19
  275. package/dist/templates/_shared/CLAUDE.md +14 -19
  276. package/dist/templates/blank/index.html +10 -4
  277. package/dist/{timeline-5I444RRE.js → timeline-BCIFQYOM.js} +20 -19
  278. package/dist/{tokens-LRRYM35A.js → tokens-7IXKALMQ.js} +2 -2
  279. package/dist/{transcribe-44XDFNVU.js → transcribe-HW7HGJ4V.js} +19 -19
  280. package/dist/{transcribe-WHYHWAB2.js → transcribe-ZUQD3B32.js} +12 -12
  281. package/dist/{updateCheck-7CPH3CAZ.js → updateCheck-Z6LNEK7B.js} +2 -2
  282. package/dist/{upgrade-WW4GQ2RI.js → upgrade-JYH72JGL.js} +2 -2
  283. package/dist/{urlDownloader-OHLLP45A.js → urlDownloader-WKLFHSUH.js} +8 -8
  284. package/dist/{validate-VNCDH2LW.js → validate-QCC27YYI.js} +23 -23
  285. package/dist/{video-5OHTLL2D.js → video-EZ7ONY6L.js} +9 -9
  286. package/dist/warmCheck.js +36 -36
  287. package/package.json +1 -1
  288. package/dist/audio-KGK44XE4.js +0 -1153
  289. package/dist/chunk-R2SQBPMH.js +0 -3805
  290. package/dist/skills/hyperframes/references/brief-contract.md +0 -108
  291. package/dist/skills/hyperframes/references/brief-format.md +0 -72
  292. package/dist/skills/hyperframes/references/capability-menu.md +0 -47
  293. package/dist/skills/hyperframes/references/frame-worker-core.md +0 -82
  294. package/dist/skills/hyperframes/references/intent-interview.md +0 -73
  295. package/dist/skills/hyperframes/references/pitch-round.md +0 -40
  296. package/dist/skills/hyperframes/references/production-loop.md +0 -26
  297. package/dist/skills/hyperframes/references/review-loop.md +0 -37
  298. package/dist/skills/hyperframes/references/route-briefs.md +0 -11
  299. package/dist/skills/hyperframes/references/routes/embedded-captions.md +0 -11
  300. package/dist/skills/hyperframes/references/routes/faceless-explainer.md +0 -12
  301. package/dist/skills/hyperframes/references/routes/general-video.md +0 -12
  302. package/dist/skills/hyperframes/references/routes/motion-graphics.md +0 -11
  303. package/dist/skills/hyperframes/references/routes/music-to-video.md +0 -12
  304. package/dist/skills/hyperframes/references/routes/pr-to-video.md +0 -28
  305. package/dist/skills/hyperframes/references/routes/product-launch-video.md +0 -13
  306. package/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +0 -9
  307. package/dist/skills/hyperframes/references/routes/slideshow.md +0 -11
  308. package/dist/skills/hyperframes/references/routes/talking-head-recut.md +0 -11
  309. package/dist/skills/hyperframes/references/script-format.md +0 -52
  310. package/dist/skills/hyperframes/references/subagent-dispatch.md +0 -35
  311. package/dist/skills/hyperframes/references/workflow-catalog.md +0 -10
  312. package/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +0 -176
  313. package/dist/skills/media-use/audio/scripts/lib/host-audio.mjs +0 -28
  314. package/dist/skills/media-use/audio/scripts/lib/host-audio.test.mjs +0 -106
@@ -11,13 +11,13 @@ import {
11
11
  } from "./chunk-57GN6KWT.js";
12
12
  import {
13
13
  captureArtifactRevision
14
- } from "./chunk-VDM3FEDP.js";
14
+ } from "./chunk-DQZMJS2P.js";
15
15
  import {
16
16
  loadProducer
17
- } from "./chunk-BCHSTE7U.js";
17
+ } from "./chunk-PEIV2SOG.js";
18
18
  import {
19
19
  trackLintRun
20
- } from "./chunk-Q33P4EAC.js";
20
+ } from "./chunk-EZINX6HH.js";
21
21
  import {
22
22
  beginCheckSnapshots,
23
23
  checkSnapshotDirectory,
@@ -27,6 +27,7 @@ import {
27
27
  import {
28
28
  CONTENT_OVERLAP_HELD_ERROR_MS,
29
29
  DEFAULT_MAX_STATIC_SEC,
30
+ END_CARD_HOLD_SEC,
30
31
  assertionTargets,
31
32
  buildLayoutSampleTimes,
32
33
  buildTransitionSampleTimes,
@@ -45,27 +46,27 @@ import {
45
46
  mergeSampleTimes,
46
47
  parseAt,
47
48
  readMotionSpec
48
- } from "./chunk-QL2PNIXC.js";
49
+ } from "./chunk-5ZMXGNGC.js";
49
50
  import {
50
51
  resolveProject
51
- } from "./chunk-LRGYPXHF.js";
52
+ } from "./chunk-HZ7M2MZA.js";
52
53
  import {
53
54
  recordArtifacts
54
55
  } from "./chunk-U6RXZNZE.js";
55
56
  import {
56
57
  BrowserCleanupError,
57
58
  closeManagedBrowser
58
- } from "./chunk-KN46TGHV.js";
59
+ } from "./chunk-UAJCTEK2.js";
59
60
  import {
60
61
  withRemainingBudget
61
62
  } from "./chunk-EHSBBBR2.js";
62
63
  import {
63
64
  resolveLocalBrowserGpuMode
64
- } from "./chunk-UNNXFKVG.js";
65
+ } from "./chunk-RVZNSKRH.js";
65
66
  import {
66
67
  trackCheckReport,
67
68
  trackCommandFailure
68
- } from "./chunk-JIUTXKWA.js";
69
+ } from "./chunk-77QM6YRQ.js";
69
70
  import {
70
71
  swallowedFlagUsageError
71
72
  } from "./chunk-HTIUNMTP.js";
@@ -85,17 +86,17 @@ import {
85
86
  import {
86
87
  extractMediaMetadata,
87
88
  findHdrAutoPromotion
88
- } from "./chunk-RGXVEYHI.js";
89
+ } from "./chunk-7M7TMM4S.js";
89
90
  import {
90
91
  lintProject,
91
92
  shouldBlockRender
92
- } from "./chunk-ADDHW2FS.js";
93
+ } from "./chunk-Q447CX26.js";
93
94
  import {
94
95
  resolveProjectRelativeSrc
95
96
  } from "./chunk-6BNTGNGD.js";
96
97
  import {
97
98
  withMeta
98
- } from "./chunk-ABZYYUUH.js";
99
+ } from "./chunk-FRLTKTOR.js";
99
100
  import {
100
101
  normalizeErrorMessage
101
102
  } from "./chunk-KNU5COPB.js";
@@ -109,10 +110,20 @@ import { join as join2, resolve } from "path";
109
110
  var CHECK_DEADLINE_MS = 12e4;
110
111
  var SCRIPT_START = "[hyperframes:script:start] ";
111
112
  var SCRIPT_FINISH = "[hyperframes:script:finish] ";
113
+ var PHASE_LABELS = {
114
+ copies: "making video copies",
115
+ launch: "starting Chrome",
116
+ load: "loading the page",
117
+ settle: "waiting for the page to be ready",
118
+ samples: "checking samples",
119
+ overlap: "running the overlap pass",
120
+ crops: "capturing finding crops"
121
+ };
122
+ var BEFORE_DEADLINE = /* @__PURE__ */ new Set(["copies", "launch"]);
112
123
  var CheckDeadlineError = class extends Error {
113
- constructor(sourceFile) {
124
+ constructor(sourceFile, phases = "") {
114
125
  super(
115
- sourceFile === void 0 ? "Check did not finish within its deadline." : `${sourceFile}: its script did not finish within the check deadline.`
126
+ (sourceFile === void 0 ? "Check did not finish within its deadline" : `${sourceFile}: its script did not finish within the check deadline`) + (phases || ".")
116
127
  );
117
128
  this.sourceFile = sourceFile;
118
129
  }
@@ -129,16 +140,38 @@ var CheckDeadline = class {
129
140
  expiry;
130
141
  rejectExpiry;
131
142
  phase = "waiting";
143
+ work;
144
+ spent = /* @__PURE__ */ new Map();
132
145
  constructor() {
133
146
  this.expiry = new Promise((_, reject) => {
134
147
  this.rejectExpiry = reject;
135
148
  });
136
149
  }
150
+ enter = (phase) => {
151
+ if (this.expired) return;
152
+ const now = Date.now();
153
+ if (this.work) this.spend(this.work.phase, now - this.work.since);
154
+ this.work = { phase, since: now };
155
+ this.spend(phase, 0);
156
+ };
157
+ spend(phase, ms) {
158
+ this.spent.set(phase, (this.spent.get(phase) ?? 0) + ms);
159
+ }
160
+ describe() {
161
+ if (!this.work) return "";
162
+ const open = Date.now() - this.work.since;
163
+ const parts = [...this.spent].map(([phase, ms]) => {
164
+ const seconds2 = ((phase === this.work?.phase ? ms + open : ms) / 1e3).toFixed(1);
165
+ return `${PHASE_LABELS[phase]} ${seconds2}${BEFORE_DEADLINE.has(phase) ? " (before the deadline)" : ""}`;
166
+ });
167
+ return ` (${CHECK_DEADLINE_MS / 1e3} s from when Chrome was ready), while ${PHASE_LABELS[this.work.phase]}. Seconds per phase: ${parts.join(", ")}.`;
168
+ }
137
169
  start = () => {
138
170
  if (this.phase !== "waiting") return;
139
171
  this.phase = "started";
172
+ this.enter("load");
140
173
  this.timer = setTimeout(() => {
141
- this.expired = new CheckDeadlineError(this.scripts.at(-1));
174
+ this.expired = new CheckDeadlineError(this.scripts.at(-1), this.describe());
142
175
  this.rejectExpiry(this.expired);
143
176
  this.abort.abort(this.expired);
144
177
  }, CHECK_DEADLINE_MS);
@@ -201,9 +234,378 @@ import { mkdirSync, writeFileSync } from "fs";
201
234
  import { readFile } from "fs/promises";
202
235
  import { join, relative } from "path";
203
236
 
237
+ // src/utils/craftAudit.ts
238
+ var CRAFT_THRESHOLDS = {
239
+ readHeightAt1080: 30,
240
+ readOpacity: 0.5,
241
+ shortLineWords: 2,
242
+ shortLineFloorSec: 0.4,
243
+ holdBaseSec: 0.5,
244
+ holdPerWordSec: 0.3,
245
+ holdFloorFraction: 0.75,
246
+ finalLineFloorSec: 2,
247
+ deadStretchSec: 3,
248
+ endCardSec: END_CARD_HOLD_SEC,
249
+ typeFloorFraction: 0.026,
250
+ typeFloorHoldSec: 0.5,
251
+ silentFilmSec: 15,
252
+ /** One video frame: a line held exactly at its floor measures a hair under it. */
253
+ measureToleranceSec: 1 / 30,
254
+ /** Halvings of a grid step when re-measuring a line's edges (0.125 s → ~8 ms). */
255
+ refineSteps: 4,
256
+ maxRefinedLines: 24
257
+ };
258
+ var T = CRAFT_THRESHOLDS;
259
+ var ZERO_BBOX = { x: 0, y: 0, width: 0, height: 0 };
260
+ var WORD_RUNS = /[\p{L}\p{M}\p{N}%$]+/gu;
261
+ var WORD_SEGMENTER = new Intl.Segmenter("ja", { granularity: "word" });
262
+ function readingWords(text) {
263
+ const runs = text.toLowerCase().normalize("NFC").match(WORD_RUNS) ?? [];
264
+ return runs.reduce(
265
+ (count, run) => count + Math.max(1, [...WORD_SEGMENTER.segment(run)].filter((s) => s.isWordLike).length),
266
+ 0
267
+ );
268
+ }
269
+ function lineTargetSec(words) {
270
+ return T.holdBaseSec + T.holdPerWordSec * words;
271
+ }
272
+ function lineFloorSec(words, finalLine) {
273
+ const floor = words <= T.shortLineWords ? T.shortLineFloorSec : T.holdFloorFraction * lineTargetSec(words);
274
+ return finalLine ? Math.max(floor, T.finalLineFloorSec) : floor;
275
+ }
276
+ async function auditCraft(input, probe) {
277
+ const frames = [...input.frames].sort((a, b) => a.time - b.time);
278
+ const step = sampleStep(frames);
279
+ const findings = [
280
+ ...detectFirstFrameEmpty(frames),
281
+ ...await detectLineUnread(frames, input.duration, input.canvas, probe),
282
+ ...input.stillnessJudgedElsewhere ? [] : detectDeadStretches(frames, input.duration),
283
+ ...detectTextBelowFloor(frames, input.duration, input.canvas),
284
+ ...detectFilmSilent(input.duration, input.soundSources)
285
+ ].sort((a, b) => a.time - b.time);
286
+ return { enabled: true, step, samples: frames.length, findings };
287
+ }
288
+ function sampleStep(frames) {
289
+ const gaps = frames.slice(1).map((frame, index) => frame.time - (frames[index]?.time ?? frame.time)).filter((gap) => gap > 0).sort((a, b) => a - b);
290
+ return gaps[Math.floor(gaps.length / 2)] ?? 0;
291
+ }
292
+ function seconds(value) {
293
+ return `${value.toFixed(2)} s`;
294
+ }
295
+ function filmFinding(code, time, message, extra = {}) {
296
+ return {
297
+ code,
298
+ severity: "warning",
299
+ message,
300
+ selector: "[data-composition-id]",
301
+ dataAttributes: {},
302
+ sourceFile: "index.html",
303
+ bbox: ZERO_BBOX,
304
+ time,
305
+ ...extra
306
+ };
307
+ }
308
+ function detectFirstFrameEmpty(frames) {
309
+ const first = frames[0];
310
+ if (!first || first.time > 1e-3 || first.painted) return [];
311
+ return [
312
+ filmFinding(
313
+ "first_frame_empty",
314
+ 0,
315
+ "Frame 0 shows only the background, and the first frame is the thumbnail on social players: have the title or key image already on screen at 0 s instead of entering from nothing; see references/review.md."
316
+ )
317
+ ];
318
+ }
319
+ function detectFilmSilent(duration, soundSources) {
320
+ if (soundSources === null || soundSources > 0 || duration <= T.silentFilmSec) return [];
321
+ return [
322
+ filmFinding(
323
+ "film_silent",
324
+ 0,
325
+ `This ${Math.round(duration)} s film has no sound source (no <audio>, no <video> with sound): add a music bed and sounds on the visible actions unless the person asked for silence; see references/sound.md.`
326
+ )
327
+ ];
328
+ }
329
+ function detectDeadStretches(frames, duration) {
330
+ const endCardStart = duration - T.endCardSec;
331
+ const findings = [];
332
+ let start = null;
333
+ let end = 0;
334
+ const flush = () => {
335
+ if (start !== null && end - start > T.deadStretchSec) findings.push(deadStretch(start, end));
336
+ start = null;
337
+ };
338
+ for (let index = 1; index < frames.length; index += 1) {
339
+ const before = frames[index - 1];
340
+ const after = frames[index];
341
+ if (!before || !after) continue;
342
+ const still = before.signature !== "" && before.signature === after.signature && !before.held && !after.held && before.time < endCardStart;
343
+ if (!still) {
344
+ flush();
345
+ continue;
346
+ }
347
+ start ??= before.time;
348
+ end = Math.min(after.time, endCardStart);
349
+ }
350
+ flush();
351
+ return findings;
352
+ }
353
+ function deadStretch(start, end) {
354
+ const length = end - start;
355
+ return filmFinding(
356
+ "dead_stretch",
357
+ start,
358
+ `Nothing on screen changes for ${seconds(length)} (${start.toFixed(2)}\u2013${end.toFixed(2)} s): start the next move within ${T.deadStretchSec} s, or put data-hold on the element whose stillness is deliberate; see references/motion.md.`,
359
+ { seconds: round(length), floorSeconds: T.deadStretchSec, until: round(end) }
360
+ );
361
+ }
362
+ function readableBlocks(frame, readHeight) {
363
+ const blocks = /* @__PURE__ */ new Map();
364
+ for (const part of frame.parts) {
365
+ if (part.captions || part.opacity < T.readOpacity) continue;
366
+ const rect = {
367
+ left: part.rect.left,
368
+ top: part.rect.top,
369
+ right: part.rect.left + part.rect.width,
370
+ bottom: part.rect.top + part.rect.height
371
+ };
372
+ const block = blocks.get(part.block);
373
+ if (!block) {
374
+ blocks.set(part.block, {
375
+ text: part.text,
376
+ rect,
377
+ selector: part.blockSelector,
378
+ sourceFile: part.sourceFile
379
+ });
380
+ continue;
381
+ }
382
+ block.text = `${block.text} ${part.text}`;
383
+ block.rect = {
384
+ left: Math.min(block.rect.left, rect.left),
385
+ top: Math.min(block.rect.top, rect.top),
386
+ right: Math.max(block.rect.right, rect.right),
387
+ bottom: Math.max(block.rect.bottom, rect.bottom)
388
+ };
389
+ }
390
+ for (const [key, block] of blocks) {
391
+ if (block.rect.bottom - block.rect.top < readHeight) blocks.delete(key);
392
+ }
393
+ return blocks;
394
+ }
395
+ function trackBlocks(frames, readHeight) {
396
+ const tracks = /* @__PURE__ */ new Map();
397
+ frames.forEach((frame, index) => {
398
+ for (const [key, block] of readableBlocks(frame, readHeight)) {
399
+ const track = tracks.get(key) ?? {
400
+ key,
401
+ selector: block.selector,
402
+ sourceFile: block.sourceFile,
403
+ seen: /* @__PURE__ */ new Map()
404
+ };
405
+ track.seen.set(index, { text: block.text, rect: block.rect });
406
+ tracks.set(key, track);
407
+ }
408
+ });
409
+ return [...tracks.values()];
410
+ }
411
+ function indexRuns(indices) {
412
+ const sorted = [...indices].sort((a, b) => a - b);
413
+ const runs = [];
414
+ for (const index of sorted) {
415
+ const last = runs[runs.length - 1];
416
+ if (last && index === last[1] + 1) last[1] = index;
417
+ else runs.push([index, index]);
418
+ }
419
+ return runs;
420
+ }
421
+ function windowSeconds(window2) {
422
+ return (window2.endIn + window2.endOut) / 2 - (window2.startOut + window2.startIn) / 2;
423
+ }
424
+ function runWindow(frames, [first, last], duration) {
425
+ const timeAt = (index) => frames[Math.min(Math.max(index, 0), frames.length - 1)]?.time ?? 0;
426
+ const reachesEnd = last === frames.length - 1;
427
+ return {
428
+ startOut: timeAt(first - 1),
429
+ startIn: timeAt(first),
430
+ endIn: reachesEnd ? duration : timeAt(last),
431
+ endOut: reachesEnd ? duration : timeAt(last + 1)
432
+ };
433
+ }
434
+ function lineCandidates(frames, duration, canvas) {
435
+ const readHeight = T.readHeightAt1080 * (Math.min(canvas.width, canvas.height) / 1080);
436
+ const tracks = trackBlocks(frames, readHeight);
437
+ const lastEnd = (track) => Math.max(...track.seen.keys());
438
+ const latest = Math.max(-1, ...tracks.map(lastEnd));
439
+ const candidates = [];
440
+ for (const track of tracks) {
441
+ const runs = indexRuns([...track.seen.keys()]);
442
+ const finalLine = lastEnd(track) === latest;
443
+ const windows = runs.map((run2) => runWindow(frames, run2, duration));
444
+ const chosen = finalLine ? windows.length - 1 : windows.reduce((best, window3, index) => {
445
+ const bestWindow = windows[best];
446
+ return bestWindow && windowSeconds(window3) > windowSeconds(bestWindow) ? index : best;
447
+ }, 0);
448
+ const window2 = windows[chosen];
449
+ const run = runs[chosen];
450
+ if (!window2 || !run) continue;
451
+ const texts = [...track.seen.values()].map((seen) => seen.text);
452
+ const text = texts.reduce(
453
+ (longest, next) => readingWords(next) > readingWords(longest) ? next : longest
454
+ );
455
+ const words = readingWords(text);
456
+ if (words === 0) continue;
457
+ const floor = lineFloorSec(words, finalLine);
458
+ if (window2.endIn - window2.startIn >= floor) continue;
459
+ candidates.push({ track, words, text, finalLine, floor, window: window2, firstIndex: run[0] });
460
+ }
461
+ return candidates;
462
+ }
463
+ async function refineWindow(candidate, probe, canvas) {
464
+ const readHeight = T.readHeightAt1080 * (Math.min(canvas.width, canvas.height) / 1080);
465
+ const visibleAt = async (time) => readableBlocks(await probe(time), readHeight).has(candidate.track.key);
466
+ const window2 = { ...candidate.window };
467
+ for (let step = 0; step < T.refineSteps; step += 1) {
468
+ if (window2.startIn > window2.startOut) {
469
+ const mid = (window2.startOut + window2.startIn) / 2;
470
+ if (await visibleAt(mid)) window2.startIn = mid;
471
+ else window2.startOut = mid;
472
+ }
473
+ if (window2.endOut > window2.endIn) {
474
+ const mid = (window2.endIn + window2.endOut) / 2;
475
+ if (await visibleAt(mid)) window2.endIn = mid;
476
+ else window2.endOut = mid;
477
+ }
478
+ }
479
+ return window2;
480
+ }
481
+ async function detectLineUnread(frames, duration, canvas, probe) {
482
+ const findings = [];
483
+ const candidates = lineCandidates(frames, duration, canvas);
484
+ for (const [index, candidate] of candidates.entries()) {
485
+ const window2 = probe && index < T.maxRefinedLines ? await refineWindow(candidate, probe, canvas) : candidate.window;
486
+ const held = windowSeconds(window2);
487
+ if (held >= candidate.floor - T.measureToleranceSec) continue;
488
+ const error = Math.max(window2.startIn - window2.startOut, window2.endOut - window2.endIn) / 2;
489
+ findings.push(lineUnreadFinding(candidate, window2, held, error));
490
+ }
491
+ return findings;
492
+ }
493
+ function lineUnreadFinding(candidate, window2, held, error) {
494
+ const { track, words, text, finalLine, floor } = candidate;
495
+ const quoted = quote(text, 60);
496
+ const wordLabel = `${words} word${words === 1 ? "" : "s"}`;
497
+ const measured = `${seconds(held)} (\xB1${Math.max(0.01, error).toFixed(2)} s)`;
498
+ const target = lineTargetSec(words);
499
+ const message = finalLine ? `The film's last line ${quoted} (${wordLabel}) is on screen ${measured}, under the ${seconds(floor)} a closing line needs: hold it about 0.5 s + 0.3 s a word and at least 2 s before the film ends; see references/motion.md.` : `${quoted} (${wordLabel}) is on screen ${measured}, under its ${seconds(floor)} floor: hold it about 0.5 s + 0.3 s a word (${seconds(target)} here) before it leaves or changes; see references/motion.md.`;
500
+ const firstSeen = track.seen.get(candidate.firstIndex);
501
+ const rect = firstSeen?.rect;
502
+ return {
503
+ code: "line_unread",
504
+ severity: "warning",
505
+ message,
506
+ text,
507
+ selector: track.selector,
508
+ dataAttributes: {},
509
+ sourceFile: track.sourceFile,
510
+ bbox: rect ? { x: rect.left, y: rect.top, width: rect.right - rect.left, height: rect.bottom - rect.top } : ZERO_BBOX,
511
+ time: round(window2.startIn),
512
+ words,
513
+ seconds: round(held),
514
+ floorSeconds: round(floor)
515
+ };
516
+ }
517
+ function typeFloorPx(canvas) {
518
+ return Math.round(T.typeFloorFraction * Math.min(canvas.width, canvas.height));
519
+ }
520
+ function detectTextBelowFloor(frames, duration, canvas) {
521
+ const floorPx = typeFloorPx(canvas);
522
+ const step = sampleStep(frames);
523
+ const sightings = /* @__PURE__ */ new Map();
524
+ frames.forEach((frame, index) => {
525
+ for (const part of frame.parts) {
526
+ if (part.captions || part.opacity < T.readOpacity) continue;
527
+ if (part.fontPx >= floorPx - 0.5 || readingWords(part.text) === 0) continue;
528
+ const seen = sightings.get(part.key) ?? /* @__PURE__ */ new Map();
529
+ seen.set(index, part);
530
+ sightings.set(part.key, seen);
531
+ }
532
+ });
533
+ const small = [];
534
+ for (const seen of sightings.values()) {
535
+ const [first, last] = longestRun(indexRuns([...seen.keys()]));
536
+ const start = frames[first]?.time ?? 0;
537
+ const end = last === frames.length - 1 ? duration : (frames[last]?.time ?? start) + step;
538
+ if (end - start < T.typeFloorHoldSec) continue;
539
+ const parts = [...seen.values()];
540
+ const part = parts[0];
541
+ if (!part) continue;
542
+ small.push({
543
+ selector: part.selector,
544
+ sourceFile: part.sourceFile,
545
+ text: part.text,
546
+ fontPx: Math.min(...parts.map((entry) => entry.fontPx)),
547
+ seconds: end - start,
548
+ time: start,
549
+ bbox: {
550
+ x: part.rect.left,
551
+ y: part.rect.top,
552
+ width: part.rect.width,
553
+ height: part.rect.height
554
+ }
555
+ });
556
+ }
557
+ const shortSide = Math.min(canvas.width, canvas.height);
558
+ return groupBySourceFile(small).map((group) => smallTextFinding(group, floorPx, shortSide));
559
+ }
560
+ function longestRun(runs) {
561
+ return runs.reduce((best, run) => run[1] - run[0] > best[1] - best[0] ? run : best, [0, -1]);
562
+ }
563
+ function groupBySourceFile(small) {
564
+ const groups = /* @__PURE__ */ new Map();
565
+ for (const entry of small)
566
+ groups.set(entry.sourceFile, [...groups.get(entry.sourceFile) ?? [], entry]);
567
+ return [...groups.values()].map(
568
+ (group) => group.sort((a, b) => a.fontPx - b.fontPx || a.time - b.time)
569
+ );
570
+ }
571
+ function quote(text, max) {
572
+ return `"${text.length > max ? `${text.slice(0, max - 3)}...` : text}"`;
573
+ }
574
+ function smallTextFinding(group, floorPx, shortSide) {
575
+ const [smallest] = group;
576
+ if (!smallest) throw new Error("text_below_floor group is empty");
577
+ const subject = group.length === 1 ? `${quote(smallest.text, 48)} renders at ${Math.round(smallest.fontPx)} px for ${seconds(smallest.seconds)}` : `${group.length} text elements stay under it for 0.5 s or more, the smallest ${quote(smallest.text, 40)} at ${Math.round(smallest.fontPx)} px`;
578
+ const byTime = [...group].sort((a, b) => a.time - b.time);
579
+ return {
580
+ code: "text_below_floor",
581
+ severity: "warning",
582
+ message: `Type floor is ${floorPx} px (2.6% of the ${shortSide} px short side, what a phone can read) and ${subject}: set reading text to at least ${floorPx} px, or put data-layout-ignore on text that is texture rather than reading; see references/look.md.`,
583
+ text: smallest.text,
584
+ selector: smallest.selector,
585
+ dataAttributes: {},
586
+ sourceFile: smallest.sourceFile,
587
+ bbox: smallest.bbox,
588
+ time: round(smallest.time),
589
+ times: byTime.map((entry) => round(entry.time)),
590
+ fontPx: round(smallest.fontPx),
591
+ floorPx,
592
+ seconds: round(smallest.seconds),
593
+ elements: group.map((entry) => ({
594
+ selector: entry.selector,
595
+ text: entry.text,
596
+ fontPx: round(entry.fontPx),
597
+ time: round(entry.time),
598
+ seconds: round(entry.seconds)
599
+ }))
600
+ };
601
+ }
602
+ function round(value) {
603
+ return Math.round(value * 1e3) / 1e3;
604
+ }
605
+
204
606
  // src/utils/hdrPromotion.ts
205
607
  async function bundleProjectHtml(projectDir) {
206
- const { bundleToSingleHtml } = await import("./compiler-Q3N6QXMT.js");
608
+ const { bundleToSingleHtml } = await import("./compiler-2EKSMC3I.js");
207
609
  return bundleToSingleHtml(projectDir);
208
610
  }
209
611
  async function collectBundledRenderMedia(html) {
@@ -279,7 +681,7 @@ function parseColorRGBA(color) {
279
681
  // src/utils/checkPipeline.ts
280
682
  var MOTION_FPS = 20;
281
683
  var MOTION_MAX_SAMPLES = 300;
282
- var ZERO_BBOX = { x: 0, y: 0, width: 0, height: 0 };
684
+ var ZERO_BBOX2 = { x: 0, y: 0, width: 0, height: 0 };
283
685
  var FRAME_BREACH_FLOOR_PX = 120;
284
686
  var FRAME_BREACH_FLOOR_FRACTION = 0.06;
285
687
  var DEFAULT_CHECK_OPTIONS = {
@@ -518,7 +920,8 @@ function emptyGridSamples() {
518
920
  contrastMs: 0,
519
921
  layoutStateSignatures: [],
520
922
  rotationSamples: [],
521
- indicatorFrames: []
923
+ indicatorFrames: [],
924
+ craftFrames: []
522
925
  };
523
926
  }
524
927
  function appendGridSamples(into, from) {
@@ -530,6 +933,7 @@ function appendGridSamples(into, from) {
530
933
  into.layoutStateSignatures.push(...from.layoutStateSignatures);
531
934
  into.rotationSamples.push(...from.rotationSamples);
532
935
  into.indicatorFrames.push(...from.indicatorFrames);
936
+ into.craftFrames.push(...from.craftFrames);
533
937
  }
534
938
  async function collectSampleAt(driver, options, grid, motion, sets, time) {
535
939
  const collected = emptyGridSamples();
@@ -561,7 +965,7 @@ async function collectSampleAt(driver, options, grid, motion, sets, time) {
561
965
  await collectContrastAt(driver, options, time, issuesAtTime, collected);
562
966
  return collected;
563
967
  }
564
- async function collectGridSamples(driver, options, grid, motion, helpers) {
968
+ async function collectGridSamples(driver, options, grid, motion, helpers, enter) {
565
969
  const geometryEnabled = grid.captionSamples.length > 0 || grid.frameSamples.length > 0;
566
970
  const sets = {
567
971
  layout: new Set(grid.layoutSamples),
@@ -605,9 +1009,20 @@ async function collectGridSamples(driver, options, grid, motion, helpers) {
605
1009
  driver.markSamples?.("end");
606
1010
  const collected = emptyGridSamples();
607
1011
  for (const samples of perTime) appendGridSamples(collected, samples);
608
- await collectMotionOverlapSamples(driver, grid, collected, options.range);
1012
+ enter("overlap");
1013
+ await collectMotionOverlapSamples(
1014
+ driver,
1015
+ grid,
1016
+ collected,
1017
+ options.range,
1018
+ craftEnabled(driver, options)
1019
+ );
1020
+ enter("samples");
609
1021
  return collected;
610
1022
  }
1023
+ function craftEnabled(driver, options) {
1024
+ return !options.range && typeof driver.collectCraftFrame === "function";
1025
+ }
611
1026
  async function collectContrastAt(driver, options, time, issuesAtTime, collected) {
612
1027
  const contrastStart = Date.now();
613
1028
  const capture = options.snapshots ? await driver.collectContrast(time, annotationBoxesFrom(issuesAtTime)) : await driver.collectContrast(time);
@@ -683,9 +1098,16 @@ async function denseOverlapTimes(driver, grid, range) {
683
1098
  const overlapTimes = buildOverlapSampleTimes(range ? range[1] - range[0] : grid.duration, edges);
684
1099
  return range ? mergeSampleTimes(overlapTimes.map((time) => time + range[0])) : overlapTimes;
685
1100
  }
686
- async function collectMotionOverlapSamples(driver, grid, collected, range) {
1101
+ async function collectMotionOverlapSamples(driver, grid, collected, range, craft) {
687
1102
  const baseTimes = new Set(grid.layoutSamples);
688
1103
  const shiftedTimes = await denseOverlapTimes(driver, grid, range);
1104
+ if (craft) {
1105
+ for (const time of buildCraftSampleTimes(grid.duration)) {
1106
+ if (time >= grid.duration) continue;
1107
+ await driver.seekGeometry(time);
1108
+ collected.craftFrames.push(...await collectCraftFrame(driver, time));
1109
+ }
1110
+ }
689
1111
  const probeHold = holdProber(driver, collected, range ? range[1] : grid.duration);
690
1112
  const gridIssues = await driver.collectOverlapGrid(shiftedTimes.filter((t) => !baseTimes.has(t)));
691
1113
  let sample = 0;
@@ -696,6 +1118,22 @@ async function collectMotionOverlapSamples(driver, grid, collected, range) {
696
1118
  await probeHold(time, shiftedTimes[index + 1] ?? Number.POSITIVE_INFINITY, issues);
697
1119
  }
698
1120
  }
1121
+ var CRAFT_SAMPLE_FPS = 8;
1122
+ var CRAFT_MAX_SAMPLES = 600;
1123
+ function buildCraftSampleTimes(duration) {
1124
+ if (!Number.isFinite(duration) || duration <= 0) return [];
1125
+ const count = Math.min(
1126
+ CRAFT_MAX_SAMPLES,
1127
+ Math.max(2, Math.ceil(duration * CRAFT_SAMPLE_FPS) + 1)
1128
+ );
1129
+ const step = duration / (count - 1);
1130
+ return mergeSampleTimes(
1131
+ Array.from({ length: count }, (_, index) => Math.round(index * step * 1e3) / 1e3)
1132
+ );
1133
+ }
1134
+ async function collectCraftFrame(driver, time) {
1135
+ return driver.collectCraftFrame ? [await driver.collectCraftFrame(time)] : [];
1136
+ }
699
1137
  var SWEEP_STATIC_MIN_DURATION_SEC = 3;
700
1138
  var ZERO_LAYOUT_RECT = {
701
1139
  left: 0,
@@ -797,7 +1235,7 @@ function sweepStaticIssue(kind) {
797
1235
  selector: "[data-composition-id]",
798
1236
  dataAttributes: {},
799
1237
  sourceFile: "index.html",
800
- bbox: ZERO_BBOX,
1238
+ bbox: ZERO_BBOX2,
801
1239
  rect: ZERO_LAYOUT_RECT,
802
1240
  message: SWEEP_STATIC_MESSAGES[kind],
803
1241
  fixHint: kind === "error" ? "An animation on the page never moved under seek. Build it on the paused GSAP timeline registered in `window.__timelines[compositionId]`, or as a CSS animation, so the seek drives it." : STILL_FIX_HINT
@@ -1131,7 +1569,17 @@ function detectOffPivotRotation(frames) {
1131
1569
  function annotationBoxesFrom(issues) {
1132
1570
  return issues.filter((issue) => issue.severity === "error" && issue.bbox.width > 0 && issue.bbox.height > 0).map((issue, index) => ({ label: `${index + 1} ${issue.code}`, bbox: issue.bbox }));
1133
1571
  }
1134
- async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([])) {
1572
+ function wholeCompositionKeepsMoving(assertions) {
1573
+ return assertions.some(
1574
+ (assertion) => assertion.kind === "keepsMoving" && assertion.withinSelector === void 0
1575
+ );
1576
+ }
1577
+ function disabledCraft() {
1578
+ return { enabled: false, step: 0, samples: 0, findings: [] };
1579
+ }
1580
+ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([]), enter = () => {
1581
+ }) {
1582
+ enter("samples");
1135
1583
  await driver.initialize(options.contrast);
1136
1584
  const grid = await buildSampleGrid(driver, options);
1137
1585
  const plan = await planMotionSampling(
@@ -1140,28 +1588,24 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1140
1588
  grid.duration
1141
1589
  );
1142
1590
  const seekLoopStart = Date.now();
1143
- const collected = await collectGridSamples(driver, options, grid, plan, helpers);
1591
+ const collected = await collectGridSamples(driver, options, grid, plan, helpers, enter);
1144
1592
  const seekLoopMs = Date.now() - seekLoopStart;
1145
1593
  let motionIssues = plan.preflightIssues;
1146
1594
  if (motion.kind === "valid" && plan.assertions.length > 0 && collected.motionFrames.length > 0) {
1147
1595
  const canvas = await driver.getCanvas();
1148
- let evaluated = evaluateMotion(collected.motionFrames, plan.assertions, canvas);
1596
+ let evaluated = evaluateMotion(collected.motionFrames, plan.assertions, canvas, grid.duration);
1149
1597
  if (evaluated.some((issue) => issue.code === "motion_frozen")) {
1150
1598
  const frames = await withFrameMotion(driver, collected.motionFrames, plan.assertions);
1151
- evaluated = evaluateMotion(frames, plan.assertions, canvas);
1599
+ evaluated = evaluateMotion(frames, plan.assertions, canvas, grid.duration);
1152
1600
  }
1153
1601
  motionIssues = [...motionIssues, ...await driver.anchorMotionIssues(evaluated)];
1154
1602
  }
1155
1603
  const userPicked = new Set(grid.userPickedSamples);
1604
+ const noTimeline = await driver.hasNoTimelineDeclaration();
1156
1605
  const sweepSamples = collected.layoutStateSignatures.filter(
1157
1606
  (sample) => !userPicked.has(sample.time)
1158
1607
  );
1159
- const sweepVerdict = options.range ? [] : detectSweepStatic(
1160
- grid.duration,
1161
- sweepSamples,
1162
- motionIssues,
1163
- await driver.hasNoTimelineDeclaration()
1164
- );
1608
+ const sweepVerdict = options.range ? [] : detectSweepStatic(grid.duration, sweepSamples, motionIssues, noTimeline);
1165
1609
  const sweepFindings = sweepVerdict.length > 0 && await framesMoved(
1166
1610
  driver,
1167
1611
  sweepSamples.map((sample) => sample.time)
@@ -1172,6 +1616,20 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1172
1616
  );
1173
1617
  const offPivotFindings = detectOffPivotRotation(collected.indicatorFrames);
1174
1618
  const contrast = buildContrastResults(collected.contrastEntries);
1619
+ const craft = craftEnabled(driver, options) ? await auditCraft(
1620
+ {
1621
+ frames: collected.craftFrames,
1622
+ duration: grid.duration,
1623
+ canvas: await driver.getCanvas(),
1624
+ soundSources: driver.collectCraftFilm ? (await driver.collectCraftFilm()).soundSources : null,
1625
+ stillnessJudgedElsewhere: noTimeline || sweepFindings.length > 0 || wholeCompositionKeepsMoving(plan.assertions)
1626
+ },
1627
+ async (time) => {
1628
+ await driver.seekGeometry(time);
1629
+ if (!driver.collectCraftFrame) throw new Error("craft sampling unavailable");
1630
+ return driver.collectCraftFrame(time);
1631
+ }
1632
+ ) : disabledCraft();
1175
1633
  if (options.components?.length) {
1176
1634
  if (!driver.matchComponents)
1177
1635
  throw new Error("Component filtering unavailable in this check driver");
@@ -1181,7 +1639,8 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1181
1639
  ...rotationFindings,
1182
1640
  ...offPivotFindings,
1183
1641
  ...motionIssues,
1184
- ...contrast.findings
1642
+ ...contrast.findings,
1643
+ ...craft.findings
1185
1644
  ];
1186
1645
  const matches = await driver.matchComponents(options.components, findings);
1187
1646
  findings.forEach((finding, i) => {
@@ -1206,6 +1665,7 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1206
1665
  contrastFindings: contrast.findings,
1207
1666
  contrastChecked: collected.contrastEntries.length,
1208
1667
  contrastPassed: contrast.passed,
1668
+ craft,
1209
1669
  screenshots: collected.screenshots,
1210
1670
  timings: { launchSettleMs: 0, seekLoopMs, contrastMs: collected.contrastMs },
1211
1671
  skipped: false
@@ -1332,6 +1792,7 @@ async function withFindingCrops(dependencies, project, options, report, deadline
1332
1792
  const cropRequests = selectFindingCropRequests(report);
1333
1793
  if (cropRequests.length === 0) return report;
1334
1794
  try {
1795
+ deadline.enter("crops");
1335
1796
  const findingFiles = await deadline.run(
1336
1797
  () => dependencies.captureFindingCrops(project, options, cropRequests, deadline)
1337
1798
  );
@@ -1443,7 +1904,7 @@ function buildLintSection(result) {
1443
1904
  selector: finding.selector ?? (finding.elementId ? `#${finding.elementId}` : "[data-composition-id]"),
1444
1905
  dataAttributes: {},
1445
1906
  sourceFile: finding.file ?? file,
1446
- bbox: ZERO_BBOX,
1907
+ bbox: ZERO_BBOX2,
1447
1908
  time: 0,
1448
1909
  fixHint: finding.fixHint
1449
1910
  }))
@@ -1458,10 +1919,12 @@ function buildReport(options, lint, browser, motion, extraMotionFindings, snapsh
1458
1919
  const runtime = section(browser.runtimeFindings);
1459
1920
  const motionSection = section(motionFindings);
1460
1921
  const contrastSection = section(browser.contrastFindings);
1461
- const warningCount = lint.warningCount + runtime.warningCount + layout.warningCount + motionSection.warningCount + contrastSection.warningCount;
1462
- const errorCount = lint.errorCount + runtime.errorCount + layout.errorCount + motionSection.errorCount + contrastSection.errorCount;
1922
+ const craftSection = section(browser.craft.findings);
1923
+ const warningCount = lint.warningCount + runtime.warningCount + layout.warningCount + motionSection.warningCount + contrastSection.warningCount + craftSection.warningCount;
1924
+ const errorCount = lint.errorCount + runtime.errorCount + layout.errorCount + motionSection.errorCount + contrastSection.errorCount + craftSection.errorCount;
1925
+ const strictWarningCount = warningCount - craftSection.warningCount;
1463
1926
  const report = {
1464
- ok: errorCount === 0 && (!options.strict || warningCount === 0),
1927
+ ok: errorCount === 0 && (!options.strict || strictWarningCount === 0),
1465
1928
  strict: options.strict,
1466
1929
  browserSkipped: browser.skipped,
1467
1930
  lint,
@@ -1480,6 +1943,12 @@ function buildReport(options, lint, browser, motion, extraMotionFindings, snapsh
1480
1943
  checked: browser.contrastChecked,
1481
1944
  passed: browser.contrastPassed
1482
1945
  },
1946
+ craft: {
1947
+ ...craftSection,
1948
+ enabled: browser.craft.enabled,
1949
+ step: browser.craft.step,
1950
+ samples: browser.craft.samples
1951
+ },
1483
1952
  hdr: { autoPromotion: hdrPromotion, inspection: hdrInspection },
1484
1953
  snapshots: {
1485
1954
  enabled: options.snapshots,
@@ -1504,6 +1973,7 @@ function buildReport(options, lint, browser, motion, extraMotionFindings, snapsh
1504
1973
  motionWarnings: motionSection.warningCount,
1505
1974
  contrastErrors: contrastSection.errorCount,
1506
1975
  contrastWarnings: contrastSection.warningCount,
1976
+ craftWarnings: craftSection.warningCount,
1507
1977
  launchSettleMs: browser.timings.launchSettleMs,
1508
1978
  seekLoopMs: browser.timings.seekLoopMs,
1509
1979
  contrastMs: browser.timings.contrastMs,
@@ -1525,11 +1995,11 @@ function filterComponentReport(report, options) {
1525
1995
  notes: [
1526
1996
  "Static lint and unscoped runtime failures remain project-wide.",
1527
1997
  ...options.range ? [
1528
- "Whole-timeline motion assertions and frozen-sweep detection are skipped for range checks."
1998
+ "Whole-timeline motion assertions, frozen-sweep detection and craft warnings are skipped for range checks."
1529
1999
  ] : []
1530
2000
  ]
1531
2001
  };
1532
- for (const group of [report.layout, report.motion, report.contrast]) {
2002
+ for (const group of [report.layout, report.motion, report.contrast, report.craft]) {
1533
2003
  const before = group.findings.length;
1534
2004
  group.findings = group.findings.filter((f) => f.componentMatch !== false);
1535
2005
  report.scope.hiddenFindings += before - group.findings.length;
@@ -1612,6 +2082,7 @@ function emptyBrowserResult() {
1612
2082
  contrastFindings: [],
1613
2083
  contrastChecked: 0,
1614
2084
  contrastPassed: 0,
2085
+ craft: disabledCraft(),
1615
2086
  screenshots: [],
1616
2087
  timings: { launchSettleMs: 0, seekLoopMs: 0, contrastMs: 0 },
1617
2088
  skipped: true
@@ -1633,7 +2104,7 @@ function findingAtRoot(code, severity, message, sourceFile) {
1633
2104
  selector: "[data-composition-id]",
1634
2105
  dataAttributes: {},
1635
2106
  sourceFile,
1636
- bbox: ZERO_BBOX,
2107
+ bbox: ZERO_BBOX2,
1637
2108
  time: 0
1638
2109
  };
1639
2110
  }
@@ -1662,7 +2133,7 @@ function resolveMotionSpec(projectDir) {
1662
2133
  };
1663
2134
  }
1664
2135
  async function runBrowserCheck(project, options, motion, deadline, prelaunched) {
1665
- const module = await import("./checkBrowser-FNINXBMZ.js");
2136
+ const module = await import("./checkBrowser-X7G6YNR7.js");
1666
2137
  return module.runBrowserCheck(project, options, motion, runAuditGrid, deadline, prelaunched);
1667
2138
  }
1668
2139
  var adoptedBrowser;
@@ -1676,7 +2147,7 @@ async function prelaunchBrowser(project, options) {
1676
2147
  if (adopted) return adopted;
1677
2148
  const html = await readFile(project.indexPath, "utf8").catch(() => void 0);
1678
2149
  if (html === void 0) return void 0;
1679
- const { prelaunchCompositionBrowser } = await import("./captureCompositionFrame-4236FVWJ.js");
2150
+ const { prelaunchCompositionBrowser } = await import("./captureCompositionFrame-5FVLAETA.js");
1680
2151
  return prelaunchCompositionBrowser(html, options.browserGpuMode);
1681
2152
  }
1682
2153
  async function writeSnapshot(projectDir, index, time, pngBase64) {
@@ -1688,7 +2159,7 @@ async function writeSnapshot(projectDir, index, time, pngBase64) {
1688
2159
  return relative(projectDir, path);
1689
2160
  }
1690
2161
  async function captureFindingCrops(project, options, requests, deadline) {
1691
- const module = await import("./checkBrowser-FNINXBMZ.js");
2162
+ const module = await import("./checkBrowser-X7G6YNR7.js");
1692
2163
  return module.captureFindingCrops(project, options, requests, deadline);
1693
2164
  }
1694
2165
  var DEFAULT_DEPENDENCIES2 = {
@@ -2134,6 +2605,7 @@ function printHumanReport(report) {
2134
2605
  printLayoutSection("Layout", report.layout);
2135
2606
  printSection("Motion", report.motion);
2136
2607
  printContrastSection(report);
2608
+ printCraftSection(report);
2137
2609
  printSnapshotSection(report);
2138
2610
  console.log();
2139
2611
  const label = report.ok ? c.success("Check passed") : c.error("Check failed");
@@ -2192,6 +2664,16 @@ function printContrastSection(report) {
2192
2664
  }
2193
2665
  printCounts(section2);
2194
2666
  }
2667
+ function printCraftSection(report) {
2668
+ const section2 = report.craft;
2669
+ if (!section2.enabled) {
2670
+ console.log();
2671
+ console.log(c.bold("Craft"));
2672
+ console.log(` ${c.dim("\u25C7")} skipped`);
2673
+ return;
2674
+ }
2675
+ printSection("Craft", section2);
2676
+ }
2195
2677
  function printSnapshotSection(report) {
2196
2678
  console.log();
2197
2679
  console.log(c.bold("Snapshots"));