Follow-up to #390. PHONE_MAX had become 599, an inclusive bound, while
three of its four consumers still read it as exclusive (width < PHONE_MAX
for phone); the one site that switched to <= disagreed with
getDeviceType(). It is 600 again with < at every site. The breakpoint
table in docs/mobile-testing-report.md says 600, and the three 430px
visual baselines are removed: they depict the tablet tier now, and the
visual suite recreates a missing baseline on its next run on the machine
that owns them. device-matrix.test.ts is also run through Prettier, which
the commit hook demanded and the format gate (src/ only) never did.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The phone tier stopped at innerWidth < 430 and @media (max-width: 430px), so every current large phone landed in the tablet layout: the 430pt iPhone 14 Pro Max, 15 Plus, 15 Pro Max and 16 Plus, the 440pt iPhone 16 Pro Max and 17 Pro Max, Pixel 6 Pro, 7 Pro and OnePlus 12 Pro, the 448pt Pixel 8 Pro and 9 Pro XL, and the Galaxy Z Fold 5 cover screen at 460. On those devices the header icon row replaced the session pill, the toolbar kept the desktop Run Shell button instead of Enter and the mic, the keyboard accessory bar could never become visible because its .visible rule lives inside the phone block, and the toolbar jumped to the top of the page when the keyboard opened.
The new cutoff is 600, the line test/mobile/devices.ts already draws between large phones (430-599) and small tablets (600-767). No physical device sits between 480 and 600, but a phone zoomed out one or two steps in Safari does: a 440pt iPhone at 85% or 75% page zoom reports 518px or 587px and still needs the phone controls, which a 480 cutoff would have taken away. The phone block is max-width: 599px and the tablet block starts at min-width: 600px, so a 600px device is a tablet in CSS and in getDeviceType() alike instead of straddling the boundary the way 430pt phones did.
The number changes everywhere it is encoded: JS, CSS, comments, CLAUDE.md, the CI tests that pin the phone block, and the test:mobile helpers. Measurement history that names 430px stays as written.
The COD-39 attachment-history header button was visible on the cramped
phone header. Hide it on phones alongside the settings gear and lifecycle
log (the mobile header is intentionally minimal — those controls live in
the toolbar). One-line addition to the existing @media (max-width: 430px)
display:none block in mobile.css.
This is the second time a header control leaked onto mobile (the
plan-usage chip was the first), so add two regression guards:
- test/mobile-header-buttons-policy.test.ts — a pure static analysis of
index.html + mobile.css (no browser), so it runs in the normal CI sweep
(the test/mobile/** Playwright suite is EXCLUDED from CI and never gated
this). It enumerates every default-visible header button and fails when
one has no phone-visibility decision — either a mobile.css hide rule or
an explicit MOBILE_VISIBLE_ALLOWLIST entry. A new header button now
forces that decision. Verified it fails on the pre-fix state and passes
after.
- test/mobile/header-buttons.test.ts — real-browser E2E in the mobile
suite: asserts the attachments/settings/lifecycle buttons are hidden on
an emulated iPhone 14 Pro and the attachments button is visible on a
desktop-class tablet.
tsc + lint + prettier + both new tests green. Only CSS + tests changed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>