Audio (src/audio/), raw WebAudio, no samples or libraries:
- TechnoEngine: 128 BPM four-on-the-floor kick, off-beat hats, 2-bar 16th
bassline, 8-bar pad. Look-ahead scheduler (25ms timer, 100ms horizon) is the
beat authority — emits beat:tick with the SCHEDULED audio time, so consumers
can compare honestly. Replaces core/StubBeatClock at integration; same event.
Stale beats are resynced to the next downbeat rather than caught up: a
throttled/hidden tab otherwise dumps a 64-beat backlog onto one sample.
Music runs through the location lowpass; SFX bypass it and stay crisp.
- Sfx: 10 procedural one-shots + rain bed, one shared noise buffer, voices
self-disconnect on ended so a six-hour night doesn't accumulate nodes.
UI (src/ui/), reusable Phaser containers, no door/floor imports:
- Stamp (the signature interaction), Phone (Dazza thread + phoneTheatre),
DialogueBox (typed-out, drunk-typo render), Clicker (digit roll),
MeterHud (neon vibe / crowd-temp aggro / hype badge / 3 heat slots).
- JuiceDemoScene exercises every widget and SFX, with a log-mapped cutoff
slider and a DOOR/FLOOR toggle that routes through the bus.
Verified in-browser: the door->floor sweep ramps 250Hz->18kHz over 600ms,
monotonic and exponential (halfway lands ~2.1kHz, not the ~9kHz a linear ramp
would give) — that late bloom is what sells the door opening. Under a real
hidden tab, 52 consecutive beats scheduled with zero in the past, 75-98ms lead,
max one beat per wake.
main.ts touched to route J / #juice to the demo — outside lane ownership,
flagged for sign-off in LANEHANDOVER.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>