git-hash-art 0.8.0 → 0.10.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.
package/ALGORITHM.md CHANGED
@@ -4,49 +4,78 @@ This document describes the deterministic art generation pipeline used by `git-h
4
4
 
5
5
  ## Pipeline Overview
6
6
 
7
- ```
7
+ ```text
8
8
  Hash String
9
9
 
10
10
  ├─► Seed (mulberry32 PRNG)
11
11
 
12
- ├─► Archetype Selection (1 of 10 visual personalities)
12
+ ├─► Archetype Selection (1 of 17 visual personalities, ~15% chance of blending two)
13
+
14
+ ├─► Color Scheme (palette mode + temperature mode + contrast enforcement)
15
+ │ └─► Color Hierarchy (dominant 60% / secondary 25% / accent 15%)
16
+ │ └─► Per-Layer Palette Evolution (±20° hue drift across layers)
17
+
18
+ ├─► Shape Palette (affinity-curated primary / supporting / accent shapes)
13
19
 
14
- ├─► Color Scheme (palette mode from archetype + temperature mode + contrast enforcement)
20
+ ├─► Color Grade Selection (unified tone for post-processing)
15
21
 
16
22
  └─► Rendering Pipeline (parameters overridden by archetype)
17
23
 
18
24
  0. Archetype Override (gridSize, layers, opacity, sizes, styles)
25
+ 0b. Color Hierarchy (dominant/secondary/accent weighting)
26
+ 0c. Shape Palette (curated via affinity graph)
27
+ 0d. Color Grade (hue + intensity for final tone)
28
+ 0e. Light Direction (consistent shadow angle)
19
29
  1. Background Layer (7 styles: radial, linear, solid, multi-stop)
30
+ └─ Gradient Mesh Overlay (3-4 radial color control points)
20
31
  1a. Background Luminance → contrast enforcement threshold
21
- 1b. Layered Background (faint shapes + concentric rings)
32
+ 1b. Layered Background (archetype-coherent shapes + concentric rings)
33
+ 1c. Background Pattern Layer (dot grid / diagonal lines / tessellation)
22
34
  2. Composition Mode Selection
23
35
  2b. Symmetry Mode Selection (none / bilateral / quad)
24
36
  3. Focal Points (rule-of-thirds biased) + Void Zones
37
+ 3b. Void Zone Decoration (halos, scattered dots, concentric rings)
25
38
  4. Flow Field Initialization
26
- 4b. Hero Shape (large focal anchor, archetype-controlled)
39
+ 4b. Hero Shape (palette-aware, affinity-styled)
27
40
  5. Shape Layers (× N layers, archetype-tuned)
28
41
  │ ├─ Blend Mode (per-layer compositing)
29
- │ ├─ Render Style (archetype-preferred + random mix)
42
+ │ ├─ Render Style (affinity-aware per shape)
43
+ │ ├─ Depth-of-Field (stroke thinning + contrast reduction on far layers)
44
+ │ ├─ Color Palette Evolution (per-layer hue drift via evolveHierarchy)
45
+ │ ├─ Focal Depth Boost (nesting/constellation chance ↑ near focal points)
30
46
  │ ├─ Position (composition mode + focal bias + density check)
31
- │ ├─ Shape Selection (4 categories: basic, complex, sacred, procedural)
47
+ │ ├─ Shape Selection (palette-driven with size constraints)
48
+ │ ├─ Hero Avoidance Field (nearby shapes orient toward hero)
32
49
  │ ├─ Contrast Enforcement (ensure readability vs background)
33
50
  │ ├─ Atmospheric Depth (desaturation on later layers)
34
51
  │ ├─ Temperature Contrast (foreground opposite to background)
35
- │ ├─ Styling (transparency, glow, gradients, color jitter)
52
+ │ ├─ Styling (transparency, glow, gradients, HSL jitter)
36
53
  │ ├─ Organic Edges (~15% watercolor bleed)
37
- └─ Recursive Nesting (~15% of large shapes)
38
- 6. Flow-Line Pass (tapered brush strokes, archetype-scaled)
39
- 6b. Symmetry Mirroring (bilateral-x, bilateral-y, or quad)
40
- 7. Noise Texture Overlay
41
- 8. Vignette (radial edge darkening)
42
- 9. Organic Connecting Curves
54
+ ├─ 5a. Tangent Placement (~25% nudge toward nearest shape edge)
55
+ │ ├─ 5b. Shape Mirroring (~40% of basic shapes get reflected copies)
56
+ │ ├─ 5c. Size Echo (~20% of large shapes spawn trailing copies)
57
+ │ ├─ 5d. Recursive Nesting (~15% of large shapes, palette-aware)
58
+ │ └─ 5e. Shape Constellations (~12% of large shapes, pre-composed groups)
59
+ 6. Flow-Line Pass (variable color, pressure, branching)
60
+ 6b. Motion/Energy Lines (directional bursts from shapes)
61
+ 6c. Layered Transparency / Glazing (~20% of shapes get multi-pass redraws)
62
+ 7. Symmetry Mirroring (bilateral-x, bilateral-y, or quad)
63
+ 7. Symmetry Mirroring (bilateral-x, bilateral-y, or quad)
64
+ 8. Noise Texture Overlay
65
+ 9. Vignette (radial edge darkening)
66
+ 10. Organic Connecting Curves
67
+ 11. Post-Processing
68
+ ├─ Color Grading (unified tone overlay)
69
+ ├─ Chromatic Aberration (neon/cosmic/ethereal only)
70
+ └─ Bloom (neon/cosmic only)
71
+ 12. Signature Mark (deterministic geometric chop mark)
43
72
  ```
44
73
 
45
74
  ## 1. Deterministic RNG
46
75
 
47
76
  All randomness flows from a single **mulberry32** PRNG seeded by hashing the full input string:
48
77
 
49
- ```
78
+ ```text
50
79
  seed = hash(gitHash) → mulberry32 state
51
80
  rng() → float in [0, 1)
52
81
  ```
@@ -55,12 +84,12 @@ The old approach extracted 2-char hex pairs from the hash (only ~20 unique value
55
84
 
56
85
  ## 2. Archetype System
57
86
 
58
- Before any rendering begins, the hash deterministically selects one of 10 **visual archetypes** — fundamentally different rendering personalities that override key parameters. This is the primary mechanism for visual diversity: two hashes that select different archetypes will look like they came from entirely different generators.
87
+ Before any rendering begins, the hash deterministically selects one of 17 **visual archetypes** — fundamentally different rendering personalities that override key parameters. This is the primary mechanism for visual diversity: two hashes that select different archetypes will look like they came from entirely different generators.
59
88
 
60
89
  Each archetype controls:
61
90
 
62
91
  | Parameter | Effect |
63
- |-----------|--------|
92
+ | --------- | ------ |
64
93
  | `gridSize` | Shape density (2 = sparse, 9 = packed) |
65
94
  | `layers` | Rendering depth (2 = flat, 5 = deep) |
66
95
  | `baseOpacity` / `opacityReduction` | Transparency character |
@@ -71,340 +100,462 @@ Each archetype controls:
71
100
  | `flowLineMultiplier` | Flow line density (0 = none, 4 = heavy) |
72
101
  | `heroShape` | Whether to draw a dominant focal shape |
73
102
  | `glowMultiplier` | Glow probability scaling (0 = none, 3 = heavy) |
74
- | `sizePower` | Size distribution curve (0.5 = uniform, 2.5 = many tiny) |
103
+ | `sizePower` | Size distribution curve (0.5 = uniform, 2.8 = many tiny) |
75
104
 
76
- ### The 10 Archetypes
105
+ ### The 17 Archetypes
77
106
 
78
- | Archetype | Character | Background | Palette | Key Traits |
79
- |-----------|-----------|------------|---------|------------|
80
- | **dense-chaotic** | Packed, energetic | radial-dark | harmonious | 9×9 grid, 5 layers, heavy flow lines, low glow |
81
- | **minimal-spacious** | Clean, deliberate | solid-light | duotone | 2×2 grid, 2 layers, large shapes, no glow |
82
- | **organic-flow** | Natural, flowing | radial-dark | earth | Heavy flow lines (), watercolor style, no hero |
83
- | **geometric-precision** | Technical, structured | solid-dark | high-contrast | Stroke-only/dashed/hatched styles, no flow lines |
84
- | **ethereal** | Dreamy, luminous | radial-light | pastel-light | High glow (2×), watercolor, hero shape |
85
- | **bold-graphic** | Poster-like, impactful | linear-diagonal | duotone | 2 layers, very large shapes, no flow lines |
86
- | **neon-glow** | Electric, vibrant | solid-dark | neon | Heavy glow (3×), stroke-heavy styles, hero shape |
87
- | **monochrome-ink** | Pen-and-ink, textural | solid-light | monochrome | Hatched/incomplete styles, no glow |
88
- | **cosmic** | Deep space, vast | radial-dark | neon | 8×8 grid, 5 layers, heavy glow, many tiny shapes |
89
- | **classic** | Balanced, familiar | radial-dark | harmonious | Preserves the original rendering look |
107
+ | Archetype | Grid | Layers | Background | Palette | Key Styles | Flow | Hero | Character |
108
+ | --------- | ---- | ------ | ---------- | ------- | ---------- | ---- | ---- | --------- |
109
+ | dense-chaotic | 9 | 5 | radial-dark | harmonious | fill-and-stroke, watercolor | 2.5× | no | Packed, layered, energetic |
110
+ | minimal-spacious | 2 | 2 | solid-light | duotone | fill-and-stroke, stroke-only, incomplete | 0.3× | yes | Clean, airy, few large shapes |
111
+ | organic-flow | 4 | 3 | radial-dark | earth | watercolor, fill-only, incomplete | | no | Natural, flowing, muted tones |
112
+ | geometric-precision | 6 | 3 | solid-dark | high-contrast | stroke-only, dashed, double-stroke, hatched | 0× | no | Sharp, structured, no flow lines |
113
+ | ethereal | 7 | 5 | radial-light | pastel-light | watercolor, incomplete | 1.5× | yes | Soft, glowing, dreamlike |
114
+ | bold-graphic | 2 | 2 | linear-diagonal | duotone | fill-and-stroke, double-stroke | 0× | yes | Poster-like, large shapes |
115
+ | neon-glow | 5 | 4 | solid-dark | neon | stroke-only, double-stroke, dashed | 2× | yes | Bright outlines on black, heavy glow |
116
+ | monochrome-ink | 6 | 3 | solid-light | monochrome | hatched, incomplete, stroke-only | 1.5× | no | Pen-and-ink, single hue |
117
+ | cosmic | 8 | 5 | radial-dark | neon | fill-only, watercolor | 3× | yes | Deep space, many tiny shapes, glow |
118
+ | watercolor-wash | 3 | 3 | radial-light | harmonious | watercolor, fill-only, incomplete | 0.5× | no | Soft washes, large shapes, low opacity |
119
+ | op-art | 8 | 2 | solid-light | high-contrast | fill-and-stroke, stroke-only, dashed | 0× | no | Dense, high-contrast, uniform sizes |
120
+ | collage | 4 | 3 | solid-light | duotone | fill-and-stroke, fill-only, double-stroke | 0× | yes | Overlapping, medium-large shapes |
121
+ | classic | 5 | 4 | radial-dark | harmonious | fill-and-stroke, watercolor | 1× | yes | Balanced, the original look |
122
+ | shattered-glass | 8 | 3 | solid-dark | high-contrast | fill-and-stroke, stroke-only, fill-only | 0× | no | Angular fragments, sharp edges, mosaic-like |
123
+ | botanical | 4 | 4 | radial-light | earth | watercolor, fill-only, incomplete | 3× | yes | Organic tendrils, flowing forms, natural tones |
124
+ | stipple-portrait | 9 | 2 | solid-light | monochrome | stipple, fill-only, hatched | 0× | no | Dense dot textures, pointillist, single hue |
125
+ | celestial | 7 | 5 | radial-dark | neon | fill-only, watercolor, stroke-only, incomplete | 2× | yes | Cosmic crescents, sacred geometry, heavy glow |
90
126
 
91
- Archetype values serve as defaults — explicit user config always wins. The `classic` archetype preserves backward compatibility with the original rendering style.
127
+ #### New Archetype Details
92
128
 
93
- ## 3. Color Scheme
129
+ **shattered-glass** — Favors angular, fragmented shapes (shardField, voronoiCell, penroseTile, diamond, triangle, ngon). Organic shapes like blobs and clouds are filtered from the palette. High contrast on a dark background with no flow lines creates a mosaic of sharp-edged fragments.
130
+
131
+ **botanical** — Boosts organic shapes (tendril, cloudForm, blob, crescent, rose, inkSplat) for a natural, garden-like feel. Earth palette on a light radial background with heavy flow lines (3×) creates flowing, vine-like compositions.
94
132
 
95
- The `SacredColorScheme` class derives three harmonious palettes from the hash:
133
+ **stipple-portrait** Extremely dense (grid 9) with very small shapes (5–120px) and a steep size power curve (2.8) producing many tiny dots. Monochrome palette with stipple and hatched styles creates a pointillist texture. No flow lines or hero shape.
96
134
 
97
- | Palette | Method | Purpose |
98
- |---------|--------|---------|
99
- | Base | `color-scheme` lib, hue = seed % 360, hash-driven scheme type | Primary shape colors |
100
- | Complementary | hue = seed + 180°, contrasting variation | Contrast accents |
101
- | Triadic | hue = seed + 120° | Additional variety |
135
+ **celestial** Boosts sacred geometry and cosmic shapes (crescent, geodesicDome, mandala, flowerOfLife, spirograph, fibonacciSpiral). Neon palette on dark background with heavy glow (2.5×) and deep layering (5 layers) creates a starfield-like composition with luminous geometric forms.
102
136
 
103
- These are merged and deduplicated into a single 6-8 color palette. Background colors are darkened variants (65% and 55% brightness) of the base scheme, with optional temperature shifting.
137
+ ### Archetype Blending
138
+
139
+ ~15% of hashes trigger **archetype blending**, where two archetypes are interpolated to create a hybrid personality. `blendArchetypes(primary, secondary, ratio)` works as follows:
140
+
141
+ - **Blend ratio:** 25–50% (the secondary archetype never dominates)
142
+ - **Numeric parameters** (`gridSize`, `layers`, `baseOpacity`, `minShapeSize`, etc.) are linearly interpolated between the two archetypes
143
+ - **Style arrays** (`preferredStyles`) are merged — the primary's styles come first, then any unique styles from the secondary
144
+ - **Categorical parameters** (`backgroundStyle`, `paletteMode`) use the primary's value when the blend ratio is below 50%, otherwise the secondary's
145
+ - **Boolean parameters** (`heroShape`) use the primary's value
146
+
147
+ This creates subtle hybrid personalities — e.g., a blend of `neon-glow` and `organic-flow` might produce glowing shapes with heavy flow lines and earth-toned neon outlines.
148
+
149
+ ## 3. Color Scheme
150
+
151
+ Color generation uses the `color-scheme` library seeded from the hash, then applies archetype-specific palette modes.
104
152
 
105
153
  ### Palette Modes
106
154
 
107
- The archetype's `paletteMode` reshapes the color palette to match the visual personality:
155
+ | Mode | Description |
156
+ | ---- | ----------- |
157
+ | harmonious | Full palette from the scheme — the default |
158
+ | monochrome | Single hue, varying lightness |
159
+ | duotone | Two colors only |
160
+ | neon | High saturation on dark backgrounds |
161
+ | pastel-light | Soft pastels on light backgrounds |
162
+ | earth | Muted warm naturals |
163
+ | high-contrast | Black + white + one accent color |
164
+
165
+ ### Color Hierarchy
166
+
167
+ After generating the raw palette, colors are organized into a **hierarchy** with weighted selection:
168
+
169
+ - **Dominant (60%)** — the most-used color, selected as the palette entry closest to the average hue
170
+ - **Secondary (25%)** — the color most distant from the dominant
171
+ - **Accent (15%)** — a remaining color for visual punctuation
108
172
 
109
- | Mode | Colors | Character |
110
- |------|--------|-----------|
111
- | **harmonious** | Full base + complementary + triadic | Rich, balanced (default) |
112
- | **monochrome** | Single hue, 5 lightness steps | Elegant, focused |
113
- | **duotone** | Two contrasting hues + tints | Bold, graphic |
114
- | **neon** | 4 hues at full saturation | Electric, vivid |
115
- | **pastel-light** | 4 hues at low saturation, high lightness | Soft, dreamy |
116
- | **earth** | Warm muted naturals (browns, olives, sage) | Organic, grounded |
117
- | **high-contrast** | Black + white + one accent | Technical, stark |
173
+ `pickHierarchyColor(hierarchy, rng)` rolls against these weights so compositions naturally converge on a dominant tone without being monotonous.
118
174
 
119
- Each mode also provides matching background colors (e.g., neon gets near-black backgrounds, pastel-light gets warm off-whites).
175
+ ### HSL Jitter
176
+
177
+ Color variation uses **HSL-space jitter** (`jitterColorHSL`) instead of the old RGB approach. This produces perceptually uniform shifts — a ±10° hue rotation and ±8% saturation/lightness shift feels natural, whereas the equivalent RGB jitter could accidentally desaturate or muddy colors.
178
+
179
+ ### Positional Color
180
+
181
+ Shapes receive color based on their position relative to the canvas center:
182
+ - **Center (< 35% radius):** biased toward the dominant color
183
+ - **Middle (35–70%):** weighted random from the full hierarchy
184
+ - **Edges (> 70%):** biased toward secondary and accent colors
185
+
186
+ This creates a natural color gradient across the composition without explicit gradient code.
120
187
 
121
188
  ### Temperature Contrast
122
189
 
123
- The hash deterministically selects a **temperature mode** that creates warm/cool tension across the image:
190
+ The scheme detects whether the background leans warm or cool, then shifts foreground shapes toward the opposite temperature. This ensures shapes always "pop" against their background.
191
+
192
+ ### Contrast Enforcement
193
+
194
+ Every shape color is checked against the background luminance. If the contrast ratio is too low, the color is lightened or darkened to ensure visibility.
195
+
196
+ ### Color Palette Evolution
197
+
198
+ Colors aren't static across layers — they evolve. `evolveHierarchy(hierarchy, layerFraction)` applies a progressive hue rotation to the entire color hierarchy as rendering moves through layers:
199
+
200
+ - **Total drift:** ±20° across the full layer stack (direction determined by the dominant color's initial hue)
201
+ - **Per-layer rotation:** `layerFraction × 20°` applied via `hueRotate(color, degrees)`, which converts to HSL, shifts the hue, and converts back
202
+ - **Effect:** Early layers lean toward the original palette; later layers drift toward adjacent hues on the color wheel
203
+
204
+ This creates a subtle color journey across the depth of the image — warm reds in the background might shift toward orange-gold in the foreground, giving the composition a sense of temporal progression without breaking palette coherence.
205
+
206
+ ## 4. Shape Affinity System
207
+
208
+ Not all shapes look equally good at all sizes or in all combinations. The affinity system replaces naive random shape selection with intentional curation.
209
+
210
+ ### Shape Inventory
211
+
212
+ The system includes 40+ shapes across 4 categories:
213
+
214
+ | Category | Shapes |
215
+ | -------- | ------ |
216
+ | Basic (9) | circle, square, triangle, hexagon, star, jacked-star, heart, diamond, cube |
217
+ | Complex (7) | platonicSolid, fibonacciSpiral, islamicPattern, celticKnot, merkaba, mandala, fractal |
218
+ | Sacred (8) | flowerOfLife, treeOfLife, metatronsCube, sriYantra, seedOfLife, vesicaPiscis, torus, eggOfLife |
219
+ | Procedural (18) | blob, ngon, lissajous, superellipse, spirograph, waveRing, rose, shardField, voronoiCell, crescent, tendril, cloudForm, inkSplat, geodesicDome, penroseTile, reuleauxTriangle, dotCluster, crosshatchPatch |
124
220
 
125
- | Mode | Probability | Background | Foreground |
126
- |------|-------------|------------|------------|
127
- | `warm-bg` | ~40% | Hues shifted toward orange (30°) | Hues shifted toward blue (210°) |
128
- | `cool-bg` | ~40% | Hues shifted toward blue (210°) | Hues shifted toward orange (30°) |
129
- | `neutral` | ~20% | No temperature shift | No temperature shift |
221
+ ### Quality Tiers
130
222
 
131
- The shift amount is subtle (15-25%) and increases on later layers, creating progressive temperature separation between foreground and background elements. This produces the kind of warm/cool interplay seen in classical painting.
223
+ Each shape has a profile with:
132
224
 
133
- ### Hash-Driven Color Variation
225
+ | Field | Purpose |
226
+ | ----- | ------- |
227
+ | `tier` (1–3) | Visual quality rating. Tier 1 shapes look good at any size; Tier 3 shapes need specific conditions |
228
+ | `minSizeFraction` / `maxSizeFraction` | Size bounds as fraction of `maxShapeSize` — prevents shapes from being drawn at sizes where they look bad |
229
+ | `affinities` | List of shapes this one composes well with |
230
+ | `category` | basic, complex, sacred, or procedural |
231
+ | `heroCandidate` | Whether the shape works as a dominant focal element |
232
+ | `bestStyles` | Render styles that suit this shape (e.g., sacred geometry looks best as stroke-only) |
134
233
 
135
- The hash deterministically selects both a **scheme type** and a **color variation**, producing dramatically different palettes from the same hue:
234
+ ### Shape Palette Construction
136
235
 
137
- | Variation | Character |
138
- |-----------|-----------|
139
- | `soft` | Muted, gentle tones |
140
- | `hard` | High saturation, vivid |
141
- | `pastel` | Light, airy |
142
- | `light` | Bright, open |
143
- | `pale` | Washed out, ethereal |
144
- | `default` | Balanced, neutral |
236
+ `buildShapePalette(rng, shapeNames, archetypeName)` builds a curated set:
145
237
 
146
- Scheme types also vary: `analogic`, `mono`, `contrast`, `triade`, `tetrade`. The complementary palette uses a contrasting variation (e.g., if base is `soft`, complementary uses `hard`) to create intentional color tension.
238
+ 1. **Seed selection:** Pick a Tier 1 hero-candidate shape as the seed
239
+ 2. **Primary (5 shapes):** The seed + its direct affinities (Tier 1–2 only)
240
+ 3. **Supporting (6 shapes):** Affinities-of-affinities + same-category Tier 1–2 shapes
241
+ 4. **Accents (3 shapes):** Tier 1–2 shapes from *other* categories for contrast
147
242
 
148
- ### Color Utilities
243
+ Archetype-specific overrides apply:
244
+ - `geometric-precision` removes organic/procedural shapes from primary
245
+ - `organic-flow` boosts blobs and wave rings
246
+ - `shattered-glass` boosts angular shapes (shardField, voronoiCell, penroseTile), removes blobs/clouds
247
+ - `botanical` boosts organic shapes (tendril, cloudForm, crescent, rose, inkSplat)
248
+ - `stipple-portrait` boosts dot-friendly shapes (dotCluster, circle, crosshatchPatch)
249
+ - `celestial` boosts sacred/cosmic shapes (crescent, geodesicDome, mandala, flowerOfLife)
149
250
 
150
- - **`hexWithAlpha(hex, alpha)`** — converts hex to `rgba()` for transparency
151
- - **`jitterColor(hex, rng, amount)`** — applies ±amount RGB jitter per channel for organic variation
152
- - **`desaturate(hex, amount)`** — blends toward luminance gray for atmospheric depth
153
- - **`shiftTemperature(hex, target, amount)`** — shifts hue toward warm (orange) or cool (blue)
154
- - **Positional blending** — shape fill color is biased by canvas position, creating smooth color flow across the image
251
+ ### Palette-Driven Selection
155
252
 
156
- ## 4. Background
253
+ During rendering, `pickShapeFromPalette(palette, rng, sizeFraction)` selects shapes with weighted probability:
254
+ - **Primary: ~60%**, Supporting: ~30%, Accent: ~10%
255
+ - Shapes whose size constraints don't match the current `sizeFraction` are filtered out before selection
157
256
 
158
- The archetype's `backgroundStyle` selects one of 7 rendering modes:
257
+ ### Affinity-Aware Styling
258
+
259
+ `pickStyleForShape(shapeName, layerStyle, rng)` gives each shape a 70% chance of using one of its `bestStyles` instead of the layer's default style. This means sacred geometry naturally renders as stroke-only while blobs naturally render as watercolor.
260
+
261
+ ## 5. Background Rendering
262
+
263
+ ### Base Background
264
+
265
+ The archetype's `backgroundStyle` selects one of 7 modes:
159
266
 
160
267
  | Style | Description |
161
- |-------|-------------|
162
- | **radial-dark** | Radial gradient from dark center to darker edges (original default) |
163
- | **radial-light** | Light off-white center fading to the base palette |
164
- | **linear-horizontal** | Left-to-right gradient between two palette colors |
165
- | **linear-diagonal** | Corner-to-corner gradient with color reversal |
166
- | **solid-dark** | Flat dark color fill |
167
- | **solid-light** | Flat warm off-white fill |
168
- | **multi-stop** | 3-4 color gradient with a darkened mid-palette accent |
268
+ | ----- | ----------- |
269
+ | radial-dark | Dark radial gradient from center outward (default) |
270
+ | radial-light | Light center (#f0ece4) fading to the palette background |
271
+ | linear-horizontal | Left-to-right gradient |
272
+ | linear-diagonal | Corner-to-corner gradient with midpoint return |
273
+ | solid-dark | Flat dark fill |
274
+ | solid-light | Flat off-white (#f5f2eb) |
275
+ | multi-stop | 34 color gradient using palette colors |
169
276
 
170
- This single change has an outsized impact on visual diversity — a solid-light background with monochrome shapes looks nothing like a radial-dark background with neon glow.
277
+ ### Gradient Mesh Overlay
171
278
 
172
- ### Layered Background
279
+ After the base background, 3–4 radial color control points are placed at random positions using `soft-light` compositing. Each point uses a hierarchy color at very low opacity (8–14%). This adds subtle color variation and depth to what would otherwise be a flat or simple gradient background.
173
280
 
174
- After the gradient, a second pass adds visual texture to the background:
281
+ ### Layered Background Shapes
175
282
 
176
- - **Faint shapes** 3-7 large, very low-opacity circles (3-8% alpha) drawn with `soft-light` blending, creating subtle color pools
177
- - **Concentric rings** — 2-4 rings emanating from center at ~2-5% opacity, adding structure without competing with foreground shapes
283
+ Large, nearly-transparent shapes (37) are drawn in `soft-light` mode at 38% opacity. The shape type is archetype-coherent: geometric archetypes (`geometric-precision`, `op-art`) use rectangles; all others use circles. Subtle concentric rings radiate from the center at ~2–5% opacity to add structure.
178
284
 
179
- This prevents the background from feeling flat and gives the image depth before the main shape layers begin.
285
+ ### Background Pattern Layer
180
286
 
181
- ## 5. Composition Modes
287
+ ~60% of images receive a subtle background pattern drawn in `soft-light` at 2–6% opacity, simulating textured paper:
182
288
 
183
- The hash deterministically selects one of five composition strategies that control how shapes are positioned on the canvas:
289
+ | Pattern | Description |
290
+ | ------- | ----------- |
291
+ | Dot grid (⅓ chance) | Evenly spaced tiny dots across the canvas |
292
+ | Diagonal lines (⅓ chance) | Parallel diagonal lines at 0.5px width |
293
+ | Hexagonal tessellation (⅓ chance) | Honeycomb grid of tiny hexagons, stroke-only |
184
294
 
185
- | Mode | Description |
186
- |------|-------------|
187
- | **Radial** | Shapes emanate from the center with distance following a power curve (denser near center) |
188
- | **Flow-field** | Random positions; shapes are rotated to align with a hash-derived vector field |
189
- | **Spiral** | Shapes follow a multi-turn spiral path outward from center with slight scatter |
190
- | **Grid-subdivision** | Canvas is divided into cells; shapes are placed randomly within cells |
191
- | **Clustered** | 3-5 cluster centers are generated; shapes scatter around the nearest cluster |
295
+ The pattern spacing scales with canvas size (1.5–3% of the shorter dimension). This adds tactile depth without competing with foreground shapes.
192
296
 
193
- Each mode produces fundamentally different visual character from the same shape set.
297
+ ### Background Luminance
194
298
 
195
- ### Symmetry Modes
299
+ The average luminance of the two background colors is computed and stored. This value drives contrast enforcement for all foreground shapes — ensuring they remain visible regardless of background brightness.
196
300
 
197
- ~25% of hashes trigger a symmetry mode that mirrors the rendered content:
301
+ ## 6. Composition & Symmetry
198
302
 
199
- | Mode | Probability | Effect |
200
- |------|-------------|--------|
201
- | `bilateral-x` | 10% | Left half mirrored onto right half |
202
- | `bilateral-y` | 10% | Top half mirrored onto bottom half |
203
- | `quad` | 5% | Both axes mirrored (4-fold symmetry) |
204
- | `none` | 75% | No mirroring |
303
+ ### Composition Modes
205
304
 
206
- Symmetry is applied after shape layers and flow lines but before post-processing (noise, vignette, connecting curves). This means the mirrored content gets the same noise texture and vignette as the original, maintaining visual consistency. Symmetrical generative art is disproportionately appealing to humans due to our innate preference for bilateral symmetry.
305
+ Each image uses one of 5 composition strategies for shape placement:
207
306
 
208
- ## 6. Focal Points & Negative Space
307
+ | Mode | Behavior |
308
+ | ---- | -------- |
309
+ | radial | Shapes cluster around center with power-curve falloff |
310
+ | spiral | Shapes follow a multi-turn spiral from center outward |
311
+ | grid-subdivision | Canvas divided into 3–5 cells; shapes placed within random cells |
312
+ | clustered | 3–5 cluster centers; shapes scatter around the nearest cluster |
313
+ | flow-field | Uniform random placement (rotation driven by flow field) |
209
314
 
210
- 1-2 focal points are placed on the canvas. **70% of the time**, focal points snap to **rule-of-thirds intersection points** (with slight jitter to avoid a mechanical look), creating compositions that feel intentionally designed. The remaining 30% use free placement within the central 60% of the canvas. Every shape position is pulled toward the nearest focal point by a strength factor (30-70%).
315
+ ### Symmetry
211
316
 
212
- ### Hero Shape
317
+ ~25% of hashes trigger symmetry mirroring, applied after all shapes and flow lines are drawn:
318
+ - **bilateral-x (10%):** Left half mirrored to right
319
+ - **bilateral-y (10%):** Top half mirrored to bottom
320
+ - **quad (5%):** Both axes mirrored
213
321
 
214
- ~60% of images receive a **hero shape** a large sacred or complex geometry piece anchored at the primary focal point. The hero shape:
215
- - Uses sacred/complex shape types (flower of life, fibonacci spiral, merkaba, fractal, etc.)
216
- - Is sized at 80-130% of the maximum shape size for visual dominance
217
- - Gets glow effects, gradient fills, and often watercolor rendering
218
- - Is drawn before the main shape layers so other shapes layer on top of it
219
- - Creates a clear center of gravity that anchors the entire composition
322
+ Symmetry is applied by drawing the canvas image onto itself with `scale(-1, 1)` or `scale(1, -1)` transforms.
220
323
 
221
- ### Void Zones (Negative Space)
324
+ ## 7. Focal Points & Void Zones
222
325
 
223
- 1-2 void zones are generated at random positions. Shapes that land inside a void zone have an 85% chance of being skipped, creating deliberate areas of breathing room. A few shapes bleed through (15%) to keep the edges organic rather than hard-cut.
326
+ 12 **focal points** are placed with 70% bias toward rule-of-thirds intersections (the remaining 30% are placed randomly within the central 60% of the canvas). Each focal point has a `strength` (0.3–0.7) that pulls nearby shapes toward it via `applyFocalBias`.
224
327
 
225
- ### Density Awareness
328
+ 1–2 **void zones** are placed randomly. Shapes landing inside a void zone have an 85% chance of being skipped, creating breathing room in the composition.
226
329
 
227
- Before placing each shape, the renderer checks how many shapes already exist nearby. If local density exceeds ~15% of the per-layer shape count, there's a 60% chance the shape is skipped. This prevents areas from becoming an opaque blob and creates natural visual rhythm.
330
+ ### Void Zone Decoration
228
331
 
229
- ## 7. Shape Layers
332
+ Void zones aren't left completely empty — they receive subtle decorative elements that acknowledge the negative space:
230
333
 
231
- The image is built in N layers (default: 4). Each layer has its own characteristics:
334
+ - **Halo ring:** A thin circular stroke at the void zone's boundary using the accent color at 6–12% opacity
335
+ - **Scattered dots (~50% chance):** 5–12 tiny dots (1–3px) scattered randomly inside the void zone at 4–10% opacity, creating a dust-like texture
336
+ - **Inner concentric ring (~30% chance):** A smaller ring at 40–70% of the void zone radius at 3–8% opacity
232
337
 
233
- ### Layer Properties
338
+ These decorations are subtle enough to preserve the breathing room while preventing void zones from feeling like rendering errors.
234
339
 
235
- | Property | Behavior |
236
- |----------|----------|
237
- | Opacity | Decays gently per layer (0.7 → 0.58 → 0.46 → 0.34), minimum 0.15 |
238
- | Size scale | Later layers use progressively smaller shapes (×0.85, ×0.70, ×0.55) |
239
- | Shape weights | Early layers favor basic shapes; later layers favor complex/sacred |
240
- | Per-shape opacity | Additional random jitter (50-100% of layer opacity) |
241
- | Blend mode | Each layer gets a hash-derived `globalCompositeOperation` (see below) |
242
- | Render style | Each layer has a dominant render style (60% from archetype preferences, 40% random); 30% of shapes pick their own |
243
- | Atmospheric depth | Later layers desaturate colors by up to 30%, simulating distance |
340
+ ## 8. Hero Shape
244
341
 
245
- ### Blend Modes (Per-Layer Compositing)
342
+ When the archetype enables `heroShape` and the RNG roll passes (60% chance), a dominant focal element is drawn at the first focal point:
246
343
 
247
- Each layer deterministically selects a `globalCompositeOperation` from: `source-over`, `screen`, `multiply`, `overlay`, `soft-light`, `color-dodge`, `color-burn`, `lighter`. There's a 40% chance of `source-over` (default) to keep some images clean, while the other modes create rich color interactions where shapes overlap — the kind of depth that makes output feel painterly rather than stacked.
344
+ - Shape is selected from palette hero candidates (Tier 1, `heroCandidate: true`)
345
+ - Size is 80–130% of `adjustedMaxSize`
346
+ - Style is chosen from the shape's `bestStyles` via its affinity profile
347
+ - Fill uses the dominant hierarchy color; stroke uses the accent
348
+ - Glow radius is 12–32px (scaled)
349
+ - The hero's position and size are stored for the **hero avoidance field**
248
350
 
249
- ### Render Styles (Per-Shape Treatment)
351
+ ## 9. Shape Layers
250
352
 
251
- Instead of always `fill()` + `stroke()`, each shape gets a rendering treatment:
353
+ The core of the image: `layers` passes (archetype-controlled, typically 2–5), each drawing `gridSize² × 1.5` shapes plus up to 30% random extra.
252
354
 
253
- | Style | Description | Probability |
254
- |-------|-------------|-------------|
255
- | `fill-and-stroke` | Classic solid fill with outline | ~22% (weighted) |
256
- | `fill-only` | Soft shapes with no outline | ~11% |
257
- | `stroke-only` | Wireframe with ghost fill at 30% alpha | ~11% |
258
- | `double-stroke` | Outer stroke at 2× width + inner stroke in fill color | ~11% |
259
- | `dashed` | Dashed outline (5% size dash, 3% gap) | ~11% |
260
- | `watercolor` | 3-4 slightly offset passes at low opacity for bleed effect | ~11% |
261
- | `hatched` | Cross-hatch texture fill clipped to shape boundary | ~11% |
262
- | `incomplete` | Only 60-85% of outline drawn via dash patterns | ~11% |
355
+ ### Per-Layer Setup
263
356
 
264
- 70% of shapes in a layer use the layer's dominant style; 30% pick independently. Additionally, ~15% of `fill-and-stroke` shapes are upgraded to `watercolor` for organic edge effects.
357
+ - **Blend mode:** Random compositing mode (`source-over`, `multiply`, `screen`, `overlay`, `soft-light`, etc.)
358
+ - **Render style bias:** 60% chance of using an archetype-preferred style; 40% random
359
+ - **Opacity:** Decreases per layer (`baseOpacity - layer × opacityReduction`, floor 0.15)
360
+ - **Size scale:** Decreases 15% per layer (later layers = smaller shapes)
361
+ - **Atmospheric desaturation:** Later layers are progressively desaturated (up to 30%) to simulate depth
362
+ - **Depth-of-field:** Later layers get thinner strokes (down to 40% of base width) and reduced contrast (up to 20% opacity reduction), simulating camera focus falloff
265
363
 
266
- ### Atmospheric Depth (Per-Layer Desaturation)
364
+ ### Focal Depth Boost
267
365
 
268
- Later layers progressively desaturate their colors (0% on layer 0, up to 30% on the final layer). This simulates atmospheric perspective — distant shapes appear more muted, creating a sense of foreground/background depth.
366
+ Shapes near focal points receive enhanced detail via `focalDetailBoost()`:
269
367
 
270
- ### Shape Selection (Layer-Weighted)
368
+ - **Nesting chance:** Boosted from the base 15% up to 15–30% for shapes within 25% of canvas size from a focal point
369
+ - **Constellation chance:** Boosted from the base 12% up to 12–22% near focal points
370
+ - **Boost strength:** Proportional to proximity — shapes right at the focal point get the full boost, shapes at the edge of the influence radius get minimal boost
271
371
 
272
- Shapes are divided into four categories with weights that shift across layers:
372
+ This creates a natural depth-of-detail effect where the areas your eye is drawn to (focal points) contain the most intricate shape compositions.
273
373
 
274
- | Category | Shapes | Early layers | Late layers |
275
- |----------|--------|-------------|-------------|
276
- | **Basic** | circle, square, triangle, hexagon, diamond, cube | High weight | Low weight |
277
- | **Complex** | star, platonic solid, fibonacci spiral, islamic pattern, celtic knot, merkaba, fractal | Medium | Medium-high |
278
- | **Sacred** | mandala, flower of life, tree of life, Metatron's cube, Sri Yantra, seed of life, vesica piscis, torus, egg of life | Low | High |
279
- | **Procedural** | blob, ngon, lissajous, superellipse, spirograph, waveRing, rose | Medium (always present) | Medium-high |
374
+ ### Per-Shape Pipeline
280
375
 
281
- Procedural shapes are hash-derived — their geometry is generated from the RNG, so every hash produces unique shapes that don't exist in any other generation. See the Procedural Shapes section below for details.
376
+ For each shape in a layer:
282
377
 
283
- ### Contrast Enforcement
378
+ 1. **Position:** Composition mode generates a candidate position, then `applyFocalBias` pulls it toward the nearest focal point
379
+ 2. **Void check:** 85% skip chance if inside a void zone
380
+ 3. **Density check:** If local density exceeds 15% of `shapesPerLayer`, 60% skip chance
381
+ 4. **Size:** Power-curve distribution controlled by `archetype.sizePower` — higher values produce more small shapes
382
+ 5. **Shape selection:** `pickShapeFromPalette` with size-constraint filtering
383
+ 6. **Rotation:** Flow-field angle in flow-field mode (±15° jitter); random otherwise
384
+ 7. **Hero avoidance:** Shapes within 1.5× the hero's size orient toward it (rotation blended 40% toward the angle-to-hero)
385
+ 8. **Color:** Positional color from hierarchy + HSL jitter, with atmospheric desaturation and temperature contrast applied
386
+ 9. **Contrast enforcement:** Fill and stroke colors checked against background luminance
387
+ 10. **Styling:** Affinity-aware render style, optional glow (sacred shapes 45% base chance × archetype multiplier), optional radial gradient fill (30% chance)
388
+ 11. **Organic edges:** 15% of `fill-and-stroke` shapes are promoted to `watercolor` style
389
+ 12. **Light direction:** Non-glowing shapes get a subtle shadow offset along the consistent light angle
284
390
 
285
- After color selection, every foreground color (fills, strokes, flow lines, connecting curves) is checked against the average background luminance. If the luminance difference is below the minimum threshold (0.15), the color is adjusted:
391
+ ### 5a. Tangent Placement
286
392
 
287
- - **Light backgrounds** foreground colors are darkened and saturated
288
- - **Dark backgrounds** — foreground colors are lightened and saturated
393
+ ~25% of shapes are nudged toward the nearest previously-placed shape so their edges "kiss." The algorithm finds the nearest shape, computes the target distance (sum of half-sizes), and repositions the current shape along the angle between them. This creates organic clustering where shapes feel intentionally arranged rather than randomly scattered.
289
394
 
290
- This prevents the white-on-white and dark-on-dark readability problems that occur when light palette modes (pastel-light, high-contrast) combine with light background styles (solid-light, radial-light).
395
+ ### 5b. Shape Mirroring
291
396
 
292
- ### Size Distribution
397
+ Basic shapes (circle, triangle, square, hexagon, star, diamond, crescent, penroseTile, reuleauxTriangle) that are larger than 20% of max size have a ~40% chance of receiving a mirrored reflection. Four mirror axes are available:
293
398
 
294
- Shape sizes follow a **power distribution** (`Math.pow(rng(), 1.8)`) — producing many small shapes and few large ones, which creates natural visual hierarchy.
399
+ | Axis | Probability | Effect |
400
+ | ---- | ----------- | ------ |
401
+ | horizontal | 15% | Reflected below with inverted rotation |
402
+ | vertical | 12% | Reflected to the right with 180° rotation offset |
403
+ | diagonal | 8% | Reflected along 45° axis with 90° rotation offset |
404
+ | radial-4 | 5% | Four copies at 90° intervals around the center |
295
405
 
296
- ### Styling Per Shape
406
+ The mirror copy is drawn at 70% opacity and 95% size (decreasing for radial-4), creating a subtle symmetry effect without perfect duplication.
297
407
 
298
- Each shape receives:
408
+ ### 5c. Size Echo
299
409
 
300
- - **Semi-transparent fill** alpha between 0.2-0.7, creating watercolor-style blending where shapes overlap
301
- - **Color jitter** — ±8% RGB variation on fills, ±5% on strokes, so no two shapes using the "same" palette color are pixel-identical
302
- - **Positional color** — fill color is biased by the shape's canvas position, creating smooth color flow
303
- - **Glow effect** — 45% of sacred shapes and 20% of others get a `shadowBlur` glow (8-28px scaled), with glow color at 60% opacity
304
- - **Gradient fill** — ~30% of shapes get a radial gradient between two jittered palette colors instead of a flat fill
305
- - **Variable stroke width** — 0.5-2.5px scaled to canvas size
410
+ ~20% of shapes larger than half `adjustedMaxSize` spawn 2–3 trailing copies along a random direction. Each echo is progressively smaller (30% → 22% → 14% of parent size) and more transparent, creating a motion-trail effect.
306
411
 
307
- ### Recursive Nesting
412
+ ### 5d. Recursive Nesting
308
413
 
309
- ~15% of shapes larger than 40% of max size spawn 1-3 inner shapes:
310
- - Inner shapes are drawn at the parent's position with small random offsets
311
- - They use more complex/sacred shape types (layer ratio biased +0.3)
312
- - Sized at 15-40% of the parent
313
- - More transparent than the parent layer
414
+ ~15% of shapes larger than 40% of `adjustedMaxSize` receive 13 inner shapes. Inner shapes are selected from the palette via `pickShapeFromPalette` at the nested size fraction, and styled with their own affinity-aware render style.
314
415
 
315
- ## 8. Flow-Line Pass (Tapered Brush Strokes)
416
+ ### 5e. Shape Constellations
316
417
 
317
- 6-16 flowing curves are drawn across the canvas, following the hash-derived vector field:
418
+ ~12% of shapes larger than 35% of `adjustedMaxSize` trigger a **constellation** — a pre-composed group of shapes placed as a unit. The entire group is rotated by a random angle for variety. Five constellation types are available:
318
419
 
319
- - Each line starts at a random position and takes 30-70 steps
320
- - At each step, direction is determined by the flow field angle at that position plus slight random wobble
321
- - Lines stop if they leave the canvas bounds
322
- - **Tapered width** — each line starts at 1-4px and tapers to 20% of its starting width by the end, simulating a brush stroke that lifts off the canvas
323
- - **Tapered opacity** alpha also decays along the stroke, creating natural fade-out
324
- - Individual segments are drawn with `lineCap: "round"` for smooth joins
420
+ | Constellation | Description |
421
+ | ------------- | ----------- |
422
+ | flanked-triangle | Central triangle with two smaller circles on either side |
423
+ | hexagon-ring | 5–6 hexagons arranged in a ring |
424
+ | spiral-dots | 7–11 circles spiraling outward with decreasing size |
425
+ | diamond-cluster | 4 diamonds in a cardinal arrangement with progressive rotation |
426
+ | crescent-pair | Two crescents facing each other |
325
427
 
326
- The flow field is defined by:
327
- ```
328
- angle(x, y) = baseAngle + sin(x/w × freq × 2π) × π/2 + cos(y/h × freq × 2π) × π/2
329
- ```
428
+ Each member shape uses hierarchy colors with HSL jitter and affinity-aware render styles. Members that fall outside the canvas bounds are skipped.
429
+
430
+ ## 10. Render Styles
431
+
432
+ Each shape is drawn using one of 15 render styles:
433
+
434
+ | Style | Description |
435
+ | ----- | ----------- |
436
+ | fill-and-stroke | Standard fill + outline (default) |
437
+ | fill-only | Solid fill, no outline |
438
+ | stroke-only | Ghost fill at 30% opacity + full outline |
439
+ | double-stroke | Fill + thick outer stroke at 50% opacity + thin inner stroke in fill color |
440
+ | dashed | Fill + dashed outline (dash = 5% of size, gap = 3%) |
441
+ | watercolor | Multi-pass: base wash (scaled up 8%), radial-bleed offset washes, edge darkening via inner lighter fill, delicate thin stroke |
442
+ | hatched | 30% opacity fill + clipped cross-hatch lines (parallel + optional perpendicular) + 50% opacity outline |
443
+ | incomplete | 25% opacity fill + long-dash stroke simulating a partially drawn outline (60–85% completeness) |
444
+ | stipple | Ghost fill at 15% + clipped dot grid with jittered positions and variable dot sizes |
445
+ | stencil | Negative-space cutout: fills a bounding rectangle, then erases the shape via destination-out compositing |
446
+ | noise-grain | 25% base tint + clipped procedural noise (random black/white dots at 15–50% opacity, variable sizes) |
447
+ | wood-grain | 20% base tint + clipped parallel wavy lines at a random angle, simulating wood texture |
448
+ | marble-vein | 35% soft base + clipped branching vein lines that drift and fork, simulating marble stone |
449
+ | fabric-weave | 15% ghost base + clipped interlocking horizontal and vertical thread lines at alternating opacities |
450
+ | hand-drawn | Fill + 2–3 wobbly offset stroke passes simulating a hand-drawn sketch |
451
+
452
+ ### Texture Fill Details
453
+
454
+ The 4 new texture fills (noise-grain, wood-grain, marble-vein, fabric-weave) all work by:
455
+ 1. Drawing a low-opacity base fill to tint the shape
456
+ 2. Clipping to the shape boundary via `ctx.clip()`
457
+ 3. Drawing the procedural texture pattern within the clipped region
458
+ 4. Adding a subtle outline stroke on top
459
+
460
+ **noise-grain** scatters random-sized dots (black or white) across the shape at variable opacity, creating a film-grain or sandpaper texture. Dot spacing scales with shape size.
461
+
462
+ **wood-grain** draws parallel wavy lines at a random angle. The wave frequency (3–8 cycles) and amplitude (1–4% of size) create organic undulation. Line spacing is ~3.5% of shape size.
463
+
464
+ **marble-vein** draws 2–4 main veins that drift randomly downward, with ~20% chance per step of spawning a thinner branch vein. This creates the characteristic forking pattern of natural marble.
465
+
466
+ **fabric-weave** draws horizontal threads at full spacing, then vertical threads at half-spacing offsets, creating an over-under weave pattern. The two thread directions use different opacities (55% vs 45%) and colors (stroke vs fill) for visual distinction.
467
+
468
+ ### Hand-Drawn Style
469
+
470
+ The `hand-drawn` style simulates a sketchy, imprecise outline:
471
+
472
+ 1. **Base fill:** Standard fill of the shape
473
+ 2. **Wobbly strokes (2–3 passes):** Each pass redraws the shape's outline with a small random offset (1–3px) and slightly varied line width, creating the impression of a hand tracing the same line multiple times
474
+ 3. **Opacity variation:** Each pass uses 40–70% opacity so the overlapping strokes build up naturally
475
+
476
+ This style works particularly well on organic shapes (circle, triangle, blob) where the wobble feels intentional rather than broken.
477
+
478
+ ### Layered Transparency / Glazing
479
+
480
+ ~20% of shapes receive **glazing** — 2–3 additional fill-only passes drawn immediately after the main shape:
481
+
482
+ - Each pass is progressively smaller (85% → 72% → 61% of the original size)
483
+ - Each pass is progressively more opaque (adding 5–10% opacity per pass)
484
+ - Only the fill is redrawn (no stroke), creating a pigment-pooling effect where the center of the shape appears richer and more saturated
485
+
486
+ This simulates the traditional oil painting technique of building up translucent layers to create depth and luminosity.
487
+
488
+ ### Motion / Energy Lines
489
+
490
+ Short directional line bursts radiate from shapes to suggest movement and energy:
491
+
492
+ - **Trigger:** Always for `dense-chaotic`, `cosmic`, `neon-glow`, and `bold-graphic` archetypes; ~25% random chance for others
493
+ - **Count:** 3–6 lines per shape
494
+ - **Length:** 8–20% of the shape's size
495
+ - **Direction:** Radiating outward from the shape center at evenly-spaced angles with ±15° jitter
496
+ - **Style:** Thin lines (0.5–1.5px) using the shape's stroke color at 15–35% opacity, tapering toward the ends
497
+
498
+ Motion lines are drawn after the main shape layers but before symmetry mirroring, so they participate in any bilateral/quad reflections.
499
+
500
+ ### Watercolor Detail
501
+
502
+ The watercolor style simulates wet media through 4 passes:
503
+ 1. **Base wash:** Shape drawn at 108% scale, 15% opacity — soft bleed beyond the boundary
504
+ 2. **Offset washes:** 4–5 passes with radial displacement (random angle, up to 5% of size) — organic edge irregularity
505
+ 3. **Edge darkening:** Shape drawn at 85–93% scale with lightened fill — simulates pigment pooling at boundaries where the inner area dries lighter
506
+ 4. **Delicate stroke:** Thin outline (60% of normal width) at 25% opacity
507
+
508
+ ## 11. Flow Lines
509
+
510
+ Flow lines follow a sinusoidal vector field defined by `flowAngle(x, y)`. The archetype's `flowLineMultiplier` controls count (0× = none, up to 4× = heavy).
511
+
512
+ Each flow line:
513
+ - Starts at a random position
514
+ - Takes 30–70 steps along the flow field (±0.3 radians jitter per step)
515
+ - **Variable color:** Interpolates between two hierarchy colors along the stroke length
516
+ - **Pressure simulation:** Line width oscillates sinusoidally (frequency 2–6 cycles, amplitude ±40%) to simulate pen pressure
517
+ - **Taper:** Width and opacity decrease toward the end (80% taper over the stroke length)
518
+ - **Branching:** ~12% chance per step (between steps 5 and N-10) to spawn a child stroke at ±0.3–0.8 radians, 40% width, 5–15 steps, 60% parent opacity
519
+
520
+ ## 12. Post-Processing
521
+
522
+ After all shapes, flow lines, and symmetry mirroring:
523
+
524
+ ### Noise Texture
525
+
526
+ Deterministic noise (separate RNG seeded from hash + salt 777) scatters single-pixel dots across the canvas. Density scales with canvas area (~1 dot per 800px²). Each dot is black or white at 1–4% opacity, adding subtle film grain.
527
+
528
+ ### Vignette
529
+
530
+ A radial gradient darkens the edges: transparent at center, ramping to 25–45% black at the corners. This draws the eye inward toward the focal points.
531
+
532
+ ### Organic Connecting Curves
533
+
534
+ Quadratic Bézier curves connect random pairs of placed shapes. The control point is offset perpendicular to the line between shapes by up to 40% of their distance, creating organic arcs. Count scales with canvas area (~8 per megapixel). Drawn at 6–16% opacity using hierarchy colors.
535
+
536
+ ### Color Grading
537
+
538
+ A `soft-light` overlay in a single hue (random, 40% saturation, 50% lightness) at low intensity (grade intensity × 25% opacity). This unifies the image's color temperature — like applying a photo filter.
539
+
540
+ ### Chromatic Aberration
541
+
542
+ Only for `neon-glow`, `cosmic`, and `ethereal` archetypes. The canvas is drawn onto itself with a small horizontal offset (±2px scaled) using `screen` compositing at 3% opacity. This creates a subtle RGB fringing effect at high-contrast edges.
543
+
544
+ ### Bloom
545
+
546
+ Only for `neon-glow` and `cosmic` archetypes. The canvas is redrawn with `shadowBlur` at 30px (scaled) and white shadow color, composited via `screen` at 8% opacity. This creates a soft glow around bright areas.
547
+
548
+ ## 13. Signature Mark
549
+
550
+ The final rendering step places a small deterministic **chop mark** (inspired by East Asian seal stamps) in the bottom-right corner of the canvas:
551
+
552
+ - **RNG isolation:** Uses a separate RNG seeded with a salt of 42, so the signature is independent of all other rendering decisions
553
+ - **Position:** Bottom-right corner with a small margin (3% of canvas size)
554
+ - **Size:** 1.5–2.5% of the shorter canvas dimension
555
+ - **Structure:**
556
+ 1. Outer circle ring (stroke-only) at 12–20% opacity
557
+ 2. 2–4 inner lines crossing the circle at unique angles derived from the hash, creating a distinctive geometric pattern
558
+ 3. Center dot at slightly higher opacity
559
+ - **Color:** Uses the accent color from the hierarchy at very low opacity so it's visible but never distracting
330
560
 
331
- ## 9. Noise Texture Overlay
332
-
333
- A dedicated noise RNG (seeded separately from the main RNG to avoid affecting shape generation) renders thousands of 1px dots across the canvas:
334
-
335
- - Density: ~1 dot per 800 square pixels
336
- - Each dot is either black or white (50/50)
337
- - Very low opacity (1-4%)
338
- - Creates subtle film-grain texture that adds organic depth
339
-
340
- ## 9b. Vignette
341
-
342
- A radial gradient overlay darkens the edges of the canvas, drawing the viewer's eye toward the center:
343
-
344
- - Strength varies by hash: 25-45% maximum edge darkening
345
- - The vignette begins fading at 60% of the canvas radius from center
346
- - Applied after noise but before connecting curves, so the curves remain visible at edges
347
- - Creates a natural "spotlight" effect that makes compositions feel more focused and photographic
348
-
349
- ## 10. Organic Connecting Curves
350
-
351
- Quadratic bezier curves connect nearby shapes:
352
-
353
- - Number of curves scales with canvas area (~8 per megapixel)
354
- - Each curve connects two shapes that were drawn near each other in sequence
355
- - Control points are offset perpendicular to the connecting line with random bulge
356
- - Drawn at low opacity (6-16%) with palette colors at 30% alpha
357
-
358
- ## Shape Implementations
359
-
360
- ### Basic Shapes
361
- Standard geometric primitives drawn as canvas paths (beginPath → moveTo/lineTo/arc → closePath). The draw pipeline calls `fill()` and `stroke()` after the path is defined.
362
-
363
- ### Complex Shapes
364
- More intricate geometry including:
365
- - **Platonic solids** — 2D projections with all edges drawn between vertices
366
- - **Fibonacci spiral** — iterative arc segments following the golden ratio
367
- - **Islamic pattern** — 8-pointed star grid at intersections
368
- - **Celtic knot** — bezier over/under weaving pattern
369
- - **Mandala** — concentric circles with radial lines
370
- - **Fractal tree** — recursive branching at ±30° with 0.7× length decay
371
-
372
- ### Sacred Geometry
373
- Mathematically precise sacred geometry patterns:
374
- - **Flower of Life** — 7 overlapping circles in hexagonal arrangement
375
- - **Tree of Life** — 10 Sephirot nodes with connecting paths
376
- - **Metatron's Cube** — 13 vertices (center + inner/outer hexagons) fully connected
377
- - **Sri Yantra** — 9 interlocking triangles at two radii
378
- - **Seed of Life** — 7 circles (same as Flower of Life, different scale)
379
- - **Vesica Piscis** — two overlapping circles
380
- - **Torus** — 2D projection of a torus via line segments
381
- - **Egg of Life** — 7 circles in tight hexagonal packing
382
-
383
- ### Procedural Shapes
384
- Hash-derived shapes whose geometry is generated from the RNG. Every hash produces unique shapes that don't exist in any other generation:
385
-
386
- | Shape | Algorithm | Hash Controls |
387
- |-------|-----------|---------------|
388
- | **Blob** | Smooth closed curve via quadratic bezier through 5-9 control points arranged around a circle | Number of lobes (5-9), radius jitter per lobe (50-100%) |
389
- | **Ngon** | Irregular polygon with independent vertex displacement | Side count (3-12), vertex jitter amount (10-50%) |
390
- | **Lissajous** | Parametric curve `x = sin(a*t + φ), y = sin(b*t)` | Frequency ratios a,b (1-5 each), phase offset φ |
391
- | **Superellipse** | `|x|^n + |y|^n = 1` rendered parametrically | Exponent n: 0.3 (spiky astroid) → 2 (circle) → 5 (rounded rectangle) |
392
- | **Spirograph** | Hypotrochoid curve `(R-r)cos(t) + d*cos((R-r)t/r)` | Inner radius ratio r (0.2-0.8), pen distance d (0.3-1.0) |
393
- | **Wave Ring** | Concentric rings with sinusoidal radial displacement | Ring count (2-5), wave frequency (3-14), amplitude (5-20%) |
394
- | **Rose** | Polar rose curve `r = cos(k*θ)` | Petal parameter k (2-7), producing k or 2k petals |
395
-
396
- ## Configuration
397
-
398
- All parameters are exposed via `GenerationConfig`:
399
-
400
- | Parameter | Default | Effect |
401
- |-----------|---------|--------|
402
- | `width` | 2048 | Canvas width in pixels |
403
- | `height` | 2048 | Canvas height in pixels |
404
- | `gridSize` | 5 | Base shape count = gridSize² × 1.5 |
405
- | `layers` | 4 | Number of rendering layers |
406
- | `minShapeSize` | 30 | Minimum shape size (scaled to canvas) |
407
- | `maxShapeSize` | 400 | Maximum shape size (scaled to canvas) |
408
- | `baseOpacity` | 0.7 | First layer opacity |
409
- | `opacityReduction` | 0.12 | Opacity decay per layer |
410
- | `shapesPerLayer` | auto | Override auto-calculated shape count |
561
+ The signature is unique per hash (different inner line patterns) but always recognizable as a chop mark, giving each generated image a subtle artist's stamp.