dreative 0.5.1 → 0.5.3

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 (48) hide show
  1. package/README.md +49 -27
  2. package/dist/cli/audit.js +206 -0
  3. package/dist/cli/audit.test.js +79 -0
  4. package/dist/cli/docsCheck.js +163 -0
  5. package/dist/cli/docsCheck.test.js +8 -0
  6. package/dist/cli/index.js +45 -9
  7. package/dist/server/preview.js +73 -73
  8. package/dist/server/store.js +11 -0
  9. package/dist/shared/artifacts.js +220 -0
  10. package/dist/shared/design.js +45 -24
  11. package/dist/shared/ruleSystem.js +220 -0
  12. package/dist/shared/ruleSystem.test.js +262 -0
  13. package/dist/shared/skillSystem.js +173 -0
  14. package/dist/shared/skillSystem.test.js +110 -0
  15. package/dist/ui/assets/{index--vztc_MR.js → index-CKwmbx2j.js} +13 -13
  16. package/dist/ui/index.html +12 -12
  17. package/package.json +5 -3
  18. package/skill/dreative/DESIGN.md +144 -108
  19. package/skill/dreative/PLAN.md +285 -116
  20. package/skill/dreative/SKILL.md +237 -144
  21. package/skill/dreative/frameworks/nextjs.md +13 -0
  22. package/skill/dreative/frameworks/react-vite.md +12 -0
  23. package/skill/dreative/frameworks/styling.md +14 -0
  24. package/skill/dreative/frameworks/sveltekit.md +10 -0
  25. package/skill/dreative/frameworks/vue-nuxt.md +12 -0
  26. package/skill/dreative/recipes/3d-recipes.md +44 -0
  27. package/skill/dreative/recipes/cinematic-recipes.md +19 -0
  28. package/skill/dreative/recipes/immersive-recipes.md +18 -0
  29. package/skill/dreative/recipes/media-recipes.md +60 -0
  30. package/skill/dreative/recipes/motion-recipes.md +68 -0
  31. package/skill/dreative/references/ARTIFACTS.md +196 -0
  32. package/skill/dreative/references/REFLEX_FONTS.json +44 -0
  33. package/skill/dreative/references/RULES.json +186 -0
  34. package/skill/dreative/references/SKILL_CONTRACT.md +30 -0
  35. package/skill/dreative/references/TIERS.md +44 -0
  36. package/skill/dreative/schemas/plan.schema.json +309 -0
  37. package/skill/dreative/schemas/verify.schema.json +75 -0
  38. package/skill/dreative/skills/3d.md +94 -267
  39. package/skill/dreative/skills/cinematic.md +56 -232
  40. package/skill/dreative/skills/experimental.md +108 -95
  41. package/skill/dreative/skills/immersive.md +61 -223
  42. package/skill/dreative/skills/interaction.md +9 -1
  43. package/skill/dreative/skills/media.md +149 -564
  44. package/skill/dreative/skills/mobile.md +129 -117
  45. package/skill/dreative/skills/motion.md +126 -256
  46. package/skill/dreative/skills/refined.md +116 -102
  47. package/skill/dreative/skills/ux.md +155 -144
  48. package/dist/server/ai.js +0 -177
@@ -1,13 +1,13 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Dreative</title>
7
- <script type="module" crossorigin src="/assets/index--vztc_MR.js"></script>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Dreative</title>
7
+ <script type="module" crossorigin src="/assets/index-CKwmbx2j.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-y0gVjC7u.css">
9
- </head>
10
- <body>
11
- <div id="root"></div>
12
- </body>
13
- </html>
9
+ </head>
10
+ <body>
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dreative",
3
- "version": "0.5.1",
4
- "description": "Layout-first visual editor skill for coding CLIs: extract your app's UI into editable wireframes, tweak with drag-drop + ref images, then the agent applies the diff back to your code.",
3
+ "version": "0.5.3",
4
+ "description": "Frontend design skill for coding CLIs with typed planning, specialist treatments, verification, and an optional visual editor.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "dreative": "dist/cli/index.js"
@@ -14,7 +14,9 @@
14
14
  "build": "npm run build:server && npm run build:ui",
15
15
  "prepublishOnly": "npm run build",
16
16
  "build:server": "tsc -p tsconfig.json",
17
- "build:ui": "vite build",
17
+ "build:ui": "vite build",
18
+ "test": "npm run build:server && node --test dist/shared/*.test.js dist/cli/*.test.js",
19
+ "docs-check": "npm run build:server && node dist/cli/index.js docs-check",
18
20
  "dev": "concurrently \"tsx watch src/cli/index.ts --no-open\" \"vite\"",
19
21
  "start": "node dist/cli/index.js"
20
22
  },
@@ -2,8 +2,8 @@
2
2
 
3
3
  You MUST read this file before servicing any `propose-skeletons`, `propose-variants`,
4
4
  `design-page`, or `edit-element` request, and run §12 before every respond. It exists
5
- because LLM-designed UIs converge on one templated look. Every rule corrects a known
6
- model default; none is a suggestion. Requests may carry a `plan` (Dreative's
5
+ because LLM-designed UIs converge on one templated look. Every rule corrects a known
6
+ model default, but its category determines how it governs. Requests may carry a `plan` (Dreative's
7
7
  pre-computed decision: dials, per-section layout families, budgets, lints) — execute
8
8
  the plan, apply this doctrine to everything the plan doesn't specify. When
9
9
  `plan.skills` names specialist skills (`motion`, `3d`, `interaction`, `immersive`,
@@ -11,13 +11,16 @@ the plan, apply this doctrine to everything the plan doesn't specify. When
11
11
  `skills/<name>.md` files extend this doctrine for that request — read them first;
12
12
  where they go deeper than a section here, they win.
13
13
 
14
- Rules come in two tiers. **Hard gates** — preservation (§11), spatial integrity
15
- (§15), the layout hard rules (§5), banned tells (§10), runtime verification —
16
- are checked mechanically and never traded away. Everything else is **craft
17
- doctrine**: binding defaults you deviate from only with a reason you could
18
- defend to the user. When attention is scarce, gates outrank craft rules, and
19
- craft rules outrank stylistic preference but a page that only clears gates
20
- and shows no point of view is still a failure of this file.
14
+ Rules use the three categories in `references/RULES.json`. **Hard gates** cover
15
+ objective failures—preservation, functionality, mobile/reduced motion, content
16
+ visibility, spatial integrity, organic-subject honesty, fallbacks, assets, and
17
+ real verification—and cannot be waived. **Evidence-backed defaults** are proven
18
+ remedies for repeated dogfood failures; follow them or declare a planning-time
19
+ alternative with measurable criteria and runtime evidence. **Creative
20
+ provocations** force divergent exploration but do not become shipment checklists.
21
+ When attention is scarce, hard gates outrank defaults, and defaults outrank
22
+ stylistic preference—but a page that only clears gates and shows no point of
23
+ view is still a failure of this file.
21
24
 
22
25
  ## 1. Register: the first decision
23
26
 
@@ -76,8 +79,9 @@ Never design by accretion, and never commit to the first concept. Three passes:
76
79
  `$RANDOM % 20 + 1`, or read digits off `date +%N`) and record the literal
77
80
  command AND its output in plan.md. The roll picks one **provocation** from
78
81
  the table below; at least ONE of the three explore concepts must take it
79
- literally, and if that concept wins, the provocation ships visibly, not
80
- as a token gesture. Roll a second number (1–6) to pick a **forced-rotation
82
+ literally. If that concept wins, the provocation becomes a candidate;
83
+ experimental delivery selects only the strongest two or three peaks instead
84
+ of forcing every candidate to ship. Roll a second number (1–6) to pick a **forced-rotation
81
85
  axis** — 1 palette strategy · 2 type voice · 3 hero concept · 4 nav/page
82
86
  architecture · 5 signature driver · 6 set-piece family — and that axis must
83
87
  differ from anything in your ledger's last 3 entries AND from the most
@@ -136,6 +140,62 @@ build ("the hero feels generic", "too much motion"), append it to that
136
140
  build's entry as a one-line `lesson:` — and the commit pass reads lessons
137
141
  alongside choices, so the same critique never has to be given twice.
138
142
 
143
+ **No-media builds: structure IS the media.** When a build ships zero
144
+ imagery (no image-gen tool, product register, or the user chose
145
+ placeholders), the ambition tier does NOT tier down — it transfers whole
146
+ onto layout, type, and motion, and this is where no-media builds die: the
147
+ executor, with no assets to arrange, collapses to the one layout it knows
148
+ (a vertical list of rounded cards in a centered column) and ships slop that
149
+ its own plan didn't describe. Hard rules for any expressive+ no-media build:
150
+
151
+ 1. **The compositional spine must survive to the screenshot.** Whatever
152
+ bespoke structure the plan named (a strip rack, a ledger, a switchboard,
153
+ a timetable) must be RECOGNIZABLE as that thing in the shipped page — its
154
+ physical vocabulary built for real: the holder edge, the notch, the rail,
155
+ the perforation, the column rules. If a stranger shown the screenshot and
156
+ the blueprint's layout-family words couldn't match them, the build
157
+ restyled a card list and called it the spine — that is a depth-honesty
158
+ failure (§11), not a detail.
159
+ 2. **Bespoke drawn/procedural artifacts carry the missing media role.** With no photography, the page
160
+ earns visual richness from things MADE for it: a live canvas (meter,
161
+ field, trace), custom SVG structure (rules, notches, connectors, dials —
162
+ drawn, not icon-font), procedural texture/grain, a data-driven ornament.
163
+ A no-media page whose only visuals are borders and border-radius has no
164
+ media plan at all.
165
+ 3. **Type does structural work.** Multi-scale composition (oversized
166
+ numerals/designators against small mono metadata), real hierarchy per §6
167
+ — not one font-size row layout repeated N times.
168
+ 4. **Motion budget spends on the structure**, not on entrance fades: the
169
+ spine's own physicality (things racked, tossed, slid, stamped) is the
170
+ choreography. Motion.md's treatment and verification rules apply.
171
+ 5. **Choose a rendering layer only when it earns its cost.** No imagery can
172
+ justify Canvas/WebGL when a live procedural or data-driven surface is the
173
+ concept, but award ambition does not require one. Spatial typography,
174
+ layered DOM/SVG composition, masks, or other subject-grounded systems may be
175
+ stronger. Vocabulary to draw from when rendering is warranted
176
+ (subject-grounded, not decorative): oscilloscope/waveform traces driven by
177
+ real events · topographic contour lines drifting · dot-matrix/LED field
178
+ that spells live state · plexus line-network connecting related items ·
179
+ isometric grid that lights under the cursor · scan sweep across data
180
+ rows · ASCII/character rain in the brand's glyphs · particle flow along
181
+ the layout's own rails · generative engraving borders · a physical sim
182
+ (springs, gravity) on the UI's actual objects.
183
+ 6. **Layout creativity means spatial composition, not relocated chrome.**
184
+ Moving the nav to the bottom, a novel tab bar, an unusual dock — that is
185
+ furniture rearrangement, and if it's the build's ONLY inventive move the
186
+ build failed. The invention must live in how the CONTENT is composed:
187
+ asymmetric multi-scale grids, overlapping planes, diagonal/rotated flow,
188
+ sections that share edges and interlock — while staying rigorously
189
+ modern and clean (generous space, disciplined alignment, few colors).
190
+ "Clean" and "insane motion" are the same build: calm composition,
191
+ spectacular behavior.
192
+
193
+ The slop tests above apply to the RENDERED page: "dark theme + rounded
194
+ cards + one accent color" fails the competitor sentence for every no-media
195
+ product tool at once — and shipped exactly that once (user verdict on
196
+ record: "pure ai slop… I would not want something like that again"). Treat
197
+ these rules as a shipped-failure postmortem, not theory.
198
+
139
199
  **Hero thesis:** open with the most characteristic thing in the subject's world —
140
200
  a headline, an image, a live demo, an interactive moment. Whatever form fits.
141
201
 
@@ -160,20 +220,27 @@ a headline, an image, a live demo, an interactive moment. Whatever form fits.
160
220
 
161
221
  ## 3. Typography
162
222
 
163
- **Font selection procedure (brand register, never skip):**
164
- 1. Write three physical-object brand-voice words ("warm, mechanical, opinionated" —
165
- never "modern" or "elegant").
166
- 2. List the three fonts you'd reach for by reflex. Reject any on the ban list below.
167
- 3. Pick for the brand as a physical object (museum caption, 1970s terminal manual,
168
- concert poster, mid-century receipt). Reject the first thing that "looks designy".
169
- 4. If the final pick matches the original reflex, start over.
170
-
171
- **Reflex-reject fonts (training-data defaults, banned as defaults):** Fraunces,
172
- Newsreader, Lora, Crimson (all), Playfair Display, Cormorant (all), Syne, IBM Plex
173
- (all), Space Mono, Space Grotesk, Inter, DM Sans/Serif, Outfit, Plus Jakarta Sans,
174
- Instrument Sans/Serif. Inter/system stacks ARE legitimate in the product register
175
- and for trust briefs. When an existing app already uses one, identity-preservation
176
- wins keep it.
223
+ **Font selection procedure (brand register, never skip):**
224
+ 1. Write three physical-object brand-voice words ("warm, mechanical, opinionated" —
225
+ never "modern" or "elegant").
226
+ 2. Read the last three display fonts from the design ledger and generate at least
227
+ three candidates for this brand, including continuity candidates when an
228
+ existing identity or design system matters.
229
+ 3. Mark candidates found in `references/REFLEX_FONTS.json`. A reflex font is not
230
+ bad or prohibited; it is a frequently unexamined choice that needs a specific
231
+ reason if it wins.
232
+ 4. Pick for the brand as a physical object (museum caption, 1970s terminal manual,
233
+ concert poster, mid-century receipt), supplied reference, product metrics,
234
+ language coverage, variable-font capability, or performance constraint.
235
+ 5. Record candidates and the winner in `plan.fontDecision`. If the winner is a
236
+ reflex font, record the concrete justification and at least one registry
237
+ category in `reasonKinds`. If it repeats one of the last three display fonts,
238
+ add a stronger repeat justification.
239
+
240
+ Valid reflex-font reason: "Inter is already embedded throughout this authenticated
241
+ product, preserves its density metrics and translated layout, and changing it
242
+ would damage brand continuity." Invalid reason: "Inter looks clean and modern."
243
+ The goal is to stop reflex selection, not to declare common fonts inherently bad.
177
244
 
178
245
  **Serif discipline:** "creative/premium brief = serif" is the most-tested AI tell.
179
246
  Default is sans display. Serif only when the brief is genuinely editorial/luxury/
@@ -292,10 +359,17 @@ sites win on composition, not decoration; this is where that happens.
292
359
  - Product register: responsive behavior is structural (collapse sidebar, responsive
293
360
  table), not fluid type.
294
361
 
295
- ## 6. Motion
296
-
297
- Every animation answers "what does this communicate?" — hierarchy, storytelling,
298
- feedback, or state change. "It looked cool" = delete it.
362
+ ## 6. Motion
363
+
364
+ Every animation answers "what does this communicate?" — hierarchy, storytelling,
365
+ feedback, or state change. "It looked cool" = delete it.
366
+
367
+ Motion has three roles. **Decorative motion** reveals, responds, or adds ambient
368
+ life. **Structural motion** controls hierarchy, pacing, pinning, and composition
369
+ handoffs. **Transformational motion** changes imagery/type/objects into a new
370
+ form or the next scene. Expressive/award pages evaluate key moments for the last
371
+ two roles; opacity, translate, scale, and slight parallax are not automatically
372
+ enough merely because they animate.
299
373
 
300
374
  **The 100/300/500 rule:** 100-150ms instant feedback (press, toggle) · 200-300ms
301
375
  state changes (menu, tooltip, hover) · 300-500ms layout changes (accordion, modal)
@@ -312,9 +386,12 @@ micro-interactions; the uniform fade-and-rise on every scrolled section is the
312
386
  saturated AI tell. Some brands skip entrance motion entirely — restraint as voice.
313
387
  Product = 150-250ms, state-conveying only, zero page-load choreography.
314
388
 
315
- **Mechanics:** animate transform/opacity by default; blur/backdrop-filter/clip-path/
316
- masks/shadow allowed when they materially improve the effect, bounded to small areas,
317
- verified smooth. Never casually animate width/height/top/left/margins (use FLIP or
389
+ **Mechanics:** use transform/opacity for ordinary local state when they fit, but
390
+ do not make them the unexamined expressive default. Select CSS, GSAP timelines,
391
+ ScrollTrigger, SVG, masks, `clip-path`, DOM fragments, Canvas, WebGL/shaders,
392
+ sequences, video, Lottie, or 3D by visual result, cost, responsiveness, and
393
+ available assets. Use the simplest mechanism capable of making the intended
394
+ transformation convincing. Never casually animate width/height/top/left/margins (use FLIP or
318
395
  grid-template-rows). Sibling stagger `calc(var(--i) * 50ms)` capped at ~500ms total.
319
396
  IntersectionObserver (unobserve after firing), CSS scroll-driven animations, or
320
397
  Motion/GSAP scroll tools — `window.addEventListener("scroll")` is a hard ban. Reveals
@@ -343,65 +420,22 @@ library (Phosphor/Radix/Tabler/HugeIcons; Lucide only on request), one strokeWid
343
420
  globally. Logo walls: real SVG marks (`https://cdn.simpleicons.org/<slug>`) or
344
421
  generated monograms — logos only, no category captions, below the hero.
345
422
 
346
- ### Generated media (probe your environment, then use it)
347
-
348
- Before designing, check what media generation your environment actually offers —
349
- image-gen tools, video-gen tools, or a CLI that can produce them — and treat any
350
- capability found as a first-class design material, not a nice-to-have:
351
-
352
- - **Images**: generate hero photography, product/context shots, and textures at
353
- the section's exact aspect ratio, prompted for the brand's physical subject
354
- and the page's light temperature so they grade into the palette. Generate the
355
- grain tile and any masks/mattes too instead of hand-rolling SVG.
356
- - **Video**: a generated 5–10s seamless loop is one of the biggest single UI
357
- upgrades available use it as: a hero background (muted, `autoplay loop
358
- playsinline`, poster frame, `prefers-reduced-motion` swaps to the poster);
359
- the budget "living surface" (a pre-rendered fluid/particle/atmosphere loop
360
- instead of a GPGPU sim cinematic.md's budget recipe); hover-preview loops
361
- on work cards; or an image-sequence for scroll-scrubbed narratives (export
362
- frames, scrub per motion.md).
363
- - **Integrate with motion, don't just embed** — a raw `<video>`/`<img>` dropped
364
- in a section is not the treatment. Generated media enters the page THROUGH the
365
- motion system; pick 1–2 treatments per page from this vocabulary (or invent in
366
- its spirit), matched to the register:
367
- - **Pixel/dither reveal**: video or image materializes from coarse blocks —
368
- a shader that lerps sample resolution from ~24px mosaic to full res (or a
369
- stepped `image-rendering: pixelated` downscale swap for the budget path),
370
- driven by scroll progress or hover. Reads as digital-craft; dark-tech and
371
- editorial registers.
372
- - **Floating media**: images hover in depth with slow damped drift (±6-10px,
373
- 4-8s loops, each at a different phase), subtle parallax by depth layer, and
374
- a soft contact shadow — the immersive "paper sheets in space" look without
375
- WebGL. Cap at 3-5 floaters per view.
376
- - **Mask-shaped video**: the loop plays inside display type (`background-clip:
377
- text` / SVG mask on a 10vw+ headline), an arch/circle clip-path, or the
378
- brand mark — the video becomes typography/identity rather than a rectangle.
379
- - **Scroll-scrubbed sequence**: generated frames scrubbed by scroll for
380
- assemble/morph/rotate narratives (motion.md's canvas product story).
381
- - **Velocity-touched media**: scroll/drag velocity stretches, RGB-splits, or
382
- ripples the media plane for a beat, settling with damped decay
383
- (cinematic.md §2) — needs the WebGL media-plane sync.
384
- - **Hover-woken loops**: stills that crossfade into their video loop on
385
- hover/focus (240ms), pause + rewind-to-poster on leave; works as generated
386
- "living thumbnails" on work/product cards.
387
- - **Curtain/split reveal**: media enters behind a 2-4 panel wipe or an
388
- expanding inset clip (`clip-path: inset(40% 30%) → inset(0)`), timed with
389
- the section's line-mask type reveal so image and headline arrive as one
390
- choreographed beat.
391
- Whatever the treatment, honor the floors: reduced-motion gets the poster
392
- frame, hover treatments have focus equivalents, and the effect is justified
393
- in one sentence like any other motion (§6).
394
- - Discipline: same rationing as everything else — one video loop per view,
395
- compress hard (H.264/AV1, ≤ 2–4MB per loop, no audio track), lazy-load below
396
- the fold, and never let generated media replace REAL product screenshots or
397
- the client's actual photography when those exist.
398
- - If no generation capability exists, say so and fall back down the §7 priority
399
- list — never fake a video with a div animation.
400
- - `skills/media.md` is this section's deep dive: the production pipeline
401
- (prompting for the page's light, compression targets, frame sequences), the
402
- full DOM-tier and WebGL media-plane treatment vocabulary, and the
403
- entrance/idle/response reasoning frame. Read it whenever generated media or
404
- motion-integrated imagery ships.
423
+ ### Generated media (probe your environment, then use it)
424
+
425
+ Before designing, check what media generation your environment actually offers —
426
+ image-gen tools, video-gen tools, or a CLI that can produce them — and treat any
427
+ capability found as a first-class design material, not a nice-to-have. Generate
428
+ for the section's exact ratio, physical subject, and light temperature. Preserve
429
+ real product screenshots and supplied photography when they are authoritative.
430
+
431
+ Do not choose a media treatment from a catalog here. First record three original
432
+ brand-native concepts in `conceptExploration`; then read `skills/media.md` for
433
+ principles. Open `recipes/media-recipes.md` only afterward for feasibility,
434
+ implementation, performance, or fallback guidance, and log that access in
435
+ `recipeAccess`. A raw `<video>` or `<img>` is not a treatment: the chosen media
436
+ system must develop the concept and retain poster/static, focus/touch, reduced-
437
+ motion, low-power, and loading fallbacks. If generation is unavailable, use the
438
+ §7 source priority instead of simulating media with decorative divs.
405
439
 
406
440
  ### Surface & light — material identity for every layer
407
441
 
@@ -411,8 +445,8 @@ ambition every major surface (page background, hero, cards/panels, media
411
445
  frames) carries at least one deliberate material cue, and the page declares
412
446
  ONE light direction that everything obeys:
413
447
 
414
- - **Grain/noise** — a 1-3% opacity noise overlay (tileable PNG or SVG
415
- `feTurbulence`, one shared asset) kills gradient banding and digital
448
+ - **Grain/noise** — a 1-3% opacity tileable PNG/WebP noise overlay (one shared
449
+ asset; never `feTurbulence`) kills gradient banding and digital
416
450
  flatness; vary its intensity by section as part of the pacing curve.
417
451
  - **Light consistency** — pick the light's direction once; every shadow,
418
452
  edge-highlight, gradient hotspot, and 3D/scene light agrees with it. Tint
@@ -652,8 +686,9 @@ the output is not done.
652
686
  3. Zero em/en-dashes visible. Zero banned tells from §10.
653
687
  4. One accent + one tinted-neutral family + one theme + one radius system + one
654
688
  icon family, locked page-wide; matches sibling pages of this project.
655
- 5. Fonts: not on the reflex-reject list (or justified by existing brand); scale
656
- ratio committed; body ≥16px at 45-75ch; caps tracked; data tabular.
689
+ 5. Fonts: three candidates considered; registry matches marked; any reflex winner
690
+ has a specific registered reason; scale ratio committed; body ≥16px at
691
+ 45-75ch; caps tracked; data tabular.
657
692
  6. Every CTA/form/placeholder passes WCAG AA; no CTA wraps; no duplicate CTA intent.
658
693
  7. Hero: ≤2-line headline, ≤20-word subtext, ≤4 elements, real visual, CTA above
659
694
  fold; centered only if variance ≤ 4 or manifesto brief.
@@ -707,11 +742,11 @@ On touch, whatever hover revealed must be visible by default or reachable by
707
742
  tap — never lost. Custom cursors simply don't exist on touch; don't ship their
708
743
  DOM/listeners there.
709
744
 
710
- **Pinned/scrubbed sections**: pinning is fragile on mobile (URL-bar resize
745
+ **Pinned/scrubbed sections**: pinning is fragile on mobile (URL-bar resize
711
746
  fires viewport changes mid-pin; iOS momentum scroll skips scrub frames).
712
- Strategies in preference order: (1) keep the pin but shorten it (≤ 1.5
713
- viewports) and drive it with `position: sticky`, never JS pinning; (2) unpin
714
- the same content as stacked sections with simple in-view reveals;
747
+ Strategies in preference order: (1) keep the pin but shorten it and drive it
748
+ with `position: sticky` when reliable; (2) redesign the same idea as a shorter
749
+ mask, layered-parallax, or state handoff sequence rather than merely disabling it;
715
750
  (3) `ScrollTrigger.matchMedia()` / a `matchMedia` branch that swaps the whole
716
751
  choreography. Never let a desktop pin length ride on a phone.
717
752
 
@@ -738,15 +773,16 @@ clamps DOWN gracefully (hero ≥ 2rem, body stays ≥ 16px — iOS zooms inputs
738
773
  under 16px); sticky navs shrink rather than stack; test the three widths 320 /
739
774
  768 / 1280 mentally before responding.
740
775
 
741
- **Motion budget on mobile**: entrance choreography total 600ms (vs 900ms
742
- desktop), at most 1 scroll-driven sequence per page, marquees pause when
743
- off-screen. Battery is a design constraint: continuous rAF loops must idle
744
- when nothing animates.
745
-
746
- ## 14. Typography sourcing (kill the Inter-everywhere default)
776
+ **Motion budget on mobile**: shorten travel and timelines according to content,
777
+ viewport, and measured device cost. Preserve one defining idea when feasible;
778
+ marquees pause off-screen and continuous rAF loops idle when nothing animates.
779
+ Battery is a design constraint, not a reason to erase the concept.
747
780
 
748
- The reflex-reject list (§3) says what NOT to reach for; this is where to reach
749
- instead. All fonts below are free (Google Fonts or Fontshare/ITF). The
781
+ ## 14. Typography sourcing (escape the first reflex)
782
+
783
+ Use this section only after the brand-register exercise in §3 has produced
784
+ several candidates; it is a sourcing aid, not a rejection or approved-font list.
785
+ All fonts below are free (Google Fonts or Fontshare/ITF). The
750
786
  commercial fonts real award sites use — verified: unseen.co sets **Saol
751
787
  Display Light/Italic + Neue Montreal**; unseen's Blossom lab sets **SangBleu
752
788
  Serif + PP Neue Montreal**; capsul-in-pro sets **Messina Sans** — are the
@@ -827,7 +863,7 @@ from the SCREENSHOT, not from the plan's prose: naming the object "eclipse",
827
863
  "thermal horizon", or "roast core" in the plan does not make a translucent
828
864
  sphere read as one — if the verify screenshot shows a ball floating over a
829
865
  photo, it fails regardless of what the plan swore it wasn't. At hero scale
830
- the answer must be a nameable thing (see 3d.md §3: abstract coded forms are
866
+ the answer must be a nameable thing (see 3d.md §2: generic abstract forms are
831
867
  supporting-only and can never be the promoted signature object).
832
868
 
833
869
  **Interactive elements never overlap other interactive elements.** Not at any