diff --git a/ANDROID.md b/ANDROID.md
index 6d7ade2..61391ea 100644
--- a/ANDROID.md
+++ b/ANDROID.md
@@ -68,6 +68,37 @@ transform (the small art flies to the big one). The player's scrubber is the
lane itself, no knob. Motion is Material 3 Expressive's springs, sampled into
`linear()`. Reduce motion (You → Appearance, or the OS setting) turns it off.
+The activity declares no `screenOrientation` and handles `orientation` and
+`screenSize` itself, so turning the phone over is a resize and nothing else —
+the audio thread, the stack and the screen's scroll all survive it, and the
+layout is the only thing that has to answer. Two media queries do that. The
+player sheet is the one surface whose portrait shape cannot survive a wide
+viewport: its artwork is a square sized by WIDTH, so at 915×411 the cover came
+out 879px tall and the title, the lane, the transport and the face buttons sat
+below the bottom of a sheet that does not scroll — a corner of the cover and no
+way to pause. Sideways it is two columns: the head across the top, the cover
+down the left sized by HEIGHT, and the track, the scrubber, the transport and
+the faces stacked on the right. With lyrics or the queue up, the face takes the
+cover's column and the thumbnail goes — the record is already the ground behind
+the whole sheet. That is an aspect problem rather than a height one, so the rule
+keys off `orientation: landscape` alone and a tablet gets the same two columns.
+
+The rest is a phone-sized query (`max-height: 560px`). The nav comes down to
+Android's own 48dp minimum and the mini bar to a 60dp row over the same lane
+strip, which gives the page back 22 of a 411-pixel screen — the chrome was 46%
+of the height, it is 40%. The artist hero stops being a 300px portrait, which
+covered its own Play button with the mini bar, and becomes a 190px banner: what
+the desktop's hero has always been. The record head puts the cover beside the
+title rather than above it, again the desktop's own shape, so Play is in view
+without a scroll. A half sheet may take all but 36px of the height instead of
+76% of it. Everything else — the grids, the rails, the artwork viewer, the
+tap-to-sync room, the chat composer — already answered to width and was left
+alone. `viewport-fit=cover` means the cutout and the gesture pill come in from
+the SIDES in landscape, so the shell reads `--inset-left` / `--inset-right`
+beside the top and bottom ones now. Those rules are appended at the end of
+`shell.css` on purpose: they have to come after `.gbar`'s padding, `.mini`'s
+and `.toast`'s left/right to win at equal specificity.
+
## Search and the resolver
Search is the desktop's top bar: the field asks the **catalog** once the
@@ -631,14 +662,20 @@ a catalog card's and the record page's sheets → the now-playing Save →
a peer's sheet, a raw file's sheet, a user's shares browsed and a folder
of theirs streamed → a buddy's sheet → You (every switch and chip saved
and read back from the config) → recent searches and a spelling
-suggestion → the sleep timer, asserts what each step should show, screenshots every step into `tests/mobile/out/`, and fails on
+suggestion → the sleep timer → the phone turned sideways (the player's three faces, a
+record with a long sheet over it, an artist page, and the side insets faked,
+all at 915×411) and back, asserts what each step should show, screenshots every step into `tests/mobile/out/`, and fails on
any exception or console error. The mock answers every command the phone
uses; one it does not know is named in the report (`[mock] no mock for X`)
rather than surfacing as a TypeError toast, console warnings carry their top
frames (the smoke bundle is built unminified for that), and every probe
carries the history mirror — the entry's depth against the layers the app
says the back gesture can peel (`hd`/`hwant`; a drift is how the blank
-page after a confirmed delete was found).
+page after a confirmed delete was found). A mock step can also set the
+viewport — `{ view: [915, 411] }` sends `Emulation.setDeviceMetricsOverride`
+through the same client, which is how the walk turns the phone over and back;
+the phone walk refuses one, because a real device's orientation is not the
+harness's to set.
The phone walk is the same driver on the real thing (plus a step kind of
its own: `{ adb: [...] }` runs an adb command — the share-sheet intent, a
diff --git a/src/mobile/Sheet.svelte b/src/mobile/Sheet.svelte
index 5ab98c5..60f6011 100644
--- a/src/mobile/Sheet.svelte
+++ b/src/mobile/Sheet.svelte
@@ -141,7 +141,7 @@