Alle ausstehenden Aenderungen (Bilder, Texte) fuer den Server-Umzug uebernommen
This commit is contained in:
+673
@@ -0,0 +1,673 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de" data-theme="dogfather">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>DogiCrew 🩵 — DOGFATHER UNIVERSE</title>
|
||||
<meta name="description" content="Unterstütze Dogfather dauerhaft mit der DogiCrew 🩵 und sammle exklusive Treueprämien — die Teddy-Kollektion entsteht in Kooperation mit VanVan." />
|
||||
<link rel="icon" type="image/png" href="assets/img/favicon.png" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<meta name="theme-color" content="#0b0d10" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="DOGFATHER UNIVERSE" />
|
||||
<meta property="og:title" content="DogiCrew 🩵 — DOGFATHER UNIVERSE" />
|
||||
<meta property="og:description" content="Unterstütze Dogfather dauerhaft mit der DogiCrew 🩵 und sammle exklusive Treueprämien — die Teddy-Kollektion entsteht in Kooperation mit VanVan." />
|
||||
<meta property="og:image" content="https://dogfather-universe.com/assets/img/og-cover.jpg" />
|
||||
<meta property="og:url" content="https://dogfather-universe.com/abonnieren.html" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="DogiCrew 🩵 — DOGFATHER UNIVERSE" />
|
||||
<meta name="twitter:description" content="Unterstütze Dogfather dauerhaft mit der DogiCrew 🩵 und sammle exklusive Treueprämien — die Teddy-Kollektion entsteht in Kooperation mit VanVan." />
|
||||
<meta name="twitter:image" content="https://dogfather-universe.com/assets/img/og-cover.jpg" />
|
||||
|
||||
<link rel="stylesheet" href="assets/css/main.css" />
|
||||
<link rel="stylesheet" href="assets/css/theme-dogfather.css" />
|
||||
<link rel="stylesheet" href="assets/css/theme-hasidog.css" />
|
||||
<link rel="stylesheet" href="assets/css/theme-spicymedia.css" />
|
||||
<style>
|
||||
/* =====================================================================
|
||||
Preis-/Anmelde-Kiste — komplett neu gestaltet (Nutzer-Feedback
|
||||
03.08.2026: "das sieht ja richtig kake aus"). Ziel: dasselbe edle
|
||||
Gold-Motiv wie beim Nav-Abo-Knopf/.btn-silver, klare visuelle
|
||||
Hierarchie (Preis dominiert, Bedingungen dezent, Formular großzügig),
|
||||
spürbar mehr Luft zwischen den Elementen statt der bisherigen dichten
|
||||
Textwand. Bewusst KEIN max-width auf der Box selbst — soll exakt so
|
||||
breit sein wie der umgebende .container (1180px), siehe Kommentar
|
||||
unten bei .abo-preis-box.
|
||||
===================================================================== */
|
||||
.abo-preis-box {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
overflow: hidden;
|
||||
padding: 2.6rem clamp(1.4rem, 5vw, 3.2rem) 3rem;
|
||||
border: 1.5px solid rgba(212,175,55,.45);
|
||||
background:
|
||||
radial-gradient(circle at 22% 0%, rgba(212,175,55,.16), transparent 55%),
|
||||
radial-gradient(circle at 82% 100%, rgba(139,92,246,.12), transparent 55%),
|
||||
linear-gradient(180deg, rgba(23,27,33,.96), rgba(15,17,21,.98));
|
||||
box-shadow: 0 0 0 1px rgba(212,175,55,.06) inset, 0 30px 60px -30px rgba(0,0,0,.6);
|
||||
}
|
||||
/* Feiner, ruhig schimmernder Goldrand oben — reines Deko-Element, kein
|
||||
rotierendes Objekt (siehe dokumentierte Lektion: rotierende Ringe auf
|
||||
nicht-runden Formen verzerren sich, deshalb hier nur ein sanftes
|
||||
Auf-und-Ab-Glühen statt einer Drehung). */
|
||||
.abo-preis-box::before {
|
||||
content: "";
|
||||
position: absolute; top: 0; left: 10%; right: 10%; height: 1px; z-index: 2;
|
||||
background: linear-gradient(90deg, transparent, rgba(255,214,102,.9), transparent);
|
||||
animation: abo-goldglanz 4.5s ease-in-out infinite;
|
||||
}
|
||||
@keyframes abo-goldglanz { 0%, 100% { opacity: .35; } 50% { opacity: 1; } }
|
||||
|
||||
/* Logo als leuchtendes Wasserzeichen im Kartenhintergrund (Nutzer-Wunsch
|
||||
03.08.2026: "mein Logo integriert, als Hintergrund, richtig geil,
|
||||
soll so geil dass man nicht davon wegkommt"). Freigestelltes Logo
|
||||
(logo-dogfather-transparent.png, siehe gate.html-Lektion: Original
|
||||
hatte einen weißen Hintergrund eingebrannt, hier bereits freigestellt)
|
||||
— groß, mittig, mit pulsierender Gold/Lila-Glut dahinter. Sitzt per
|
||||
z-index HINTER dem echten Karteninhalt (Preis/Formular), damit nichts
|
||||
an Lesbarkeit verliert; .abo-preis-box hat dafür isolation:isolate +
|
||||
overflow:hidden bekommen, damit die Glut nicht über den Kartenrand
|
||||
hinausblutet (dieselbe dokumentierte Lektion wie beim TikTok-Button-
|
||||
Glow). Bewusst KEINE Rotation des Logos selbst (nur Skalieren/
|
||||
Verblassen) — ein Markenlogo, das sich dreht, würde zeitweise auf dem
|
||||
Kopf stehen. */
|
||||
.abo-preis-box .abo-logo-glut {
|
||||
position: absolute; inset: -10%; z-index: -1; pointer-events: none;
|
||||
background:
|
||||
radial-gradient(circle at 50% 28%, rgba(255,233,168,.4) 0%, rgba(212,175,55,.16) 32%, transparent 62%),
|
||||
radial-gradient(circle at 22% 75%, rgba(139,92,246,.22), transparent 55%),
|
||||
radial-gradient(circle at 80% 80%, rgba(143,217,234,.16), transparent 55%);
|
||||
animation: abo-logo-glut-puls 5s ease-in-out infinite;
|
||||
}
|
||||
@keyframes abo-logo-glut-puls { 0%, 100% { opacity: .75; } 50% { opacity: 1; } }
|
||||
.abo-preis-box .abo-logo-wz {
|
||||
/* Bewusst NICHT inset:0 über die ganze (sehr hohe) Karte — dadurch
|
||||
wären background-position/mask-Prozentwerte relativ zur kompletten
|
||||
Kartenhöhe (inkl. Formular) berechnet und kaum kontrollierbar. Eine
|
||||
feste Zone oben (deckt Badge/Preis/Bedingungen ab) macht Position
|
||||
und Ausblenden vorhersagbar und garantiert, dass die Eingabefelder
|
||||
darunter sauber lesbar bleiben (Nutzer-Feedback: Logo lag vorher
|
||||
über dem Namensfeld). */
|
||||
position: absolute; top: 0; left: 0; right: 0; height: 420px; z-index: -1; pointer-events: none;
|
||||
background-image: url('assets/img/logo-dogfather-transparent.png');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center 6%;
|
||||
background-size: min(62%, 320px) auto;
|
||||
opacity: .4;
|
||||
filter: drop-shadow(0 0 28px rgba(255,233,168,.65)) drop-shadow(0 0 56px rgba(139,92,246,.4));
|
||||
-webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 92%);
|
||||
mask-image: linear-gradient(to bottom, #000 0%, #000 45%, transparent 92%);
|
||||
animation: abo-logo-wz-atem 6s ease-in-out infinite;
|
||||
}
|
||||
@keyframes abo-logo-wz-atem {
|
||||
0%, 100% { opacity: .32; transform: scale(.99); }
|
||||
50% { opacity: .48; transform: scale(1.03); }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.abo-preis-box .abo-logo-glut, .abo-preis-box .abo-logo-wz, .abo-preis-box::before { animation: none; }
|
||||
}
|
||||
|
||||
.abo-preis-box .eyebrow {
|
||||
display: inline-flex; align-items: center; gap: .5rem;
|
||||
color: #ffe9a8; border-color: rgba(255,214,102,.5);
|
||||
font-size: 1.3rem; letter-spacing: .1em;
|
||||
}
|
||||
.abo-preis-zahl {
|
||||
font-size: clamp(2.6rem, 5vw, 3.4rem); font-weight: 800; color: #ffe9a8;
|
||||
margin: .6rem 0 .2rem; letter-spacing: -.01em;
|
||||
text-shadow: 0 0 28px rgba(255,214,102,.35);
|
||||
}
|
||||
.abo-preis-zahl small { font-size: 1.05rem; font-weight: 600; color: var(--text-muted); letter-spacing: 0; text-shadow: none; }
|
||||
|
||||
.abo-bedingungen {
|
||||
list-style: none; padding: 0; text-align: left; max-width: 460px;
|
||||
margin: 1.6rem auto 0; display: flex; flex-direction: column; gap: .55rem;
|
||||
}
|
||||
.abo-bedingungen li {
|
||||
display: flex; align-items: flex-start; gap: .6rem;
|
||||
color: var(--text-muted); font-size: .96rem; line-height: 1.5;
|
||||
}
|
||||
.abo-bedingungen li::before {
|
||||
content: "✓"; flex-shrink: 0; width: 1.35rem; height: 1.35rem; margin-top: .05rem;
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
border-radius: 50%; font-size: .78rem; font-weight: 800;
|
||||
color: #0b0d10; background: linear-gradient(135deg, #ffe9a8, #d4af37);
|
||||
}
|
||||
|
||||
/* Widerrufsrecht-Checkbox (siehe agb.html Ziffer 6): NICHT vorausgewählt,
|
||||
sperrt die PayPal-Zahlungsoptionen optisch + funktional (pointer-events),
|
||||
bis sie aktiv angehakt wurde. */
|
||||
.abo-widerruf-check {
|
||||
display: flex; align-items: flex-start; gap: .65rem; text-align: left;
|
||||
max-width: 460px; margin: 0 auto 1.1rem; padding: .85rem .95rem; border-radius: 12px;
|
||||
background: rgba(255,255,255,.03); border: 1.5px solid rgba(139,92,246,.35);
|
||||
font-size: .85rem; line-height: 1.5; color: var(--text-muted); cursor: pointer;
|
||||
}
|
||||
.abo-widerruf-check input[type="checkbox"] {
|
||||
flex-shrink: 0; width: 1.15rem; height: 1.15rem; margin-top: .15rem; cursor: pointer; accent-color: #8b5cf6;
|
||||
}
|
||||
.abo-widerruf-check a { color: var(--accent); }
|
||||
#paypal-button-container.paypal-gesperrt { opacity: .35; filter: grayscale(1); pointer-events: none; min-height: 45px; }
|
||||
#paypal-gesperrt-hinweis { text-align: center; margin-top: .5rem; }
|
||||
|
||||
.abo-panel { max-width: 440px; margin: 2.2rem auto 0; }
|
||||
.abo-panel[hidden] { display: none; }
|
||||
|
||||
.abo-field { margin-bottom: 1.2rem; text-align: left; }
|
||||
.abo-field label {
|
||||
display: block; font-size: .82rem; font-weight: 600; letter-spacing: .02em;
|
||||
color: var(--text-muted); margin-bottom: .45rem;
|
||||
}
|
||||
.abo-field input {
|
||||
display: block; width: 100%; box-sizing: border-box;
|
||||
padding: .9rem 1.05rem; border-radius: 12px;
|
||||
background: rgba(255,255,255,.035); border: 1.5px solid var(--border); color: var(--text);
|
||||
font-size: 1.02rem; transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
|
||||
}
|
||||
.abo-field input::placeholder { color: rgba(154,164,178,.55); }
|
||||
.abo-field input:focus {
|
||||
outline: none; border-color: rgba(212,175,55,.7); background: rgba(255,255,255,.055);
|
||||
box-shadow: 0 0 0 4px rgba(212,175,55,.12);
|
||||
}
|
||||
|
||||
/* Registrieren/Login-Knöpfe: eigener Gold-Foil-Stil statt des generischen
|
||||
.btn-primary (Nutzer-Feedback 03.08.2026: "viel spezieller" + Text
|
||||
zentriert). Gleiche sichere Technik wie überall im Projekt — die
|
||||
Fläche schimmert per background-position, NICHT per rotierendem Ring
|
||||
(der würde auf dieser Pillenform verzerren, siehe dokumentierte
|
||||
TikTok-Button-Lektion). */
|
||||
.abo-panel .btn {
|
||||
position: relative; isolation: isolate; overflow: hidden;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
padding: 1rem 1.4rem; border-radius: 14px; font-weight: 800; font-size: 1.04rem;
|
||||
color: #1a1408; text-decoration: none; cursor: pointer;
|
||||
border: 1.5px solid rgba(255,233,168,.65);
|
||||
background: linear-gradient(120deg, #ffe9a8 0%, #d4af37 30%, #ffe9a8 55%, #fff2c9 78%, #d4af37 100%);
|
||||
background-size: 280% 100%;
|
||||
animation: abo-btn-shine 6s ease-in-out infinite;
|
||||
box-shadow: 0 10px 26px -12px rgba(212,175,55,.55);
|
||||
transition: transform .2s ease, box-shadow .2s ease;
|
||||
}
|
||||
.abo-panel .btn::before { content: none; }
|
||||
.abo-panel .btn::after {
|
||||
content: ""; position: absolute; inset: 0; z-index: 1;
|
||||
background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.85) 48%, transparent 66%);
|
||||
background-size: 240% 100%;
|
||||
mix-blend-mode: overlay;
|
||||
animation: abo-btn-glare 3.2s ease-in-out infinite;
|
||||
pointer-events: none;
|
||||
}
|
||||
.abo-panel .btn:hover {
|
||||
transform: translateY(-3px) scale(1.015);
|
||||
box-shadow: 0 16px 34px -10px rgba(212,175,55,.65), 0 0 26px rgba(212,175,55,.4);
|
||||
}
|
||||
@keyframes abo-btn-shine { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
|
||||
@keyframes abo-btn-glare { 0% { background-position: -80% 0; } 100% { background-position: 180% 0; } }
|
||||
@media (prefers-reduced-motion: reduce) { .abo-panel .btn { animation: none; } .abo-panel .btn::after { animation: none; } }
|
||||
|
||||
.abo-fehler { color: #ff9a9a; font-size: .88rem; margin: .8rem 0 0; display: none; }
|
||||
.abo-fehler.zeige { display: block; }
|
||||
.abo-erfolg { color: #baf7d6; font-size: .88rem; margin: .8rem 0 0; display: none; }
|
||||
.abo-erfolg.zeige { display: block; }
|
||||
|
||||
.abo-switch { text-align: center; margin-top: 1.4rem; font-size: .92rem; color: var(--text-muted); }
|
||||
.abo-switch a { color: var(--accent); cursor: pointer; font-weight: 600; }
|
||||
.abo-switch a:hover { text-decoration: underline; }
|
||||
|
||||
.abo-oder {
|
||||
display: flex; align-items: center; gap: .8rem;
|
||||
color: var(--text-muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .08em;
|
||||
margin: .3rem 0 1.4rem;
|
||||
}
|
||||
.abo-oder::before, .abo-oder::after { content: ""; flex: 1; height: 1px; background: var(--border); }
|
||||
|
||||
/* Google liefert seinen Knopf als eigenes iframe aus — die Innenfarben
|
||||
(Schwarz/Weiß/Blau) lassen sich aus Sicherheitsgründen NICHT per CSS
|
||||
umfärben. "Größer und passend zur Seite" wird deshalb über einen
|
||||
eigenen Goldrahmen drumherum gelöst (derselbe Schimmer-Trick wie beim
|
||||
Preis-Rahmen) plus einer Vergrößerung des Google-Knopfs selbst per
|
||||
transform:scale — der Knopf bleibt dabei voll funktionsfähig, es wird
|
||||
nur optisch skaliert. */
|
||||
.abo-google-frame {
|
||||
display: flex; justify-content: center; margin: 0 auto 1.3rem; padding: .55rem 0;
|
||||
border-radius: 999px; border: 1.5px solid transparent;
|
||||
background: linear-gradient(rgba(20,23,29,.5), rgba(20,23,29,.5)) padding-box,
|
||||
linear-gradient(120deg, #d4af37, #ffe9a8, #d4af37, #fff2c9) border-box;
|
||||
background-size: 100% 100%, 260% 100%;
|
||||
animation: abo-btn-shine 6s ease-in-out infinite;
|
||||
box-shadow: 0 10px 26px -12px rgba(212,175,55,.5);
|
||||
}
|
||||
.abo-google-frame > div { transform: scale(1.18); transform-origin: center; }
|
||||
|
||||
.abo-vorteile { max-width: 520px; margin: 1.6rem auto 0; display: flex; flex-direction: column; gap: .6rem; }
|
||||
.abo-vorteile li { display: flex; gap: .65rem; align-items: baseline; color: var(--text-muted); font-size: .97rem; line-height: 1.5; }
|
||||
.abo-vorteile li::before { content: "👑"; flex-shrink: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body class="mit-hintergrund" style="--page-bg:url('/assets/img/bg-abonnieren.jpg');--page-bg-mobile:url('/assets/img/bg-abonnieren-mobile.jpg');">
|
||||
<div id="site-header"></div>
|
||||
|
||||
<main>
|
||||
<section class="hero page-bg">
|
||||
<div class="hero-banner"><img src="/assets/img/bg-abonnieren.jpg" alt="Dogfather Supporter-Abo" loading="eager" /></div>
|
||||
<div class="container">
|
||||
<span class="eyebrow" data-i18n="ab_eyebrow">👑 DogiCrew 🩵</span>
|
||||
<h1 data-i18n="ab_h1">Mehr als ein Abo — deine Unterstützung wird Teil unserer Geschichte</h1>
|
||||
<p class="lead worlds" data-i18n="ab_lead">Kein gewöhnlicher Shop. Ein exklusives Dankeschön- und Treueprogramm für alle, die Dogfather dauerhaft unterstützen.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-tight">
|
||||
<div class="container">
|
||||
<div class="card abo-preis-box">
|
||||
<div class="abo-logo-glut" aria-hidden="true"></div>
|
||||
<div class="abo-logo-wz" aria-hidden="true"></div>
|
||||
<span class="eyebrow" data-i18n="ab_preis_eyebrow">DogiCrew 🩵</span>
|
||||
<div class="abo-preis-zahl">4,99 € <small data-i18n="ab_preis_pro_monat">/ Monat</small></div>
|
||||
<p class="small muted" style="margin-top:-.6rem;margin-bottom:1rem;">Keine gesondert ausgewiesene MwSt. gemäß Kleinunternehmerregelung (Art. 57 des luxemburgischen TVA-Gesetzes) — keine weiteren Kosten.</p>
|
||||
<ul class="abo-bedingungen">
|
||||
<li data-i18n="ab_bed1">Monatliche automatische Zahlung über PayPal</li>
|
||||
<li data-i18n="ab_bed2">Keine Mindestlaufzeit, jederzeit kündbar</li>
|
||||
<li data-i18n="ab_bed3">Kündigung zum Ende des bereits bezahlten Zeitraums</li>
|
||||
<li data-i18n="ab_bed4">Keine versteckten Zusatzkosten</li>
|
||||
</ul>
|
||||
|
||||
<!-- Zustand 1: lädt (kurz, bis localStorage/Session geprüft ist) -->
|
||||
<div class="abo-panel" id="panel-lade">
|
||||
<p class="small" data-i18n="ab_laedt">Einen Moment …</p>
|
||||
</div>
|
||||
|
||||
<!-- Professioneller Login: Google, sitzt über Registrierung/Login und
|
||||
wird zusammen mit ihnen ein-/ausgeblendet (siehe Skript unten).
|
||||
Ohne konfigurierte GOOGLE_CLIENT_ID bleibt der Bereich leer/
|
||||
unsichtbar — der normale E-Mail-Code-Weg funktioniert immer. -->
|
||||
<div class="abo-panel" id="panel-social-login" hidden>
|
||||
<!-- Datenschutz: Googles Skript (und damit eine Verbindung/IP-Übertragung
|
||||
zu Google) wird bewusst NICHT automatisch beim Seitenaufruf geladen,
|
||||
sondern erst nach explizitem Klick hier — echtes Opt-in statt
|
||||
versteckter Drittanbieter-Verbindung vor jeder Zustimmung. -->
|
||||
<div id="google-consent-wrap" style="text-align:center;margin-bottom:1.1rem;" hidden>
|
||||
<button type="button" id="google-consent-btn" class="btn btn-primary" style="width:100%;display:inline-flex;align-items:center;justify-content:center;gap:.6rem;">
|
||||
<svg width="20" height="20" viewBox="0 0 48 48" aria-hidden="true" style="flex-shrink:0;">
|
||||
<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-12s5.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,24s8.955,20,20,20s20-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>
|
||||
<span data-i18n="ab_google_consent_btn">Mit Google anmelden</span>
|
||||
</button>
|
||||
<p class="small muted" style="margin-top:.5rem;" data-i18n="ab_google_consent_hint">Beim Klick wird eine Verbindung zu Google hergestellt (deine IP-Adresse wird dabei übertragen).</p>
|
||||
</div>
|
||||
<div class="abo-google-frame" id="google-frame-wrap" hidden>
|
||||
<div id="google-signin-button"></div>
|
||||
</div>
|
||||
<div class="abo-oder" data-i18n="ab_oder_email">oder mit E-Mail</div>
|
||||
</div>
|
||||
|
||||
<!-- Zustand 2: Registrierung -->
|
||||
<div class="abo-panel" id="panel-register" hidden>
|
||||
<div class="abo-field">
|
||||
<label for="reg-name" data-i18n="ab_feld_name">Name oder Anzeigename</label>
|
||||
<input type="text" id="reg-name" maxlength="60" />
|
||||
</div>
|
||||
<div class="abo-field">
|
||||
<label for="reg-tiktok" data-i18n="ab_feld_tiktok">TikTok-Benutzername</label>
|
||||
<input type="text" id="reg-tiktok" placeholder="@benutzername" maxlength="40" />
|
||||
</div>
|
||||
<div class="abo-field">
|
||||
<label for="reg-email" data-i18n="ab_feld_email">E-Mail-Adresse</label>
|
||||
<input type="email" id="reg-email" maxlength="120" />
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" style="width:100%;" id="btn-register" data-i18n="ab_btn_register">Registrieren</button>
|
||||
<p class="abo-fehler" id="register-fehler"></p>
|
||||
<p class="abo-switch"><a id="switch-to-login" data-i18n="ab_switch_login">Schon Supporter? Hier einloggen</a></p>
|
||||
</div>
|
||||
|
||||
<!-- Zustand 3: Login (E-Mail-Code anfordern) -->
|
||||
<div class="abo-panel" id="panel-login" hidden>
|
||||
<div class="abo-field">
|
||||
<label for="login-email" data-i18n="ab_feld_email">E-Mail-Adresse</label>
|
||||
<input type="email" id="login-email" maxlength="120" />
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" style="width:100%;" id="btn-login-request" data-i18n="ab_btn_login_code">Login-Code anfordern</button>
|
||||
<p class="abo-fehler" id="login-fehler"></p>
|
||||
<p class="abo-switch"><a id="switch-to-register" data-i18n="ab_switch_register">Noch kein Konto? Jetzt registrieren</a></p>
|
||||
</div>
|
||||
|
||||
<!-- Zustand 4: Code-Eingabe (nach Registrierung ODER Login-Anfrage) -->
|
||||
<div class="abo-panel" id="panel-code" hidden>
|
||||
<p class="small" id="code-hinweis" data-i18n="ab_code_hinweis">Wir haben dir einen 6-stelligen Code per E-Mail geschickt.</p>
|
||||
<div class="abo-field">
|
||||
<label for="code-input" data-i18n="ab_feld_code">Code</label>
|
||||
<input type="text" id="code-input" inputmode="numeric" maxlength="6" style="letter-spacing:4px;font-size:1.3rem;text-align:center;" />
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary" style="width:100%;" id="btn-code-verify" data-i18n="ab_btn_code_verify">Bestätigen</button>
|
||||
<p class="abo-fehler" id="code-fehler"></p>
|
||||
</div>
|
||||
|
||||
<!-- Zustand 5: eingeloggt, noch kein Abo -> PayPal Smart Buttons.
|
||||
Zeigt automatisch alle für die Käuferin/den Käufer verfügbaren
|
||||
Zahlarten (PayPal-Konto, Kreditkarte als Gast, je nach Land) —
|
||||
das Geld landet dabei direkt auf Dogis eigenem PayPal-Konto. -->
|
||||
<div class="abo-panel" id="panel-subscribe" hidden>
|
||||
<p class="abo-erfolg zeige" data-i18n="ab_eingeloggt_als">Eingeloggt.</p>
|
||||
|
||||
<!-- Button-Lösung (§ 312j BGB / entspr. Regelung): Preis- und
|
||||
Zahlungspflicht-Hinweis unmittelbar vor der Zahlung. -->
|
||||
<p class="small" style="text-align:center;font-weight:700;margin-bottom:.8rem;">4,99 € / Monat · zahlungspflichtiges Abo · monatlich kündbar</p>
|
||||
|
||||
<!-- Widerrufsrecht bei digitalen Inhalten (§ 356 Abs. 5 BGB /
|
||||
entspr. Regelung, siehe agb.html Ziffer 6): ohne aktives
|
||||
Ankreuzen bleibt der Zahlungsbereich gesperrt, es gibt keine
|
||||
Zahlung ohne diese ausdrückliche, nicht vorausgewählte
|
||||
Zustimmung. -->
|
||||
<label class="abo-widerruf-check" for="widerruf-consent">
|
||||
<input type="checkbox" id="widerruf-consent" />
|
||||
<span>Ich wünsche ausdrücklich, dass der Zugang zum Supporter-Bereich sofort mit Vertragsschluss beginnt, und weiß, dass mein 14-tägiges Widerrufsrecht dadurch erlischt, sobald der Zugang vollständig bereitgestellt ist (Details in den <a href="agb.html" target="_blank" rel="noopener">AGB</a>, Ziffer 6).</span>
|
||||
</label>
|
||||
|
||||
<div id="paypal-button-container" class="paypal-gesperrt"></div>
|
||||
<p class="small muted" id="paypal-gesperrt-hinweis">Bitte bestätige oben die Checkbox, um die Zahlungsoptionen freizuschalten.</p>
|
||||
<p class="small" id="paypal-laedt" data-i18n="ab_paypal_laedt" hidden>Zahlungsoptionen werden geladen …</p>
|
||||
<p class="abo-fehler" id="subscribe-fehler"></p>
|
||||
</div>
|
||||
|
||||
<!-- Zustand 6: bereits Supporter -->
|
||||
<div class="abo-panel" id="panel-already" hidden>
|
||||
<p class="abo-erfolg zeige" data-i18n="ab_bereits_supporter">Du bist bereits Supporter! 🩵</p>
|
||||
<a class="btn btn-primary" style="width:100%;" href="supporter.html" data-i18n="ab_btn_zum_bereich">Zum Supporter-Bereich</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-tight">
|
||||
<div class="container grid grid-2">
|
||||
<div class="card">
|
||||
<p data-i18n="ab_text1">Dieses Abonnement ist kein gewöhnlicher Shop und kein einfacher Kauf. Es ist für die Menschen gedacht, die Dogfather dauerhaft unterstützen und ein besonderer Teil dieser gemeinsamen Reise sein möchten.</p>
|
||||
<p data-i18n="ab_text2">Für 4,99 € im Monat erhältst du Zugang zu einem exklusiven Supporter-Bereich, besonderen Inhalten und einer persönlichen Treuekollektion. Mit jedem erfolgreich bezahlten Meilenstein wächst deine Sammlung: vom kleinen Hasen-Teddy über besondere Jubiläumsprämien bis zum exklusiven Hoodie nach 30 Monaten. Danach beginnt für dich eine neue Kollektion — mit neuen Designs, neuen Erinnerungen und derselben Bedeutung.</p>
|
||||
<ul class="abo-vorteile">
|
||||
<li data-i18n="ab_vorteil1">Exklusiver Supporter-Bereich</li>
|
||||
<li data-i18n="ab_vorteil2">Kleiner Hasen-Teddy nach 6 bezahlten Monaten</li>
|
||||
<li data-i18n="ab_vorteil3">Mittelgroßer Hasen-Teddy nach 12 bezahlten Monaten</li>
|
||||
<li data-i18n="ab_vorteil4">Großer Hasen-Teddy nach 18 bezahlten Monaten</li>
|
||||
<li data-i18n="ab_vorteil5">Tasse & Autogrammkarte nach 24 bezahlten Monaten</li>
|
||||
<li data-i18n="ab_vorteil6">Exklusiver Hoodie nach 30 bezahlten Monaten</li>
|
||||
<li data-i18n="ab_vorteil7">Neue Supporter-Kollektion nach jedem abgeschlossenen Zyklus</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h2 data-i18n="ab_vanvan_h2">Die Teddy-Kollektion — in Kooperation mit VanVan</h2>
|
||||
<p data-i18n="ab_vanvan_text">Die DogiCrew 🩵 gehört Dogfather. Die Hasen-Teddys und die dazugehörigen Sammlerkollektionen entstehen jedoch in Zusammenarbeit mit VanVan — der rechten Hand von Dogfather, seiner wichtigsten Vertrauensperson und einem festen Bestandteil der Team-Dogi-Familie. Sie stehen für ihre besondere Rolle, den Zusammenhalt innerhalb der Community und die Verbindung zwischen Dogfather, VanVan und allen Menschen, die diesen gemeinsamen Weg dauerhaft unterstützen.</p>
|
||||
<div style="display:flex;justify-content:flex-end;margin-top:1.4rem;">
|
||||
<a class="btn-silver" href="#" aria-disabled="true" onclick="return false;"><span class="btn-silver-spark" aria-hidden="true">✨</span><span class="btn-silver-text" data-i18n="ab_kollektion_coming_soon">Coming soon…</span><span class="btn-silver-spark" aria-hidden="true">✨</span></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div id="site-footer"></div>
|
||||
<script src="assets/js/i18n-abonnieren.js"></script>
|
||||
<script src="assets/js/supporter.js"></script>
|
||||
<script src="assets/js/main.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
const S = window.DogiSupporter;
|
||||
const panels = ["panel-lade", "panel-register", "panel-login", "panel-code", "panel-subscribe", "panel-already"];
|
||||
// panel-social-login (Google-Button) hängt sich an register/login dran,
|
||||
// ist aber kein "richtiger" exklusiver Zustand — separat gesteuert.
|
||||
const SOCIAL_LOGIN_PANELS = ["panel-register", "panel-login"];
|
||||
let publicConfig = {
|
||||
googleClientId: null,
|
||||
paypalClientId: null, paypalPlanId: null,
|
||||
};
|
||||
|
||||
function irgendeinSocialLoginAktiv() {
|
||||
return !!publicConfig.googleClientId;
|
||||
}
|
||||
|
||||
function zeige(id) {
|
||||
panels.forEach((p) => { document.getElementById(p).hidden = p !== id; });
|
||||
const socialArea = document.getElementById("panel-social-login");
|
||||
socialArea.hidden = !(irgendeinSocialLoginAktiv() && SOCIAL_LOGIN_PANELS.includes(id));
|
||||
// Bugfix/Rechts-Update 04.08.2026: PayPal-Zahlungsoptionen werden NICHT
|
||||
// mehr automatisch beim Anzeigen dieser Kiste geladen — erst nach
|
||||
// aktivem Ankreuzen der Widerrufsrecht-Checkbox (siehe
|
||||
// widerrufCheckbox-Listener unten). Bei jedem erneuten Aufruf dieser
|
||||
// Kiste wird die Checkbox zurückgesetzt, die Zustimmung gilt immer nur
|
||||
// für den jeweils aktuellen Besuch.
|
||||
if (id === "panel-subscribe") {
|
||||
const check = document.getElementById("widerruf-consent");
|
||||
if (check) check.checked = false;
|
||||
document.getElementById("paypal-button-container").classList.add("paypal-gesperrt");
|
||||
document.getElementById("paypal-gesperrt-hinweis").hidden = false;
|
||||
}
|
||||
}
|
||||
function fehlerZeigen(el, msg) {
|
||||
el.textContent = msg;
|
||||
el.classList.add("zeige");
|
||||
}
|
||||
function fehlerVerstecken(el) {
|
||||
el.classList.remove("zeige");
|
||||
}
|
||||
|
||||
let codePurpose = "verify_email"; // oder "login"
|
||||
let codeEmail = "";
|
||||
|
||||
async function pruefeStatus() {
|
||||
if (!S.getToken()) {
|
||||
zeige("panel-register");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = await S.apiFetch("/supporter/me", {}, true);
|
||||
const status = data.subscription?.status || "none";
|
||||
S.cacheSubStatus(status);
|
||||
S.cacheDisplayName(data.profile?.displayName || "");
|
||||
if (["active", "pending", "suspended", "cancelled"].includes(status)) {
|
||||
zeige("panel-already");
|
||||
} else {
|
||||
zeige("panel-subscribe");
|
||||
}
|
||||
} catch (err) {
|
||||
// Token ungültig/abgelaufen -> zurück zur Registrierung/Login
|
||||
S.clearToken();
|
||||
zeige("panel-register");
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- "Mit Google anmelden" (professioneller Login, Abschnitt
|
||||
"screen1" Feedback vom 03.08.2026) — komplett optional, taucht nur
|
||||
auf, wenn der Websitebetreiber eine GOOGLE_CLIENT_ID hinterlegt hat.
|
||||
Datenschutz (Nachtrag 04.08.2026): Googles Skript wird NICHT mehr
|
||||
automatisch beim Seitenaufruf nachgeladen — das würde eine Verbindung
|
||||
zu Google (inkl. IP-Übertragung) herstellen, bevor der/die Besucher:in
|
||||
überhaupt zugestimmt hat. Stattdessen zeigt initGoogleConsent() nur
|
||||
einen eigenen, klar beschrifteten Button; erst der echte Klick darauf
|
||||
lädt Googles Skript und rendert deren echten Button (initGoogleSignIn). */
|
||||
function initGoogleConsent() {
|
||||
const wrap = document.getElementById("google-consent-wrap");
|
||||
const btn = document.getElementById("google-consent-btn");
|
||||
if (!publicConfig.googleClientId || !wrap || !btn) return;
|
||||
wrap.hidden = false;
|
||||
btn.addEventListener("click", () => {
|
||||
wrap.hidden = true;
|
||||
document.getElementById("google-frame-wrap").hidden = false;
|
||||
initGoogleSignIn();
|
||||
}, { once: true });
|
||||
}
|
||||
|
||||
function initGoogleSignIn() {
|
||||
if (!publicConfig.googleClientId) return;
|
||||
const script = document.createElement("script");
|
||||
script.src = "https://accounts.google.com/gsi/client";
|
||||
script.async = true;
|
||||
script.defer = true;
|
||||
script.onload = () => {
|
||||
window.google.accounts.id.initialize({
|
||||
client_id: publicConfig.googleClientId,
|
||||
callback: handleGoogleCredential,
|
||||
});
|
||||
window.google.accounts.id.renderButton(document.getElementById("google-signin-button"), {
|
||||
type: "standard", theme: "filled_black", size: "large", shape: "pill", text: "continue_with", width: 340,
|
||||
});
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
async function handleGoogleCredential(response) {
|
||||
const el = document.getElementById("register-fehler");
|
||||
fehlerVerstecken(el);
|
||||
try {
|
||||
const data = await S.apiFetch("/supporter/google-login", { credential: response.credential });
|
||||
S.setToken(data.token);
|
||||
await pruefeStatus();
|
||||
} catch (err) {
|
||||
fehlerZeigen(el, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- PayPal Smart Payment Buttons (Abschnitt "screen2" Feedback
|
||||
vom 03.08.2026: alle in Deutschland üblichen Zahlarten anzeigen — das
|
||||
übernimmt PayPal automatisch, sobald die echten Buttons statt einer
|
||||
reinen Weiterleitung genutzt werden). ---------- */
|
||||
let paypalSdkGeladen = false;
|
||||
// Zeitpunkt der Widerrufsrecht-Zustimmung (siehe Checkbox-Listener weiter
|
||||
// unten) — wird beim Abschluss an den Server mitgegeben, damit ein
|
||||
// Zeitstempel-Nachweis existiert (siehe Datenschutzerklärung Ziffer 7).
|
||||
let widerrufConsentAt = null;
|
||||
function ladePaypalButtons() {
|
||||
const fehlerEl = document.getElementById("subscribe-fehler");
|
||||
const ladeHinweis = document.getElementById("paypal-laedt");
|
||||
fehlerVerstecken(fehlerEl);
|
||||
ladeHinweis.hidden = false;
|
||||
ladeHinweis.textContent = "Zahlungsoptionen werden geladen …";
|
||||
if (!publicConfig.paypalClientId || !publicConfig.paypalPlanId) {
|
||||
ladeHinweis.textContent = "Das Bezahlsystem wird gerade eingerichtet — bitte später erneut versuchen.";
|
||||
return;
|
||||
}
|
||||
if (paypalSdkGeladen) {
|
||||
renderPaypalButtons();
|
||||
return;
|
||||
}
|
||||
const script = document.createElement("script");
|
||||
script.src = `https://www.paypal.com/sdk/js?client-id=${encodeURIComponent(publicConfig.paypalClientId)}&vault=true&intent=subscription¤cy=EUR&locale=de_DE`;
|
||||
script.onload = () => { paypalSdkGeladen = true; renderPaypalButtons(); };
|
||||
script.onerror = () => { ladeHinweis.textContent = "PayPal konnte nicht geladen werden. Bitte Seite neu laden."; ladeHinweis.hidden = false; };
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
function renderPaypalButtons() {
|
||||
const container = document.getElementById("paypal-button-container");
|
||||
const ladeHinweis = document.getElementById("paypal-laedt");
|
||||
container.innerHTML = "";
|
||||
window.paypal
|
||||
.Buttons({
|
||||
style: { shape: "pill", color: "gold", layout: "vertical", label: "subscribe" },
|
||||
createSubscription: (data, actions) => actions.subscription.create({ plan_id: publicConfig.paypalPlanId }),
|
||||
onApprove: async (data) => {
|
||||
const fehlerEl = document.getElementById("subscribe-fehler");
|
||||
try {
|
||||
await S.apiFetch("/supporter/paypal/confirm", { subscriptionId: data.subscriptionID, widerrufConsentAt }, true);
|
||||
await pruefeStatus();
|
||||
} catch (err) {
|
||||
fehlerZeigen(fehlerEl, err.message);
|
||||
}
|
||||
},
|
||||
onError: (err) => {
|
||||
fehlerZeigen(document.getElementById("subscribe-fehler"), "PayPal-Fehler: " + (err?.message || "Unbekannter Fehler."));
|
||||
},
|
||||
})
|
||||
.render("#paypal-button-container");
|
||||
ladeHinweis.hidden = true;
|
||||
}
|
||||
|
||||
document.getElementById("switch-to-login").addEventListener("click", () => zeige("panel-login"));
|
||||
document.getElementById("switch-to-register").addEventListener("click", () => zeige("panel-register"));
|
||||
|
||||
// Widerrufsrecht-Checkbox: erst nach aktivem Ankreuzen werden die
|
||||
// PayPal-Zahlungsoptionen überhaupt geladen/klickbar (siehe agb.html
|
||||
// Ziffer 6 + Datenschutzerklärung Ziffer 7). Beim Abwählen wird alles
|
||||
// wieder gesperrt und der Zeitstempel verworfen.
|
||||
document.getElementById("widerruf-consent").addEventListener("change", (e) => {
|
||||
const container = document.getElementById("paypal-button-container");
|
||||
const gesperrtHinweis = document.getElementById("paypal-gesperrt-hinweis");
|
||||
if (e.target.checked) {
|
||||
widerrufConsentAt = new Date().toISOString();
|
||||
container.classList.remove("paypal-gesperrt");
|
||||
gesperrtHinweis.hidden = true;
|
||||
ladePaypalButtons();
|
||||
} else {
|
||||
widerrufConsentAt = null;
|
||||
container.classList.add("paypal-gesperrt");
|
||||
gesperrtHinweis.hidden = false;
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("btn-register").addEventListener("click", async () => {
|
||||
const el = document.getElementById("register-fehler");
|
||||
fehlerVerstecken(el);
|
||||
const displayName = document.getElementById("reg-name").value.trim();
|
||||
const tiktokUsername = document.getElementById("reg-tiktok").value.trim();
|
||||
const email = document.getElementById("reg-email").value.trim();
|
||||
if (!displayName || !email) return fehlerZeigen(el, "Bitte Name und E-Mail-Adresse angeben.");
|
||||
try {
|
||||
await S.apiFetch("/supporter/register", { displayName, tiktokUsername, email });
|
||||
codePurpose = "verify_email";
|
||||
codeEmail = email;
|
||||
zeige("panel-code");
|
||||
} catch (err) {
|
||||
fehlerZeigen(el, err.message);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("btn-login-request").addEventListener("click", async () => {
|
||||
const el = document.getElementById("login-fehler");
|
||||
fehlerVerstecken(el);
|
||||
const email = document.getElementById("login-email").value.trim();
|
||||
if (!email) return fehlerZeigen(el, "Bitte E-Mail-Adresse angeben.");
|
||||
try {
|
||||
await S.apiFetch("/supporter/login-request", { email });
|
||||
codePurpose = "login";
|
||||
codeEmail = email;
|
||||
zeige("panel-code");
|
||||
} catch (err) {
|
||||
fehlerZeigen(el, err.message);
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("btn-code-verify").addEventListener("click", async () => {
|
||||
const el = document.getElementById("code-fehler");
|
||||
fehlerVerstecken(el);
|
||||
const code = document.getElementById("code-input").value.trim();
|
||||
if (!code) return fehlerZeigen(el, "Bitte Code eingeben.");
|
||||
try {
|
||||
const path = codePurpose === "login" ? "/supporter/verify-login" : "/supporter/verify-email";
|
||||
const data = await S.apiFetch(path, { email: codeEmail, code });
|
||||
S.setToken(data.token);
|
||||
await pruefeStatus();
|
||||
} catch (err) {
|
||||
fehlerZeigen(el, err.message);
|
||||
}
|
||||
});
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
const res = await fetch(`${S.API_BASE}/supporter/public-config`);
|
||||
const data = await res.json();
|
||||
if (data.ok) publicConfig = data;
|
||||
} catch {
|
||||
/* Konfiguration konnte nicht geladen werden — Google-Button/PayPal-Buttons bleiben dann aus. */
|
||||
}
|
||||
initGoogleConsent();
|
||||
await pruefeStatus();
|
||||
}
|
||||
|
||||
init();
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user