1. Seed generation
Seeds are generated client-side with crypto.getRandomValues (Web Crypto). The seed is a base32 string drawn from 80 bits of entropy. There is no server endpoint involved in any draw; the site works fully offline after first load.
2. Deterministic PRNG
The seed string is hashed with xmur3 to initialize a mulberry32 generator. We chose this pair because it is tiny, fast, well-distributed for shuffling, and — critically — reproducible across every JavaScript engine and device. For statistical sampling quality we run a Chi-square uniformity check on every release build; for cryptographic guarantees, see the disclosure below.
3. Fisher–Yates shuffle
All ordering operations use an inside-out Fisher–Yates driven by the seeded stream. Every permutation of the input is equally likely, and the permutation is fully determined by the seed — which is what makes draws replayable for verification.
4. Constraints
Grouping searches for an assignment satisfying hard constraints (keep-apart, keep-together) while minimizing historical pair repeats across up to 20 shuffle attempts, returning the best valid assignment. If no valid assignment exists within the attempt budget, the tool reports the rules as unsatisfiable instead of returning an invalid result. Manual edits are re-validated against the same constraint set.
5. Receipts
A receipt is the UTF-8 text seed / mode / result plus a checksum computed by re-hashing the receipt body. Receipts contain no personal data beyond what you typed, and are designed to be pasted into documents, chats and video descriptions.
Honest disclosure
Seeded PRNGs provide reproducibility, not cryptographic commitment. A party who fully controls the seed could in theory search for favorable seeds — which is exactly why your browser generates the seed, in front of you, and we never see it first. For draws where even the operator must not know the seed in advance, generate the seed live in front of all participants rather than preparing a draw privately.