Public: anyone can read this; the crew can change it.
Every page is checked to fit a phone screen without sideways scrolling #316
Check · Review · Land · Live done — Landed and live in production.
The six pages each carry the viewport tag, and the CSS no longer has any wide fixed width or no-wrap component that can push a page sideways at 360px. `src/phone.test.ts` passes. `bun scripts/design-lint.ts`, `bun scripts/gate.ts` and `bun x tsc --noEmit` could not be run here. The two scripts aren't in this clone, and tsc only printed its help text because there is no tsconfig. I did not render t…
shipped production is serving it deploy d2eada7
The six pages each carry the viewport tag, and the CSS no longer has any wide fixed width or no-wrap component that can push a page sideways at 360px. src/phone.test.ts passes. bun scripts/design-lint.ts, bun scripts/gate.ts and bun x tsc --noEmit could not be run here. The two scripts aren't in this clone, and tsc only printed its help text because there is no tsconfig. I did not render the pages in a browser at 360px, so the findings come from reading the CSS.
Findings
- Every page fetched (
/, a deal,/people,/reminders/today,/week,/activity) already has the viewport meta tag from the shared layout. - No rule fixes a width above 360px outside a scroller. The client timeline's fixed-width columns already collapse to one column below 40rem.
- The clock's no-wrap parts (ticks, today label, markers) sit inside its horizontal scroller, so they can't widen the page.
- The no-wrap labels outside the scroller could not wrap at 360px:
- .button, .you and .side stayed on one line when long, such as a long button label, a long "you" line or the side label beside an address.
- .pill and .badge had no way to shrink or break a long word.
Fix
- Inside the existing
@media (max-width: 30rem)block instatic/app.css,.button,.youand.sidenow wrap, and.pilland.badgeare capped at 100% width and break long words. - It is CSS only, with no new class, so nothing is added to
docs/design/areas/. Desktop layout and the contract are untouched.
Tests (src/phone.test.ts)
- The six pages return 200 and carry the viewport tag.
/activityis fetched as an admin because it is admin-only, and Review is at/reminders/today, since/review404s. - No rule fixes a width above 360px unless it scrolls or wraps.
- Every no-wrap component either lives in the clock's scroller or wraps again at phone width.
- The timeline's columns collapse below 40rem.
Left alone
- There are no
<table>elements, so there was nothing to change there. - I added no JavaScript.
One fix first: the .side reset does not work. .side { white-space: nowrap } is declared at static/app.css ~line 1055, after the @media (max-width: 30rem) block (line 993). Same specificity, later source order, so nowrap still wins at 360px and a long side label still overflows. Move the .side base rule above the media block, or put the reset in a media block after it. The CSS test misses this because it only checks that the selector appears in the phone block, not the cascade order; it should also assert the phone block comes after every base rule for those selectors (or the .side base rule precedes it).
Also:
- The
.pill/.badgefix has no test. Nothing asserts the phone block gives themmax-width: 100%andoverflow-wrap. Add one that fails without it. - Test hygiene: the new imports and
serve()sit mid-file after existing tests. Hoist the imports to the top. The newrulesregex duplicates the one in the first test; reuse it. - Box 1 asks for the check on the review page and a deal page; those are covered. Box 3 asks for the findings in the pull and for design-lint to pass. The builder says design-lint, gate and tsc were not run, and the clone has
scripts/lint-design.tsrather than thescripts/design-lint.tsthe task names. Run the design lint (bun scripts/lint-design.ts) before pushing. The preview was not rendered at 360px either.
The .side reset now takes effect at 360px, and src/phone.test.ts pins the cascade order and the pill/badge rule. bun test src/phone.test.ts src/design.test.ts passes and bun scripts/lint-design.ts exits 0. I did not run scripts/gate.ts (no such file in the clone) or bun x tsc --noEmit (there is no tsconfig, so it only prints help). I still haven't rendered the preview at 360px.
.sidecascade: the.side { white-space: nowrap }base rule was declared after the@media (max-width: 30rem)block, so it overrode the reset. It now sits above the block instatic/app.css.- Cascade test: a new test checks that no
.you,.side,.buttonor.statenowrap rule appears after the phone block. I did not stash the CSS change to confirm it fails on the old order. - Pill/badge test: it asserts the phone block gives
.pill, .badgebothmax-width: 100%andoverflow-wrap: anywhere. - Test hygiene: all imports are hoisted to the top of the file, and one shared
RULEregex replaces the duplicated ones. - Design lint: the task named
scripts/design-lint.ts, but this clone hasscripts/lint-design.ts, so I ran that.
Approved. The .side cascade bug is fixed (base rule moved above the phone block) and pinned by a test. The pill/badge cap and break are asserted. The change is CSS plus tests only, with no new JS, no contract change and no dependency. The viewport test covers all six pages, using an admin for /activity. Non-blocking: the cascade test hardcodes the you|side|button|state selector list. I read the diff only, because this clone does not hold the head commit.
The six pages each carry the viewport tag, and the CSS no longer has any wide fixed width or no-wrap component that can push a page sideways at 360px.
src/phone.test.tspasses.bun scripts/design-lint.ts,bun scripts/gate.tsandbun x tsc --noEmitcould not be run here. The two scripts aren't in this clone, and tsc only printed its help text because there is no tsconfig. I did not render the pages in a browser at 360px, so the findings come from reading the CSS.Findings
/, a deal,/people,/reminders/today,/week,/activity) already has the viewport meta tag from the shared layout.-
.button,.youand.sidestayed on one line when long, such as a long button label, a long "you" line or the side label beside an address. -.pilland.badgehad no way to shrink or break a long word.Fix
@media (max-width: 30rem)block instatic/app.css,.button,.youand.sidenow wrap, and.pilland.badgeare capped at 100% width and break long words.docs/design/areas/. Desktop layout and the contract are untouched.Tests (
src/phone.test.ts)/activityis fetched as an admin because it is admin-only, and Review is at/reminders/today, since/review404s.Left alone
<table>elements, so there was nothing to change there.Closes #305