Neue Farbvariablen --c-lila/--c-lila-hover (sattes, kräftiges Violett) ersetzen das bisherige
Gold/Gelb überall dort, wo es verwendet wurde: "Noch nicht öffentlich"-Badge, Verlaufsrand der
Kopf-Kiste, sowie komplett das VanVan-Fenster (Rand, Avatar-Glow, Name, Eingabefeld-Fokus,
Button). Gelbes Herz-Emoji im VanVan-Button ebenfalls zu einem violetten Herz gewechselt, damit
nichts mehr gold/gelb übrig bleibt. Dogis Cyan-Fenster bleibt unverändert.
Per Build + Browsertest verifiziert: neue Farbe korrekt angezeigt, Login-Funktion unverändert.
Gemeldeter Bug: Bei kleineren Fensterhöhen (z.B. Laptop mit wenig Höhe, manche Handy-Größen) hat
"overflow: hidden" auf <body> zusammen mit der vertikal zentrierten Flexbox den oberen Teil des
Inhalts (Badge/Überschrift) und/oder die unteren Fenster einfach abgeschnitten, OHNE dass man
dorthin scrollen konnte — der Inhalt war schlicht nicht mehr erreichbar. Behoben:
- "align-items: safe center" statt nur "center" — zentriert normal, springt aber auf
Start-Ausrichtung um, sobald der Inhalt höher als der sichtbare Bereich ist.
- overflow-y: auto statt hidden — falls "safe center" von einem Browser nicht unterstützt wird,
kann trotzdem ganz normal zu den restlichen Fenstern heruntergescrollt werden.
- Logo-Wasserzeichen von position:absolute auf position:fixed umgestellt, damit es IMMER exakt in
der Mitte des sichtbaren Fensters bleibt, unabhängig von der tatsächlichen Seitenhöhe.
Zusätzlich auf ausdrücklichen Wunsch: der Kopfbereich (Badge + Überschrift + Text) sitzt jetzt in
einer eigenen "speziellen" Kiste im selben Stil wie die beiden Personen-Fenster darunter
(wandernder Verlaufsrand aus allen drei Markenfarben + Glanz-Sweep) statt als loser Text über den
Kisten zu schweben — liest sich jetzt sichtbar als gemeinsames "Dach" über beiden Fenstern.
Per Browsertest über mehrere Fenstergrößen (inkl. absichtlich sehr niedriger Höhe) verifiziert:
Inhalt vollständig erreichbar/scrollbar, Login-Funktion beider Fenster weiterhin unverändert.
- qciga-Fenster zeigt jetzt Dogi (Name + echtes Foto) statt Icon-Platzhalter — Rolle/Code-Prüfung
im Hintergrund bleibt unverändert "qciga" (nur die Anzeige wurde umbenannt).
- VanVan-Fenster bekommt ein neues, eigenes Foto für die Zugangsseite.
- Beide Quellfotos (~1,8 MB PNG) auf 400×400 zugeschnitten (gesichtsfokussiert) und als WebP
komprimiert (7–14 KB) — eigene Dateien nur für diese Seite, NICHT die sitehweit verwendete
öffentliche vanvan-portrait.png ersetzt oder angetastet.
- Schlüssel-Emoji im Dogi-Button durch 🩵 (Baby-Blau-Herz) ersetzt, passend zur Cyan-Akzentfarbe
seines Fensters.
- functions/_middleware.js: alte Freigabe von /img/vanvan-portrait.png entfernt, stattdessen
gezielt nur die zwei neuen Avatar-Dateien freigegeben (kein Shop-/Kundendatum).
Per Build + wrangler pages dev + Browsertest verifiziert: beide Avatare laden korrekt (200),
alte Foto-Freigabe korrekt entfernt (wieder 302), Layout/Funktion unverändert intakt.
Auf ausdrücklichen Wunsch im Stil einer bereits bestehenden Zwei-Personen-Zugangsseite umgebaut,
aber komplett an Van's eigene Marke angepasst (Farben/Schrift/Wasserzeichen unverändert: Lila/
Anthrazit/Hellblau/Gold statt fremder Projektfarben). Jede Person bekommt ihr eigenes Fenster mit
Avatar (VanVan: ihr echtes Porträtfoto; qciga: passendes Icon, da noch kein Foto in diesem Projekt
hinterlegt ist), eigenem Codefeld und eigenem "Öffnen"-Button in unterschiedlicher Akzentfarbe
(Cyan/Violett für qciga, Gold/Violett für VanVan). Technisch unverändert: /gate-auth erkennt die
Rolle weiterhin selbst anhand des eingegebenen Codes, unabhängig vom benutzten Fenster.
Dabei gefundener und behobener Bug: /img/vanvan-portrait.png wurde von der Zugangs-Schranke selbst
blockiert (302) — das für den Avatar gebrauchte Foto zeigte deshalb nur einen leeren Kreis. Gezielt
nur diese eine Datei freigegeben (kein Shop-/Kundendatum, ohnehin VanVans öffentliches Porträtfoto).
Per echtem Browsertest verifiziert: beide Fenster funktional getrennt (falscher Code im einen
Fenster zeigt den Fehler nur dort, richtiger Code im anderen Fenster loggt korrekt ein), Layout auf
Desktop nebeneinander und auf schmalen Bildschirmen sauber gestapelt.
Neues Kästchen "🔥 Nur Bestseller (Top 6)" im Shop-Filter (alle 4 Sprachen) — zeigt beim Anhaken
genau die 6 Produkte mit den meisten echten Verkäufen. Keine manuelle Pflege nötig: neuer
öffentlicher Endpunkt GET /api/bestseller berechnet die Rangliste live per SQL-Aggregation aus
den echten Bestelldaten (order_items JOIN orders, GROUP BY Produkt-Slug, SUM der Menge), NICHT
die manuell im Admin-Bereich setzbare "Bestseller"-Auszeichnung.
Zählweise: stornierte und noch nicht bezahlte (zahlungOffen) Bestellungen zählen nicht mit (sonst
würden Fehlbestellungen/nie eingegangene Zahlungen die Rangliste verfälschen), ebenso wenig
kostenlose Positionen wie der Abo-Teddy (kein echtes Kaufinteresse). Liefert ausschließlich
Produkt-Slugs zurück, keinerlei Bestell-/Kundendaten — bleiben weiterhin nur in /api/verwaltung/*.
Verifiziert: SQL-Aggregation mit Testdaten geprüft (korrekte Rangfolge, korrekter Ausschluss von
storniert/zahlungOffen/gratis, LIMIT 6 exakt). Frontend-Verdrahtung (Checkbox -> fetch -> Filter)
per echtem Browsertest mit vorgetäuschter API-Antwort bestätigt (checken zeigt genau die
vorgegebenen Produkte, abwählen zeigt wieder alle).
Neuer Endpunkt POST /gate-logout (functions/_middleware.js) löscht alle drei Zugangs-Cookies auf
einmal (normale 90-Tage-Sitzung, Rollen-Anzeige, tägliche Verwaltungs-Sitzung) — "abmelden"
bedeutet also wirklich abmelden von allem, nicht nur einen Teil der Schranke offen lassen. Button
im selben "besonderen" Look wie die Hero-Kiste darunter (wandernder Verlaufsrand in den drei
Markenfarben + Funkeln) statt eines schlichten Standard-Buttons.
Per curl (Cookie-Löschung + anschließende 302-Sperre auf /verwaltung/ und /) und per echtem
Browser-Klicktest (Playwright) end-to-end verifiziert.
Live per Browsertest gefunden: Auf /admin/ (das die Haupt-Schranke bewusst umgeht) versucht ein
eigenes Skript, den Service Worker unter /sw.js zu registrieren (für die "Installieren"-Funktion) —
das schlug mit einem echten Browserfehler fehl ("script resource is behind a redirect"), weil
/sw.js und /manifest.webmanifest bisher nicht auf der Liste öffentlich erreichbarer Dateien standen
und deshalb selbst einen 302 auf die Zugangscode-Seite bekamen. Betrifft jeden Aufruf von /admin/
ohne aktive Haupt-Gate-Sitzung (z.B. direkt per Lesezeichen). Beide Dateien enthalten keinerlei
Shop-/Kundendaten (reines Caching-Skript bzw. App-Metadaten), Freigabe also unbedenklich — vor der
Änderung geprüft, dass wirklich nichts Sensibles drin steht.
Bisher hätte SITE_PUBLIC=true (gedacht für den Go-Live der eigenen Domain) versehentlich auch die
interne *.pages.dev-Werkstatt-Adresse für jede/n im Internet geöffnet, weil die Middleware nur den
Pfad, nie den aufgerufenen Hostnamen geprüft hat. Jetzt hart anhand des Hostnamens geprüft: nur ein
Hostname außerhalb von *.pages.dev darf durch SITE_PUBLIC öffentlich werden. Per wrangler pages dev
mit Host-Header-Overrides verifiziert (pages.dev -> weiterhin 302 Gate-Redirect, andere Domain -> 200).
Nebenbei: totes, seit 04.08.2026 ungenutztes Secret VERWALTUNG_ACCESS_CODE live + lokal entfernt
(Code prüft seitdem denselben Zugangscode wie der normale Seitenzugang), sowie zwei veraltete
Kommentare bereinigt, die noch auf die längst entfernte Seite /demo-abo/ verwiesen.
Beide <script>-Blöcke am Ende von shop/index.astro (+en/ch/fr) liefen bisher direkt beim Parsen,
statt wie in Layout.astro etabliert in "astro:page-load" gekapselt zu sein. Da <ClientRouter
fallback="swap" /> Inline-Skripte bei einem clientseitigen Seitenwechsel nicht erneut ausführt,
wurden die Klick-Listener der beiden eigenen Dropdowns nie angehängt, wenn man per Link (statt
Direktaufruf) auf /shop/ navigiert ist — Preis-Regler/Checkbox blieben unbemerkt funktionsfähig,
weil das natives Browser-Verhalten ohne JS ist.
Auf ausdrücklichen Wunsch: das rotierende Logo-Wasserzeichen im Hintergrund der Verwaltungs-
Hauptseite wirkte als EIN großer zentraler Fleck (zwei große, zentrierte Ebenen). Jetzt sechs
kleinere Logos (150-260px statt 950-1500px), über den ganzen Viewport verteilt (obere/mittlere/
untere Zeile, je links und rechts), weiterhin gegenläufig rotierend, jetzt zusätzlich mit einer
dritten Markenfarbe (Cyan) neben Gold/Violett für mehr Abwechslung. Reine Markup-/CSS-Änderung.
Zusätzlich: die Standard-Browser-Scrollbar im Kategorie-Dropdown des Shop-Filters (schwarz-weiß,
wirkte fremd im dunklen Design) durch eine gestylte, schlanke, markenfarbene Verlaufs-Scrollbar
ersetzt (Firefox über scrollbar-color/-width, Chrome/Edge/Safari über ::-webkit-scrollbar).
Lokal mit wrangler pages dev getestet (beide Änderungen im ausgelieferten CSS bestätigt).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch: oben auf jeder Produktseite jetzt ein "← Zurück"-Button vor dem
Breadcrumb. Nutzt den Browser-Verlauf (history.back()) statt fest zur Kategorieseite zu
springen — landet man z.B. von der Startseite, einer Suche oder "Das könnte dir gefallen" auf
einer Produktseite, kommt man genau dahin zurück. Fällt sauber auf einen normalen Link zur
Kategorieseite zurück, wenn kein echter vorheriger Seitenaufruf im Verlauf existiert (Direkt-
aufruf, neuer Tab, Suchmaschine). In allen 4 Sprachversionen (de/en/ch/fr) umgesetzt.
Nebenbei behoben: t.common.skipToContent (Skip-Link aus der BFSG-Barrierefreiheits-Arbeit vom
04.08.) war nur für "de" gepflegt und dadurch auf den en/ch/fr-Seiten leer — jetzt für alle
4 Sprachen ergänzt (gleicher Commit, da hier ohnehin dieselbe common-Sektion bearbeitet wurde).
Lokal mit wrangler pages dev end-to-end getestet (Login, echtes Produkt, Button + Skript im
gerenderten HTML bestätigt).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch NUR die Haupt-Bestellverwaltungsseite (nicht die Zugangscode-Seite,
nicht deren Formular-Logik) grundlegend aufgewertet:
- Rollenbasierte, tageszeitabhängige Begrüßung ("Guten Morgen, VanVan!") aus dem vorhandenen
Vorschau-Rollen-Cookie
- Van's-Logo als großes, fix positioniertes, warm eingefärbtes Wasserzeichen im gesamten
Seitenhintergrund (zwei gegenläufig rotierende Ebenen, derselbe CSS-Trick wie auf der
Zugangscode-Seite, aber eigenständig für diese scrollbare Seite nachgebaut)
- Handgebaute SVG-Sparkline (Umsatztrend der letzten 14 Tage) + Wochenvergleich-Badge
- Sanft hochzählende Kennzahlen-Kacheln statt abruptem Zahlensprung
- Sichtbarer Status-Fortschrittsbalken pro Bestellkarte + Ein-Klick-"nächster Schritt"-Knopf
neben dem bisherigen Dropdown
- Konfetti + Erfolgs-Banner bei runden Bestell-Meilensteinen (10er/25er/50er-Schritte)
- Tab-Titel zeigt die Anzahl offener Bestellungen, auch wenn der Tab im Hintergrund ist
- Optionaler Ton (Web-Audio-Glöckchen, keine Audio-Datei) und Desktop-Benachrichtigungen bei
neuen Bestellungen, beides einzeln togglebar und in localStorage gemerkt
Alles handgebaut ohne externe Bibliotheken/Kosten, respektiert prefers-reduced-motion. Lokal mit
wrangler pages dev + echter D1-Bindung end-to-end getestet (Login, Bestell-API, Status-PATCH,
alle neuen UI-Elemente im Seiten-HTML verifiziert).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Bug: bei Produkten mit mehreren Fotos (z.B. Armbändern) sprang ein Klick auf den ‹/›-Pfeil
zum Bildwechsel kurz zum nächsten Foto und öffnete dann trotzdem sofort die volle
Produktseite. Ursache: Astros <ClientRouter /> (View-Transitions, siehe Layout.astro) fängt
Klicks auf <a>-Links über einen eigenen, früher registrierten document-Klick-Listener in der
Bubble-Phase ab und startet die Navigation, BEVOR der Karussell-Klick-Handler von ProductCard
(der ebenfalls in der Bubble-Phase lief) preventDefault()/stopPropagation() aufrufen konnte.
Fix: Karussell-Klick-Handler läuft jetzt in der Capture-Phase (wie schon beim benachbarten
Wisch-Sperr-Handler etwas weiter unten in derselben Datei) — läuft dadurch garantiert vor
ClientRouters eigenem Listener und verhindert die Navigation zuverlässig, bevor sie startet.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Fix für gemeldetes Problem: VanVans Code funktionierte nicht auf der Verwaltungsseite. Ursache
war ein dritter, komplett separater, gemeinsamer Code (6GAM4AST), den sich niemand gemerkt
hatte — VanVan gab stattdessen ihren normalen persönlichen Zugangscode ein, der dort aber nicht
galt. Jetzt auf ausdrücklichen Wunsch vereinheitlicht: die Verwaltungsseite prüft denselben
persönlichen Code wie der normale Seitenzugang (SITE_ACCESS_CODE_QCIGA/_VANVAN). Die tägliche
Neueingabe-Pflicht bleibt bestehen (eigene Sitzung mit 24h statt 90 Tagen Gültigkeit) — nur der
geprüfte Code ist jetzt kein separater dritter mehr. Das alte Secret VERWALTUNG_ACCESS_CODE wird
nicht mehr verwendet. Lokal mit wrangler pages dev end-to-end getestet (beide Codes + alter Code
korrekt abgelehnt).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch NUR diese eine Zugangsseite (öffentliche Startseite und die
eingeloggte Verwaltung selbst bleiben unangetastet): zwei groß und gegenläufig rotierende,
warm golden bzw. violett eingefärbte Van's-Logo-Wasserzeichen im gesamten Fensterhintergrund,
plus das echte Logo als sich drehendes "Siegel" im Kästchen mit pulsierendem Glanz-Kreis und
drei zeitversetzt aufblitzenden Funkel-Emojis. Ziel: die tägliche Pflicht-Eingabe soll Freude
machen statt trockene Sicherheitsabfrage zu sein. Alle Animationen respektieren weiterhin
prefers-reduced-motion. Reine Design-Änderung, Formular-/Auth-Logik unverändert.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Technisches Accessibility-Audit ergab sechs behebbare Punkte, alle jetzt gefixt:
- Skip-to-Content-Link ganz oben auf jeder Seite (WCAG 2.4.1)
- Fehler-/Statusmeldungen (Checkout, Login, Rezension, Gate-/Verwaltungs-Code) jetzt mit
role="alert"/aria-live, damit Screenreader sie automatisch ansagen (WCAG 4.1.3)
- Warenkorb-Icon hatte fälschlich das "Konto"-Label geerbt, sagt jetzt korrekt "Warenkorb"
(WCAG 4.1.2/2.4.4), dafür t.nav.cart in allen 4 Sprachen neu ergänzt
- Sichtbarer Fokus-Ring beim Mengenfeld auf der Produktseite wiederhergestellt (WCAG 2.4.7)
- Placeholder-only Formularfelder (Gate-Zugangscode, Verwaltungs-Suche/Filter/Tracking) haben
jetzt echte Labels (sichtbar per sr-only-Klasse oder aria-label) statt nur Platzhaltertext
(WCAG 1.3.1/3.3.2)
- Übersprungene Überschriften-Ebenen (h1→h3 ohne h2) in Checkout, Warenkorb, Kontakt, Konto
korrigiert (WCAG 1.3.1)
Reine Accessibility-Nachrüstung, keine funktionale Änderung. Kleinstunternehmer-Ausnahme
(§3 Abs.3 BFSG) greift hier vermutlich, aber vorsorglich sauber umgesetzt.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Der Name "Tages-Code" konnte fälschlich als sich täglich änderndem/rotierendem Code
verstanden werden. Tatsächlich bleibt der Code dauerhaft gleich (6GAM4AST) — nur die
24h-Sitzung läuft ab, wodurch derselbe Code einmal pro Tag erneut eingegeben werden
muss. Reine Text-/Kommentar-Korrektur, keine Verhaltensänderung.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch: /verwaltung/ + /api/verwaltung/* verlangen jetzt ZUSÄTZLICH zum
normalen 90-Tage-Seitenzugang einen zweiten, eigenen Code, den nur qciga und VanVan kennen —
und der nach 24 Stunden automatisch abläuft (muss also einmal täglich neu eingegeben werden).
Der Rest der Seite ist davon unberührt, nur die Bestellübersicht ist betroffen.
Bewusst als eigenständiges System (eigenes Cookie vandiy_verwaltung_session, eigenes Geheimnis
VERWALTUNG_SESSION_SECRET, eigener HMAC-Signaturcode statt geteiltem mit dem normalen
Seitenzugang) — gleiches Trennungsprinzip wie bei den Kundenkonten: ein Leck bei einer
Sitzungsart darf nie die andere gefährden.
Neue Dateien: functions/_shared/verwaltung-auth.js (Session-Logik), public/verwaltung-code.html
(Eingabemaske im selben Stil wie die Haupt-Zugangsseite). functions/_middleware.js prüft nach
erfolgreicher Haupt-Sitzung zusätzlich diese zweite Sitzung für /verwaltung*-Pfade. Beide
API-Routen (orders.js, orders/[id].js) prüfen die zweite Schranke zusätzlich eigenständig,
nach demselben Verteidigungs-in-der-Tiefe-Prinzip wie die bestehende Haupt-Prüfung.
Lokal vollständig durchgetestet (wrangler pages dev): kompletter Ablauf ohne jeden Zugang ->
Haupt-Gate -> Redirect zum Tages-Code -> falscher Code abgelehnt -> richtiger Code setzt
24-Stunden-Cookie -> Seite und API danach erreichbar. Bestätigt: der Rest der Seite bleibt
unberührt (kein Tages-Code nötig), UND dass VanVan mit nur dem Haupt-Zugang (ohne Tages-Code)
ebenfalls noch ausgesperrt bleibt, wie gewünscht.
Zwei neue Cloudflare-Secrets in Produktion gesetzt: VERWALTUNG_SESSION_SECRET (zufällig
erzeugt) und VERWALTUNG_ACCESS_CODE (der eigentliche Tages-Code, an qciga und VanVan zu
verteilen).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch: statt der vagen Ersatzformulierung "Teddy aus einer früheren
Einlösung" zeigt die Liste "Diese Teddys hast du schon bekommen" jetzt fuer JEDEN Eintrag
den echten Produktnamen + eine kleine Vorschau — auch fuer Einloesungen von vor diesem
Feature, bei denen kein Name gespeichert war. Das geht zuverlaessig, weil es je Groesse
aktuell nur EIN konfiguriertes Teddy-Produkt gibt (aboEinstellungen.kleinTeddySlug/
grossTeddySlug) — es gibt also keine Mehrdeutigkeit, welcher Teddy es war.
Mini-Foto: echtes Produktfoto, sobald VanVan eins im Adminbereich hochlaedt (automatisch,
ohne Code-Aenderung) — bis dahin ein gestalteter Platzhalter statt eines kaputten Bildes,
da beide Teddy-Produkte aktuell noch kein Foto hinterlegt haben.
Dabei einen echten Datenfehler gefunden und behoben: der KLEINE Teddy trug auf Englisch
"Large Teddy" und auf Schweizerdeutsch "Grosse Teddy" (Kopierfehler vom grossen Teddy) —
war nicht nur in dieser Liste sichtbar, sondern auch auf der Produktseite selbst in allen
nicht-deutschen Sprachen. Jetzt korrekt "Small Teddy" / "Chliine Teddy" / "Petit ours en peluche".
Getestet (Browser): genau der Fall aus der Rückmeldung nachgestellt (2 alte Einlösungen ohne
Namensverlauf) — zeigt jetzt Name + Link statt "unbekannt". Gemischter Fall (echter + alter
Eintrag) korrekt sortiert. Vorhandenes Foto ersetzt den Platzhalter automatisch. Korrigierte
Produktnamen in allen 4 Sprachen bestätigt.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch: die Visa-/Mastercard-Badges in der unteren Hälfte sehen jetzt genauso
"fertig" aus wie das PayPal-Badge oben — größer (48x48 statt 40x27), mit demselben weichen
Glanz-Verlauf, kräftigem Schlagschatten in der jeweiligen Markenfarbe und Lift-Effekt beim
Hovern. Die Markenfarben selbst bleiben unverändert (Visa weiß, Mastercard schwarz).
Die untere Hälfte hat jetzt außerdem eine EIGENE Farbgebung statt eines Blau-Abklatschs der
PayPal-Hälfte darüber: dezentes Visa-Blau unten links, Mastercard-Orange/Rot oben rechts,
beide nur angedeutet (niedrige Deckkraft) auf dunklem Grund, damit Text und Karten weiterhin
klar lesbar bleiben.
Getestet: Breiten-Sweep 390–1440px ohne Überlappung mit der Radio-Markierung (die Karten sind
jetzt größer, deshalb erneut geprüft), Screenshots Desktop + Mobil, Markup in allen 4 Sprachen
bestätigt.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch: die PayPal-Zahlungsoption ist jetzt eine "besondere" Kachel statt
der schlichten Icon-Zeile — exakt in der Mitte horizontal geteilt, obere Hälfte PayPal-
Markenverlauf mit Logo + zweifarbiger Wortmarke, untere Hälfte die Visa-/Mastercard-Hinweise.
Animierter Verlaufsrand, leuchtender Mittelsteg, Glanzeffekt und Glitzer-Akzente — dieselbe
Formsprache wie die anderen "besonderen" Karten der Seite (z.B. .account-head). Alle 4 Sprachen.
Feste Höhe (statt min-height) auf der Kachel, damit die Trennlinie IMMER exakt mittig sitzt,
unabhängig vom Inhalt jeder Hälfte — mit auto-Höhe hätte der Flex-Container sich sonst am
längeren Inhalt orientiert und die Linie wäre verrutscht (nachgemessen: vorher 106,6px oben vs.
141px unten, jetzt 109px/109px exakt).
Dabei zwei echte Bugs gefunden und behoben:
1. Eine generische Farb-Regel (".pay-card:has(input:checked) .pay-option span:not(.pay-icon)")
hätte die neue zweifarbige Wortmarke und den Kartenhinweis auf die einfarbige Markenfarbe
umgefärbt und auf dem blauen Verlaufshintergrund fast unlesbar gemacht — mit gezielt
spezifischeren Regeln überschrieben.
2. Die Radio-Markierung überlappte bei bestimmten Fensterbreiten (ca. 800–1000px) die
Mastercard-Karte, weil zwei VERSCHACHTELTE Zweispalten-Layouts (.checkout-layout und
.checkout-split) bei ZU ÄHNLICHEN Umbruchpunkten (800px bzw. 760px) gleichzeitig aktiv
blieben und die Zahlungsspalte auf ca. 90px zusammenquetschten — ein vorbestehender
Layout-Fehler, der die ganze Zahlungsspalte betraf, nicht nur die neue Kachel. Behoben,
indem die innere Spalte jetzt deutlich früher umbricht (1024px statt 760px), lange bevor
die äußere Spalte eng wird.
Getestet (Browser, alle 4 Sprachen): Kontrastprüfung im markierten Zustand, Geometrie der
Trennlinie, Breiten-Sweep von 390px bis 1600px ohne Überlappung mehr, Mobil-Ansicht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Auf ausdrücklichen Wunsch: der Knopf war bisher unter allen aktuellen Bestellungen platziert.
Jetzt steht er direkt unter der Überschrift "Meine Bestellungen", noch vor der neuesten
Bestellung — beim Aufklappen erscheinen Suchfeld und ältere Bestellungen also ganz oben,
noch vor der aktuellen Liste. Alle 4 Sprachen.
Rein eine Markup-Verschiebung (das <div class="order-archive"> wandert vor <div id="order-list">
im DOM) — die JavaScript-Logik, die ältere Karten per appendChild() in den Aufklappbereich
verschiebt, funktioniert unabhängig von der Position weiter, da sie über getElementById auf
beide Container zugreift. CSS entsprechend angepasst: margin-top wurde zu margin-bottom, weil
der Abstand jetzt VOR der ersten Bestellkarte gebraucht wird statt danach.
Getestet (Browser): DOM-Reihenfolge in allen 4 Sprachen bestätigt (order-archive vor
order-list), Auf-/Zuklappen weiterhin funktionsfähig, Karten wandern korrekt in den
Archiv-Bereich und wieder zurück, Sichtprüfung per Screenshot.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Statt "Bereits erhalten: 1x kleiner Teddy, 1x grosser Teddy" steht im Abo-Bereich jetzt eine
Liste mit dem tatsaechlichen Teddy-Namen, dem Einloesedatum und einem Link zum Produkt —
damit Kundinnen sehen, welchen Teddy sie schon besitzen, und keinen doppelt waehlen.
Dafuer haelt das Konto beim Einloesen fest, WELCHER Teddy vergeben wurde (neues Feld
abo.erhalteneTeddys mit Slug, Name und Datum). Bewusst als Verlauf gespeichert statt aus der
aktuellen Abo-Einstellung abgeleitet: VanVan kann die hinterlegten Teddy-Produkte jederzeit im
Adminbereich austauschen — eine nachtraeglich berechnete Liste wuerde dann einen Teddy
anzeigen, den die Kundin nie bekommen hat. Die Anzeige nimmt den aktuellen, uebersetzten
Produktnamen und faellt auf den gespeicherten Namen zurueck, falls das Produkt spaeter
umbenannt oder entfernt wird.
Nebenbei behoben: Beim Einloesen wanderte der Teddy in den Warenkorb, BEVOR geprueft wurde, ob
ueberhaupt eine Praemie offen ist. Bei einem zweiten Klick landete er dadurch erneut gratis im
Warenkorb, ohne im Konto gezaehlt zu werden. Jetzt wird zuerst geprueft.
Ausserdem sichert getAccount() nun auch die Listenfelder gegen kaputte Speicherwerte ab.
Getestet (Browser): Leerzustand, Einloesen beider Arten, Speicherung im Konto, zweiter Klick
ohne offene Praemie, Altkonto ohne Namensliste (ehrlicher Ersatztext) und entferntes Produkt
(gespeicherter Name greift). Beschriftungen in allen 4 Sprachen geprueft.
Co-Authored-By: Claude Opus 5 <[email protected]>