Every one of the N = 900 spheres is a hash bucket. A real mobile A/B framework assigns each user to a bucket with a deterministic hash of their user ID and the experiment's salt:
bucket(user) = hash(user_id + experiment_salt) mod N
variant(user) = "treatment" if rank(bucket) < N · ramp/100
"control" otherwise
Because rank(bucket) never changes for a fixed salt, raising the ramp % can only ever move buckets from control into treatment — a user already in treatment is never sent back to control, and a user in control keeps seeing control until their bucket's rank crosses the new threshold. That's the "consistent assignment" property real experimentation platforms (feature-flag services, mobile SDKs) rely on to keep a user's exposure history clean throughout a test.
Deterministic hash mode shows exactly that: move the ramp slider and only the buckets sitting near the boundary change color — "Buckets flipped" stays small and proportional to the ramp step.
Naive re-random mode simulates a common implementation bug: re-rolling every user's coin flip on each deploy instead of hashing a stable ID. Move the same slider and most of the grid recolors at once — "Buckets flipped" spikes toward N, meaning thousands of real users would silently swap variants mid-experiment, corrupting whatever metric you're measuring.
New experiment rotates the salt, which reshuffles the rank of every bucket. This models running two concurrent, mutually-exclusive experiments on the same user base: experiment B's bucket ranks are uncorrelated with experiment A's, so a user's assignment in one test says nothing about their assignment in another.
"Actual treatment %" is the true fraction of the 900 discrete buckets currently in treatment, which only approximates the target ramp — the same finite-sample rounding a real experiment sees when N users don't divide evenly into a target split.