Tuner (see TUNER.md): a draggable, collapsible dev panel rendering every
group registered via defineTunables() as slider + number-input rows.
- Live: physics/light/material/halo values are read per frame; formation
values trigger a debounced re-sample
- Values persist to localStorage; modified labels tint accent; Copy puts a
JSON snapshot on the clipboard for baking back into defaults; Reset clears
- Shown in dev builds or with ?tuner=1; drag position and section collapse
state persist
- Policy (documented): every new tweakable constant registers with the tuner
by default
- Hero groups: Formation, Physics, Cursor & Light, Material, Halo
Formation: the hex lattice read too uniform. Balls are now placed by
multi-pass dart throwing over the glyph mask — big balls claim spots first,
smaller ones settle into leftover gaps, random depth within the slab, 3D
overlap rejection via spatial hash — a faked settled-pile impression, not a
physics solve. Stroke-margin test keeps big balls inside the letterforms so
the type stays crisp.
- Ball sizes now vary organically: smooth spatial value noise drifts size
clusters across the word, white noise roughens per ball; the neighbor cap
keeps every draw collision-safe
- Radial halo billboard tracks the cursor BEHIND the text plane, so balls
silhouette against the glow (additive in dark, soft accent wash in light)
- Cursor point light switched to physical inverse-square falloff (decay 2):
balls near the cursor are genuinely brighter; the light dims to 30% when
the pointer leaves so the resting state stays moody
- Dark mode is an eclipse rig: near-black lacquer balls (clearcoat physical
material), almost no front light, cool key + counter rim from behind, and
no environment map — scene.environment floods instanced materials at full
strength regardless of envMapIntensity, which was washing the whole word
to gray; light mode keeps the procedural room reflections
The hero brand mark is now the signature interactive moment: 'artcraft'
rasterized per-glyph (manual advances so no ligature shaping), sampled onto a
jittered close-packed lattice 2-3 layers deep, and rendered as instanced 3D
spheres under a perspective camera fitted so world units equal CSS pixels at
the text plane.
- Cursor is both a point light and a push force (radial + swirl, quadratic
falloff, toward-viewer pop); balls scatter, then rejoin on home springs
- Per-ball radii capped at half the nearest-neighbor gap, plus a 3D
spatial-hash collision pass, so spheres never clip through each other
- Mount plays an assemble: balls fly in from a scattered shell
- Idle: light wanders a slow Lissajous path; balls breathe subtly
- Fallbacks: static display-type wordmark for SSR/crawlers, reduced motion,
and WebGL failure; theme-aware colors via shared token watcher (extracted
to lib/theme-colors, now also used by the blocking/render comparator)
- Tagline 'Controllable AI for artists.' remains the crawlable h1
Standalone Next 16 app at frontend/apps/artcraft-website-next (excluded from
the npm workspace like artcraft-dashboard; React 19 + R3F 9 + GSAP + Lenis +
Tailwind 4). Branched from design/prototype0; the Marathon-style navbar is
ported to next/link with theme-aware tokens plus a light/dark toggle.
- Design system: hairline-grid 'instrument panel' language; light (blueprint
paper) + dark (viewport terminal) themes via CSS tokens, system-pref default
with persisted override applied pre-paint
- Landing: hero, capability ticker, feature grid (real product footage),
ownership, made-with (click-to-load YouTube), CTA, footer — all crawlable
SSR HTML; GSAP reveals are progressive enhancement only
- 3D hero: interactive blocking↔render comparator — wireframe R3F set clipped
over the product reel by a cursor-driven scan line; degrades to plain video
on reduced-motion/coarse-pointer/WebGL failure
- SEO: metadata + OG, sitemap.ts, robots.ts, SoftwareApplication JSON-LD