asciify-engine 4.30.0 → 4.31.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 (56) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/kit/chunk-26HU7QJW.js +1 -0
  3. package/dist/kit/chunk-2ZBPTNGK.js +1 -0
  4. package/dist/kit/{chunk-64NSPD2R.js → chunk-62KEKWSM.js} +1 -1
  5. package/dist/kit/chunk-6646EUJY.js +1 -0
  6. package/dist/kit/chunk-6YLMG37G.js +1 -0
  7. package/dist/kit/{chunk-MYAZOXMF.js → chunk-7DBDSJ5R.js} +1 -1
  8. package/dist/kit/chunk-7NS6YAD3.js +1 -0
  9. package/dist/kit/chunk-7OPCQDAL.js +1 -0
  10. package/dist/kit/{chunk-Y2SDQ6EC.js → chunk-CIGEXHZ5.js} +1 -1
  11. package/dist/kit/chunk-DANNL7WR.js +1 -0
  12. package/dist/kit/{chunk-VENDLTH4.js → chunk-ECGALF3G.js} +1 -1
  13. package/dist/kit/chunk-EOTPXDMH.js +1 -0
  14. package/dist/kit/{chunk-6NDTKY3V.js → chunk-J7TFGVZT.js} +1 -1
  15. package/dist/kit/{chunk-UXJRBOSR.js → chunk-JSRXW3FL.js} +1 -1
  16. package/dist/kit/chunk-KO5NAI4S.js +1 -0
  17. package/dist/kit/chunk-LZGSWPH4.js +1 -0
  18. package/dist/kit/chunk-MZDZ6G75.js +1 -0
  19. package/dist/kit/{chunk-G3FVDS2A.js → chunk-O25QXHEZ.js} +1 -1
  20. package/dist/kit/chunk-ODLKGAX2.js +1 -0
  21. package/dist/kit/chunk-P5M6AQQX.js +1 -0
  22. package/dist/kit/{chunk-M5JJSIWI.js → chunk-QRSVLQ2I.js} +1 -1
  23. package/dist/kit/chunk-RPSE33GI.js +1 -0
  24. package/dist/kit/chunk-RU2KQTTL.js +1 -0
  25. package/dist/kit/{chunk-7QH33RJJ.js → chunk-UZR3T5XA.js} +1 -1
  26. package/dist/kit/{chunk-G7GQSPMC.js → chunk-V3J6KJQ2.js} +1 -1
  27. package/dist/kit/chunk-VWFC5XOB.js +1 -0
  28. package/dist/kit/chunk-VXPUEFYR.js +1 -0
  29. package/dist/kit/{chunk-EH4S6T7U.js → chunk-W3GINZLK.js} +1 -1
  30. package/dist/kit/{chunk-2UOPVMN3.js → chunk-WOKKM6CG.js} +1 -1
  31. package/dist/kit/{chunk-NS6HYTQZ.js → chunk-XB7XBYHA.js} +1 -1
  32. package/dist/kit/chunk-XJBVU5QP.js +1 -0
  33. package/dist/kit/{chunk-3H3DJI3M.js → chunk-YFW377RN.js} +1 -1
  34. package/dist/kit.cjs +1 -1
  35. package/dist/kit.d.cts +65 -1
  36. package/dist/kit.d.ts +65 -1
  37. package/dist/kit.js +1 -1
  38. package/package.json +1 -1
  39. package/skills/asciify-engine/SKILL.md +3 -3
  40. package/skills/asciify-engine/references/applying-asciify.md +1 -0
  41. package/skills/asciify-engine/references/components.md +26 -0
  42. package/skills/asciify-engine/references/kit.md +33 -0
  43. package/skills/asciify-engine/references/scenario-prompts.md +7 -0
  44. package/dist/kit/chunk-4G5LJNMB.js +0 -1
  45. package/dist/kit/chunk-5Q634WWI.js +0 -1
  46. package/dist/kit/chunk-7TXDNPL3.js +0 -1
  47. package/dist/kit/chunk-F4IO3HWD.js +0 -1
  48. package/dist/kit/chunk-GJANKSX6.js +0 -1
  49. package/dist/kit/chunk-LTRVMY3D.js +0 -1
  50. package/dist/kit/chunk-OOVUQEXT.js +0 -1
  51. package/dist/kit/chunk-UWX7VIXT.js +0 -1
  52. package/dist/kit/chunk-V6KL3IA7.js +0 -1
  53. package/dist/kit/chunk-X7AUCVMH.js +0 -1
  54. package/dist/kit/chunk-XXHIFJ5Z.js +0 -1
  55. package/dist/kit/chunk-XZO4VH2Z.js +0 -1
  56. package/dist/kit/chunk-ZNZAO7JA.js +0 -1
package/dist/kit.d.cts CHANGED
@@ -770,6 +770,61 @@ interface GlobeHandle extends KitHandle<GlobeOptions> {
770
770
  */
771
771
  declare function globe(element: HTMLElement, options?: GlobeOptions): GlobeHandle;
772
772
 
773
+ /** What swims. A `school` is one shoal of small fish that move together; its `count` is how many fish are in it. */
774
+ type OceanKind = 'fish' | 'shark' | 'hammerhead' | 'manta' | 'jellyfish' | 'school';
775
+ declare const OCEAN_KINDS: readonly OceanKind[];
776
+ interface OceanCreature {
777
+ kind: OceanKind;
778
+ /** Multiplies the kind's own length, which follows the element's shorter side. Default 1. */
779
+ size?: number;
780
+ /** How many: individuals, or for a `school` the fish in it. Default 1 (a school 28). Scaled by `density`. */
781
+ count?: number;
782
+ }
783
+ interface OceanOptions extends KitOptions {
784
+ /** What swims. Default a shark, a hammerhead, a manta, four fish, two jellyfish and a school of 28. */
785
+ creatures?: OceanCreature[];
786
+ /** Swimming pace, 0 holds everything; 1 is natural. Default 1. */
787
+ speed?: number;
788
+ /** Multiplies every count. Default 1. */
789
+ density?: number;
790
+ /** How far the depth layers go, 0 to 1: far creatures are smaller, fainter and slower. 0 puts everything on one plane. Default 0.7. */
791
+ depth?: number;
792
+ /** An ink per kind, as a CSS colour or theme token (`--brand`). Kinds without one use `ink`. Draws in source colour. */
793
+ palette?: Partial<Record<OceanKind, string>>;
794
+ /** `transparent` (default) or a CSS colour or token for the water behind the characters. */
795
+ background?: string;
796
+ /** The cursor scatters small fish and sharks turn to investigate it; a press sends a ripple. Default true. */
797
+ interactive?: boolean;
798
+ /** A press sends a ring through the field and scatters the fish near it. Default true; needs `interactive`. */
799
+ ripples?: boolean;
800
+ /** At the element's edges creatures turn back (`turn`, default) or swim out and come in on the other side (`wrap`). */
801
+ edges?: 'turn' | 'wrap';
802
+ /** The same seed always lays out and moves the same ocean. Default 1. */
803
+ seed?: number;
804
+ /** `under` (default) sits behind the element's content, as a background; `over` draws above it. */
805
+ layer?: 'under' | 'over';
806
+ /** Read to assistive technology. Without one the ocean is decoration. */
807
+ label?: string;
808
+ }
809
+ interface OceanHandle extends KitHandle<OceanOptions> {
810
+ /** Adds creatures of a kind (a whole school for `school`); returns how many were added. */
811
+ add(kind: OceanKind, options?: {
812
+ size?: number;
813
+ count?: number;
814
+ }): number;
815
+ /** Removes the most recently added creature of `kind` (or of any kind), a whole school at once. Returns whether one went. */
816
+ remove(kind?: OceanKind): boolean;
817
+ /** Creatures swimming now, every fish of a school counted. */
818
+ readonly count: number;
819
+ }
820
+ /**
821
+ * An ocean drawn as characters: fish, sharks, hammerheads, mantas, jellyfish and schools seen from above, each a procedural body
822
+ * that swims with a travelling wave, steers, wanders and schools, in depth layers that are smaller and fainter the deeper they
823
+ * swim. The cursor scatters small fish and sharks turn to investigate it; a press sends a ripple. It holds a still composition
824
+ * under reduced motion, and pauses off screen and in a hidden tab.
825
+ */
826
+ declare function ocean(element: HTMLElement, options?: OceanOptions): OceanHandle;
827
+
773
828
  /** A frame to morph through: an image URL or element, a canvas, a video, or a function that draws white-on-black each frame. */
774
829
  type MorphSource = string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ((pen: CanvasRenderingContext2D, w: number, h: number, now: number) => void);
775
830
  interface MorphFieldOptions extends KitOptions {
@@ -1329,6 +1384,15 @@ declare const cascade: BackgroundPreset;
1329
1384
  /** Points wander in their own cells, and neighbours close enough are linked by fine lines that come and go. */
1330
1385
  declare const constellation: BackgroundPreset;
1331
1386
 
1387
+ /** Thin branching veins: a faint network at rest, and new veins that grow toward the cursor and burst from a click. */
1388
+ declare const capillary: BackgroundPreset;
1389
+
1390
+ /** Soft blotches drifting on a slow current; the pointer stirs them into swirls that settle back. */
1391
+ declare const estuary: BackgroundPreset;
1392
+
1393
+ /** Rings of characters a click sends out across the field, a strong front and two echoes, over a faint grain. */
1394
+ declare const shockwave: BackgroundPreset;
1395
+
1332
1396
  /**
1333
1397
  * Curtains of light at three depths hang from the top in vertical rays, the nearest tallest and brightest, folding slowly.
1334
1398
  * @deprecated Retired from the curated set; kept so existing code still runs. `mesh` is the closest current preset.
@@ -1590,4 +1654,4 @@ declare function subscribeGlobalLook(listener: (look: GlobalLook | null) => void
1590
1654
  declare function setFieldBudget(n: number): void;
1591
1655
  declare const getFieldBudget: () => number;
1592
1656
 
1593
- export { type AccordionHandle, type AccordionImage, type AccordionOptions, type ArtPanelHandle, type ArtPanelOptions, type AsciiVideoHandle, type AsciiVideoOptions, BEAM_PALETTES, type BackgroundCharset, type BackgroundContext, type BackgroundCursor, type BackgroundHandle, type BackgroundMark, type BackgroundOptions, type BackgroundPreset, type BackgroundRun, type BackgroundSettings, type BeamHandle, type BeamMode, type BeamOptions, type BeamPalette, type BlockChartHandle, type BlockChartOptions, type Box, type ButtonLoadingHandle, type ButtonLoadingOptions, type ButtonState, type CodeInputHandle, type CodeInputOptions, type CodeState, type CommandPaletteHandle, type CommandPaletteOptions, type CompareHandle, type CompareOptions, type CursorTrailHandle, type CursorTrailOptions, type CursorTrailStyle, type DecodeHandle, type DecodeOptions, type DisintegrateOptions, type DitherGradientHandle, type DitherGradientOptions, type DitherImageHandle, type DitherImageOptions, type DitherLight, type DropState, type DroppedImage, type DropzoneHandle, type DropzoneOptions, type FieldBackgroundHandle, type FieldBackgroundOptions, type FieldPreset, type GenerateState, type GlobalLook, type GlobeHandle, type GlobeOptions, type GlobePoint, type ImageGenerateHandle, type ImageGenerateOptions, type ImageStream, type ImageUpdate, KIT_STYLES, type KitHandle, type KitOptions, type KitStyle, type LikeBurstHandle, type LikeBurstOptions, type LikeMark, type MorphFieldHandle, type MorphFieldOptions, type MorphSource, type OdometerHandle, type OdometerOptions, type OrbState, PILL_TONES, type PageDissolveHandle, type PageDissolveOptions, type PaintFrame, type PillHandle, type PillOptions, type PillTone, type PricingGlowHandle, type PricingGlowOptions, type PullRefreshHandle, type PullRefreshOptions, type PullState, SCRAMBLE_SCRIPTS, type SkeletonBlock, type SkeletonHandle, type SkeletonOptions, type SlideToConfirmHandle, type SlideToConfirmOptions, type StatusOrbHandle, type StatusOrbOptions, type StreamState, type StreamTextHandle, type StreamTextOptions, type Surface, type SurfaceConfig, type SwipeDeckHandle, type SwipeDeckOptions, type TabsHandle, type TabsOptions, type TemplateDraw, type TemplateFrame, type ThinkingHandle, type ThinkingOptions, type ThinkingState, type Toast, type ToastStackHandle, type ToastStackOptions, VOICE_PALETTES, type VoiceOrbHandle, type VoiceOrbOptions, type VoicePalette, type VoiceState, type WordmarkHandle, type WordmarkOptions, accordion, artPanel, asciiVideo, aurora, background, backgroundCharset, beam, beamPalette, blockChart, buttonLoading, cascade, caustics, circuit, codeInput, commandPalette, compare, constellation, contour, cursorTrail, decode, disintegrate, ditherGradient, ditherImage, dna, drift, dropzone, dune, etch, facet, fieldBackground, fire, fluid, getFieldBudget, getGlobalLook, globe, grid, halftone, halo, imageGenerate, interference, likeBurst, mesh, moire, morph, morphField, mountCanvas, mountSurface, noise, odometer, pageDissolve, pill, pricingGlow, pullRefresh, pulse, rain, resolveColor, ripple, setFieldBudget, setGlobalLook, silk, skeleton, slideToConfirm, stars, statusOrb, streamText, subscribeGlobalLook, swell, swipeDeck, tabs, terrain, thinking, toastStack, veil, voiceOrb, voidWell, wave, weave, wordField, wordmark };
1657
+ export { type AccordionHandle, type AccordionImage, type AccordionOptions, type ArtPanelHandle, type ArtPanelOptions, type AsciiVideoHandle, type AsciiVideoOptions, BEAM_PALETTES, type BackgroundCharset, type BackgroundContext, type BackgroundCursor, type BackgroundHandle, type BackgroundMark, type BackgroundOptions, type BackgroundPreset, type BackgroundRun, type BackgroundSettings, type BeamHandle, type BeamMode, type BeamOptions, type BeamPalette, type BlockChartHandle, type BlockChartOptions, type Box, type ButtonLoadingHandle, type ButtonLoadingOptions, type ButtonState, type CodeInputHandle, type CodeInputOptions, type CodeState, type CommandPaletteHandle, type CommandPaletteOptions, type CompareHandle, type CompareOptions, type CursorTrailHandle, type CursorTrailOptions, type CursorTrailStyle, type DecodeHandle, type DecodeOptions, type DisintegrateOptions, type DitherGradientHandle, type DitherGradientOptions, type DitherImageHandle, type DitherImageOptions, type DitherLight, type DropState, type DroppedImage, type DropzoneHandle, type DropzoneOptions, type FieldBackgroundHandle, type FieldBackgroundOptions, type FieldPreset, type GenerateState, type GlobalLook, type GlobeHandle, type GlobeOptions, type GlobePoint, type ImageGenerateHandle, type ImageGenerateOptions, type ImageStream, type ImageUpdate, KIT_STYLES, type KitHandle, type KitOptions, type KitStyle, type LikeBurstHandle, type LikeBurstOptions, type LikeMark, type MorphFieldHandle, type MorphFieldOptions, type MorphSource, OCEAN_KINDS, type OceanCreature, type OceanHandle, type OceanKind, type OceanOptions, type OdometerHandle, type OdometerOptions, type OrbState, PILL_TONES, type PageDissolveHandle, type PageDissolveOptions, type PaintFrame, type PillHandle, type PillOptions, type PillTone, type PricingGlowHandle, type PricingGlowOptions, type PullRefreshHandle, type PullRefreshOptions, type PullState, SCRAMBLE_SCRIPTS, type SkeletonBlock, type SkeletonHandle, type SkeletonOptions, type SlideToConfirmHandle, type SlideToConfirmOptions, type StatusOrbHandle, type StatusOrbOptions, type StreamState, type StreamTextHandle, type StreamTextOptions, type Surface, type SurfaceConfig, type SwipeDeckHandle, type SwipeDeckOptions, type TabsHandle, type TabsOptions, type TemplateDraw, type TemplateFrame, type ThinkingHandle, type ThinkingOptions, type ThinkingState, type Toast, type ToastStackHandle, type ToastStackOptions, VOICE_PALETTES, type VoiceOrbHandle, type VoiceOrbOptions, type VoicePalette, type VoiceState, type WordmarkHandle, type WordmarkOptions, accordion, artPanel, asciiVideo, aurora, background, backgroundCharset, beam, beamPalette, blockChart, buttonLoading, capillary, cascade, caustics, circuit, codeInput, commandPalette, compare, constellation, contour, cursorTrail, decode, disintegrate, ditherGradient, ditherImage, dna, drift, dropzone, dune, estuary, etch, facet, fieldBackground, fire, fluid, getFieldBudget, getGlobalLook, globe, grid, halftone, halo, imageGenerate, interference, likeBurst, mesh, moire, morph, morphField, mountCanvas, mountSurface, noise, ocean, odometer, pageDissolve, pill, pricingGlow, pullRefresh, pulse, rain, resolveColor, ripple, setFieldBudget, setGlobalLook, shockwave, silk, skeleton, slideToConfirm, stars, statusOrb, streamText, subscribeGlobalLook, swell, swipeDeck, tabs, terrain, thinking, toastStack, veil, voiceOrb, voidWell, wave, weave, wordField, wordmark };
package/dist/kit.d.ts CHANGED
@@ -770,6 +770,61 @@ interface GlobeHandle extends KitHandle<GlobeOptions> {
770
770
  */
771
771
  declare function globe(element: HTMLElement, options?: GlobeOptions): GlobeHandle;
772
772
 
773
+ /** What swims. A `school` is one shoal of small fish that move together; its `count` is how many fish are in it. */
774
+ type OceanKind = 'fish' | 'shark' | 'hammerhead' | 'manta' | 'jellyfish' | 'school';
775
+ declare const OCEAN_KINDS: readonly OceanKind[];
776
+ interface OceanCreature {
777
+ kind: OceanKind;
778
+ /** Multiplies the kind's own length, which follows the element's shorter side. Default 1. */
779
+ size?: number;
780
+ /** How many: individuals, or for a `school` the fish in it. Default 1 (a school 28). Scaled by `density`. */
781
+ count?: number;
782
+ }
783
+ interface OceanOptions extends KitOptions {
784
+ /** What swims. Default a shark, a hammerhead, a manta, four fish, two jellyfish and a school of 28. */
785
+ creatures?: OceanCreature[];
786
+ /** Swimming pace, 0 holds everything; 1 is natural. Default 1. */
787
+ speed?: number;
788
+ /** Multiplies every count. Default 1. */
789
+ density?: number;
790
+ /** How far the depth layers go, 0 to 1: far creatures are smaller, fainter and slower. 0 puts everything on one plane. Default 0.7. */
791
+ depth?: number;
792
+ /** An ink per kind, as a CSS colour or theme token (`--brand`). Kinds without one use `ink`. Draws in source colour. */
793
+ palette?: Partial<Record<OceanKind, string>>;
794
+ /** `transparent` (default) or a CSS colour or token for the water behind the characters. */
795
+ background?: string;
796
+ /** The cursor scatters small fish and sharks turn to investigate it; a press sends a ripple. Default true. */
797
+ interactive?: boolean;
798
+ /** A press sends a ring through the field and scatters the fish near it. Default true; needs `interactive`. */
799
+ ripples?: boolean;
800
+ /** At the element's edges creatures turn back (`turn`, default) or swim out and come in on the other side (`wrap`). */
801
+ edges?: 'turn' | 'wrap';
802
+ /** The same seed always lays out and moves the same ocean. Default 1. */
803
+ seed?: number;
804
+ /** `under` (default) sits behind the element's content, as a background; `over` draws above it. */
805
+ layer?: 'under' | 'over';
806
+ /** Read to assistive technology. Without one the ocean is decoration. */
807
+ label?: string;
808
+ }
809
+ interface OceanHandle extends KitHandle<OceanOptions> {
810
+ /** Adds creatures of a kind (a whole school for `school`); returns how many were added. */
811
+ add(kind: OceanKind, options?: {
812
+ size?: number;
813
+ count?: number;
814
+ }): number;
815
+ /** Removes the most recently added creature of `kind` (or of any kind), a whole school at once. Returns whether one went. */
816
+ remove(kind?: OceanKind): boolean;
817
+ /** Creatures swimming now, every fish of a school counted. */
818
+ readonly count: number;
819
+ }
820
+ /**
821
+ * An ocean drawn as characters: fish, sharks, hammerheads, mantas, jellyfish and schools seen from above, each a procedural body
822
+ * that swims with a travelling wave, steers, wanders and schools, in depth layers that are smaller and fainter the deeper they
823
+ * swim. The cursor scatters small fish and sharks turn to investigate it; a press sends a ripple. It holds a still composition
824
+ * under reduced motion, and pauses off screen and in a hidden tab.
825
+ */
826
+ declare function ocean(element: HTMLElement, options?: OceanOptions): OceanHandle;
827
+
773
828
  /** A frame to morph through: an image URL or element, a canvas, a video, or a function that draws white-on-black each frame. */
774
829
  type MorphSource = string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | ((pen: CanvasRenderingContext2D, w: number, h: number, now: number) => void);
775
830
  interface MorphFieldOptions extends KitOptions {
@@ -1329,6 +1384,15 @@ declare const cascade: BackgroundPreset;
1329
1384
  /** Points wander in their own cells, and neighbours close enough are linked by fine lines that come and go. */
1330
1385
  declare const constellation: BackgroundPreset;
1331
1386
 
1387
+ /** Thin branching veins: a faint network at rest, and new veins that grow toward the cursor and burst from a click. */
1388
+ declare const capillary: BackgroundPreset;
1389
+
1390
+ /** Soft blotches drifting on a slow current; the pointer stirs them into swirls that settle back. */
1391
+ declare const estuary: BackgroundPreset;
1392
+
1393
+ /** Rings of characters a click sends out across the field, a strong front and two echoes, over a faint grain. */
1394
+ declare const shockwave: BackgroundPreset;
1395
+
1332
1396
  /**
1333
1397
  * Curtains of light at three depths hang from the top in vertical rays, the nearest tallest and brightest, folding slowly.
1334
1398
  * @deprecated Retired from the curated set; kept so existing code still runs. `mesh` is the closest current preset.
@@ -1590,4 +1654,4 @@ declare function subscribeGlobalLook(listener: (look: GlobalLook | null) => void
1590
1654
  declare function setFieldBudget(n: number): void;
1591
1655
  declare const getFieldBudget: () => number;
1592
1656
 
1593
- export { type AccordionHandle, type AccordionImage, type AccordionOptions, type ArtPanelHandle, type ArtPanelOptions, type AsciiVideoHandle, type AsciiVideoOptions, BEAM_PALETTES, type BackgroundCharset, type BackgroundContext, type BackgroundCursor, type BackgroundHandle, type BackgroundMark, type BackgroundOptions, type BackgroundPreset, type BackgroundRun, type BackgroundSettings, type BeamHandle, type BeamMode, type BeamOptions, type BeamPalette, type BlockChartHandle, type BlockChartOptions, type Box, type ButtonLoadingHandle, type ButtonLoadingOptions, type ButtonState, type CodeInputHandle, type CodeInputOptions, type CodeState, type CommandPaletteHandle, type CommandPaletteOptions, type CompareHandle, type CompareOptions, type CursorTrailHandle, type CursorTrailOptions, type CursorTrailStyle, type DecodeHandle, type DecodeOptions, type DisintegrateOptions, type DitherGradientHandle, type DitherGradientOptions, type DitherImageHandle, type DitherImageOptions, type DitherLight, type DropState, type DroppedImage, type DropzoneHandle, type DropzoneOptions, type FieldBackgroundHandle, type FieldBackgroundOptions, type FieldPreset, type GenerateState, type GlobalLook, type GlobeHandle, type GlobeOptions, type GlobePoint, type ImageGenerateHandle, type ImageGenerateOptions, type ImageStream, type ImageUpdate, KIT_STYLES, type KitHandle, type KitOptions, type KitStyle, type LikeBurstHandle, type LikeBurstOptions, type LikeMark, type MorphFieldHandle, type MorphFieldOptions, type MorphSource, type OdometerHandle, type OdometerOptions, type OrbState, PILL_TONES, type PageDissolveHandle, type PageDissolveOptions, type PaintFrame, type PillHandle, type PillOptions, type PillTone, type PricingGlowHandle, type PricingGlowOptions, type PullRefreshHandle, type PullRefreshOptions, type PullState, SCRAMBLE_SCRIPTS, type SkeletonBlock, type SkeletonHandle, type SkeletonOptions, type SlideToConfirmHandle, type SlideToConfirmOptions, type StatusOrbHandle, type StatusOrbOptions, type StreamState, type StreamTextHandle, type StreamTextOptions, type Surface, type SurfaceConfig, type SwipeDeckHandle, type SwipeDeckOptions, type TabsHandle, type TabsOptions, type TemplateDraw, type TemplateFrame, type ThinkingHandle, type ThinkingOptions, type ThinkingState, type Toast, type ToastStackHandle, type ToastStackOptions, VOICE_PALETTES, type VoiceOrbHandle, type VoiceOrbOptions, type VoicePalette, type VoiceState, type WordmarkHandle, type WordmarkOptions, accordion, artPanel, asciiVideo, aurora, background, backgroundCharset, beam, beamPalette, blockChart, buttonLoading, cascade, caustics, circuit, codeInput, commandPalette, compare, constellation, contour, cursorTrail, decode, disintegrate, ditherGradient, ditherImage, dna, drift, dropzone, dune, etch, facet, fieldBackground, fire, fluid, getFieldBudget, getGlobalLook, globe, grid, halftone, halo, imageGenerate, interference, likeBurst, mesh, moire, morph, morphField, mountCanvas, mountSurface, noise, odometer, pageDissolve, pill, pricingGlow, pullRefresh, pulse, rain, resolveColor, ripple, setFieldBudget, setGlobalLook, silk, skeleton, slideToConfirm, stars, statusOrb, streamText, subscribeGlobalLook, swell, swipeDeck, tabs, terrain, thinking, toastStack, veil, voiceOrb, voidWell, wave, weave, wordField, wordmark };
1657
+ export { type AccordionHandle, type AccordionImage, type AccordionOptions, type ArtPanelHandle, type ArtPanelOptions, type AsciiVideoHandle, type AsciiVideoOptions, BEAM_PALETTES, type BackgroundCharset, type BackgroundContext, type BackgroundCursor, type BackgroundHandle, type BackgroundMark, type BackgroundOptions, type BackgroundPreset, type BackgroundRun, type BackgroundSettings, type BeamHandle, type BeamMode, type BeamOptions, type BeamPalette, type BlockChartHandle, type BlockChartOptions, type Box, type ButtonLoadingHandle, type ButtonLoadingOptions, type ButtonState, type CodeInputHandle, type CodeInputOptions, type CodeState, type CommandPaletteHandle, type CommandPaletteOptions, type CompareHandle, type CompareOptions, type CursorTrailHandle, type CursorTrailOptions, type CursorTrailStyle, type DecodeHandle, type DecodeOptions, type DisintegrateOptions, type DitherGradientHandle, type DitherGradientOptions, type DitherImageHandle, type DitherImageOptions, type DitherLight, type DropState, type DroppedImage, type DropzoneHandle, type DropzoneOptions, type FieldBackgroundHandle, type FieldBackgroundOptions, type FieldPreset, type GenerateState, type GlobalLook, type GlobeHandle, type GlobeOptions, type GlobePoint, type ImageGenerateHandle, type ImageGenerateOptions, type ImageStream, type ImageUpdate, KIT_STYLES, type KitHandle, type KitOptions, type KitStyle, type LikeBurstHandle, type LikeBurstOptions, type LikeMark, type MorphFieldHandle, type MorphFieldOptions, type MorphSource, OCEAN_KINDS, type OceanCreature, type OceanHandle, type OceanKind, type OceanOptions, type OdometerHandle, type OdometerOptions, type OrbState, PILL_TONES, type PageDissolveHandle, type PageDissolveOptions, type PaintFrame, type PillHandle, type PillOptions, type PillTone, type PricingGlowHandle, type PricingGlowOptions, type PullRefreshHandle, type PullRefreshOptions, type PullState, SCRAMBLE_SCRIPTS, type SkeletonBlock, type SkeletonHandle, type SkeletonOptions, type SlideToConfirmHandle, type SlideToConfirmOptions, type StatusOrbHandle, type StatusOrbOptions, type StreamState, type StreamTextHandle, type StreamTextOptions, type Surface, type SurfaceConfig, type SwipeDeckHandle, type SwipeDeckOptions, type TabsHandle, type TabsOptions, type TemplateDraw, type TemplateFrame, type ThinkingHandle, type ThinkingOptions, type ThinkingState, type Toast, type ToastStackHandle, type ToastStackOptions, VOICE_PALETTES, type VoiceOrbHandle, type VoiceOrbOptions, type VoicePalette, type VoiceState, type WordmarkHandle, type WordmarkOptions, accordion, artPanel, asciiVideo, aurora, background, backgroundCharset, beam, beamPalette, blockChart, buttonLoading, capillary, cascade, caustics, circuit, codeInput, commandPalette, compare, constellation, contour, cursorTrail, decode, disintegrate, ditherGradient, ditherImage, dna, drift, dropzone, dune, estuary, etch, facet, fieldBackground, fire, fluid, getFieldBudget, getGlobalLook, globe, grid, halftone, halo, imageGenerate, interference, likeBurst, mesh, moire, morph, morphField, mountCanvas, mountSurface, noise, ocean, odometer, pageDissolve, pill, pricingGlow, pullRefresh, pulse, rain, resolveColor, ripple, setFieldBudget, setGlobalLook, shockwave, silk, skeleton, slideToConfirm, stars, statusOrb, streamText, subscribeGlobalLook, swell, swipeDeck, tabs, terrain, thinking, toastStack, veil, voiceOrb, voidWell, wave, weave, wordField, wordmark };
package/dist/kit.js CHANGED
@@ -1 +1 @@
1
- export{silk}from"./kit/chunk-XZO4VH2Z.js";export{stars}from"./kit/chunk-XXHIFJ5Z.js";export{terrain}from"./kit/chunk-UWX7VIXT.js";export{veil}from"./kit/chunk-R3ALZFUQ.js";export{voidWell}from"./kit/chunk-4G5LJNMB.js";export{wave}from"./kit/chunk-F4IO3HWD.js";export{weave}from"./kit/chunk-P5MVACML.js";export{facet}from"./kit/chunk-UXDJSGED.js";export{fire}from"./kit/chunk-NS6HYTQZ.js";export{grid}from"./kit/chunk-OOVUQEXT.js";export{moire}from"./kit/chunk-XDX6WLED.js";export{morph}from"./kit/chunk-5Q634WWI.js";export{noise}from"./kit/chunk-V6KL3IA7.js";export{pulse}from"./kit/chunk-GJANKSX6.js";export{rain}from"./kit/chunk-7TXDNPL3.js";export{cascade}from"./kit/chunk-G3FVDS2A.js";export{constellation}from"./kit/chunk-6NDTKY3V.js";export{aurora}from"./kit/chunk-G7GQSPMC.js";export{halftone}from"./kit/chunk-3H3DJI3M.js";export{circuit}from"./kit/chunk-ZNZAO7JA.js";export{dna}from"./kit/chunk-X7AUCVMH.js";export{dune}from"./kit/chunk-NQ4PFWOG.js";export{etch}from"./kit/chunk-ZGCKUXYP.js";import"./kit/chunk-XPXMCXYI.js";import"./kit/chunk-ZCHGV2CV.js";export{mountCanvas}from"./kit/chunk-AAV5QNHU.js";export{wordField}from"./kit/chunk-EH4S6T7U.js";export{fluid}from"./kit/chunk-UT6MJP5B.js";export{caustics}from"./kit/chunk-2UOPVMN3.js";export{contour}from"./kit/chunk-MYAZOXMF.js";export{ripple}from"./kit/chunk-UXJRBOSR.js";export{halo}from"./kit/chunk-Y2SDQ6EC.js";export{interference}from"./kit/chunk-M5JJSIWI.js";export{mesh}from"./kit/chunk-VENDLTH4.js";export{compare}from"./kit/chunk-NP7UG7DS.js";export{accordion}from"./kit/chunk-4NR7QENR.js";export{dropzone}from"./kit/chunk-TJHSBZBF.js";export{disintegrate}from"./kit/chunk-N7J4UAWY.js";export{pullRefresh}from"./kit/chunk-CZL5WMU6.js";export{background,backgroundCharset}from"./kit/chunk-X6GAMLEH.js";export{swell}from"./kit/chunk-64NSPD2R.js";export{drift}from"./kit/chunk-7QH33RJJ.js";import"./kit/chunk-LTRVMY3D.js";export{morphField}from"./kit/chunk-AU33Y2SZ.js";export{ditherGradient}from"./kit/chunk-BV6AOHFU.js";export{ditherImage}from"./kit/chunk-GI5BNKBL.js";export{swipeDeck}from"./kit/chunk-UHLNVM63.js";export{codeInput}from"./kit/chunk-E427W6P5.js";export{toastStack}from"./kit/chunk-WPWCFCEZ.js";export{thinking}from"./kit/chunk-VQ4KIRBW.js";export{streamText}from"./kit/chunk-2NACMWVV.js";export{VOICE_PALETTES,voiceOrb}from"./kit/chunk-JF3WEYIE.js";export{commandPalette}from"./kit/chunk-PZKQUZQK.js";import"./kit/chunk-DKRZSP5K.js";export{slideToConfirm}from"./kit/chunk-FU4WW3PU.js";export{likeBurst}from"./kit/chunk-MWUPCAET.js";export{blockChart}from"./kit/chunk-NSKX2OFA.js";export{pageDissolve}from"./kit/chunk-CMGMCRAD.js";import"./kit/chunk-HENGH3DE.js";export{cursorTrail}from"./kit/chunk-BQ53B2HP.js";export{globe}from"./kit/chunk-SBAUVRBY.js";export{tabs}from"./kit/chunk-V42Q4L2G.js";export{imageGenerate}from"./kit/chunk-BJJUDT26.js";export{fieldBackground}from"./kit/chunk-MT23DCGU.js";export{wordmark}from"./kit/chunk-SQNULNT3.js";export{asciiVideo}from"./kit/chunk-BO4CPM26.js";export{artPanel}from"./kit/chunk-ZTCSVEHT.js";export{pricingGlow}from"./kit/chunk-XVA7UGUQ.js";import"./kit/chunk-RGV7VRYC.js";export{BEAM_PALETTES,beam,beamPalette}from"./kit/chunk-WSWIOD2C.js";export{SCRAMBLE_SCRIPTS,decode}from"./kit/chunk-IFZDWKIX.js";export{odometer}from"./kit/chunk-6G2ZVIBS.js";export{buttonLoading}from"./kit/chunk-CH64MY3U.js";export{statusOrb}from"./kit/chunk-BGPEFFKK.js";export{skeleton}from"./kit/chunk-WRBLIULG.js";export{PILL_TONES,pill}from"./kit/chunk-J7Y2KBXK.js";export{mountSurface,resolveColor}from"./kit/chunk-I377LEZA.js";export{KIT_STYLES,getFieldBudget,getGlobalLook,setFieldBudget,setGlobalLook,subscribeGlobalLook}from"./kit/chunk-FEAFQY7O.js";//# sourceMappingURL=kit.js.map
1
+ export{voidWell}from"./kit/chunk-MZDZ6G75.js";export{wave}from"./kit/chunk-KO5NAI4S.js";export{weave}from"./kit/chunk-P5MVACML.js";export{morph}from"./kit/chunk-6YLMG37G.js";export{noise}from"./kit/chunk-7NS6YAD3.js";export{pulse}from"./kit/chunk-XJBVU5QP.js";export{rain}from"./kit/chunk-RPSE33GI.js";export{silk}from"./kit/chunk-6646EUJY.js";export{stars}from"./kit/chunk-DANNL7WR.js";export{terrain}from"./kit/chunk-RU2KQTTL.js";export{veil}from"./kit/chunk-R3ALZFUQ.js";export{circuit}from"./kit/chunk-26HU7QJW.js";export{dna}from"./kit/chunk-P5M6AQQX.js";export{dune}from"./kit/chunk-NQ4PFWOG.js";export{etch}from"./kit/chunk-ZGCKUXYP.js";export{facet}from"./kit/chunk-UXDJSGED.js";export{fire}from"./kit/chunk-XB7XBYHA.js";export{grid}from"./kit/chunk-VXPUEFYR.js";export{moire}from"./kit/chunk-XDX6WLED.js";import"./kit/chunk-XPXMCXYI.js";export{mountCanvas}from"./kit/chunk-AAV5QNHU.js";export{mesh}from"./kit/chunk-ECGALF3G.js";export{cascade}from"./kit/chunk-O25QXHEZ.js";export{constellation}from"./kit/chunk-J7TFGVZT.js";export{capillary}from"./kit/chunk-7OPCQDAL.js";export{estuary}from"./kit/chunk-LZGSWPH4.js";export{shockwave}from"./kit/chunk-2ZBPTNGK.js";import"./kit/chunk-ZCHGV2CV.js";import"./kit/chunk-ODLKGAX2.js";export{aurora}from"./kit/chunk-V3J6KJQ2.js";export{halftone}from"./kit/chunk-YFW377RN.js";export{drift}from"./kit/chunk-UZR3T5XA.js";export{wordField}from"./kit/chunk-W3GINZLK.js";export{fluid}from"./kit/chunk-UT6MJP5B.js";export{caustics}from"./kit/chunk-WOKKM6CG.js";export{contour}from"./kit/chunk-7DBDSJ5R.js";export{ripple}from"./kit/chunk-JSRXW3FL.js";export{halo}from"./kit/chunk-CIGEXHZ5.js";export{interference}from"./kit/chunk-QRSVLQ2I.js";export{streamText}from"./kit/chunk-2NACMWVV.js";export{compare}from"./kit/chunk-NP7UG7DS.js";export{accordion}from"./kit/chunk-4NR7QENR.js";export{dropzone}from"./kit/chunk-TJHSBZBF.js";export{disintegrate}from"./kit/chunk-N7J4UAWY.js";export{pullRefresh}from"./kit/chunk-CZL5WMU6.js";export{background,backgroundCharset}from"./kit/chunk-X6GAMLEH.js";export{swell}from"./kit/chunk-62KEKWSM.js";import"./kit/chunk-VWFC5XOB.js";export{OCEAN_KINDS,ocean}from"./kit/chunk-EOTPXDMH.js";export{morphField}from"./kit/chunk-AU33Y2SZ.js";export{ditherGradient}from"./kit/chunk-BV6AOHFU.js";export{ditherImage}from"./kit/chunk-GI5BNKBL.js";export{swipeDeck}from"./kit/chunk-UHLNVM63.js";export{codeInput}from"./kit/chunk-E427W6P5.js";export{toastStack}from"./kit/chunk-WPWCFCEZ.js";export{thinking}from"./kit/chunk-VQ4KIRBW.js";export{VOICE_PALETTES,voiceOrb}from"./kit/chunk-JF3WEYIE.js";export{commandPalette}from"./kit/chunk-PZKQUZQK.js";import"./kit/chunk-DKRZSP5K.js";export{slideToConfirm}from"./kit/chunk-FU4WW3PU.js";export{likeBurst}from"./kit/chunk-MWUPCAET.js";export{blockChart}from"./kit/chunk-NSKX2OFA.js";export{pageDissolve}from"./kit/chunk-CMGMCRAD.js";import"./kit/chunk-HENGH3DE.js";export{cursorTrail}from"./kit/chunk-BQ53B2HP.js";export{globe}from"./kit/chunk-SBAUVRBY.js";export{tabs}from"./kit/chunk-V42Q4L2G.js";export{imageGenerate}from"./kit/chunk-BJJUDT26.js";export{fieldBackground}from"./kit/chunk-MT23DCGU.js";export{wordmark}from"./kit/chunk-SQNULNT3.js";export{asciiVideo}from"./kit/chunk-BO4CPM26.js";export{artPanel}from"./kit/chunk-ZTCSVEHT.js";export{pricingGlow}from"./kit/chunk-XVA7UGUQ.js";import"./kit/chunk-RGV7VRYC.js";export{BEAM_PALETTES,beam,beamPalette}from"./kit/chunk-WSWIOD2C.js";export{SCRAMBLE_SCRIPTS,decode}from"./kit/chunk-IFZDWKIX.js";export{odometer}from"./kit/chunk-6G2ZVIBS.js";export{buttonLoading}from"./kit/chunk-CH64MY3U.js";export{statusOrb}from"./kit/chunk-BGPEFFKK.js";export{skeleton}from"./kit/chunk-WRBLIULG.js";export{PILL_TONES,pill}from"./kit/chunk-J7Y2KBXK.js";export{mountSurface,resolveColor}from"./kit/chunk-I377LEZA.js";export{KIT_STYLES,getFieldBudget,getGlobalLook,setFieldBudget,setGlobalLook,subscribeGlobalLook}from"./kit/chunk-FEAFQY7O.js";//# sourceMappingURL=kit.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asciify-engine",
3
- "version": "4.30.0",
3
+ "version": "4.31.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.30.0"
5
+ tested-engine: "4.31.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.30.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.31.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
@@ -35,7 +35,7 @@ Most requests are a feeling ("make the loading state feel alive", "a calm backgr
35
35
 
36
36
  | The user wants | Use |
37
37
  | --- | --- |
38
- | A UI component in characters: button loading, status, toasts, tabs, pills, odometer, chart, AI thinking and streaming, transitions, sign-in, pricing, 404; event-site pieces (scrambling headers and headlines, morphing hatched heroes, dithered glows, a dotted globe, two-tone photos, assembling wordmarks, a spray cursor) | `asciify-engine/kit` ([applying-asciify.md](references/applying-asciify.md), [components.md](references/components.md), [kit.md](references/kit.md)) |
38
+ | A UI component in characters: button loading, status, toasts, tabs, pills, odometer, chart, AI thinking and streaming, transitions, sign-in, pricing, 404; event-site pieces (scrambling headers and headlines, morphing hatched heroes, dithered glows, a dotted globe, two-tone photos, assembling wordmarks, a spray cursor); an ASCII ocean of swimming creatures; interactive backgrounds visitors stir, grow and ripple | `asciify-engine/kit` ([applying-asciify.md](references/applying-asciify.md), [components.md](references/components.md), [kit.md](references/kit.md)) |
39
39
  | A background behind a hero, pricing, docs or a section, light or dark | Kit `fieldBackground(el, { preset: 'hero', clear })` (asciify.org's hero) or `background(el, { preset, clear })` with one of the 12 curated presets below |
40
40
  | Their word or brand in characters | Kit `wordmark`, or `background()` with `wordField` |
41
41
  | Their video in characters on the page | Kit `asciiVideo` |
@@ -18,6 +18,7 @@ Pick by what the field does for the person, not by how it looks.
18
18
  | Follow the pointer across the page | `cursorTrail` (one per page, off on touch and under reduced motion) |
19
19
  | Carry a brand moment or media | `decode` (and its `scramble`), `wordmark` (and its `assemble`), `morphField`, `ditherImage`, `asciiVideo`, `artPanel`, `pricingGlow`, `fieldBackground` `notFound` |
20
20
  | Show where: places, reach, a network | `globe` with `points` |
21
+ | A playful, living hero ground | `ocean` (fish, sharks, mantas, jellyfish and schools that answer the cursor), or `background()` with `estuary`, `capillary` or `shockwave` for a ground visitors stir, grow and ripple |
21
22
  | Set the page's one ground | `fieldBackground` `hero`, `ditherGradient`, or `background()` with a preset (section 9) |
22
23
 
23
24
  Do not use characters:
@@ -506,6 +506,32 @@ const title = decode(heroTitle, { scramble: true, settle: 'text' });
506
506
  nextButton.onclick = () => hero.next();
507
507
  ```
508
508
 
509
+ ## stir-grow-ripple: Interactive hero background
510
+ Category: Backgrounds
511
+
512
+ Prompt:
513
+ “Put an interactive ASCII background behind [our dark hero] with Asciify that visitors can stir, grow and ripple, with a small pill switcher: Estuary (soft blotches the cursor stirs), Capillary (thin veins that grow toward the cursor and burst from a click) and Shockwave (a click sends rings of characters outward). Faint by default so the headline reads, in our text token's ink, still under reduced motion.”
514
+
515
+ ```ts
516
+ import { background, capillary, estuary, shockwave } from 'asciify-engine/kit';
517
+
518
+ const modes = { estuary, capillary, shockwave };
519
+ const bg = background(hero, { preset: estuary, clear: headline });
520
+ pills.forEach(pill => (pill.onclick = () => bg.setPreset(modes[pill.dataset.mode])));
521
+ ```
522
+
523
+ ## ascii-ocean: Ocean
524
+ Category: Backgrounds
525
+
526
+ Prompt:
527
+ “Put an ASCII ocean behind [our landing hero] with Asciify: [a shark, a hammerhead and a school of small fish, plus a jellyfish or two] seen from above, swimming with real tail beats, the school keeping together, far ones smaller and fainter. The cursor scatters the fish and the sharks turn to investigate; a click sends a ripple. Inked from our text token, behind the headline, still under reduced motion.”
528
+
529
+ ```ts
530
+ import { ocean } from 'asciify-engine/kit';
531
+
532
+ ocean(hero, { creatures: [{ kind: 'shark' }, { kind: 'hammerhead' }, { kind: 'school', count: 32 }, { kind: 'jellyfish', count: 2 }], label: 'Sharks and fish swimming' });
533
+ ```
534
+
509
535
  ## ascii-globe: Globe of dots
510
536
  Category: Media
511
537
 
@@ -617,6 +617,24 @@ wordmark(footerMark, { text: 'connect', assemble: 'scroll', look: { hover: 'none
617
617
 
618
618
  Keep each piece to one job: the hero's morph is the key visual, the spray is ambient, the globe and glow are sections. Mount the cursor once per page, keep every headline and link real HTML, and give each piece a `poster` where it is above the fold.
619
619
 
620
+ ## Ocean
621
+
622
+ ### ocean
623
+
624
+ An ocean seen from above, drawn as characters: fish, sharks, hammerheads, manta rays, jellyfish and schools of small fish. Each creature is a procedural body (a spine with a width profile, fins and a tail) that swims with a travelling wave from snout to tail, steers, wanders and, in a school, keeps together. Depth layers make the far ones smaller, fainter and slower. The cursor scatters small fish and sharks turn to investigate it and circle; a press sends a ring through the field and scatters the fish near it. By default it sits behind the element's content, as a background.
625
+
626
+ ```ts
627
+ import { ocean } from 'asciify-engine/kit';
628
+
629
+ const sea = ocean(hero, {
630
+ creatures: [{ kind: 'shark' }, { kind: 'hammerhead', size: 0.9 }, { kind: 'school', count: 32 }, { kind: 'jellyfish', count: 2 }],
631
+ ink: '--ascii-ink', label: 'Sharks and a school of fish swimming',
632
+ });
633
+ addButton.onclick = () => sea.add('manta');
634
+ ```
635
+
636
+ Options: `creatures` (`{ kind, size?, count? }[]`, kinds `fish`, `shark`, `hammerhead`, `manta`, `jellyfish`, `school`; a school's `count` is its fish, default 28; size multiplies the kind's length, which follows the element's shorter side; default a shark, a hammerhead, a manta, four fish, two jellyfish and a school), `speed` (default 1; 0 holds and idles), `density` (multiplies every count), `depth` (0–1, default 0.7; 0 one plane), `palette` (an ink per kind, colours or tokens, drawn in source colour; kinds without one use `ink`), `background` (`'transparent'` default, or a colour or token for the water), `interactive` (default true), `ripples` (default true), `edges` (`'turn'` default, or `'wrap'`), `seed` (default 1; the same seed always gives the same ocean), `layer` (`'under'` default, `'over'`), `label`. Methods: `add(kind, { size?, count? })` returns how many were added, `remove(kind?)` removes the latest (a whole school at once), getter `count`. Default look: glyphs `' .:-=+*#%@'` at `cellSize: 7`; every mark works (`look: { mark: 'dither' }`, `'dot'`, `'pixel'`, `'engraving'`, …) and every charset (`look: { charset: ' ⠁⠃⠇⡇⣇⣧⣷⣿' }` for braille). Under reduced motion it draws a still composition (the creatures where a moment of swimming left them); it pauses off screen and in a hidden tab. Keep headlines over the quieter middle, or lower `density`.
637
+
620
638
  ## Backgrounds
621
639
 
622
640
  The curated backgrounds on asciify.org/backgrounds as one call each. They are scenes of the GPU glyph field, so they follow `setGlobalLook` (the header's characters and the 24 render styles) like every field component, keep a quiet zone for your copy, take `lazy`, `poster`, `globalLook` and the context budget, and hold one still frame under reduced motion. The canvas sits under the element's content (`isolation: isolate`, `z-index: -1`), follows the theme and pauses off screen and in hidden tabs.
@@ -652,6 +670,21 @@ Options: `preset` (required), `palette` (one ink or `{ light, dark }`, winning o
652
670
  | `cascade` | Streaks falling in three depths: far ones faint and slow, near ones bright and quick | 11, 1, lantern |
653
671
  | `wordField` | Your word (`text`) as a flowing field of letters | 13, 1, trail |
654
672
  | `fluid` | The original Asciify hero: flowing folds with a wake behind the cursor | 7, 1, wake |
673
+ | `estuary` | Soft blotches drifting on a slow current; the cursor stirs them into swirls that settle back, a click stirs harder | 9, 1, stir |
674
+ | `capillary` | Thin branching veins: a faint resting network, new veins sprouting toward the cursor and bursting from a click, fading as they age | 8, 1, grow |
675
+ | `shockwave` | A faint grain; a click sends rings of characters outward (a front and two echoes, slowing and fading), and the moving cursor leaves small gusts | 9, 1, rings |
676
+
677
+ ### Interactive simulations: estuary, capillary, shockwave
678
+
679
+ Three presets are simulations the visitor plays with rather than scenes: each runs on a coarse grid on the CPU and draws into the field's source, so every mark and charset works (`look: { mark: 'dither' }`, `charset: 'braille'`), the ink follows the theme, and the defaults are faint enough for a headline on top. They answer the cursor and clicks (`cursor: false` turns both off), hold one still frame under reduced motion, pause off screen, and stop drawing once nothing moves: `capillary` and `shockwave` rest until the pointer wakes them, `estuary` drifts at any `speed` above 0 and with `speed: 0` waits to be stirred. None keeps a quiet middle by default; pass `clear: headline` for one.
680
+
681
+ ```ts
682
+ import { background, capillary, estuary, shockwave } from 'asciify-engine/kit';
683
+
684
+ const modes = { estuary, capillary, shockwave };
685
+ const bg = background(hero, { preset: estuary, clear: headline });
686
+ pills.forEach(pill => (pill.onclick = () => bg.setPreset(modes[pill.dataset.mode as keyof typeof modes])));
687
+ ```
655
688
 
656
689
  Retired presets are still exported, marked `@deprecated`, so code that imports them keeps running unchanged; they are no longer shown on the site or in these docs. Move to the closest current one: `halftone` → `drift` with `mark: 'dot'` (`cellSize: 14`), `dna` and `voidWell` → `halo`, `circuit` and `stars` → `constellation`, `aurora`, `fire`, `silk` and `veil` → `mesh`, `grid`, `weave` and `moire` → `interference`, `morph` and `noise` → `mesh`, `pulse` → `ripple`, `rain` → `cascade`, `terrain`, `dune` and `etch` → `contour`, `facet` → `caustics`, `wave` → `swell`. The retired canvas presets draw on a 2D canvas and also take `accent` and `dither`.
657
690
 
@@ -94,3 +94,10 @@ The website uses the published renderer's native Trail. A chain-shaped tonal ove
94
94
 
95
95
  “Draw [image] with `ditherImage` in our two tones `[ground token, ink token]`, mark [dither/pixel/dot/engraving], developing in on scroll (`reveal: 'scroll'`). Keep the `<img>` in the markup with its `alt` as the fallback and accessible name. Compare cell sizes 4–8 on desktop and phone, and both themes.”
96
96
 
97
+ ## 22. An ASCII ocean behind the hero
98
+
99
+ “Put an ASCII ocean behind our landing hero with `ocean` from `asciify-engine/kit`: [a shark, a hammerhead, a manta, a few fish, two jellyfish and a school of 30 small fish], inked from [our text token] (or a `palette` per kind from our brand tokens), `layer: 'under'` so the headline and CTA stay real HTML above it. The cursor scatters the fish and the sharks turn to investigate; a click sends a ripple. Pick a `seed` we like, keep the busiest creatures off the headline (fewer, or a lower `density` on phones), give it a `label` or leave it decorative, and a `poster` for the first viewport in both themes. Reduced motion shows a still composition; it pauses off screen. Check light and dark, a 390px phone and WebGL off.”
100
+
101
+ ## 23. An interactive hero background with a mode switcher
102
+
103
+ “Build an interactive ASCII hero background visitors can stir, click and grow, with a mode switcher: `background(hero, { preset: estuary, clear: headline })` from `asciify-engine/kit`, and three pills (Estuary, Capillary, Shockwave) as a real radio group that call `bg.setPreset(estuary | capillary | shockwave)`. Keep it faint behind the headline in [our text token] (`palette: { light, dark }` if we need a tint), the headline and CTA real HTML, the pills keyboard-reachable and labelled, a `poster` for the first viewport in both themes, and one still frame under reduced motion. Check light and dark, a 390px phone, touch, and WebGL off.”
@@ -1 +0,0 @@
1
- import{parseColor as t,hash2 as o}from"./chunk-ZCHGV2CV.js";import{mountCanvas as e}from"./chunk-AAV5QNHU.js";function n(e,n,c,i,a={x:.5,y:.5},r={}){const{fontSize:l=13,chars:s=" ·:;=+*#%@",color:h,accentColor:f,speed:M=1,radius:$=.38,swirl:d=3,lightMode:g=!1}=r,m=f??(g?"#6b8700":"#d4ff00"),p=.62*l,u=1.4*l,x=Math.ceil(n/p),b=Math.ceil(c/u),S=n/c;e.clearRect(0,0,n,c),e.font=`${l}px monospace`,e.textBaseline="top";let y=255,z=255,C=255;if(g&&(y=55,z=55,C=55),h){const o=t(h);o&&(y=o.r,z=o.g,C=o.b)}let V=212,k=255,v=0;const w=t(m);w&&(V=w.r,k=w.g,v=w.b);const A=i*M;for(let t=0;t<b;t++){const n=t/b;for(let c=0;c<x;c++){const i=(c/x-a.x)*S,r=n-a.y,l=Math.sqrt(i*i+r*r)/$;if(l>1){const n=o(3*c,7*t)*Math.max(0,1-3*(l-1));if(n<.62)continue;const i=n*(g?.28:.04);e.fillStyle=`rgba(${y},${z},${C},${i})`,e.fillText(s[1],c*p,t*u);continue}const h=Math.max(0,1-Math.abs(l-(.15+.12*Math.sin(1.1*A)))/.07),f=Math.pow(1-l,2.2),M=Math.min(1,f+.6*h);if(M<.06)continue;const d=Math.floor(M*(s.length-1)),m=s[Math.min(s.length-1,d)],b=h>.35||l<.08,w=g?.85*M:.18*M;e.fillStyle=b?`rgba(${V},${k},${v},${g?.95:.38})`:`rgba(${y},${z},${C},${w})`,e.fillText(m,c*p,t*u)}}}var c={id:"void",name:"Void",description:"A gravity well that spirals characters around the cursor.",cellSize:13,speed:1,cursor:!0,mount:t=>e(t,(t,o,e,c,i,a)=>n(t,o,e,c,i,{fontSize:a.fontSize,chars:a.chars,lightMode:a.lightMode,color:a.ink,accentColor:a.accent}))};export{n as renderVoidBackground,c as voidWell};//# sourceMappingURL=chunk-4G5LJNMB.js.map
@@ -1 +0,0 @@
1
- import{parseColor as t,hash2 as e}from"./chunk-ZCHGV2CV.js";import{mountCanvas as o}from"./chunk-AAV5QNHU.js";function r(o,r,c,n,l={}){const{fontSize:i=14,chars:s=" ·∙•:-=+*#",color:a,accentColor:h,speed:f=.5,harmonics:m=3,lightMode:p=!1}=l,g=h??(p?"#6b8700":"#d4ff00"),M=.62*i,d=1.4*i,$=Math.ceil(r/M),u=Math.ceil(c/d);o.clearRect(0,0,r,c),o.font=`${i}px monospace`,o.textBaseline="top";let b=255,S=255,x=255;if(p&&(b=55,S=55,x=55),a){const e=t(a);e&&(b=e.r,S=e.g,x=e.b)}let z=212,C=255,k=0;const y=t(g);y&&(z=y.r,C=y.g,k=y.b);const A=n*f,V=Array.from({length:m},(t,e)=>1/(e+1)).reduce((t,e)=>t+e,0);for(let t=0;t<u;t++)for(let r=0;r<$;r++){let c=0;for(let o=0;o<m;o++){const n=.18+1.4*e(r*(o+3)+7,t*(o+5)+11),l=e(r*(o+7),t*(o+9)+3)*Math.PI*2,i=1/(o+1);c+=Math.sin(A*n+l)*i}const n=.5*(c/V+1);if(n<.28)continue;const l=(n-.28)/.72,i=s[Math.min(s.length-1,Math.floor(l*s.length))],a=n>.88,h=p?.82*l:.13*l;o.fillStyle=a?`rgba(${z},${C},${k},${p?.92:.28})`:`rgba(${b},${S},${x},${h})`,o.fillText(i,r*M,t*d)}}var c={id:"morph",name:"Morph",description:"Every cell shimmers at its own frequencies.",cellSize:14,speed:1,cursor:!1,mount:t=>o(t,(t,e,o,c,n,l)=>r(t,e,o,c,{fontSize:l.fontSize,chars:l.chars,lightMode:l.lightMode,color:l.ink,accentColor:l.accent}))};export{c as morph,r as renderMorphBackground};//# sourceMappingURL=chunk-5Q634WWI.js.map
@@ -1 +0,0 @@
1
- import{parseColor as t,hash2 as o}from"./chunk-ZCHGV2CV.js";import{mountCanvas as e}from"./chunk-AAV5QNHU.js";function n(e,n,c,l,i={}){const{fontSize:r=13,chars:a="0123456789ABCDEF@#$&*+=/<>",accentColor:s,color:f,speed:h=1,density:g=.55,tailLength:d=14,lightMode:$=!1}=i,p=s??($?"#6b8700":"#d4ff00"),m=.62*r,u=1.4*r,M=Math.ceil(n/m),b=Math.ceil(c/u);e.clearRect(0,0,n,c),e.font=`${r}px monospace`,e.textBaseline="top";let C=255,S=255,x=255;if($&&(C=55,S=55,x=55),f){const o=t(f);o&&(C=o.r,S=o.g,x=o.b)}let z=212,k=255,y=0;const A=t(p);A&&(z=A.r,k=A.g,y=A.b);const V=b+d;for(let t=0;t<M;t++){if(o(17*t,3)>g)continue;const n=(.5+1.5*o(31*t,7))*h,c=o(13*t,11)*V,i=Math.floor((l*n*7+c)%V),r=t*m;for(let n=0;n<=d;n++){const c=i-(d-n);if(c<0||c>=b)continue;const s=c*u,f=o(53*t+Math.floor(5*l+n),7*c),h=a[Math.floor(f*a.length)],g=n/d;if(n===d)e.fillStyle=`rgba(${z},${k},${y},${$?.7:.85})`;else{const t=$?.85*g:.15*g;e.fillStyle=`rgba(${C},${S},${x},${t})`}e.fillText(h,r,s)}}}var c={id:"rain",name:"Rain",description:"Columns of falling characters with bright heads.",cellSize:13,speed:1,cursor:!1,mount:t=>e(t,(t,o,e,c,l,i)=>n(t,o,e,c,{fontSize:i.fontSize,chars:i.chars,lightMode:i.lightMode,color:i.ink,accentColor:i.accent}))};export{c as rain,n as renderRainBackground};//# sourceMappingURL=chunk-7TXDNPL3.js.map
@@ -1 +0,0 @@
1
- import{parseColor as t,MONO as e,pixelSnap as n,fbm as o,hash2 as a,band as r,ditherIndex as i,toneAlpha as c}from"./chunk-ZCHGV2CV.js";import{mountCanvas as h}from"./chunk-AAV5QNHU.js";import{hexRgb as s}from"./chunk-I377LEZA.js";function l(h,s,l,f,M={x:.5,y:.5},m={}){const{fontSize:g=13,charAspect:u=.62,lineHeightRatio:d=1.3,chars:p=" .:-=+*#%@",baseColor:x=null,accentColor:$,accentThreshold:b=.52,mouseInfluence:S=.4,mouseFalloff:A=2.8,speed:C=1,vortex:k=!0,sparkles:v=!1,breathe:y=!0,lightMode:z=!1}=m,j=Array.from(p),w=g*u,H=g*d,V=Math.ceil(s/w),I=Math.ceil(l/H),R=M.x,T=M.y,Z=$?t($):null;h.clearRect(0,0,s,l),h.font=`${g}px ${e}`;const q=n(h);h.textBaseline="top";const B=f*C,E=y?.12*(.5*Math.sin(.22*B)+.5):0;for(let t=0;t<I;t++)for(let e=0;e<V;e++){const n=e/V,s=t/I,l=.045,f=.08*B,M=.06,g=.45*((.5*Math.sin(.08*e+.05*t+.6*B)+.5+(.5*Math.sin(.03*e-.07*t+.4*B)+.5)+(.5*Math.sin(.05*e+.03*t+.8*B)+.5))/3)+.35*(.5*o(e*l+f,t*l*1.4-.7*f)+.5)+.2*(.5*Math.sin((e+.65*t)*M+1.1*B)+.5)+E,u=n-R,d=s-T,p=Math.sqrt(u*u+d*d);let $=0;if(k&&p<.35){const t=Math.atan2(d,u),e=Math.sin(4*t+2.2*B-14*p),n=Math.max(0,1-p/.35);$=e*n*n*.22}const C=g*(1-S)+(Math.max(0,1-p*A)+.5*$)*S+.15*$,y=Math.min(1,Math.max(0,C));let F=y;if(v&&y>.72){const n=Math.floor(8*B),o=a(7*e+3*n,11*t+n);o>.88&&(F=Math.min(1,y+4*(o-.88)))}const G=r(F,.32,.9);if(G<=0)continue;const L=i(G,j.length,e,t,m.ditherStrength);if(" "===j[L])continue;const N=c(G);h.fillStyle=Z&&F>b?`rgba(${Z.r},${Z.g},${Z.b},${N})`:x?x.replace("{a}",String(N)):z?`rgba(111,109,103,${N})`:`rgba(143,141,134,${N})`,h.fillText(j[L],q(e*w),q(t*H))}}var f={id:"wave",name:"Wave",description:"An interference field with a soft vortex at the cursor and a slow breath.",cellSize:13,speed:.6,cursor:!0,mount:t=>h(t,(t,e,n,o,a,r)=>{const[i,c,h]=s(r.ink);l(t,e,n,o,a,{ditherStrength:r.ditherStrength,fontSize:r.fontSize,chars:r.chars,lightMode:r.lightMode,baseColor:`rgba(${i},${c},${h},{a})`,accentColor:r.accent})})};export{l as renderWaveBackground,f as wave};//# sourceMappingURL=chunk-F4IO3HWD.js.map
@@ -1 +0,0 @@
1
- import{parseColor as t}from"./chunk-ZCHGV2CV.js";import{mountCanvas as e}from"./chunk-AAV5QNHU.js";function o(e,o,n,c,r={x:.5,y:.5},l={}){const{fontSize:s=14,chars:a=". · ○ ◎ ●",accentColor:i,color:h,rings:f=5,speed:M=1,sharpness:g=4,lightMode:p=!1}=l,m=i??(p?"#007a5e":"#00ffcc");e.clearRect(0,0,o,n),e.textBaseline="middle",e.textAlign="center";const u=o*r.x,d=n*r.y,x=1.6*Math.sqrt(u*u+d*d)+.2*Math.sqrt(o*o+n*n);let $=255,b=255,S=255;if(p&&($=55,b=55,S=55),h){const e=t(h);e&&($=e.r,b=e.g,S=e.b)}let z=0,A=255,C=204;const k=t(m);k&&(z=k.r,A=k.g,C=k.b);const q=a.replace(/ /g,"").split("");if(0===q.length)return;const y=Math.ceil(o/s),V=Math.ceil(n/s);for(let t=0;t<V;t++)for(let o=0;o<y;o++){const n=o*s+.5*s,r=t*s+.5*s,l=n-u,a=r-d,i=Math.sqrt(l*l+a*a)/x;let h=0;for(let t=0;t<f;t++){const e=(c*M*.38+t/f)%1,o=Math.abs(i-e),n=Math.max(0,1-o*x/(s*(12-g)));h+=Math.cos(n*Math.PI*.5)*n}if(h=Math.min(1,h),h<.02)continue;const m=h>.6;e.font=`${s}px monospace`;const k=Math.floor(h*(q.length-1)),y=q[Math.min(k,q.length-1)],V=p?.88*h:.22*h;e.fillStyle=m?`rgba(${z},${A},${C},${Math.min(p?.95:.4,.55*h)})`:`rgba(${$},${b},${S},${V})`,e.fillText(y,n,r)}e.textAlign="left"}var n={id:"pulse",name:"Pulse",description:"Rings of characters ripple out from the cursor.",cellSize:14,speed:1,cursor:!0,mount:t=>e(t,(t,e,n,c,r,l)=>o(t,e,n,c,r,{fontSize:l.fontSize,chars:l.chars,lightMode:l.lightMode,color:l.ink,accentColor:l.accent}))};export{n as pulse,o as renderPulseBackground};//# sourceMappingURL=chunk-GJANKSX6.js.map
@@ -1 +0,0 @@
1
- import{mountPageField as e}from"./chunk-RGV7VRYC.js";var r=(e,r)=>!1===e.cursor?"none":"string"==typeof e.cursor?e.cursor:r;function t(r,t,n,l){let o=null;if(o=e({host:r.host,kit:r.kit,layer:"under",glyphs:l&&(()=>l(r.settings())),look:e=>{const n=r.settings();return{...t(n,e),...n.look}},ink:e=>r.ink(e)??(e?n.dark:n.light),reducedMotion:r.reducedMotion,onFail:()=>{o=null,r.onFail()}}),!o)return null;const i=o.canvas;return{get field(){return o?.field??null},get canvas(){return o?.canvas??i},refresh(){o?.refresh()},play(){o?.field.play()},pause(){o?.field.pause()},destroy(){o?.destroy(),o=null}}}var n=()=>"number"==typeof innerWidth&&innerWidth<760,l={light:"#86847e",dark:"#7c7a74"},o={light:"#8f8d86",dark:"#64625d"},i=e=>({font:'"Geist Mono", ui-monospace, monospace',fontWeight:400,cellSize:e.cellSize,cellAspect:.62,glyphScale:.86}),s=e=>({cellSize:e.cellSize,cellAspect:1,dotScale:.68}),a={x:.18,y:.2,width:.64,height:.6,feather:.3,shape:"ellipse"};function c(e){const{scene:n,charset:o,hover:c,middle:d=a,feather:h=.3,graphite:u=l}=e,p=e.mark??"glyph";return{id:e.id,name:e.name,description:e.description,cellSize:e.cellSize,speed:e.speed??1,cursor:e.cursor??!0,opacity:e.opacity,mount(l){const a=t(l,(t,l)=>{const a=((e,r)=>e.mark??(e.charset||e.look?.charset?"glyph":r))(t,p);return{scene:n,color:"ink",shade:0,background:"transparent",vignette:0,speed:t.speed,maxPixelRatio:2,levels:"none",blend:"on",..."dot"===a?{mark:"dot",...s(t)}:{mark:"glyph",charset:t.charset??o,...i(t)},hover:r(t,c),lantern:{radius:.14,strength:.45,trail:.8,follow:9},trail:{strength:.8,radius:.35},fluid:{radius:.09,refraction:.03,glow:.6},clear:t.clear?{element:t.clear,padding:0,feather:h,shape:"ellipse"}:d,...e.tune?.(t,l)}},u,"dot"===p?e=>({...i(e),charset:o}):void 0);if(!a||!e.extra)return a;const g=e.extra(l,a),f=a.destroy.bind(a);return Object.assign(a,{destroy(){g(),f()}})}}}export{o as FIELD_GRAPHITE,r as hoverOf,t as mountField,n as narrow,c as scenePreset};//# sourceMappingURL=chunk-LTRVMY3D.js.map
@@ -1 +0,0 @@
1
- import{parseColor as t,hash2 as o}from"./chunk-ZCHGV2CV.js";import{mountCanvas as c}from"./chunk-AAV5QNHU.js";function e(c,e,n,r,a={x:.5,y:.5},i={}){const{fontSize:l=12,chars:s="·-=+|/",accentColor:h,color:f,bands:d=3,speed:g=1,bandWidth:M=.12,glitch:m=!0,lightMode:p=!1}=i,$=h??(p?"#6b8700":"#d4ff00"),b=.62*l,x=1.4*l,u=Math.ceil(e/b),S=Math.ceil(n/x);c.clearRect(0,0,e,n),c.font=`${l}px monospace`,c.textBaseline="top";let z=255,C=255,k=255;if(p&&(z=55,C=55,k=55),f){const o=t(f);o&&(z=o.r,C=o.g,k=o.b)}let y=212,V=255,j=0;const A=t($);A&&(y=A.r,V=A.g,j=A.b);const G=r*g;for(let t=0;t<S;t++)for(let e=0;e<u;e++){const n=t/S,r=((n*d-.5*G)%1+1)%1,i=Math.max(0,1-r/M),l=.35*(.5*o(3*e,7*t)+.5);let h=0;if(m){const c=e/u-a.x,r=n-a.y,i=Math.sqrt(c*c+r*r);if(i<.18){const c=o(11*e+Math.floor(12*G),5*t);h=Math.max(0,1-i/.18)*(c>.5?c-.3:0)}}const f=Math.min(1,l+.8*i+.6*h);if(f<.04)continue;const g=s[Math.floor(f*(s.length-1))],$=i>.55,A=p?.82*f:.12*f;c.fillStyle=$?`rgba(${y},${V},${j},${p?.92:.28})`:`rgba(${z},${C},${k},${A})`,c.fillText(g,e*b,t*x)}}var n={id:"grid",name:"Grid",description:"Scan bands roll down a character grid and glitch near the cursor.",cellSize:12,speed:1,cursor:!0,mount:t=>c(t,(t,o,c,n,r,a)=>e(t,o,c,n,r,{fontSize:a.fontSize,chars:a.chars,lightMode:a.lightMode,color:a.ink,accentColor:a.accent}))};export{n as grid,e as renderGridBackground};//# sourceMappingURL=chunk-OOVUQEXT.js.map
@@ -1 +0,0 @@
1
- import{parseColor as o,fbm as t,hash2 as e}from"./chunk-ZCHGV2CV.js";import{mountCanvas as r}from"./chunk-AAV5QNHU.js";import{mixHex as l}from"./chunk-I377LEZA.js";function n(r,l,n,a,i={}){const{fontSize:c=13,chars:s=" .,:;+*#@",color:f="#4caf50",skyColor:h="#1a237e",peakColor:g="#e0e0e0",speed:p=1,roughness:b=.55,heightScale:M=.55,stars:d=!0,lightMode:m=!1}=i,k=.62*c,u=1.4*c,A=Math.ceil(l/k),x=Math.ceil(n/u),S=o(f)??{r:76,g:175,b:80},$=o(h)??{r:26,g:35,b:126},y=o(g)??{r:224,g:224,b:224};r.clearRect(0,0,l,n),r.font=`${c}px "JetBrains Mono", monospace`,r.textBaseline="top";const C=a*p*.4,z=new Array(A);for(let o=0;o<A;o++){const e=(.5*t((o/A+C)*b*3,.5)+.5)*M;z[o]=Math.floor(e*x)}for(let o=0;o<x;o++)for(let t=0;t<A;t++){const l=x-1-z[t],n=o===l;if(!(o>=l)){if(d){const l=e(7*t+Math.floor(.3*C),13*o);if(l>.97){const e=.3*Math.sin(2*a+100*l)+.7;r.globalAlpha=.5*e,r.fillStyle=`rgb(${$.r+60},${$.g+60},${$.b+80})`,r.fillText("·",t*k,o*u)}}continue}const i=(o-l)/Math.max(1,z[t]),c=s[Math.min(s.length-1,Math.floor(i*s.length))];if(" "===c&&!n)continue;const f=n?1:Math.max(0,1-4*i),h=S.r+(y.r-S.r)*f|0,g=S.g+(y.g-S.g)*f|0,p=S.b+(y.b-S.b)*f|0;r.globalAlpha=.5+.5*i,r.fillStyle=`rgb(${h},${g},${p})`,r.fillText(n?s[s.length-1]:c,t*k,o*u)}r.globalAlpha=1}var a={id:"terrain",name:"Terrain",description:"A side-scrolling landscape drawn in density characters.",cellSize:13,speed:1,cursor:!1,mount:o=>r(o,(o,t,e,r,a,i)=>n(o,t,e,r,{fontSize:i.fontSize,chars:i.chars,lightMode:i.lightMode,color:i.ink,peakColor:i.accent??l(i.ink,"#ffffff",.65),skyColor:l(i.ink,"#0c0d0b",.55)}))};export{n as renderTerrainBackground,a as terrain};//# sourceMappingURL=chunk-UWX7VIXT.js.map
@@ -1 +0,0 @@
1
- import{MONO as t,GRAPHITE_LIGHT as e,GRAPHITE_DARK as o,pixelSnap as r,parseColor as n,band as c,ditherIndex as i,toneAlpha as a,vnoise as l}from"./chunk-ZCHGV2CV.js";import{mountCanvas as s}from"./chunk-AAV5QNHU.js";function h(s,h,f,d,g={x:.5,y:.5},u={}){const{fontSize:m=13,chars:M=" .:-=+*#%@",accentColor:p,color:$,octaves:x=4,speed:S=1,scale:b=1,accentThreshold:y=.9,mouseWarp:z=.3,lightMode:A=!1}=u,C=Array.from(M),k=.62*m,V=1.3*m,j=Math.ceil(h/k),v=Math.ceil(f/V);s.clearRect(0,0,h,f),s.font=`${m}px ${t}`,s.textBaseline="top";const w=A?e:o;let H=w.r,N=w.g,T=w.b;const q=r(s);if($){const t=n($);t&&(H=t.r,N=t.g,T=t.b)}let B=H,G=N,Q=T;const R=p?n(p):null;R&&(B=R.r,G=R.g,Q=R.b);const U=.035*b,W=d*S,Z=Math.min(6,Math.max(1,x)),D=(t,e)=>{let o=0,r=.5,n=1,c=0;for(let i=0;i<Z;i++)o+=l(t*n,e*n)*r,c+=r,r*=.5,n*=2.1;return o/c};for(let t=0;t<v;t++)for(let e=0;e<j;e++){const o=e*U+.06*W,r=t*U*1.3-.04*W,n=e/j-g.x,l=t/v-g.y,h=Math.sqrt(n*n+l*l),f=z>0?.12*Math.max(0,1-h/z):0,d=D(o+f*Math.sin(1.3*W+8*l),r+f*Math.cos(.9*W+8*n)),m=c(.5*d+.5,.7,.83);if(m<=0)continue;const M=C[i(m,C.length,e,t,u.ditherStrength)];if(" "===M)continue;const p=!!R&&m>y,$=a(m);s.fillStyle=p?`rgba(${B},${G},${Q},${$})`:`rgba(${H},${N},${T},${$})`,s.fillText(M,q(e*k),q(t*V))}}var f={id:"noise",name:"Noise",description:"A slow fractal noise field that warps around the cursor.",cellSize:13,speed:.5,cursor:!0,mount:t=>s(t,(t,e,o,r,n,c)=>h(t,e,o,r,n,{ditherStrength:c.ditherStrength,fontSize:c.fontSize,chars:c.chars,lightMode:c.lightMode,color:c.ink,accentColor:c.accent}))};export{f as noise,h as renderNoiseBackground};//# sourceMappingURL=chunk-V6KL3IA7.js.map
@@ -1 +0,0 @@
1
- import{parseColor as o,hash2 as t}from"./chunk-ZCHGV2CV.js";import{mountCanvas as l}from"./chunk-AAV5QNHU.js";import{mixHex as e}from"./chunk-I377LEZA.js";function r(l,e,r,a,i={}){const{fontSize:n=13,baseChars:f="ATCG",bridgeChars:h="-=≡",color:c="#00e5ff",color2:s="#ff4081",bridgeColor:b="#88ffcc",speed:g=1,helixCount:M,lightMode:p=!1}=i,d=.62*n,m=1.4*n,u=Math.ceil(e/d),$=Math.ceil(r/m),x=M??Math.max(1,Math.floor(e/80)),A=u/x,C=o(c)??{r:0,g:229,b:255},S=o(s)??{r:255,g:64,b:129},k=o(b)??{r:136,g:255,b:204};l.clearRect(0,0,e,r),l.font=`${n}px "JetBrains Mono", monospace`,l.textBaseline="top";const z=a*g,I=.35*A;for(let o=0;o<x;o++){const e=A*(o+.5);for(let r=0;r<$;r++){const a=r/$*Math.PI*6-1.8*z,i=e+Math.sin(a)*I,n=e+Math.sin(a+Math.PI)*I,c=Math.round(i),s=Math.round(n);if(c<0||c>=u)continue;const b=t(31*o+7*r,3),g=f[Math.floor(b*f.length)],M=.5*(Math.sin(a)+1),p=.5*(Math.sin(a+Math.PI)+1);if(l.globalAlpha=.35+.65*M,l.fillStyle=`rgb(${C.r},${C.g},${C.b})`,l.fillText(g,c*d,r*m),s>=0&&s<u){const e=t(53*o+11*r,7),a=f[Math.floor(e*f.length)];l.globalAlpha=.35+.65*p,l.fillStyle=`rgb(${S.r},${S.g},${S.b})`,l.fillText(a,s*d,r*m)}if(r%3===0){const e=Math.min(c,s),a=Math.max(c,s);if(a-e>1){const i=t(17*r+43*o,5),n=h[Math.floor(i*h.length)],f=.25*(M+p)+.2;l.globalAlpha=f,l.fillStyle=`rgb(${k.r},${k.g},${k.b})`;for(let o=e+1;o<a;o++)l.fillText(n,o*d,r*m)}}}}l.globalAlpha=1}var a={id:"dna",name:"DNA",description:"Double helices scroll past with base-pair letters.",cellSize:13,speed:1,cursor:!1,mount:o=>l(o,(o,t,l,a,i,n)=>r(o,t,l,a,{fontSize:n.fontSize,color:n.ink,color2:n.accent??e(n.ink,"#ffffff",.55),bridgeColor:e(n.ink,"#0c0d0b",.35)}))};export{a as dna,r as renderDnaBackground};//# sourceMappingURL=chunk-X7AUCVMH.js.map
@@ -1 +0,0 @@
1
- import{parseColor as t,hash2 as e}from"./chunk-ZCHGV2CV.js";import{mountCanvas as o}from"./chunk-AAV5QNHU.js";function n(o,n,c,r,s={x:.5,y:.5},l={}){const{fontSize:a=14,chars:i=" . · * + ° ★",accentColor:h,color:f,speed:d=1,count:g=180,lightMode:m=!1}=l,p=h??(m?"#6b8700":"#d4ff00");o.clearRect(0,0,n,c),o.textBaseline="middle",o.textAlign="center";const M=n*(.2+.6*s.x),x=c*(.2+.6*s.y),$=.65*Math.sqrt(n*n+c*c);let u=255,S=255,b=255;if(m&&(u=55,S=55,b=55),f){const e=t(f);e&&(u=e.r,S=e.g,b=e.b)}let A=212,k=255,z=0;const C=t(p);C&&(A=C.r,k=C.g,z=C.b);const y=i.replace(/ /g,"").split("");if(0!==y.length){for(let t=0;t<g;t++){const s=e(17*t,3)*Math.PI*2,l=(r*(.15+.85*e(31*t,7))*d*.22+e(13*t,11))%1,i=M+Math.cos(s)*l*$,h=x+Math.sin(s)*l*$;if(i<-20||i>n+20||h<-20||h>c+20)continue;const f=Math.max(6,a*(.4+.9*l));o.font=`${f}px monospace`;const g=y[Math.min(y.length-1,Math.floor(l*y.length))],p=l>.72,C=m?.85*l:.2*l;o.fillStyle=p?`rgba(${A},${k},${z},${Math.min(m?.92:.32,2.2*C)})`:`rgba(${u},${S},${b},${C})`,o.fillText(g,i,h)}o.textAlign="left"}}var c={id:"stars",name:"Stars",description:"A sparse starfield that twinkles, drifts and leans toward the cursor.",cellSize:14,speed:1,cursor:!0,mount:t=>o(t,(t,e,o,c,r,s)=>n(t,e,o,c,r,{fontSize:s.fontSize,chars:s.chars,lightMode:s.lightMode,color:s.ink,accentColor:s.accent}))};export{n as renderStarsBackground,c as stars};//# sourceMappingURL=chunk-XXHIFJ5Z.js.map
@@ -1 +0,0 @@
1
- import{MONO as t,GRAPHITE_LIGHT as o,GRAPHITE_DARK as e,pixelSnap as n,parseColor as r,hash2 as c,band as h,ditherIndex as i,toneAlpha as l}from"./chunk-ZCHGV2CV.js";import{mountCanvas as a}from"./chunk-AAV5QNHU.js";function s(a,s,f,M,g={}){const{fontSize:d=13,color:u,accentColor:S,speed:$=.4,layers:I=4,turbulence:P=.8,lightMode:b=!1}=g,p=.62*d,m=1.3*d,k=Math.ceil(s/p),x=Math.ceil(f/m);a.clearRect(0,0,s,f),a.font=`${d}px ${t}`,a.textBaseline="top";const z=b?o:e;let C=z.r,w=z.g,y=z.b;const A=n(a);if(u){const t=r(u);t&&(C=t.r,w=t.g,y=t.b)}let V=C,j=w,v=y;const H=S?r(S):null;H&&(V=H.r,j=H.g,v=H.b);const B=M*$,G=g.chars?Array.from(g.chars):void 0,L=["-","\\","|","/"];for(let t=0;t<x;t++){const o=t/x;for(let e=0;e<k;e++){const n=e/k;let r=0,s=0;for(let t=0;t<I;t++){const e=c(13*t,7*t+3),h=1.1+2.4*e,i=.9+2*c(29*t,11*t+1),l=e*Math.PI*6,a=(.2+.5*c(41*t,17*t))*(t%2==0?1:-1.3),f=Math.sin(n*h*Math.PI*2+B*a+l),M=Math.cos(o*i*Math.PI*2+B*a*.6+1.7*l),g=Math.sin(n*i*Math.PI*P+o*h*Math.PI*P+B*a*.4);r+=Math.atan2(M+.3*g,f),s+=.5*(f*M+1)}const f=r/I,M=h(s/I,.54,.74);if(M<=0)continue;const d=(f%Math.PI+Math.PI)%Math.PI,u=Math.round(d/(Math.PI/4))%L.length;if(!G&&g.ditherStrength&&0===i(M,2,e,t,g.ditherStrength))continue;const S=G?G[i(M,G.length,e,t,g.ditherStrength)]:L[u];if(" "===S)continue;const $=!!H&&M>.85,b=l(M);a.fillStyle=$?`rgba(${V},${j},${v},${b})`:`rgba(${C},${w},${y},${b})`,a.fillText(S,A(e*p),A(t*m))}}}var f={id:"silk",name:"Silk",description:"Long ribbons that follow a slow flow field.",cellSize:13,speed:1,cursor:!1,mount:t=>a(t,(t,o,e,n,r,c)=>s(t,o,e,n,{ditherStrength:c.ditherStrength,fontSize:c.fontSize,chars:c.chars,lightMode:c.lightMode,color:c.ink,accentColor:c.accent}))};export{s as renderSilkBackground,f as silk};//# sourceMappingURL=chunk-XZO4VH2Z.js.map
@@ -1 +0,0 @@
1
- import{parseColor as t,hash2 as o}from"./chunk-ZCHGV2CV.js";import{mountCanvas as e}from"./chunk-AAV5QNHU.js";import{mixHex as l}from"./chunk-I377LEZA.js";var r=1,i=2,n=4,f=8,c={3:"─",12:"│",9:"┌",10:"┐",5:"└",6:"┘",11:"┬",7:"┴",13:"├",14:"┤",15:"┼",[r]:"╶",[i]:"╴",[n]:"╵",[f]:"╷"};function a(e,l,r,i,n={}){const{fontSize:f=13,pulseColor:a="#ffffff",color:s="#00ff88",density:h=.38,speed:g=1,lightMode:p=!1}=n,u=.62*f,b=1.4*f,m=Math.ceil(l/u),d=Math.ceil(r/b),M=t(s)??{r:0,g:255,b:136},$=t(a)??{r:255,g:255,b:255},A=(t,e)=>{if(o(17*t+1,7*e+2)>h)return 0;let l=0;return t+1<m&&o(17*t+1,7*e+2)>.15&&(l|=1),t-1>=0&&o(17*(t-1)+1,7*e+2)>.15&&(l|=2),e+1<d&&o(17*t+1,7*(e+1)+2)>.15&&(l|=8),e-1>=0&&o(17*t+1,7*(e-1)+2)>.15&&(l|=4),l};e.clearRect(0,0,l,r),e.font=`${f}px "JetBrains Mono", monospace`,e.textBaseline="top";const C=i*g;for(let t=0;t<d;t++)for(let l=0;l<m;l++){const r=A(l,t);if(0===r)continue;const i=c[r]??"·",n=(8*C+40*o(l,23*t))%m,f=(6*C+40*o(17*t,11*l))%d,a=(1&r||2&r)&&Math.abs(l-n)<1.5,s=(4&r||8&r)&&Math.abs(t-f)<1.5,h=a||s,g=.25+.35*o(3*l,5*t);h?(e.globalAlpha=.95,e.fillStyle=`rgb(${$.r},${$.g},${$.b})`):(e.globalAlpha=g,e.fillStyle=`rgb(${M.r},${M.g},${M.b})`),e.fillText(i,l*u,t*b)}e.globalAlpha=1}var s={id:"circuit",name:"Circuit",description:"Circuit traces with signals running along them.",cellSize:13,speed:1,cursor:!1,mount:t=>e(t,(t,o,e,r,i,n)=>a(t,o,e,r,{fontSize:n.fontSize,chars:n.chars,lightMode:n.lightMode,color:n.ink,pulseColor:n.accent??l(n.ink,"#ffffff",.7)}))};export{s as circuit,a as renderCircuitBackground};//# sourceMappingURL=chunk-ZNZAO7JA.js.map