- Orbs rise from below the bottom edge to above the top edge, each with
its own 36-68s pass (slower on phones), a negative delay (scene already
populated on load), own horizontal position, a gentle sway and a slight
scale drift; opacity fades in/out at the edges so the loop never pops.
- Only transform + opacity animate, each orb on its own composited layer
(will-change: transform); no filter/backdrop-filter, nothing animates
size/offsets/shadow. The glacier blobs are untouched.
- Opacity lowered ~38% in both themes: 0.55->0.34 light, 0.8->0.5 dark,
phone overrides 0.32->0.2 / 0.42->0.26.
- prefers-reduced-motion: rise removed, orbs return to the old static
placements (a paused-from-start CSS animation is not applied in Chrome
and would park them below the fold); tab hidden: a visibility listener
parks the whole scene (.ice-paused), blob drift included.
- Measured with a CDP perf trace on a 4x throttled phone profile: p95
33.4ms, 0 frames over 34ms, no long tasks - identical to the pre-change
baseline; ~0.6% extra main-thread CPU. Desktop stays compositor-bound
from the pre-existing blob drift, as before. tests/bubble-perf.mjs
keeps it repeatable.
- New bubbles suite (34 checks) in the repo harness; the axe contrast
matrix is now 16 runs (360/390/1280 x dark/light x EN/CS) and passes.
- SW cache -> freezmo-v31; README decision 46.
Full suite: 11/11 suites, 424 checks.