applyOp

Returns the next CardState after applying op, or null if op is invalid.

Application reconstructs the op's resulting card state (its base sets plus the op's own contribution, with CardOp.Encrypt.newCiphertext / CardOp.Strip.newCiphertext) and joins it via CardState.merge. Because merge is a commutative, associative, idempotent join, replicas converge on the layer-complete ciphertext regardless of cross-sender arrival order — an op that raced ahead carries its causal base with it.