Scale the combo FX with cascade depth (mv.rounds.len) — the same depth the
cascade SFX (play_cascade) steps up on — so deeper cascades read as more
exciting and land in lockstep with the audio escalation. Purely visual and
self-pruning: no board / score / move state changes, and input stays gated by
BoardAnim.active alone.
- board_fx.sx: add fx_combo_level (mirrors audio's cascade_cue_index clamp:
depth<=1 -> floor, depth>=5 -> ceiling). The +points popup now carries the
cascade depth and grows one font step + lerps gold -> hot-gold per level
(fx_popup_font / fx_popup_color). Every burst of a deep cascade gets a
whole-move depth boost (FX_BURST_DEPTH) on top of the existing per-round bump.
- board_view.sx: render_fx_popups derives styling from depth and tops a combo
with a "COMBO xN" label naming the true cascade depth.
- tests/fx_combo.sx: headless snapshot locking the depth->level/font table and
asserting fx_combo_level matches the cascade-cue index column entry-for-entry.
- goldens/p11_combo_deep.png + README: deterministic depth-5 capture (M3TE_FX=11)
vs the depth-1 single clear (M3TE_FX=3); FX gone after settle at a later phase.
Visual-juice vibe-pass, FX-only — no logic/state changes, input gating
still owned by BoardAnim.active.
- board_fx.sx: bigger, punchier match bursts — peak size 1.95->2.50 cells,
combo bonus 0.55->0.72, and the per-gem fx tints saturated a touch (low
channel trimmed, dominant/mid lifted) so every burst pops as a brighter,
more vivid candy colour. The hot per-pixel tint loop's hoisted locals are
preserved (issue 0001).
- gem_anim.sx: snappier clear pop — faster rise (0.30->0.18 of the window)
to a bigger overshoot (CLEAR_POP_A 0.22->0.34) so the matched-gem clear
reads as a candy snap. gem_pose's clear-pop invariants still hold.
- main.sx: M3TE_FX=<n> deterministic match-FX capture hook, mirroring the
M3TE_SELECT pattern. Commits the n-th currently-legal swap at startup via
the normal plan_and_commit path and begins the move timeline + burst/popup
FX; M3TE_ANIM_TIME pins the phase and the frame loop holds the move/FX
frozen while pinned, so the burst + "+points" screenshot identically every
run. A larger M3TE_ANIM_TIME captures the settled, FX-gone board. Startup-
only and guarded, so normal play is untouched.
- README.md: document the new M3TE_FX pin alongside the other capture hooks.
- goldens/p6_fx_match.png: updated deterministic golden (iOS 26 sim,
SIMCTL_CHILD_M3TE_FX=3 SIMCTL_CHILD_M3TE_ANIM_TIME=0.22) — the vertical
red 3-match, burst region +1.4% mean luminance / 3.2:1 brighter:dimmer vs
the same scene on the pre-juice constants.
Gate: ios-sim build links, 19/19 logic tests green (incl. gem_pose t=0 rest).
Add a purely-visual, transient juice layer over a committed move — score
popups + a tinted particle/flash burst at the clears — with no change to the
model, score, moves, or settled board.
- assets/fx/particle.png: key the painted transparency checkerboard out of the
provided particle art to real alpha (8-connected border flood fill +
smooth luminance falloff that preserves the soft glow), downscaled to a
256x256 RGBA white sparkle. tools/key_particle.sx is the reproducible tool.
- board_fx.sx: BoardFx (live particle bursts + one "+points" popup) and
BoardFxAssets. The engine image path samples texture*white (no draw-time
tint), so the white sprite is tinted per gem colour at LOAD time into one
texture per colour; a burst animates by scale (grow -> shrink) and the soft
texture edges carry the fade. Combos (cascade depth > 1) burst bigger and the
popup is larger + gold. All driven by delta_time and self-pruning.
- board_anim.sx: AnimMove carries the model's cascade.awarded so the popup
shows the real payout without re-deriving any scoring in the view.
- board_view.sx / main.sx: wire BoardFx + the tinted assets, tick each frame,
spawn on a legal commit, and render bursts (clipped to the grid) under the
popups (drawn on top). Input-lock (BoardAnim.active) is untouched; FX never
gate input and may outlast the move slightly before vanishing.
Goldens (iPhone-17-class sim, iOS 26): p6_fx.png (combo: gold "+480" + bursts
mid-cascade), p6_fx_match.png (single match: "+30" + red burst), p6_fx_after.png
(settled board, FX fully gone). Gate: ios-sim build links, 15/15 logic tests
green (scoring/cascade goldens unchanged).