frameyard 0.7.0 → 0.9.0

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 (334) hide show
  1. package/CHANGELOG.md +164 -7
  2. package/GLOSSARY.md +152 -18
  3. package/README.md +328 -285
  4. package/dist/assets/integrations.d.ts +8 -4
  5. package/dist/assets/integrations.d.ts.map +1 -1
  6. package/dist/assets/integrations.js +8 -4
  7. package/dist/assets/integrations.js.map +1 -1
  8. package/dist/assets/provenance.d.ts +2 -2
  9. package/dist/assets/provenance.d.ts.map +1 -1
  10. package/dist/assets/provenance.js +5 -3
  11. package/dist/assets/provenance.js.map +1 -1
  12. package/dist/assets/tts-supertonic.d.ts +28 -0
  13. package/dist/assets/tts-supertonic.d.ts.map +1 -0
  14. package/dist/assets/tts-supertonic.js +156 -0
  15. package/dist/assets/tts-supertonic.js.map +1 -0
  16. package/dist/assets/tts.d.ts +18 -6
  17. package/dist/assets/tts.d.ts.map +1 -1
  18. package/dist/assets/tts.js +219 -97
  19. package/dist/assets/tts.js.map +1 -1
  20. package/dist/cli.js +1705 -106
  21. package/dist/cli.js.map +1 -1
  22. package/dist/composition/descriptor.d.ts +17 -3
  23. package/dist/composition/descriptor.d.ts.map +1 -1
  24. package/dist/composition/descriptor.js +51 -28
  25. package/dist/composition/descriptor.js.map +1 -1
  26. package/dist/composition/format.d.ts +12 -0
  27. package/dist/composition/format.d.ts.map +1 -0
  28. package/dist/composition/format.js +28 -0
  29. package/dist/composition/format.js.map +1 -0
  30. package/dist/composition/index.d.ts +2 -1
  31. package/dist/composition/index.d.ts.map +1 -1
  32. package/dist/composition/index.js +1 -0
  33. package/dist/composition/index.js.map +1 -1
  34. package/dist/context.d.ts +82 -0
  35. package/dist/context.d.ts.map +1 -0
  36. package/dist/context.js +277 -0
  37. package/dist/context.js.map +1 -0
  38. package/dist/contracts.d.ts +80 -6
  39. package/dist/contracts.d.ts.map +1 -1
  40. package/dist/contracts.js +3 -0
  41. package/dist/contracts.js.map +1 -1
  42. package/dist/doctor.d.ts +14 -1
  43. package/dist/doctor.d.ts.map +1 -1
  44. package/dist/doctor.js +166 -7
  45. package/dist/doctor.js.map +1 -1
  46. package/dist/errors.d.ts +1 -1
  47. package/dist/errors.d.ts.map +1 -1
  48. package/dist/errors.js.map +1 -1
  49. package/dist/fonts/add.d.ts +41 -0
  50. package/dist/fonts/add.d.ts.map +1 -0
  51. package/dist/fonts/add.js +259 -0
  52. package/dist/fonts/add.js.map +1 -0
  53. package/dist/fonts/binary.d.ts +4 -0
  54. package/dist/fonts/binary.d.ts.map +1 -0
  55. package/dist/fonts/binary.js +21 -0
  56. package/dist/fonts/binary.js.map +1 -0
  57. package/dist/fonts/css.d.ts +4 -0
  58. package/dist/fonts/css.d.ts.map +1 -0
  59. package/dist/fonts/css.js +50 -0
  60. package/dist/fonts/css.js.map +1 -0
  61. package/dist/fonts/fontsource.d.ts +107 -0
  62. package/dist/fonts/fontsource.d.ts.map +1 -0
  63. package/dist/fonts/fontsource.js +565 -0
  64. package/dist/fonts/fontsource.js.map +1 -0
  65. package/dist/fonts/index.d.ts +11 -0
  66. package/dist/fonts/index.d.ts.map +1 -0
  67. package/dist/fonts/index.js +11 -0
  68. package/dist/fonts/index.js.map +1 -0
  69. package/dist/fonts/install.d.ts +24 -0
  70. package/dist/fonts/install.d.ts.map +1 -0
  71. package/dist/fonts/install.js +145 -0
  72. package/dist/fonts/install.js.map +1 -0
  73. package/dist/fonts/manifest.d.ts +21 -0
  74. package/dist/fonts/manifest.d.ts.map +1 -0
  75. package/dist/fonts/manifest.js +96 -0
  76. package/dist/fonts/manifest.js.map +1 -0
  77. package/dist/fonts/options.d.ts +9 -0
  78. package/dist/fonts/options.d.ts.map +1 -0
  79. package/dist/fonts/options.js +66 -0
  80. package/dist/fonts/options.js.map +1 -0
  81. package/dist/fonts/schema.d.ts +4 -0
  82. package/dist/fonts/schema.d.ts.map +1 -0
  83. package/dist/fonts/schema.js +316 -0
  84. package/dist/fonts/schema.js.map +1 -0
  85. package/dist/fonts/summary.d.ts +16 -0
  86. package/dist/fonts/summary.d.ts.map +1 -0
  87. package/dist/fonts/summary.js +22 -0
  88. package/dist/fonts/summary.js.map +1 -0
  89. package/dist/fonts/types.d.ts +56 -0
  90. package/dist/fonts/types.d.ts.map +1 -0
  91. package/dist/fonts/types.js +8 -0
  92. package/dist/fonts/types.js.map +1 -0
  93. package/dist/fonts/verify.d.ts +33 -0
  94. package/dist/fonts/verify.d.ts.map +1 -0
  95. package/dist/fonts/verify.js +200 -0
  96. package/dist/fonts/verify.js.map +1 -0
  97. package/dist/html/document-adapter.d.ts +3 -3
  98. package/dist/html/document-adapter.d.ts.map +1 -1
  99. package/dist/html/document-adapter.js +1 -1
  100. package/dist/html/document-adapter.js.map +1 -1
  101. package/dist/html/index.d.ts +1 -1
  102. package/dist/html/index.d.ts.map +1 -1
  103. package/dist/html/parse.d.ts +10 -2
  104. package/dist/html/parse.d.ts.map +1 -1
  105. package/dist/html/parse.js +14 -5
  106. package/dist/html/parse.js.map +1 -1
  107. package/dist/html/validate.d.ts +12 -1
  108. package/dist/html/validate.d.ts.map +1 -1
  109. package/dist/html/validate.js +292 -61
  110. package/dist/html/validate.js.map +1 -1
  111. package/dist/index.d.ts +4 -4
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +2 -2
  114. package/dist/index.js.map +1 -1
  115. package/dist/inspect.d.ts +61 -0
  116. package/dist/inspect.d.ts.map +1 -0
  117. package/dist/inspect.js +325 -0
  118. package/dist/inspect.js.map +1 -0
  119. package/dist/lint.d.ts +63 -0
  120. package/dist/lint.d.ts.map +1 -0
  121. package/dist/lint.js +265 -0
  122. package/dist/lint.js.map +1 -0
  123. package/dist/policy.d.ts +69 -0
  124. package/dist/policy.d.ts.map +1 -0
  125. package/dist/policy.js +361 -0
  126. package/dist/policy.js.map +1 -0
  127. package/dist/preview/main.d.ts +2 -2
  128. package/dist/preview/main.d.ts.map +1 -1
  129. package/dist/preview/main.js +35 -14
  130. package/dist/preview/main.js.map +1 -1
  131. package/dist/preview/timeline-data.d.ts +17 -65
  132. package/dist/preview/timeline-data.d.ts.map +1 -1
  133. package/dist/preview/timeline-host.d.ts.map +1 -1
  134. package/dist/preview/timeline-host.js +73 -38
  135. package/dist/preview/timeline-host.js.map +1 -1
  136. package/dist/preview/timeline-main.d.ts.map +1 -1
  137. package/dist/preview/timeline-main.js +47 -3
  138. package/dist/preview/timeline-main.js.map +1 -1
  139. package/dist/project.d.ts +13 -8
  140. package/dist/project.d.ts.map +1 -1
  141. package/dist/project.js +20 -17
  142. package/dist/project.js.map +1 -1
  143. package/dist/renderer/browser.d.ts +2 -2
  144. package/dist/renderer/browser.d.ts.map +1 -1
  145. package/dist/renderer/browser.js +10 -4
  146. package/dist/renderer/browser.js.map +1 -1
  147. package/dist/renderer/ffmpeg.d.ts +44 -1
  148. package/dist/renderer/ffmpeg.d.ts.map +1 -1
  149. package/dist/renderer/ffmpeg.js +371 -73
  150. package/dist/renderer/ffmpeg.js.map +1 -1
  151. package/dist/renderer/index.d.ts +40 -4
  152. package/dist/renderer/index.d.ts.map +1 -1
  153. package/dist/renderer/index.js +100 -25
  154. package/dist/renderer/index.js.map +1 -1
  155. package/dist/renderer/keyframe-expressions.d.ts +39 -0
  156. package/dist/renderer/keyframe-expressions.d.ts.map +1 -0
  157. package/dist/renderer/keyframe-expressions.js +180 -0
  158. package/dist/renderer/keyframe-expressions.js.map +1 -0
  159. package/dist/renderer/timeline.d.ts +2 -0
  160. package/dist/renderer/timeline.d.ts.map +1 -1
  161. package/dist/renderer/timeline.js +168 -106
  162. package/dist/renderer/timeline.js.map +1 -1
  163. package/dist/runtime/host.d.ts.map +1 -1
  164. package/dist/runtime/host.js +159 -31
  165. package/dist/runtime/host.js.map +1 -1
  166. package/dist/scaffold.d.ts +3 -0
  167. package/dist/scaffold.d.ts.map +1 -1
  168. package/dist/scaffold.js +48 -317
  169. package/dist/scaffold.js.map +1 -1
  170. package/dist/server/composition-html.d.ts +15 -7
  171. package/dist/server/composition-html.d.ts.map +1 -1
  172. package/dist/server/composition-html.js +72 -16
  173. package/dist/server/composition-html.js.map +1 -1
  174. package/dist/server/server.d.ts.map +1 -1
  175. package/dist/server/server.js +56 -6
  176. package/dist/server/server.js.map +1 -1
  177. package/dist/server/timeline-preview-data.d.ts.map +1 -1
  178. package/dist/server/timeline-preview-data.js +12 -23
  179. package/dist/server/timeline-preview-data.js.map +1 -1
  180. package/dist/server/timeline-preview-html.d.ts.map +1 -1
  181. package/dist/server/timeline-preview-html.js +20 -3
  182. package/dist/server/timeline-preview-html.js.map +1 -1
  183. package/dist/templates.d.ts +16 -0
  184. package/dist/templates.d.ts.map +1 -0
  185. package/dist/templates.js +186 -0
  186. package/dist/templates.js.map +1 -0
  187. package/dist/timeline/easing.d.ts +36 -0
  188. package/dist/timeline/easing.d.ts.map +1 -0
  189. package/dist/timeline/easing.js +225 -0
  190. package/dist/timeline/easing.js.map +1 -0
  191. package/dist/timeline/keyframes.d.ts +23 -0
  192. package/dist/timeline/keyframes.d.ts.map +1 -0
  193. package/dist/timeline/keyframes.js +95 -0
  194. package/dist/timeline/keyframes.js.map +1 -0
  195. package/dist/timeline/plan.d.ts +6 -12
  196. package/dist/timeline/plan.d.ts.map +1 -1
  197. package/dist/timeline/plan.js +17 -30
  198. package/dist/timeline/plan.js.map +1 -1
  199. package/dist/timeline/resolve.d.ts +16 -3
  200. package/dist/timeline/resolve.d.ts.map +1 -1
  201. package/dist/timeline/resolve.js +119 -13
  202. package/dist/timeline/resolve.js.map +1 -1
  203. package/dist/timeline/scene.d.ts +126 -0
  204. package/dist/timeline/scene.d.ts.map +1 -0
  205. package/dist/timeline/scene.js +109 -0
  206. package/dist/timeline/scene.js.map +1 -0
  207. package/dist/timeline/schema.d.ts +38 -0
  208. package/dist/timeline/schema.d.ts.map +1 -1
  209. package/dist/timeline/schema.js +290 -9
  210. package/dist/timeline/schema.js.map +1 -1
  211. package/dist/timeline/transitions.d.ts +21 -0
  212. package/dist/timeline/transitions.d.ts.map +1 -0
  213. package/dist/timeline/transitions.js +23 -0
  214. package/dist/timeline/transitions.js.map +1 -0
  215. package/dist/version.d.ts +1 -1
  216. package/dist/version.js +1 -1
  217. package/docs/adr/0007-make-html-documents-the-composition-unit.md +2 -2
  218. package/docs/adr/0008-share-the-composition-document-grammar.md +1 -1
  219. package/docs/adr/0010-make-timelines-the-render-unit.md +3 -2
  220. package/docs/adr/0011-compose-timeline-frames-in-a-live-browser-host.md +1 -1
  221. package/docs/adr/0012-render-timelines-with-segmented-lossless-clip-intermediates.md +1 -1
  222. package/docs/adr/0014-compose-timeline-clips-with-css-blend-modes.md +38 -0
  223. package/docs/adr/0015-inherit-composition-format-from-the-project.md +28 -0
  224. package/docs/adr/0016-author-compositions-as-html-fragments.md +32 -0
  225. package/docs/adr/0017-render-timeless-compositions-as-stills.md +99 -0
  226. package/docs/adr/0018-animate-timeline-clips-with-keyframes.md +35 -0
  227. package/docs/adr/0019-make-same-track-overlap-the-transition-window.md +36 -0
  228. package/docs/adr/0020-crossfade-audio-clips-on-audio-tracks.md +27 -0
  229. package/docs/adr/0021-project-timeline-scenes-once.md +32 -0
  230. package/docs/adr/0022-gate-heavy-operations-with-a-workspace-resource-policy.md +35 -0
  231. package/docs/adr/0023-pin-fonts-as-project-assets.md +98 -0
  232. package/docs/migration-0.4.md +5 -3
  233. package/docs/migration-0.8.md +163 -0
  234. package/docs/preview-testing.md +23 -3
  235. package/docs/{v0.1-design.md → v0.x-design.md} +86 -53
  236. package/examples/blend/README.md +106 -0
  237. package/examples/blend/assets/ink.mp4 +0 -0
  238. package/examples/blend/compositions/aurora.html +55 -0
  239. package/examples/blend/compositions/backdrop.html +74 -0
  240. package/examples/blend/compositions/labels.html +149 -0
  241. package/examples/blend/fy.config.js +11 -0
  242. package/examples/blend/scripts/make-ink.sh +26 -0
  243. package/examples/blend/timelines/blend.timeline.json +155 -0
  244. package/examples/demo/README.md +2 -2
  245. package/examples/demo/compositions/demo.html +243 -251
  246. package/examples/intro/README.md +71 -0
  247. package/examples/intro/assets/fonts/figtree/LICENSE.txt +93 -0
  248. package/examples/intro/assets/fonts/figtree/figtree-latin-wght-normal.woff2 +0 -0
  249. package/examples/intro/assets/fonts/instrument-serif/LICENSE.txt +93 -0
  250. package/examples/intro/assets/fonts/instrument-serif/instrument-serif-latin-400-italic.woff2 +0 -0
  251. package/examples/intro/assets/fonts/space-mono/LICENSE.txt +93 -0
  252. package/examples/intro/assets/fonts/space-mono/space-mono-latin-400-normal.woff2 +0 -0
  253. package/examples/intro/assets/fonts/space-mono/space-mono-latin-700-normal.woff2 +0 -0
  254. package/examples/intro/assets/grain.png +0 -0
  255. package/examples/intro/assets/score.ogg +0 -0
  256. package/examples/intro/compositions/brand.html +412 -0
  257. package/examples/intro/compositions/chrome.controller.js +63 -0
  258. package/examples/intro/compositions/chrome.html +256 -0
  259. package/examples/intro/compositions/lattice.controller.js +148 -0
  260. package/examples/intro/compositions/lattice.html +308 -0
  261. package/examples/intro/compositions/opening.html +504 -0
  262. package/examples/intro/compositions/studio.html +930 -0
  263. package/examples/intro/compositions/theme.css +218 -0
  264. package/examples/intro/fy.config.js +13 -0
  265. package/examples/intro/fy.fonts.json +100 -0
  266. package/examples/intro/scripts/make-grain.mjs +79 -0
  267. package/examples/intro/scripts/make-score.mjs +702 -0
  268. package/examples/intro/timelines/intro.timeline.json +60 -0
  269. package/examples/keyframes/README.md +76 -0
  270. package/examples/keyframes/compositions/backdrop.html +60 -0
  271. package/examples/keyframes/compositions/card.html +99 -0
  272. package/examples/keyframes/fy.config.js +10 -0
  273. package/examples/keyframes/timelines/keyframes.timeline.json +60 -0
  274. package/examples/nested/README.md +112 -0
  275. package/examples/nested/assets/pulse.wav +0 -0
  276. package/examples/nested/compositions/backdrop.html +84 -0
  277. package/examples/nested/compositions/card.html +275 -0
  278. package/examples/nested/compositions/overlay.html +307 -0
  279. package/examples/nested/fy.config.js +13 -0
  280. package/examples/nested/scripts/make-pulse.sh +20 -0
  281. package/examples/nested/timelines/chapter-a.timeline.json +39 -0
  282. package/examples/nested/timelines/chapter-b.timeline.json +39 -0
  283. package/examples/nested/timelines/nested-reel.timeline.json +52 -0
  284. package/examples/static/README.md +17 -0
  285. package/examples/static/compositions/still.html +37 -0
  286. package/examples/static/fy.config.js +9 -0
  287. package/examples/static/timelines/still.timeline.json +13 -0
  288. package/examples/transitions/README.md +128 -0
  289. package/examples/transitions/assets/alpha.wav +0 -0
  290. package/examples/transitions/assets/beta.wav +0 -0
  291. package/examples/transitions/assets/gamma.wav +0 -0
  292. package/examples/transitions/compositions/alpha.html +56 -0
  293. package/examples/transitions/compositions/beta.html +56 -0
  294. package/examples/transitions/compositions/gamma.html +56 -0
  295. package/examples/transitions/fy.config.js +12 -0
  296. package/examples/transitions/timelines/audio-crossfade.timeline.json +44 -0
  297. package/examples/transitions/timelines/transitions.timeline.json +31 -0
  298. package/examples/video/README.md +4 -4
  299. package/examples/video/compositions/video-mp4.html +349 -357
  300. package/examples/video/compositions/video-overlay.html +337 -345
  301. package/examples/video/compositions/video.html +349 -357
  302. package/examples/webgl/README.md +1 -1
  303. package/examples/webgl/compositions/webgl.html +205 -213
  304. package/package.json +13 -5
  305. package/scaffolds/init/AGENTS.md +131 -0
  306. package/scaffolds/init/README.md +56 -0
  307. package/scaffolds/init/compositions/hello.html +79 -0
  308. package/scaffolds/init/fy.config.js +9 -0
  309. package/scaffolds/init/gitignore.template +1 -0
  310. package/scaffolds/init/package.json +11 -0
  311. package/scaffolds/init/props/hello.json +4 -0
  312. package/scaffolds/init/props/main.json +6 -0
  313. package/scaffolds/init/timelines/main.timeline.json +20 -0
  314. package/scaffolds/local-models/LOCAL-MODELS.md +77 -0
  315. package/scaffolds/local-models/fy.policy.json +5 -0
  316. package/scaffolds/local-models/opencode/opencode.jsonc +17 -0
  317. package/scaffolds/local-models/pi/APPEND_SYSTEM.md +21 -0
  318. package/scaffolds/local-models/pi/sandbox.json +15 -0
  319. package/scaffolds/local-models/pi/settings.json +15 -0
  320. package/skills/frameyard/README.md +1 -0
  321. package/skills/frameyard/SKILL.md +59 -59
  322. package/skills/frameyard/references/audio-assets.md +32 -3
  323. package/skills/frameyard/references/common-mistakes.md +81 -7
  324. package/skills/frameyard/references/controllers.md +5 -4
  325. package/skills/frameyard/references/deterministic-authoring.md +49 -37
  326. package/skills/frameyard/references/diagnostics.md +42 -4
  327. package/skills/frameyard/references/failure-recovery.md +56 -10
  328. package/skills/frameyard/references/fonts.md +132 -0
  329. package/skills/frameyard/references/json-results.md +165 -10
  330. package/skills/frameyard/references/quick-reference.md +222 -0
  331. package/skills/frameyard/references/timelines.md +109 -15
  332. /package/examples/demo/{video.config.js → fy.config.js} +0 -0
  333. /package/examples/video/{video.config.js → fy.config.js} +0 -0
  334. /package/examples/webgl/{video.config.js → fy.config.js} +0 -0
@@ -1,362 +1,354 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <script type="application/json" data-fy="props">
6
- {
7
- "kicker": "Frameyard / Clip Study 001",
8
- "title": "Moving",
9
- "titleAccent": "Image",
10
- "subtitle": "A local clip, loaded once and seeked twice from the composition clock.",
11
- "detail": "Detail / second pass",
12
- "accent": "#ffc37a"
13
- }
14
- </script>
15
- <style>
16
- @keyframes fade-in {
17
- from {
18
- opacity: 0;
19
- }
20
- to {
21
- opacity: 1;
22
- }
23
- }
24
- @keyframes rise {
25
- from {
26
- opacity: 0;
27
- transform: translateY(42px);
28
- }
29
- to {
30
- opacity: 1;
31
- transform: translateY(0);
32
- }
33
- }
34
- @keyframes draw {
35
- from {
36
- opacity: 0;
37
- transform: scaleX(0);
38
- }
39
- to {
40
- opacity: 1;
41
- transform: scaleX(1);
42
- }
43
- }
44
- @keyframes outro-fade {
45
- from {
46
- opacity: 0;
47
- }
48
- to {
49
- opacity: 1;
50
- }
51
- }
52
- html,
53
- body,
54
- fy-composition {
55
- background: #04080b;
56
- }
57
- #scene {
58
- position: relative;
59
- width: 100%;
60
- height: 100%;
61
- overflow: hidden;
62
- isolation: isolate;
63
- background: #04080b;
64
- color: #eef4f1;
65
- font-family: Inter, "Helvetica Neue", ui-sans-serif, system-ui, sans-serif;
66
- }
67
- #hero {
68
- position: absolute;
69
- inset: 0;
70
- display: block;
71
- width: 100%;
72
- height: 100%;
73
- object-fit: cover;
74
- transform: scale(calc(1 + var(--fy-progress) * 0.035));
75
- transform-origin: center;
76
- }
77
- #scrim {
78
- position: absolute;
79
- inset: 0;
80
- background:
81
- linear-gradient(
82
- 90deg,
83
- rgba(4, 8, 11, 0.94) 0%,
84
- rgba(4, 8, 11, 0.8) 24%,
85
- rgba(4, 8, 11, 0.24) 52%,
86
- rgba(4, 8, 11, 0) 74%
87
- ),
88
- linear-gradient(0deg, rgba(4, 8, 11, 0.9) 0%, rgba(4, 8, 11, 0) 34%);
89
- }
90
- #vignette {
91
- position: absolute;
92
- inset: 0;
93
- background: radial-gradient(ellipse at 62% 44%, transparent 42%, rgba(0, 0, 0, 0.3) 100%);
94
- pointer-events: none;
95
- }
96
- #frame-border {
97
- position: absolute;
98
- inset: 36px;
99
- border: 1px solid rgba(238, 244, 241, 0.16);
100
- pointer-events: none;
101
- }
102
- #header {
103
- position: absolute;
104
- top: 80px;
105
- left: 148px;
106
- right: 148px;
107
- display: flex;
108
- justify-content: space-between;
109
- align-items: center;
110
- gap: 32px;
111
- animation: fade-in 1s linear both;
112
- }
113
- #kicker {
114
- display: flex;
115
- align-items: center;
116
- gap: 15px;
117
- font:
118
- 600 14px/1 ui-monospace,
119
- monospace;
120
- letter-spacing: 0.24em;
121
- text-transform: uppercase;
122
- color: var(--fy-prop-accent);
123
- }
124
- #kicker::before {
125
- content: "";
126
- width: 8px;
127
- height: 8px;
128
- background: var(--fy-prop-accent);
129
- box-shadow: 0 0 16px var(--fy-prop-accent);
130
- }
131
- #format {
132
- font:
133
- 500 12px/1 ui-monospace,
134
- monospace;
135
- letter-spacing: 0.16em;
136
- text-transform: uppercase;
137
- color: #8b999c;
138
- }
139
- #copy {
140
- position: absolute;
141
- top: 278px;
142
- left: 148px;
143
- width: 860px;
144
- }
145
- #title {
146
- margin: 0;
147
- font-size: 174px;
148
- line-height: 0.84;
149
- letter-spacing: -0.064em;
150
- font-weight: 660;
151
- }
152
- #title span,
153
- #title em {
154
- display: block;
155
- animation: rise 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
156
- }
157
- #title em {
158
- margin-top: 0.06em;
159
- font-family: "Iowan Old Style", "Palatino Linotype", Georgia, ui-serif, serif;
160
- font-style: italic;
161
- font-weight: 400;
162
- letter-spacing: -0.035em;
163
- color: var(--fy-prop-accent);
164
- }
165
- #subtitle {
166
- width: 720px;
167
- margin: 38px 0 0;
168
- font-size: 29px;
169
- line-height: 1.5;
170
- font-weight: 420;
171
- color: #a6b3b6;
172
- animation: rise 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
173
- }
174
- #footer {
175
- position: absolute;
176
- left: 148px;
177
- right: 148px;
178
- bottom: 70px;
179
- contain: layout paint style;
180
- animation: fade-in 1s linear both;
181
- }
182
- #rule {
183
- position: relative;
184
- height: 1px;
185
- background: rgba(238, 244, 241, 0.16);
186
- transform-origin: left center;
187
- animation: draw 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
188
- }
189
- #progress {
190
- position: absolute;
191
- inset: 0 auto 0 0;
192
- width: calc(var(--fy-progress) * 100%);
193
- background: var(--fy-prop-accent);
194
- box-shadow: 0 0 14px var(--fy-prop-accent);
195
- }
196
- #footer-row {
197
- display: flex;
198
- justify-content: space-between;
199
- align-items: baseline;
200
- gap: 24px;
201
- margin-top: 18px;
202
- font:
203
- 500 12px/1 ui-monospace,
204
- monospace;
205
- letter-spacing: 0.14em;
206
- color: #879598;
207
- text-transform: uppercase;
208
- }
209
- #footer-row strong {
210
- color: #edf5f2;
211
- font-weight: 600;
212
- }
213
- #footer-row .accent {
214
- color: var(--fy-prop-accent);
215
- }
216
- #frame-counter {
217
- display: inline-block;
218
- min-width: 3ch;
219
- text-align: right;
220
- }
221
- #frame-counter::after {
222
- counter-reset: fy-frame var(--fy-frame);
223
- content: counter(fy-frame);
224
- }
225
- #detail {
226
- position: absolute;
227
- right: 148px;
228
- bottom: 154px;
229
- width: 440px;
230
- }
231
- #detail-bar {
232
- display: flex;
233
- justify-content: space-between;
234
- align-items: baseline;
235
- gap: 24px;
236
- margin-bottom: 10px;
237
- contain: layout paint style;
238
- font:
239
- 600 11px/1 ui-monospace,
240
- monospace;
241
- letter-spacing: 0.18em;
242
- text-transform: uppercase;
243
- }
244
- #detail-bar > span:first-child {
245
- color: var(--fy-prop-accent);
246
- }
247
- #detail-time {
248
- color: #98a5a6;
249
- font-weight: 500;
250
- }
251
- #detail-window {
252
- position: relative;
253
- width: 440px;
254
- height: 248px;
255
- overflow: hidden;
256
- border: 1px solid rgba(255, 195, 122, 0.65);
257
- background: #000;
258
- box-shadow: 0 24px 90px rgba(0, 0, 0, 0.55);
259
- }
260
- #detail-clip {
261
- display: block;
262
- width: 100%;
263
- height: 100%;
264
- object-fit: cover;
265
- object-position: 68% 50%;
266
- transform: scale(1.3);
267
- }
268
- #detail-tint {
269
- position: absolute;
270
- inset: 0;
271
- background: linear-gradient(0deg, rgba(4, 8, 11, 0.28) 0%, rgba(4, 8, 11, 0) 45%);
272
- pointer-events: none;
273
- }
274
- #outro-fade {
275
- position: absolute;
276
- inset: 0;
277
- background: #04080b;
278
- pointer-events: none;
279
- opacity: 0;
280
- animation: outro-fade 1s linear both;
281
- }
282
- </style>
283
- </head>
284
- <body>
285
- <fy-composition width="1920" height="1080" fps="30" duration-in-frames="360">
286
- <div id="scene">
287
- <video
288
- id="hero"
289
- src="assets/clip.mp4"
290
- data-fy-start="0"
291
- data-fy-trim="0"
292
- data-fy-duration="12"
293
- data-fy-volume="0.85"
294
- ></video>
295
- <div id="scrim"></div>
296
- <div id="vignette"></div>
297
- <div id="frame-border"></div>
1
+ <script type="application/json" data-fy="props">
2
+ {
3
+ "kicker": "Frameyard / Clip Study 001",
4
+ "title": "Moving",
5
+ "titleAccent": "Image",
6
+ "subtitle": "A local clip, loaded once and seeked twice from the composition clock.",
7
+ "detail": "Detail / second pass",
8
+ "accent": "#ffc37a"
9
+ }
10
+ </script>
11
+ <style>
12
+ @keyframes fade-in {
13
+ from {
14
+ opacity: 0;
15
+ }
16
+ to {
17
+ opacity: 1;
18
+ }
19
+ }
20
+ @keyframes rise {
21
+ from {
22
+ opacity: 0;
23
+ transform: translateY(42px);
24
+ }
25
+ to {
26
+ opacity: 1;
27
+ transform: translateY(0);
28
+ }
29
+ }
30
+ @keyframes draw {
31
+ from {
32
+ opacity: 0;
33
+ transform: scaleX(0);
34
+ }
35
+ to {
36
+ opacity: 1;
37
+ transform: scaleX(1);
38
+ }
39
+ }
40
+ @keyframes outro-fade {
41
+ from {
42
+ opacity: 0;
43
+ }
44
+ to {
45
+ opacity: 1;
46
+ }
47
+ }
48
+ html,
49
+ body,
50
+ fy-composition {
51
+ background: #04080b;
52
+ }
53
+ #scene {
54
+ position: relative;
55
+ width: 100%;
56
+ height: 100%;
57
+ overflow: hidden;
58
+ isolation: isolate;
59
+ background: #04080b;
60
+ color: #eef4f1;
61
+ font-family: Inter, "Helvetica Neue", ui-sans-serif, system-ui, sans-serif;
62
+ }
63
+ #hero {
64
+ position: absolute;
65
+ inset: 0;
66
+ display: block;
67
+ width: 100%;
68
+ height: 100%;
69
+ object-fit: cover;
70
+ transform: scale(calc(1 + var(--fy-progress) * 0.035));
71
+ transform-origin: center;
72
+ }
73
+ #scrim {
74
+ position: absolute;
75
+ inset: 0;
76
+ background:
77
+ linear-gradient(
78
+ 90deg,
79
+ rgba(4, 8, 11, 0.94) 0%,
80
+ rgba(4, 8, 11, 0.8) 24%,
81
+ rgba(4, 8, 11, 0.24) 52%,
82
+ rgba(4, 8, 11, 0) 74%
83
+ ),
84
+ linear-gradient(0deg, rgba(4, 8, 11, 0.9) 0%, rgba(4, 8, 11, 0) 34%);
85
+ }
86
+ #vignette {
87
+ position: absolute;
88
+ inset: 0;
89
+ background: radial-gradient(ellipse at 62% 44%, transparent 42%, rgba(0, 0, 0, 0.3) 100%);
90
+ pointer-events: none;
91
+ }
92
+ #frame-border {
93
+ position: absolute;
94
+ inset: 36px;
95
+ border: 1px solid rgba(238, 244, 241, 0.16);
96
+ pointer-events: none;
97
+ }
98
+ #header {
99
+ position: absolute;
100
+ top: 80px;
101
+ left: 148px;
102
+ right: 148px;
103
+ display: flex;
104
+ justify-content: space-between;
105
+ align-items: center;
106
+ gap: 32px;
107
+ animation: fade-in 1s linear both;
108
+ }
109
+ #kicker {
110
+ display: flex;
111
+ align-items: center;
112
+ gap: 15px;
113
+ font:
114
+ 600 14px/1 ui-monospace,
115
+ monospace;
116
+ letter-spacing: 0.24em;
117
+ text-transform: uppercase;
118
+ color: var(--fy-prop-accent);
119
+ }
120
+ #kicker::before {
121
+ content: "";
122
+ width: 8px;
123
+ height: 8px;
124
+ background: var(--fy-prop-accent);
125
+ box-shadow: 0 0 16px var(--fy-prop-accent);
126
+ }
127
+ #format {
128
+ font:
129
+ 500 12px/1 ui-monospace,
130
+ monospace;
131
+ letter-spacing: 0.16em;
132
+ text-transform: uppercase;
133
+ color: #8b999c;
134
+ }
135
+ #copy {
136
+ position: absolute;
137
+ top: 278px;
138
+ left: 148px;
139
+ width: 860px;
140
+ }
141
+ #title {
142
+ margin: 0;
143
+ font-size: 174px;
144
+ line-height: 0.84;
145
+ letter-spacing: -0.064em;
146
+ font-weight: 660;
147
+ }
148
+ #title span,
149
+ #title em {
150
+ display: block;
151
+ animation: rise 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
152
+ }
153
+ #title em {
154
+ margin-top: 0.06em;
155
+ font-family: "Iowan Old Style", "Palatino Linotype", Georgia, ui-serif, serif;
156
+ font-style: italic;
157
+ font-weight: 400;
158
+ letter-spacing: -0.035em;
159
+ color: var(--fy-prop-accent);
160
+ }
161
+ #subtitle {
162
+ width: 720px;
163
+ margin: 38px 0 0;
164
+ font-size: 29px;
165
+ line-height: 1.5;
166
+ font-weight: 420;
167
+ color: #a6b3b6;
168
+ animation: rise 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
169
+ }
170
+ #footer {
171
+ position: absolute;
172
+ left: 148px;
173
+ right: 148px;
174
+ bottom: 70px;
175
+ contain: layout paint style;
176
+ animation: fade-in 1s linear both;
177
+ }
178
+ #rule {
179
+ position: relative;
180
+ height: 1px;
181
+ background: rgba(238, 244, 241, 0.16);
182
+ transform-origin: left center;
183
+ animation: draw 1s cubic-bezier(0.215, 0.61, 0.355, 1) both;
184
+ }
185
+ #progress {
186
+ position: absolute;
187
+ inset: 0 auto 0 0;
188
+ width: calc(var(--fy-progress) * 100%);
189
+ background: var(--fy-prop-accent);
190
+ box-shadow: 0 0 14px var(--fy-prop-accent);
191
+ }
192
+ #footer-row {
193
+ display: flex;
194
+ justify-content: space-between;
195
+ align-items: baseline;
196
+ gap: 24px;
197
+ margin-top: 18px;
198
+ font:
199
+ 500 12px/1 ui-monospace,
200
+ monospace;
201
+ letter-spacing: 0.14em;
202
+ color: #879598;
203
+ text-transform: uppercase;
204
+ }
205
+ #footer-row strong {
206
+ color: #edf5f2;
207
+ font-weight: 600;
208
+ }
209
+ #footer-row .accent {
210
+ color: var(--fy-prop-accent);
211
+ }
212
+ #frame-counter {
213
+ display: inline-block;
214
+ min-width: 3ch;
215
+ text-align: right;
216
+ }
217
+ #frame-counter::after {
218
+ counter-reset: fy-frame var(--fy-frame);
219
+ content: counter(fy-frame);
220
+ }
221
+ #detail {
222
+ position: absolute;
223
+ right: 148px;
224
+ bottom: 154px;
225
+ width: 440px;
226
+ }
227
+ #detail-bar {
228
+ display: flex;
229
+ justify-content: space-between;
230
+ align-items: baseline;
231
+ gap: 24px;
232
+ margin-bottom: 10px;
233
+ contain: layout paint style;
234
+ font:
235
+ 600 11px/1 ui-monospace,
236
+ monospace;
237
+ letter-spacing: 0.18em;
238
+ text-transform: uppercase;
239
+ }
240
+ #detail-bar > span:first-child {
241
+ color: var(--fy-prop-accent);
242
+ }
243
+ #detail-time {
244
+ color: #98a5a6;
245
+ font-weight: 500;
246
+ }
247
+ #detail-window {
248
+ position: relative;
249
+ width: 440px;
250
+ height: 248px;
251
+ overflow: hidden;
252
+ border: 1px solid rgba(255, 195, 122, 0.65);
253
+ background: #000;
254
+ box-shadow: 0 24px 90px rgba(0, 0, 0, 0.55);
255
+ }
256
+ #detail-clip {
257
+ display: block;
258
+ width: 100%;
259
+ height: 100%;
260
+ object-fit: cover;
261
+ object-position: 68% 50%;
262
+ transform: scale(1.3);
263
+ }
264
+ #detail-tint {
265
+ position: absolute;
266
+ inset: 0;
267
+ background: linear-gradient(0deg, rgba(4, 8, 11, 0.28) 0%, rgba(4, 8, 11, 0) 45%);
268
+ pointer-events: none;
269
+ }
270
+ #outro-fade {
271
+ position: absolute;
272
+ inset: 0;
273
+ background: #04080b;
274
+ pointer-events: none;
275
+ opacity: 0;
276
+ animation: outro-fade 1s linear both;
277
+ }
278
+ </style>
279
+ <fy-composition width="1920" height="1080" fps="30" duration-in-frames="360">
280
+ <div id="scene">
281
+ <video
282
+ id="hero"
283
+ src="assets/clip.mp4"
284
+ data-fy-start="0"
285
+ data-fy-trim="0"
286
+ data-fy-duration="12"
287
+ data-fy-volume="0.85"
288
+ ></video>
289
+ <div id="scrim"></div>
290
+ <div id="vignette"></div>
291
+ <div id="frame-border"></div>
298
292
 
299
- <header id="header" data-fy-anim-start="8" data-fy-anim-duration="28">
300
- <div id="kicker" data-fy-text="kicker"></div>
301
- <div id="format">Embedded video / H.264 + AAC / 30 FPS</div>
302
- </header>
293
+ <header id="header" data-fy-anim-start="8" data-fy-anim-duration="28">
294
+ <div id="kicker" data-fy-text="kicker"></div>
295
+ <div id="format">Embedded video / H.264 + AAC / 30 FPS</div>
296
+ </header>
303
297
 
304
- <div id="copy">
305
- <h1 id="title">
306
- <span
307
- data-fy-text="title"
308
- data-fy-anim-start="14"
309
- data-fy-anim-duration="44"
310
- data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
311
- ></span>
312
- <em
313
- data-fy-text="titleAccent"
314
- data-fy-anim-start="26"
315
- data-fy-anim-duration="44"
316
- data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
317
- ></em>
318
- </h1>
319
- <p
320
- id="subtitle"
321
- data-fy-text="subtitle"
322
- data-fy-anim-start="40"
323
- data-fy-anim-duration="40"
324
- data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
325
- ></p>
326
- </div>
298
+ <div id="copy">
299
+ <h1 id="title">
300
+ <span
301
+ data-fy-text="title"
302
+ data-fy-anim-start="14"
303
+ data-fy-anim-duration="44"
304
+ data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
305
+ ></span>
306
+ <em
307
+ data-fy-text="titleAccent"
308
+ data-fy-anim-start="26"
309
+ data-fy-anim-duration="44"
310
+ data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
311
+ ></em>
312
+ </h1>
313
+ <p
314
+ id="subtitle"
315
+ data-fy-text="subtitle"
316
+ data-fy-anim-start="40"
317
+ data-fy-anim-duration="40"
318
+ data-fy-anim-easing="cubic-bezier(0.215, 0.61, 0.355, 1)"
319
+ ></p>
320
+ </div>
327
321
 
328
- <div id="detail">
329
- <div id="detail-bar">
330
- <span data-fy-text="detail"></span>
331
- <span id="detail-time">SRC 5.8–10.8 S</span>
332
- </div>
333
- <div id="detail-window">
334
- <video
335
- id="detail-clip"
336
- src="assets/clip.mp4"
337
- data-fy-start="120"
338
- data-fy-trim="5.8"
339
- data-fy-duration="5"
340
- data-fy-audio="off"
341
- ></video>
342
- <div id="detail-tint"></div>
343
- </div>
344
- </div>
345
-
346
- <div id="footer" data-fy-anim-start="46" data-fy-anim-duration="30">
347
- <div id="rule" data-fy-anim-start="52" data-fy-anim-duration="50">
348
- <div id="progress"></div>
349
- </div>
350
- <div id="footer-row">
351
- <span>Hero / SRC <strong>0.0–12.0 S</strong></span>
352
- <span>Frame <strong id="frame-counter"></strong> / 359</span>
353
- <span class="accent">Frame-seeked</span>
354
- <span>12.00 S · 30 FPS</span>
355
- </div>
356
- </div>
322
+ <div id="detail">
323
+ <div id="detail-bar">
324
+ <span data-fy-text="detail"></span>
325
+ <span id="detail-time">SRC 5.8–10.8 S</span>
326
+ </div>
327
+ <div id="detail-window">
328
+ <video
329
+ id="detail-clip"
330
+ src="assets/clip.mp4"
331
+ data-fy-start="120"
332
+ data-fy-trim="5.8"
333
+ data-fy-duration="5"
334
+ data-fy-audio="off"
335
+ ></video>
336
+ <div id="detail-tint"></div>
337
+ </div>
338
+ </div>
357
339
 
358
- <div id="outro-fade" data-fy-anim-start="329" data-fy-anim-duration="30"></div>
340
+ <div id="footer" data-fy-anim-start="46" data-fy-anim-duration="30">
341
+ <div id="rule" data-fy-anim-start="52" data-fy-anim-duration="50">
342
+ <div id="progress"></div>
359
343
  </div>
360
- </fy-composition>
361
- </body>
362
- </html>
344
+ <div id="footer-row">
345
+ <span>Hero / SRC <strong>0.0–12.0 S</strong></span>
346
+ <span>Frame <strong id="frame-counter"></strong> / 359</span>
347
+ <span class="accent">Frame-seeked</span>
348
+ <span>12.00 S · 30 FPS</span>
349
+ </div>
350
+ </div>
351
+
352
+ <div id="outro-fade" data-fy-anim-start="329" data-fy-anim-duration="30"></div>
353
+ </div>
354
+ </fy-composition>