diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts
index f5d141d..24f76e2 100644
--- a/src/i18n/ui.ts
+++ b/src/i18n/ui.ts
@@ -208,6 +208,13 @@ export const ui = {
newTitle: "Neu hier?", newText: "Lege ein Konto an, um Bestellhistorie, Wunschliste und Sendungsverfolgung an einem Ort zu haben – oder bestelle einfach als Gast, ganz ohne Konto.",
guestButton: "Als Gast weiter einkaufen",
loginError: "Bitte gib eine E-Mail-Adresse ein.",
+ socialHeading: "Schneller anmelden mit",
+ socialGoogle: "Mit Google anmelden", socialApple: "Mit Apple anmelden", socialPaypal: "Mit PayPal anmelden",
+ socialComingSoon: "Kommt in Phase 2: Sobald die echte Konto-Anbindung steht, kannst du dich hier direkt anmelden — ganz ohne neues Passwort.",
+ orDivider: "oder mit E-Mail",
+ showPassword: "Passwort anzeigen", hidePassword: "Passwort verbergen",
+ rememberMe: "Angemeldet bleiben",
+ consentPrefix: "Mit der Anmeldung akzeptierst du unsere", consentLink: "Datenschutzerklärung", consentSuffix: ".",
},
accountDash: {
eyebrow: "Mein Konto", greeting: (name: string) => `Hallo ${name} 🩵`, lead: "Schön, dass du wieder da bist. Hier findest du alle deine Bestellungen, deine Wunschliste und deine Daten auf einen Blick.",
@@ -429,6 +436,13 @@ export const ui = {
newTitle: "New here?", newText: "Create an account to keep order history, wishlist and tracking in one place – or simply check out as a guest, no account needed.",
guestButton: "Continue shopping as guest",
loginError: "Please enter an email address.",
+ socialHeading: "Sign in faster with",
+ socialGoogle: "Sign in with Google", socialApple: "Sign in with Apple", socialPaypal: "Sign in with PayPal",
+ socialComingSoon: "Coming in Phase 2: once the real account backend is live, you'll be able to sign in here directly — no new password needed.",
+ orDivider: "or with email",
+ showPassword: "Show password", hidePassword: "Hide password",
+ rememberMe: "Keep me signed in",
+ consentPrefix: "By signing in you accept our", consentLink: "privacy policy", consentSuffix: ".",
},
accountDash: {
eyebrow: "My Account", greeting: (name: string) => `Hello ${name} 🩵`, lead: "Good to see you again. Here you'll find all your orders, your wishlist and your details at a glance.",
@@ -650,6 +664,13 @@ export const ui = {
newTitle: "Neu da?", newText: "Leg es Konto a, für Bstellhistorie, Wunschlischte und Sändigsverfolgig a einem Ort z'ha – oder bstell eifach als Gast, ganz ohni Konto.",
guestButton: "Als Gast wyter yichaufe",
loginError: "Bitte gib e E-Mail-Adrässe i.",
+ socialHeading: "Schnäller aamälde mit",
+ socialGoogle: "Mit Google aamälde", socialApple: "Mit Apple aamälde", socialPaypal: "Mit PayPal aamälde",
+ socialComingSoon: "Chunnt i Phase 2: Sobald d'echti Konto-Aabindig staht, chasch di da direkt aamälde — ganz ohni nöis Passwort.",
+ orDivider: "oder mit E-Mail",
+ showPassword: "Passwort azeige", hidePassword: "Passwort verstecke",
+ rememberMe: "Aagmäldet bliebe",
+ consentPrefix: "Mit dr Aamäldig akzeptiersch üsi", consentLink: "Datenschutzerklärig", consentSuffix: ".",
},
accountDash: {
eyebrow: "Mis Konto", greeting: (name: string) => `Hoi ${name} 🩵`, lead: "Schön, bisch wieder da. Da findsch alli dini Bstellige, dini Wunschlischte und dini Date uf ein Blick.",
@@ -871,6 +892,13 @@ export const ui = {
newTitle: "Nouveau ici ?", newText: "Créez un compte pour retrouver l'historique des commandes, la liste de souhaits et le suivi au même endroit – ou commandez simplement en tant qu'invité, sans compte.",
guestButton: "Continuer mes achats en tant qu'invité",
loginError: "Veuillez saisir une adresse e-mail.",
+ socialHeading: "Connexion plus rapide avec",
+ socialGoogle: "Se connecter avec Google", socialApple: "Se connecter avec Apple", socialPaypal: "Se connecter avec PayPal",
+ socialComingSoon: "Disponible en phase 2 : dès que la vraie connexion au compte sera en place, vous pourrez vous connecter directement ici — sans nouveau mot de passe.",
+ orDivider: "ou avec e-mail",
+ showPassword: "Afficher le mot de passe", hidePassword: "Masquer le mot de passe",
+ rememberMe: "Rester connecté(e)",
+ consentPrefix: "En vous connectant, vous acceptez notre", consentLink: "politique de confidentialité", consentSuffix: ".",
},
accountDash: {
eyebrow: "Mon compte", greeting: (name: string) => `Bonjour ${name} 🩵`, lead: "Ravie de vous revoir. Retrouvez ici toutes vos commandes, votre liste de souhaits et vos données en un coup d'œil.",
diff --git a/src/pages/ch/konto/index.astro b/src/pages/ch/konto/index.astro
index 73c5b2f..f8f2b8b 100644
--- a/src/pages/ch/konto/index.astro
+++ b/src/pages/ch/konto/index.astro
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
@@ -51,4 +100,28 @@ const t = useTranslations(lang);
login(email);
window.location.href = "/ch/konto/angemeldet/";
});
+
+ // Passwort-Sichtbarkeits-Toggle — rein clientseitig, braucht kein Backend.
+ const pwInput = document.getElementById("login-pw") as HTMLInputElement | null;
+ const pwToggle = document.getElementById("login-pw-toggle") as HTMLButtonElement | null;
+ const EYE_OPEN = `
`;
+ const EYE_CLOSED = `
`;
+ pwToggle?.addEventListener("click", () => {
+ if (!pwInput) return;
+ const showing = pwInput.type === "text";
+ pwInput.type = showing ? "password" : "text";
+ pwToggle.setAttribute("aria-pressed", String(!showing));
+ pwToggle.setAttribute("aria-label", showing ? (pwToggle.dataset.showLabel ?? "") : (pwToggle.dataset.hideLabel ?? ""));
+ const icon = document.getElementById("login-pw-icon");
+ if (icon) icon.innerHTML = showing ? EYE_OPEN : EYE_CLOSED;
+ });
+
+ // Social-Login-Buttons: kein echtes OAuth ohne Backend — Klick zeigt stattdessen ehrlich
+ // den Phase-2-Hinweis (siehe .social-note oben im Markup).
+ const socialNote = document.getElementById("social-note");
+ document.querySelectorAll(".btn-social").forEach((btn) => {
+ btn.addEventListener("click", () => {
+ if (socialNote) socialNote.style.display = "block";
+ });
+ });
diff --git a/src/pages/en/konto/index.astro b/src/pages/en/konto/index.astro
index f842e93..4040171 100644
--- a/src/pages/en/konto/index.astro
+++ b/src/pages/en/konto/index.astro
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
@@ -51,4 +100,28 @@ const t = useTranslations(lang);
login(email);
window.location.href = "/en/konto/angemeldet/";
});
+
+ // Passwort-Sichtbarkeits-Toggle — rein clientseitig, braucht kein Backend.
+ const pwInput = document.getElementById("login-pw") as HTMLInputElement | null;
+ const pwToggle = document.getElementById("login-pw-toggle") as HTMLButtonElement | null;
+ const EYE_OPEN = `
`;
+ const EYE_CLOSED = `
`;
+ pwToggle?.addEventListener("click", () => {
+ if (!pwInput) return;
+ const showing = pwInput.type === "text";
+ pwInput.type = showing ? "password" : "text";
+ pwToggle.setAttribute("aria-pressed", String(!showing));
+ pwToggle.setAttribute("aria-label", showing ? (pwToggle.dataset.showLabel ?? "") : (pwToggle.dataset.hideLabel ?? ""));
+ const icon = document.getElementById("login-pw-icon");
+ if (icon) icon.innerHTML = showing ? EYE_OPEN : EYE_CLOSED;
+ });
+
+ // Social-Login-Buttons: kein echtes OAuth ohne Backend — Klick zeigt stattdessen ehrlich
+ // den Phase-2-Hinweis (siehe .social-note oben im Markup).
+ const socialNote = document.getElementById("social-note");
+ document.querySelectorAll(".btn-social").forEach((btn) => {
+ btn.addEventListener("click", () => {
+ if (socialNote) socialNote.style.display = "block";
+ });
+ });
diff --git a/src/pages/fr/konto/index.astro b/src/pages/fr/konto/index.astro
index 2015ac7..076cef0 100644
--- a/src/pages/fr/konto/index.astro
+++ b/src/pages/fr/konto/index.astro
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
@@ -51,4 +100,28 @@ const t = useTranslations(lang);
login(email);
window.location.href = "/fr/konto/angemeldet/";
});
+
+ // Passwort-Sichtbarkeits-Toggle — rein clientseitig, braucht kein Backend.
+ const pwInput = document.getElementById("login-pw") as HTMLInputElement | null;
+ const pwToggle = document.getElementById("login-pw-toggle") as HTMLButtonElement | null;
+ const EYE_OPEN = `
`;
+ const EYE_CLOSED = `
`;
+ pwToggle?.addEventListener("click", () => {
+ if (!pwInput) return;
+ const showing = pwInput.type === "text";
+ pwInput.type = showing ? "password" : "text";
+ pwToggle.setAttribute("aria-pressed", String(!showing));
+ pwToggle.setAttribute("aria-label", showing ? (pwToggle.dataset.showLabel ?? "") : (pwToggle.dataset.hideLabel ?? ""));
+ const icon = document.getElementById("login-pw-icon");
+ if (icon) icon.innerHTML = showing ? EYE_OPEN : EYE_CLOSED;
+ });
+
+ // Social-Login-Buttons: kein echtes OAuth ohne Backend — Klick zeigt stattdessen ehrlich
+ // den Phase-2-Hinweis (siehe .social-note oben im Markup).
+ const socialNote = document.getElementById("social-note");
+ document.querySelectorAll(".btn-social").forEach((btn) => {
+ btn.addEventListener("click", () => {
+ if (socialNote) socialNote.style.display = "block";
+ });
+ });
diff --git a/src/pages/konto/index.astro b/src/pages/konto/index.astro
index eb9580c..a6f61ad 100644
--- a/src/pages/konto/index.astro
+++ b/src/pages/konto/index.astro
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
@@ -51,4 +100,28 @@ const t = useTranslations(lang);
login(email);
window.location.href = "/konto/angemeldet/";
});
+
+ // Passwort-Sichtbarkeits-Toggle — rein clientseitig, braucht kein Backend.
+ const pwInput = document.getElementById("login-pw") as HTMLInputElement | null;
+ const pwToggle = document.getElementById("login-pw-toggle") as HTMLButtonElement | null;
+ const EYE_OPEN = `
`;
+ const EYE_CLOSED = `
`;
+ pwToggle?.addEventListener("click", () => {
+ if (!pwInput) return;
+ const showing = pwInput.type === "text";
+ pwInput.type = showing ? "password" : "text";
+ pwToggle.setAttribute("aria-pressed", String(!showing));
+ pwToggle.setAttribute("aria-label", showing ? (pwToggle.dataset.showLabel ?? "") : (pwToggle.dataset.hideLabel ?? ""));
+ const icon = document.getElementById("login-pw-icon");
+ if (icon) icon.innerHTML = showing ? EYE_OPEN : EYE_CLOSED;
+ });
+
+ // Social-Login-Buttons: kein echtes OAuth ohne Backend — Klick zeigt stattdessen ehrlich
+ // den Phase-2-Hinweis (siehe .social-note oben im Markup).
+ const socialNote = document.getElementById("social-note");
+ document.querySelectorAll(".btn-social").forEach((btn) => {
+ btn.addEventListener("click", () => {
+ if (socialNote) socialNote.style.display = "block";
+ });
+ });
diff --git a/src/styles/global.css b/src/styles/global.css
index 11e5704..574726f 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -365,6 +365,71 @@ a:focus-visible, button:focus-visible {
.frm .checkbox-row { display: flex; gap: 0.6rem; align-items: flex-start; font-size: 0.88rem; color: var(--c-text-muted); }
.frm .checkbox-row input { width: auto; margin-top: 0.2rem; }
+/* ============================================================
+ Login: Social-Login-Buttons, Passwort-Sichtbarkeit, DSGVO-Hinweis
+ In Deutschland/DACH übliche Anmelde-Alternativen zur reinen E-Mail/Passwort-
+ Anmeldung (siehe Recherche: PayPal-Login ist wegen der PayPal-Marktdominanz
+ in DE besonders verbreitet, neben Google/Apple). Die Buttons sind bewusst
+ NICHT funktional (kein echtes OAuth ohne Backend) — ein Klick zeigt einen
+ ehrlichen Hinweis statt eine vorgetäuschte Anmeldung.
+ ============================================================ */
+.social-login { display: grid; gap: 0.6rem; }
+.btn-social {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.6em;
+ width: 100%;
+ padding: 0.7em 1em;
+ border-radius: var(--radius-s);
+ border: 1px solid rgba(244, 241, 247, 0.16);
+ background: var(--c-anthracite);
+ color: var(--c-text);
+ font-family: var(--font-body);
+ font-size: 0.92rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: background 0.15s var(--ease), border-color 0.15s var(--ease), transform 0.1s var(--ease);
+}
+.btn-social:hover { background: var(--c-anthracite-light); border-color: rgba(244, 241, 247, 0.3); }
+.btn-social:active { transform: scale(0.99); }
+.btn-social svg { flex-shrink: 0; }
+.btn-social-paypal .social-icon-badge {
+ display: inline-flex; align-items: center; justify-content: center;
+ width: 18px; height: 18px; border-radius: 50%;
+ background: #003087; color: #fff; font-family: var(--font-head); font-weight: 700; font-size: 0.72rem;
+ flex-shrink: 0;
+}
+.social-note {
+ display: none;
+ font-size: 0.82rem;
+ color: var(--c-text-muted);
+ background: color-mix(in srgb, var(--c-accent) 10%, transparent);
+ border: 1px solid color-mix(in srgb, var(--c-accent) 25%, transparent);
+ border-radius: var(--radius-s);
+ padding: 0.6em 0.8em;
+ margin: -0.2rem 0 0;
+}
+.social-divider { display: flex; align-items: center; gap: 0.8em; color: var(--c-text-muted); font-size: 0.82rem; margin: 0.1rem 0; }
+.social-divider::before, .social-divider::after { content: ""; flex: 1; height: 1px; background: rgba(244, 241, 247, 0.14); }
+.pw-field { position: relative; }
+.pw-field input { padding-right: 2.6em; }
+.pw-toggle {
+ position: absolute;
+ top: 50%;
+ right: 0.5em;
+ transform: translateY(-50%);
+ background: none;
+ border: none;
+ color: var(--c-text-muted);
+ cursor: pointer;
+ padding: 0.3em;
+ display: flex;
+ border-radius: var(--radius-s);
+}
+.pw-toggle:hover { color: var(--c-text); }
+.login-consent { color: var(--c-text-muted); margin-top: -0.3rem; }
+
/* ============================================================
Sprach-Umschalter + Konto-Button (Header)
============================================================ */