Login-Seite professionalisiert: Social-Login-Optionen, Passwort-Toggle, DSGVO-Hinweis

Nach Recherche zu üblichen Anmelde-Standards bei deutschen Online-Shops:
Ergänzt Social-Login-Buttons für Google, Apple und PayPal (PayPal explizit
wegen seiner Marktdominanz bei Zahlungen in DE/DACH), da Social Login
Registrierung/Login deutlich beschleunigt und laut Studien die Conversion
spürbar erhöht. Die Buttons sind noch nicht funktional (kein OAuth ohne
eigenes Backend) — ein Klick zeigt stattdessen ehrlich einen Phase-2-
Hinweis, statt eine Anmeldung vorzutäuschen.

Zusätzlich: Passwort-Sichtbarkeits-Toggle (Augen-Icon, eine der
wirkungsvollsten Login-UX-Verbesserungen laut UX-Recherche), "Angemeldet
bleiben"-Checkbox, sowie ein DSGVO-konformer Hinweis mit Link zur
Datenschutzerklärung unterhalb des Formulars. Gastbestellung ("Neu hier?")
war als gleichwertige Alternative schon vorhanden und bleibt bestehen —
Gastbestellung gilt laut EDPB-Empfehlung als Standard neben der freiwilligen
Registrierung.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
qcigano
2026-08-03 04:33:12 +02:00
co-authored by Claude Sonnet 5
parent cc3e84bd98
commit ab3bf675b9
6 changed files with 393 additions and 8 deletions
+75 -2
View File
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
<div class="container grid grid-2 account-grid">
<form class="frm card" id="login-form">
<h3>{t.account.loginTitle}</h3>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required /></div>
<div><label for="login-pw">{t.account.password}</label><input id="login-pw" type="password" /></div>
{/* Social-Login: in DE/DACH übliche Alternativen zu E-Mail/Passwort — Google und Apple
als verbreitetste Anbieter, PayPal zusätzlich wegen seiner Marktdominanz bei
Zahlungen in Deutschland (siehe Recherche). Ohne eigenes Backend noch nicht
funktional; ein Klick zeigt ehrlich den Phase-2-Hinweis statt eine Anmeldung
vorzutäuschen. */}
<div class="social-login">
<p class="small" style="margin:0 0 -0.2rem;">{t.account.socialHeading}</p>
<button type="button" class="btn-social btn-social-google">
<svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true"><path fill="#FFC107" d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12c0-6.627,5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24c0,11.045,8.955,20,20,20c11.045,0,20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"/><path fill="#FF3D00" d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"/><path fill="#4CAF50" d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"/><path fill="#1976D2" d="M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"/></svg>
{t.account.socialGoogle}
</button>
<button type="button" class="btn-social btn-social-apple">
<svg width="15" height="18" viewBox="0 0 814 1000" fill="currentColor" aria-hidden="true"><path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-163.9-39.5c-76.4 0-103.5 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
{t.account.socialApple}
</button>
<button type="button" class="btn-social btn-social-paypal">
<span class="social-icon-badge" aria-hidden="true">P</span>
{t.account.socialPaypal}
</button>
<p class="small social-note" id="social-note">{t.account.socialComingSoon}</p>
</div>
<div class="social-divider">{t.account.orDivider}</div>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required autocomplete="email" /></div>
<div>
<label for="login-pw">{t.account.password}</label>
<div class="pw-field">
<input id="login-pw" type="password" autocomplete="current-password" />
<button
type="button"
class="pw-toggle"
id="login-pw-toggle"
data-show-label={t.account.showPassword}
data-hide-label={t.account.hidePassword}
aria-label={t.account.showPassword}
aria-pressed="false"
>
<svg id="login-pw-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle></svg>
</button>
</div>
</div>
<div class="checkbox-row">
<input id="login-remember" type="checkbox" />
<label for="login-remember">{t.account.rememberMe}</label>
</div>
<button class="btn btn-primary btn-block" type="submit">{t.account.loginButton}</button>
<p class="small" id="login-error" style="display:none; color: var(--c-sale);">{t.account.loginError}</p>
<a class="small" href="#">{t.account.forgotPassword}</a>
<p class="small login-consent">{t.account.consentPrefix} <a href="/datenschutz/">{t.account.consentLink}</a>{t.account.consentSuffix}</p>
</form>
<div class="card">
@@ -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 = `<path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle>`;
const EYE_CLOSED = `<path d="M3 3l18 18"></path><path d="M10.6 10.6a2 2 0 0 0 2.8 2.8"></path><path d="M9.9 4.24A9.9 9.9 0 0 1 12 4c7 0 11 7 11 7a13.2 13.2 0 0 1-3.4 4.06M6.1 6.1C3.5 7.9 1 12 1 12s4 7 11 7a9.9 9.9 0 0 0 4.9-1.24"></path>`;
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";
});
});
</script>
+75 -2
View File
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
<div class="container grid grid-2 account-grid">
<form class="frm card" id="login-form">
<h3>{t.account.loginTitle}</h3>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required /></div>
<div><label for="login-pw">{t.account.password}</label><input id="login-pw" type="password" /></div>
{/* Social-Login: in DE/DACH übliche Alternativen zu E-Mail/Passwort — Google und Apple
als verbreitetste Anbieter, PayPal zusätzlich wegen seiner Marktdominanz bei
Zahlungen in Deutschland (siehe Recherche). Ohne eigenes Backend noch nicht
funktional; ein Klick zeigt ehrlich den Phase-2-Hinweis statt eine Anmeldung
vorzutäuschen. */}
<div class="social-login">
<p class="small" style="margin:0 0 -0.2rem;">{t.account.socialHeading}</p>
<button type="button" class="btn-social btn-social-google">
<svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true"><path fill="#FFC107" d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12c0-6.627,5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24c0,11.045,8.955,20,20,20c11.045,0,20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"/><path fill="#FF3D00" d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"/><path fill="#4CAF50" d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"/><path fill="#1976D2" d="M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"/></svg>
{t.account.socialGoogle}
</button>
<button type="button" class="btn-social btn-social-apple">
<svg width="15" height="18" viewBox="0 0 814 1000" fill="currentColor" aria-hidden="true"><path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-163.9-39.5c-76.4 0-103.5 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
{t.account.socialApple}
</button>
<button type="button" class="btn-social btn-social-paypal">
<span class="social-icon-badge" aria-hidden="true">P</span>
{t.account.socialPaypal}
</button>
<p class="small social-note" id="social-note">{t.account.socialComingSoon}</p>
</div>
<div class="social-divider">{t.account.orDivider}</div>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required autocomplete="email" /></div>
<div>
<label for="login-pw">{t.account.password}</label>
<div class="pw-field">
<input id="login-pw" type="password" autocomplete="current-password" />
<button
type="button"
class="pw-toggle"
id="login-pw-toggle"
data-show-label={t.account.showPassword}
data-hide-label={t.account.hidePassword}
aria-label={t.account.showPassword}
aria-pressed="false"
>
<svg id="login-pw-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle></svg>
</button>
</div>
</div>
<div class="checkbox-row">
<input id="login-remember" type="checkbox" />
<label for="login-remember">{t.account.rememberMe}</label>
</div>
<button class="btn btn-primary btn-block" type="submit">{t.account.loginButton}</button>
<p class="small" id="login-error" style="display:none; color: var(--c-sale);">{t.account.loginError}</p>
<a class="small" href="#">{t.account.forgotPassword}</a>
<p class="small login-consent">{t.account.consentPrefix} <a href="/datenschutz/">{t.account.consentLink}</a>{t.account.consentSuffix}</p>
</form>
<div class="card">
@@ -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 = `<path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle>`;
const EYE_CLOSED = `<path d="M3 3l18 18"></path><path d="M10.6 10.6a2 2 0 0 0 2.8 2.8"></path><path d="M9.9 4.24A9.9 9.9 0 0 1 12 4c7 0 11 7 11 7a13.2 13.2 0 0 1-3.4 4.06M6.1 6.1C3.5 7.9 1 12 1 12s4 7 11 7a9.9 9.9 0 0 0 4.9-1.24"></path>`;
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";
});
});
</script>
+75 -2
View File
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
<div class="container grid grid-2 account-grid">
<form class="frm card" id="login-form">
<h3>{t.account.loginTitle}</h3>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required /></div>
<div><label for="login-pw">{t.account.password}</label><input id="login-pw" type="password" /></div>
{/* Social-Login: in DE/DACH übliche Alternativen zu E-Mail/Passwort — Google und Apple
als verbreitetste Anbieter, PayPal zusätzlich wegen seiner Marktdominanz bei
Zahlungen in Deutschland (siehe Recherche). Ohne eigenes Backend noch nicht
funktional; ein Klick zeigt ehrlich den Phase-2-Hinweis statt eine Anmeldung
vorzutäuschen. */}
<div class="social-login">
<p class="small" style="margin:0 0 -0.2rem;">{t.account.socialHeading}</p>
<button type="button" class="btn-social btn-social-google">
<svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true"><path fill="#FFC107" d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12c0-6.627,5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24c0,11.045,8.955,20,20,20c11.045,0,20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"/><path fill="#FF3D00" d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"/><path fill="#4CAF50" d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"/><path fill="#1976D2" d="M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"/></svg>
{t.account.socialGoogle}
</button>
<button type="button" class="btn-social btn-social-apple">
<svg width="15" height="18" viewBox="0 0 814 1000" fill="currentColor" aria-hidden="true"><path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-163.9-39.5c-76.4 0-103.5 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
{t.account.socialApple}
</button>
<button type="button" class="btn-social btn-social-paypal">
<span class="social-icon-badge" aria-hidden="true">P</span>
{t.account.socialPaypal}
</button>
<p class="small social-note" id="social-note">{t.account.socialComingSoon}</p>
</div>
<div class="social-divider">{t.account.orDivider}</div>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required autocomplete="email" /></div>
<div>
<label for="login-pw">{t.account.password}</label>
<div class="pw-field">
<input id="login-pw" type="password" autocomplete="current-password" />
<button
type="button"
class="pw-toggle"
id="login-pw-toggle"
data-show-label={t.account.showPassword}
data-hide-label={t.account.hidePassword}
aria-label={t.account.showPassword}
aria-pressed="false"
>
<svg id="login-pw-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle></svg>
</button>
</div>
</div>
<div class="checkbox-row">
<input id="login-remember" type="checkbox" />
<label for="login-remember">{t.account.rememberMe}</label>
</div>
<button class="btn btn-primary btn-block" type="submit">{t.account.loginButton}</button>
<p class="small" id="login-error" style="display:none; color: var(--c-sale);">{t.account.loginError}</p>
<a class="small" href="#">{t.account.forgotPassword}</a>
<p class="small login-consent">{t.account.consentPrefix} <a href="/datenschutz/">{t.account.consentLink}</a>{t.account.consentSuffix}</p>
</form>
<div class="card">
@@ -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 = `<path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle>`;
const EYE_CLOSED = `<path d="M3 3l18 18"></path><path d="M10.6 10.6a2 2 0 0 0 2.8 2.8"></path><path d="M9.9 4.24A9.9 9.9 0 0 1 12 4c7 0 11 7 11 7a13.2 13.2 0 0 1-3.4 4.06M6.1 6.1C3.5 7.9 1 12 1 12s4 7 11 7a9.9 9.9 0 0 0 4.9-1.24"></path>`;
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";
});
});
</script>
+75 -2
View File
@@ -19,11 +19,60 @@ const t = useTranslations(lang);
<div class="container grid grid-2 account-grid">
<form class="frm card" id="login-form">
<h3>{t.account.loginTitle}</h3>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required /></div>
<div><label for="login-pw">{t.account.password}</label><input id="login-pw" type="password" /></div>
{/* Social-Login: in DE/DACH übliche Alternativen zu E-Mail/Passwort — Google und Apple
als verbreitetste Anbieter, PayPal zusätzlich wegen seiner Marktdominanz bei
Zahlungen in Deutschland (siehe Recherche). Ohne eigenes Backend noch nicht
funktional; ein Klick zeigt ehrlich den Phase-2-Hinweis statt eine Anmeldung
vorzutäuschen. */}
<div class="social-login">
<p class="small" style="margin:0 0 -0.2rem;">{t.account.socialHeading}</p>
<button type="button" class="btn-social btn-social-google">
<svg width="18" height="18" viewBox="0 0 48 48" aria-hidden="true"><path fill="#FFC107" d="M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12c0-6.627,5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24c0,11.045,8.955,20,20,20c11.045,0,20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z"/><path fill="#FF3D00" d="M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z"/><path fill="#4CAF50" d="M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36c-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z"/><path fill="#1976D2" d="M43.611,20.083H42V20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571c0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z"/></svg>
{t.account.socialGoogle}
</button>
<button type="button" class="btn-social btn-social-apple">
<svg width="15" height="18" viewBox="0 0 814 1000" fill="currentColor" aria-hidden="true"><path d="M788.1 340.9c-5.8 4.5-108.2 62.2-108.2 190.5 0 148.4 130.3 200.9 134.2 202.2-.6 3.2-20.7 71.9-68.7 141.9-42.8 61.6-87.5 123.1-155.5 123.1s-85.5-39.5-163.9-39.5c-76.4 0-103.5 40.8-165.9 40.8s-105.6-57-155.5-127C46.7 790.7 0 663 0 541.8c0-194.4 126.4-297.5 250.8-297.5 66.1 0 121.2 43.4 162.7 43.4 39.5 0 101.1-46 176.3-46 28.5 0 130.9 2.6 198.3 99.2zm-234-181.5c31.1-36.9 53.1-88.1 53.1-139.3 0-7.1-.6-14.3-1.9-20.1-50.6 1.9-110.8 33.7-147.1 75.8-28.5 32.4-55.1 83.6-55.1 135.5 0 7.8 1.3 15.6 1.9 18.1 3.2.6 8.4 1.3 13.6 1.3 45.4 0 102.5-30.4 135.5-71.3z"/></svg>
{t.account.socialApple}
</button>
<button type="button" class="btn-social btn-social-paypal">
<span class="social-icon-badge" aria-hidden="true">P</span>
{t.account.socialPaypal}
</button>
<p class="small social-note" id="social-note">{t.account.socialComingSoon}</p>
</div>
<div class="social-divider">{t.account.orDivider}</div>
<div><label for="login-email">{t.account.email}</label><input id="login-email" type="email" required autocomplete="email" /></div>
<div>
<label for="login-pw">{t.account.password}</label>
<div class="pw-field">
<input id="login-pw" type="password" autocomplete="current-password" />
<button
type="button"
class="pw-toggle"
id="login-pw-toggle"
data-show-label={t.account.showPassword}
data-hide-label={t.account.hidePassword}
aria-label={t.account.showPassword}
aria-pressed="false"
>
<svg id="login-pw-icon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle></svg>
</button>
</div>
</div>
<div class="checkbox-row">
<input id="login-remember" type="checkbox" />
<label for="login-remember">{t.account.rememberMe}</label>
</div>
<button class="btn btn-primary btn-block" type="submit">{t.account.loginButton}</button>
<p class="small" id="login-error" style="display:none; color: var(--c-sale);">{t.account.loginError}</p>
<a class="small" href="#">{t.account.forgotPassword}</a>
<p class="small login-consent">{t.account.consentPrefix} <a href="/datenschutz/">{t.account.consentLink}</a>{t.account.consentSuffix}</p>
</form>
<div class="card">
@@ -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 = `<path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7Z"></path><circle cx="12" cy="12" r="3"></circle>`;
const EYE_CLOSED = `<path d="M3 3l18 18"></path><path d="M10.6 10.6a2 2 0 0 0 2.8 2.8"></path><path d="M9.9 4.24A9.9 9.9 0 0 1 12 4c7 0 11 7 11 7a13.2 13.2 0 0 1-3.4 4.06M6.1 6.1C3.5 7.9 1 12 1 12s4 7 11 7a9.9 9.9 0 0 0 4.9-1.24"></path>`;
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";
});
});
</script>