Every pair is live: move the real pointer over it. Numbers in captions were measured in Chrome Canary 159 with trusted CDP input (below); the counters on the page are yours. Each group's bar stays in view while you look: its controls change only that group. Values are examples, not proposed defaults.
Chrome Canary 159.0.8128.2 (Windows), trusted mouse and wheel input sent over raw CDP (Input.dispatchMouseEvent), own tab. Probe-page figures come from separate minimal pages; the demo figures come from this page with the same geometry. Lift counts depend on layout, so the two differ.
| Case | Result |
Card scrolled under a still pointer (instant scrollTop or a wheel step) | pointerover/pointerenter (and the mouse events) fire in the same task as the scroll; :hover matches one frame later; pointermove never fires. Each wheel tick wakes the card under the pointer. |
Same, smooth scrollTo (14 scroll events over about 235 ms) | Nothing during the animation; all events and the :hover change land about 59 ms after the last scroll event, at scrollend. Cards passed in between are never hovered. |
Card lifts itself (.card:hover { transform: translateY(-4px) }), pointer 2 px inside its bottom edge, 40 one-pixel moves 25 ms apart | Probe page: 41 to 48 enters across runs, about one per move. This demo: 47–48 enters, 48 leaves (3 repeats). |
Same, with transition: transform 150ms | Probe page: 18 to 23 enters. This demo: 21–23 (3 repeats). |
| Same, but the card stays put and an inner element lifts | 0 enters, 0 leaves |
| Pointer at rest 2 px inside the edge, no transition | Keeps toggling: 3–4 enters in the first 300 ms, 13 by 1.8 s on this page; the probe page settled after about 3 toggles. Where it ends (hovered or not) varied between runs. |
Hovered card scale(1.05) with z-index: 2, 4 px gap | Neighbor's getBoundingClientRect() unchanged; elementFromPoint just inside the neighbor's edge returns the hovered card |
Same scale on an inner layer with pointer-events: none | The neighbor keeps its edge |
| Fast sweep of one row here (10, 30, 60 px steps, about 0.7 px/ms) | Plain :hover grid wakes 3 each time; proposed grid wakes 0 |
| Settle on a card / slow pass at about 0.2 to 0.3 px/ms | Wakes after about 400 ms; 0 wakes at 150 ms. A slow pass wakes it once, after 400 ms |
| Handoff on, neighbor reached within the window / 500 ms after (window 300 ms) | Woken with no wait, and handoff chains across a sweep / not woken |
| Exit interrupted at 40% of the reveal | Transition: 0.89, 0.89 same tick, 0.48 next frame (reverses). Keyframe swap: 0.89, 1.00 same tick (jumps to open), then 0.79 |
Lift geometry: a target that moves slides out from under the pointer, so it toggles while the pointer sits in that band. A 4 px lift was measured; a 2 px lift has a 2 px band by the same geometry (not measured). The hit-target case was measured with z-index raised only.
Example values from the author's own surfaces, not proposed defaults:
| Surface | Wait before reveal | Speed gate | Exit |
| Portfolio cards (Persuade, shipped) | 400 ms | 0.6 px/ms | lingers 1200 ms, then exits in 280 ms |
| Dashboard metric card body (Operate, tuning playground) | 280 ms | 0.6 px/ms | |
| Narrow action strip on that card (tuning playground) | 100 ms | 0.6 px/ms | |
hoverIntent v1.10.2 defaults: interval: 100, sensitivity: 6, so it fires when the pointer moves under 6 px between 100 ms polls, roughly 0.06 px/ms.
Untested: Firefox, Safari, touchpads, touchpad inertia, a physical (smoothed) wheel, reduced-motion emulation, an unraised scale, the exit linger.