@vfrey/vfrey 0.0.1 → 1.0.0-beta.1

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 (610) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +78 -3
  3. package/accounts.example.json +61 -0
  4. package/accounts.first-run.json +41 -0
  5. package/bin/vfrey.mjs +36 -0
  6. package/integration-tools/README.md +43 -0
  7. package/integration-tools/image/pillow.md +32 -0
  8. package/integration-tools/image/playwright.md +33 -0
  9. package/integration-tools/image/resvg.md +36 -0
  10. package/integration-tools/image/satori.md +36 -0
  11. package/integration-tools/image/sharp.md +38 -0
  12. package/integration-tools/video/blender.md +34 -0
  13. package/integration-tools/video/ffmpeg.md +41 -0
  14. package/integration-tools/video/manim.md +37 -0
  15. package/integration-tools/video/motion-canvas.md +37 -0
  16. package/integration-tools/video/remotion.md +50 -0
  17. package/integration-tools/video/revideo.md +32 -0
  18. package/package.json +74 -6
  19. package/skills/vfrey-orchestrator/SKILL.md +15 -0
  20. package/skills/vfrey-orchestrator/channel-video/SKILL.md +41 -0
  21. package/skills/vfrey-product/SKILL.md +63 -0
  22. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/cook-one.svg +14 -0
  23. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/cook-two.svg +22 -0
  24. package/skills/vfrey-product/examples/concurrency-vs-parallelism/framey/index.html +70 -0
  25. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/cook-one.svg +14 -0
  26. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/cook-two.svg +22 -0
  27. package/skills/vfrey-product/examples/concurrency-vs-parallelism/remotion/index.tsx +49 -0
  28. package/skills/vfrey-product/examples/concurrency-vs-parallelism/script.json +15 -0
  29. package/skills/vfrey-product/examples/octopus-facts/index.html +60 -0
  30. package/skills/vfrey-product/examples/octopus-facts/octopus.svg +8 -0
  31. package/skills/vfrey-product/examples/octopus-facts/script.json +14 -0
  32. package/skills/vfrey-product/push/SKILL.md +15 -0
  33. package/skills/vfrey-product/scenes/NOTICE +5 -0
  34. package/skills/vfrey-product/scenes/blocks.md +57 -0
  35. package/skills/vfrey-product/scenes/craft.md +118 -0
  36. package/skills/vfrey-product/scenes/motion.md +88 -0
  37. package/src/analytics/dashboard.ts +109 -0
  38. package/src/analytics/index.ts +260 -0
  39. package/src/api/client.ts +361 -0
  40. package/src/api/cloud-files.ts +197 -0
  41. package/src/api/cloud-runs.ts +75 -0
  42. package/src/api/cloud.ts +413 -0
  43. package/src/api/commands.ts +330 -0
  44. package/src/api/config.ts +34 -0
  45. package/src/api/creators.ts +463 -0
  46. package/src/api/credentials.ts +152 -0
  47. package/src/api/mail.ts +333 -0
  48. package/src/api/topics.ts +207 -0
  49. package/src/api/types.ts +273 -0
  50. package/src/cli.ts +468 -0
  51. package/src/cloud/bundle.ts +70 -0
  52. package/src/cloud/cloudrun-executor.ts +237 -0
  53. package/src/cloud/executor.ts +281 -0
  54. package/src/cloud/gcs-sign.ts +76 -0
  55. package/src/cloud/job.ts +106 -0
  56. package/src/cloud/remote-job.ts +67 -0
  57. package/src/cloud/render-job.ts +191 -0
  58. package/src/config.ts +309 -0
  59. package/src/dashboard-link.ts +180 -0
  60. package/src/dashboard-start.ts +103 -0
  61. package/src/desk/channel.ts +64 -0
  62. package/src/desk/cli.ts +216 -0
  63. package/src/desk/creators-route.ts +129 -0
  64. package/src/desk/fonts/JetBrainsMono-OFL.txt +93 -0
  65. package/src/desk/fonts/google-sans-flex-latin.woff2 +0 -0
  66. package/src/desk/fonts/jetbrains-mono-medium.woff2 +0 -0
  67. package/src/desk/http.ts +460 -0
  68. package/src/desk/mail-route.ts +103 -0
  69. package/src/desk/overlay.ts +112 -0
  70. package/src/desk/preview.ts +422 -0
  71. package/src/desk/screens.ts +149 -0
  72. package/src/desk/secrets.ts +143 -0
  73. package/src/desk/series.ts +127 -0
  74. package/src/desk/state.ts +77 -0
  75. package/src/desk/studio-route.ts +119 -0
  76. package/src/desk/tick-runner.ts +66 -0
  77. package/src/desk/tick.ts +56 -0
  78. package/src/desk/topics-route.ts +41 -0
  79. package/src/desk/ui/app.css +505 -0
  80. package/src/desk/ui/app.js +185 -0
  81. package/src/desk/ui/apple-icon.png +0 -0
  82. package/src/desk/ui/components.js +79 -0
  83. package/src/desk/ui/core.js +156 -0
  84. package/src/desk/ui/favicon.ico +0 -0
  85. package/src/desk/ui/icon.svg +1 -0
  86. package/src/desk/ui/icons.js +49 -0
  87. package/src/desk/ui/index.html +41 -0
  88. package/src/desk/ui/metrics-math.d.ts +22 -0
  89. package/src/desk/ui/metrics-math.js +135 -0
  90. package/src/desk/ui/theme.js +5 -0
  91. package/src/desk/ui/views-creators.js +209 -0
  92. package/src/desk/ui/views-keys.js +114 -0
  93. package/src/desk/ui/views-mail.js +188 -0
  94. package/src/desk/ui/views-misc.js +123 -0
  95. package/src/desk/ui/views-review.js +119 -0
  96. package/src/desk/ui/views-runs.js +350 -0
  97. package/src/desk/ui/views-screens.js +163 -0
  98. package/src/desk/ui/views-series.js +318 -0
  99. package/src/desk/ui/views-topics.js +87 -0
  100. package/src/desk/verbs.ts +361 -0
  101. package/src/doctor.ts +212 -0
  102. package/src/drain.ts +14 -0
  103. package/src/engage/index.ts +217 -0
  104. package/src/generate/index.ts +110 -0
  105. package/src/generate/script.ts +152 -0
  106. package/src/generate/title.ts +78 -0
  107. package/src/help.ts +252 -0
  108. package/src/home.ts +45 -0
  109. package/src/llm/client.ts +177 -0
  110. package/src/log.ts +7 -0
  111. package/src/oauth/tokens.ts +189 -0
  112. package/src/oauth/vault.ts +72 -0
  113. package/src/pipeline/review.ts +642 -0
  114. package/src/pipeline/run.ts +443 -0
  115. package/src/pipeline/series-guard.ts +26 -0
  116. package/src/pipeline/source-fetch.ts +69 -0
  117. package/src/pipeline/stages.ts +728 -0
  118. package/src/pipeline/topics-source.ts +90 -0
  119. package/src/product/commands.ts +296 -0
  120. package/src/product/config-file.ts +38 -0
  121. package/src/product/engine-choice.ts +89 -0
  122. package/src/product/engines.ts +103 -0
  123. package/src/product/insights.ts +50 -0
  124. package/src/product/keys.ts +67 -0
  125. package/src/product/paths.ts +18 -0
  126. package/src/product/probes.ts +88 -0
  127. package/src/product/push-flow.ts +90 -0
  128. package/src/product/render-video.ts +21 -0
  129. package/src/product/short.ts +62 -0
  130. package/src/product/update.ts +32 -0
  131. package/src/project/canonical.ts +14 -0
  132. package/src/project/commands.ts +177 -0
  133. package/src/project/dashboard-status.ts +28 -0
  134. package/src/project/discover.ts +19 -0
  135. package/src/project/index-file.ts +73 -0
  136. package/src/project/marker.ts +92 -0
  137. package/src/project/migrate.ts +201 -0
  138. package/src/project/names.ts +27 -0
  139. package/src/project/notice.ts +16 -0
  140. package/src/project/open.ts +88 -0
  141. package/src/project/scaffold.ts +112 -0
  142. package/src/project/templates.ts +42 -0
  143. package/src/project/videos.ts +64 -0
  144. package/src/publish/facebook.ts +91 -0
  145. package/src/publish/index.ts +12 -0
  146. package/src/publish/instagram.ts +97 -0
  147. package/src/publish/rate.ts +62 -0
  148. package/src/publish/session.ts +242 -0
  149. package/src/publish/tiktok.ts +202 -0
  150. package/src/publish/youtube.ts +177 -0
  151. package/src/queue/desk-ops.ts +1170 -0
  152. package/src/queue/seal.ts +3 -0
  153. package/src/queue/store.ts +1006 -0
  154. package/src/remotion/AiLabel.tsx +26 -0
  155. package/src/remotion/Root.tsx +73 -0
  156. package/src/remotion/defaults.ts +26 -0
  157. package/src/remotion/films/claude/ClaudeFilm.tsx +1014 -0
  158. package/src/remotion/films/engine/EngineMark.tsx +17 -0
  159. package/src/remotion/films/rea/ReaShort.tsx +552 -0
  160. package/src/remotion/films/rea/drawings.tsx +907 -0
  161. package/src/remotion/films/rea/timing.ts +144 -0
  162. package/src/remotion/index.ts +4 -0
  163. package/src/remotion/templates/EditorialSplit.tsx +39 -0
  164. package/src/remotion/templates/KineticType.tsx +39 -0
  165. package/src/remotion/templates/SignalBoard.tsx +50 -0
  166. package/src/remotion/timing.ts +22 -0
  167. package/src/render/chrome.ts +78 -0
  168. package/src/render/engine-mark.ts +29 -0
  169. package/src/render/framey-template.ts +130 -0
  170. package/src/render/html-engine.ts +149 -0
  171. package/src/render/node-crypto-stub.ts +11 -0
  172. package/src/render/probe.ts +29 -0
  173. package/src/render/props.ts +17 -0
  174. package/src/render/vertical-short.ts +35 -0
  175. package/src/render/webpack.ts +33 -0
  176. package/src/render/worker.ts +65 -0
  177. package/src/scene/assets/fonts/TitanOne-OFL.txt +94 -0
  178. package/src/scene/assets/fonts/titan-one.woff2 +0 -0
  179. package/src/scene/assets/gsap/LICENSE.txt +8 -0
  180. package/src/scene/assets/gsap/gsap.min.js +11 -0
  181. package/src/scene/audio.ts +54 -0
  182. package/src/scene/blocks/LICENSE +190 -0
  183. package/src/scene/blocks/NOTICE +5 -0
  184. package/src/scene/blocks/bar-chart-race/bar-chart-race.html +585 -0
  185. package/src/scene/blocks/beat-freeze-cut/beat-freeze-cut.html +874 -0
  186. package/src/scene/blocks/camcorder-hud/camcorder-hud.html +164 -0
  187. package/src/scene/blocks/camera-dolly-zoom/camera-dolly-zoom.html +355 -0
  188. package/src/scene/blocks/code-diff/code-diff.html +817 -0
  189. package/src/scene/blocks/code-snippet-apple-terminal-pro/code-snippet-apple-terminal-pro.html +248 -0
  190. package/src/scene/blocks/code-typing/code-typing.html +764 -0
  191. package/src/scene/blocks/data-chart/data-chart.html +452 -0
  192. package/src/scene/blocks/flowchart-vertical/flowchart-vertical.html +454 -0
  193. package/src/scene/blocks/hw-scribble-transition/hw-scribble-transition.html +153 -0
  194. package/src/scene/blocks/index.json +824 -0
  195. package/src/scene/blocks/lt-accent-underline/lt-accent-underline.html +107 -0
  196. package/src/scene/blocks/lt-bold-block/lt-bold-block.html +109 -0
  197. package/src/scene/blocks/lt-clean-bar/lt-clean-bar.html +112 -0
  198. package/src/scene/blocks/lt-dark-card/lt-dark-card.html +111 -0
  199. package/src/scene/blocks/lt-kicker-name/lt-kicker-name.html +114 -0
  200. package/src/scene/blocks/lt-mask-reveal/lt-mask-reveal.html +120 -0
  201. package/src/scene/blocks/lt-neon-border/lt-neon-border.html +391 -0
  202. package/src/scene/blocks/lt-stack-bars/lt-stack-bars.html +109 -0
  203. package/src/scene/blocks/macos-notification/macos-notification.html +194 -0
  204. package/src/scene/blocks/mk-background/mk-background.html +236 -0
  205. package/src/scene/blocks/mk-callout-highlight/mk-callout-highlight.html +183 -0
  206. package/src/scene/blocks/mk-clone-wall-transition/mk-clone-wall-transition.html +226 -0
  207. package/src/scene/blocks/mk-line-graph/mk-line-graph.html +293 -0
  208. package/src/scene/blocks/mk-progress-stat/mk-progress-stat.html +186 -0
  209. package/src/scene/blocks/mk-specs-list/mk-specs-list.html +223 -0
  210. package/src/scene/blocks/news-ticker/news-ticker.html +409 -0
  211. package/src/scene/blocks/organic-light-leak-overlay/organic-light-leak-overlay.html +126 -0
  212. package/src/scene/blocks/oscilloscope-trace/oscilloscope-trace.html +519 -0
  213. package/src/scene/blocks/snow/snow.html +205 -0
  214. package/src/scene/blocks/split-flap-board/split-flap-board.html +347 -0
  215. package/src/scene/blocks/spotify-card/spotify-card.html +294 -0
  216. package/src/scene/blocks/starfield/starfield.html +188 -0
  217. package/src/scene/blocks/thread-message-stack/thread-message-stack.html +239 -0
  218. package/src/scene/blocks/week-in-merges/week-in-merges.html +470 -0
  219. package/src/scene/blocks/x-post/x-post.html +437 -0
  220. package/src/scene/blocks/yt-comment-card/yt-comment-card.html +319 -0
  221. package/src/scene/blocks/yt-lcd-background/yt-lcd-background.html +307 -0
  222. package/src/scene/blocks/yt-prism-title/yt-prism-title.html +205 -0
  223. package/src/scene/blocks.ts +229 -0
  224. package/src/scene/command.ts +272 -0
  225. package/src/scene/figure.ts +181 -0
  226. package/src/scene/glyphs.ts +107 -0
  227. package/src/scene/init.ts +86 -0
  228. package/src/scene/inspect/css-tree.d.ts +6 -0
  229. package/src/scene/inspect/page-scripts.ts +272 -0
  230. package/src/scene/inspect/report.ts +405 -0
  231. package/src/scene/inspect/run.ts +200 -0
  232. package/src/scene/inspect/source.ts +236 -0
  233. package/src/scene/label.ts +131 -0
  234. package/src/scene/net-guard.ts +74 -0
  235. package/src/scene/render.ts +292 -0
  236. package/src/scene/runtime/browser.ts +199 -0
  237. package/src/scene/runtime/core.ts +181 -0
  238. package/src/scene/runtime/react.tsx +115 -0
  239. package/src/scene/runtime/transitions.ts +133 -0
  240. package/src/scene/sanitize.ts +181 -0
  241. package/src/scene/scene.ts +152 -0
  242. package/src/scene/studio-command.ts +48 -0
  243. package/src/scene/studio-skin.ts +59 -0
  244. package/src/scene/studio.ts +337 -0
  245. package/src/scene/supply.ts +111 -0
  246. package/src/scene/timing.ts +288 -0
  247. package/src/scene/transitions/LICENSE +190 -0
  248. package/src/scene/transitions/NOTICE +5 -0
  249. package/src/scene/transitions/SOURCE.json +24 -0
  250. package/src/scene/transitions/transitions.global.js +38 -0
  251. package/src/scene/transitions.ts +26 -0
  252. package/src/service/all-projects.ts +153 -0
  253. package/src/service/commands.ts +256 -0
  254. package/src/service/due.ts +82 -0
  255. package/src/service/lock.ts +101 -0
  256. package/src/service/log-file.ts +56 -0
  257. package/src/service/state.ts +41 -0
  258. package/src/service/units.ts +90 -0
  259. package/src/service/worker.ts +51 -0
  260. package/src/skill-agents.ts +74 -0
  261. package/src/skill-install.ts +334 -0
  262. package/src/sync-write.ts +21 -0
  263. package/src/tick-report.ts +205 -0
  264. package/src/tts.ts +124 -0
  265. package/vendor/@vfrey/contracts/dist/account.d.ts +97 -0
  266. package/vendor/@vfrey/contracts/dist/account.js +27 -0
  267. package/vendor/@vfrey/contracts/dist/checks.d.ts +8 -0
  268. package/vendor/@vfrey/contracts/dist/checks.js +1 -0
  269. package/vendor/@vfrey/contracts/dist/credentials/crypto.d.ts +4 -0
  270. package/vendor/@vfrey/contracts/dist/credentials/crypto.js +38 -0
  271. package/vendor/@vfrey/contracts/dist/domain/advice-persona.d.ts +10 -0
  272. package/vendor/@vfrey/contracts/dist/domain/advice-persona.js +24 -0
  273. package/vendor/@vfrey/contracts/dist/domain/backoff.d.ts +13 -0
  274. package/vendor/@vfrey/contracts/dist/domain/backoff.js +27 -0
  275. package/vendor/@vfrey/contracts/dist/domain/cadence.d.ts +29 -0
  276. package/vendor/@vfrey/contracts/dist/domain/cadence.js +95 -0
  277. package/vendor/@vfrey/contracts/dist/domain/creators.d.ts +146 -0
  278. package/vendor/@vfrey/contracts/dist/domain/creators.js +2 -0
  279. package/vendor/@vfrey/contracts/dist/domain/disclosure.d.ts +127 -0
  280. package/vendor/@vfrey/contracts/dist/domain/disclosure.js +250 -0
  281. package/vendor/@vfrey/contracts/dist/domain/errors.d.ts +34 -0
  282. package/vendor/@vfrey/contracts/dist/domain/errors.js +68 -0
  283. package/vendor/@vfrey/contracts/dist/domain/redact.d.ts +1 -0
  284. package/vendor/@vfrey/contracts/dist/domain/redact.js +21 -0
  285. package/vendor/@vfrey/contracts/dist/domain/revenue.d.ts +13 -0
  286. package/vendor/@vfrey/contracts/dist/domain/revenue.js +16 -0
  287. package/vendor/@vfrey/contracts/dist/domain/safety.d.ts +20 -0
  288. package/vendor/@vfrey/contracts/dist/domain/safety.js +61 -0
  289. package/vendor/@vfrey/contracts/dist/domain/similarity.d.ts +13 -0
  290. package/vendor/@vfrey/contracts/dist/domain/similarity.js +100 -0
  291. package/vendor/@vfrey/contracts/dist/domain/templates.d.ts +18 -0
  292. package/vendor/@vfrey/contracts/dist/domain/templates.js +67 -0
  293. package/vendor/@vfrey/contracts/dist/domain/tiktok-chunks.d.ts +19 -0
  294. package/vendor/@vfrey/contracts/dist/domain/tiktok-chunks.js +52 -0
  295. package/vendor/@vfrey/contracts/dist/domain/topics.d.ts +78 -0
  296. package/vendor/@vfrey/contracts/dist/domain/topics.js +4 -0
  297. package/vendor/@vfrey/contracts/dist/domain/types.d.ts +216 -0
  298. package/vendor/@vfrey/contracts/dist/domain/types.js +1 -0
  299. package/vendor/@vfrey/contracts/dist/domain/variation.d.ts +57 -0
  300. package/vendor/@vfrey/contracts/dist/domain/variation.js +278 -0
  301. package/vendor/@vfrey/contracts/dist/events.d.ts +20 -0
  302. package/vendor/@vfrey/contracts/dist/events.js +1 -0
  303. package/vendor/@vfrey/contracts/dist/http.d.ts +11 -0
  304. package/vendor/@vfrey/contracts/dist/http.js +37 -0
  305. package/vendor/@vfrey/contracts/dist/index.d.ts +22 -0
  306. package/vendor/@vfrey/contracts/dist/index.js +22 -0
  307. package/vendor/@vfrey/contracts/dist/log.d.ts +2 -0
  308. package/vendor/@vfrey/contracts/dist/log.js +10 -0
  309. package/vendor/@vfrey/contracts/dist/mail.d.ts +55 -0
  310. package/vendor/@vfrey/contracts/dist/mail.js +1 -0
  311. package/vendor/@vfrey/contracts/package.json +18 -0
  312. package/vendor/@vfrey/ingest/dist/index.d.ts +41 -0
  313. package/vendor/@vfrey/ingest/dist/index.js +221 -0
  314. package/vendor/@vfrey/ingest/dist/parse.d.ts +5 -0
  315. package/vendor/@vfrey/ingest/dist/parse.js +165 -0
  316. package/vendor/@vfrey/ingest/package.json +21 -0
  317. package/vendor/framey/LICENSE +190 -0
  318. package/vendor/framey/NOTICE +15 -0
  319. package/vendor/framey/SOURCE.json +24 -0
  320. package/vendor/framey/STUDIO-SOURCE.json +9 -0
  321. package/vendor/framey/bin/framey-localize-fonts.mjs +12 -0
  322. package/vendor/framey/bin/framey.mjs +16 -0
  323. package/vendor/framey/dist/add-VMJD5KBS.js +75 -0
  324. package/vendor/framey/dist/animatedGifPrep-QPKGJ6PM.js +43 -0
  325. package/vendor/framey/dist/api.d.ts +211 -0
  326. package/vendor/framey/dist/api.js +76 -0
  327. package/vendor/framey/dist/appHistory-WW56FZTT.js +31 -0
  328. package/vendor/framey/dist/asset-WQKGOELE.js +26 -0
  329. package/vendor/framey/dist/audio-RSJWVWRA.js +1936 -0
  330. package/vendor/framey/dist/batchRender-3HPICDCT.js +366 -0
  331. package/vendor/framey/dist/beats-HL2BDUZI.js +273 -0
  332. package/vendor/framey/dist/benchmark-RWCWHI5Z.js +230 -0
  333. package/vendor/framey/dist/browser-ECYET3Q2.js +206 -0
  334. package/vendor/framey/dist/bundleWithLocalizedFonts-ALYBQEQT.js +52 -0
  335. package/vendor/framey/dist/captureCompositionFrame-4DA6SEH2.js +94 -0
  336. package/vendor/framey/dist/catalog-5JVDEUWK.js +979 -0
  337. package/vendor/framey/dist/catch-up-NEBCL5NO.js +106 -0
  338. package/vendor/framey/dist/check-F5N544ML.js +111 -0
  339. package/vendor/framey/dist/checkBrowser-LZ66CMJG.js +110 -0
  340. package/vendor/framey/dist/chunk-2K7Z2HVP.js +372 -0
  341. package/vendor/framey/dist/chunk-2UZQHDM7.js +323 -0
  342. package/vendor/framey/dist/chunk-2X4PQEYM.js +34 -0
  343. package/vendor/framey/dist/chunk-3422KMTD.js +168 -0
  344. package/vendor/framey/dist/chunk-3FYD4YEK.js +72 -0
  345. package/vendor/framey/dist/chunk-3GXQPCJC.js +682 -0
  346. package/vendor/framey/dist/chunk-3LM6YPBR.js +179 -0
  347. package/vendor/framey/dist/chunk-442JNXRM.js +20 -0
  348. package/vendor/framey/dist/chunk-4BNN5FGX.js +182 -0
  349. package/vendor/framey/dist/chunk-4P7NX5BM.js +11532 -0
  350. package/vendor/framey/dist/chunk-4UMPIPCQ.js +88 -0
  351. package/vendor/framey/dist/chunk-4YYJOFKS.js +28 -0
  352. package/vendor/framey/dist/chunk-54HJ63Q2.js +29 -0
  353. package/vendor/framey/dist/chunk-5ETJX6WM.js +89 -0
  354. package/vendor/framey/dist/chunk-5SG54JRS.js +68 -0
  355. package/vendor/framey/dist/chunk-634HSJ3J.js +58 -0
  356. package/vendor/framey/dist/chunk-66LREXGS.js +48 -0
  357. package/vendor/framey/dist/chunk-6BEFEWFB.js +25 -0
  358. package/vendor/framey/dist/chunk-6BNTGNGD.js +286 -0
  359. package/vendor/framey/dist/chunk-6DDPOHMK.js +140 -0
  360. package/vendor/framey/dist/chunk-6GV5XSOR.js +214 -0
  361. package/vendor/framey/dist/chunk-6JR2XUEE.js +127 -0
  362. package/vendor/framey/dist/chunk-73QVATIM.js +362 -0
  363. package/vendor/framey/dist/chunk-7FMUTGOH.js +279 -0
  364. package/vendor/framey/dist/chunk-7JQFJ6JJ.js +291 -0
  365. package/vendor/framey/dist/chunk-AHPGAESX.js +113 -0
  366. package/vendor/framey/dist/chunk-AHX34EFP.js +15 -0
  367. package/vendor/framey/dist/chunk-AJ5CSAEZ.js +487 -0
  368. package/vendor/framey/dist/chunk-B7RJV74O.js +5047 -0
  369. package/vendor/framey/dist/chunk-BL4U6U52.js +254 -0
  370. package/vendor/framey/dist/chunk-BSQ7XANM.js +210 -0
  371. package/vendor/framey/dist/chunk-BZ56MTDX.js +6 -0
  372. package/vendor/framey/dist/chunk-C5BO7PMT.js +282 -0
  373. package/vendor/framey/dist/chunk-CFUCHO4T.js +358 -0
  374. package/vendor/framey/dist/chunk-CZGHFATT.js +31 -0
  375. package/vendor/framey/dist/chunk-DLA44CMS.js +5649 -0
  376. package/vendor/framey/dist/chunk-DPVXBVLL.js +31292 -0
  377. package/vendor/framey/dist/chunk-DQBY7FRR.js +397 -0
  378. package/vendor/framey/dist/chunk-EAMLBAHA.js +154 -0
  379. package/vendor/framey/dist/chunk-EOVYQ3IG.js +143 -0
  380. package/vendor/framey/dist/chunk-EVMY7IPL.js +612 -0
  381. package/vendor/framey/dist/chunk-FG4BBFZI.js +122 -0
  382. package/vendor/framey/dist/chunk-FI4I7CME.js +56 -0
  383. package/vendor/framey/dist/chunk-FLREUEHW.js +2081 -0
  384. package/vendor/framey/dist/chunk-FUFP7A7S.js +1126 -0
  385. package/vendor/framey/dist/chunk-FV3PIKGH.js +56 -0
  386. package/vendor/framey/dist/chunk-FXMKHHPO.js +123 -0
  387. package/vendor/framey/dist/chunk-GGZAM5VH.js +1187 -0
  388. package/vendor/framey/dist/chunk-GKZEVJIB.js +39 -0
  389. package/vendor/framey/dist/chunk-GMECXFAN.js +57 -0
  390. package/vendor/framey/dist/chunk-GNEFDLFB.js +621 -0
  391. package/vendor/framey/dist/chunk-GPMLSOEG.js +19274 -0
  392. package/vendor/framey/dist/chunk-GPYVT5EE.js +59 -0
  393. package/vendor/framey/dist/chunk-H6IEMZEV.js +40 -0
  394. package/vendor/framey/dist/chunk-HEFQCIXR.js +170 -0
  395. package/vendor/framey/dist/chunk-HFQ4CWHA.js +118 -0
  396. package/vendor/framey/dist/chunk-HPDTCOKE.js +304 -0
  397. package/vendor/framey/dist/chunk-HTUHQKDB.js +548 -0
  398. package/vendor/framey/dist/chunk-HU2SPFNG.js +103 -0
  399. package/vendor/framey/dist/chunk-HVW7ABXD.js +19 -0
  400. package/vendor/framey/dist/chunk-IG7NDKXO.js +26 -0
  401. package/vendor/framey/dist/chunk-II3J3WXK.js +246 -0
  402. package/vendor/framey/dist/chunk-IR35BCLK.js +13 -0
  403. package/vendor/framey/dist/chunk-ISN5GRYI.js +20 -0
  404. package/vendor/framey/dist/chunk-IUONB55J.js +669 -0
  405. package/vendor/framey/dist/chunk-IVSUQR2B.js +161 -0
  406. package/vendor/framey/dist/chunk-IXU6PQSW.js +259 -0
  407. package/vendor/framey/dist/chunk-IZCW2NKT.js +29 -0
  408. package/vendor/framey/dist/chunk-JGXJU5PF.js +68 -0
  409. package/vendor/framey/dist/chunk-JHOCK3DG.js +27 -0
  410. package/vendor/framey/dist/chunk-JVBRJMOP.js +121 -0
  411. package/vendor/framey/dist/chunk-K4MJX7SR.js +17 -0
  412. package/vendor/framey/dist/chunk-K4WKGXRC.js +18 -0
  413. package/vendor/framey/dist/chunk-KGPLIH7B.js +127 -0
  414. package/vendor/framey/dist/chunk-KLIKCX6Q.js +63 -0
  415. package/vendor/framey/dist/chunk-KXTKKBOC.js +61 -0
  416. package/vendor/framey/dist/chunk-KZI44OPA.js +185 -0
  417. package/vendor/framey/dist/chunk-LEKZNRKI.js +45 -0
  418. package/vendor/framey/dist/chunk-LFGJWOVA.js +61 -0
  419. package/vendor/framey/dist/chunk-LLMSX6V6.js +17 -0
  420. package/vendor/framey/dist/chunk-LTGTN2TH.js +195 -0
  421. package/vendor/framey/dist/chunk-M2WBOQ2Q.js +54 -0
  422. package/vendor/framey/dist/chunk-MI5FTLYK.js +399 -0
  423. package/vendor/framey/dist/chunk-MLQP2QUF.js +1809 -0
  424. package/vendor/framey/dist/chunk-MMQ52NIZ.js +956 -0
  425. package/vendor/framey/dist/chunk-ND46XKK3.js +742 -0
  426. package/vendor/framey/dist/chunk-NYEXNSHM.js +504 -0
  427. package/vendor/framey/dist/chunk-O4YRB27L.js +57 -0
  428. package/vendor/framey/dist/chunk-O7BGSQ5F.js +92 -0
  429. package/vendor/framey/dist/chunk-OFQWTKPW.js +117 -0
  430. package/vendor/framey/dist/chunk-P5ZBLXJ6.js +91 -0
  431. package/vendor/framey/dist/chunk-P6LJ4Y32.js +4662 -0
  432. package/vendor/framey/dist/chunk-PKZ7RK5N.js +281 -0
  433. package/vendor/framey/dist/chunk-PURHAXFL.js +15 -0
  434. package/vendor/framey/dist/chunk-Q5X2B5WT.js +29 -0
  435. package/vendor/framey/dist/chunk-QAMKOG67.js +248 -0
  436. package/vendor/framey/dist/chunk-R6YBK4XX.js +514 -0
  437. package/vendor/framey/dist/chunk-RGLQURIX.js +2997 -0
  438. package/vendor/framey/dist/chunk-RNV3DM4S.js +3573 -0
  439. package/vendor/framey/dist/chunk-ROEW726S.js +4638 -0
  440. package/vendor/framey/dist/chunk-RQVDTPGD.js +6 -0
  441. package/vendor/framey/dist/chunk-RVZHGOGR.js +26 -0
  442. package/vendor/framey/dist/chunk-RXATE6FZ.js +385 -0
  443. package/vendor/framey/dist/chunk-S3S4TGEH.js +424 -0
  444. package/vendor/framey/dist/chunk-SDYDNHEE.js +11202 -0
  445. package/vendor/framey/dist/chunk-SSWBU67I.js +173 -0
  446. package/vendor/framey/dist/chunk-ST35C4K6.js +28 -0
  447. package/vendor/framey/dist/chunk-SZNTYTIV.js +990 -0
  448. package/vendor/framey/dist/chunk-T2EUWCJE.js +29 -0
  449. package/vendor/framey/dist/chunk-T6AGUTZJ.js +444 -0
  450. package/vendor/framey/dist/chunk-THJALHFJ.js +11131 -0
  451. package/vendor/framey/dist/chunk-TIQB63MX.js +18128 -0
  452. package/vendor/framey/dist/chunk-U242RTCT.js +134 -0
  453. package/vendor/framey/dist/chunk-UJZREAV6.js +3901 -0
  454. package/vendor/framey/dist/chunk-UMD3V7CU.js +264 -0
  455. package/vendor/framey/dist/chunk-UOFAE5RF.js +42 -0
  456. package/vendor/framey/dist/chunk-UTEIUGAZ.js +29 -0
  457. package/vendor/framey/dist/chunk-VAS6HQX3.js +138 -0
  458. package/vendor/framey/dist/chunk-VC76R6W2.js +27 -0
  459. package/vendor/framey/dist/chunk-VFZ7W5W7.js +226 -0
  460. package/vendor/framey/dist/chunk-VHNLZAE2.js +348 -0
  461. package/vendor/framey/dist/chunk-VMC4WSH5.js +278 -0
  462. package/vendor/framey/dist/chunk-VORQIH64.js +108 -0
  463. package/vendor/framey/dist/chunk-VTXFRIHO.js +186 -0
  464. package/vendor/framey/dist/chunk-W2LGJSEN.js +182 -0
  465. package/vendor/framey/dist/chunk-WKBM7NDG.js +32 -0
  466. package/vendor/framey/dist/chunk-WMQNIQDJ.js +2057 -0
  467. package/vendor/framey/dist/chunk-WN4XZC5F.js +504 -0
  468. package/vendor/framey/dist/chunk-WQ6ZXHFQ.js +133 -0
  469. package/vendor/framey/dist/chunk-X7HBSTCZ.js +53 -0
  470. package/vendor/framey/dist/chunk-X7MTZ4T2.js +6 -0
  471. package/vendor/framey/dist/chunk-XPTOJZJF.js +308 -0
  472. package/vendor/framey/dist/chunk-XT6MXC7A.js +6 -0
  473. package/vendor/framey/dist/chunk-XT7X6QCP.js +6 -0
  474. package/vendor/framey/dist/chunk-XTMDWNEC.js +2820 -0
  475. package/vendor/framey/dist/chunk-XUHOIDKG.js +6 -0
  476. package/vendor/framey/dist/chunk-XX7LTW5Y.js +138 -0
  477. package/vendor/framey/dist/chunk-Y3YGTZEG.js +382 -0
  478. package/vendor/framey/dist/chunk-Y5SBSGN7.js +346 -0
  479. package/vendor/framey/dist/chunk-YCMVI4MZ.js +625 -0
  480. package/vendor/framey/dist/chunk-YOR4CTCE.js +261 -0
  481. package/vendor/framey/dist/chunk-YPRBGITP.js +2748 -0
  482. package/vendor/framey/dist/chunk-ZKDMAOFU.js +32 -0
  483. package/vendor/framey/dist/chunk-ZW6DURPF.js +1318 -0
  484. package/vendor/framey/dist/clean-ZJOGDKDM.js +336 -0
  485. package/vendor/framey/dist/cli.js +439 -0
  486. package/vendor/framey/dist/cloudrun-HGJ3B6ZV.js +767 -0
  487. package/vendor/framey/dist/commands/contrast-audit.browser.js +643 -0
  488. package/vendor/framey/dist/commands/layout-audit.browser.js +2914 -0
  489. package/vendor/framey/dist/commands/motion-sample.browser.js +74 -0
  490. package/vendor/framey/dist/commands/motion-signature.browser.js +475 -0
  491. package/vendor/framey/dist/compare-W7UY3BAZ.js +463 -0
  492. package/vendor/framey/dist/compiler-TM3W6GYF.js +136 -0
  493. package/vendor/framey/dist/component-QF5VGYMU.js +176 -0
  494. package/vendor/framey/dist/compositions-XT3PMNDF.js +238 -0
  495. package/vendor/framey/dist/contactSheet-7W6GYHBQ.js +24 -0
  496. package/vendor/framey/dist/deploy-6FJPWKF2.js +299 -0
  497. package/vendor/framey/dist/destroy-HE2RIPKZ.js +57 -0
  498. package/vendor/framey/dist/deterministicFonts-RADD3BSX.js +50 -0
  499. package/vendor/framey/dist/dist-4S2FGGVY.js +422 -0
  500. package/vendor/framey/dist/dist-BE4B2EZE.js +32 -0
  501. package/vendor/framey/dist/dist-EWXJGN63.js +129 -0
  502. package/vendor/framey/dist/docs-VKIRFEEX.js +131 -0
  503. package/vendor/framey/dist/doctor-2UNJ2G7U.js +74 -0
  504. package/vendor/framey/dist/dom-37K6YOH4.js +14 -0
  505. package/vendor/framey/dist/dotEnv-7PZQTVIM.js +54 -0
  506. package/vendor/framey/dist/events-ACY3P2PA.js +76 -0
  507. package/vendor/framey/dist/events-IHB3B2MK.js +69 -0
  508. package/vendor/framey/dist/ffmpeg-DR5LGGSK.js +63 -0
  509. package/vendor/framey/dist/figma-BODVUPHB.js +63 -0
  510. package/vendor/framey/dist/fontData.generated-NXAOI4GH.js +13 -0
  511. package/vendor/framey/dist/fontLocalizeCli.js +142 -0
  512. package/vendor/framey/dist/gpuPolicy-XLEXORZY.js +49 -0
  513. package/vendor/framey/dist/grade-compare-GAXFQ74C.js +661 -0
  514. package/vendor/framey/dist/gsapParser-IEUSLYDJ.js +2885 -0
  515. package/vendor/framey/dist/gsapParserAcorn-LZJKCFQI.js +30 -0
  516. package/vendor/framey/dist/help-VCB5X2HS.js +184 -0
  517. package/vendor/framey/dist/history-ENGZEVFT.js +471 -0
  518. package/vendor/framey/dist/hyperframe.manifest.json +22 -0
  519. package/vendor/framey/dist/hyperframe.runtime.iife.js +1132 -0
  520. package/vendor/framey/dist/hyperframes-player.global.js +478 -0
  521. package/vendor/framey/dist/hyperframes-slideshow.global.js +148 -0
  522. package/vendor/framey/dist/info-WPCJHBMU.js +182 -0
  523. package/vendor/framey/dist/init-G4WGLYGD.js +1176 -0
  524. package/vendor/framey/dist/inspect-5IQ6CNEQ.js +106 -0
  525. package/vendor/framey/dist/installer-ML4HWUV7.js +40 -0
  526. package/vendor/framey/dist/keyframes-Q6XJO7VW.js +2755 -0
  527. package/vendor/framey/dist/lambda-A7JC74JF.js +468 -0
  528. package/vendor/framey/dist/layout-YET6XNXA.js +95 -0
  529. package/vendor/framey/dist/lint-I7FZN2VJ.js +162 -0
  530. package/vendor/framey/dist/lintProject-PDB3UN72.js +30 -0
  531. package/vendor/framey/dist/manager-CD6LJ7ZN.js +45 -0
  532. package/vendor/framey/dist/manager-WA4F2GST.js +67 -0
  533. package/vendor/framey/dist/media-treatment-BXYS4WVA.js +1030 -0
  534. package/vendor/framey/dist/media-use-LWH3MANK.js +113 -0
  535. package/vendor/framey/dist/models-K363FYM4.js +195 -0
  536. package/vendor/framey/dist/motionShot-GPAVWXLH.js +640 -0
  537. package/vendor/framey/dist/normalize-FASIPBUM.js +24 -0
  538. package/vendor/framey/dist/normalize-audio-VDWYRHN6.js +268 -0
  539. package/vendor/framey/dist/open-E3TB6P6J.js +128 -0
  540. package/vendor/framey/dist/parakeetRunner-UP34UOI2.js +58 -0
  541. package/vendor/framey/dist/pipeline-VXIUYEBU.js +64 -0
  542. package/vendor/framey/dist/play-BUTDQ4DV.js +353 -0
  543. package/vendor/framey/dist/policies-OLDYGFK5.js +309 -0
  544. package/vendor/framey/dist/preflight-2KZ2GWAZ.js +55 -0
  545. package/vendor/framey/dist/present-GXYSM7NX.js +353 -0
  546. package/vendor/framey/dist/preview-EKZ33JOJ.js +1910 -0
  547. package/vendor/framey/dist/producer-SKU5EV3J.js +13 -0
  548. package/vendor/framey/dist/progress-ZWB4Z4ET.js +76 -0
  549. package/vendor/framey/dist/projectConfig-3MZAYVTS.js +60 -0
  550. package/vendor/framey/dist/publication-DTKWNF74.js +33 -0
  551. package/vendor/framey/dist/remove-background-OY5L7XN2.js +265 -0
  552. package/vendor/framey/dist/render-CDV4GDFX.js +187 -0
  553. package/vendor/framey/dist/render-YE5YAMOD.js +2620 -0
  554. package/vendor/framey/dist/render-batch-ZAMFPCLL.js +274 -0
  555. package/vendor/framey/dist/renderSetupWorker.js +120 -0
  556. package/vendor/framey/dist/resolver-D5BIPSEW.js +42 -0
  557. package/vendor/framey/dist/runtimeVersion.js +18 -0
  558. package/vendor/framey/dist/sam-WFZXI4F7.js +23 -0
  559. package/vendor/framey/dist/shaderTransitionWorker.js +44 -0
  560. package/vendor/framey/dist/sherpa-RQWLV7I3.js +79 -0
  561. package/vendor/framey/dist/sherpaWorker.js +84 -0
  562. package/vendor/framey/dist/sites-AMOVABTK.js +54 -0
  563. package/vendor/framey/dist/skill-ZHVLH7KX.js +15 -0
  564. package/vendor/framey/dist/slideshow-SJGK4RQS.js +24 -0
  565. package/vendor/framey/dist/snapshot-TUXL6LBQ.js +1515 -0
  566. package/vendor/framey/dist/src-JHQGB2S6.js +215 -0
  567. package/vendor/framey/dist/src-Z5PGEMXB.js +532 -0
  568. package/vendor/framey/dist/state-B6H3WHCF.js +28 -0
  569. package/vendor/framey/dist/staticProjectServer-DFVZOUGI.js +63 -0
  570. package/vendor/framey/dist/studio/assets/hyperframes-player-DLaKjw0L.js +478 -0
  571. package/vendor/framey/dist/studio/assets/index-BX3KHhGX.js +71 -0
  572. package/vendor/framey/dist/studio/assets/index-CYbvOVp-.css +1 -0
  573. package/vendor/framey/dist/studio/assets/index-Dp3QEUGL.js +402 -0
  574. package/vendor/framey/dist/studio/assets/index-qrTAXbqc.js +531 -0
  575. package/vendor/framey/dist/studio/favicon.svg +14 -0
  576. package/vendor/framey/dist/studio/icons/timeline/audio.svg +7 -0
  577. package/vendor/framey/dist/studio/icons/timeline/captions.svg +5 -0
  578. package/vendor/framey/dist/studio/icons/timeline/composition.svg +12 -0
  579. package/vendor/framey/dist/studio/icons/timeline/image.svg +18 -0
  580. package/vendor/framey/dist/studio/icons/timeline/music.svg +10 -0
  581. package/vendor/framey/dist/studio/icons/timeline/text.svg +3 -0
  582. package/vendor/framey/dist/studio/index.html +23 -0
  583. package/vendor/framey/dist/studio-api-2NECGRMB.js +179 -0
  584. package/vendor/framey/dist/studioSelectionClient-IUUPKUHZ.js +25 -0
  585. package/vendor/framey/dist/studioServer-N2OPUMOQ.js +1569 -0
  586. package/vendor/framey/dist/synthesize-PKTB5ATG.js +183 -0
  587. package/vendor/framey/dist/system-7F3UEHQT.js +27 -0
  588. package/vendor/framey/dist/telemetry-DQGPEKM6.js +145 -0
  589. package/vendor/framey/dist/telemetry-UN55N6U6.js +77 -0
  590. package/vendor/framey/dist/timeline-LHUUMK63.js +1295 -0
  591. package/vendor/framey/dist/tokens-OLECWDFK.js +92 -0
  592. package/vendor/framey/dist/transcribe-O7HQKMIV.js +331 -0
  593. package/vendor/framey/dist/transcribe-UJESPBT5.js +76 -0
  594. package/vendor/framey/dist/tts-YCCQHZD4.js +234 -0
  595. package/vendor/framey/dist/urlDownloader-H2LXLG4U.js +48 -0
  596. package/vendor/framey/dist/usage-HG4WMM7A.js +2167 -0
  597. package/vendor/framey/dist/validate-F2XMN6EV.js +87 -0
  598. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/GSAP-LICENSE.txt +8 -0
  599. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/CustomEase.min.js +11 -0
  600. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/MotionPathPlugin.min.js +11 -0
  601. package/vendor/framey/dist/vendor/npm/gsap@3.15.0/dist/gsap.min.js +11 -0
  602. package/vendor/framey/dist/warmCheck.js +220 -0
  603. package/vendor/framey/dist/warmCheckClient.js +139 -0
  604. package/vendor/framey/dist/workspaceBuildCheck-XYD2YTFW.js +133 -0
  605. package/vendor/framey-player/LICENSE +190 -0
  606. package/vendor/framey-player/NOTICE +16 -0
  607. package/vendor/framey-player/SOURCE.json +6 -0
  608. package/vendor/framey-player/hyperframes-player.global.js +478 -0
  609. package/vendor/framey.pin +1 -0
  610. package/bin/index.js +0 -3
@@ -0,0 +1,643 @@
1
+ // Browser-side WCAG contrast audit, injected as a raw string so esbuild can't mangle it.
2
+ // __contrastAuditPrepare() hides each text element's own paint (layout-neutral) and returns candidates;
3
+ // the caller takes one screenshot, full frame or clipped to the candidates (collectContrast in checkBrowser.ts);
4
+ // __contrastAuditFinish(png, time, candidates, region) restores paint first, then samples inside each box.
5
+
6
+ // Sampling inside the box reads the exact pixels behind the glyphs; a ring outside the text misreads
7
+ // neighbouring panels, rounded pills, blurred glass and partial decorations.
8
+ // __contrastAuditRestoreIfPending() restores hidden paint if the screenshot or finish() throws.
9
+
10
+ // The "which rect to sample" decision is mirrored and unit-tested in contrast-sample.ts.
11
+
12
+ /* eslint-disable */
13
+ window.__contrastAuditPrepare = function () {
14
+ // SVG text (<text>, <tspan>, <textPath>) is painted via the `fill`
15
+ // property, not `color` — the two are independent CSS properties in SVG.
16
+ // A page can set `fill` (inline style, `fill` attribute, or a CSS rule)
17
+ // without ever touching `color`, in which case getComputedStyle(el).color
18
+ // resolves to the inherited/initial value (often black) and does not
19
+ // reflect what's actually rendered on screen.
20
+ function isSvgTextElement(el) {
21
+ return !!el.ownerSVGElement;
22
+ }
23
+
24
+ // Raster-free contrast: a leaf text box whose backdrop is provably one opaque CSS colour needs no
25
+ // screenshot. Anything this cannot prove (overlays, images, blending, rotation, round corners) returns null.
26
+ var REPLACED = /^(IMG|VIDEO|CANVAS|IFRAME|OBJECT|EMBED|INPUT|TEXTAREA|SELECT|svg|PICTURE)$/;
27
+ var paintCache = new Map();
28
+ function blends(cs) {
29
+ return (
30
+ cs.opacity !== "1" ||
31
+ cs.filter !== "none" ||
32
+ (cs.backdropFilter || cs.webkitBackdropFilter || "none") !== "none" ||
33
+ cs.mixBlendMode !== "normal" ||
34
+ (cs.maskImage || cs.webkitMaskImage || "none") !== "none" ||
35
+ cs.clipPath !== "none"
36
+ );
37
+ }
38
+ function axisAligned(cs) {
39
+ var t = cs.transform;
40
+ if (t === "none") return true;
41
+ var m = t.match(/^matrix\(([^)]+)\)$/);
42
+ if (!m) return false;
43
+ var v = m[1].split(",").map(parseFloat);
44
+ return v[1] === 0 && v[2] === 0;
45
+ }
46
+ function pseudoPaints(el) {
47
+ return ["::before", "::after"].some(function (pseudo) {
48
+ var content = getComputedStyle(el, pseudo).content;
49
+ return content !== "none" && content !== "normal";
50
+ });
51
+ }
52
+ function hasOwnText(el) {
53
+ for (var n = el.firstChild; n; n = n.nextSibling) {
54
+ if (n.nodeType === 3 && /\S/.test(n.nodeValue || "")) return true;
55
+ }
56
+ return false;
57
+ }
58
+ function boxPaints(el, cs) {
59
+ var bg = parseColor(cs.backgroundColor || "");
60
+ return (
61
+ (cs.backgroundImage || "none") !== "none" ||
62
+ !bg ||
63
+ bg[3] !== 0 ||
64
+ ["Top", "Right", "Bottom", "Left"].some(function (side) {
65
+ return (
66
+ cs["border" + side + "Style"] !== "none" && parseFloat(cs["border" + side + "Width"]) > 0
67
+ );
68
+ }) ||
69
+ cs.boxShadow !== "none" ||
70
+ (cs.outlineStyle !== "none" && parseFloat(cs.outlineWidth) > 0) ||
71
+ pseudoPaints(el)
72
+ );
73
+ }
74
+ // True unless the element provably adds no pixels of its own.
75
+ function paints(el) {
76
+ if (paintCache.has(el)) return paintCache.get(el);
77
+ var cs = getComputedStyle(el);
78
+ var result =
79
+ cs.visibility === "hidden" && cs.filter === "none"
80
+ ? false
81
+ : REPLACED.test(el.tagName) ||
82
+ !!el.ownerSVGElement ||
83
+ hasOwnText(el) ||
84
+ boxPaints(el, cs) ||
85
+ blends(cs);
86
+ paintCache.set(el, result);
87
+ return result;
88
+ }
89
+ function intersects(a, b) {
90
+ return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom;
91
+ }
92
+ function solidBackdrop(el, rect, cs) {
93
+ if (el.children.length > 0 || el.ownerSVGElement || cs.textShadow !== "none") return null;
94
+ if (cs.textDecorationLine !== "none" || boxPaints(el, cs) || !axisAligned(cs)) return null;
95
+ if ((cs.backdropFilter || cs.webkitBackdropFilter || "none") !== "none") return null;
96
+ var region = {
97
+ left: Math.max(0, rect.left),
98
+ top: Math.max(0, rect.top),
99
+ right: Math.min(window.innerWidth, rect.right),
100
+ bottom: Math.min(window.innerHeight, rect.bottom),
101
+ };
102
+ if (region.right <= region.left || region.bottom <= region.top) return null;
103
+ var chain = new Set([el]);
104
+ var solid = null;
105
+ for (var a = el.parentElement; a; a = a.parentElement) {
106
+ chain.add(a);
107
+ var acs = getComputedStyle(a);
108
+ if (blends(acs) || !axisAligned(acs) || pseudoPaints(a)) return null;
109
+ if (a === document.body || a === document.documentElement) {
110
+ if (!solid) solid = canvasColor(a, acs, region);
111
+ if (!solid && (a === document.documentElement || boxPaints(a, acs))) return null;
112
+ continue;
113
+ }
114
+ if (solid) {
115
+ if (acs.overflow !== "visible" && !contains(a.getBoundingClientRect(), acs, region))
116
+ return null;
117
+ continue;
118
+ }
119
+ var bg =
120
+ (acs.backgroundImage || "none") === "none" ? parseColor(acs.backgroundColor || "") : null;
121
+ if (bg && bg[3] === 1) {
122
+ var radius = ["TopLeft", "TopRight", "BottomRight", "BottomLeft"].some(function (corner) {
123
+ return parseFloat(acs["border" + corner + "Radius"]) > 0;
124
+ });
125
+ if (radius || !contains(a.getBoundingClientRect(), acs, region)) return null;
126
+ solid = bg;
127
+ continue;
128
+ }
129
+ if (hasOwnText(a) || boxPaints(a, acs)) return null;
130
+ }
131
+ if (!solid) return null;
132
+ var all = document.querySelectorAll("*");
133
+ for (var i = 0; i < all.length; i++) {
134
+ var other = all[i];
135
+ if (chain.has(other) || !intersects(other.getBoundingClientRect(), region)) continue;
136
+ if (paints(other)) return null;
137
+ }
138
+ return [solid[0], solid[1], solid[2]];
139
+ }
140
+ // body's background paints the whole canvas unless html has its own (CSS background propagation).
141
+ function canvasColor(el, cs, region) {
142
+ var bg =
143
+ (cs.backgroundImage || "none") === "none" ? parseColor(cs.backgroundColor || "") : null;
144
+ var html = document.documentElement;
145
+ var htmlCs = getComputedStyle(html);
146
+ var htmlBg = parseColor(htmlCs.backgroundColor || "");
147
+ var htmlPaints = (htmlCs.backgroundImage || "none") !== "none" || !htmlBg || htmlBg[3] !== 0;
148
+ if (el === html) return bg && bg[3] === 1 ? bg : null;
149
+ if (!bg || bg[3] !== 1) return null;
150
+ return htmlPaints && !contains(el.getBoundingClientRect(), cs, region) ? null : bg;
151
+ }
152
+ function contains(box, cs, region) {
153
+ return (
154
+ box.left + parseFloat(cs.borderLeftWidth) <= region.left &&
155
+ box.top + parseFloat(cs.borderTopWidth) <= region.top &&
156
+ box.right - parseFloat(cs.borderRightWidth) >= region.right &&
157
+ box.bottom - parseFloat(cs.borderBottomWidth) >= region.bottom
158
+ );
159
+ }
160
+
161
+ function parseColor(c) {
162
+ var m = (c || "").match(/^rgba?\(([^)]+)\)$/i);
163
+ if (!m) {
164
+ var mix = (c || "").match(
165
+ /^color-mix\(\s*in\s+srgb\s*,\s*(rgba?\([^)]+\))\s+(\d+(?:\.\d+)?|\.\d+)%\s*,\s*(rgba?\([^)]+\))\s+(\d+(?:\.\d+)?|\.\d+)%\s*\)$/i,
166
+ );
167
+ if (!mix) return null;
168
+ var first = parseColor(mix[1]);
169
+ var second = parseColor(mix[3]);
170
+ var firstWeight = parseFloat(mix[2]);
171
+ var secondWeight = parseFloat(mix[4]);
172
+ var weightTotal = firstWeight + secondWeight;
173
+ if (!first || !second || !isFinite(weightTotal) || weightTotal <= 0) return null;
174
+ return first.map(function (channel, index) {
175
+ return (channel * firstWeight + second[index] * secondWeight) / weightTotal;
176
+ });
177
+ }
178
+ var p = m[1].split(",").map(function (s) {
179
+ return parseFloat(s.trim());
180
+ });
181
+ if (
182
+ (p.length !== 3 && p.length !== 4) ||
183
+ p.some(function (v) {
184
+ return !isFinite(v);
185
+ })
186
+ )
187
+ return null;
188
+ return [p[0], p[1], p[2], p[3] != null ? p[3] : 1];
189
+ }
190
+
191
+ function selectorOf(el) {
192
+ if (el.id) return "#" + el.id;
193
+ var cls = Array.from(el.classList).slice(0, 2).join(".");
194
+ return cls ? el.tagName.toLowerCase() + "." + cls : el.tagName.toLowerCase();
195
+ }
196
+
197
+ function hasClipPath(el) {
198
+ for (var ce = el; ce; ce = ce.parentElement) {
199
+ var cp = getComputedStyle(ce).clipPath;
200
+ if (cp && cp !== "none") return true;
201
+ }
202
+ return false;
203
+ }
204
+
205
+ var CLIP_PROBE_COLS = [0.05, 0.25, 0.5, 0.75, 0.95];
206
+ var CLIP_PROBE_ROWS = [0.25, 0.5, 0.75];
207
+
208
+ var compositionBoxPaint = new WeakMap();
209
+ var COMPOSITION_BOX_TAGS = new Set(["DIV", "SECTION"]);
210
+
211
+ function hasContainerPaint(style) {
212
+ var background = parseColor(style.backgroundColor);
213
+ if (
214
+ style.backgroundColor &&
215
+ style.backgroundColor !== "transparent" &&
216
+ (!background || background[3] > 0)
217
+ )
218
+ return true;
219
+ if (
220
+ ["backgroundImage", "boxShadow", "filter", "backdropFilter"].some(function (property) {
221
+ return style[property] && style[property] !== "none";
222
+ })
223
+ )
224
+ return true;
225
+ if (parseFloat(style.outlineWidth) > 0 && style.outlineStyle !== "none") return true;
226
+ return ["Top", "Right", "Bottom", "Left"].some(function (side) {
227
+ return (
228
+ parseFloat(style["border" + side + "Width"]) > 0 &&
229
+ style["border" + side + "Style"] !== "none"
230
+ );
231
+ });
232
+ }
233
+
234
+ function isUnpaintedCompositionBox(el) {
235
+ if (!el || !el.matches("[data-composition-id], [data-hf-inner-root]")) return false;
236
+ if (!el.closest("[data-composition-id]")) return false;
237
+ if (
238
+ el.namespaceURI !== "http://www.w3.org/1999/xhtml" ||
239
+ !COMPOSITION_BOX_TAGS.has(el.tagName) ||
240
+ el.shadowRoot
241
+ )
242
+ return false;
243
+ if (compositionBoxPaint.has(el)) return !compositionBoxPaint.get(el);
244
+ var painted =
245
+ Array.from(el.childNodes).some(function (child) {
246
+ return child.nodeType === 3 && (child.textContent || "").trim().length > 0;
247
+ }) || hasContainerPaint(getComputedStyle(el));
248
+ if (!painted) {
249
+ painted = ["::before", "::after"].some(function (pseudo) {
250
+ var content = getComputedStyle(el, pseudo).content;
251
+ return content && content !== "none" && content !== "normal";
252
+ });
253
+ }
254
+ compositionBoxPaint.set(el, !!painted);
255
+ return !painted;
256
+ }
257
+
258
+ function paintsAnyProbePoint(el, rect, skipCompositionBoxes) {
259
+ // Keep probe resolution aligned with layout-audit.browser.js. Edge strips
260
+ // narrower than the nearest probe point are treated as clipped away to
261
+ // avoid noisy typewriter pre-reveal contrast reports.
262
+ for (var ci = 0; ci < CLIP_PROBE_COLS.length; ci++) {
263
+ for (var ri = 0; ri < CLIP_PROBE_ROWS.length; ri++) {
264
+ var x = rect.left + rect.width * CLIP_PROBE_COLS[ci];
265
+ var y = rect.top + rect.height * CLIP_PROBE_ROWS[ri];
266
+ var hits =
267
+ skipCompositionBoxes && typeof document.elementsFromPoint === "function"
268
+ ? document.elementsFromPoint(x, y)
269
+ : [document.elementFromPoint(x, y)];
270
+ for (var hit of hits) {
271
+ if (hit === el || el.contains(hit)) return true;
272
+ if (!skipCompositionBoxes || !isUnpaintedCompositionBox(hit)) break;
273
+ }
274
+ }
275
+ }
276
+ return false;
277
+ }
278
+
279
+ // A clip-path can shrink an element's painted region to nothing (a typewriter
280
+ // span pre-reveal at `inset(0 100% 0 0)`, or `circle(0px)`) while its box and
281
+ // colours read normally; it then paints zero pixels and measures a meaningless
282
+ // background-on-background ratio. clip-path drives hit-testing, so a fully
283
+ // clipped element is unreachable by elementFromPoint across its box. Probe only
284
+ // when a clip-path is in effect (self or ancestor) so genuinely-occluded but
285
+ // unclipped text is not skipped.
286
+ function isClippedAway(el, rect) {
287
+ if (typeof document.elementFromPoint !== "function") return false;
288
+ if (!hasClipPath(el)) return false;
289
+ return !paintsAnyProbePoint(el, rect, true);
290
+ }
291
+
292
+ function isIntentionallyOccluded(el, rect) {
293
+ if (typeof document.elementFromPoint !== "function") return false;
294
+ if (!el.closest || !el.closest("[data-layout-allow-occlusion]")) return false;
295
+ return !paintsAnyProbePoint(el, rect, true);
296
+ }
297
+
298
+ var out = [];
299
+ var restores = [];
300
+ // Registered BEFORE the walk starts (not after it finishes) and pushed to
301
+ // incrementally as each element is hidden: if getComputedStyle/
302
+ // getBoundingClientRect/etc. throws partway through the walk (e.g. on a
303
+ // detached or otherwise pathological element), everything hidden before
304
+ // the throw is still reachable for restore instead of leaking hidden
305
+ // indefinitely.
306
+ window.__contrastAuditRestores = restores;
307
+ var walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT);
308
+ var node;
309
+ while ((node = walker.nextNode())) {
310
+ var el = node;
311
+
312
+ // Must have a direct text node child
313
+ var hasText = false;
314
+ for (var i = 0; i < el.childNodes.length; i++) {
315
+ if (
316
+ el.childNodes[i].nodeType === 3 &&
317
+ (el.childNodes[i].textContent || "").trim().length > 0
318
+ ) {
319
+ hasText = true;
320
+ break;
321
+ }
322
+ }
323
+ if (!hasText) continue;
324
+
325
+ // Same decorative opt-out the layout audit honors: text marked (or inside)
326
+ // data-layout-ignore is set dressing, not copy a viewer must read —
327
+ // deliberately dim rail labels, ghost typography, texture text.
328
+ if (el.closest && el.closest("[data-layout-ignore]")) continue;
329
+
330
+ // Text that has (nearly) left the canvas — a cursor exiting the frame, an
331
+ // element parked off-screen — is not readable content, and sampling its
332
+ // clamped edge reads whatever pixels happen to sit at the border (the
333
+ // classic false "white-on-white"). Require a minimally-visible on-canvas
334
+ // intersection before judging contrast; the layout audit separately owns
335
+ // off-canvas detection as its own finding class.
336
+ var vis = el.getBoundingClientRect();
337
+ var onX = Math.min(vis.right, window.innerWidth) - Math.max(vis.left, 0);
338
+ var onY = Math.min(vis.bottom, window.innerHeight) - Math.max(vis.top, 0);
339
+ if (onX < 8 || onY < 8) continue;
340
+
341
+ var cs = getComputedStyle(el);
342
+ if (cs.visibility === "hidden" || cs.display === "none") continue;
343
+ if (parseFloat(cs.opacity) <= 0.01) continue;
344
+ // Also skip when an ANCESTOR is effectively invisible (opacity≈0 / hidden / display:none).
345
+ // Karaoke captions keep every word at opacity 1 but toggle the GROUP's opacity per beat,
346
+ // so an inactive word's OWN opacity is 1 — only an ancestor reveals it's hidden. Without
347
+ // this, the hidden caption words flood the audit with false ~1:1 contrast warnings.
348
+ var anc = el.parentElement,
349
+ ancHidden = false;
350
+ while (anc && anc !== document.body) {
351
+ var acs = getComputedStyle(anc);
352
+ if (
353
+ acs.visibility === "hidden" ||
354
+ acs.display === "none" ||
355
+ parseFloat(acs.opacity) <= 0.01
356
+ ) {
357
+ ancHidden = true;
358
+ break;
359
+ }
360
+ anc = anc.parentElement;
361
+ }
362
+ if (ancHidden) continue;
363
+ var rect = el.getBoundingClientRect();
364
+ if (rect.width < 8 || rect.height < 8) continue;
365
+ if (rect.right <= 0 || rect.bottom <= 0) continue;
366
+ if (isClippedAway(el, rect)) continue;
367
+ // The layout audit's explicit occlusion opt-out means this text is allowed
368
+ // to sit behind another scene. Skip contrast only while every probe point
369
+ // is actually covered; the same copy is audited normally when visible.
370
+ if (isIntentionallyOccluded(el, rect)) continue;
371
+
372
+ // For SVG text, `fill` is the paint that's actually rendered; `color` is
373
+ // frequently just the inherited/initial value and unrelated to what's on
374
+ // screen. Only trust `fill` when it resolves to a solid color — "none",
375
+ // "context-fill", and gradient/pattern refs (url(#...)) fall back to
376
+ // `color` rather than crashing parseColor or reporting a fabricated
377
+ // black.
378
+ var isSvgText = isSvgTextElement(el);
379
+ var fg = isSvgText ? parseColor(cs.fill) || parseColor(cs.color) : parseColor(cs.color);
380
+ if (!fg) continue;
381
+ if (fg[3] <= 0.01) continue;
382
+ var strokeWidth = parseFloat(cs.webkitTextStrokeWidth || "0");
383
+ var stroke = strokeWidth > 0 ? parseColor(cs.webkitTextStrokeColor || "") : null;
384
+ if (stroke && stroke[3] <= 0.01) stroke = null;
385
+
386
+ var fontSize = parseFloat(cs.fontSize);
387
+ var fontWeight = Number(cs.fontWeight) || 400;
388
+ var large = fontSize >= 24 || (fontSize >= 19 && fontWeight >= 700);
389
+
390
+ // Glyphs sit on this element's own fill. The bounding box also contains
391
+ // border-radius corners and neighbouring pixels, and those read as the
392
+ // panel behind a circular avatar. An opaque background with no image is
393
+ // the fill; pixel sampling stays for transparent text.
394
+ var ownBg = null;
395
+ if ((cs.backgroundImage || "none") === "none") {
396
+ var parsedOwnBg = parseColor(cs.backgroundColor || "");
397
+ if (parsedOwnBg && parsedOwnBg[3] >= 0.99) ownBg = parsedOwnBg;
398
+ }
399
+
400
+ // Hide this element's OWN text paint so the caller's next screenshot
401
+ // reveals the true pixels behind the glyphs. Layout-neutral: color/fill
402
+ // never affect box geometry. `!important` beats any non-!important rule
403
+ // that might otherwise win on specificity; we restore the exact prior
404
+ // inline value (or remove the property entirely) afterward.
405
+ //
406
+ // A `transition` on color/fill would otherwise animate this hide instead
407
+ // of applying it instantly — the caller's screenshot lands in the same
408
+ // task-queue gap as the transition's own frames, so it can catch a
409
+ // partially-transparent (still partly the original color) glyph instead
410
+ // of a fully hidden one, contaminating the background sample. Force
411
+ // `transition: none` alongside color/fill so the hide is atomic, and
412
+ // restore it alongside them.
413
+ var origTransition = el.style.getPropertyValue("transition");
414
+ var origTransitionPriority = el.style.getPropertyPriority("transition");
415
+ el.style.setProperty("transition", "none", "important");
416
+ var origColor = el.style.getPropertyValue("color");
417
+ var origColorPriority = el.style.getPropertyPriority("color");
418
+ el.style.setProperty("color", "transparent", "important");
419
+ var origFill = null,
420
+ origFillPriority = null;
421
+ if (isSvgText) {
422
+ origFill = el.style.getPropertyValue("fill");
423
+ origFillPriority = el.style.getPropertyPriority("fill");
424
+ el.style.setProperty("fill", "transparent", "important");
425
+ }
426
+ var origStrokeColor = null,
427
+ origStrokeColorPriority = null;
428
+ if (stroke) {
429
+ origStrokeColor = el.style.getPropertyValue("-webkit-text-stroke-color");
430
+ origStrokeColorPriority = el.style.getPropertyPriority("-webkit-text-stroke-color");
431
+ el.style.setProperty("-webkit-text-stroke-color", "transparent", "important");
432
+ }
433
+ restores.push({
434
+ el: el,
435
+ origTransition: origTransition,
436
+ origTransitionPriority: origTransitionPriority,
437
+ origColor: origColor,
438
+ origColorPriority: origColorPriority,
439
+ origFill: origFill,
440
+ origFillPriority: origFillPriority,
441
+ origStrokeColor: origStrokeColor,
442
+ origStrokeColorPriority: origStrokeColorPriority,
443
+ hasStroke: !!stroke,
444
+ isSvgText: isSvgText,
445
+ });
446
+
447
+ out.push({
448
+ selector: selectorOf(el),
449
+ text: (el.textContent || "").trim().slice(0, 50),
450
+ fg: fg,
451
+ stroke: stroke,
452
+ fontSize: fontSize,
453
+ fontWeight: fontWeight,
454
+ large: large,
455
+ ownBg: ownBg,
456
+ solidBg: ownBg ? null : solidBackdrop(el, rect, cs),
457
+ bbox: { x: rect.x, y: rect.y, w: rect.width, h: rect.height },
458
+ });
459
+ }
460
+
461
+ return out;
462
+ };
463
+
464
+ function __contrastAuditRestoreAll() {
465
+ var restores = window.__contrastAuditRestores;
466
+ if (!restores) return;
467
+ for (var i = 0; i < restores.length; i++) {
468
+ var r = restores[i];
469
+ if (r.origColor) r.el.style.setProperty("color", r.origColor, r.origColorPriority);
470
+ else r.el.style.removeProperty("color");
471
+ if (r.isSvgText) {
472
+ if (r.origFill) r.el.style.setProperty("fill", r.origFill, r.origFillPriority);
473
+ else r.el.style.removeProperty("fill");
474
+ }
475
+ if (r.hasStroke) {
476
+ if (r.origStrokeColor)
477
+ r.el.style.setProperty(
478
+ "-webkit-text-stroke-color",
479
+ r.origStrokeColor,
480
+ r.origStrokeColorPriority,
481
+ );
482
+ else r.el.style.removeProperty("-webkit-text-stroke-color");
483
+ }
484
+ if (r.origTransition)
485
+ r.el.style.setProperty("transition", r.origTransition, r.origTransitionPriority);
486
+ else r.el.style.removeProperty("transition");
487
+ }
488
+ window.__contrastAuditRestores = null;
489
+ }
490
+
491
+ // Safety net for the caller: if the screenshot or finish() call throws
492
+ // between prepare() and finish(), call this to restore any still-hidden
493
+ // paint so the next sample in the loop isn't auditing a page with stale
494
+ // invisible text. No-op if finish() already ran normally.
495
+ window.__contrastAuditRestoreIfPending = function () {
496
+ __contrastAuditRestoreAll();
497
+ };
498
+
499
+ window.__contrastAuditFinish = async function (imgBase64, time, candidates, region) {
500
+ function relLum(r, g, b) {
501
+ function ch(v) {
502
+ var s = v / 255;
503
+ return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
504
+ }
505
+ return 0.2126 * ch(r) + 0.7152 * ch(g) + 0.0722 * ch(b);
506
+ }
507
+
508
+ function wcagRatio(r1, g1, b1, r2, g2, b2) {
509
+ var l1 = relLum(r1, g1, b1),
510
+ l2 = relLum(r2, g2, b2);
511
+ var hi = l1 > l2 ? l1 : l2,
512
+ lo = l1 > l2 ? l2 : l1;
513
+ return (hi + 0.05) / (lo + 0.05);
514
+ }
515
+
516
+ function median(arr) {
517
+ var s = arr.slice().sort(function (a, b) {
518
+ return a - b;
519
+ });
520
+ return s[Math.floor(s.length / 2)];
521
+ }
522
+
523
+ // Restore original paint first — we already have the screenshot, and we
524
+ // never want a decode failure below to leave the page's text invisible.
525
+ __contrastAuditRestoreAll();
526
+
527
+ // No image when every candidate's background is known from styles.
528
+ var canvas = { width: region ? region.frameWidth : 0, height: region ? region.frameHeight : 0 };
529
+ var px = null;
530
+ if (imgBase64) {
531
+ var img = new Image();
532
+ await new Promise(function (resolve) {
533
+ img.onload = resolve;
534
+ img.onerror = function () {
535
+ resolve();
536
+ };
537
+ img.src = "data:image/png;base64," + imgBase64;
538
+ });
539
+ if (!img.naturalWidth) return [];
540
+ canvas = document.createElement("canvas");
541
+ canvas.width = img.naturalWidth || 1920;
542
+ canvas.height = img.naturalHeight || 1080;
543
+ var ctx = canvas.getContext("2d");
544
+ if (!ctx) return [];
545
+ ctx.drawImage(img, 0, 0);
546
+ px = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
547
+ }
548
+ // A clipped shot holds `region.clip` of the frame: clamp to the frame, read at the offset.
549
+ var w = region ? region.frameWidth : canvas.width;
550
+ var h = region ? region.frameHeight : canvas.height;
551
+ var ox = region ? region.clip.x : 0;
552
+ var oy = region ? region.clip.y : 0;
553
+
554
+ var out = [];
555
+ for (var ci = 0; ci < candidates.length; ci++) {
556
+ var c = candidates[ci];
557
+ var bbox = c.bbox;
558
+
559
+ // Sample the element's OWN box (glyphs are hidden in this screenshot),
560
+ // inset 1px on each side to dodge anti-aliased edge pixels, clamped to
561
+ // the canvas. Mirrors contrast-sample.ts's computeSampleRect.
562
+ var x0 = Math.max(0, Math.round(bbox.x) + 1);
563
+ var x1 = Math.min(w - 1, Math.round(bbox.x + bbox.w) - 1);
564
+ var y0 = Math.max(0, Math.round(bbox.y) + 1);
565
+ var y1 = Math.min(h - 1, Math.round(bbox.y + bbox.h) - 1);
566
+ if (x1 <= x0 || y1 <= y0) continue;
567
+
568
+ // Bounded grid, not a full scan — dense enough to catch a
569
+ // partially-overlapping decoration without turning a wide caption bar
570
+ // into thousands of samples. Mirrors contrast-sample.ts's
571
+ // sampleGridPoints.
572
+ var stepX = Math.max(1, Math.floor((x1 - x0) / 12));
573
+ var stepY = Math.max(1, Math.floor((y1 - y0) / 6));
574
+ var known = c.ownBg && c.ownBg.length >= 4 && c.ownBg[3] >= 0.99 ? c.ownBg : c.solidBg;
575
+ var rr = [],
576
+ gg = [],
577
+ bb = [],
578
+ aa = [];
579
+ for (var y = y0; !known && y <= y1; y += stepY) {
580
+ for (var x = x0; x <= x1; x += stepX) {
581
+ var idx = ((y - oy) * canvas.width + (x - ox)) * 4;
582
+ rr.push(px[idx]);
583
+ gg.push(px[idx + 1]);
584
+ bb.push(px[idx + 2]);
585
+ aa.push(px[idx + 3]);
586
+ }
587
+ }
588
+ if (!known && rr.length === 0) continue;
589
+
590
+ var bgR, bgG, bgB;
591
+ if (known) {
592
+ bgR = known[0];
593
+ bgG = known[1];
594
+ bgB = known[2];
595
+ } else {
596
+ // A transparent sampled backdrop is supplied by the downstream editor,
597
+ // not this composition. WCAG contrast cannot be inferred until that live
598
+ // video/image is known, so do not invent an opaque browser default and
599
+ // hard-fail an otherwise valid alpha overlay.
600
+ if (median(aa) < 255) continue;
601
+ bgR = median(rr);
602
+ bgG = median(gg);
603
+ bgB = median(bb);
604
+ }
605
+
606
+ // Composite foreground alpha over the measured background
607
+ var fg = c.fg;
608
+ var compR = Math.round(fg[0] * fg[3] + bgR * (1 - fg[3]));
609
+ var compG = Math.round(fg[1] * fg[3] + bgG * (1 - fg[3]));
610
+ var compB = Math.round(fg[2] * fg[3] + bgB * (1 - fg[3]));
611
+
612
+ var ratio = +wcagRatio(compR, compG, compB, bgR, bgG, bgB).toFixed(2);
613
+
614
+ // A solid text stroke is part of the visible glyph paint. Use whichever
615
+ // of fill or stroke provides the stronger edge contrast, rather than
616
+ // failing readable outlined captions based on fill alone.
617
+ if (c.stroke) {
618
+ var stroke = c.stroke;
619
+ var strokeR = Math.round(stroke[0] * stroke[3] + bgR * (1 - stroke[3]));
620
+ var strokeG = Math.round(stroke[1] * stroke[3] + bgG * (1 - stroke[3]));
621
+ var strokeB = Math.round(stroke[2] * stroke[3] + bgB * (1 - stroke[3]));
622
+ var strokeRatio = +wcagRatio(strokeR, strokeG, strokeB, bgR, bgG, bgB).toFixed(2);
623
+ if (strokeRatio > ratio) {
624
+ compR = strokeR;
625
+ compG = strokeG;
626
+ compB = strokeB;
627
+ ratio = strokeRatio;
628
+ }
629
+ }
630
+
631
+ out.push({
632
+ time: time,
633
+ selector: c.selector,
634
+ text: c.text,
635
+ ratio: ratio,
636
+ wcagAA: c.large ? ratio >= 3 : ratio >= 4.5,
637
+ large: c.large,
638
+ fg: "rgb(" + compR + "," + compG + "," + compB + ")",
639
+ bg: "rgb(" + bgR + "," + bgG + "," + bgB + ")",
640
+ });
641
+ }
642
+ return out;
643
+ };