hyperframes 0.8.184 → 0.8.185

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 (309) hide show
  1. package/dist/{add-5ZTD3MUZ.js → add-ODTNPRGG.js} +14 -14
  2. package/dist/{agentPromptGenerator-VIIPZCJ3.js → agentPromptGenerator-KYO5MKTW.js} +1 -1
  3. package/dist/{animatedGifPrep-AGASIWVA.js → animatedGifPrep-PEP5GWOJ.js} +9 -9
  4. package/dist/api.js +17 -17
  5. package/dist/{asset-LSTEMPIB.js → asset-EZG42XPA.js} +2 -2
  6. package/dist/{assetCataloger-BKBMNL3A.js → assetCataloger-OHAJFCA7.js} +9 -9
  7. package/dist/{audio-KGK44XE4.js → audio-65R4T74I.js} +16 -15
  8. package/dist/{auth-MJWKYK77.js → auth-VP2SIZFN.js} +1 -1
  9. package/dist/{autoUpdate-2GGDKYR2.js → autoUpdate-RVSUX4SS.js} +2 -2
  10. package/dist/{backgroundChecks-7GRX5VQY.js → backgroundChecks-LEHK74NS.js} +3 -3
  11. package/dist/backgroundChecksWorker.js +3 -3
  12. package/dist/{batchRender-BCV2LELR.js → batchRender-3X6CL7PK.js} +5 -5
  13. package/dist/{beats-7BCFRBAL.js → beats-66VPQLSC.js} +6 -6
  14. package/dist/{benchmark-2R6CN5MQ.js → benchmark-PBJVTOJP.js} +10 -10
  15. package/dist/{browser-6AFGOI7G.js → browser-TPL5MWGC.js} +3 -3
  16. package/dist/{bundleWithLocalizedFonts-2EGPA5ZO.js → bundleWithLocalizedFonts-67MLTHKM.js} +2 -2
  17. package/dist/{capture-HOIAW6MO.js → capture-F3GNMRZM.js} +13 -13
  18. package/dist/{capture-HA2UHLIU.js → capture-YYRE7EV3.js} +2 -2
  19. package/dist/{captureCompositionFrame-4236FVWJ.js → captureCompositionFrame-PXV2ISHD.js} +13 -13
  20. package/dist/{catalog-A6CZAWW4.js → catalog-6SDD3OHF.js} +14 -14
  21. package/dist/{catch-up-TNA4DJOA.js → catch-up-CWIVA5VG.js} +4 -4
  22. package/dist/{check-5E5U2EQZ.js → check-YQ6REK2S.js} +34 -34
  23. package/dist/{checkBrowser-FNINXBMZ.js → checkBrowser-5XZCBRXM.js} +31 -31
  24. package/dist/{chunk-2ULXZ4PG.js → chunk-2TAS5O4P.js} +56 -11
  25. package/dist/{chunk-3TXNNBI2.js → chunk-37CNYTQQ.js} +2 -2
  26. package/dist/chunk-3NPOFC43.js +3805 -0
  27. package/dist/{chunk-EEP5Y5IE.js → chunk-46HEFGXJ.js} +1 -1
  28. package/dist/{chunk-2XA7KXQO.js → chunk-4CTNDBE3.js} +2 -2
  29. package/dist/{chunk-MFAETWIF.js → chunk-55YELV7B.js} +1 -1
  30. package/dist/{chunk-LRGYPXHF.js → chunk-5GUKZRQN.js} +1 -1
  31. package/dist/{chunk-SAX7HQ5E.js → chunk-6ASIXMFP.js} +1 -1
  32. package/dist/{chunk-SN7KI5JA.js → chunk-6GPR3G3C.js} +2 -2
  33. package/dist/{chunk-E32ZQ2WO.js → chunk-6RIZY7OP.js} +1 -1
  34. package/dist/{chunk-5CS4T6C6.js → chunk-7L37AB57.js} +1 -1
  35. package/dist/{chunk-BCHSTE7U.js → chunk-7PS6RVWD.js} +1 -1
  36. package/dist/{chunk-X3CG5YQA.js → chunk-7RAY4WZP.js} +3 -3
  37. package/dist/{chunk-YWHCXIMD.js → chunk-A6QCO474.js} +5 -5
  38. package/dist/{chunk-YMS5FOMC.js → chunk-B2A56S5C.js} +1 -1
  39. package/dist/{chunk-IWTNTUPQ.js → chunk-BH7TTIPN.js} +11 -13
  40. package/dist/{chunk-DWUGKEHR.js → chunk-BRAPBUPQ.js} +1 -1
  41. package/dist/{chunk-R2BFTECP.js → chunk-CX3USX23.js} +3 -3
  42. package/dist/{chunk-JB6ARMQS.js → chunk-D42NU3DZ.js} +1 -1
  43. package/dist/{chunk-GDEV42FA.js → chunk-EMAWIZ54.js} +481 -36
  44. package/dist/{chunk-UNNXFKVG.js → chunk-EMSDWBG3.js} +2 -2
  45. package/dist/{chunk-CXABAXB3.js → chunk-ESBMUZXZ.js} +1 -1
  46. package/dist/{chunk-EM7C7H7S.js → chunk-F3OPUWQX.js} +7 -7
  47. package/dist/{chunk-YOZPQCSR.js → chunk-FX6RUJUY.js} +3 -3
  48. package/dist/{chunk-PSKEKWVU.js → chunk-G2UANIDX.js} +1 -1
  49. package/dist/{chunk-UKOTVJFV.js → chunk-H5SM5PJI.js} +1 -1
  50. package/dist/{chunk-YWNJTZGN.js → chunk-H6UY725W.js} +2 -2
  51. package/dist/{chunk-PFYWVUHA.js → chunk-HDIRZGK4.js} +1 -1
  52. package/dist/{chunk-HR23IKLZ.js → chunk-HHSJJFVM.js} +2 -2
  53. package/dist/{chunk-LLC4CS6I.js → chunk-HXUTX5GR.js} +3 -3
  54. package/dist/{chunk-RGXVEYHI.js → chunk-I3IH5MV5.js} +6 -10
  55. package/dist/{chunk-Q33P4EAC.js → chunk-I45HL3VP.js} +3 -3
  56. package/dist/{chunk-TYXH3EKP.js → chunk-I5JRXMCV.js} +16 -1
  57. package/dist/{chunk-4N4P3ZWL.js → chunk-I7QMXZSB.js} +2 -2
  58. package/dist/{chunk-ICJEAFPD.js → chunk-IDFNKFPL.js} +7 -7
  59. package/dist/{chunk-VNVQGDPC.js → chunk-IDGLGXPA.js} +1 -1
  60. package/dist/{chunk-2PVE4WS2.js → chunk-IPDKZ5IN.js} +33 -6
  61. package/dist/{chunk-ABZYYUUH.js → chunk-ISTRDGIX.js} +1 -1
  62. package/dist/{chunk-3MDJIWOV.js → chunk-IVEFOUZI.js} +46 -30
  63. package/dist/{chunk-4KKKBEP3.js → chunk-J5XEZ24I.js} +3 -3
  64. package/dist/{chunk-7HJALUIO.js → chunk-K2ZKXTVL.js} +1 -1
  65. package/dist/{chunk-TE427YID.js → chunk-K73RJB23.js} +2 -2
  66. package/dist/{chunk-3QVMJ7GX.js → chunk-KQ4JEJLF.js} +9 -9
  67. package/dist/{chunk-J3QM7AHP.js → chunk-KROXPHXX.js} +9 -3
  68. package/dist/{chunk-OLZENUPI.js → chunk-LLFQA7XF.js} +1 -1
  69. package/dist/chunk-LLMSX6V6.js +17 -0
  70. package/dist/{chunk-WTFUDNW2.js → chunk-LYKSTRAY.js} +3 -3
  71. package/dist/{chunk-VDM3FEDP.js → chunk-OAG47RE6.js} +1 -1
  72. package/dist/{chunk-FGJEUV4S.js → chunk-PHMBMOXF.js} +1 -1
  73. package/dist/{chunk-7MB2ZAQF.js → chunk-PMMQRJDE.js} +1 -1
  74. package/dist/{chunk-ADDHW2FS.js → chunk-Q447CX26.js} +82 -12
  75. package/dist/{chunk-YALM6XN4.js → chunk-Q47FAYYK.js} +3 -3
  76. package/dist/{chunk-ZOCHDXDG.js → chunk-RTBSA3EA.js} +1 -1
  77. package/dist/{chunk-UJKUB2LH.js → chunk-RUEGYANA.js} +11 -11
  78. package/dist/{chunk-OYLO6TYK.js → chunk-RUOG4VB7.js} +1 -1
  79. package/dist/{chunk-ZRHO6YMM.js → chunk-SKYPMHQC.js} +4 -4
  80. package/dist/{chunk-ES426XRJ.js → chunk-SQVRXHOW.js} +3 -3
  81. package/dist/{chunk-QL2PNIXC.js → chunk-TAX2ZJAP.js} +24 -16
  82. package/dist/{chunk-KN46TGHV.js → chunk-TOI35GN2.js} +1 -1
  83. package/dist/{chunk-74JMKLVU.js → chunk-UPR3MU6Z.js} +1 -1
  84. package/dist/{chunk-JIUTXKWA.js → chunk-WQLKDL35.js} +2 -1
  85. package/dist/{chunk-WHPN2TIT.js → chunk-X6L6MD5B.js} +5 -5
  86. package/dist/{chunk-7NRI7HYX.js → chunk-XWC7CNPY.js} +1 -1
  87. package/dist/{clean-HGASSMWI.js → clean-7J6ZCCGV.js} +18 -18
  88. package/dist/cli.js +53 -53
  89. package/dist/{cloud-JPDVNXHN.js → cloud-7IJCJCDD.js} +4 -4
  90. package/dist/{cloudrun-AMMGSDRP.js → cloudrun-UNZRIIDB.js} +7 -7
  91. package/dist/commands/contrast-audit.browser.js +1 -2
  92. package/dist/commands/layout-audit.browser.js +196 -0
  93. package/dist/{compare-LHHVHUN3.js → compare-Q7VW5JZT.js} +28 -28
  94. package/dist/{compiler-Q3N6QXMT.js → compiler-KPHYGFXL.js} +6 -6
  95. package/dist/{component-D72J32Q7.js → component-UUBREJKN.js} +3 -3
  96. package/dist/{compositions-UQRJ5ROG.js → compositions-T4FTKIDP.js} +13 -13
  97. package/dist/{delete-P42VIDDA.js → delete-WZQF2IIA.js} +2 -2
  98. package/dist/{deploy-WZTH57O4.js → deploy-JU7A3XNC.js} +1 -1
  99. package/dist/{deterministicFonts-VQ5UBMXY.js → deterministicFonts-EGAAE7QL.js} +3 -3
  100. package/dist/{dist-SENYPQGW.js → dist-LM7AVHOU.js} +3 -3
  101. package/dist/{dist-DYS24AMA.js → dist-ULGTPSU4.js} +8 -4
  102. package/dist/docs/data-attributes.md +1 -1
  103. package/dist/{doctor-KEJIG2SK.js → doctor-VSNGRKXJ.js} +13 -13
  104. package/dist/{events-CYKSNR7N.js → events-CRW2DYUT.js} +3 -3
  105. package/dist/{events-UZXFQPMT.js → events-E63YBUL2.js} +3 -3
  106. package/dist/{feedback-LXNQF7CA.js → feedback-OSZWVR6N.js} +8 -8
  107. package/dist/{ffmpeg-BYHON577.js → ffmpeg-JLH3Z7G7.js} +9 -9
  108. package/dist/{figma-EIQ35PS6.js → figma-2BQNNR53.js} +3 -3
  109. package/dist/fontLocalizeCli.js +12 -12
  110. package/dist/{get-CC2YL7QO.js → get-P2XI53QW.js} +2 -2
  111. package/dist/{gpuPolicy-VFSACUQV.js → gpuPolicy-NTKQJY75.js} +9 -9
  112. package/dist/{grade-compare-TUQL7IV2.js → grade-compare-OYASIHIB.js} +29 -29
  113. package/dist/{gsapParserAcorn-7NCK2LVT.js → gsapParserAcorn-SKODXC2N.js} +2 -2
  114. package/dist/{help-ROROO5K6.js → help-HK6K2N4G.js} +1 -1
  115. package/dist/{history-PNELYLXX.js → history-JMTYKLXW.js} +6 -6
  116. package/dist/hyperframe.manifest.json +1 -1
  117. package/dist/hyperframe.runtime.iife.js +63 -63
  118. package/dist/hyperframes-player.global.js +1 -1
  119. package/dist/{info-4FZTH6AS.js → info-AW7CIVRE.js} +9 -9
  120. package/dist/{init-I43GHHVP.js → init-6KIDG4LB.js} +30 -30
  121. package/dist/{inspect-IT4TYIZ3.js → inspect-B7BLYMRZ.js} +29 -29
  122. package/dist/{installer-CWOJVK5K.js → installer-ZP2LQZUQ.js} +7 -7
  123. package/dist/{keyframes-3FBOGVD4.js → keyframes-EQ36A5JE.js} +7 -7
  124. package/dist/{lambda-H3V32I7M.js → lambda-E6VURLIS.js} +9 -9
  125. package/dist/{layout-BZ5LYJ5C.js → layout-XYC64QQQ.js} +29 -29
  126. package/dist/{lint-ZTNSGP2S.js → lint-V5DJYWBX.js} +9 -9
  127. package/dist/{lintProject-C2ONSH2U.js → lintProject-JATQKR64.js} +3 -3
  128. package/dist/{list-XM4GWJYY.js → list-RUGVRTVD.js} +2 -2
  129. package/dist/{login-H6HYKMWX.js → login-ZTKGKXGS.js} +4 -4
  130. package/dist/{manager-TWVDSJXO.js → manager-JUP7PM6N.js} +10 -10
  131. package/dist/{media-treatment-N7MY5NXB.js → media-treatment-VIUPK4OR.js} +15 -15
  132. package/dist/{models-WEMIMYBD.js → models-LJS2HBOZ.js} +13 -13
  133. package/dist/{motionShot-RHICTVPU.js → motionShot-3UAXZ7SN.js} +16 -16
  134. package/dist/{normalize-audio-ZFUZCJE3.js → normalize-audio-SBYI4YIH.js} +4 -4
  135. package/dist/{open-IBJ4FL3G.js → open-S27TUD3A.js} +14 -14
  136. package/dist/{parakeetRunner-XXO4WSLR.js → parakeetRunner-ETLMLJ4L.js} +14 -14
  137. package/dist/{pipeline-6ML3LUVK.js → pipeline-I2M22M24.js} +10 -10
  138. package/dist/{play-RV4NAVF5.js → play-COJU6VJK.js} +21 -21
  139. package/dist/{preflight-R3DEFMLA.js → preflight-FZ24NCHH.js} +10 -10
  140. package/dist/{present-5TBJGE6B.js → present-YAHKLC5D.js} +17 -17
  141. package/dist/{preview-FLKZ5CXJ.js → preview-KQOEU5YE.js} +20 -20
  142. package/dist/{producer-7XYSPVKH.js → producer-DTNNG4T6.js} +1 -1
  143. package/dist/{projectConfig-TBU2VWZX.js → projectConfig-4A76VYUP.js} +9 -9
  144. package/dist/{publication-CWWUJYJ5.js → publication-SQPMC2W3.js} +4 -4
  145. package/dist/{publish-FSNE4FEB.js → publish-QUEJBGGT.js} +11 -11
  146. package/dist/{remove-background-MDFWRWCT.js → remove-background-FP2ETAQH.js} +11 -11
  147. package/dist/{render-F4JQ553X.js → render-BIFIL4U6.js} +31 -31
  148. package/dist/{render-DBGQZAZT.js → render-GQFXJWLV.js} +17 -29
  149. package/dist/{render-LWZKXCLY.js → render-P664SMC7.js} +5 -5
  150. package/dist/{render-batch-PU7NMLIJ.js → render-batch-ZCPMYH6Z.js} +5 -5
  151. package/dist/renderSetupWorker.js +3 -3
  152. package/dist/{resolver-RUBGFXPC.js → resolver-BUC2GFZQ.js} +6 -6
  153. package/dist/{sherpa-X2TBNO6P.js → sherpa-HFT6XEP6.js} +13 -13
  154. package/dist/skills/hyperframes/SKILL.md +52 -174
  155. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/FRAME.md +289 -0
  156. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/caption-skin.html +220 -0
  157. package/dist/skills/hyperframes/assets/frame-presets/biennale-yellow/frame-showcase.html +1214 -0
  158. package/dist/skills/hyperframes/assets/frame-presets/blockframe/FRAME.md +275 -0
  159. package/dist/skills/hyperframes/assets/frame-presets/blockframe/caption-skin.html +223 -0
  160. package/dist/skills/hyperframes/assets/frame-presets/blockframe/frame-showcase.html +1347 -0
  161. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/FRAME.md +307 -0
  162. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/caption-skin.html +222 -0
  163. package/dist/skills/hyperframes/assets/frame-presets/blue-professional/frame-showcase.html +1372 -0
  164. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/FRAME.md +275 -0
  165. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/caption-skin.html +229 -0
  166. package/dist/skills/hyperframes/assets/frame-presets/bold-poster/frame-showcase.html +1140 -0
  167. package/dist/skills/hyperframes/assets/frame-presets/broadside/FRAME.md +284 -0
  168. package/dist/skills/hyperframes/assets/frame-presets/broadside/caption-skin.html +224 -0
  169. package/dist/skills/hyperframes/assets/frame-presets/broadside/frame-showcase.html +1166 -0
  170. package/dist/skills/hyperframes/assets/frame-presets/capsule/FRAME.md +284 -0
  171. package/dist/skills/hyperframes/assets/frame-presets/capsule/caption-skin.html +223 -0
  172. package/dist/skills/hyperframes/assets/frame-presets/capsule/frame-showcase.html +1465 -0
  173. package/dist/skills/hyperframes/assets/frame-presets/cartesian/FRAME.md +278 -0
  174. package/dist/skills/hyperframes/assets/frame-presets/cartesian/caption-skin.html +221 -0
  175. package/dist/skills/hyperframes/assets/frame-presets/cartesian/frame-showcase.html +1263 -0
  176. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/FRAME.md +265 -0
  177. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/caption-skin.html +237 -0
  178. package/dist/skills/hyperframes/assets/frame-presets/cobalt-grid/frame-showcase.html +1468 -0
  179. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/FRAME.md +277 -0
  180. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/caption-skin.html +223 -0
  181. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-400.woff2 +0 -0
  182. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/EBGaramond-700.woff2 +0 -0
  183. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-400.woff2 +0 -0
  184. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/Inter-700.woff2 +0 -0
  185. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-400.woff2 +0 -0
  186. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/JetBrainsMono-700.woff2 +0 -0
  187. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-eb-garamond.txt +93 -0
  188. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-inter.txt +93 -0
  189. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/fonts/OFL-jetbrains-mono.txt +93 -0
  190. package/dist/skills/hyperframes/assets/frame-presets/code-editorial/frame-showcase.html +1438 -0
  191. package/dist/skills/hyperframes/assets/frame-presets/coral/FRAME.md +314 -0
  192. package/dist/skills/hyperframes/assets/frame-presets/coral/caption-skin.html +225 -0
  193. package/dist/skills/hyperframes/assets/frame-presets/coral/frame-showcase.html +1268 -0
  194. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/FRAME.md +333 -0
  195. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/caption-skin.html +226 -0
  196. package/dist/skills/hyperframes/assets/frame-presets/creative-mode/frame-showcase.html +1330 -0
  197. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/FRAME.md +274 -0
  198. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/caption-skin.html +229 -0
  199. package/dist/skills/hyperframes/assets/frame-presets/daisy-days/frame-showcase.html +1444 -0
  200. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/FRAME.md +265 -0
  201. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/caption-skin.html +222 -0
  202. package/dist/skills/hyperframes/assets/frame-presets/editorial-forest/frame-showcase.html +1273 -0
  203. package/dist/skills/hyperframes/references/captions.md +46 -0
  204. package/dist/skills/hyperframes/references/film.md +47 -0
  205. package/dist/skills/hyperframes/references/format.md +157 -0
  206. package/dist/skills/hyperframes/references/look.md +69 -0
  207. package/dist/skills/hyperframes/references/motion.md +94 -0
  208. package/dist/skills/hyperframes/references/overlays.md +39 -0
  209. package/dist/skills/hyperframes/references/plugin-installation.md +3 -3
  210. package/dist/skills/hyperframes/references/review.md +51 -0
  211. package/dist/skills/hyperframes/references/runtimes.md +43 -0
  212. package/dist/skills/hyperframes/references/skill-lifecycle.md +21 -13
  213. package/dist/skills/hyperframes/references/sound.md +43 -0
  214. package/dist/skills/hyperframes/references/spec.md +76 -0
  215. package/dist/skills/hyperframes/references/story.md +103 -0
  216. package/dist/skills/hyperframes/references/storyboard-format.md +30 -22
  217. package/dist/skills/hyperframes/references/storyboard.md +36 -0
  218. package/dist/skills/hyperframes/references/types/3d.md +25 -0
  219. package/dist/skills/hyperframes/references/types/character.md +20 -0
  220. package/dist/skills/hyperframes/references/types/data.md +19 -0
  221. package/dist/skills/hyperframes/references/types/explainer.md +34 -0
  222. package/dist/skills/hyperframes/references/types/launch.md +31 -0
  223. package/dist/skills/hyperframes/references/types/music.md +24 -0
  224. package/dist/skills/hyperframes/references/types/vertical.md +23 -0
  225. package/dist/skills/hyperframes/scripts/bake-basemap.mjs +324 -0
  226. package/dist/skills/hyperframes/scripts/lib/main-module.test.mjs +1 -6
  227. package/dist/skills/hyperframes/scripts/locate.mjs +228 -0
  228. package/dist/skills/hyperframes-cli/SKILL.md +76 -179
  229. package/dist/skills/hyperframes-cli/references/beats.md +1 -1
  230. package/dist/skills/hyperframes-cli/references/cloud.md +2 -2
  231. package/dist/skills/hyperframes-cli/references/cloudrun.md +1 -1
  232. package/dist/skills/hyperframes-cli/references/conventions.md +17 -0
  233. package/dist/skills/hyperframes-cli/references/feedback.md +14 -0
  234. package/dist/skills/hyperframes-cli/references/init-and-scaffold.md +11 -7
  235. package/dist/skills/hyperframes-cli/references/lambda.md +1 -1
  236. package/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +19 -8
  237. package/dist/skills/hyperframes-cli/references/preview-render.md +8 -2
  238. package/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +8 -0
  239. package/dist/skills/media-use/SKILL.md +47 -91
  240. package/dist/skills/media-use/audio/references/bgm.md +1 -1
  241. package/dist/skills/media-use/audio/references/captions/authoring.md +1 -2
  242. package/dist/skills/media-use/audio/references/captions/motion.md +5 -5
  243. package/dist/skills/media-use/audio/references/tts.md +0 -3
  244. package/dist/skills/media-use/audio/scripts/audio.mjs +5 -6
  245. package/dist/skills/media-use/audio/scripts/carve.mjs +560 -0
  246. package/dist/skills/media-use/audio/scripts/carve.test.mjs +254 -0
  247. package/dist/skills/media-use/audio/scripts/extract-audio-data.py +199 -0
  248. package/dist/skills/media-use/references/local.md +24 -0
  249. package/dist/skills/media-use/references/memory.md +4 -4
  250. package/dist/skills/media-use/references/mixing.md +71 -0
  251. package/dist/skills/media-use/references/operations.md +1 -1
  252. package/dist/skills/media-use/scripts/compatibility.test.mjs +1 -56
  253. package/dist/skills/media-use/scripts/lib/prefs-store.mjs +1 -1
  254. package/dist/skills/media-use/scripts/lib/recipe-store.mjs +1 -1
  255. package/dist/skills/media-use/scripts/prefs.mjs +2 -3
  256. package/dist/skills/media-use/scripts/recipe.mjs +1 -3
  257. package/dist/{skills-WHKMWO2D.js → skills-3WEVO3NU.js} +20 -13
  258. package/dist/{skillsUpdateCheck-XQGZGJJG.js → skillsUpdateCheck-BFPWFOK5.js} +3 -3
  259. package/dist/{snapshot-M4NUUSNU.js → snapshot-WDQ6S7CJ.js} +457 -98
  260. package/dist/{src-6MSC62U2.js → src-NPR2JZOJ.js} +11 -11
  261. package/dist/{src-4UYM2K3S.js → src-RZ574OKP.js} +8 -8
  262. package/dist/{staticProjectServer-ERDTFP45.js → staticProjectServer-FTGTEZI4.js} +17 -17
  263. package/dist/studio/assets/{hyperframes-player-DEncBxR7.js → hyperframes-player-CoOdf435.js} +1 -1
  264. package/dist/studio/assets/{index-Cc22mgvY.js → index-CR85xg2x.js} +1 -1
  265. package/dist/studio/assets/{index-BABXr78Q.js → index-C_6rTpaB.js} +5 -5
  266. package/dist/studio/index.html +1 -1
  267. package/dist/{studio-api-SAKD3VKC.js → studio-api-TAWB7B23.js} +11 -11
  268. package/dist/{studioServer-IRI7EVOM.js → studioServer-HRQGJTBU.js} +48 -48
  269. package/dist/{telemetry-F4XADVAF.js → telemetry-QZ6HJF4W.js} +3 -3
  270. package/dist/templates/_shared/AGENTS.md +14 -19
  271. package/dist/templates/_shared/CLAUDE.md +14 -19
  272. package/dist/templates/blank/index.html +10 -4
  273. package/dist/{timeline-5I444RRE.js → timeline-IKUEW42T.js} +20 -19
  274. package/dist/{tokens-LRRYM35A.js → tokens-AUGUEWHS.js} +2 -2
  275. package/dist/{transcribe-44XDFNVU.js → transcribe-7734CG3N.js} +18 -18
  276. package/dist/{transcribe-WHYHWAB2.js → transcribe-FWU6EMEO.js} +12 -12
  277. package/dist/{updateCheck-7CPH3CAZ.js → updateCheck-VIPQ3FPW.js} +2 -2
  278. package/dist/{upgrade-WW4GQ2RI.js → upgrade-4VNDQTVO.js} +2 -2
  279. package/dist/{urlDownloader-OHLLP45A.js → urlDownloader-6CXL4CL7.js} +8 -8
  280. package/dist/{validate-VNCDH2LW.js → validate-QWCMVWID.js} +23 -23
  281. package/dist/{video-5OHTLL2D.js → video-245Q5WN4.js} +9 -9
  282. package/dist/warmCheck.js +36 -36
  283. package/package.json +1 -1
  284. package/dist/chunk-R2SQBPMH.js +0 -3805
  285. package/dist/skills/hyperframes/references/brief-contract.md +0 -108
  286. package/dist/skills/hyperframes/references/brief-format.md +0 -72
  287. package/dist/skills/hyperframes/references/capability-menu.md +0 -47
  288. package/dist/skills/hyperframes/references/frame-worker-core.md +0 -82
  289. package/dist/skills/hyperframes/references/intent-interview.md +0 -73
  290. package/dist/skills/hyperframes/references/pitch-round.md +0 -40
  291. package/dist/skills/hyperframes/references/production-loop.md +0 -26
  292. package/dist/skills/hyperframes/references/review-loop.md +0 -37
  293. package/dist/skills/hyperframes/references/route-briefs.md +0 -11
  294. package/dist/skills/hyperframes/references/routes/embedded-captions.md +0 -11
  295. package/dist/skills/hyperframes/references/routes/faceless-explainer.md +0 -12
  296. package/dist/skills/hyperframes/references/routes/general-video.md +0 -12
  297. package/dist/skills/hyperframes/references/routes/motion-graphics.md +0 -11
  298. package/dist/skills/hyperframes/references/routes/music-to-video.md +0 -12
  299. package/dist/skills/hyperframes/references/routes/pr-to-video.md +0 -28
  300. package/dist/skills/hyperframes/references/routes/product-launch-video.md +0 -13
  301. package/dist/skills/hyperframes/references/routes/remotion-to-hyperframes.md +0 -9
  302. package/dist/skills/hyperframes/references/routes/slideshow.md +0 -11
  303. package/dist/skills/hyperframes/references/routes/talking-head-recut.md +0 -11
  304. package/dist/skills/hyperframes/references/script-format.md +0 -52
  305. package/dist/skills/hyperframes/references/subagent-dispatch.md +0 -35
  306. package/dist/skills/hyperframes/references/workflow-catalog.md +0 -10
  307. package/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +0 -176
  308. package/dist/skills/media-use/audio/scripts/lib/host-audio.mjs +0 -28
  309. 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-OAG47RE6.js";
15
15
  import {
16
16
  loadProducer
17
- } from "./chunk-BCHSTE7U.js";
17
+ } from "./chunk-7PS6RVWD.js";
18
18
  import {
19
19
  trackLintRun
20
- } from "./chunk-Q33P4EAC.js";
20
+ } from "./chunk-I45HL3VP.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-TAX2ZJAP.js";
49
50
  import {
50
51
  resolveProject
51
- } from "./chunk-LRGYPXHF.js";
52
+ } from "./chunk-5GUKZRQN.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-TOI35GN2.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-EMSDWBG3.js";
65
66
  import {
66
67
  trackCheckReport,
67
68
  trackCommandFailure
68
- } from "./chunk-JIUTXKWA.js";
69
+ } from "./chunk-WQLKDL35.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-I3IH5MV5.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-ISTRDGIX.js";
99
100
  import {
100
101
  normalizeErrorMessage
101
102
  } from "./chunk-KNU5COPB.js";
@@ -201,9 +202,378 @@ import { mkdirSync, writeFileSync } from "fs";
201
202
  import { readFile } from "fs/promises";
202
203
  import { join, relative } from "path";
203
204
 
205
+ // src/utils/craftAudit.ts
206
+ var CRAFT_THRESHOLDS = {
207
+ readHeightAt1080: 30,
208
+ readOpacity: 0.5,
209
+ shortLineWords: 2,
210
+ shortLineFloorSec: 0.4,
211
+ holdBaseSec: 0.5,
212
+ holdPerWordSec: 0.3,
213
+ holdFloorFraction: 0.75,
214
+ finalLineFloorSec: 2,
215
+ deadStretchSec: 3,
216
+ endCardSec: END_CARD_HOLD_SEC,
217
+ typeFloorFraction: 0.026,
218
+ typeFloorHoldSec: 0.5,
219
+ silentFilmSec: 15,
220
+ /** One video frame: a line held exactly at its floor measures a hair under it. */
221
+ measureToleranceSec: 1 / 30,
222
+ /** Halvings of a grid step when re-measuring a line's edges (0.125 s → ~8 ms). */
223
+ refineSteps: 4,
224
+ maxRefinedLines: 24
225
+ };
226
+ var T = CRAFT_THRESHOLDS;
227
+ var ZERO_BBOX = { x: 0, y: 0, width: 0, height: 0 };
228
+ var WORD_RUNS = /[\p{L}\p{M}\p{N}%$]+/gu;
229
+ var WORD_SEGMENTER = new Intl.Segmenter("ja", { granularity: "word" });
230
+ function readingWords(text) {
231
+ const runs = text.toLowerCase().normalize("NFC").match(WORD_RUNS) ?? [];
232
+ return runs.reduce(
233
+ (count, run) => count + Math.max(1, [...WORD_SEGMENTER.segment(run)].filter((s) => s.isWordLike).length),
234
+ 0
235
+ );
236
+ }
237
+ function lineTargetSec(words) {
238
+ return T.holdBaseSec + T.holdPerWordSec * words;
239
+ }
240
+ function lineFloorSec(words, finalLine) {
241
+ const floor = words <= T.shortLineWords ? T.shortLineFloorSec : T.holdFloorFraction * lineTargetSec(words);
242
+ return finalLine ? Math.max(floor, T.finalLineFloorSec) : floor;
243
+ }
244
+ async function auditCraft(input, probe) {
245
+ const frames = [...input.frames].sort((a, b) => a.time - b.time);
246
+ const step = sampleStep(frames);
247
+ const findings = [
248
+ ...detectFirstFrameEmpty(frames),
249
+ ...await detectLineUnread(frames, input.duration, input.canvas, probe),
250
+ ...input.stillnessJudgedElsewhere ? [] : detectDeadStretches(frames, input.duration),
251
+ ...detectTextBelowFloor(frames, input.duration, input.canvas),
252
+ ...detectFilmSilent(input.duration, input.soundSources)
253
+ ].sort((a, b) => a.time - b.time);
254
+ return { enabled: true, step, samples: frames.length, findings };
255
+ }
256
+ function sampleStep(frames) {
257
+ const gaps = frames.slice(1).map((frame, index) => frame.time - (frames[index]?.time ?? frame.time)).filter((gap) => gap > 0).sort((a, b) => a - b);
258
+ return gaps[Math.floor(gaps.length / 2)] ?? 0;
259
+ }
260
+ function seconds(value) {
261
+ return `${value.toFixed(2)} s`;
262
+ }
263
+ function filmFinding(code, time, message, extra = {}) {
264
+ return {
265
+ code,
266
+ severity: "warning",
267
+ message,
268
+ selector: "[data-composition-id]",
269
+ dataAttributes: {},
270
+ sourceFile: "index.html",
271
+ bbox: ZERO_BBOX,
272
+ time,
273
+ ...extra
274
+ };
275
+ }
276
+ function detectFirstFrameEmpty(frames) {
277
+ const first = frames[0];
278
+ if (!first || first.time > 1e-3 || first.painted) return [];
279
+ return [
280
+ filmFinding(
281
+ "first_frame_empty",
282
+ 0,
283
+ "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."
284
+ )
285
+ ];
286
+ }
287
+ function detectFilmSilent(duration, soundSources) {
288
+ if (soundSources === null || soundSources > 0 || duration <= T.silentFilmSec) return [];
289
+ return [
290
+ filmFinding(
291
+ "film_silent",
292
+ 0,
293
+ `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.`
294
+ )
295
+ ];
296
+ }
297
+ function detectDeadStretches(frames, duration) {
298
+ const endCardStart = duration - T.endCardSec;
299
+ const findings = [];
300
+ let start = null;
301
+ let end = 0;
302
+ const flush = () => {
303
+ if (start !== null && end - start > T.deadStretchSec) findings.push(deadStretch(start, end));
304
+ start = null;
305
+ };
306
+ for (let index = 1; index < frames.length; index += 1) {
307
+ const before = frames[index - 1];
308
+ const after = frames[index];
309
+ if (!before || !after) continue;
310
+ const still = before.signature !== "" && before.signature === after.signature && !before.held && !after.held && before.time < endCardStart;
311
+ if (!still) {
312
+ flush();
313
+ continue;
314
+ }
315
+ start ??= before.time;
316
+ end = Math.min(after.time, endCardStart);
317
+ }
318
+ flush();
319
+ return findings;
320
+ }
321
+ function deadStretch(start, end) {
322
+ const length = end - start;
323
+ return filmFinding(
324
+ "dead_stretch",
325
+ start,
326
+ `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.`,
327
+ { seconds: round(length), floorSeconds: T.deadStretchSec, until: round(end) }
328
+ );
329
+ }
330
+ function readableBlocks(frame, readHeight) {
331
+ const blocks = /* @__PURE__ */ new Map();
332
+ for (const part of frame.parts) {
333
+ if (part.captions || part.opacity < T.readOpacity) continue;
334
+ const rect = {
335
+ left: part.rect.left,
336
+ top: part.rect.top,
337
+ right: part.rect.left + part.rect.width,
338
+ bottom: part.rect.top + part.rect.height
339
+ };
340
+ const block = blocks.get(part.block);
341
+ if (!block) {
342
+ blocks.set(part.block, {
343
+ text: part.text,
344
+ rect,
345
+ selector: part.blockSelector,
346
+ sourceFile: part.sourceFile
347
+ });
348
+ continue;
349
+ }
350
+ block.text = `${block.text} ${part.text}`;
351
+ block.rect = {
352
+ left: Math.min(block.rect.left, rect.left),
353
+ top: Math.min(block.rect.top, rect.top),
354
+ right: Math.max(block.rect.right, rect.right),
355
+ bottom: Math.max(block.rect.bottom, rect.bottom)
356
+ };
357
+ }
358
+ for (const [key, block] of blocks) {
359
+ if (block.rect.bottom - block.rect.top < readHeight) blocks.delete(key);
360
+ }
361
+ return blocks;
362
+ }
363
+ function trackBlocks(frames, readHeight) {
364
+ const tracks = /* @__PURE__ */ new Map();
365
+ frames.forEach((frame, index) => {
366
+ for (const [key, block] of readableBlocks(frame, readHeight)) {
367
+ const track = tracks.get(key) ?? {
368
+ key,
369
+ selector: block.selector,
370
+ sourceFile: block.sourceFile,
371
+ seen: /* @__PURE__ */ new Map()
372
+ };
373
+ track.seen.set(index, { text: block.text, rect: block.rect });
374
+ tracks.set(key, track);
375
+ }
376
+ });
377
+ return [...tracks.values()];
378
+ }
379
+ function indexRuns(indices) {
380
+ const sorted = [...indices].sort((a, b) => a - b);
381
+ const runs = [];
382
+ for (const index of sorted) {
383
+ const last = runs[runs.length - 1];
384
+ if (last && index === last[1] + 1) last[1] = index;
385
+ else runs.push([index, index]);
386
+ }
387
+ return runs;
388
+ }
389
+ function windowSeconds(window2) {
390
+ return (window2.endIn + window2.endOut) / 2 - (window2.startOut + window2.startIn) / 2;
391
+ }
392
+ function runWindow(frames, [first, last], duration) {
393
+ const timeAt = (index) => frames[Math.min(Math.max(index, 0), frames.length - 1)]?.time ?? 0;
394
+ const reachesEnd = last === frames.length - 1;
395
+ return {
396
+ startOut: timeAt(first - 1),
397
+ startIn: timeAt(first),
398
+ endIn: reachesEnd ? duration : timeAt(last),
399
+ endOut: reachesEnd ? duration : timeAt(last + 1)
400
+ };
401
+ }
402
+ function lineCandidates(frames, duration, canvas) {
403
+ const readHeight = T.readHeightAt1080 * (Math.min(canvas.width, canvas.height) / 1080);
404
+ const tracks = trackBlocks(frames, readHeight);
405
+ const lastEnd = (track) => Math.max(...track.seen.keys());
406
+ const latest = Math.max(-1, ...tracks.map(lastEnd));
407
+ const candidates = [];
408
+ for (const track of tracks) {
409
+ const runs = indexRuns([...track.seen.keys()]);
410
+ const finalLine = lastEnd(track) === latest;
411
+ const windows = runs.map((run2) => runWindow(frames, run2, duration));
412
+ const chosen = finalLine ? windows.length - 1 : windows.reduce((best, window3, index) => {
413
+ const bestWindow = windows[best];
414
+ return bestWindow && windowSeconds(window3) > windowSeconds(bestWindow) ? index : best;
415
+ }, 0);
416
+ const window2 = windows[chosen];
417
+ const run = runs[chosen];
418
+ if (!window2 || !run) continue;
419
+ const texts = [...track.seen.values()].map((seen) => seen.text);
420
+ const text = texts.reduce(
421
+ (longest, next) => readingWords(next) > readingWords(longest) ? next : longest
422
+ );
423
+ const words = readingWords(text);
424
+ if (words === 0) continue;
425
+ const floor = lineFloorSec(words, finalLine);
426
+ if (window2.endIn - window2.startIn >= floor) continue;
427
+ candidates.push({ track, words, text, finalLine, floor, window: window2, firstIndex: run[0] });
428
+ }
429
+ return candidates;
430
+ }
431
+ async function refineWindow(candidate, probe, canvas) {
432
+ const readHeight = T.readHeightAt1080 * (Math.min(canvas.width, canvas.height) / 1080);
433
+ const visibleAt = async (time) => readableBlocks(await probe(time), readHeight).has(candidate.track.key);
434
+ const window2 = { ...candidate.window };
435
+ for (let step = 0; step < T.refineSteps; step += 1) {
436
+ if (window2.startIn > window2.startOut) {
437
+ const mid = (window2.startOut + window2.startIn) / 2;
438
+ if (await visibleAt(mid)) window2.startIn = mid;
439
+ else window2.startOut = mid;
440
+ }
441
+ if (window2.endOut > window2.endIn) {
442
+ const mid = (window2.endIn + window2.endOut) / 2;
443
+ if (await visibleAt(mid)) window2.endIn = mid;
444
+ else window2.endOut = mid;
445
+ }
446
+ }
447
+ return window2;
448
+ }
449
+ async function detectLineUnread(frames, duration, canvas, probe) {
450
+ const findings = [];
451
+ const candidates = lineCandidates(frames, duration, canvas);
452
+ for (const [index, candidate] of candidates.entries()) {
453
+ const window2 = probe && index < T.maxRefinedLines ? await refineWindow(candidate, probe, canvas) : candidate.window;
454
+ const held = windowSeconds(window2);
455
+ if (held >= candidate.floor - T.measureToleranceSec) continue;
456
+ const error = Math.max(window2.startIn - window2.startOut, window2.endOut - window2.endIn) / 2;
457
+ findings.push(lineUnreadFinding(candidate, window2, held, error));
458
+ }
459
+ return findings;
460
+ }
461
+ function lineUnreadFinding(candidate, window2, held, error) {
462
+ const { track, words, text, finalLine, floor } = candidate;
463
+ const quoted = quote(text, 60);
464
+ const wordLabel = `${words} word${words === 1 ? "" : "s"}`;
465
+ const measured = `${seconds(held)} (\xB1${Math.max(0.01, error).toFixed(2)} s)`;
466
+ const target = lineTargetSec(words);
467
+ 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.`;
468
+ const firstSeen = track.seen.get(candidate.firstIndex);
469
+ const rect = firstSeen?.rect;
470
+ return {
471
+ code: "line_unread",
472
+ severity: "warning",
473
+ message,
474
+ text,
475
+ selector: track.selector,
476
+ dataAttributes: {},
477
+ sourceFile: track.sourceFile,
478
+ bbox: rect ? { x: rect.left, y: rect.top, width: rect.right - rect.left, height: rect.bottom - rect.top } : ZERO_BBOX,
479
+ time: round(window2.startIn),
480
+ words,
481
+ seconds: round(held),
482
+ floorSeconds: round(floor)
483
+ };
484
+ }
485
+ function typeFloorPx(canvas) {
486
+ return Math.round(T.typeFloorFraction * Math.min(canvas.width, canvas.height));
487
+ }
488
+ function detectTextBelowFloor(frames, duration, canvas) {
489
+ const floorPx = typeFloorPx(canvas);
490
+ const step = sampleStep(frames);
491
+ const sightings = /* @__PURE__ */ new Map();
492
+ frames.forEach((frame, index) => {
493
+ for (const part of frame.parts) {
494
+ if (part.captions || part.opacity < T.readOpacity) continue;
495
+ if (part.fontPx >= floorPx - 0.5 || readingWords(part.text) === 0) continue;
496
+ const seen = sightings.get(part.key) ?? /* @__PURE__ */ new Map();
497
+ seen.set(index, part);
498
+ sightings.set(part.key, seen);
499
+ }
500
+ });
501
+ const small = [];
502
+ for (const seen of sightings.values()) {
503
+ const [first, last] = longestRun(indexRuns([...seen.keys()]));
504
+ const start = frames[first]?.time ?? 0;
505
+ const end = last === frames.length - 1 ? duration : (frames[last]?.time ?? start) + step;
506
+ if (end - start < T.typeFloorHoldSec) continue;
507
+ const parts = [...seen.values()];
508
+ const part = parts[0];
509
+ if (!part) continue;
510
+ small.push({
511
+ selector: part.selector,
512
+ sourceFile: part.sourceFile,
513
+ text: part.text,
514
+ fontPx: Math.min(...parts.map((entry) => entry.fontPx)),
515
+ seconds: end - start,
516
+ time: start,
517
+ bbox: {
518
+ x: part.rect.left,
519
+ y: part.rect.top,
520
+ width: part.rect.width,
521
+ height: part.rect.height
522
+ }
523
+ });
524
+ }
525
+ const shortSide = Math.min(canvas.width, canvas.height);
526
+ return groupBySourceFile(small).map((group) => smallTextFinding(group, floorPx, shortSide));
527
+ }
528
+ function longestRun(runs) {
529
+ return runs.reduce((best, run) => run[1] - run[0] > best[1] - best[0] ? run : best, [0, -1]);
530
+ }
531
+ function groupBySourceFile(small) {
532
+ const groups = /* @__PURE__ */ new Map();
533
+ for (const entry of small)
534
+ groups.set(entry.sourceFile, [...groups.get(entry.sourceFile) ?? [], entry]);
535
+ return [...groups.values()].map(
536
+ (group) => group.sort((a, b) => a.fontPx - b.fontPx || a.time - b.time)
537
+ );
538
+ }
539
+ function quote(text, max) {
540
+ return `"${text.length > max ? `${text.slice(0, max - 3)}...` : text}"`;
541
+ }
542
+ function smallTextFinding(group, floorPx, shortSide) {
543
+ const [smallest] = group;
544
+ if (!smallest) throw new Error("text_below_floor group is empty");
545
+ 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`;
546
+ const byTime = [...group].sort((a, b) => a.time - b.time);
547
+ return {
548
+ code: "text_below_floor",
549
+ severity: "warning",
550
+ 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.`,
551
+ text: smallest.text,
552
+ selector: smallest.selector,
553
+ dataAttributes: {},
554
+ sourceFile: smallest.sourceFile,
555
+ bbox: smallest.bbox,
556
+ time: round(smallest.time),
557
+ times: byTime.map((entry) => round(entry.time)),
558
+ fontPx: round(smallest.fontPx),
559
+ floorPx,
560
+ seconds: round(smallest.seconds),
561
+ elements: group.map((entry) => ({
562
+ selector: entry.selector,
563
+ text: entry.text,
564
+ fontPx: round(entry.fontPx),
565
+ time: round(entry.time),
566
+ seconds: round(entry.seconds)
567
+ }))
568
+ };
569
+ }
570
+ function round(value) {
571
+ return Math.round(value * 1e3) / 1e3;
572
+ }
573
+
204
574
  // src/utils/hdrPromotion.ts
205
575
  async function bundleProjectHtml(projectDir) {
206
- const { bundleToSingleHtml } = await import("./compiler-Q3N6QXMT.js");
576
+ const { bundleToSingleHtml } = await import("./compiler-KPHYGFXL.js");
207
577
  return bundleToSingleHtml(projectDir);
208
578
  }
209
579
  async function collectBundledRenderMedia(html) {
@@ -279,7 +649,7 @@ function parseColorRGBA(color) {
279
649
  // src/utils/checkPipeline.ts
280
650
  var MOTION_FPS = 20;
281
651
  var MOTION_MAX_SAMPLES = 300;
282
- var ZERO_BBOX = { x: 0, y: 0, width: 0, height: 0 };
652
+ var ZERO_BBOX2 = { x: 0, y: 0, width: 0, height: 0 };
283
653
  var FRAME_BREACH_FLOOR_PX = 120;
284
654
  var FRAME_BREACH_FLOOR_FRACTION = 0.06;
285
655
  var DEFAULT_CHECK_OPTIONS = {
@@ -518,7 +888,8 @@ function emptyGridSamples() {
518
888
  contrastMs: 0,
519
889
  layoutStateSignatures: [],
520
890
  rotationSamples: [],
521
- indicatorFrames: []
891
+ indicatorFrames: [],
892
+ craftFrames: []
522
893
  };
523
894
  }
524
895
  function appendGridSamples(into, from) {
@@ -530,6 +901,7 @@ function appendGridSamples(into, from) {
530
901
  into.layoutStateSignatures.push(...from.layoutStateSignatures);
531
902
  into.rotationSamples.push(...from.rotationSamples);
532
903
  into.indicatorFrames.push(...from.indicatorFrames);
904
+ into.craftFrames.push(...from.craftFrames);
533
905
  }
534
906
  async function collectSampleAt(driver, options, grid, motion, sets, time) {
535
907
  const collected = emptyGridSamples();
@@ -605,9 +977,18 @@ async function collectGridSamples(driver, options, grid, motion, helpers) {
605
977
  driver.markSamples?.("end");
606
978
  const collected = emptyGridSamples();
607
979
  for (const samples of perTime) appendGridSamples(collected, samples);
608
- await collectMotionOverlapSamples(driver, grid, collected, options.range);
980
+ await collectMotionOverlapSamples(
981
+ driver,
982
+ grid,
983
+ collected,
984
+ options.range,
985
+ craftEnabled(driver, options)
986
+ );
609
987
  return collected;
610
988
  }
989
+ function craftEnabled(driver, options) {
990
+ return !options.range && typeof driver.collectCraftFrame === "function";
991
+ }
611
992
  async function collectContrastAt(driver, options, time, issuesAtTime, collected) {
612
993
  const contrastStart = Date.now();
613
994
  const capture = options.snapshots ? await driver.collectContrast(time, annotationBoxesFrom(issuesAtTime)) : await driver.collectContrast(time);
@@ -683,9 +1064,16 @@ async function denseOverlapTimes(driver, grid, range) {
683
1064
  const overlapTimes = buildOverlapSampleTimes(range ? range[1] - range[0] : grid.duration, edges);
684
1065
  return range ? mergeSampleTimes(overlapTimes.map((time) => time + range[0])) : overlapTimes;
685
1066
  }
686
- async function collectMotionOverlapSamples(driver, grid, collected, range) {
1067
+ async function collectMotionOverlapSamples(driver, grid, collected, range, craft) {
687
1068
  const baseTimes = new Set(grid.layoutSamples);
688
1069
  const shiftedTimes = await denseOverlapTimes(driver, grid, range);
1070
+ if (craft) {
1071
+ for (const time of buildCraftSampleTimes(grid.duration)) {
1072
+ if (time >= grid.duration) continue;
1073
+ await driver.seekGeometry(time);
1074
+ collected.craftFrames.push(...await collectCraftFrame(driver, time));
1075
+ }
1076
+ }
689
1077
  const probeHold = holdProber(driver, collected, range ? range[1] : grid.duration);
690
1078
  const gridIssues = await driver.collectOverlapGrid(shiftedTimes.filter((t) => !baseTimes.has(t)));
691
1079
  let sample = 0;
@@ -696,6 +1084,22 @@ async function collectMotionOverlapSamples(driver, grid, collected, range) {
696
1084
  await probeHold(time, shiftedTimes[index + 1] ?? Number.POSITIVE_INFINITY, issues);
697
1085
  }
698
1086
  }
1087
+ var CRAFT_SAMPLE_FPS = 8;
1088
+ var CRAFT_MAX_SAMPLES = 600;
1089
+ function buildCraftSampleTimes(duration) {
1090
+ if (!Number.isFinite(duration) || duration <= 0) return [];
1091
+ const count = Math.min(
1092
+ CRAFT_MAX_SAMPLES,
1093
+ Math.max(2, Math.ceil(duration * CRAFT_SAMPLE_FPS) + 1)
1094
+ );
1095
+ const step = duration / (count - 1);
1096
+ return mergeSampleTimes(
1097
+ Array.from({ length: count }, (_, index) => Math.round(index * step * 1e3) / 1e3)
1098
+ );
1099
+ }
1100
+ async function collectCraftFrame(driver, time) {
1101
+ return driver.collectCraftFrame ? [await driver.collectCraftFrame(time)] : [];
1102
+ }
699
1103
  var SWEEP_STATIC_MIN_DURATION_SEC = 3;
700
1104
  var ZERO_LAYOUT_RECT = {
701
1105
  left: 0,
@@ -797,7 +1201,7 @@ function sweepStaticIssue(kind) {
797
1201
  selector: "[data-composition-id]",
798
1202
  dataAttributes: {},
799
1203
  sourceFile: "index.html",
800
- bbox: ZERO_BBOX,
1204
+ bbox: ZERO_BBOX2,
801
1205
  rect: ZERO_LAYOUT_RECT,
802
1206
  message: SWEEP_STATIC_MESSAGES[kind],
803
1207
  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,6 +1535,14 @@ function detectOffPivotRotation(frames) {
1131
1535
  function annotationBoxesFrom(issues) {
1132
1536
  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
1537
  }
1538
+ function wholeCompositionKeepsMoving(assertions) {
1539
+ return assertions.some(
1540
+ (assertion) => assertion.kind === "keepsMoving" && assertion.withinSelector === void 0
1541
+ );
1542
+ }
1543
+ function disabledCraft() {
1544
+ return { enabled: false, step: 0, samples: 0, findings: [] };
1545
+ }
1134
1546
  async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([])) {
1135
1547
  await driver.initialize(options.contrast);
1136
1548
  const grid = await buildSampleGrid(driver, options);
@@ -1145,23 +1557,19 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1145
1557
  let motionIssues = plan.preflightIssues;
1146
1558
  if (motion.kind === "valid" && plan.assertions.length > 0 && collected.motionFrames.length > 0) {
1147
1559
  const canvas = await driver.getCanvas();
1148
- let evaluated = evaluateMotion(collected.motionFrames, plan.assertions, canvas);
1560
+ let evaluated = evaluateMotion(collected.motionFrames, plan.assertions, canvas, grid.duration);
1149
1561
  if (evaluated.some((issue) => issue.code === "motion_frozen")) {
1150
1562
  const frames = await withFrameMotion(driver, collected.motionFrames, plan.assertions);
1151
- evaluated = evaluateMotion(frames, plan.assertions, canvas);
1563
+ evaluated = evaluateMotion(frames, plan.assertions, canvas, grid.duration);
1152
1564
  }
1153
1565
  motionIssues = [...motionIssues, ...await driver.anchorMotionIssues(evaluated)];
1154
1566
  }
1155
1567
  const userPicked = new Set(grid.userPickedSamples);
1568
+ const noTimeline = await driver.hasNoTimelineDeclaration();
1156
1569
  const sweepSamples = collected.layoutStateSignatures.filter(
1157
1570
  (sample) => !userPicked.has(sample.time)
1158
1571
  );
1159
- const sweepVerdict = options.range ? [] : detectSweepStatic(
1160
- grid.duration,
1161
- sweepSamples,
1162
- motionIssues,
1163
- await driver.hasNoTimelineDeclaration()
1164
- );
1572
+ const sweepVerdict = options.range ? [] : detectSweepStatic(grid.duration, sweepSamples, motionIssues, noTimeline);
1165
1573
  const sweepFindings = sweepVerdict.length > 0 && await framesMoved(
1166
1574
  driver,
1167
1575
  sweepSamples.map((sample) => sample.time)
@@ -1172,6 +1580,20 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1172
1580
  );
1173
1581
  const offPivotFindings = detectOffPivotRotation(collected.indicatorFrames);
1174
1582
  const contrast = buildContrastResults(collected.contrastEntries);
1583
+ const craft = craftEnabled(driver, options) ? await auditCraft(
1584
+ {
1585
+ frames: collected.craftFrames,
1586
+ duration: grid.duration,
1587
+ canvas: await driver.getCanvas(),
1588
+ soundSources: driver.collectCraftFilm ? (await driver.collectCraftFilm()).soundSources : null,
1589
+ stillnessJudgedElsewhere: noTimeline || sweepFindings.length > 0 || wholeCompositionKeepsMoving(plan.assertions)
1590
+ },
1591
+ async (time) => {
1592
+ await driver.seekGeometry(time);
1593
+ if (!driver.collectCraftFrame) throw new Error("craft sampling unavailable");
1594
+ return driver.collectCraftFrame(time);
1595
+ }
1596
+ ) : disabledCraft();
1175
1597
  if (options.components?.length) {
1176
1598
  if (!driver.matchComponents)
1177
1599
  throw new Error("Component filtering unavailable in this check driver");
@@ -1181,7 +1603,8 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1181
1603
  ...rotationFindings,
1182
1604
  ...offPivotFindings,
1183
1605
  ...motionIssues,
1184
- ...contrast.findings
1606
+ ...contrast.findings,
1607
+ ...craft.findings
1185
1608
  ];
1186
1609
  const matches = await driver.matchComponents(options.components, findings);
1187
1610
  findings.forEach((finding, i) => {
@@ -1206,6 +1629,7 @@ async function runAuditGrid(driver, options, motion, helpers = Promise.resolve([
1206
1629
  contrastFindings: contrast.findings,
1207
1630
  contrastChecked: collected.contrastEntries.length,
1208
1631
  contrastPassed: contrast.passed,
1632
+ craft,
1209
1633
  screenshots: collected.screenshots,
1210
1634
  timings: { launchSettleMs: 0, seekLoopMs, contrastMs: collected.contrastMs },
1211
1635
  skipped: false
@@ -1443,7 +1867,7 @@ function buildLintSection(result) {
1443
1867
  selector: finding.selector ?? (finding.elementId ? `#${finding.elementId}` : "[data-composition-id]"),
1444
1868
  dataAttributes: {},
1445
1869
  sourceFile: finding.file ?? file,
1446
- bbox: ZERO_BBOX,
1870
+ bbox: ZERO_BBOX2,
1447
1871
  time: 0,
1448
1872
  fixHint: finding.fixHint
1449
1873
  }))
@@ -1458,10 +1882,12 @@ function buildReport(options, lint, browser, motion, extraMotionFindings, snapsh
1458
1882
  const runtime = section(browser.runtimeFindings);
1459
1883
  const motionSection = section(motionFindings);
1460
1884
  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;
1885
+ const craftSection = section(browser.craft.findings);
1886
+ const warningCount = lint.warningCount + runtime.warningCount + layout.warningCount + motionSection.warningCount + contrastSection.warningCount + craftSection.warningCount;
1887
+ const errorCount = lint.errorCount + runtime.errorCount + layout.errorCount + motionSection.errorCount + contrastSection.errorCount + craftSection.errorCount;
1888
+ const strictWarningCount = warningCount - craftSection.warningCount;
1463
1889
  const report = {
1464
- ok: errorCount === 0 && (!options.strict || warningCount === 0),
1890
+ ok: errorCount === 0 && (!options.strict || strictWarningCount === 0),
1465
1891
  strict: options.strict,
1466
1892
  browserSkipped: browser.skipped,
1467
1893
  lint,
@@ -1480,6 +1906,12 @@ function buildReport(options, lint, browser, motion, extraMotionFindings, snapsh
1480
1906
  checked: browser.contrastChecked,
1481
1907
  passed: browser.contrastPassed
1482
1908
  },
1909
+ craft: {
1910
+ ...craftSection,
1911
+ enabled: browser.craft.enabled,
1912
+ step: browser.craft.step,
1913
+ samples: browser.craft.samples
1914
+ },
1483
1915
  hdr: { autoPromotion: hdrPromotion, inspection: hdrInspection },
1484
1916
  snapshots: {
1485
1917
  enabled: options.snapshots,
@@ -1504,6 +1936,7 @@ function buildReport(options, lint, browser, motion, extraMotionFindings, snapsh
1504
1936
  motionWarnings: motionSection.warningCount,
1505
1937
  contrastErrors: contrastSection.errorCount,
1506
1938
  contrastWarnings: contrastSection.warningCount,
1939
+ craftWarnings: craftSection.warningCount,
1507
1940
  launchSettleMs: browser.timings.launchSettleMs,
1508
1941
  seekLoopMs: browser.timings.seekLoopMs,
1509
1942
  contrastMs: browser.timings.contrastMs,
@@ -1525,11 +1958,11 @@ function filterComponentReport(report, options) {
1525
1958
  notes: [
1526
1959
  "Static lint and unscoped runtime failures remain project-wide.",
1527
1960
  ...options.range ? [
1528
- "Whole-timeline motion assertions and frozen-sweep detection are skipped for range checks."
1961
+ "Whole-timeline motion assertions, frozen-sweep detection and craft warnings are skipped for range checks."
1529
1962
  ] : []
1530
1963
  ]
1531
1964
  };
1532
- for (const group of [report.layout, report.motion, report.contrast]) {
1965
+ for (const group of [report.layout, report.motion, report.contrast, report.craft]) {
1533
1966
  const before = group.findings.length;
1534
1967
  group.findings = group.findings.filter((f) => f.componentMatch !== false);
1535
1968
  report.scope.hiddenFindings += before - group.findings.length;
@@ -1612,6 +2045,7 @@ function emptyBrowserResult() {
1612
2045
  contrastFindings: [],
1613
2046
  contrastChecked: 0,
1614
2047
  contrastPassed: 0,
2048
+ craft: disabledCraft(),
1615
2049
  screenshots: [],
1616
2050
  timings: { launchSettleMs: 0, seekLoopMs: 0, contrastMs: 0 },
1617
2051
  skipped: true
@@ -1633,7 +2067,7 @@ function findingAtRoot(code, severity, message, sourceFile) {
1633
2067
  selector: "[data-composition-id]",
1634
2068
  dataAttributes: {},
1635
2069
  sourceFile,
1636
- bbox: ZERO_BBOX,
2070
+ bbox: ZERO_BBOX2,
1637
2071
  time: 0
1638
2072
  };
1639
2073
  }
@@ -1662,7 +2096,7 @@ function resolveMotionSpec(projectDir) {
1662
2096
  };
1663
2097
  }
1664
2098
  async function runBrowserCheck(project, options, motion, deadline, prelaunched) {
1665
- const module = await import("./checkBrowser-FNINXBMZ.js");
2099
+ const module = await import("./checkBrowser-5XZCBRXM.js");
1666
2100
  return module.runBrowserCheck(project, options, motion, runAuditGrid, deadline, prelaunched);
1667
2101
  }
1668
2102
  var adoptedBrowser;
@@ -1676,7 +2110,7 @@ async function prelaunchBrowser(project, options) {
1676
2110
  if (adopted) return adopted;
1677
2111
  const html = await readFile(project.indexPath, "utf8").catch(() => void 0);
1678
2112
  if (html === void 0) return void 0;
1679
- const { prelaunchCompositionBrowser } = await import("./captureCompositionFrame-4236FVWJ.js");
2113
+ const { prelaunchCompositionBrowser } = await import("./captureCompositionFrame-PXV2ISHD.js");
1680
2114
  return prelaunchCompositionBrowser(html, options.browserGpuMode);
1681
2115
  }
1682
2116
  async function writeSnapshot(projectDir, index, time, pngBase64) {
@@ -1688,7 +2122,7 @@ async function writeSnapshot(projectDir, index, time, pngBase64) {
1688
2122
  return relative(projectDir, path);
1689
2123
  }
1690
2124
  async function captureFindingCrops(project, options, requests, deadline) {
1691
- const module = await import("./checkBrowser-FNINXBMZ.js");
2125
+ const module = await import("./checkBrowser-5XZCBRXM.js");
1692
2126
  return module.captureFindingCrops(project, options, requests, deadline);
1693
2127
  }
1694
2128
  var DEFAULT_DEPENDENCIES2 = {
@@ -2134,6 +2568,7 @@ function printHumanReport(report) {
2134
2568
  printLayoutSection("Layout", report.layout);
2135
2569
  printSection("Motion", report.motion);
2136
2570
  printContrastSection(report);
2571
+ printCraftSection(report);
2137
2572
  printSnapshotSection(report);
2138
2573
  console.log();
2139
2574
  const label = report.ok ? c.success("Check passed") : c.error("Check failed");
@@ -2192,6 +2627,16 @@ function printContrastSection(report) {
2192
2627
  }
2193
2628
  printCounts(section2);
2194
2629
  }
2630
+ function printCraftSection(report) {
2631
+ const section2 = report.craft;
2632
+ if (!section2.enabled) {
2633
+ console.log();
2634
+ console.log(c.bold("Craft"));
2635
+ console.log(` ${c.dim("\u25C7")} skipped`);
2636
+ return;
2637
+ }
2638
+ printSection("Craft", section2);
2639
+ }
2195
2640
  function printSnapshotSection(report) {
2196
2641
  console.log();
2197
2642
  console.log(c.bold("Snapshots"));