# Design pass 10: phone polish on Now, Situation, Board and Market

Built on copies of the pass 9 files (`design-pass9-2026-09-27/d2-tracks/`). The rule held: frozen strings stay, and only the phone layout changes. At 1280, `document.body.innerText` is byte-equal to pass 9 and every header, nav, head, clock, rail, row, card and footer box is within 1 px of pass 9, at live, 16:57Z, 16:42Z and, on Board, 17:15Z, with and without an entry (checks in (c)). Every change sits inside a `max-width:820px` media query or is phone-only markup that is `display:none` on desktop. Pass 10 is the proposal beside pass 9. Whether it replaces pass 7's phone form on the frozen Now is Thomas's call.

## (a) What changed per page, and departures from the frozen specs

**First read of the pass 9 phone shots: what looked like "the desktop instrument compressed onto a phone"**
- **Now** (`now-phone.jpg`, 2742 px tall): every row printed eight blocks at once: identity, pill, sentence, Latest, clock, a two-line readout in 12 px grey, For you, plus the checkpoint clock. The readout and Latest lines were the fine print the reviewer means. The nine-line legend under the list was taller than a row. The `Powered by CoinGecko` mark had a 24 px hit box. The rail times and `Market time` were 11 px.
- **Board** (`board-phone.jpg`): each card stacked the delta line, two change lines and `and N more` before the identity, so the token name sat in the middle of the card. The legend had ten lines. The rail times were 11 px.
- **Situation** (no pass 9 phone shot; I took one at 390): it was the desktop stacked. A six-number metric grid came between the sentence and the clock. The seven lane-name buttons were 16 px tall. `Pin A` was 20 px, Play and Back 26 px, the address, copy and vendor links 28 px, and `View all observations` 21 px. Lane labels and ruler text were 10.5 to 11.5 px.
- **Market** (`market-phone.jpg`): the cards read well. The only issues were the 11 px clock label and rail times.

**Now (phone).**
- The row follows reviewer 20's order: (1) identity (symbol, name, `~$X · ±N% since seen`, caption line), (2) state pill with its descriptor (tap for Why here, as before), (3) the sentence, (4) the Mini Clock, (5) For you, with a `Details` control at the right of the same line.
- `Latest: …` and the exact readout (`price · entered · profiled · attention · holders/top 20 · safety`) moved into a bottom sheet. It opens from `Details` or a tap anywhere on the row. The sheet also holds `Open Situation` and `Copy address`, the desktop hover actions, which pass 9 hid on the phone. Result: the page is 2150 px tall at 390, down from 2742.
- On the phone a row tap now opens the sheet, not Situation. `Open Situation` is the sheet's first button, and the For you link still opens Situation compare directly.
- Legend: a single 44 px line (the first seven glyphs plus `Legend`) that opens to the full legend.
- Strip: the `Powered by CoinGecko` hit box went from 24 px to 36 px.
- Type floor: `Market time`, `Following`, `Why here` and the rail times went from 11 or 11.5 px to 12 px. Play and Copy link are now 32 px.
- **Fine labels the brief names.** On pass 9's phone Now, the column head (`Situation · 60 min`, `16:27Z`, `17:27Z`) was already hidden, and Now's rows carry no checkpoint label. So nothing was removed here beyond Latest and the readout. Both are one tap away in the sheet.
- **Mini Clock expansion: not built.** At 390 the clock is already the full width of the row (330 px), so expanding it would add nothing. A taller sheet clock is listed in (e).

**Board (phone).**
- The card keeps pass 8's six elements. The delta line stays first and visible.
- The top changes and `and N more` move into the same sheet as Now, opened by `Details` at the right of the actions row or a tap on the card. The sheet repeats the delta line as its heading, and the `and N more` link keeps its target.
- The intact line (`Nothing material since your look; still …` / `Reasons at entry still hold: …`) stays on the card, because it is one short line and is element 2 itself.
- The delta-line link sits above the card-tap layer, so it still opens compare directly.
- Group toggle (`Archived`) is now 45 px. The legend is one line, as on Now. Type floor as on Now.

**Situation (phone).**
- Order: identity, then the state, sentence and the since-you-looked chip, then the clock (the ruler and the seven lanes, then the `Now · Situation` panel), then the six-number metric grid, then the sections.
- Every control is 32 px or more: address, copy and vendor links 36 px; state heading 36 px; chip 36 px; Play and Back 32 px; lane-name buttons 34 px; `Pin A` has a 34 px hit area (its drawn size stays 20 px, so the moment tag does not cover the ruler labels); the moment tag has a 34 px hit area; `Pin A` and `Copy link` in the panel are 32 px; `View all observations` is 36 px.
- All SVG lane and ruler text is at least 12 px.
- The compare table and the reads table scroll inside their own box. The page never scrolls sideways (scrollWidth equals the viewport at every moment).

**Market (phone).** Only the type floor changed (the clock label and rail times, 11 to 12 px). The vendor links in the caption were already 35 px or more, and the About summary is 52 px.

**Departures from the frozen specs, with the reason and the reviewer line.**
1. **Pass 7 phone row, element (4) Latest and the readout inside (5).** On the phone they move behind one tap into the sheet. Reason: reviewer 20, "Then expose: exact readout, why here, latest event, supporting metrics on tap", and "reduce simultaneous fine-grained labels". No string is shortened or paraphrased; the sheet prints the same nodes.
2. **Pass 7/8 legend.** On the phone it is one line until tapped. Reviewer 20: "simplify legend presentation".
3. **Pass 8 phone card, element (2).** The top changes and `and N more` go into the sheet when there are changes. Brief, Board paragraph (from reviewer 20: "use popovers/bottom sheets for event explanation").
4. **Pass 7 phone row tap.** The tap target on the row changes from opening Situation to opening the sheet. Reviewer 20 wants the readout "on tap", and a row has only one tap. `Open Situation` is the sheet's first button.
5. **Situation order.** On the phone the metric grid moves below the clock. Brief ("identity, state, sentence, the clock, then the sections") and reviewer 20's sequence.
6. **Strip height: not reduced.** It stays four lines (94 px). Measured at 390 and 360: the three phrases (146 characters) take three lines on their own at 12 px. Flowing `Market`, the phrases, the clock and the mark inline at 12 px takes four lines. Three lines or fewer is only possible by truncating, which the brief forbids. A short phone form of the weather is asked for in (e).
7. **Tap labels added** (not in pass 9): `Details` (visible, aria-label `Details, <SYMBOL>`), `Legend`, `Close`. These are the only new strings.

## (b) Phone specification (390 and 360, portrait, touch)

**Now row:** identity (symbol 20/600 largest, name, `~$X · ±N% since seen` right or on its own line, caption) → state pill + descriptor → sentence → Mini Clock (full row width, 58 px) → For you on one line + `Details` at the right. **Behind a tap:** Why here (pill, popover), and in the sheet: `Latest: <event> · HH:MMZ`, the readout line, `Open Situation`, `Copy address`.

**Board card:** delta line (+ `· HH:MMZ`, `· N since look`, `Out · HH:MMZ`) → the intact line when there is no change → identity and scale (+ entry line when In) → state pill + descriptor → Mini Clock with the checkpoint span → actions (`Open Situation`, `Compare since look|entry`, `In → Out`) + `Details`. **Behind a tap:** Why here, and in the sheet: the delta line, the two top changes with clocks, `and N more` (linked to compare when a Situation page exists).

**Situation:** identity (symbol, chain and tracked, address, Copy, DexScreener, Explorer, Following / I'm in / Share) → state + sentence + `Money has led…` + since-you-looked chip → clock (ruler with Play, moment tag, Pin A, seven lanes, then the Now · Situation panel) → metric grid → sections (Money, Participants open; Holders, Attention, Safety, Market, About collapsed). Wide tables scroll inside their box.

**Market:** the strip on Now is four lines: `Market` + `Market · 07:15Z` + `Powered by CoinGecko` on line one, then the three phrases (12.5 px), band 94 px, the whole band opens Market. Each card is a title (18/600), the sentence (14 px) and one caption paragraph.

**Sheet grammar (Now and Board, one component):** a bottom sheet (`role="dialog"`, `aria-modal`, labelled by the symbol), full width, at most 78 % of the viewport, radius 16, surface `#1C232B` over a 62 % scrim.
- **Opens** from `Details` (`aria-haspopup="dialog"`, `aria-expanded`, `aria-controls="shx"`) or a tap on the row or card body (a pointer-only layer; the pill, For you link, delta link and actions sit above it). Focus moves into the sheet and Tab cycles inside it. The page behind does not scroll.
- **Closes** on `Close` (44 px), Escape, a tap on the scrim (which is also the second tap on the row), or resizing to desktop. Focus returns to that row's `Details`.
- While open, the sheet refills on every tick of the clock. If the row leaves the list at the new moment, the sheet closes.
- Reduced motion: no slide-in.

**Floors:** every button, link, pill, slider, summary and sheet control has a hit box of 32 px or more, measured by an elementFromPoint scan. Group toggles and the strip band are 44 px or more. No rendered text under 12 px, SVG text included (font size × screen scale). Focus-visible rings are ice .55, 2 px. Pass 2 palette, Geist, tabular figures.

## (c) Verification

`NODE_PATH=/home/botbox/node_modules node scripts/verify.cjs` → **280 passed, 0 failed** (full output in `scripts/verify-output.txt`). Pass 9's Market checks are kept as `scripts/verify-market-pass9.cjs` and its shots script as `scripts/shots-pass9.cjs`.
- **1. Desktop invariance at 1280.** Pass 9 and pass 10 are opened in the same run: 5 page variants (Board with and without an entry) × 3 or 4 moments. innerText is byte-equal and all boxes are within 1 px. Example: `PASS 1280 now.html live innerText byte-equal to pass 9 (2964 chars)` / `17 boxes … within 1 px of pass 9`.
- **2. Strings on the phone.** Collected at 390 and 360 with every drawer, the legend, Why here and every sheet open, plus title, aria-label and aria-valuetext. Compared against pass 9 at 390 as atoms (split on new lines and ` · `, so re-flowed lines compare equal).
  - Missing: none, on every page and moment.
  - Added: the tap labels `Details`, `Details, <SYMBOL>`, `Legend`, `Close`, and on Now `Open Situation | Copy address`. Those two are strings pass 9 prints at 1280 and hid on the phone; they now sit in the sheet.
- **3. Hit boxes.** Smallest: Now 32, Board 32, Situation 33, Market 35 px. The strip band is 94 px and the `Archived` toggle 45 px.
- **4. Sheets.** On every row or card at every moment and both widths, the sheet:
  - opens inside the viewport, with aria-expanded true and aria-controls `shx`, as a modal dialog with focus inside;
  - keeps the page from scrolling (a 600 px wheel moves nothing);
  - closes on Escape, an outside tap and Close, returning focus to Details;
  - opens the same way from a tap on the row;
  - has controls of 32 px or more.

  The legend is one 44 px line until tapped, and toggles aria-expanded. Why here stays inside the viewport and toggles aria-expanded.
- **5. No overflow.** scrollWidth equals 390 or 360 on every page and moment.
- **6. Type floor.** No rendered text under 12 px with drawers, the legend, Why here and a sheet open.
- **7. Banned words and internal names.** `alpha`, `smart money`, `signal`, `score`, `rank`, `PnL`, `will`, `expect`, `likely`: zero across the four pages. Em dashes: 0. Internal names, worker signatures and pass numbers: zero.
- **8. Shots** (`scripts/shots.cjs`, JPEG):
  - `now-phone.jpg` 117 KB, `now-phone-sheet.jpg` 32 KB, `now-strip-phone.jpg` 11 KB, `now-phone-360.jpg` 115 KB
  - `situation-phone.jpg` 163 KB
  - `board-phone.jpg` 94 KB (entry at 17:11Z), `board-phone-sheet.jpg` 31 KB
  - `market-phone.jpg` 103 KB
  - `now-desktop.jpg` 189 KB (unchanged from pass 9)

Two notes from the run:
- Now rows without a Situation page carry pass 7's `aria-disabled="true"` on the row container. Playwright therefore treats their `Details` as disabled, and the test taps with `force`. A screen reader may announce those rows' Details as dimmed. I did not change it, because the attribute is frozen desktop markup (see (e)).
- On Situation, the moment tag's pointer still sits close to the `your look` and `trader` ruler labels at 17:27Z, as in pass 9. I did not move the ruler labels, because they are strings on the frozen clock.

## (d) Hashes and diff against pass 9

```
12db4c4ca4d3855fb5132f0b7a26764874ab870debc9bedabbd7a6d330a75962  now.html
fdfa01dd5cdb2da48c8d2d53f6238de86e29a0977fb91a3336a55be511103543  situation.html
7def80fb1f300ff39de2e78d8a5788b5e5e32752bc6ccdb47405082a48bc11dc  board.html
906a21d5aeeac8fea6a73d2a371472a4985b199c2836423937e3eaff19f4d2ac  market.html
```
- **now.html** (`diff` hunks `159a160,179 209a230 407c428 410a432 419c441 446c468 484a507,510 522a549,550 555a584,628`):
  - A phone-only `<style>` block before `</head>`: `.lgb{display:none}` outside a `max-width:820px` query, everything else inside it.
  - The phone-only `Legend` button before the legend.
  - In the row script: the row keeps a reference to its data (`d._r`), plus the phone-only `.rtap` layer and `Details` button (both `display:none` on desktop).
  - `render()` refreshes an open sheet.
  - The sheet click handler and `sheetFor`; the legend's icon line and toggle.
  - The sheet component (style, markup, script) before `</body>`. Its markup is `hidden`, and its controls are `display:none` above 820 px.
- **board.html** (`226a227,245 251a271 509c529,530 532c553 563c584 606a628,630 644a669,670 668a695,739`): the same pattern, plus a `tcx` class on cards that have top changes (styled only on the phone).
- **situation.html** (`292a293,316`): one phone-only `<style>` block, all inside `max-width:820px`.
- **market.html** (`116a117,123`): one phone-only `<style>` block, all inside `max-width:820px`.
- No other lines changed.

## (e) Wants from the read model

- A short weather form per phrase (at most 40 characters), so the strip can be two lines on the phone without truncating our own sentence.
- A per-row readout split into labelled fields (price, entered, profiled, attention, holders or top 20, safety), so the sheet can print a two-column list instead of one ` · ` line.
- Event lists per row with an `explain` sentence, so the sheet can explain each glyph on the Mini Clock (reviewer 20, "popovers for event explanation") without authoring text on the page.
- A `hasRoom` flag per row, so the frozen `aria-disabled` on the row container can become a flag on the link alone, and `Details` is never announced as dimmed.
- A taller clock form (the same glyphs at 96 px) for the sheet, once the glyph geometry is parameterised by height.

Status: DONE
