Pointer routing stays generic
listenPointerDrag owns pointer capture, identity, end, and cancellation. The new gesture utility layers click-versus-drag classification on top rather than duplicating routing.
if (!state.dragged && deltaSquared >= threshold ** 2) {
state.dragged = true;
onDragStart(event, gesture);
}
if (state.dragged) onDragMove(event, gesture);