flomotion 0.2.0 → 0.4.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 (129) hide show
  1. package/CHANGELOG.md +58 -2
  2. package/LICENSE +1 -1
  3. package/README.md +29 -20
  4. package/dist/bin.mjs +6279 -2582
  5. package/dist/chunks/{chunk-QG2MOGKO.mjs → chunk-IGG2VZB6.mjs} +178 -14
  6. package/dist/chunks/{chunk-AVP5XX4G.mjs → chunk-PEC2UVQY.mjs} +138 -108
  7. package/dist/chunks/{chunk-IUSYVGP6.mjs → chunk-TTHAZGRG.mjs} +7 -7
  8. package/dist/chunks/{chunk-JCLRAREG.mjs → chunk-XWY6CUY6.mjs} +16 -16
  9. package/dist/chunks/{lock-MLQUU7X3.mjs → lock-WGPR7CJ2.mjs} +3 -3
  10. package/dist/components.mjs +19 -13
  11. package/dist/core.mjs +12 -12
  12. package/dist/hooks.mjs +8 -12
  13. package/dist/jsx-dev-runtime.mjs +1 -1
  14. package/dist/jsx-runtime.mjs +1 -1
  15. package/docs/components/Adjustment.md +2 -2
  16. package/docs/components/Audio.md +2 -2
  17. package/docs/components/B.md +3 -3
  18. package/docs/components/Captions.md +2 -2
  19. package/docs/components/Card.md +2 -2
  20. package/docs/components/Center.md +2 -2
  21. package/docs/components/Chart.md +2 -2
  22. package/docs/components/Chip.md +2 -2
  23. package/docs/components/Circle.md +2 -2
  24. package/docs/components/Clip.md +2 -2
  25. package/docs/components/CodeBlock.md +2 -2
  26. package/docs/components/Composition.md +2 -2
  27. package/docs/components/Counter.md +2 -2
  28. package/docs/components/Cursor.md +2 -2
  29. package/docs/components/Fonts.md +2 -2
  30. package/docs/components/GlassCard.md +2 -2
  31. package/docs/components/Grid.md +2 -2
  32. package/docs/components/Group.md +2 -2
  33. package/docs/components/Highlight.md +3 -3
  34. package/docs/components/I.md +3 -3
  35. package/docs/components/Image.md +2 -2
  36. package/docs/components/Line.md +2 -2
  37. package/docs/components/Marker.md +2 -2
  38. package/docs/components/Path.md +2 -2
  39. package/docs/components/Polygon.md +2 -2
  40. package/docs/components/Precomp.md +2 -2
  41. package/docs/components/ProgressRing.md +2 -2
  42. package/docs/components/Rect.md +2 -2
  43. package/docs/components/RoundRect.md +2 -2
  44. package/docs/components/SafeArea.md +2 -2
  45. package/docs/components/Scene.md +2 -2
  46. package/docs/components/Sequence.md +2 -2
  47. package/docs/components/Span.md +3 -3
  48. package/docs/components/SplitText.md +2 -2
  49. package/docs/components/Stack.md +2 -2
  50. package/docs/components/Stagger.md +2 -2
  51. package/docs/components/Strike.md +3 -3
  52. package/docs/components/Svg.md +2 -2
  53. package/docs/components/Text.md +2 -2
  54. package/docs/components/Title.md +2 -2
  55. package/docs/components/Track.md +2 -2
  56. package/docs/components/UIMock.md +2 -2
  57. package/docs/components/Underline.md +3 -3
  58. package/docs/components/Video.md +2 -2
  59. package/docs/gate2-manual-checklist.md +10 -9
  60. package/docs/hyperframes-notes.md +20 -20
  61. package/docs/later.md +23 -16
  62. package/docs/spec.md +83 -22
  63. package/package.json +1 -2
  64. package/skills/flomotion-studio/CHANGELOG.md +39 -0
  65. package/skills/flomotion-studio/README.md +81 -0
  66. package/skills/flomotion-studio/SKILL.md +90 -0
  67. package/skills/flomotion-studio/config/thresholds.md +191 -0
  68. package/skills/flomotion-studio/dataset/annotations/ansarada.md +53 -0
  69. package/skills/flomotion-studio/dataset/annotations/canva.md +49 -0
  70. package/skills/flomotion-studio/dataset/annotations/clickup.md +60 -0
  71. package/skills/flomotion-studio/dataset/annotations/gemini-stub.md +39 -0
  72. package/skills/flomotion-studio/dataset/annotations/monday.md +51 -0
  73. package/skills/flomotion-studio/dataset/annotations/phantom.md +53 -0
  74. package/skills/flomotion-studio/dataset/annotations/slack.md +54 -0
  75. package/skills/flomotion-studio/dataset/annotations/unknown-7.md +39 -0
  76. package/skills/flomotion-studio/dataset/annotations/vaylens.md +53 -0
  77. package/skills/flomotion-studio/dataset/brief-template.md +110 -0
  78. package/skills/flomotion-studio/dataset/rating-sheet.md +28 -0
  79. package/skills/flomotion-studio/dataset/schema.md +44 -0
  80. package/skills/flomotion-studio/evals/README.md +33 -0
  81. package/skills/flomotion-studio/evals/briefs/briefs.md +25 -0
  82. package/skills/{motion-studio/looks → flomotion-studio/examples/engine-looks}/kinetic.scene.tsx +1 -1
  83. package/skills/{motion-studio/looks → flomotion-studio/examples/engine-looks}/minimal.scene.tsx +1 -1
  84. package/skills/{motion-studio/looks → flomotion-studio/examples/engine-looks}/sketch.scene.tsx +1 -1
  85. package/skills/flomotion-studio/examples/flomotion-ad/LOG.md +39 -0
  86. package/skills/flomotion-studio/examples/flomotion-ad/brief.md +41 -0
  87. package/skills/flomotion-studio/examples/flomotion-ad/ideas.md +12 -0
  88. package/skills/flomotion-studio/examples/flomotion-ad/project.tsx +1694 -0
  89. package/skills/flomotion-studio/examples/flomotion-ad/script.md +28 -0
  90. package/skills/flomotion-studio/examples/flomotion-ad/storyboard.md +93 -0
  91. package/skills/{motion-studio → flomotion-studio}/examples/saas-promo/README.md +1 -1
  92. package/skills/{motion-studio → flomotion-studio}/examples/saas-promo/make-assets.sh +1 -1
  93. package/skills/{motion-studio → flomotion-studio}/examples/saas-promo/project.tsx +3 -3
  94. package/skills/flomotion-studio/looks/bold-kinetic.md +122 -0
  95. package/skills/flomotion-studio/looks/clean-light.md +122 -0
  96. package/skills/flomotion-studio/looks/dark-product.md +120 -0
  97. package/skills/flomotion-studio/references/anti-patterns.md +36 -0
  98. package/skills/flomotion-studio/references/assets.md +42 -0
  99. package/skills/flomotion-studio/references/block-recipes.md +249 -0
  100. package/skills/flomotion-studio/references/blocks.md +114 -0
  101. package/skills/flomotion-studio/references/catalogue.md +53 -0
  102. package/skills/flomotion-studio/references/checks.md +87 -0
  103. package/skills/flomotion-studio/references/clean-styles.md +56 -0
  104. package/skills/{motion-studio → flomotion-studio}/references/components.md +94 -94
  105. package/skills/flomotion-studio/references/copywriting.md +64 -0
  106. package/skills/flomotion-studio/references/decision-tables.md +80 -0
  107. package/skills/flomotion-studio/references/interview.md +145 -0
  108. package/skills/flomotion-studio/references/looks.md +45 -0
  109. package/skills/flomotion-studio/references/mcp-tools.md +70 -0
  110. package/skills/flomotion-studio/references/motion.md +68 -0
  111. package/skills/flomotion-studio/references/patterns.md +45 -0
  112. package/skills/flomotion-studio/references/review.md +56 -0
  113. package/skills/flomotion-studio/references/script-craft.md +59 -0
  114. package/skills/flomotion-studio/references/sound.md +57 -0
  115. package/skills/flomotion-studio/references/story-templates.md +52 -0
  116. package/skills/flomotion-studio/references/storyboard.md +62 -0
  117. package/skills/flomotion-studio/references/styles.md +70 -0
  118. package/skills/flomotion-studio/references/transitions.md +62 -0
  119. package/skills/flomotion-studio/references/typography.md +46 -0
  120. package/skills/flomotion-studio/references/workflow.md +96 -0
  121. package/skills/motion-studio/SKILL.md +0 -87
  122. package/skills/motion-studio/looks/kinetic.json +0 -89
  123. package/skills/motion-studio/looks/minimal.json +0 -91
  124. package/skills/motion-studio/looks/sketch.json +0 -83
  125. package/skills/motion-studio/references/motion.md +0 -73
  126. package/skills/motion-studio/references/review.md +0 -32
  127. package/skills/motion-studio/references/saas-promo.md +0 -29
  128. package/skills/motion-studio/references/sound.md +0 -47
  129. package/skills/motion-studio/references/typography.md +0 -50
@@ -1,91 +0,0 @@
1
- {
2
- "id": "minimal",
3
- "name": "Minimal",
4
- "description": "Calm and precise. DM Sans, soft neutrals, slow eases, dissolves.",
5
- "palette": {
6
- "bg": "#f6f5f2",
7
- "fg": "#14141a",
8
- "primary": "#2f5bff",
9
- "accent": "#14141a",
10
- "surface": "#ffffff",
11
- "muted": "#7a7a86"
12
- },
13
- "background": "#f6f5f2",
14
- "fonts": [
15
- {
16
- "id": "display",
17
- "family": "DM Sans",
18
- "source": "google",
19
- "weights": [500, 700],
20
- "variable": true,
21
- "axes": {
22
- "wght": [300, 700]
23
- },
24
- "subsets": ["latin"]
25
- },
26
- {
27
- "id": "body",
28
- "family": "DM Sans",
29
- "source": "google",
30
- "weights": [400, 500],
31
- "variable": true,
32
- "axes": {
33
- "wght": [300, 700]
34
- },
35
- "subsets": ["latin"]
36
- },
37
- {
38
- "id": "mono",
39
- "family": "IBM Plex Mono",
40
- "source": "google",
41
- "weights": [400],
42
- "subsets": ["latin"]
43
- }
44
- ],
45
- "type": {
46
- "display": {
47
- "font": "display",
48
- "size": 88,
49
- "weight": 600,
50
- "tracking": -20,
51
- "leading": 1.06
52
- },
53
- "body": {
54
- "font": "body",
55
- "size": 40,
56
- "weight": 400,
57
- "tracking": 0,
58
- "leading": 1.4
59
- },
60
- "mono": {
61
- "font": "mono",
62
- "size": 32,
63
- "weight": 400,
64
- "tracking": 0,
65
- "leading": 1.5
66
- },
67
- "numerals": {
68
- "font": "display",
69
- "size": 150,
70
- "weight": 600,
71
- "tracking": -25,
72
- "leading": 1
73
- }
74
- },
75
- "easing": {
76
- "in": "power3.out",
77
- "out": "power3.in",
78
- "pop": "back.out(1.2)",
79
- "settle": "sine.inOut",
80
- "spring": "spring(120,22)"
81
- },
82
- "transition": {
83
- "type": "dissolve",
84
- "duration": 0.6
85
- },
86
- "grain": 0,
87
- "sound": {
88
- "ui/pop": "freesound:soft-pop",
89
- "ui/tick": "freesound:tick"
90
- }
91
- }
@@ -1,83 +0,0 @@
1
- {
2
- "id": "sketch",
3
- "name": "Sketch",
4
- "description": "Hand-drawn and playful. Permanent Marker display, paper colours, bouncy eases, wipes.",
5
- "palette": {
6
- "bg": "#fbf4e4",
7
- "fg": "#2a2420",
8
- "primary": "#e8452c",
9
- "accent": "#2d7dd2",
10
- "surface": "#fffaf0",
11
- "muted": "#8c7f70"
12
- },
13
- "background": "#fbf4e4",
14
- "fonts": [
15
- {
16
- "id": "display",
17
- "family": "Permanent Marker",
18
- "source": "google",
19
- "weights": [400],
20
- "subsets": ["latin"]
21
- },
22
- {
23
- "id": "body",
24
- "family": "Patrick Hand",
25
- "source": "google",
26
- "weights": [400],
27
- "subsets": ["latin"]
28
- },
29
- {
30
- "id": "mono",
31
- "family": "Space Mono",
32
- "source": "google",
33
- "weights": [400],
34
- "subsets": ["latin"]
35
- }
36
- ],
37
- "type": {
38
- "display": {
39
- "font": "display",
40
- "size": 96,
41
- "weight": 400,
42
- "tracking": 0,
43
- "leading": 1.05
44
- },
45
- "body": {
46
- "font": "body",
47
- "size": 48,
48
- "weight": 400,
49
- "tracking": 0,
50
- "leading": 1.25
51
- },
52
- "mono": {
53
- "font": "mono",
54
- "size": 32,
55
- "weight": 400,
56
- "tracking": 0,
57
- "leading": 1.5
58
- },
59
- "numerals": {
60
- "font": "display",
61
- "size": 150,
62
- "weight": 400,
63
- "tracking": 0,
64
- "leading": 1
65
- }
66
- },
67
- "easing": {
68
- "in": "back.out(2)",
69
- "out": "back.in(1.4)",
70
- "pop": "elastic.out(1,0.5)",
71
- "settle": "power2.out",
72
- "spring": "spring(150,12)"
73
- },
74
- "transition": {
75
- "type": "wipe",
76
- "duration": 0.45
77
- },
78
- "grain": 0.18,
79
- "sound": {
80
- "ui/pop": "freesound:pop",
81
- "move/whip": "freesound:whoosh"
82
- }
83
- }
@@ -1,73 +0,0 @@
1
- # Motion
2
-
3
- Rules first, then patterns with the exact CodeCut props. Everything is a pure function of time, so a render repeats exactly.
4
-
5
- ## Rules
6
-
7
- 1. **Never linear motion.** Every move has an ease. `keyframe_set` takes it as the third value: `[0.4, 1, "expo.out"]`. A key's ease is the curve used to arrive at that key.
8
- 2. **Fast in, slow settle.** Entrances use `expo.out` or `power3.out` (most of the distance in the first third). Exits are shorter than entrances and use `expo.in` or `power2.in`.
9
- 3. **A slight overshoot for pops.** `back.out(1.8)` for things that land, `back.out(1.2)` for calm Looks. Do not overshoot text you need to read at the end.
10
- 4. **Stagger 0.05 to 0.1 s.** Lists, letters and cards enter one after another. Under 0.04 s reads as one blob; over 0.15 s feels slow. Use `<Stagger each={0.08}>` around the children, or `SplitText` for text.
11
- 5. **Overlap actions.** The next move starts before the last one has settled (about 60 to 70 % through). Nothing waits for everything else to stop.
12
- 6. **A slow constant push on the camera.** Put a scale key on the Scene: `scale={[[0, 1], [3, 1.06]]}` over the scene's length. This also keeps the frame from ever being still (review check 4).
13
- 7. **Parallax between depth layers.** Background moves 0.3 to 0.5 times as far as the foreground over the same time. Give them different `position` keys.
14
- 8. **Sound on every landing.** Each impact effect has a `sound` tag; `sound_auto` places it. Check 10 in the review fails without it.
15
- 9. **One idea per beat.** One hero move per scene; the rest supports it.
16
- 10. **Hold the end state briefly** (0.3 to 0.5 s) before the next thing so the eye can read.
17
-
18
- ## Durations
19
-
20
- | What | Seconds |
21
- | ---------------- | ------------------------------------------------------------- |
22
- | Pop / small UI | 0.25 to 0.4 |
23
- | Title enter | 0.5 to 0.7 |
24
- | Scene transition | 0.3 (flash, cut) to 0.6 (dissolve) |
25
- | Counter | 0.8 to 1.4 |
26
- | Hold for reading | about 0.25 s per word on screen, minimum 1.2 s for a headline |
27
-
28
- ## Patterns
29
-
30
- Entrance of a headline (props, no effect element needed):
31
-
32
- ```tsx
33
- <Title
34
- id="t1"
35
- text="Ship videos as code"
36
- size={118}
37
- enter={{ from: "sw", distance: 120, ease: "expo.out", duration: 0.6 }}
38
- />
39
- ```
40
-
41
- A landing with weight (impact effect as a child of the layer):
42
-
43
- ```tsx
44
- <Title id="t1" text="Boom" enter={{ from: "n", distance: 300, ease: "expo.in", duration: 0.25 }}>
45
- <Shake id="t1-shake" amp={10} freq={14} decay={5} start="0.25s" />
46
- </Title>
47
- ```
48
-
49
- `Shake`, `Thud`, `Slam`, `PunchZoom`, `Hitstop`, `Glitch`, `RGBSplit`, `Pulse`, `Wobble`, `SquashStretch` are impact effects. `start` is relative to the parent layer. Each has a default `sound` tag; set `sound=""` only when you want it silent on purpose.
50
-
51
- Staggered cards:
52
-
53
- ```tsx
54
- <Stagger id="cards" each={0.08}>
55
- <Card id="c1" enter={{ from: "s", distance: 80, ease: "expo.out" }} />
56
- <Card id="c2" enter={{ from: "s", distance: 80, ease: "expo.out" }} />
57
- <Card id="c3" enter={{ from: "s", distance: 80, ease: "expo.out" }} />
58
- </Stagger>
59
- ```
60
-
61
- Text by word: `<SplitText id="h" text="Make it move" preset="rise" />`. Presets: rise, typewriter, wave, scramble, slam, blur-in, mask-reveal, weight-pulse, tracking-in, counter. Use `rise` or `mask-reveal` for headlines, `typewriter` for code and quotes, `slam` only once per film.
62
-
63
- Camera push on a scene: `scale={[[0, 1], [3, 1.06]]}` (the key times are relative to the Scene).
64
-
65
- Cut on a beat: end a scene on a hit and start the next on the following frame; use the Look's transition for a change of idea and a hard cut for the same idea.
66
-
67
- ## What to avoid
68
-
69
- - Linear ease on anything that moves.
70
- - Everything entering at once.
71
- - Shake on every element (it stops meaning "hit"). Use it for the main impact of a scene.
72
- - Long fades on text the viewer must read quickly.
73
- - Randomness from code. Use `ctx.noise(seed, freq)` in expressions; the linter rejects `Math.random`, `Date.now` and timers.
@@ -1,32 +0,0 @@
1
- # Review checklist (17 points)
2
-
3
- `review` decides what it can from the compiled project, the mix and (unless `deep:false`) a rendered-page measurement. Items marked "eyes" always need you to look at the contact sheet in a second, separate pass. Fix failures, call `review` again, at most three rounds, then show the user what still fails.
4
-
5
- | # | Check | How it is decided | Typical fix |
6
- | --- | -------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
7
- | 1 | Frame 0 has motion | Something is already changing within 0.1 s | Start an enter or a slow push at 0 s |
8
- | 2 | A hero element carries across 4+ beats | A layer spans 4 scenes; else eyes | Move the hero onto its own track, or repeat it with the same look in every beat |
9
- | 3 | Something new at least every 2 s | A layer appears or a move starts at least every 2 s | Add an element, a cut or a new move in the gap named |
10
- | 4 | No static frame longer than 0.5 s | Nothing on screen changes for more than 0.5 s | Slow push, drift, pulse or stagger |
11
- | 5 | Every spoken word on screen is in sync with the voice | Captions follow the voice; other words: eyes | `align_to_voice` |
12
- | 6 | Numbers shown add up | Lists the numbers; you add them up | Fix the number or the script |
13
- | 7 | No overlapping or clipped text | Measured in the rendered page at several times; eyes if skipped | Shorten, shrink, or move |
14
- | 8 | All text inside the SafeArea for the format | Lint rule `text-outside-safe-area` | Put it inside `<SafeArea preset=…>` |
15
- | 9 | Contrast of text against its background passes | Lint plus measured contrast | Lighter or darker colour; a card or scrim behind text |
16
- | 10 | Every impact effect has a sound on its frame | Impact cues against sfx events (0.1 s) | `sound_auto` |
17
- | 11 | Voice is always on top in the mix | Music ducks 6 dB or more; gains compared | Lower music/sfx gain, raise `duckAmount` |
18
- | 12 | Loudness within target | Measured integrated LUFS within 1.5 of -14, peak under -1 dBTP | Adjust gains |
19
- | 13 | Transitions are used with intent | More than two types warns; always eyes | One signature transition, hard cuts elsewhere |
20
- | 14 | Looks and type are consistent with the chosen Look | Theme set, font count; eyes | Use `$brand.*` and `$type.*` |
21
- | 15 | Captions readable (line length, reading speed) | Line length at most 32 characters, at most 21 characters per second | Lower `maxChars`/`maxWords`, longer `hold` |
22
- | 16 | All assets have ledger entries (downloaded ones; your own files need none) | Ledger lookup | Fetch with `sound_get` / `font_get` |
23
- | 17 | CC-BY credits are present in the license report | Attribution entries have an author and become `credits.txt` | Re-fetch with `sound_get` |
24
-
25
- ## The second pass
26
-
27
- Open the contact sheet image. For each check marked manual or needs-eyes, write one sentence saying what you see and whether it passes. Be specific ("the logo on frames 1, 4, 7 and 10 is the same teal circle"). If you cannot tell from the image, say so and ask the user. Never write "looks good" without naming what you looked at.
28
-
29
- ## Honest limits
30
-
31
- - Audio is measured, not heard. State levels and peak positions; ask the user to listen.
32
- - Taste is not measurable. The checklist catches mechanical problems; the user decides if it is good.
@@ -1,29 +0,0 @@
1
- # The six-beat SaaS promo (30 s, 9:16)
2
-
3
- `project_create` with `template: "saas-promo"` makes these six scenes, empty, at these times. Change the times only if the script needs it, and keep the total.
4
-
5
- | Beat | Scene id | Start | Length | Job |
6
- | ----------- | ---------- | ----- | ------ | ---------------------------------------------------------------------------- |
7
- | 1. Hook | `hook` | 0 s | 3 s | Stop the scroll. One bold claim or question, in motion on frame 0. |
8
- | 2. Problem | `problem` | 3 s | 5 s | Name the pain in the viewer's words. Show it, do not explain it. |
9
- | 3. Reveal | `reveal` | 8 s | 6 s | The product arrives. The biggest move and the biggest sound of the film. |
10
- | 4. Features | `features` | 14 s | 9 s | Three things, one at a time, each with proof on screen (UI, number, result). |
11
- | 5. Proof | `proof` | 23 s | 4 s | One number, one quote, or one logo row. Only what the user gave you. |
12
- | 6. CTA | `cta` | 27 s | 3 s | One action, one URL or button. Hold it. |
13
-
14
- ## Rules for each beat
15
-
16
- - **Hook:** the first frame already moves (review check 1). Text is large (96 px or more on 1080 wide), at most 7 words, inside the safe area. The hero element introduced here should come back in later beats (check 2).
17
- - **Problem:** two short lines at most. Contrast with the hook: slower, or a colour shift. Something new on screen at least every 2 s (check 3).
18
- - **Reveal:** use the Look's signature transition into this scene. A `Slam` or `PunchZoom` on the product name, with a `hit/boom` or `hit/land` sound.
19
- - **Features:** a stagger of 0.08 s. Counters use `<Counter over="1s" />` with tabular figures. Show the product through `UIMock` with `Cursor` clicks rather than describing it.
20
- - **Proof:** do not invent numbers. If the user gave none, make this a "what you get" beat with a checklist, and tell them why.
21
- - **CTA:** the action in the user's words, a `Pulse` on the button, quiet music tail. Hold the final state for 1 s or more.
22
-
23
- ## Timing against the script
24
-
25
- About 2.5 spoken words per second: 30 s holds about 75 words. Write the script first (step 2), record or generate the voice (step 4), then adjust scene lengths to the real voice and use `align_to_voice` to start the on-screen words with the spoken ones.
26
-
27
- ## Captions
28
-
29
- For vertical video use `<Captions voice="#vo" captionStyle="karaoke" maxChars={22} maxWords={4} />` near the lower third, inside the safe area, 64 px or more, heavy weight, a contrasting active colour. See `typography.md`.
@@ -1,47 +0,0 @@
1
- # Sound
2
-
3
- You cannot hear. You choose sounds from their tag, description, measured duration and measured peak, and then you ask the user to listen.
4
-
5
- ## Tags (what each is for)
6
-
7
- | Tag | Job | Typical length |
8
- | ------------------ | --------------------------- | -------------- |
9
- | `ui/pop` | A small element appears | 0.03 to 0.8 s |
10
- | `ui/tap` | A tap or press | 0.02 to 0.6 s |
11
- | `ui/tick` | A counter step, a tiny tick | 0.01 to 0.4 s |
12
- | `move/whip` | A fast move or whip pan | 0.1 to 1.2 s |
13
- | `move/whoosh-deep` | A big slow move | 0.4 to 2.5 s |
14
- | `hit/land` | A heavy element lands | 0.1 to 1.5 s |
15
- | `hit/punch` | A sharp hit | 0.05 to 1 s |
16
- | `hit/boom` | A big boom for a reveal | 0.5 to 4 s |
17
- | `tech/click` | A UI click | 0.01 to 0.5 s |
18
- | `tech/data` | Data or numbers appear | 0.1 to 2 s |
19
- | `tech/glass` | A bright glassy accent | 0.2 to 2.5 s |
20
- | `tech/success` | A success moment | 0.3 to 2.5 s |
21
- | `tech/glitch` | A glitch or error | 0.1 to 1.5 s |
22
-
23
- `sound_search` with `tag` adds good search words and the length range. Add your own `query` words for flavour ("wooden", "soft").
24
-
25
- ## Workflow
26
-
27
- 1. `sound_auto` (dry run) lists impact effects with no sound on their frame.
28
- 2. Apply it, or `sound_search` and `sound_get` by hand. `sound_get` downloads, measures the loudest moment (`peak`), and writes the ledger. Pass `tag` so the peak gets the job's name (`hit/land` gives `peak="land"`).
29
- 3. Place with `<Sound id src="freesound:123" at="0.6s" peak="land" gain={-6} />`. `at` is where the peak must land; the clip starts early by the measured peak offset. Review check 10 allows 0.1 s.
30
- 4. `mix_preview`. Read `peakLandsAt` for each sound and the measured loudness.
31
- 5. Tell the user which sounds you picked (name, author, licence, description) and ask them to listen.
32
-
33
- ## Levels
34
-
35
- - Voice is on top. Music is set 10 to 14 dB below the voice and ducks another 12 dB (`duckAmount`) while the voice speaks.
36
- - SFX sit 3 to 9 dB below the voice, except the one main hit per scene.
37
- - The master is normalised to -14 LUFS for social. Check 12 passes within 1.5 LU.
38
- - Do not stack more than two loud sounds on one frame.
39
-
40
- ## Licensing
41
-
42
- - Default allowed: CC0 and CC-BY. CC-BY needs credit: `render` writes `<name>.credits.txt`; tell the user to paste it into the post or description.
43
- - NonCommercial and other licences are refused with `license_blocked`. Pick another sound.
44
- - To restrict to CC0 only, set `"soundLicenses": ["CC0"]` in `codecut.json`.
45
- - With only a Freesound API key the downloaded file is the HQ MP3 preview (original files need OAuth). The ledger entry says so.
46
- - Without `FREESOUND_API_KEY`, list your own licensed files in `sounds/catalog.json` and `sound_search` uses them.
47
- - Your own files (recordings, tracks you licensed) need no ledger entry, but the rights are yours to confirm.
@@ -1,50 +0,0 @@
1
- # Typography
2
-
3
- You cannot judge taste from an image, but you can check legibility and mechanical problems. Propose, show the frame, and let the user choose.
4
-
5
- ## The rules
6
-
7
- 1. **One display face and one body face.** Get contrast from weight and width, not from a third family. The linter warns above 3 families (display, body, mono at most).
8
- 2. **Hierarchy by size, weight and colour, in that order.** Three levels per screen: headline, support line, small print. If everything is bold, nothing is.
9
- 3. **Sizes for a 1080 px wide frame** (scale for other widths): headline 96 to 140 px, support 44 to 56 px, small print 34 px minimum (the linter rejects text under about 28 px), captions 60 to 72 px. Landscape 1920 px wide: scale by 1.3 to 1.5.
10
- 4. **Tabular figures for anything that counts.** `<Counter>` does this for you. For other numbers set `features={["tnum"]}` so the width does not jitter. Use lining figures (`"lnum"`) next to caps.
11
- 5. **Track all-caps.** Add 40 to 100 (thousandths of an em) to `tracking` for `case="upper"`. Tighten large display text by -15 to -30.
12
- 6. **Line length.** Headlines at most 3 lines, 4 to 7 words total. Body at most 40 characters per line on mobile. Break by meaning (`maxWidth` as a percentage, not hard breaks).
13
- 7. **Safe areas.** Keep text inside `<SafeArea preset="reels">` (also `shorts`, `tiktok`, `feed`). The platform UI covers the top, the bottom and the right edge. Review check 8 fails otherwise.
14
- 8. **Leading.** 1.0 to 1.1 for display, 1.25 to 1.4 for body. Do not use the default 1.15 for big headlines.
15
- 9. **Contrast.** At least 3:1 for large text, 4.5:1 for small. Put text on a card or scrim, not on a busy picture.
16
- 10. **Check the glyphs.** `font_check` before you write text in another script (Devanagari, Arabic, Thai, CJK). The lint rule `missing-glyph` rejects characters the face cannot draw and lists them. Add a face that covers that script instead of letting it fall back.
17
-
18
- ## Captions
19
-
20
- - At most 22 to 28 characters per line on 9:16, 2 lines maximum, 1 to 4 words per page (`maxChars`, `maxWords`).
21
- - Reading speed at most 21 characters per second (review check 15). Fast speech: fewer words per page, not smaller text.
22
- - Weight 700 to 900, 64 px or more, a dark outline or card behind it, active word in the Look's accent colour (`captionStyle="karaoke"`), or scaled (`"pop"`). Use `"word"` for hype, `"line"` for calm explainers.
23
- - Lower third, inside the safe area, never over the face or the product.
24
- - Export with the project: `.srt`/`.vtt` come from the same word timings.
25
-
26
- ## The Looks
27
-
28
- Use the Look's type tokens through `font="$type.display"` and `$brand.*` colours. Do not hard-code families.
29
-
30
- | Look | Display | Body | Mono | Scale (display / body / numerals) | Feel |
31
- | ------- | ---------------------------------------------------------- | ---------------- | ------------------ | --------------------------------- | -------------------------- |
32
- | kinetic | Space Grotesk 700 (variable wght 300 to 700), tracking -25 | Inter 400/600 | JetBrains Mono 500 | 104 / 44 / 160 px | Loud, fast, hard contrast |
33
- | minimal | DM Sans 600 (variable), tracking -20 | DM Sans 400/500 | IBM Plex Mono 400 | 88 / 40 / 150 px | Calm, precise, lots of air |
34
- | sketch | Permanent Marker 400 | Patrick Hand 400 | Space Mono 400 | 96 / 48 / 150 px | Hand-drawn, playful |
35
-
36
- Pairing logic: a characterful display face with a neutral body face. Do not pair two characterful faces. Variable fonts let you animate weight (`axes={{ wght: [[0, 300], [0.6, 700, "expo.out"]] }}`) for emphasis instead of switching families.
37
-
38
- ## Using `font_preview`
39
-
40
- 1. `font_get` the face so it is on disk and locked.
41
- 2. `font_preview` with `fontId`, a line of the **real** text from the script, and a size near the real one (for example 96).
42
- 3. Open the PNG. Check: are the letters distinct (I, l, 1; O, 0), do the numerals look right, does the weight read at phone size, do accents and special characters render?
43
- 4. Show the user the preview and the alternatives; say what you checked and what you cannot judge (personality, brand fit). Ask them to choose.
44
-
45
- ## Mechanics worth knowing
46
-
47
- - Fonts are declared in `<Fonts>`; `font_get` adds the declaration and downloads the files once. Renders never use the network, and a changed or missing font file fails the render naming the font id.
48
- - Google Fonts are licensed individually (mostly OFL). The ledger records each; `font_list` shows them.
49
- - Variable axes (`wght`, `wdth`, `slnt`, `opsz`) are animatable props on text. Keep weight changes smooth and small (a 200 to 300 swing), they are for emphasis.
50
- - Numerals in big counters: use the Look's `$type.numerals` token.