diff --git a/PROJECT.md b/PROJECT.md
index fd06493..54df9c7 100644
--- a/PROJECT.md
+++ b/PROJECT.md
@@ -493,6 +493,35 @@ it in one of the pauses") — the first cut rode the incoming ball, at the momen
least attention to spare. Touch only, rally modes only, and the tap lesson wins if both qualify:
teaching placement to someone who cannot reach the ball is the wrong lesson.
+**...and its LENGTH is its strength** (2026-08-18). Oliver: *"the flick to aim sometimes is applied
+very strong, sometimes it barely does anything. this leads to a lack of agency, the player can't
+really tell if there was skill or luck."* He was right and it was the gesture reader, not the feel:
+the rally flick was quantised to THREE LANES (`ax`, a swipe past 0.38 of its own length sideways),
+so two neighbouring gestures differed by the whole court and nothing lived in between. `gameplay.
+swayOf` reads the swipe's length as a continuous 0..1 (`TUNE.flickMin`..`flickFull`, px) exactly as
+the SERVE already did, and `doHit` spends that instead of `ax`. Keys have no length, so they keep
+the full lane, and the AI's aim (no `mag`) is untouched.
+
+**This is also what hands the OUT back to the player.** Oliver: *"the number one reason i die is
+that i myself keep firing balls into the out."* Going out was never his choice — every aimed shot
+took the FULL width and then `err()` on top, so the dice decided. Width follows the swipe now, so
+the risk band has a floor the player can stop short of: **below `(line - aimError) / (flickWidth *
+flickReach)` ≈ 0.7 of a full swipe, the worst mistiming in the game cannot put the ball out**, and
+above it the old risk curve is untouched. The tested contract from the pass before this one still
+holds — a perfectly timed flick never sails, a badly timed full one can.
+
+**THE AIM IS DRAWN WHILE THE THUMB IS STILL MOVING.** Oliver asked to *"visualize the strength of my
+flick at flick-time"*, and he was asking for the half the placement ring cannot give: the ring is a
+RECEIPT, it arrives with the ball already gone. `G.swipe` (set by input.js during the drag, cleared
+on release) draws the same target ring live, plus a RAY from the player's feet — the ring alone sits
+deep in perspective and 300 ms is not long enough to go looking for it. Cream while the ask is safe,
+`UI.hot` once the sway crosses that derived threshold: the colour is the answer to "was I too hard".
+Only inside the window where a release would still BE a flick (`FLICK_MS`/`TUNE.flickMin`, the same
+gate `endTouch` uses) — past that the gesture is a run and a target hanging off it would be a lie.
+Rally modes only (`rallyFeel`); gore's flick free-aims at a body, not at a lane. The placement ring
+turns `UI.bad` when the shot really is out, so the two rings together ARE the lesson: what you asked
+for, what your timing gave you, and the difference between them.
+
**The umpire and the boy.** `aside()` refused during any interlude and the match runs on a permanent
one, so he was silently muted for the entire mode — the one mode that is literally a tennis match he
is sitting over (`G.interlude && !G.match` now, the same shape as `sendBoy`). Six dry lines: two on
diff --git a/index.html b/index.html
index 525b60e..85d1dbc 100644
--- a/index.html
+++ b/index.html
@@ -659,6 +659,6 @@ if (location.hostname !== 'splatter-tennis.wuwi.one') {
-
+