# Design pass 11: the two pass 10 phone defects, nothing else

Scope: phone hit boxes only. Desktop 1280 is byte-equal to pass 10 in `innerText` with every box within 1 px, and the phone string set at 390 and 360 is unchanged. `now.html` and `market.html` are byte-equal to pass 10 (same sha256). Only `situation.html` and `board.html` changed.

## (a) What changed, with before and after measurements

The "before" figures come from Vesper's check of pass 10 (`workspace-vesper/.openclaw/tmp/own-check-pass10.run.log`, 292 pass, 10 fail). The "after" figures come from this pass's `scripts/verify.cjs`, which uses the same kind of `elementFromPoint` scan on a 4 px grid: a control counts only where it is the topmost element.

**1. Situation, lane markers (390 and 360, every moment).**

Before (pass 10), the markers under the 32 px floor were:
- `State became Money first, 16:32Z`: 0x17. The `Money first` band label and the state band sat on top of it.
- `Read, 17:27Z` on the ruler: 31x44.
- `Your look, 16:57Z`: 31x44.
- `Read, 16:42Z` in the price chart: 43x26 at 390 and 44x26 at 360. The `low` label covered it.
- `Read, 17:27Z` in the price chart: 31x21 live and 31x25 at 16:57Z and 16:42Z. It was clipped at the right edge.

Brief figure: 26 to 31 px, plus the state marker, which was 0 px wide.

The fix is phone only (`max-width:820px`, or `w<500` inside the draw code):
- SVG text in the clock and the lane charts no longer takes taps (`pointer-events:none`). Labels such as `low`, `your look` and `trader` stop covering the markers under them.
- `mk()` takes an optional hit shape. On the phone, each chart Read marker gets a 22 px radius hit circle and each ruler marker an 18 px one. The centre is clamped inside the SVG width so the markers at the edges are not clipped. The drawn glyphs do not move.
- The state marker gets its own row inside the clock block. On the phone the ruler SVG grows from 84 to 104 px, the state band moves down 20 px, and the marker gets a 44x32 hit rectangle in that row. It is drawn after the ruler marks, so no marker covers another.
- No marker was dropped and no text changed.

After (390, live, 16:57Z and 16:42Z, measured W x H owned):
- Ruler Reads: 35 to 36 x 36.
- `First profiled trader, 17:08Z`: 36x36 on the ruler and 44x44 in the Participants chart.
- `Read, 16:57Z, your last look`: 35x36.
- `State became Money first, 16:32Z`: 44x32.
- Chart Reads: 43 to 44 x 44.
- `Your look, 16:57Z`: 43x44.
- `You entered, 17:11Z` (with an entry): 44x44.

At 360 the figures are the same within 1 px. The smallest marker is 32 px (the state marker's height) and the narrowest is 35 px. Every page and moment has 12 markers, or 13 with an entry.

**2. Board, card-body tap layer.**

Before (pass 10): a `button.rtap` with `tabindex="-1"` and `aria-hidden="true"` covered each card body (`inset:0`). It opened the sheet but it was not a real control: no keyboard path and not in the accessibility tree. The scan measured it at 0x262 or 0x263 and reported the symbol control as covered. That gave 4 FAILs, at 390 live and 17:15Z, with and without an entry.

Fix: the layer is removed (the markup, the `[data-rtap]` click path and its CSS). The sheet now opens only from the card's `Details` button, which on the phone is `min-height:44px`.

After:
- `Details` is 79x45 on every card, at 390 and 360, every moment that has cards.
- There are 0 tap layers.
- On the 4 px grid over the cards, every point that opens the sheet is on that card's `Details`: 868 of 23132 points at 390 live. A tap on bare card body leaves the sheet closed.
- `Details` is a `BUTTON` with `aria-expanded`, `aria-controls="shx"` and `aria-haspopup="dialog"`. Enter and Space both open the sheet, and it has a solid 2 px focus ring.
- The sheet grammar from pass 10 (b) holds.

The foreground verify passed on its first run, so no HTML was changed in this relaunch. The HTML edits are the first run's (09:52 and 09:53); this run only ran the verify and wrote these notes.

## (b) Amended phone specification (only the lines that changed)

**Situation, clock:** ruler (Play, moment tag, Pin A, the four Reads and the first profiled trader, each with a hit area of 36 px or more), then **the state band on its own row** (`Developing | Money first`). The `State became` marker has a 44x32 hit area in that row. Then the seven lanes, then the Now · Situation panel. On the phone the ruler block is 104 px tall (desktop stays 84). SVG labels in the clock and lanes do not take taps. Lane chart markers have a 44 px hit area, kept inside the chart width.

**Sheet grammar, Opens (Board):** from `Details` only (`aria-haspopup="dialog"`, `aria-expanded`, `aria-controls="shx"`, 44 px or more). There is no card-body tap layer: a tap on the card body does nothing. (Now keeps its pass 10 row behaviour; `now.html` is unchanged.)

**Sheet grammar, Closes (Board):** `Close` (44 px), Escape, a tap on the scrim, or resizing to desktop. Focus returns to that card's `Details`. ("The second tap on the row" no longer applies to Board cards.)

**Floors, addition:** a lane marker counts toward the 32 px floor only where the `elementFromPoint` scan finds it topmost. No marker may cover another.

## (c) Verification

`NODE_PATH=/home/botbox/node_modules node scripts/verify.cjs > scripts/verify-output.txt 2>&1`. It ran in the foreground, 3 min 38 s, exit 0. The full output (406 lines) is in `scripts/verify-output.txt`. The reference is pass 10, opened in the same run.

```
== 1. Desktop 1280 invariance against the reference, same run
PASS 1280 situation.html live innerText byte-equal (2642 chars)
PASS 1280 situation.html live 51 boxes within 1 px (incl. every mark, button and link)
PASS 1280 board.html live innerText byte-equal (2154 chars)
PASS 1280 board.html live 31 boxes within 1 px (incl. every mark, button and link)
... (every 1280 line PASS: 4 pages x live, 16:57Z, 16:42Z, Board also 17:15Z, with and without entry)
== Phone 390
PASS 390 situation.html live page errors: none
PASS 390 situation.html live 5. scrollWidth 390 equals viewport 390
PASS 390 situation.html live 3. hit boxes: 41 controls, smallest 32 px tall, narrowest 33 px
PASS 390 situation.html live 3. lane markers (12), W x H owned: "Read, 16:32Z" 36x36, "Read, 16:42Z" 35x36, "Read, 16:57Z, your last look" 35x36, "First profiled trader, 17:08Z" 36x36, "Read, 17:27Z" 35x36, "State became Money first, 16:32Z" 44x32, "Read, 16:32Z" 44x44, "Read, 16:42Z" 43x44, "Read, 16:57Z" 43x44, "Read, 17:27Z" 43x44, "First profiled trader, 17:08Z" 44x44, "Your look, 16:57Z" 43x44
PASS 390 situation.html live 5. type floor: no rendered text under 12 px
PASS 390 situation.html live 2. strings: 201 atoms, reference 201; missing: none; added: none
PASS 390 situation.html live 5. banned words and internal names zero, em dashes 0
PASS 390 board.html live page errors: none
PASS 390 board.html live 5. scrollWidth 390 equals viewport 390
PASS 390 board.html live 3. hit boxes: 17 controls, smallest 32 px tall, narrowest 67 px
PASS 390 board.html live 3. group toggles / strip band 44 px or more: BUTTON#arcT.gtog 45
PASS 390 board.html live 3. card control: tap layers 0; Details (the sheet opener) W x H owned: MARLIN 79x45, SPRING 79x45, LUMEN 79x45, AGRIPPA 79x45
PASS 390 board.html live 3. 4 px grid over 4 cards (23132 points): 868 points open the sheet, all on the card's Details
PASS 390 board.html live 3. a tap on bare card body leaves the sheet closed (open: false)
PASS 390 board.html live 3. Details is a real control: BUTTON, aria-expanded false, aria-controls shx, aria-haspopup dialog, tabindex 0, Enter opens true, Space opens true, focus ring solid 2px
PASS 390 board.html live 4. sheets (4): inside the viewport, dialog modal, focus in, no scroll behind, close on Escape and outside tap with focus back on Details, controls 32 px or more
PASS 390 board.html live 4. Why here popover: visible true, inside viewport true, aria-expanded true, after Escape false, after outside tap false
PASS 390 board.html live 5. type floor: no rendered text under 12 px
PASS 390 board.html live 2. strings: 251 atoms, reference 251; missing: none; added: none
PASS 390 board.html live 5. banned words and internal names zero, em dashes 0
== Phone 360
PASS 360 situation.html live page errors: none
PASS 360 situation.html live 5. scrollWidth 360 equals viewport 360
PASS 360 situation.html live 3. hit boxes: 41 controls, smallest 32 px tall, narrowest 33 px
PASS 360 situation.html live 3. lane markers (12), W x H owned: "Read, 16:32Z" 36x36, "Read, 16:42Z" 36x36, "Read, 16:57Z, your last look" 35x36, "First profiled trader, 17:08Z" 36x36, "Read, 17:27Z" 35x36, "State became Money first, 16:32Z" 44x32, "Read, 16:32Z" 44x44, "Read, 16:42Z" 44x44, "Read, 16:57Z" 43x44, "Read, 17:27Z" 43x44, "First profiled trader, 17:08Z" 44x44, "Your look, 16:57Z" 43x44
PASS 360 situation.html live 5. type floor: no rendered text under 12 px
PASS 360 situation.html live 2. strings: 201 atoms, reference 201; missing: none; added: none
PASS 360 situation.html live 5. banned words and internal names zero, em dashes 0
PASS 360 board.html+in 17:15Z page errors: none
PASS 360 board.html+in 17:15Z 5. scrollWidth 360 equals viewport 360
PASS 360 board.html+in 17:15Z 3. hit boxes: 17 controls, smallest 32 px tall, narrowest 53 px
PASS 360 board.html+in 17:15Z 3. group toggles / strip band 44 px or more: BUTTON#arcT.gtog 45
PASS 360 board.html+in 17:15Z 3. card control: tap layers 0; Details (the sheet opener) W x H owned: SPRING 79x45, LUMEN 79x45, AGRIPPA 79x45
PASS 360 board.html+in 17:15Z 3. 4 px grid over 3 cards (19500 points): 627 points open the sheet, all on the card's Details
PASS 360 board.html+in 17:15Z 3. a tap on bare card body leaves the sheet closed (open: false)
PASS 360 board.html+in 17:15Z 3. Details is a real control: BUTTON, aria-expanded false, aria-controls shx, aria-haspopup dialog, tabindex 0, Enter opens true, Space opens true, focus ring solid 2px
PASS 360 board.html+in 17:15Z 4. sheets (3): inside the viewport, dialog modal, focus in, no scroll behind, close on Escape and outside tap with focus back on Details, controls 32 px or more
PASS 360 board.html+in 17:15Z 4. Why here popover: visible true, inside viewport true, aria-expanded true, after Escape false, after outside tap false
PASS 360 board.html+in 17:15Z 5. type floor: no rendered text under 12 px
PASS 360 board.html+in 17:15Z 2. strings: 200 atoms, reference 200; missing: none; added: none
PASS 360 board.html+in 17:15Z 5. banned words and internal names zero, em dashes 0
...
ALL PASS (398 passed, 0 failed)
```

Shots (`scripts/shots.cjs`, JPEG, all under 500 KB, largest 205 KB):
- `shots/situation-phone-markers.jpg` and `shots/situation-phone.jpg`: 390 live, clock in view with the markers.
- `shots/situation-phone-360-markers.jpg` and `shots/situation-phone-360.jpg`: 360 live.
- `shots/board-phone.jpg` and `shots/board-phone-sheet.jpg`: 390 live, without the sheet and with the LUMEN sheet open.
- `shots/situation-desktop.jpg` and `shots/board-desktop.jpg`: 1280.

## (d) Hashes and diff against pass 10

```
12db4c4ca4d3855fb5132f0b7a26764874ab870debc9bedabbd7a6d330a75962  now.html
aa52c42ec6536bf02a09f4564c63ed57dd20d3fa7f290223df0564aeeebcbaa6  situation.html
27aa5e1d8e3eaf22cff7f542f92861e049adc5e6d06394fb080b7508bd961296  board.html
906a21d5aeeac8fea6a73d2a371472a4985b199c2836423937e3eaff19f4d2ac  market.html
```

- `now.html`: byte-equal to pass 10 (same sha256 `12db4c4c...`).
- `market.html`: byte-equal to pass 10 (same sha256 `906a21d5...`).
- `situation.html`: 27 changed lines, four blocks.
  1. A new phone-only `<style>` after the head styles: `.rc svg text,.ch svg text{pointer-events:none}`.
  2. The `hitIn()` helper, plus an optional `hit` argument to `mk()`. The default is the pass 10 circle.
  3. The price lane's Read markers pass `hitIn(...)`. It returns `null` at 500 px and wider, so desktop keeps its circle.
  4. `draw()` for the ruler: `SB`/`RH` phone offsets, the state band and its labels at `y+SB`, and the state marker with a 44x32 hit rectangle drawn after the ruler marks on the phone. Ruler marks pass `hitIn(x,53,w,18)`. On desktop `SB=0`, `RH=84`, and the draw order and hit shapes are as in pass 10.
- `board.html`: 11 changed lines.
  1. `fill()` no longer emits `button.rtap`.
  2. The groups click handler matches `[data-sheet]` only, with its comment updated.
  3. The `.rtap` CSS rules are removed.
  4. The phone `.dtl` has `min-height:44px`.
  5. The sheet comment is updated.

## (e) Wants from the read model

None. Both fixes are presentation only.

## (f) Landing check, Vesper 10:20 to 10:28 Beirut

The first run (09:49 to 09:59) edited `situation.html` and `board.html`, wrote `scripts/verify.cjs` and `scripts/shots.cjs`, took the 8 shots, then ended its turn with "Both runs are still going. I'll pick them up when they finish." The end of the turn closed the browser: `scripts/verify-output.txt` stops at 360 board.html 16:57Z with "Target page, context or browser has been closed", no FAIL line before it. This NOTES file was never rewritten; it is the pass 10 copy. Vesper's own check of the pass 11 files (`workspace-vesper/.openclaw/tmp/own-check-pass11.cjs`, run 10:27): 320 pass. Desktop 1280 innerText byte-equal to pass 10 on all four pages at live, 16:57Z, 16:42Z, Board also 17:15Z, boxes within 1 px. Situation markers by elementFromPoint at 390 and 360, every moment: 12 markers (Read 8, Your look 1, State became 1), smallest 32 px. Board Details buttons 45 px, tap layers 0. Banned words zero, em dashes zero. Four FAILs were Vesper's own assertion on Board at 16:42Z, where the Board carries no cards; not a defect. `now.html` and `market.html` are byte-equal to pass 10. Relaunched once, for the notes.

Status: DONE
