diff --git a/src/App.css b/src/App.css
index e92f2fd..63b07e7 100644
--- a/src/App.css
+++ b/src/App.css
@@ -104,7 +104,7 @@
display: flex;
flex-direction: column;
gap: 1.75rem;
- background: var(--color-surface);
+ background: #fff;
border-radius: 24px;
border-top: 4px solid #22c55e;
padding: 2rem 1.75rem;
@@ -168,6 +168,29 @@
text-align: left;
}
+/* Login page is always light — ignore dark / liquid-glass themes */
+[data-theme="dark"] .lp,
+[data-theme="liquid-glass"] .lp {
+ background: linear-gradient(160deg, #eef6ee 0%, #dcfce7 100%);
+}
+[data-theme="dark"] .lp__form,
+[data-theme="liquid-glass"] .lp__form {
+ background: #fff;
+ backdrop-filter: none;
+ -webkit-backdrop-filter: none;
+ border: none;
+ border-top: 4px solid #22c55e;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
+}
+[data-theme="dark"] .lp__tagline,
+[data-theme="liquid-glass"] .lp__tagline {
+ color: #4b505a;
+}
+[data-theme="dark"] .lp__privacy,
+[data-theme="liquid-glass"] .lp__privacy {
+ color: #6d727a;
+}
+
/* kept for other callers */
.login-card__error {
margin: 0;
@@ -3215,8 +3238,7 @@
[data-theme="liquid-glass"] .settings-tutorial-btn,
[data-theme="liquid-glass"] .settings-clear-btn,
[data-theme="liquid-glass"] .settings-signout-btn,
-[data-theme="liquid-glass"] .bottom-nav,
-[data-theme="liquid-glass"] .lp__form {
+[data-theme="liquid-glass"] .bottom-nav {
background: var(--glass-bg);
backdrop-filter: var(--glass-blur);
-webkit-backdrop-filter: var(--glass-blur);
@@ -3497,6 +3519,21 @@
box-shadow: 0 1px 8px rgba(74, 222, 128, 0.1);
}
+/* Login page is always light — force button to light style */
+[data-theme="dark"] .lp .google-sign-in-btn,
+[data-theme="liquid-glass"] .lp .google-sign-in-btn {
+ background: #fff;
+ border-color: #dadce0;
+ color: #3c4043;
+}
+
+[data-theme="dark"] .lp .google-sign-in-btn:hover:not(:disabled),
+[data-theme="liquid-glass"] .lp .google-sign-in-btn:hover:not(:disabled) {
+ background: #f8f9fa;
+ border-color: #dadce0;
+ box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
+}
+
/* ============================
WELCOME MODAL
============================ */
diff --git a/src/contexts/AuthContext.tsx b/src/contexts/AuthContext.tsx
index ee87da3..4275350 100644
--- a/src/contexts/AuthContext.tsx
+++ b/src/contexts/AuthContext.tsx
@@ -191,11 +191,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
}
useEffect(() => {
- // Handle returning from a redirect sign-in (mobile flow)
+ // Handle returning from a redirect sign-in (Safari / iOS / Android WebViews)
getRedirectResult(auth).catch((error) => {
console.error('[Auth] Redirect sign-in error:', error)
setAuthError(error instanceof Error ? error.message : 'Sign-in failed')
})
+ // onAuthStateChanged below handles the successful redirect result automatically
const unsubscribe = onAuthStateChanged(auth, async (u) => {
setUser(u)
@@ -218,6 +219,14 @@ export function AuthProvider({ children }: { children: ReactNode }) {
async function signInWithGoogle() {
setAuthError(null)
await setPersistence(auth, browserLocalPersistence)
+
+ // Safari blocks cross-origin storage in popups (ITP), so use redirect flow
+ const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
+ if (isSafari) {
+ await signInWithRedirect(auth, googleProvider)
+ return
+ }
+
try {
await signInWithPopup(auth, googleProvider)
} catch (err: unknown) {
diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx
index 504e70c..ea2f8a5 100644
--- a/src/pages/LoginPage.tsx
+++ b/src/pages/LoginPage.tsx
@@ -40,7 +40,7 @@ export default function LoginPage() {
// Without the `user` check here, the login form flashes for one frame
// between loading→false and the useEffect redirect.
if (loading || signingIn || user) {
- return