Gate 7 — Responsive Audit — Ticket #3269 (Password Reset Flow) ================================================================ Date: 2026-09-04 Feature files audited: - middleware.ts (no UI — excluded from responsive checks) - app/(auth)/forgot-password/page.tsx - app/(auth)/verify-otp/page.tsx - app/(auth)/reset-password/page.tsx - components/auth/ForgotPasswordForm.tsx - components/auth/VerifyOtpForm.tsx - components/auth/CompleteResetForm.tsx Related files inspected (not in feature_files but consumed by them): - components/auth/BrandPanel.tsx (shared left-hand panel, w-[45%] shrink-0) - components/ui/SubmitButton.tsx - components/ui/fields/PhoneInput.tsx (country dropdown w-72) - components/ui/fields/PasswordField.tsx (eye toggle touch target) - components/ui/button.tsx (buttonVariants CVA) - components/ui/Toast.tsx (fixed bottom-4 right-4) - app/(auth)/layout.tsx (session guard only, no styling) - app/(auth)/login/page.tsx + components/auth/SignInForm.tsx (UX-consistency baseline) - app/globals.css (field-input/field-control/field-error layer components) - tailwind.config.ts (breakpoints: default Tailwind sm:640 md:768 lg:1024 xl:1280) screen_inventory: — UX-consistency audit limited to login page comparison. Skills resolved (all via read_file, path 3 — no slash-command layer available): 1. nextjs-tailwind-responsive-components-audit — SKILL.md read ✓ 2. nextjs-tailwind-responsive-desktop-audit — SKILL.md read ✓ 3. nextjs-tailwind-responsive-mobile-audit — SKILL.md read ✓ 4. nextjs-tailwind-responsive-tablet-breakpoint-audit — SKILL.md read ✓ 5. nextjs-tailwind-responsive-typography-audit — SKILL.md read ✓ 6. nextjs-tailwind-responsive-ux-consistency-audit — SKILL.md read ✓ ======================================================================== MERGED FINDINGS (deduplicated, tagged by source audit) ======================================================================== --- FINDING 1 [P1] --- Tags: [mobile][components][tablet] File: app/(auth)/forgot-password/page.tsx, app/(auth)/verify-otp/page.tsx, app/(auth)/reset-password/page.tsx (all three pages) Root cause in: components/auth/BrandPanel.tsx (w-[45%] shrink-0, no responsive hide) Component: Auth page layout (BrandPanel + form side-by-side) Viewport(s) affected: 320-767px (all mobile and small-tablet widths) Problem: BrandPanel renders at w-[45%] with shrink-0 at EVERY viewport — no responsive hide/collapse. At 320px mobile, BrandPanel takes 144px and the form area gets only 176px. At 375px, BrandPanel=169px / form=206px. At 430px, BrandPanel=194px / form=236px. All three widths are far below the forms' designed min content width (~360px). The forms are effectively unusable: inputs are impossibly narrow, PhoneInput's country selector consumes most of the available width, and the BrandPanel's own content (with left-12 + right-12 = 96px horizontal padding) has only 48px of usable text width at 320px — its text-3xl heading is unreadable. Evidence: BrandPanel.tsx line 7: className="relative h-full w-[45%] shrink-0 overflow-hidden bg-accent" forgot-password/page.tsx line 14:
No breakpoint-conditional rendering of BrandPanel. Same pattern on all three pages. Login page (app/(auth)/login/page.tsx) uses the identical pattern — this is an inherited layout, but it is still a P1 on these pages because they ship the same broken mobile experience. Why it matters: All three password-reset pages are completely unusable on any phone. A user who forgot their password and is on mobile cannot complete the reset flow. Recommended fix: Add responsive hide to BrandPanel's root div: className="relative hidden h-full w-[45%] shrink-0 overflow-hidden bg-accent md:block" And ensure the form wrapper gets padding on mobile: className="flex flex-grow items-center justify-center p-6 md:p-0" (This also fixes the login page since BrandPanel is shared.) Risk of change: Low — BrandPanel is purely decorative branding, hiding it on mobile loses no functionality. The login page gains the same fix. Fixed: false --- FINDING 2 [P2] --- Tags: [mobile] File: app/(auth)/forgot-password/page.tsx, app/(auth)/verify-otp/page.tsx Component: Form wrapper (flex-grow container around ForgotPasswordForm / VerifyOtpForm) Viewport(s) affected: 320-767px Problem: The form wrapper div has no horizontal padding:
If/when BrandPanel is hidden on mobile, the form (max-w-[360px] w-full) would stretch to full viewport width with zero breathing room — inputs would touch screen edges. The reset-password page correctly has p-6 on its wrapper; these two pages do not. Evidence: forgot-password/page.tsx line 16: className="flex flex-grow items-center justify-center" verify-otp/page.tsx line 37: className="flex flex-grow flex-col items-center justify-center gap-0" reset-password/page.tsx line 37: className="flex flex-grow items-center justify-center overflow-y-auto p-6" (reset-password has p-6, the other two do not) Why it matters: Once the BrandPanel-hide fix is applied, these pages still lack the safe-area padding mobile forms need. Recommended fix: Add p-6 (or at minimum px-4 sm:px-6) to both page wrappers, matching reset-password's existing pattern. Risk of change: None — adding padding only narrows the max available width, well within the form's own max-w-[360px]. Fixed: false --- FINDING 3 [P2] --- Tags: [mobile][components] File: components/auth/VerifyOtpForm.tsx (line 120-126) Component: Resend code button Viewport(s) affected: 320-430px (all mobile) Category: touch-targets Problem: The "Resend code" / "Resend code in Xs" button is a bare text button with no explicit height or padding: className="text-sm font-medium text-accent hover:underline ..." At text-sm (14px font, ~20px line-height), the rendered touch target is approximately 20px tall — well below the 44px accessible minimum for touch targets on mobile. Evidence: VerifyOtpForm.tsx lines 120-131: