Grid layout transitions — v3 sketch (Firewatch Camera Grid)

**Note** from Bead: Firewatch Camera Grid · [canonical source](https://redfish.acequia.io/guerin/.agents/65783732-7907-4a36-983a-3b015e75e80b/2026-06-23/notes/04-grid-layout-v3-sketch.md) · session 2026-06-23 · discussion: Talk: Firewatch Camera Grid

Sketched by Debbie (senior UX/UI). v3 is a demo-ready advance on the [v2 convergent sketch](./03-grid-layout-v2-sketch.md), still in the sketch-ux house style (rendered HTML/SVG, "✎ SKETCH" marker, replay-able transition). It honors the full ratified spine — spatial morph, select-on-map → fly frustum→tile → return, distinct grid⇄map fullscreen + to/from panel mode, segmented `Grid | 3D | Map` toggle, 180°-aware auto-order plus hand-rearrange, preserved selection + amber time-cursor — and pushes three things forward. **Rendered sketch:** https://redfish.acequia.io/guerin/.agents/65783732-7907-4a36-983a-3b015e75e80b/2026-06-23/artifacts/sketches/grid-layout-transitions-v3.html

## What's new vs v2 1. **Resolved the open sub-question (drag-rest) — and it works live.** v2 left three forks for "after a manual card-drag, what happens to the rest?" v3 picks **re-flow the rest** and demonstrates it: when you drag a card it becomes a **pinned anchor**, and every **unpinned** card re-derives its 180°-aware (azimuth) slot in the remaining gaps, flashing a brief green outline so the re-flow is legible. `reflowAroundPins()` is the resolved policy; the tour drags a card to slot #1 and you watch the others re-order without crossing the line of action. 2. **Folded in shipped reality (OrientedMap + tie-point read-through).** The selection map draws the real OrientedMap glyph set, and the **selected camera's red tie-point cast-ray reads through into its grid card face** (`miniFrustum` now renders the camera's `ray` offset as a red ray on the tile, alongside the blue frustum + green centerline). The grid is visibly *the same oriented cameras, just assembled* — selection feels continuous from map dot → card. The time-cursor wobbles the poses and the tile faces repaint with it, so the card and the map agree. (Still a layout-transition demo — not the full tie-point UI.) 3. **3D selection is real enough to demo, and you can return to 3D.** The tour now **starts on the oblique 3D map**, selects there, captures `returnView = 3d` at fly time, and the **fly-back lands in 3D** (not only 2D). The segmented toggle's `3D` button flies grid→3D; `Map` flies grid→2D. A `◀ reverse` button replays the arc backwards (grid → fly to 3D → de-select).

## The resolved sub-question + why **Drag-rest = re-flow the rest.** Of the three v2 forks: - *Pin-only* keeps neighbors put, but that silently **breaks the 180° guarantee** for the cards you didn't touch — after any swap, unpinned neighbors can end up crossing the line. - *First-drag-locks-all* throws auto-ordering away on the first manual move, which **contradicts the ratified "auto, then hand-tweak"** (it makes auto a one-shot, not a living default). - *Re-flow the rest* is the only policy that **keeps both promises**: your pin is honored as a fixed anchor, and the rest stay 180°-correct by re-deriving around it. It's also the least-surprising mental model — "I moved this one; the system kept the rest sensible." So re-flow is shown as the working default, not posed as a fork.

## The single remaining fork (answerable in the sketch) **How does a pinned card release back to auto?** Re-flow is settled, but the release gesture isn't. The card on the right rail PUTs the chosen fork to the handler `request/` dock as a `sketch-answer` request object (with `resolved.drag-rest = reflow-rest` carried along): - **Per-card un-pin** — each pinned card's `✋#` badge is a toggle; click it and that one card rejoins auto. (Wired live in the sketch — click a pinned badge to try it.) - **Global "re-auto"** — one button drops all pins and re-derives the whole grid. - **Auto-release on re-select** — pins persist until the camera selection changes, then the grid re-derives fresh ("pins are for this selection"). (Also partly live: removing a camera drops its pin.) (Provisional sub-fork still forkable later, per the v1 ratification: keep the segmented toggle vs. add click-a-tile / gesture triggers.)

## Reused from the real app - **OrientedMap glyph vocabulary** (`apps/camera-grid/oriented-map.js`): blue wedge `#39c0ff`, green dashed centerline `#2ee06a`, red ray `#ff2d2d`, white-ringed dot — inline SVG on both the map and the tile faces, with the tie-point ray carried through. - **grid⇄map collapse** generalized from the app's `map-closed` / `panel-closed` flex-collapse. - **House style** from `plume.html` / `styles.css`: dark palette, amber accent, segmented toggle, the time strip.

## Status First-cut (one fork open). The drag-rest resolution and the 3D-return + tie-point read-through are demonstrated, not posed. Awaiting Stephen's pin-release choice via the `request/` dock.