Stage 1 · roll axis only

Keep the window
level with the world.

Gravity is the reference. The accelerometer reads which way is down — absolutely, without drift. The gyroscope fills the gaps between those readings, because gravity gets buried in noise the moment the phone is moving.

Browsers disagree about which gyroscope channel carries which axis, so the first thing this does is watch your motion and work it out. Rock the phone side to side when it asks.

deg roll
axis —
Accel
Gyro int
Zoom
Rate Hz
Gravity clean
Roll observable
Angle source

Accelerometer anchors the angle, gyroscope smooths it. This is the one you ship.

Gyro roll channel

Detecting…

The spec puts the screen-normal rate in α, but WebKit maps its channels straight onto CoreMotion's x/y/z, so on iOS it lands in γ and α carries pitch. Auto settles it by correlating each channel against the accelerometer's own roll rate.

Framing
0.80 s

Time constant of the complementary filter. Short reacts fast and shakes; long is glassy but lags.

Content & gravity

Gravity sign: normal.