From 147730c9051309fa7e0d136fc8ef6e596ec6e26f Mon Sep 17 00:00:00 2001 From: Tanish Manku Date: Thu, 10 Sep 2026 23:23:20 -0700 Subject: [PATCH] hero: the dispersion ring trails the reveal wave on its own delayed clock The chromatic flare front now launches Flare lag seconds (0.2) after the reveal front and sweeps the already-revealed field behind it as a second pass, instead of riding fused to the reveal edge. Claude-Session: https://claude.ai/code/session_01YBoaBEt3gynzTwogBFtn4B --- .../landing/hero-galaxy-tunables.ts | 10 +++++++++- .../src/components/landing/hero-galaxy.tsx | 20 ++++++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy-tunables.ts b/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy-tunables.ts index 77e1b9f160..bfef3506c1 100644 --- a/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy-tunables.ts +++ b/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy-tunables.ts @@ -184,7 +184,15 @@ export const galaxyMotionTuner = defineTunables( max: 0.15, step: 0.002, default: 0.05, - info: "Dispersion flare riding the wave front — cards flash chromatic as the reveal crosses them.", + info: "Dispersion flare of the chromatic ring trailing the reveal wave — cards flash as it crosses them.", + }, + waveLag: { + label: "Flare lag s", + min: 0, + max: 1, + step: 0.05, + default: 0.2, + info: "How far behind the reveal front the dispersion ring launches — it sweeps the already-revealed field as a second pass.", }, perfFloor: { label: "FPS floor", diff --git a/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy.tsx b/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy.tsx index ee4a7bdfaf..009f1cbed6 100644 --- a/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy.tsx +++ b/frontend/apps/artcraft-website-next/src/components/landing/hero-galaxy.tsx @@ -745,6 +745,12 @@ function GalaxyScene({ (introClock.t - iv.cardsAt) / Math.max(0.1, mv.introDur), ); const waveEase = easeOutCubic(rollT); + // The dispersion ring launches on its own delayed clock, trailing the + // reveal front and sweeping the already-revealed field behind it. + const flareT = clamp01( + (introClock.t - iv.cardsAt - mv.waveLag) / Math.max(0.1, mv.introDur), + ); + const flareEase = easeOutCubic(flareT); const burstT = clamp01( (introClock.t - iv.cardsAt) / Math.max(0.1, mv.burstDur), ); @@ -1126,13 +1132,17 @@ function GalaxyScene({ // dispersion flash riding the front itself (waveG). let waveK = 1; let waveG = 0; - if (rollT < 1) { + if (rollT < 1 || (flareT > 0 && flareT < 1)) { const rr = L.b * (L.thetaBirth + c * (L.thetaExit - L.thetaBirth)); - const waveR = waveEase * L.b * L.thetaExit; const band = Math.max(1, mv.waveBand); - waveK = clamp01((waveR - rr) / band + 1); - const fr = (rr - waveR) / band; - waveG = Math.exp(-fr * fr); + if (rollT < 1) { + const waveR = waveEase * L.b * L.thetaExit; + waveK = clamp01((waveR - rr) / band + 1); + } + if (flareT > 0 && flareT < 1) { + const fr = (rr - flareEase * L.b * L.thetaExit) / band; + waveG = Math.exp(-fr * fr); + } } const ready = videos[card.clip].readyState >= 2 ? 1 : 0;