The desktop/mobile consistency review found primary mobile controls
rendering below the ~44px comfortable touch floor. Address the genuinely
shared primitives in one pass:
- Add a --tap-min: 44px token (documented anchor for the floor).
- tokens.css: text inputs, selects, and submit buttons grow to --tap-min
under the 640px breakpoint (fixes the 36px auth/login form controls).
Scoped to form controls + type=submit so dense icon buttons aren't
inflated.
- SegmentedControl: .seg options reach the floor on mobile (it doubles as
the catalog sort toggle and the Library tab switcher).
- Chip: expand .chip-remove's tappable area to --tap-min via a centered
pseudo-element so the 16px glyph stays compact and tag rows don't grow.
Pure-CSS responsive change — jsdom can't evaluate @media or layout, so the
test pins the stylesheet contract (each shared primitive bumps to --tap-min
inside the mobile breakpoint), guarding against the bump being dropped.
The per-route .icon-btn (copy-pasted across seven files) is left for a
separate refactor.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sort the manga catalog by created / updated / title / author with an
independent asc/desc direction control. An omitted `order` defaults per field
(dates newest-first, text A→Z), matching the UI, so a bare `?sort=<field>`
means the same thing in the browser and over the API; `sort=recent` remains a
back-compat alias for `created`.
- Backend: SortField/SortOrder parsed with validation (structured 422 on bad
input), per-field default_order, NULLS LAST only on the nullable author key,
and migration 0033 indexing mangas(updated_at DESC, id) to back the default
sort and its id tie-break.
- Frontend: catalog sort field + direction (SegmentedControl) on desktop and a
mobile bottom sheet; pure helpers in $lib/mangaSort; keyboard-accessible
direction control; visible Direction labels and a sheet "Done" button.
- Tests: backend integration coverage (defaults, alias, invalid input,
ascending-id tie-break), frontend unit + e2e.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase 1 of the mobile redesign: add the reusable primitives every
later phase plugs into, and switch the layout to a 4-tab bottom nav
+ compact AppBar on phone viewports while leaving the desktop header
untouched above 640px.
- New primitives: BottomNav, Sheet, AppBar, SegmentedControl, all
with vitest unit tests.
- Layout swaps the desktop header for AppBar + BottomNav under the
existing 640px breakpoint. Login / register / reader routes opt
out of the mobile chrome.
- Library tab currently points at /bookmarks; the curated /library
wrapper lands in Phase 5.
- Independent ResizeObservers publish --app-header-h,
--mobile-app-bar-h, --app-bottom-nav-h, with a zero-height skip so
hidden bars don't clobber the visible one's value.
- viewport-fit=cover + env(safe-area-inset-*) tokens for notched
devices and the iOS home indicator.
- Playwright spec covers visibility at 390px / 1280px viewports and
tab navigation.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>