From 39d2e4caa8f376487e0f9973346751cfda951e8e Mon Sep 17 00:00:00 2001 From: Miguel Angel Simon Sierra Date: Sat, 18 Jul 2026 08:47:20 +0200 Subject: [PATCH] feat(registry): wave L wild-shelf candidates from the frame study cursor-glyph-trail, echo-trail, facet-morph, light-sweep-pass, soft-blob-touch, halftone-dissolve; all pure functions of timeline time, tri-order seek determinism verified; watch page at docs/wild-shelf.html. Candidates pending owner judgment, no catalog changes. --- docs/wild-shelf.html | 99 ++++ .../components/cursor-glyph-trail/README.md | 51 ++ .../cursor-glyph-trail.html | 398 +++++++++++++ .../components/cursor-glyph-trail/demo.html | 85 +++ .../cursor-glyph-trail/registry-item.json | 90 +++ registry/components/echo-trail/README.md | 50 ++ registry/components/echo-trail/demo.html | 86 +++ .../components/echo-trail/echo-trail.html | 358 ++++++++++++ .../components/echo-trail/registry-item.json | 77 +++ registry/components/facet-morph/README.md | 75 +++ registry/components/facet-morph/demo.html | 90 +++ .../components/facet-morph/facet-morph.html | 546 ++++++++++++++++++ .../components/facet-morph/registry-item.json | 64 ++ .../components/halftone-dissolve/README.md | 68 +++ .../components/halftone-dissolve/demo.html | 147 +++++ .../halftone-dissolve/halftone-dissolve.html | 413 +++++++++++++ .../halftone-dissolve/registry-item.json | 86 +++ .../components/light-sweep-pass/README.md | 103 ++++ .../components/light-sweep-pass/demo.html | 90 +++ .../light-sweep-pass/light-sweep-pass.html | 479 +++++++++++++++ .../light-sweep-pass/registry-item.json | 84 +++ registry/components/soft-blob-touch/README.md | 67 +++ registry/components/soft-blob-touch/demo.html | 86 +++ .../soft-blob-touch/registry-item.json | 96 +++ .../soft-blob-touch/soft-blob-touch.html | 522 +++++++++++++++++ 25 files changed, 4310 insertions(+) create mode 100644 docs/wild-shelf.html create mode 100644 registry/components/cursor-glyph-trail/README.md create mode 100644 registry/components/cursor-glyph-trail/cursor-glyph-trail.html create mode 100644 registry/components/cursor-glyph-trail/demo.html create mode 100644 registry/components/cursor-glyph-trail/registry-item.json create mode 100644 registry/components/echo-trail/README.md create mode 100644 registry/components/echo-trail/demo.html create mode 100644 registry/components/echo-trail/echo-trail.html create mode 100644 registry/components/echo-trail/registry-item.json create mode 100644 registry/components/facet-morph/README.md create mode 100644 registry/components/facet-morph/demo.html create mode 100644 registry/components/facet-morph/facet-morph.html create mode 100644 registry/components/facet-morph/registry-item.json create mode 100644 registry/components/halftone-dissolve/README.md create mode 100644 registry/components/halftone-dissolve/demo.html create mode 100644 registry/components/halftone-dissolve/halftone-dissolve.html create mode 100644 registry/components/halftone-dissolve/registry-item.json create mode 100644 registry/components/light-sweep-pass/README.md create mode 100644 registry/components/light-sweep-pass/demo.html create mode 100644 registry/components/light-sweep-pass/light-sweep-pass.html create mode 100644 registry/components/light-sweep-pass/registry-item.json create mode 100644 registry/components/soft-blob-touch/README.md create mode 100644 registry/components/soft-blob-touch/demo.html create mode 100644 registry/components/soft-blob-touch/registry-item.json create mode 100644 registry/components/soft-blob-touch/soft-blob-touch.html diff --git a/docs/wild-shelf.html b/docs/wild-shelf.html new file mode 100644 index 0000000000..f9e928deae --- /dev/null +++ b/docs/wild-shelf.html @@ -0,0 +1,99 @@ + + + + + + The wild shelf: six candidates from the frame study + + + +
+

Wave L candidates / from the 30fps frame study

+

The wild shelf

+

Six moves reverse-engineered from the masters' own frames: jh3yy's stamp-and-decay trail, ordinaryfolk's reshaping facets and traveling light, alexwidua's tactile blob, and the textures they all imply. Candidates, not heroes, until you say so.

+
+
+

cursor-glyph-trail

after jh3yy
+
+

An actor deposits dithered glyphs at its past positions; each fades where it was stamped, density riding velocity. Time made visible.

+
+
+

echo-trail

the onion skin
+
+

A moving element carries ghosted copies of itself from moments ago, collapsing into the settled state at rest.

+
+
+

facet-morph

after ordinaryfolk
+
+

A faceted mass reshapes between silhouettes, every triangle re-lit from its angle to the key light as it moves.

+
+
+

light-sweep-pass

after ordinaryfolk
+
+

A key light travels once across the scene; every highlight and shadow answers it in lockstep, then it settles.

+
+
+

soft-blob-touch

after alexwidua
+
+

A granular soft body leans toward a touch and springs back with preserved momentum. The tactile AI orb.

+
+
+

halftone-dissolve

the texture register
+
+

One scene becomes the next through a growing field of halftone dots, smallest first, ordered by a seeded map.

+
+
+
+ + + + + diff --git a/registry/components/cursor-glyph-trail/README.md b/registry/components/cursor-glyph-trail/README.md new file mode 100644 index 0000000000..06a336f45c --- /dev/null +++ b/registry/components/cursor-glyph-trail/README.md @@ -0,0 +1,51 @@ +# cursor-glyph-trail + +An actor (default: a cursor dot) travels an authored path and deposits small dithered glyphs at its past positions. Each glyph pops in where the actor passed and decays in place; stamps land at fixed arc-length spacing along the path, so the per-second stamp rate scales with the actor's velocity. The jh3yy stamp-and-decay register: the trail is the residue of the motion, fully dissolved before the hold. + +4s authored, elastic HOLD, exit `none` by default. + +## Variables + +| id | type | default | notes | +| --- | --- | --- | --- | +| `glyphs` | string | `░▒▓+·×` | Stamp charset; one glyph per stamp is chosen by a fixed-seed LCG. | +| `density` | enum | `med` | Arc-length spacing between stamps: `low` (4.6), `med` (2.9), `high` (1.8) percent units. | +| `path` | enum | `sweep` | `sweep` is an S-curve lower-left to upper-right; `arc` rises over the top; `zigzag` cuts three straight legs. | +| `fade` | number | `0.8` | Per-stamp decay window in seconds, clamped 0.3 to 1.5; per stamp varied 0.75x to 1.25x. | +| `accent` | enum | `green` | Trail and actor color: green rides `--brand`, blue rides `--accent`, violet rides `--accent-2`. | +| `exit` | enum | `none` | `none` holds until the cut; `fade` departs opacity-only; `up` rises out. | + +## Actor slot + +The actor is a slot. Place an inert template anywhere in the HOST page (templates never render, and the runtime wipes the host clip's own children on mount, so the slot lives at document level): + +```html + +``` + +With no slot, the primitive renders a token cursor dot (accent core, hairline ring, contract tokens only). + +## Mount + +```html +
+``` + +Elastic root: no `data-width`/`data-height`; it fills whatever box the host clip gives it. Timeline registers under the literal `cursor-glyph-trail` key. + +## Notes + +- Deterministic: the stamp table (positions, times, glyph choices, jitter, sizes, peaks, decay multipliers) is built once at mount from fixed LCG seed `0x67117a11`. Stamps carry no tweens: each stamp's opacity is recomputed on every timeline update as a pure function `f(tl.time() - t_i)` of its table row (two sequential tweens on one property render in direction-dependent order under GSAP seeks), and the actor position is recomputed from `tl.time()` the same way, so eventful seeks (`suppressEvents=false`, the engine's render path) land identical frames in any order and either direction. +- Density law: stamps land at fixed arc-length spacing, so faster travel deposits more stamps per second; the shared ease (power2-style inOut) makes the trail thin at the ends and dense through the middle. +- Every stamp's decay completes inside IN by construction (`IN = travel + pop + fade * 1.25 + margin`), so the HOLD is truly still: the actor rests at the path end and the field is empty. +- The travel ease is one shared function used by both the stamp-table sampler and the per-update actor position, so stamps always sit exactly on the actor's past path. diff --git a/registry/components/cursor-glyph-trail/cursor-glyph-trail.html b/registry/components/cursor-glyph-trail/cursor-glyph-trail.html new file mode 100644 index 0000000000..ebf173787b --- /dev/null +++ b/registry/components/cursor-glyph-trail/cursor-glyph-trail.html @@ -0,0 +1,398 @@ + + + + + + Cursor Glyph Trail + + + + + diff --git a/registry/components/cursor-glyph-trail/demo.html b/registry/components/cursor-glyph-trail/demo.html new file mode 100644 index 0000000000..d872c5e8ce --- /dev/null +++ b/registry/components/cursor-glyph-trail/demo.html @@ -0,0 +1,85 @@ + + + + + + + Cursor Glyph Trail Demo + + + +
+
+
+ + + + + diff --git a/registry/components/cursor-glyph-trail/registry-item.json b/registry/components/cursor-glyph-trail/registry-item.json new file mode 100644 index 0000000000..43e258b183 --- /dev/null +++ b/registry/components/cursor-glyph-trail/registry-item.json @@ -0,0 +1,90 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "cursor-glyph-trail", + "type": "hyperframes:component", + "title": "Cursor Glyph Trail", + "description": "An actor travels an authored path depositing small dithered glyphs at its past positions, each popping in and decaying in place, stamp rate scaling with the actor's velocity.", + "tags": ["motion-primitive", "demonstrate", "trail", "cursor", "glyphs", "deterministic"], + "jobs": ["demonstrate"], + "family": "demonstrate", + "profile": "stamp-decay", + "evidence": "Wave L1 frame study: jh3yy stamp-and-decay contact sheet (2069614221747224613/sheet-01)", + "syncPoints": [{ "id": "travel-complete", "phase": "in", "offset": 2.4 }], + "files": [ + { + "path": "cursor-glyph-trail.html", + "target": "compositions/components/cursor-glyph-trail.html", + "type": "hyperframes:snippet" + } + ], + "variables": [ + { + "id": "glyphs", + "type": "string", + "role": "content", + "label": "Glyphs", + "description": "Stamp charset; one glyph per stamp is chosen deterministically.", + "default": "░▒▓+·×" + }, + { + "id": "density", + "type": "enum", + "role": "style", + "label": "Density", + "description": "Arc-length spacing between stamps along the path.", + "default": "med", + "options": [ + { "value": "low", "label": "Low" }, + { "value": "med", "label": "Medium" }, + { "value": "high", "label": "High" } + ] + }, + { + "id": "path", + "type": "enum", + "role": "timing", + "label": "Path", + "description": "Authored travel path preset.", + "default": "sweep", + "options": [ + { "value": "sweep", "label": "Sweep" }, + { "value": "arc", "label": "Arc" }, + { "value": "zigzag", "label": "Zigzag" } + ] + }, + { + "id": "fade", + "type": "number", + "role": "timing", + "label": "Fade", + "description": "Per-stamp decay window in seconds, clamped 0.3 to 1.5.", + "default": 0.8 + }, + { + "id": "accent", + "type": "enum", + "role": "style", + "label": "Accent", + "description": "Trail and actor color: green rides --brand, blue rides --accent, violet rides --accent-2.", + "default": "green", + "options": [ + { "value": "green", "label": "Green" }, + { "value": "blue", "label": "Blue" }, + { "value": "violet", "label": "Violet" } + ] + }, + { + "id": "exit", + "type": "enum", + "role": "timing", + "label": "Exit", + "description": "Optional departure. Default none: the settled actor holds until the frame cuts.", + "default": "none", + "options": [ + { "value": "none", "label": "None" }, + { "value": "fade", "label": "Fade" }, + { "value": "up", "label": "Up" } + ] + } + ] +} diff --git a/registry/components/echo-trail/README.md b/registry/components/echo-trail/README.md new file mode 100644 index 0000000000..45fd650227 --- /dev/null +++ b/registry/components/echo-trail/README.md @@ -0,0 +1,50 @@ +# echo-trail + +The generalized onion skin: a moving element renders with N ghosted copies of itself, each ghost showing the element where it was at t minus i * delta, opacity stepped down per ghost. One traversal along an authored path; as the element decelerates into rest the echoes collapse into it and vanish, leaving a clean settled hold. + +3.5s authored, elastic HOLD, exit `none` by default. + +## Variables + +| id | type | default | notes | +| --- | --- | --- | --- | +| `echoes` | number | `4` | Ghost copy count, clamped 2 to 6. | +| `delta` | number | `0.09` | Lag between successive ghosts in seconds, clamped 0.03 to 0.3. | +| `path` | enum | `sweep` | `sweep` is a shallow S left to right; `rise` climbs bottom-center to upper-center; `arc` rises over the top left to right. | +| `accent` | enum | `green` | Subject accent color: green rides `--brand`, blue rides `--accent`, violet rides `--accent-2`. | +| `exit` | enum | `none` | `none` holds until the cut; `fade` departs opacity-only; `up` rises out. | + +## Subject slot + +The subject is a slot. Place an inert template anywhere in the HOST page (templates never render, and the runtime wipes the host clip's own children on mount, so the slot lives at document level): + +```html + +``` + +Ghosts are deep clones of the subject content. With no slot, the primitive renders a token card (surface, hairline border, accent dot, two skeleton lines, contract tokens only). + +## Mount + +```html +
+``` + +Elastic root: no `data-width`/`data-height`; it fills whatever box the host clip gives it. Timeline registers under the literal `echo-trail` key. + +## Notes + +- Deterministic: ghost i's position at time t is `path(ease(clamp01((t - i * delta) / travel)))` and its opacity is its stepped base times a separation ramp (distance to the lead); both are recomputed from `tl.time()` on every update. No Math.random, no wall clock, no incremental state; eventful seeks (`suppressEvents=false`, the engine's render path) land identical frames in any order and either direction. +- The separation ramp is what makes the echoes collapse: before motion starts and after the lead rests, every ghost is coincident with the lead and its opacity is exactly zero, so the HOLD is truly still. +- Ghosts render beneath the lead (inserted before it) with a slight per-ghost scale step for depth; transforms are set once at mount, per-update writes touch only left/top/opacity. +- The envelope accounts for the tail: `IN = travel + echoes * delta + settle`, so the last ghost has converged inside IN even at the largest lag. diff --git a/registry/components/echo-trail/demo.html b/registry/components/echo-trail/demo.html new file mode 100644 index 0000000000..1ba9801329 --- /dev/null +++ b/registry/components/echo-trail/demo.html @@ -0,0 +1,86 @@ + + + + + + + Echo Trail Demo + + + +
+
+
+ + + + + diff --git a/registry/components/echo-trail/echo-trail.html b/registry/components/echo-trail/echo-trail.html new file mode 100644 index 0000000000..4ee056eb30 --- /dev/null +++ b/registry/components/echo-trail/echo-trail.html @@ -0,0 +1,358 @@ + + + + + + Echo Trail + + + + + diff --git a/registry/components/echo-trail/registry-item.json b/registry/components/echo-trail/registry-item.json new file mode 100644 index 0000000000..cfcab2d0f7 --- /dev/null +++ b/registry/components/echo-trail/registry-item.json @@ -0,0 +1,77 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "echo-trail", + "type": "hyperframes:component", + "title": "Echo Trail", + "description": "A moving element renders with N ghosted copies of itself at t minus i times delta, opacity stepped down per ghost; one traversal, echoes collapsing into the settled element at rest.", + "tags": ["motion-primitive", "demonstrate", "trail", "onion-skin", "ghosts", "deterministic"], + "jobs": ["demonstrate"], + "family": "demonstrate", + "profile": "onion-skin", + "evidence": "Wave L5 frame study: generalized onion skin from the trails contact sheets", + "syncPoints": [{ "id": "travel-complete", "phase": "in", "offset": 2.1 }], + "files": [ + { + "path": "echo-trail.html", + "target": "compositions/components/echo-trail.html", + "type": "hyperframes:snippet" + } + ], + "variables": [ + { + "id": "echoes", + "type": "number", + "role": "style", + "label": "Echoes", + "description": "Ghost copy count, clamped 2 to 6.", + "default": 4 + }, + { + "id": "delta", + "type": "number", + "role": "timing", + "label": "Delta", + "description": "Lag between successive ghosts in seconds, clamped 0.03 to 0.3.", + "default": 0.09 + }, + { + "id": "path", + "type": "enum", + "role": "timing", + "label": "Path", + "description": "Authored traversal preset.", + "default": "sweep", + "options": [ + { "value": "sweep", "label": "Sweep" }, + { "value": "rise", "label": "Rise" }, + { "value": "arc", "label": "Arc" } + ] + }, + { + "id": "accent", + "type": "enum", + "role": "style", + "label": "Accent", + "description": "Subject accent color: green rides --brand, blue rides --accent, violet rides --accent-2.", + "default": "green", + "options": [ + { "value": "green", "label": "Green" }, + { "value": "blue", "label": "Blue" }, + { "value": "violet", "label": "Violet" } + ] + }, + { + "id": "exit", + "type": "enum", + "role": "timing", + "label": "Exit", + "description": "Optional departure. Default none: the settled element holds until the frame cuts.", + "default": "none", + "options": [ + { "value": "none", "label": "None" }, + { "value": "fade", "label": "Fade" }, + { "value": "up", "label": "Up" } + ] + } + ] +} diff --git a/registry/components/facet-morph/README.md b/registry/components/facet-morph/README.md new file mode 100644 index 0000000000..39dcaa2354 --- /dev/null +++ b/registry/components/facet-morph/README.md @@ -0,0 +1,75 @@ +# facet-morph + +A faceted low-poly mass (36 triangles, one SVG) continuously reshapes between +three authored silhouettes (blob, mark, badge) with per-facet flat shading +that recomputes as the vertices move. Light reads from the upper left: facets +turned toward it lift toward a pale accent-tinted tone, facets turned away +fall toward near-black. One calm continuous morph in the quiet register, then +a settled hold (or a slow breath when `hold_last` is false). + +Reference: the ordinaryfolk reshaping-mass beat (motion-reference +`ordinaryfolkco/2001090228958752945`, sheet 02). + +## Files + +- `facet-morph.html`: the mountable sub-composition (install target: + `compositions/components/facet-morph.html`). +- `registry-item.json`: registry metadata and the variables block. +- `demo.html`: a full-bleed 1920x1080 LIGHT host that mounts the primitive + with non-default variables (QA gallery input). + +## Variables + +| id | type | default | notes | +| ----------- | ------- | ----------------- | ------------------------------------------------------------------------- | +| `forms` | string | `blob,mark,badge` | comma-separated silhouette sequence; valid names blob, mark, badge | +| `hold_last` | boolean | `true` | true settles dead still on the final form; false breathes through hold | +| `accent` | enum | `green` | `green` maps to `--brand`, `blue` to `--accent`, `violet` to `--accent-2` | +| `exit` | enum | `none` | `none` holds the settled mass; `fade` and `up` release the stage | + +Envelope: IN = 0.55s entrance + one 1.45s morph leg per silhouette step +(0.35s dwell between legs) + 0.55s wobble decay; OUT = 0.45s only when `exit` +is `fade` or `up`; HOLD is the sole elastic phase. The `form-lock` sync point +(`hf:sfx` id `facet-settle-soft`) fires when the mass reaches its final +silhouette, 3.95s at the 3-form default. + +## How it works (and how to restyle it) + +- Vertex positions are authored keyframe tables (per-silhouette radius, + jitter, and center rows over fixed angular spokes), interpolated as a pure + function of timeline time by one linear driver tween. Forward, backward, + and shuffled seeks land identical frames. +- Facet fills are computed in JS on every update and written as `fill` / + `stroke` ATTRIBUTES with literal `rgb()` strings. Contract tokens + (`--fg`, `--surface`, and the accent token) are resolved to concrete rgb + once at mount, so a host theme restyles the mass without any var() color + ever reaching a tween. +- The mass tone is fg-heavy (`--fg` mixed toward `--surface`), so it reads + dark on light hosts and light on dark hosts, always contrasting `--bg`. +- To add a silhouette, add one row to the `FORMS` table in your installed + copy (18 outer radii, 18 outer jitters, 9 inner radii, 9 inner jitters, + center, rotation) and name it in `forms`. + +## Worked example + +```bash +npx hyperframes add facet-morph +``` + +Mount it from a host composition like any sub-composition: + +```html +
+``` + +The mass enters over 0.55s, reshapes badge to blob to mark, and keeps a slow +breath between the last two silhouettes until the frame cuts (`exit` +defaults to `none`; frame roots own scene transitions). diff --git a/registry/components/facet-morph/demo.html b/registry/components/facet-morph/demo.html new file mode 100644 index 0000000000..3d67ff23e6 --- /dev/null +++ b/registry/components/facet-morph/demo.html @@ -0,0 +1,90 @@ + + + + + + + facet-morph Demo + + + +
+
+
+ + + + + diff --git a/registry/components/facet-morph/facet-morph.html b/registry/components/facet-morph/facet-morph.html new file mode 100644 index 0000000000..132685a687 --- /dev/null +++ b/registry/components/facet-morph/facet-morph.html @@ -0,0 +1,546 @@ + + + + + + Facet Morph + + + + + diff --git a/registry/components/facet-morph/registry-item.json b/registry/components/facet-morph/registry-item.json new file mode 100644 index 0000000000..7dd3706a1d --- /dev/null +++ b/registry/components/facet-morph/registry-item.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "facet-morph", + "type": "hyperframes:component", + "title": "Facet Morph", + "description": "A faceted low-poly mass of 36 triangles continuously reshapes between three authored silhouettes (blob, mark, badge) with per-facet flat shading that recomputes as the vertices move. Light reads from the upper left; lit facets lift toward a pale accent-tinted tone while turned-away facets fall toward near-black. One calm continuous morph, then a settled hold.", + "tags": ["motion-primitive", "intro", "morph", "low-poly", "svg", "deterministic"], + "jobs": ["reveal"], + "family": "intros-reveals", + "profile": "holdable", + "evidence": "Wave L2 frame study: ordinaryfolkco 2001090228958752945 sheet-02, the continuously reshaping faceted mass under a traveling light band", + "syncPoints": [{ "id": "form-lock", "phase": "in", "offset": 3.95 }], + "files": [ + { + "path": "facet-morph.html", + "target": "compositions/components/facet-morph.html", + "type": "hyperframes:snippet" + } + ], + "variables": [ + { + "id": "forms", + "type": "string", + "role": "content", + "label": "Forms", + "description": "Comma-separated silhouette sequence from blob, mark, badge.", + "default": "blob,mark,badge" + }, + { + "id": "hold_last", + "type": "boolean", + "role": "timing", + "label": "Hold last", + "description": "True settles dead still on the final silhouette; false keeps the mass slowly breathing through the hold.", + "default": true + }, + { + "id": "accent", + "type": "enum", + "role": "style", + "label": "Accent", + "description": "Tint of the lit facets.", + "default": "green", + "options": [ + { "value": "green", "label": "Green" }, + { "value": "blue", "label": "Blue" }, + { "value": "violet", "label": "Violet" } + ] + }, + { + "id": "exit", + "type": "enum", + "role": "timing", + "label": "Exit", + "description": "Outgoing transition. None holds the settled mass.", + "default": "none", + "options": [ + { "value": "none", "label": "None" }, + { "value": "fade", "label": "Fade" }, + { "value": "up", "label": "Up" } + ] + } + ] +} diff --git a/registry/components/halftone-dissolve/README.md b/registry/components/halftone-dissolve/README.md new file mode 100644 index 0000000000..ecd4a9aaa8 --- /dev/null +++ b/registry/components/halftone-dissolve/README.md @@ -0,0 +1,68 @@ +# halftone-dissolve + +Transition texture primitive: scene A dissolves into scene B through a +growing halftone dot field. Accent ink dots pop onto a fixed staggered grid +smallest-first, each dot then opens into a circular window onto B (the ink +leads the window by a beat, so every site flashes accent before B fills it), +until the windows merge and B fully replaces A. Radius per dot is a pure +function of (grid position, progress) via a seeded threshold map; the +direction enum orders the thresholds. 3.5s authored, elastic HOLD on B +(never time-scaled). + +## Mounting + +```html +
+``` + +## Scene slots + +Both scenes are slots. Place inert templates anywhere in the HOST page: + +```html + + +``` + +Direct `img` / `video` children are stretched to cover the stage; arbitrary +HTML is centered. A missing slot falls back to a token monogram tile +(A neutral on `--muted`, B tinted by the accent). + +## Variables + +| id | type | default | notes | +| ----------- | ------ | ------- | -------------------------------------------------------------------- | +| dot_size | enum | medium | small, medium, or large grid pitch (host width / 44, 30, 20). | +| direction | enum | ltr | ltr sweeps left to right, center grows from the middle, noise is a pure seeded scatter. | +| dissolve_at | number | 1.1 | Seconds from mount start when the dissolve begins. Clamped so the 1.3s dissolve and any exit stay inside the clip. | +| accent | enum | green | green maps to --brand, blue to --accent, violet to --accent-2. Colors the ink dots. | +| exit | enum | none | none holds scene B (frame roots own transitions); fade or up add a 0.45s departure. | + +## Choreography + +- 0.00s: scene A holds clean; no dots. +- dissolve_at: the field starts. Dots appear smallest-first in threshold + order (with a seeded jitter so the front stays granular, never ruled), + each as accent ink, then opening into a window onto B. +- dissolve_at + 1.3s: the windows merge past full coverage; the clip path + releases and B holds clean. +- HOLD: dead still on B, elastic with the clip duration. + +Sync point `dissolve` fires as the field starts; align SFX to it. + +## Determinism + +The grid and its threshold map are computed once at build from a fixed LCG +seed. One plain-object progress tween feeds one painter that redraws the +ink canvas from scratch and rebuilds B's clip-path string, all pure +functions of progress, so eventful seeks land identical frames in any order +and either direction. The raster and clip-path basis is the host box +measured once at mount. diff --git a/registry/components/halftone-dissolve/demo.html b/registry/components/halftone-dissolve/demo.html new file mode 100644 index 0000000000..236bc926c7 --- /dev/null +++ b/registry/components/halftone-dissolve/demo.html @@ -0,0 +1,147 @@ + + + + + + + Halftone Dissolve Demo + + + + + + +
+
+
+ + + + + diff --git a/registry/components/halftone-dissolve/halftone-dissolve.html b/registry/components/halftone-dissolve/halftone-dissolve.html new file mode 100644 index 0000000000..c29a08cdc9 --- /dev/null +++ b/registry/components/halftone-dissolve/halftone-dissolve.html @@ -0,0 +1,413 @@ + + + + + + Halftone Dissolve + + + + + diff --git a/registry/components/halftone-dissolve/registry-item.json b/registry/components/halftone-dissolve/registry-item.json new file mode 100644 index 0000000000..9f6d824ca0 --- /dev/null +++ b/registry/components/halftone-dissolve/registry-item.json @@ -0,0 +1,86 @@ +{ + "$schema": "https://hyperframes.heygen.com/schema/registry-item.json", + "name": "halftone-dissolve", + "type": "hyperframes:component", + "title": "Halftone Dissolve", + "description": "Scene A dissolves into scene B through a growing halftone dot field: accent ink dots pop onto a fixed grid smallest-first, each opens into a window onto B, until the windows merge and B fully replaces A.", + "tags": ["motion-primitive", "transition", "texture", "halftone", "dissolve"], + "jobs": ["bridge"], + "family": "transitions", + "profile": "texture", + "evidence": "Wave L L6: the halftone texture transition from the frame study, a seeded threshold map ordered by a direction enum", + "syncPoints": [{ "id": "dissolve", "phase": "in", "offset": 1.1 }], + "files": [ + { + "path": "halftone-dissolve.html", + "target": "compositions/components/halftone-dissolve.html", + "type": "hyperframes:snippet" + } + ], + "variables": [ + { + "id": "dot_size", + "type": "enum", + "role": "style", + "label": "Dot size", + "description": "Grid pitch for the halftone field.", + "default": "medium", + "options": [ + { "value": "small", "label": "Small" }, + { "value": "medium", "label": "Medium" }, + { "value": "large", "label": "Large" } + ] + }, + { + "id": "direction", + "type": "enum", + "role": "timing", + "label": "Direction", + "description": "Threshold ordering: ltr sweeps left to right, center grows from the middle, noise scatters.", + "default": "ltr", + "options": [ + { "value": "ltr", "label": "Left to right" }, + { "value": "center", "label": "Center out" }, + { "value": "noise", "label": "Noise" } + ] + }, + { + "id": "dissolve_at", + "type": "number", + "role": "timing", + "label": "Dissolve at", + "description": "Seconds from mount start when the dissolve begins.", + "default": 1.1, + "min": 0.2, + "max": 10, + "step": 0.1, + "unit": "s" + }, + { + "id": "accent", + "type": "enum", + "role": "style", + "label": "Accent", + "description": "Ink dot color: green rides --brand, blue rides --accent, violet rides --accent-2.", + "default": "green", + "options": [ + { "value": "green", "label": "Green" }, + { "value": "blue", "label": "Blue" }, + { "value": "violet", "label": "Violet" } + ] + }, + { + "id": "exit", + "type": "enum", + "role": "timing", + "label": "Exit", + "description": "How the frame leaves. None holds scene B.", + "default": "none", + "options": [ + { "value": "none", "label": "None" }, + { "value": "fade", "label": "Fade" }, + { "value": "up", "label": "Up" } + ] + } + ] +} diff --git a/registry/components/light-sweep-pass/README.md b/registry/components/light-sweep-pass/README.md new file mode 100644 index 0000000000..2e9e33ad12 --- /dev/null +++ b/registry/components/light-sweep-pass/README.md @@ -0,0 +1,103 @@ +# light-sweep-pass + +A traveling key light re-shades a slotted scene: a soft diagonal gradient +band crosses the frame once while every per-element highlight and shadow +shifts in lockstep, then the light settles into a resting key from the upper +third. Quiet, expensive-feeling; the scene itself never moves. + +One custom property owns the whole pass: the timeline writes `--light-x` +(a unitless frame-percent scalar on `#root`) and nothing else. The band's +translate, every highlight bloom, every shadow offset, and the ambient lift +read it through `calc()`/`clamp()`/`max()` in static CSS, so seeks in any +order resolve identical frames. + +Reference: the ordinaryfolk traveling light band (motion-reference +`ordinaryfolkco/2001090228958752945`). + +## Files + +- `light-sweep-pass.html`: the mountable sub-composition (install target: + `compositions/components/light-sweep-pass.html`). +- `registry-item.json`: registry metadata and the variables block. +- `demo.html`: a full-bleed 1920x1080 LIGHT host that mounts the primitive + with non-default variables (QA gallery input). + +## Variables + +| id | type | default | notes | +| ---------- | ------ | ---------- | ------------------------------------------------------------------------- | +| `angle` | number | `115` | band and highlight gradient angle in degrees (60 to 160) | +| `sweep_at` | number | `0.9` | seconds after mount start when the band starts crossing (0 to 8) | +| `strength` | enum | `standard` | `subtle` halves the band opacity and highlight bloom | +| `accent` | enum | `green` | `green` maps to `--brand`, `blue` to `--accent`, `violet` to `--accent-2` | +| `exit` | enum | `none` | `none` holds the settled key; `fade` and `up` release the stage | + +Envelope: IN = `sweep_at` + 1.60s crossing + 0.55s settle, OUT = 0.5s only +when `exit` is `fade` or `up`, HOLD is the sole elastic phase. The +`sweep-land` sync point (`hf:sfx` id `light-settle-soft`) fires when the +light reaches its resting key, 3.05s at defaults. + +## The slot mechanism + +The primitive ships one named full-bleed slot inside its `