Die drei Fußzeilen-Spaltentitel (Filipe, Dogi&Hasi & Manager, Mehr) waren <h4>, obwohl der Hauptinhalt bei h2/h3 endet -- ein Sprung in der Überschriftenordnung (h2 -> h4) auf jeder Seite. Für Bildschirmleser ist die Überschriftenliste das Inhaltsverzeichnis; eine übersprungene Ebene stört die Orientierung. Jetzt <h2> (eigenständige Abschnitte unter der Seiten-h1). Die Optik bleibt exakt: Der CSS-Selektor .footer-grid h4 wurde zu .footer-grid h2 umgezogen, die kleine, gedämpfte Darstellung (.85rem, uppercase, Akzentfarbe) überschreibt weiterhin die große globale h2-Größe. Teil des Barrierefreiheits-Durchgangs (pruef-barrierefrei.mjs). Behebt die reinen Fußzeilen-Fälle; die Hauptinhalt-Überschriften folgen separat. Co-Authored-By: Claude Opus 5 <[email protected]>
930 lines
51 KiB
HTML
930 lines
51 KiB
HTML
<!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?v=20260828a" />
|
|
<link rel="stylesheet" href="assets/css/theme-dogfather.css?v=20260828a" />
|
|
<link rel="stylesheet" href="assets/css/theme-hasidog.css?v=20260828a" />
|
|
<link rel="stylesheet" href="assets/css/theme-spicymedia.css?v=20260828a" />
|
|
<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; }
|
|
|
|
/* Registrieren/Einloggen-Umschalter (21.08.2026, Nutzer-Wunsch: "die
|
|
sollen dann sofort immer den anmelde knopf auswählen können") — zwei
|
|
Segmente in einer Pille, aktiver Tab in Gold hervorgehoben, damit die
|
|
Wahl sofort ins Auge fällt, noch bevor überhaupt ein Formularfeld zu
|
|
sehen ist. Augenschonend: kein grelles Weiß, ruhiger Farbwechsel. */
|
|
/* =====================================================================
|
|
Aktionsleiste (21.08.2026) — EIN Element für beide Wege, statt vorher
|
|
doppeltem "Registrieren" (Umschalter oben + Knopf unten). Links die
|
|
eigentliche Aktion in Gold (unverändert im bestehenden Marken-Look),
|
|
rechts der Wechsel in Babyblau — der zweiten Hausfarbe der Seite
|
|
(theme-dogfather.css). Beide Hälften nutzen dieselbe Technik wie die
|
|
bestehenden Gold-Knöpfe (wandernder Verlauf per background-position +
|
|
ein durchlaufender Glanzstreifen als ::after) — dadurch wirken sie wie
|
|
ein zusammengehöriges Paar statt wie zwei fremde Knöpfe.
|
|
Augenschonend (Projektregel): kein Blinken/Flackern, nur ruhig
|
|
wandernde Verläufe, und bei prefers-reduced-motion steht alles still.
|
|
===================================================================== */
|
|
.abo-aktionsleiste {
|
|
display: flex; gap: .6rem; margin-top: .4rem;
|
|
}
|
|
/* flex-basis "auto" statt "0": jede Hälfte startet bei ihrer eigenen
|
|
Textbreite und wächst dann anteilig mit. Dadurch bekommt automatisch
|
|
die Seite mit dem längeren Text mehr Platz — egal ob das gerade links
|
|
("Login-Code anfordern") oder rechts ("Schon registriert? Einloggen")
|
|
ist. Mit fester 0-Basis wären beide exakt gleich breit gewesen und der
|
|
jeweils längere Text wäre auf zwei Zeilen umgebrochen. */
|
|
.abo-aktionsleiste > button {
|
|
position: relative; isolation: isolate; overflow: hidden;
|
|
flex: 1 1 auto; min-width: 0;
|
|
display: flex; align-items: center; justify-content: center; text-align: center;
|
|
padding: 1rem .95rem; border-radius: 14px;
|
|
font-weight: 800; font-size: .92rem; line-height: 1.25;
|
|
white-space: nowrap;
|
|
cursor: pointer;
|
|
transition: transform .2s ease, box-shadow .2s ease;
|
|
}
|
|
.abo-aktionsleiste > button::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-aktionsleiste > button:hover { transform: translateY(-3px) scale(1.015); }
|
|
|
|
/* Links: Gold — exakt die bestehende Knopf-Optik der Seite. */
|
|
.abo-aktion-haupt {
|
|
color: #1a1408;
|
|
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);
|
|
}
|
|
.abo-aktion-haupt:hover {
|
|
box-shadow: 0 16px 34px -10px rgba(212,175,55,.65), 0 0 26px rgba(212,175,55,.4);
|
|
}
|
|
|
|
/* Babyblau — gleiche Machart, kräftigeres Sky-Blau statt des sehr
|
|
blassen Standard-Babyblaus, damit es neben dem Gold nicht untergeht
|
|
(dieselbe Lektion wie auf der Verwaltungsseite). Dunkler Tiefsee-Text
|
|
darauf für klaren Kontrast; zusätzlich ein sanft atmender Ring, der die
|
|
Kachel leicht leuchten lässt, ohne zu blenden.
|
|
|
|
Zwei Namen, eine Optik: ".abo-aktion-neben" ist der Wechsel-Knopf neben
|
|
einer Gold-Aktion (Registrierungs-Seite), ".abo-aktion-blau" ist ein
|
|
Knopf, der selbst DIE Hauptaktion ist und trotzdem blau sein soll
|
|
(Einloggen-Seite, Nutzer-Wunsch 21.08.2026). Bewusst getrennte Namen,
|
|
damit später klar bleibt, warum ein Knopf blau ist. */
|
|
.abo-aktion-neben,
|
|
.abo-aktion-blau {
|
|
color: #05202b;
|
|
border: 1.5px solid rgba(224,247,254,.7);
|
|
background: linear-gradient(120deg, #e0f7fe 0%, #38bdf8 30%, #7dd3fc 55%, #f0fbff 78%, #38bdf8 100%);
|
|
background-size: 280% 100%;
|
|
animation: abo-btn-shine 6s ease-in-out infinite, abo-blau-atem 4.5s ease-in-out infinite;
|
|
box-shadow: 0 10px 26px -12px rgba(56,189,248,.6), 0 0 0 0 rgba(125,211,252,.5);
|
|
}
|
|
.abo-aktion-neben:hover,
|
|
.abo-aktion-blau:hover {
|
|
box-shadow: 0 16px 34px -10px rgba(56,189,248,.75), 0 0 30px rgba(125,211,252,.55);
|
|
}
|
|
@keyframes abo-blau-atem {
|
|
0%, 100% { box-shadow: 0 10px 26px -12px rgba(56,189,248,.55), 0 0 14px rgba(125,211,252,.25); }
|
|
50% { box-shadow: 0 12px 30px -12px rgba(56,189,248,.75), 0 0 26px rgba(125,211,252,.5); }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.abo-aktionsleiste > button,
|
|
.abo-aktionsleiste > button::after { animation: none; }
|
|
}
|
|
/* Auf schmalen Handys untereinander statt gequetscht nebeneinander. */
|
|
@media (max-width: 430px) {
|
|
.abo-aktionsleiste { flex-direction: column; gap: .55rem; }
|
|
.abo-aktionsleiste > button { font-size: .92rem; }
|
|
}
|
|
|
|
.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>
|
|
<!-- Bugfix/Nutzer-Wunsch 20.08.2026: Preis noch NICHT zeigen, solange die
|
|
Registrierung gesperrt ist (siehe .btn-gold-locked weiter unten) — sonst
|
|
wäre der Preis schon öffentlich, bevor überhaupt jemand abschließen kann.
|
|
Gleicher Chrome-Gold-Schimmer-Text wie beim gesperrten Knopf
|
|
(.btn-gold-locked-text), hier freistehend statt in einem Knopf. -->
|
|
<div class="abo-preis-zahl"><span class="btn-gold-locked-text" style="font-size:1em;" data-i18n="ab_kollektion_coming_soon">Coming soon…</span></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>
|
|
<!-- Bugfix/Nutzer-Wunsch 20.08.2026 (Nachpruefung): Nur der Knopf war
|
|
gesperrt, die drei Felder ließen sich trotzdem antippen und
|
|
beschreiben ("ich kann immer nur was rein tippen, soll garnicht
|
|
möglich sein"). Jetzt wie das E-Mail-Feld im Login-Panel: disabled
|
|
statt nur readonly, damit auch Tastatur-/Screenreader-Nutzung
|
|
korrekt "nicht bedienbar" meldet. -->
|
|
<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>
|
|
<!-- Das Zugangscode-Feld stand bis 21.08.2026 hier, direkt neben den
|
|
Stammdaten. Es ist bewusst in einen eigenen, SPÄTEREN Schritt
|
|
gewandert (Nutzer-Wunsch: "bei der ersten registrierung sollen
|
|
die eine email bekommen mit einem einmaligen code damit wir auch
|
|
wissen dass email stimmt und danach wenn sie den code eingegeben
|
|
haben sollen die erst ihren zugangscode auswählen/eintippen
|
|
können"). Ablauf jetzt: hier Stammdaten -> Einmalcode per Mail
|
|
(#panel-code) -> Zugangscode festlegen (#panel-neuer-code). -->
|
|
<p class="small muted" style="margin:-.2rem 0 .2rem;" data-i18n="ab_reg_hinweis_bestaetigung">Wir schicken dir gleich einen 6-stelligen Code per E-Mail. Danach legst du deinen eigenen Zugangscode fest.</p>
|
|
<!-- Nutzer-Wunsch 21.08.2026: "die leute sollen sich auch schon
|
|
registrieren können, aber der abo soll noch zu sein, da soll
|
|
dann coming soon stehen." Registrierung/Login sind ab jetzt
|
|
offen -- Konten können angelegt werden. Gesperrt bleibt NUR
|
|
noch der eigentliche Zahlungsschritt danach (siehe
|
|
panel-subscribe weiter unten), weil ohne Dogis echte PayPal-
|
|
Business-Zugangsdaten niemand wirklich zahlen kann. Wieder
|
|
normaler .btn-primary-Stil statt .btn-gold-locked. -->
|
|
<!-- Aktionsleiste (21.08.2026, Nutzer-Wunsch: "bringt nichts 2 mal
|
|
registrieren da zu haben"). EIN Element statt vorher Umschalter
|
|
oben + Knopf unten: links die eigentliche Aktion in Gold,
|
|
rechts der Wechsel zum Einloggen in Babyblau. Beide Hälften
|
|
sind immer aktiv (kein Tab-Zustand) — links macht etwas,
|
|
rechts wechselt die Ansicht. -->
|
|
<div class="abo-aktionsleiste">
|
|
<button type="button" class="abo-aktion-haupt" id="btn-register" data-i18n="ab_btn_register">Registrieren</button>
|
|
<button type="button" class="abo-aktion-neben" id="tab-login" data-i18n="ab_tab_login">Schon registriert? Einloggen</button>
|
|
</div>
|
|
<p class="abo-fehler" id="register-fehler"></p>
|
|
</div>
|
|
|
|
<!-- Zustand 3: Einloggen mit E-Mail + eigenem Zugangscode.
|
|
Umgestellt 21.08.2026 (Nutzer-Wunsch: "wieso sollte ich wieder
|
|
ein code bekommen, mach die anmeldung einfach"): vorher wurde
|
|
auch hier bei JEDEM Login erst ein Einmalcode per E-Mail
|
|
verschickt — für längst registrierte Leute ein völlig
|
|
unnötiger Umweg. Der E-Mail-Weg existiert weiterhin, aber nur
|
|
noch als "Code vergessen?" (siehe Link unten). -->
|
|
<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" autocomplete="email" />
|
|
</div>
|
|
<div class="abo-field">
|
|
<label for="login-code" data-i18n="ab_feld_code_eigen">Dein Zugangscode</label>
|
|
<input type="password" id="login-code" maxlength="200" autocomplete="current-password" />
|
|
</div>
|
|
<!-- Nutzer-Wunsch 21.08.2026: "da soll nur noch einloggen sein und
|
|
der knopf soll auch blau sein, der neu registriert soll weg."
|
|
Hier steht deshalb nur EIN Knopf, in Babyblau statt Gold —
|
|
wer auf dieser Ansicht gelandet ist, will einloggen; der Weg
|
|
zurück zur Registrierung führt über den Zurück-Knopf des
|
|
Browsers bzw. den blauen Knopf auf der Registrierungs-Seite. -->
|
|
<div class="abo-aktionsleiste">
|
|
<button type="button" class="abo-aktion-blau" id="btn-login" data-i18n="ab_btn_login">Einloggen</button>
|
|
</div>
|
|
<p class="abo-fehler" id="login-fehler"></p>
|
|
<p class="abo-switch"><a id="code-vergessen" data-i18n="ab_code_vergessen">Code vergessen?</a></p>
|
|
</div>
|
|
|
|
<!-- Zustand 4: Einmalcode aus der E-Mail eingeben. Kommt seit
|
|
21.08.2026 NUR noch im "Code vergessen?"-Weg vor — die normale
|
|
Registrierung/Anmeldung braucht ihn nicht mehr. -->
|
|
<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 4b: neuen dauerhaften Zugangscode festlegen. Letzter
|
|
Schritt des "Code vergessen?"-Weges — an dieser Stelle ist man
|
|
durch den Einmalcode bereits eingeloggt, es fehlt nur noch der
|
|
neue Code für künftige Anmeldungen. -->
|
|
<div class="abo-panel" id="panel-neuer-code" hidden>
|
|
<p class="small" data-i18n="ab_neuer_code_hinweis">Fast fertig — leg jetzt deinen neuen Zugangscode fest.</p>
|
|
<div class="abo-field">
|
|
<label for="neuer-code" data-i18n="ab_feld_code_neu">Dein Zugangscode (mindestens 6 Zeichen)</label>
|
|
<input type="password" id="neuer-code" maxlength="200" autocomplete="new-password" />
|
|
</div>
|
|
<button type="button" class="btn btn-primary" style="width:100%;" id="btn-neuer-code" data-i18n="ab_btn_code_speichern">Zugangscode speichern</button>
|
|
<p class="abo-fehler" id="neuer-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>
|
|
|
|
<!-- Nutzer-Wunsch 21.08.2026: "die leute sollen sich schon registrieren
|
|
können, aber der abo soll noch zu sein, da soll dann coming soon
|
|
stehen." Konto ist angelegt/Login hat geklappt -- aber die eigent-
|
|
liche Zahlung (PayPal) bleibt gesperrt, bis Dogis echte PayPal-
|
|
Business-Zugangsdaten stehen. Die echten Zahlungs-Elemente (Preis-
|
|
Hinweis, Widerrufs-Checkbox, PayPal-Container) bleiben unten UNVER-
|
|
ÄNDERT im DOM (nur per hidden versteckt), damit das Skript weiter
|
|
unten (Checkbox-Listener, ladePaypalButtons() usw.) unangetastet
|
|
funktioniert -- einfach das hidden am Wrapper unten entfernen,
|
|
sobald PayPal bereitsteht. -->
|
|
<div class="btn-gold-locked" style="width:100%;margin-top:.4rem;cursor:default;">
|
|
<span class="btn-gold-locked-lock" aria-hidden="true">🔒</span>
|
|
<span class="btn-gold-locked-text" data-i18n="ab_kollektion_coming_soon">Coming soon…</span>
|
|
</div>
|
|
<p class="small muted" style="text-align:center;margin-top:.9rem;" data-i18n="ab_subscribe_locked_hinweis">Dein Konto ist bereit — die Bezahlung startet, sobald das Abo offiziell live geht. Schau einfach bald wieder vorbei.</p>
|
|
|
|
<!-- Nutzer-Wunsch 21.08.2026: "ich will dass jetzt alles verbunden
|
|
ist so dass man mit den klicks pro klick weiter kommt" — vorher
|
|
war hier eine Sackgasse (kein Link/Knopf mehr nach dem Login).
|
|
Jetzt zwei klare Wege weiter: zurück zur Startseite, oder
|
|
direkt zum Streamplan (naheliegendster nächster Klick für
|
|
jemanden, der sich gerade für Dogi interessiert). -->
|
|
<div class="btn-row" style="justify-content:center;margin-top:1.4rem;">
|
|
<a class="btn btn-outline" href="index.html" data-i18n="ab_weiter_startseite">Zur Startseite →</a>
|
|
<a class="btn btn-outline" href="streamplan.html" data-i18n="ab_weiter_streamplan">Zum Streamplan →</a>
|
|
</div>
|
|
|
|
<div hidden>
|
|
<p class="small" style="text-align:center;font-weight:700;margin-bottom:.8rem;">4,99 € / Monat · zahlungspflichtiges Abo · monatlich kündbar</p>
|
|
<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>
|
|
</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>
|
|
<!-- Bugfix/Nutzer-Wunsch 20.08.2026: "4,99 €" hier entfernt (nur die Zahl, Rest
|
|
des Satzes unverändert) — sonst hätte der eigentlich gesperrte Preis
|
|
weiter oben in der Preis-Box hier im Fließtext trotzdem gestanden. -->
|
|
<p data-i18n="ab_text2">Mit deinem monatlichen Beitrag 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" aria-disabled="true"><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?v=20260828a"></script>
|
|
<script src="assets/js/supporter.js?v=20260828a"></script>
|
|
<script src="assets/js/main.js?v=20260828a"></script>
|
|
<script>
|
|
(function () {
|
|
const S = window.DogiSupporter;
|
|
const panels = ["panel-lade", "panel-register", "panel-login", "panel-code", "panel-neuer-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");
|
|
}
|
|
|
|
// Merkt sich die E-Mail-Adresse zwischen "Code vergessen?" und der
|
|
// Eingabe des Einmalcodes (der frühere codePurpose-Schalter entfiel mit
|
|
// der Umstellung 21.08.2026 — es gibt nur noch diesen einen Code-Weg).
|
|
let codeEmail = "";
|
|
// Merkt sich, WARUM gerade ein Einmalcode eingegeben wird (21.08.2026):
|
|
// "register" = Erstbestätigung der E-Mail, "login" = "Code vergessen?".
|
|
// Steuert in btn-code-verify, welcher Endpunkt aufgerufen wird.
|
|
let codeZweck = "login";
|
|
|
|
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 || "");
|
|
/* Nutzer-Wunsch 21.08.2026: "anstatt das was du jetzt auf dem screen
|
|
siehst, sollen die leute nicht mehr sehen wenn sie angemeldet sind.
|
|
sie sollen die richtige seite sehen die wir schon mal vorbereitet
|
|
hatten, wo sie ihre persönliche daten sehen und so."
|
|
|
|
Wer eingeloggt ist, gehört nicht mehr auf diese Anmeldeseite —
|
|
egal ob mit oder ohne bezahltes Abo. supporter.html zeigt in BEIDEN
|
|
Fällen das Richtige: persönliche Daten, Fortschritt mit allen
|
|
Prämien-Meilensteinen, Sammlungsarchiv, Profil bearbeiten,
|
|
Ausloggen — bei "kein Abo" eben mit entsprechendem Hinweis statt
|
|
echter Laufzeit. Vorher landete man hier stattdessen in einer
|
|
Sackgasse ("Coming soon…"), ohne je die eigentliche Seite zu sehen.
|
|
|
|
replace() statt href: die Anmeldeseite verschwindet damit aus dem
|
|
Verlauf — ein "Zurück" führt sonst sofort wieder hierher und von
|
|
hier wieder weiter, was sich wie eine Schleife anfühlt. */
|
|
location.replace("supporter.html");
|
|
return;
|
|
} 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;
|
|
}
|
|
|
|
// Der frühere Gegenstück-Knopf "Neu registrieren" auf der Einloggen-Seite
|
|
// wurde am 21.08.2026 auf Wunsch entfernt — deshalb hier nur noch der eine
|
|
// Wechsel von der Registrierung zum Einloggen.
|
|
document.getElementById("tab-login").addEventListener("click", () => zeige("panel-login"));
|
|
|
|
// 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 {
|
|
// Schritt 1 von 3 (21.08.2026): /supporter/register legt nur das noch
|
|
// unbestätigte Konto an und verschickt einen Einmalcode -- es kommt
|
|
// bewusst KEIN Token zurück, eingeloggt ist man erst nach Schritt 2.
|
|
await S.apiFetch("/supporter/register", { displayName, tiktokUsername, email });
|
|
codeEmail = email;
|
|
codeZweck = "register";
|
|
zeige("panel-code");
|
|
} catch (err) {
|
|
fehlerZeigen(el, err.message);
|
|
}
|
|
});
|
|
|
|
// Normale Anmeldung: E-Mail + eigener Zugangscode, ohne Umweg über E-Mail.
|
|
document.getElementById("btn-login").addEventListener("click", async () => {
|
|
const el = document.getElementById("login-fehler");
|
|
fehlerVerstecken(el);
|
|
const email = document.getElementById("login-email").value.trim();
|
|
const accessCode = document.getElementById("login-code").value;
|
|
if (!email || !accessCode) return fehlerZeigen(el, "Bitte E-Mail-Adresse und Zugangscode eingeben.");
|
|
try {
|
|
const data = await S.apiFetch("/supporter/login-code", { email, accessCode });
|
|
S.setToken(data.token);
|
|
await pruefeStatus();
|
|
} catch (err) {
|
|
fehlerZeigen(el, err.message);
|
|
}
|
|
});
|
|
|
|
// "Code vergessen?" — hier lebt der alte E-Mail-Einmalcode-Weg weiter.
|
|
document.getElementById("code-vergessen").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 zuerst deine E-Mail-Adresse eingeben.");
|
|
try {
|
|
await S.apiFetch("/supporter/login-request", { email });
|
|
codeEmail = email;
|
|
codeZweck = "login";
|
|
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 {
|
|
// Dieselbe Code-Eingabe bedient zwei Wege (21.08.2026):
|
|
// "register" -> Erstbestätigung der E-Mail bei der Registrierung
|
|
// "login" -> "Code vergessen?"-Weg für bestehende Konten
|
|
// Beide enden gleich: eingeloggt, danach Zugangscode festlegen.
|
|
const endpunkt = codeZweck === "register" ? "/supporter/verify-email" : "/supporter/verify-login";
|
|
const data = await S.apiFetch(endpunkt, { email: codeEmail, code });
|
|
S.setToken(data.token);
|
|
zeige("panel-neuer-code");
|
|
} catch (err) {
|
|
fehlerZeigen(el, err.message);
|
|
}
|
|
});
|
|
|
|
document.getElementById("btn-neuer-code").addEventListener("click", async () => {
|
|
const el = document.getElementById("neuer-code-fehler");
|
|
fehlerVerstecken(el);
|
|
const accessCode = document.getElementById("neuer-code").value;
|
|
if (!accessCode) return fehlerZeigen(el, "Bitte leg einen Zugangscode fest.");
|
|
try {
|
|
await S.apiFetch("/supporter/set-access-code", { accessCode }, true);
|
|
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. */
|
|
}
|
|
/* Bugfix 20.08.2026, wieder aktiviert 21.08.2026: "Mit Google anmelden" war ein
|
|
dritter, bisher übersehener Weg, trotz gesperrtem Registrieren-/Login-Knopf
|
|
doch ein echtes Konto anzulegen bzw. sich einzuloggen. War deshalb deaktiviert,
|
|
solange die Registrierung selbst gesperrt war. Registrierung ist jetzt (Nutzer-
|
|
Wunsch 21.08.2026) bewusst offen -- Google-Login ist nur ein weiterer,
|
|
gleichwertiger Weg zum selben jetzt erlaubten Ziel, kein Schlupfloch mehr. */
|
|
initGoogleConsent();
|
|
await pruefeStatus();
|
|
}
|
|
|
|
init();
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|