Files
punktfunk/clients/apple/Sources/PunktfunkClient
enricobuehler 8ab4918923 fix(apple): the host strip stopped flashing as it settles
Reported from the iPad: the cards arrive, come to rest, and then flash. They
did — and it was not the motion. Every card sat at the WRONG fill for as long
as the entrance animation ran, then snapped to its real one in a single frame
once SwiftUI tore the animation down, roughly a third of a second AFTER the
last card had stopped moving.

`rotation3DEffect` was the cause. A real 3D transform renders its subtree
through an offscreen layer, and these cards carry translucent glass, which
resolves differently in there — so the strip showed the aurora through itself
for the duration and went opaque the instant the layer was dropped.

Measured on an iPad Pro 13", sampling the centred tile: it held #4a3d87 across
twelve frames in which nothing moved, then stepped to #423970 — 23/255 of blue
in one frame, on every card at once, while the backdrop beside them stayed
exactly #713fa0 throughout. Stretching the timeline from 1.02 s to 2.82 s moved
the step from 0.70 s to 2.50 s after launch: the same 0.32 s before the end in
both runs, which is what proves it is the animation ENDING and not any state
the tiles were waiting on. Deleting the rotation deleted the step outright.
`compositingGroup()` above and below the transforms each changed nothing, so
this is the 3D layer specifically, not compositing in general.

The turn is now projected instead of rendered: cos(angle) as a horizontal
squeeze IS the orthographic projection of a Y-axis rotation, hinged on the edge
the card fans from — which also puts the code behind the doc comment that
already described the fan that way (the sign of a rotation carried it before;
cos is even, so the anchor has to). Affine, so there is no offscreen pass and
no layer to drop. What's lost is the perspective trapezoid, which at card size
was never what sold the motion; the fan-out, the stagger and the overshoot are
untouched.

Also drops the temporary PUNKTFUNK_DIAG_OPEN hook that gated each step of this
branch in the simulator.

284 tests pass; macOS + tvOS typecheck; entrance re-recorded on the iPad Pro
simulator — the tile now settles monotonically (#4153cf → #383c77 → #39396e →
#393a6e) and holds, with the fan-out still reading as a turn.
2026-08-10 09:36:02 +02:00
..