asciify-engine 4.21.0 → 4.23.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 (44) hide show
  1. package/README.md +13 -0
  2. package/dist/{animation-presets-DztfFvTc.d.cts → animation-presets-CzM3jLT6.d.cts} +42 -28
  3. package/dist/{animation-presets-Bqupq1Gx.d.ts → animation-presets-a8WDzKDj.d.ts} +42 -28
  4. package/dist/core.cjs +1 -1
  5. package/dist/core.d.cts +5 -4
  6. package/dist/core.d.ts +5 -4
  7. package/dist/core.js +1 -1
  8. package/dist/field.cjs +1 -1
  9. package/dist/field.d.cts +10 -1
  10. package/dist/field.d.ts +10 -1
  11. package/dist/field.js +1 -1
  12. package/dist/{hover-guide-DKRQPtDO.d.cts → hover-catalog-CrmxlmUe.d.cts} +91 -85
  13. package/dist/{hover-guide-DKRQPtDO.d.ts → hover-catalog-CrmxlmUe.d.ts} +91 -85
  14. package/dist/hover-guide-DdFnAnfU.d.cts +9 -0
  15. package/dist/hover-guide-DdFnAnfU.d.ts +9 -0
  16. package/dist/hover.cjs +1 -1
  17. package/dist/hover.d.cts +8 -6
  18. package/dist/hover.d.ts +8 -6
  19. package/dist/hover.js +1 -1
  20. package/dist/index.cjs +1 -1
  21. package/dist/index.d.cts +4 -3
  22. package/dist/index.d.ts +4 -3
  23. package/dist/index.js +1 -1
  24. package/dist/kit.cjs +1 -1
  25. package/dist/kit.d.cts +1 -0
  26. package/dist/kit.d.ts +1 -0
  27. package/dist/kit.js +1 -1
  28. package/dist/{model-BNShxUhx.d.cts → model-C3TTmMXv.d.ts} +2 -1
  29. package/dist/{model-D2L86aNZ.d.ts → model-DAZNnqXr.d.cts} +2 -1
  30. package/dist/studio.cjs +1 -1
  31. package/dist/studio.d.cts +5 -4
  32. package/dist/studio.d.ts +5 -4
  33. package/dist/studio.js +1 -1
  34. package/dist/{types-Bmu4dXdQ.d.ts → types-BnakIXAU.d.ts} +2 -2
  35. package/dist/{types-Cn3wY-ST.d.cts → types-_8MohOZ1.d.cts} +2 -2
  36. package/package.json +1 -1
  37. package/skills/asciify-engine/SKILL.md +3 -3
  38. package/skills/asciify-engine/references/design-matching.md +1 -1
  39. package/skills/asciify-engine/references/glyph-field.md +2 -1
  40. package/skills/asciify-engine/references/kit.md +1 -1
  41. package/skills/asciify-engine/references/looks.md +2 -2
  42. package/skills/asciify-engine/references/studio-effects.md +30 -9
  43. package/skills/asciify-engine/references/studio-workspace.md +7 -8
  44. package/skills/asciify-engine/references/upgrading.md +6 -0
@@ -1,8 +1,8 @@
1
- import { A as AmbientMotion } from './hover-guide-DKRQPtDO.js';
1
+ import { A as AmbientMotion, L as LegacyAmbientMotion } from './hover-catalog-CrmxlmUe.js';
2
2
 
3
3
  type ColorMode = 'grayscale' | 'fullcolor' | 'matrix' | 'accent';
4
4
  type RenderMode = 'ascii' | 'dots';
5
- type AnimationStyle = AmbientMotion;
5
+ type AnimationStyle = AmbientMotion | LegacyAmbientMotion;
6
6
  /** Core media draws ASCII/dots; use StudioStyle for the 15 render styles. */
7
7
  type ArtStyle = 'classic';
8
8
  type HoverEffect = 'spotlight' | 'magnify' | 'repel' | 'glow' | 'colorShift' | 'attract' | 'shatter' | 'trail' | 'glitchText';
@@ -1,8 +1,8 @@
1
- import { A as AmbientMotion } from './hover-guide-DKRQPtDO.cjs';
1
+ import { A as AmbientMotion, L as LegacyAmbientMotion } from './hover-catalog-CrmxlmUe.cjs';
2
2
 
3
3
  type ColorMode = 'grayscale' | 'fullcolor' | 'matrix' | 'accent';
4
4
  type RenderMode = 'ascii' | 'dots';
5
- type AnimationStyle = AmbientMotion;
5
+ type AnimationStyle = AmbientMotion | LegacyAmbientMotion;
6
6
  /** Core media draws ASCII/dots; use StudioStyle for the 15 render styles. */
7
7
  type ArtStyle = 'classic';
8
8
  type HoverEffect = 'spotlight' | 'magnify' | 'repel' | 'glow' | 'colorShift' | 'attract' | 'shatter' | 'trail' | 'glitchText';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asciify-engine",
3
- "version": "4.21.0",
3
+ "version": "4.23.0",
4
4
  "description": "Framework-agnostic ASCII art engine. Convert images, videos, and GIFs into ASCII art rendered on canvas, or run full-bleed GPU character fields with a fluid cursor wake.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -2,13 +2,13 @@
2
2
  name: asciify-engine
3
3
  description: Apply Asciify the way asciify.org does - ASCII components and backgrounds that belong in a real interface, inked from the theme, clear around text, inside the page's radii and motion. Use for UI components in characters (loading, status, toasts, tabs, AI states, charts, transitions, pages), animated ASCII backgrounds, and also photo, video and GIF conversion, GPU character fields, artwork looks for wallpapers, posters and prints, art styles and export, hover and motion, layered typography and rendering performance.
4
4
  metadata:
5
- tested-engine: "4.21.0"
5
+ tested-engine: "4.23.0"
6
6
  updated: "2026-10-17"
7
7
  ---
8
8
 
9
9
  # Asciify Engine
10
10
 
11
- Use the published `asciify-engine` npm package. Tested against **4.21.0**. Check the application's installed version and its public types before using newer options; a local checkout can contain unpublished changes.
11
+ Use the published `asciify-engine` npm package. Tested against **4.23.0**. Check the application's installed version and its public types before using newer options; a local checkout can contain unpublished changes.
12
12
 
13
13
  - Agent entry: https://asciify.org/skill (redirects to this Markdown document).
14
14
  - Components: https://asciify.org/components · Looks: https://asciify.org/looks · Backgrounds: https://asciify.org/backgrounds
@@ -153,7 +153,7 @@ Preview it: letter glyph densities differ, so arbitrary words are not automatica
153
153
 
154
154
  The core `HoverEffect` IDs are `spotlight`, `magnify`, `repel`, `glow`, `colorShift`, `attract`, `shatter`, `trail`, and `glitchText`. Those remain valid APIs, but they are **not identical to the current website's enhanced interactions**.
155
155
 
156
- The website offers **Trail, Dissolve, Contour, Emboss, Ripple rings, Ink bleed, Water, Silk, Vortex, Magnetic Pull, Scatter, Elastic, Lens wake, Smudge, Loupe, Reveal, Repel, Tilt, Heat haze, and Off** through an optional studio surface module, each with `scope: 'all' | 'subject' | 'outside'` to keep it on a cut-out subject or around it (`rake` is retired and plays Silk). Its fourteen still-image motions—Caustics, Slow Current, Reveal & Reform, Sheen, Tidal Rings, Living Grain, Parallax, Woven Flow, Print Shift, Contour Light, Relight, Shimmer, Breeze, Unfold—and fine-dither treatments ship in the same `asciify-engine/hover` module. Use its typed options rather than converting display names into engine `hoverEffect` or `animationStyle` values.
156
+ The website offers **Trail, Dissolve, Contour, Emboss, Ripple rings, Ink bleed, Water, Silk, Vortex, Magnetic Pull, Scatter, Elastic, Lens wake, Smudge, Loupe, Reveal, Repel, Tilt, Heat haze, and Off** through an optional studio surface module, each with `scope: 'all' | 'subject' | 'outside'` to keep it on a cut-out subject or around it (`rake` is retired and plays Silk). Its ten photo-aware still-image motions—Relight, Specular sweep, Highlight bloom, Glints, Parallax, Slow push, Focus pull, Mist, Drift, Develop—read the image's own light and depth (retired IDs such as `caustics` load as their closest replacement), and they and the fine-dither treatments ship in the same `asciify-engine/hover` module. Use its typed options rather than converting display names into engine `hoverEffect` or `animationStyle` values.
157
157
 
158
158
  To reproduce those interactions, read [references/studio-effects.md](references/studio-effects.md). Import `mountHover` from `asciify-engine/hover`; no separate download is needed. Keep engine `hoverStrength: 0` and `animationStyle: 'none'` when using it, to avoid applying two effects. Trail is the site's default. Prefer a stationary-grid effect such as Trail or Dissolve when the user wants a wake without spatial displacement.
159
159
 
@@ -82,7 +82,7 @@ A still photo can be made to feel alive, and many users want that. Others want i
82
82
  | API | Living | Still |
83
83
  | --- | --- | --- |
84
84
  | `/field` | `drift: 0.15–0.35` so a photo breathes; or a video `source`; or `scene: 'flow' \| 'orb'` with no media | A media `source`, `drift: 0`, and `hover: 'lantern'` or `'none'`. With no pointer it draws once and stops working |
85
- | `/studio` | `motion: { type: 'sheen' \| 'breeze' \| 'relight' \| 'shimmer', speed: 0.4–0.8, amount: 0.3–0.6 }` for calm life; `'current'`, `'tidal'`, `'caustics'` for stronger; or a `STUDIO_ANIMATION_PRESETS` entry such as `quiet-light` | `motion: { type: 'none' }`, and `hover.effect: 'none'` or a stationary one such as `'trail'` |
85
+ | `/studio` | `motion: { type: 'relight' \| 'sheen' \| 'glow' \| 'mist', speed: 0.4–0.8, amount: 0.5–0.9 }` for calm life; `'parallax'`, `'push'`, `'focus'`, `'current'` for depth; or a `STUDIO_ANIMATION_PRESETS` entry such as `quiet-light` | `motion: { type: 'none' }`, and `hover.effect: 'none'` or a stationary one such as `'trail'` |
86
86
  | `/hover` over a core render | `motion: 'sheen'` (any `AmbientMotion`) | `motion: 'none'`; core `animationStyle: 'none'` |
87
87
 
88
88
  Autonomous motion that lasts longer than five seconds needs a visible pause control (WCAG 2.2.2). Prefer slow speeds; motion should be noticed on the second look, not the first.
@@ -55,7 +55,8 @@ Size the canvas with CSS (for example `position:absolute; inset:0; width:100%; h
55
55
  | `fit`, `focus` | `'cover'`, centre | `focus` moves the cover crop (0–1 on each axis). |
56
56
  | `vignette` | `0` | Darkens toward the corners. |
57
57
  | `drift`, `speed` | `0`, `1` | Slow ambient sampling drift keeps a still image alive; `speed` scales drift and generated scenes. |
58
- | `hover` | `'fluid'` | `'fluid'`: an ink-in-water wake that bends the image and swirls the characters. `'lantern'`: a soft light that follows the pointer and lifts characters with no distortion. `'trail'`: the Asciify Trail, the same ink field as the studio's Trail hover: in the wake, sparse characters fill in and dense ones open up, then settle, with no distortion. `'loupe'`: a glass loupe glides after the pointer and magnifies the characters it covers through a soft rim. `'reveal'`: under a soft spotlight the characters take the source's own colours (best over a photo in one ink). Loupe and Reveal use the `lantern` radius, strength and follow. `'none'`: still under the pointer. `FIELD_HOVERS` lists them with labels. The field has no `scope`; for a cut-out subject use `/studio` or `/hover`. |
58
+ | `hover` | `'fluid'` | `'fluid'`: an ink-in-water wake that bends the image and swirls the characters. `'lantern'`: a soft light that follows the pointer and lifts characters with no distortion. `'trail'`: the Asciify Trail, the same ink field as the studio's Trail hover: in the wake, sparse characters fill in and dense ones open up, then settle, with no distortion. `'loupe'`: a glass loupe glides after the pointer and magnifies the characters it covers through a soft rim. `'reveal'`: under a soft spotlight the characters take the source's own colours (best over a photo in one ink). Loupe and Reveal use the `lantern` radius, strength and follow. `'none'`: still under the pointer. `FIELD_HOVERS` lists them with labels. See `scope`. |
59
+ | `scope` | `'all'` | Where the pointer response acts: `'all'`, `'subject'` (only on the source's subject) or `'outside'` (only on the ground around it). The subject is the source's alpha, or for an opaque source on a plain, even border its distance from that ground (the same detection as `/studio`), feathered at the edge; a busy photo and generated scenes act as `'all'`. Video re-reads the subject about six times a second on a 96-cell grid. Applies to every hover. |
59
60
  | `trail` | `{ strength: 0.55, radius: 0.45 }` | Same meaning and defaults as the studio's Trail hover, so a look moves between renderers unchanged. |
60
61
  | `lantern` | soft | `radius` (fraction of height), `strength`, `trail` (seconds its tail takes to fade), `follow` (how tightly the light catches the pointer). |
61
62
  | `fluid` | on | Settings for the fluid hover; `false` turns it off. `radius` (fraction of height), `force`, `dissipation` (per second; higher settles sooner), `curl` (vorticity: how strongly the wake curls into eddies, 0 is a straight smear), `refraction` (how far the flow bends sampling), `glow` (how strongly the flow lights characters), `resolution` (simulation grid, longest side). |
@@ -15,7 +15,7 @@ Every function takes these options:
15
15
  | Option | Default | Meaning |
16
16
  | --- | --- | --- |
17
17
  | `ink` | per component | A CSS colour, a custom property (`'--brand'`) or `'var(--brand, #888)'`. Re-read when the theme changes (media query, or `class`/`data-theme` on `<html>` or `<body>`). Defaults pick light or dark ink from the element's own opaque background, else from its text colour. |
18
- | `look` | none | Raw glyph-field settings layered over the component's look: `charset`, `cellSize`, `font` and so on. |
18
+ | `look` | none | Raw glyph-field settings layered over the component's look: `charset`, `cellSize`, `font` and so on. Pointer settings go here too: `hover`, `trail`, `lantern` and `scope` (`'all'` default, `'subject'`, `'outside'`), e.g. `look: { scope: 'outside' }` keeps a component's wake off a cut-out subject. |
19
19
  | `reducedMotion` | the visitor's setting | `true` or `false` to override `prefers-reduced-motion`. Reduced motion draws each state settled, in one frame. |
20
20
  | `lazy` | `true` | Mount the field only near the viewport and release it far from it. `false` mounts at once, wherever the element is. See Performance and integration. |
21
21
  | `poster` | none | A still image under the field: shown until the first GPU frame, while the field is released, and in its place without WebGL. |
@@ -858,7 +858,7 @@ const art = await mountStudio(canvas, '/your-video.mp4', {
858
858
  ## wallpaper: Wallpaper
859
859
  Category: Characters
860
860
  Use it for: a living desktop or phone wallpaper, a screensaver, or a full-bleed artwork that moves on its own.
861
- Settings: `studioLook('wallpaper')`: ASCII, `#e6e3da` ink over the source blurred 18px at .4 opacity on `#0b0b0a`, caustics motion at speed .35.
861
+ Settings: `studioLook('wallpaper')`: ASCII, `#e6e3da` ink over the source blurred 18px at .4 opacity on `#0b0b0a`, Relight motion at speed .35 and strength .8.
862
862
 
863
863
  Prompt:
864
864
  “Make [my photo] into a living wallpaper with asciify-engine: ASCII characters over a softened, blurred copy of the photo, with slow caustic light moving through them. Export one seamless loop as a 1920×1440 MP4 and a 3200×2400 PNG still.”
@@ -871,7 +871,7 @@ const media = await loadStudioMedia(file);
871
871
  try {
872
872
  const loop = await exportStudio({ frame: () => media.frame(0) }, settings, {
873
873
  format: 'mp4', width: 1920, height: 1440, referenceWidth: 960, fps: 30,
874
- duration: 12 / settings.motion.speed, maxCells: 131072, // one full caustics cycle loops cleanly
874
+ duration: 12 / settings.motion.speed, maxCells: 131072, // one full Relight orbit loops cleanly
875
875
  });
876
876
  } finally { media.destroy(); }
877
877
  ```
@@ -40,7 +40,7 @@ Nineteen hovers plus Off, in three families. All share `strength` (0–1), `radi
40
40
  | `etch` | Change characters | Signed light-and-shadow impression (“Emboss”). | Engraving, paper. |
41
41
  | `ripple` | Change characters | Expanding signed tonal wave packets; faster strokes ring stronger. | Dot, LED and tile looks. |
42
42
  | `bleed` | Change characters | Ink bleed: ink wells up where the cursor rests, spreads along a fibrous paper grain, then dries back from its edges. | Sumi, woodcut, stipple, pen and ink. |
43
- | `water` | Move the image | Damped height-field refraction that settles after the stroke. | Frosted glass, water, calm heroes. |
43
+ | `water` | Move the image | Damped height-field refraction. Once the stroke stops the damping firms up: most of the wake is gone within about a second and it is still by about 1.7 s at the default `decay` (raise `decay` to linger). | Frosted glass, water, calm heroes. |
44
44
  | `silk` | Move the image | Directional folds that follow the hand. | Fabric, fashion, slow motion. |
45
45
  | `vortex` | Move the image | A swirling wake. | Playful, music. |
46
46
  | `magnetic` | Move the image | The image gathers toward the stroke, then relaxes. | Product details. |
@@ -55,7 +55,9 @@ Nineteen hovers plus Off, in three families. All share `strength` (0–1), `radi
55
55
  | `haze` | Follow the cursor | Heat haze: a rising shimmer bends the characters above the cursor, livelier while moving, calm at rest. | Neon, broadcast, dusk gradients. |
56
56
  | `none` | | No hover effect. | |
57
57
 
58
- Retired: `rake` (its combed strips tore the image) now plays `silk`. Saved settings and old integrations keep working; `DEPRECATED_STUDIO_HOVERS` lists the mapping. Cursor hovers (`loupe`, `reveal`, `repel`, `tilt`, `haze`) store a fraction of the artwork, so they scale with it; stroke hovers keep their CSS-pixel reach.
58
+ The catalog lives in the engine: `STUDIO_HOVERS` (IDs, labels, groups, descriptions), `HOVER_SCOPES`, `HOVER_CONTROLS` (label, `min`, `max`, `step` and `default` of `radius`, `strength` and `decay`), `DEFAULT_HOVER`, `DEPRECATED_STUDIO_HOVERS`, `resolveHover(value)` and the `HoverEffect` type, exported from both `asciify-engine/hover` and `asciify-engine/studio`. Build pickers and sliders from these rather than copying them.
59
+
60
+ Retired: `rake` (its combed strips tore the image) now plays `silk`. Saved settings and old integrations keep working; `DEPRECATED_STUDIO_HOVERS` lists the mapping. Cursor hovers (`loupe`, `reveal`, `repel`, `tilt`, `haze`) store a fraction of the artwork, so they scale with it; stroke hovers keep their CSS-pixel reach. On `/hover` the image moves in whole cells, read at each cell's centre, so characters are carried intact rather than smeared; a redrawn cell keeps the artwork's plain ground under it. Match `fontSize`, `charAspect` and `charSpacing` to the backing canvas's cells (for a Studio canvas: `fontSize` = cell size, `charAspect` = 1 / 1.65 for character styles).
59
61
 
60
62
  These are `/hover` module `effect` IDs, not the root engine’s legacy `HoverEffect` values. For example, passing `hoverEffect: 'water'` to the published engine is invalid.
61
63
 
@@ -76,7 +78,7 @@ How the subject is found, in order:
76
78
  3. **A plain ground.** An opaque image whose border is one even tone (a product or figure on black or white, as the Cutout, Halo overlay and Mascot sticker looks expect) is keyed by each area's distance from that tone.
77
79
  4. **Otherwise** (a busy edge-to-edge photo) there is no reliable subject, so every scope behaves like `'all'` rather than guessing.
78
80
 
79
- Coverage is feathered over about 2% of the short side, so a scoped hover fades softly at the boundary and never clips hard. Displacement, tone and light are all weighted by it. With `'outside'` on a transparent ground, tone hovers (Trail, Contour, Emboss, Ripple, Ink bleed, Heat haze) draw their own marks in the ink colour on the empty ground. In `/hover` the subject is read from the drawn canvas once per still (`invalidate()` rereads it); for video the first frame's subject is kept.
81
+ Coverage is feathered over about 2% of the short side, so a scoped hover fades softly at the boundary and never clips hard. Displacement, tone and light are all weighted by it. With `'outside'` on a transparent ground, tone hovers (Trail, Contour, Emboss, Ripple, Ink bleed, Heat haze) draw their own marks in the ink colour on the empty ground. Ripple and Emboss also draw their own faint rings on a near-black opaque ground (in any scope that reaches it), where a tone lift alone barely shows. In `/hover` the subject is read from the drawn canvas once per still (`invalidate()` rereads it); with `animated: true` (video, GIF) it is re-read from new frames about six times a second on a small grid, reusing its buffers.
80
82
 
81
83
  ## Smart behaviour
82
84
 
@@ -86,7 +88,22 @@ Coverage is feathered over about 2% of the short side, so a scoped hover fades s
86
88
 
87
89
  ## Still-image motion and dither
88
90
 
89
- The module's `motion` IDs are `none`, `caustics` (traveling light on a fixed grid), `current` (Slow Current), `reform` (Reveal & Reform), `sheen` (diagonal light sweep), `tidal` (Tidal Rings), and `grain` (Living Grain). 4.4 adds `parallax` (shallow drift), `weave` (interlaced flow), `print` (staggered row registration), and `trace` (light that follows source-image tonal contours). Sheen, Living Grain and Contour Light keep the grid anchored. Contour Light uses source luminance; pass `getFrame` for exact source tones when layering a surface over an existing canvas. Keep source-video motion alone unless the user intentionally wants another animation layered onto it. For a still, select one motion and a restrained `motionSpeed`, rather than stacking effects.
91
+ Still-image motion reads the photograph itself (its soft luminance, a relief normal, highlight nearness, local detail, an estimated depth and where its water and sky are, rebuilt once per source frame) so light and movement are motivated by the image instead of laid over it. The `motion` IDs:
92
+
93
+ | ID | Label | Group | What moves | Grid |
94
+ |---|---|---|---|---|
95
+ | `relight` | Relight | Light | A key light circles the subject and models its own relief; flat areas stay put. | anchored |
96
+ | `sheen` | Specular sweep | Light | One slow pass of light across the upper midtones and highlights, bent by their form, then a rest. | anchored |
97
+ | `glow` | Highlight bloom | Light | The brightest areas breathe a halo outward; deep shadows stay deep. | anchored |
98
+ | `shimmer` | Glints | Light | Sparse, phased glints only on bright fine detail (water, metal, eyes). | anchored |
99
+ | `parallax` | Parallax | Depth | Slow camera drift; near and far move against each other. | resampled |
100
+ | `push` | Slow push | Depth | Ken Burns push toward the subject's center and back; nearer areas move slightly more. Never samples outside the frame. | resampled |
101
+ | `focus` | Focus pull | Depth | Focus racks from subject to background and back; out-of-focus areas flatten toward their neighbourhood. | anchored |
102
+ | `mist` | Mist | Atmosphere | Soft mist drifts through the distance and plain areas only. | anchored |
103
+ | `current` | Drift | Atmosphere | Cinemagraph: water swells sideways and glints, falling water streams down, sky and clouds slide very slowly. Subjects, buildings and land hold perfectly still. | resampled |
104
+ | `develop` | Develop | Reveal | Holds, fades, then develops back in from highlights to shadows. | anchored |
105
+
106
+ "Anchored" motions change light only. "Resampled" motions move the image through a fixed character grid, so every glyph stays aligned and readable. Light motions mostly brighten the ink and change character density for only part of the shift, so light glows instead of flickering. Every motion except Relight, Glints and Mist shows the untouched still at time 0, which is what reduced motion and a paused preview display. Retired IDs still load as their closest replacement (`DEPRECATED_STUDIO_MOTIONS`): `caustics` → `sheen`, `grain` → `shimmer`, `trace` → `relight`, `tidal`/`weave`/`breeze` → `current`, `reform`/`print`/`unfold` → `develop`. Keep source-video motion alone unless the user intentionally wants another animation layered onto it. For a still, select one motion and a restrained `motionSpeed`, rather than stacking effects.
90
107
 
91
108
  For the website's fine-dither treatment, use the module's `fineDither: true` and `ditherStrength` after matching the backing canvas's character settings. This is separate from the core renderer’s built-in dither behavior. Check a still and a moving scene for flicker before choosing the default.
92
109
 
@@ -105,19 +122,23 @@ Version 1.3.0 adds text-shaped charcoal cutouts (`textMask`), peripheral scanlin
105
122
 
106
123
  ## Catalogs and useful combinations (4.4)
107
124
 
108
- Build controls from `STUDIO_HOVERS`, `HOVER_SCOPES` and `STUDIO_MOTIONS`, exported by `/studio` and `/hover`. Each entry includes `value`, `label` and `description` (hovers also a `group`). Show the scope control as a segmented choice next to the hover settings. Use the `value` as the API ID; “Emboss” is `etch` and “Contour Light” is `trace`. Do not maintain a second hard-coded menu or use the legacy core hover IDs for these interactions.
125
+ Build controls from `STUDIO_HOVERS`, `HOVER_SCOPES` and `STUDIO_MOTIONS`, exported by `/studio` and `/hover`. Each entry includes `value`, `label` and `description` (hovers also a `group`). Show the scope control as a segmented choice next to the hover settings. Use the `value` as the API ID; “Emboss” is `etch`, “Specular sweep” is `sheen` and “Drift” is `current`. Do not maintain a second hard-coded menu or use the legacy core hover IDs for these interactions.
109
126
 
110
- For a fixed grid, try Contour Light with Emboss. For continuous spatial movement, try Parallax with Elastic. For a fabric-like treatment, try Woven Flow with Rake. These are combinations of two independent settings, not additional art styles. Keep strength restrained until you have checked the source at actual display size.
127
+ For a fixed grid, try Relight with Emboss. For depth, try Parallax or Slow push with Tilt. For water and sky, try Drift with Ripple rings. These are combinations of two independent settings, not additional art styles. Keep strength restrained until you have checked the source at actual display size.
111
128
 
112
129
  All ambient modes repeat after `12 / speed` seconds. Looping the motion does not guarantee that a source video, film grain, dust, glitch or animated dither has the same boundary. Exported PNG/JPEG captures one frame; MP4/WebM/GIF carries autonomous motion, not live pointer movement. For complete composition export, use `/studio` rather than capturing the hover overlay.
113
130
 
114
131
  The pointer simulations have bounded storage. Elastic allocates its two velocity buffers only when first selected; idle effects stop. This is not a device-independent FPS promise. Test dense grids, fast reversal and the actual finish stack on the target device.
115
132
 
116
- ## Lively images (4.10)
133
+ ## Lively images
134
+
135
+ The catalogs contain nineteen active hover effects and ten active ambient motions, plus Off for each (see the table above). All use deterministic 12-second base cycles; `motion.speed` changes cycle duration, `motion.amount` (0–2) changes strength. These are local image treatments driven by the photo's own light and depth estimate, not AI-generated scene or subject motion.
136
+
137
+ **Depth** is a monocular estimate on a small analysis grid (up to 12,000 cells; larger grids are averaged down first), about 2–6 ms per source frame with no model or network. It fuses focus (fine and mid detail survive where the lens was focused; defocus is far), atmospheric perspective (haze lifts the darkest channel, lowers contrast and cools; dark areas abstain), a ground-plane prior (nearer toward the bottom, trusted only when the frame has a horizon: a long colour step across the width with rougher ground below), texture gradient (finer texture is farther on a receding surface) and colour saliency (a distinct, saturated, central region is near), each weighted by its own confidence. Sky is pushed far, and objects standing against it (a palm, a tower, a cable car) are left to the other cues. A subject cut out by alpha or a plain ground still wins. The fused map is smoothed with a colour guided filter, so it follows object edges instead of bleeding across them. Parallax, Slow push, Focus pull and Mist read it.
117
138
 
118
- The catalogs contain nineteen active hover effects and fourteen active ambient motions, plus Off for each. New motion IDs are `relight`, `shimmer`, `breeze`, and `unfold`. Relight models midtones with a rotating light field; Shimmer slowly animates source highlights. Both keep geometry stationary. Breeze bends the image with a traveling sway. Unfold closes and opens staggered panels, then holds the complete image. All use deterministic 12-second base cycles; `motion.speed` changes cycle duration, `motion.amount` changes strength. These are local image treatments, not AI-generated scene or subject motion.
139
+ **Water, sky and falls** (Drift) come from colour, texture, direction and position, read from the photograph before grading (contrast can clip a fall or a sky to flat white). Sky is smooth blue, a warm gradient or (with a horizon) night or cloud-white, reached from the top edge; a night sky must be plainer than the lit city under it, and clouds extend only a few cells out from the sky, so snow and pale walls touching it stay put. Water is blue-green to cyan in a real expanse (below the horizon when there is a sky), grown through foam, spray, glints and dark water and stopped by clearly hued objects (skin, a shell, a hull). A sea of any other colour (sunset, night harbour) is found by its reflection: below a ruler-straight waterline, each cell echoes the hue of the cell mirrored above it, is clearly darker, and itself looks like water (fine level ripples, or the dark of a night sea); every straight line is tried and the one whose echo explains the most cells wins. Falling water (a waterfall, a fountain) is bright, nearly colourless, streaked up and down, churning along its length (a column or a pleat is smooth top to bottom) and tall; it flows downward. All masks are snapped to the photo and eroded so the flow never samples across a subject's edge. A grayscale or single-ink grid has no hue to read, so Drift then finds less. Known gaps: rain is not treated as falling water, and a sea is found only where its waterline is straight and its sky is visible.
119
140
 
120
- `STUDIO_ANIMATION_PRESETS` is exported by `/studio` and `/hover`. Its six entries have `id`, `label`, `description`, `motion: {type,speed,amount}`, and `hover: {effect,radius,strength}`. These are editable combinations, not additional renderer styles. Do not overwrite the rest of a user's settings to apply one:
141
+ `STUDIO_ANIMATION_PRESETS` is exported by `/studio` and `/hover`. Its seven entries have `id`, `label`, `description`, `motion: {type,speed,amount}`, and `hover: {effect,radius,strength}`. These are editable combinations, not additional renderer styles. Do not overwrite the rest of a user's settings to apply one:
121
142
 
122
143
  ```ts
123
144
  import { mountStudio, STUDIO_ANIMATION_PRESETS } from 'asciify-engine/studio';
@@ -93,7 +93,7 @@ Bounds: 4096 pixels per side and 16 megapixels for stills; video at most 3840×2
93
93
 
94
94
  ## Curated characters and the primary editor (2.0)
95
95
 
96
- The site opens the workspace directly at `/editor`. Upload media, choose Style, then use Canvas for framing/backdrops/masks, Effects for motion/hover/finishing, Looks for reuse, and Export for downloads/code. Optical finish and Lighting expand on demand; they keep applied values when collapsed. The prior editor remains at `/editor/classic` for earlier workflows.
96
+ The site opens the workspace directly at `/editor`. Upload media, choose Style, then use Canvas for framing/backdrops/masks, Effects for motion/hover/finishing, Looks for reuse, and Export for downloads/code. Optical finish and Lighting expand on demand; they keep applied values when collapsed. The prior editor remains at `/editor/classic` for earlier workflows, including posting to the community. Its motion menu is the same Studio catalog, drawn by the core renderer through `animationStyle`.
97
97
 
98
98
  ```ts
99
99
  import { STUDIO_CHARACTER_SETS, updateStudioSettings } from 'asciify-engine/studio';
@@ -113,7 +113,7 @@ For PNG/JPEG, pass `time: player.time` and `motionTime: player.motionTime` to `e
113
113
 
114
114
  ## Still-image motion (3.0)
115
115
 
116
- Import `STUDIO_MOTIONS` from `/studio` to populate controls; each item has `value`, `label`, and `description`. Use `motion: { type: 'caustics' | 'current' | 'reform' | 'none', speed: 1 }`. Off is the default. Caustics preserves the grid, Current introduces fluid displacement, and Reform uses a staggered dissolve with a readable hold. Loops last 12 / speed seconds and preserve source/accent/gray color choice. Speed is 0.1–3. Do not combine source video with ambient motion unless requested. Hover remains independently configurable. Retired saved motion names normalize to Off. See [upgrading.md](upgrading.md) before moving an existing integration to 3.0.
116
+ Import `STUDIO_MOTIONS` from `/studio` to populate controls; each item has `value`, `label`, and `description`. Use `motion: { type: 'relight' | 'sheen' | 'glow' | 'shimmer' | 'parallax' | 'push' | 'focus' | 'mist' | 'current' | 'develop' | 'none', speed: 1 }`. Off is the default. Every motion reads the photo's own light and depth ([studio-effects.md](studio-effects.md#still-image-motion-and-dither)); retired IDs such as `caustics` load as their closest replacement. Loops last 12 / speed seconds and preserve source/accent/gray color choice. Speed is 0.1–3. Do not combine source video with ambient motion unless requested. Hover remains independently configurable. Names retired in 3.0 normalize to Off; later retired names map to a current motion. See [upgrading.md](upgrading.md) before moving an existing integration to 3.0.
117
117
 
118
118
  ## Sharp previews (3.0.1)
119
119
 
@@ -166,9 +166,8 @@ and `scatter` (radial, spatially varied scatter that relaxes). Both retain a
166
166
  bounded field after cursor exit; radius and strength control the response.
167
167
  Use `hover.effect` in Studio and `effect` in mountHover. Defaults remain unchanged.
168
168
 
169
- Still-image motion now has six active choices: `caustics`, `current`, `reform`,
170
- `sheen`, `tidal`, and `grain`, plus `none`. Sheen and Living Grain change tone
171
- without displacement; Tidal Rings moves the image with protected edges.
169
+ Still-image motion: see the current catalog in [studio-effects.md](studio-effects.md#still-image-motion-and-dither).
170
+ Light motions change tone without displacement; depth motions move the image through a fixed grid.
172
171
  Set Studio `motion: { type: 'sheen', speed: 0.7, amount: 0.6 }`.
173
172
  Core uses `animationStyle`; mountHover uses `motion` and `motionSpeed`.
174
173
  Base cycles last 12 seconds; speed scales duration. Studio amount scales strength.
@@ -182,9 +181,9 @@ Stationary artwork, masks, lights, backdrops and character bloom are cached whil
182
181
 
183
182
  ## Expanded motion library (4.4)
184
183
 
185
- Use `STUDIO_HOVERS` and `STUDIO_MOTIONS` to show all available hovers and still-image motions, plus Off, grouped by behavior. New hover IDs are `etch`, `elastic`, `rake`; new motion IDs are `parallax`, `weave`, `print`, `trace`. `hover.radius` and `hover.strength` are independent of `motion.speed` and `motion.amount`. All remain serialized in look links and saved projects. A static photo needs no video input or AI service to animate.
184
+ Use `STUDIO_HOVERS` and `STUDIO_MOTIONS` to show all available hovers and still-image motions, plus Off, grouped by behavior. New hover IDs are `etch`, `elastic`, `rake`; the 4.4 motions were later replaced by photo-aware ones (see [upgrading.md](upgrading.md)). `hover.radius` and `hover.strength` are independent of `motion.speed` and `motion.amount`. All remain serialized in look links and saved projects. A static photo needs no video input or AI service to animate.
186
185
 
187
- Example: `player.update({ motion: { type: 'trace', speed: 1, amount: .7 }, hover: { effect: 'etch', radius: .45, strength: .65 } })`. Tone and character choices remain yours. See [effect behaviors and combinations](studio-effects.md#catalogs-and-useful-combinations-44). Do not run several looping thumbnail canvases just to display this catalog; apply the selected treatment to one shared preview.
186
+ Example: `player.update({ motion: { type: 'relight', speed: 1, amount: .7 }, hover: { effect: 'etch', radius: .45, strength: .65 } })`. Tone and character choices remain yours. See [effect behaviors and combinations](studio-effects.md#catalogs-and-useful-combinations-44). Do not run several looping thumbnail canvases just to display this catalog; apply the selected treatment to one shared preview.
188
187
 
189
188
  ## Tonal detail and blue noise (4.5)
190
189
 
@@ -202,7 +201,7 @@ const player = await mountStudio(canvas, '/portrait.jpg', {
202
201
  style: 'dither',
203
202
  color: { gamma: 1.12, shadows: .15, highlights: -.12 },
204
203
  dither: { algorithm: 'blue-noise', palette: 'gray8', scale: 3 },
205
- motion: { type: 'trace', speed: .7, amount: .25 },
204
+ motion: { type: 'relight', speed: .7, amount: .4 },
206
205
  },
207
206
  maxDimension: 960,
208
207
  maxCells: 65536,
@@ -85,3 +85,9 @@ Six additional `STUDIO_STYLES` use optional `print` settings. Existing v1 settin
85
85
  ## 4.10 interaction expansion
86
86
 
87
87
  Adds `lens`, `smudge`, `ripple` hover and `relight`, `shimmer`, `breeze`, `unfold` ambient motion. No IDs are removed and existing defaults remain. `STUDIO_ANIMATION_PRESETS` is exported by Studio and hover; its nested settings are shaped for `player.update`. Core accepts the new ambient IDs through `animationStyle`, with its existing simpler opacity treatment. Do not pass the new surface hover IDs to core `hoverEffect`. Update the npm dependency and refresh the agent skill separately; older packages do not implement these IDs.
88
+
89
+ ## Photo-aware motion and finish (after 4.21)
90
+
91
+ The still-image motions are rebuilt to read the photograph's own light, relief, highlights, detail and depth instead of laying a pattern over it. The catalog is `relight`, `sheen` (Specular sweep), `glow` (Highlight bloom, new), `shimmer` (Glints), `parallax`, `push` (Slow push, new), `focus` (Focus pull, new), `mist` (new), `current` (Drift) and `develop` (new), plus `none`. Retired IDs keep working everywhere (Studio settings, share links, `mountHover` `motion`, core `animationStyle`) and load as their closest replacement, listed in `DEPRECATED_STUDIO_MOTIONS`: `caustics` → `sheen`, `grain` → `shimmer`, `trace` → `relight`, `tidal`, `weave`, `breeze` → `current`, `reform`, `print`, `unfold` → `develop`. Normalized settings store the new ID. Depth motions now move the image through a fixed character grid instead of moving glyphs; the core renderer (`animationStyle`) draws them the same way as the Studio, sharing its motion code, and light motions change tone, colour and density there rather than only opacity. Drift moves only detected water and sky. `STUDIO_ANIMATION_PRESETS` keeps its six IDs with new pairings and adds `depth-study`; the `wallpaper` look uses Relight.
92
+
93
+ The optical finish's `bloom` is now a wide, soft-kneed halation screened over the image (no offset ghosts), and `grain` is fine triangular film grain weighted to the midtones. IDs and ranges are unchanged; existing looks render slightly softer and cleaner.