Abosystem mit dauerhaften Rabatten und Teddy-Prämien

Drei Mitgliedschaftsstufen (Klein 4,99€/5%, Mittel 9,99€/10%, Groß 19,99€/20%)
mit automatischem Bestellrabatt und Teddy-Prämien nach Meilensteinen (12-Monats-
Rhythmus bzw. 6+12 bei Groß). Preise/Rabatte und alle Admin-Regeln (Kombinier-
barkeit mit anderen Rabatten, Fortsetzung bei Wiederanmeldung, Monate über
Stufen zusammenzählen, kostenloser Versand bei Prämie) sind über Decap CMS
einstellbar (src/content/abo-einstellungen.json).

Neuer "Mein Abo"-Bereich im Kundenkonto (6. Nav-Kachel) mit Plan-Vergleich,
Live-Status (Laufzeit, nächste Zahlung, Rabatt, Fortschritt bis zur nächsten
Prämie), Einlösen-Buttons für freigeschaltete Teddys, Kündigen/Wechseln sowie
einer übersetzten Benachrichtigungsliste. Dazu ein extra hervorgehobener
"Mein Abo verwalten"-Button neben Abmelden in der Kopfkarte.

Warenkorb/Checkout rechnen den Abo-Rabatt korrekt in die Summe ein und stellen
eingelöste Teddys als 0€-Gratisposition dar. Alles in 4 Sprachen (DE/EN/CH/FR).

Unterwegs zwei echte Bugs gefunden und behoben: addMonateISO() vermischte
lokale Zeit mit toISOString() (UTC) und verlor dadurch bei jeder Monats-
verlängerung reproduzierbar einen Tag; die Checkout-Positionsliste zeigte für
Gratis-Prämien fälschlich den vollen Preis statt 0€.

Wie beim Treuebonus gilt: Speicherung aktuell im localStorage des Geräts
(Phase 1) statt einer echten geräteübergreifenden Datenbank — folgt mit der
Zahlungsanbindung in Phase 2.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
qcigano
2026-08-03 16:54:25 +02:00
co-authored by Claude Sonnet 5
parent 0cb7d3ca65
commit 208d995941
21 changed files with 1902 additions and 91 deletions
+90 -1
View File
@@ -1344,7 +1344,7 @@ a:focus-visible, button:focus-visible {
}
.account-head > * { position: relative; z-index: 1; }
.account-head-identity { display: flex; align-items: center; gap: 1rem; }
.account-head > #dash-logout-btn { margin-left: auto; }
.account-head-actions { margin-left: auto; display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.account-head h1 { margin: 0.2rem 0 0.5rem; }
.account-head .lead { margin: 0; max-width: 52ch; }
.account-head-sparkle {
@@ -1482,6 +1482,9 @@ a:focus-visible, button:focus-visible {
keinen Fall übersehen werden, wenn die Belohnung bereit ist. */
.account-nav-loyalty.is-ready { animation-duration: 1.4s, 1.1s; }
.account-nav-loyalty.is-ready::after { height: 4px; }
.account-nav-abo { --nav-color: #e3b23c; --nav-delay: 2s; }
.account-nav-abo.is-ready { animation-duration: 1.4s, 1.1s; }
.account-nav-abo.is-ready::after { height: 4px; }
/* Treuebonus-Fortschrittskarte im Inhaltsbereich — eigener grüner Farbton, sonst dieselbe
"besondere" Formsprache wie die anderen Konto-Karten (siehe .profile-card). */
@@ -2347,3 +2350,89 @@ a:focus-visible, button:focus-visible {
/* Konto */
.account-grid { align-items: start; }
/* "Mein Abo verwalten"-Button neben Abmelden: bewusst deutlich auffälliger als der normale
btn-outline-Rahmen der übrigen Kopfzeile — eigener Gold/Lila-Farbverlauf, wanderndes Glanzlicht
und ein leicht pulsierender Schein, damit der Einstieg ins neue Abosystem sofort ins Auge
fällt (explizit vom Kunden gewünscht: "ein mega geiler Button ... neben dem Abmelden"). */
.btn-abo-hero {
position: relative;
overflow: hidden;
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.7rem 1.3rem;
border-radius: var(--radius-l);
border: 1.5px solid transparent;
background:
linear-gradient(155deg, var(--c-anthracite-light), var(--c-anthracite)) padding-box,
linear-gradient(120deg, #e3b23c, #9b7fd6, var(--c-accent), #e3b23c) border-box;
background-size: 100% 100%, 300% 100%;
color: #f9e9b8;
font-weight: 800;
font-size: 0.95rem;
letter-spacing: 0.01em;
cursor: pointer;
animation: abo-hero-border-shift 5s ease-in-out infinite, abo-hero-glow 2.4s ease-in-out infinite;
transition: transform 0.2s var(--ease);
}
.btn-abo-hero:hover { transform: translateY(-2px) scale(1.03); }
.btn-abo-hero::after {
content: "";
position: absolute;
top: 0;
left: -60%;
width: 35%;
height: 100%;
background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.35), transparent);
transform: skewX(-18deg);
animation: account-head-shine 3.4s ease-in-out infinite;
pointer-events: none;
}
.btn-abo-hero-sparkle { display: inline-block; animation: account-nav-sparkle-twinkle 2.2s ease-in-out infinite; }
@keyframes abo-hero-border-shift {
0%, 100% { background-position: 0 0, 0% 50%; }
50% { background-position: 0 0, 100% 50%; }
}
@keyframes abo-hero-glow {
0%, 100% { box-shadow: 0 0 0 2px color-mix(in srgb, #e3b23c 30%, transparent), 0 0 16px -4px color-mix(in srgb, #e3b23c 60%, transparent); }
50% { box-shadow: 0 0 0 2px color-mix(in srgb, #9b7fd6 40%, transparent), 0 0 24px -2px color-mix(in srgb, #9b7fd6 70%, transparent); }
}
@media (prefers-reduced-motion: reduce) { .btn-abo-hero, .btn-abo-hero::after, .btn-abo-hero-sparkle { animation: none; } }
/* Abosystem: drei Planvergleichs-Karten + Statuskarte + Benachrichtigungsliste. */
.abo-plans { margin: 1.4rem 0 1.6rem; }
.abo-plan-card {
position: relative;
display: flex;
flex-direction: column;
gap: 0.6rem;
border: 1.5px solid rgba(244, 241, 247, 0.14);
transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.abo-plan-card:hover { transform: translateY(-3px); }
.abo-plan-klein { --plan-color: #6ecb8f; }
.abo-plan-mittel { --plan-color: var(--c-accent); }
.abo-plan-gross { --plan-color: #e3b23c; }
.abo-plan-card h3 { margin: 0.2rem 0 0; color: var(--plan-color, var(--c-accent)); }
.abo-plan-price { font-family: var(--font-head); font-size: 1.6rem; font-weight: 700; margin: 0; }
.abo-plan-vorteil { margin: 0; color: var(--c-text-muted); flex-grow: 1; }
.abo-plan-card.is-current-plan { border-color: var(--plan-color, var(--c-accent)); box-shadow: 0 0 0 1px color-mix(in srgb, var(--plan-color, var(--c-accent)) 50%, transparent), 0 0 20px -8px color-mix(in srgb, var(--plan-color, var(--c-accent)) 60%, transparent); }
.abo-plan-badge { align-self: flex-start; background: color-mix(in srgb, var(--plan-color, var(--c-accent)) 30%, transparent); border: 1px solid color-mix(in srgb, var(--plan-color, var(--c-accent)) 55%, transparent); border-radius: 999px; padding: 0.2rem 0.7rem; font-size: 0.78rem; font-weight: 700; }
.abo-plan-btn { align-self: flex-start; }
.abo-plan-btn:disabled { opacity: 0.6; cursor: default; }
.abo-status-card { margin-bottom: 1.4rem; }
.abo-status-card h3 { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.abo-badge-active { background: rgba(126, 200, 160, 0.28); border-color: rgba(126, 200, 160, 0.5); color: #cfeee0; }
.abo-badge-inactive { background: color-mix(in srgb, var(--c-sale) 30%, transparent); border-color: color-mix(in srgb, var(--c-sale) 55%, transparent); }
.abo-praemien-block { border-top: 1px dashed rgba(244, 241, 247, 0.14); padding-top: 0.9rem; margin-top: 0.3rem; }
.abo-praemien-block h4 { margin: 0 0 0.4rem; }
.abo-praemien-row { display: flex; gap: 0.7rem; flex-wrap: wrap; }
.abo-actions { display: flex; gap: 0.7rem; flex-wrap: wrap; margin-top: 0.6rem; }
.abo-cancel-btn { border-color: color-mix(in srgb, var(--c-sale) 55%, transparent); color: var(--c-sale); }
.abo-notif-list { list-style: none; margin: 0.6rem 0 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; max-height: 260px; overflow-y: auto; }
.abo-notif-item { padding: 0.5rem 0.7rem; border-radius: var(--radius-m); background: rgba(244, 241, 247, 0.05); border-left: 3px solid transparent; }
.abo-notif-item.abo-notif-unread { border-left-color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 10%, transparent); }
@media (prefers-reduced-motion: reduce) { .abo-plan-card { transition: none; } }