Five mobile-UX issues caught in the 2026-05-03 audit, fixed in one pass:
1. SpecRow on berth detail clipped at right edge on phone widths.
"Length 49.21 ft / 15 r" (the "m" cut off). Mobile-first stack:
label on top, value full-width below; flex row only from sm up.
2. ResponsiveTabs collapsed to a Select on phone widths, which read like
a generic dropdown and obscured the existence of peer tabs. Replaced
with a horizontally-scrollable strip that auto-scrolls the active
trigger into view (so the user sees neighbors and gets a discovery
cue that more exists beyond the edge). Removes the phone-only Select
and unifies the tab UI across viewport sizes.
3. Documents page tab strip ("All / EOI queue / Awaiting them / ...")
overflowed the 390px viewport because the wrapper was a fixed flex
row. Same horizontal-scroll fix as (2); inherits because Documents
uses ResponsiveTabs.
4. Berth detail header: "Change Status" + "Edit" buttons crowded the
area subtitle on mobile, causing "North Pier" to wrap to two lines
("North" / "Pier"). Stacked vertically on phone widths; from sm up
the buttons sit beside the title block as before.
5. Empty contact rows on client detail rendered a stale "Add tag · star"
metadata strip even when the contact value was unset, which cluttered
the row and offered no useful action. The metadata block now only
shows when contact.value is non-empty; the trash icon stays visible
so users can clean up the empty placeholder.
Verification:
- pnpm exec vitest run: 858/858 passing
- pnpm exec tsc --noEmit: same 36 errors as baseline (all pre-existing
on feat/mobile-foundation, none introduced)
- lint clean
Defers:
- Mobile More sheet last-row alignment / "Email" label specificity
- Admin index grouping (Access / System / Configuration / Content)
- Interest detail header icon labels (trophy/X discoverability)
- Pipeline funnel x-axis label abbreviations
- Reminders rail width allocation on dashboard
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The mobile topbar already shows the entity name pushed via
useMobileChrome, so the gradient detail-header strip was rendering it
a second time. Hides the inline h1 below sm: while keeping the source
/ email / phone meta and action buttons visible — the strip's
practical content (actions + meta) stays where users need it, and the
title responsibility moves cleanly to the topbar.
Affects: clients, yachts, companies, berths detail headers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Action buttons in entity detail headers (Invite/GDPR/Archive on
clients, similar sets elsewhere) overflowed off-screen at 393px
because the actions row was flex without flex-wrap. Adds flex-wrap
so buttons drop to a second/third row instead of clipping.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds shared <DetailHeaderStrip> wrapper (rounded-xl + gradient-brand-soft + shadow-xs)
and applies it to every legacy domain detail header. Residential client/interest and
invoice detail get an inline gradient strip with eyebrow ('Residential Client',
'Residential Interest', 'Invoice'). Residential bodies normalized to lg:grid-cols-[2fr_1fr]
per spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>