The loading spinner in RequireAuth caused a hydration error: on SSR the session was available so children rendered, but during client hydration session.loading was true so the spinner rendered instead, causing DOM mismatch (null nextSibling).
Also includes role resolution priority fixes from previous session:
- prefer preferredRole when backendRole is JOB_SEEKER but preferredRole is not
- pass role via URL param to dashboard
- urlRoleLocked signal prevents auth effects from overriding URL role
- login.tsx: pass role via URL param to dashboard instead of relying on localStorage
- dashboard.tsx: add urlRoleLocked signal to prevent auth effects from overriding URL-passed role
- auth.tsx: trust passed-in role over re-reading from localStorage in saveUser
- Change from /api/gateway/api/auth/resend-otp to /api/auth/resend-otp
- Fix in signup.tsx and login.tsx
- Gateway already proxies /api/auth/* to users service
- Add AuthProvider context and RequireAuth route guard
- Create API client with all endpoint helpers
- Add forgot-password route wired to backend reset endpoints
- Remove dummy login button from login page
- Wire dashboard to auth context for user data
- Enhance profile save to send all fields
- Wire profile submit-for-verification to backend API