diff --git a/.projektstructure.txt b/.projektstructure.txt
index e80a2fe..fd271dc 100755
--- a/.projektstructure.txt
+++ b/.projektstructure.txt
@@ -1,10 +1,9 @@
Anweisung: Projektstruktur (Basis-Template) wie in „papa-kind-treff“
Aktueller Projektstand
-- Papa-Kind-Treff nutzt im Mitgliederbereich einen modernen Avatar-Generator auf Layer-Basis.
-- Die Avatare bestehen aus getrennten SVG-Ebenen für Kopf, Haare, Bart, Brille, Mütze, Outfit und Farben.
+- Papa-Kind-Treff nutzt im Mitgliederbereich 100 moderne Portrait-Presets im gewünschten Referenzstil.
- Relevante Logik liegt in `src/App/Avatar.php`.
-- Die Layer-Assets liegen unter `public/assets/avatars/layers/modern/`.
+- Die Preset-Assets liegen unter `public/assets/avatars/presets/`.
- Änderungen an Funktionen mit Cookies, LocalStorage, SessionStorage, Geolocation, Tracking oder Drittanbietern müssen immer auch in Datenschutz-/Cookie-Hinweisen und im Consent-Flow berücksichtigt werden.
Ziel
diff --git a/PROJECT_CONTEXT.md b/PROJECT_CONTEXT.md
index dafd1d1..58dcf3d 100644
--- a/PROJECT_CONTEXT.md
+++ b/PROJECT_CONTEXT.md
@@ -19,13 +19,13 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter. Kernbereiche sind l
- Die Community ist hierarchisch aufgebaut: Kategorien -> Boards -> Threads -> Posts.
- Moderation ist getrennt vom normalen Community-Frontend in einem eigenen Adminbereich.
- Standortfunktionen sind relevant für lokale Treffen und werden künftig weiter ausgebaut.
-- Profilbilder werden aktuell über einen modernen Layer-Generator mit getrennten SVG-Ebenen statt über freie Bild-Uploads erzeugt.
+- Profilbilder werden aktuell über 100 moderne Preset-Portraits im gewünschten Referenzstil statt über freie Bild-Uploads erzeugt.
## Navigation / Konto
- Eingeloggte Nutzer sehen rechts ein Profil-Menü statt einzelner `Dashboard`-/`Logout`-Buttons.
- Das Profil-Menü enthält aktuell `Profil`, `Kinder`, `Termine`, `Community`, `Einstellungen`, `Abmelden`.
- Der Mitgliederbereich selbst ist als Layout mit linker Bereichsnavigation aufgebaut.
-- Im Profil kann der Nutzer aktuell seinen Avatar über Layer für Kopfform, Haare, Bart, Brille, Mütze, Outfit und Farbwelten zusammenstellen.
+- Im Profil kann der Nutzer aktuell aus 100 modernen Preset-Varianten wählen, gruppiert nach Hauttönen.
- Debug ist kein Menüpunkt und erscheint nur als Floating-Käfer für `site_admin` bei aktivem Debug-Modus.
## Community und Rechte
diff --git a/README.md b/README.md
index 1e2a134..ca1afa5 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Papa-Kind-Treff ist eine PHP-basierte Plattform für Väter mit Fokus auf lokale
- Impressum, Datenschutz-&-Cookies-Seite und Über-uns
- standortbasierte Sortierung für die neuesten Treffen
- eigener Einstellungsbereich für Standortfreigabe, Browser-Hinweise und Consent-Verwaltung
-- moderner Avatar-Generator auf Layer-Basis mit kombinierbaren SVG-Elementen für Kopf, Haare, Bart, Brille, Mütze, Outfit und Farben
+- modernes Avatar-System auf Basis von 100 festen Portrait-Presets im Referenzstil, gruppiert nach Hauttönen
- Consent-Manager für Analyse und externe Dienste
- Navigation aktuell mit `Home`, `Suche`, `Community`
- eingeloggte Nutzer sehen rechts ein Profil-Menü mit Direktlinks zu `Profil`, `Kinder`, `Termine`, `Community`, `Einstellungen`
diff --git a/partials/landing/account/dashboard.php b/partials/landing/account/dashboard.php
index b1684af..0b85b4f 100755
--- a/partials/landing/account/dashboard.php
+++ b/partials/landing/account/dashboard.php
@@ -67,7 +67,7 @@ $sectionLinks = [
Dein Profilbild
-
Stell dir mit wenigen Klicks ein wiedererkennbares Community-Bild zusammen. Du kannst Haut, Haare, Augen, Bart, Brille und Kopfform direkt anpassen.
+
Wähle ein modernes Portrait im Stil der Community. Die Varianten bleiben konsistent, frisch und deutlich näher an der gewünschten Optik.
Profilbild gestalten
@@ -302,121 +302,39 @@ $sectionLinks = [
= \App\Avatar::render($profile, $profile['display_name'] ?: 'Papa', 'xxl') ?>
- Stell dein Portrait direkt aus Haaren, Bart, Brille, Mütze, Outfit und Farben zusammen. Die Vorschau wird sofort aktualisiert.
+ Wähle zuerst einen Hautton-Bereich und dann eine passende Variante. Die Vorschau aktualisiert sich sofort.
-
-
Kopfform
-
- $label): ?>
- >= htmlspecialchars((string)$label, ENT_QUOTES) ?>
-
-
+
+ $groupMeta): ?>
+
+ = htmlspecialchars((string)$groupMeta['label'], ENT_QUOTES) ?>
+
+
- Haarform
-
- $label): ?>
- >= htmlspecialchars((string)$label, ENT_QUOTES) ?>
-
-
-
-
- Bart
-
- $label): ?>
- >= htmlspecialchars((string)$label, ENT_QUOTES) ?>
-
-
-
-
- Brille
-
- $label): ?>
- >= htmlspecialchars((string)$label, ENT_QUOTES) ?>
-
-
-
-
- Mütze
-
- $label): ?>
- >= htmlspecialchars((string)$label, ENT_QUOTES) ?>
-
-
-
-
- Outfit
-
- $label): ?>
- >= htmlspecialchars((string)$label, ENT_QUOTES) ?>
-
-
-
-
-
-
Hautfarbe
-
- $meta): ?>
-
- >
-
- = htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?>
-
-
-
-
-
-
-
Haarfarbe
-
- $meta): ?>
-
- >
-
- = htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?>
-
-
-
-
-
-
-
Augenfarbe
-
- $meta): ?>
-
- >
-
- = htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?>
-
-
-
-
-
-
-
Mützenfarbe
-
- $meta): ?>
-
- >
-
- = htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?>
-
-
-
-
-
-
-
Outfit-Farbe
-
- $meta): ?>
-
- >
-
- = htmlspecialchars((string)$meta['label'], ENT_QUOTES) ?>
-
-
-
+
Variante wählen
+ $groupPresets): ?>
+
+
diff --git a/public/assets/avatars/presets/modern_001.png b/public/assets/avatars/presets/modern_001.png
new file mode 100644
index 0000000..dbdf204
Binary files /dev/null and b/public/assets/avatars/presets/modern_001.png differ
diff --git a/public/assets/avatars/presets/modern_002.png b/public/assets/avatars/presets/modern_002.png
new file mode 100644
index 0000000..733939b
Binary files /dev/null and b/public/assets/avatars/presets/modern_002.png differ
diff --git a/public/assets/avatars/presets/modern_003.png b/public/assets/avatars/presets/modern_003.png
new file mode 100644
index 0000000..4768846
Binary files /dev/null and b/public/assets/avatars/presets/modern_003.png differ
diff --git a/public/assets/avatars/presets/modern_004.png b/public/assets/avatars/presets/modern_004.png
new file mode 100644
index 0000000..8505bbf
Binary files /dev/null and b/public/assets/avatars/presets/modern_004.png differ
diff --git a/public/assets/avatars/presets/modern_005.png b/public/assets/avatars/presets/modern_005.png
new file mode 100644
index 0000000..2955ab9
Binary files /dev/null and b/public/assets/avatars/presets/modern_005.png differ
diff --git a/public/assets/avatars/presets/modern_006.png b/public/assets/avatars/presets/modern_006.png
new file mode 100644
index 0000000..a716eac
Binary files /dev/null and b/public/assets/avatars/presets/modern_006.png differ
diff --git a/public/assets/avatars/presets/modern_007.png b/public/assets/avatars/presets/modern_007.png
new file mode 100644
index 0000000..a26c3c8
Binary files /dev/null and b/public/assets/avatars/presets/modern_007.png differ
diff --git a/public/assets/avatars/presets/modern_008.png b/public/assets/avatars/presets/modern_008.png
new file mode 100644
index 0000000..8395051
Binary files /dev/null and b/public/assets/avatars/presets/modern_008.png differ
diff --git a/public/assets/avatars/presets/modern_009.png b/public/assets/avatars/presets/modern_009.png
new file mode 100644
index 0000000..3a75dcc
Binary files /dev/null and b/public/assets/avatars/presets/modern_009.png differ
diff --git a/public/assets/avatars/presets/modern_010.png b/public/assets/avatars/presets/modern_010.png
new file mode 100644
index 0000000..29a3e32
Binary files /dev/null and b/public/assets/avatars/presets/modern_010.png differ
diff --git a/public/assets/avatars/presets/modern_011.png b/public/assets/avatars/presets/modern_011.png
new file mode 100644
index 0000000..2fabf02
Binary files /dev/null and b/public/assets/avatars/presets/modern_011.png differ
diff --git a/public/assets/avatars/presets/modern_012.png b/public/assets/avatars/presets/modern_012.png
new file mode 100644
index 0000000..ee78593
Binary files /dev/null and b/public/assets/avatars/presets/modern_012.png differ
diff --git a/public/assets/avatars/presets/modern_013.png b/public/assets/avatars/presets/modern_013.png
new file mode 100644
index 0000000..452e340
Binary files /dev/null and b/public/assets/avatars/presets/modern_013.png differ
diff --git a/public/assets/avatars/presets/modern_014.png b/public/assets/avatars/presets/modern_014.png
new file mode 100644
index 0000000..9a86b35
Binary files /dev/null and b/public/assets/avatars/presets/modern_014.png differ
diff --git a/public/assets/avatars/presets/modern_015.png b/public/assets/avatars/presets/modern_015.png
new file mode 100644
index 0000000..54b911c
Binary files /dev/null and b/public/assets/avatars/presets/modern_015.png differ
diff --git a/public/assets/avatars/presets/modern_016.png b/public/assets/avatars/presets/modern_016.png
new file mode 100644
index 0000000..c68c69b
Binary files /dev/null and b/public/assets/avatars/presets/modern_016.png differ
diff --git a/public/assets/avatars/presets/modern_017.png b/public/assets/avatars/presets/modern_017.png
new file mode 100644
index 0000000..185bc03
Binary files /dev/null and b/public/assets/avatars/presets/modern_017.png differ
diff --git a/public/assets/avatars/presets/modern_018.png b/public/assets/avatars/presets/modern_018.png
new file mode 100644
index 0000000..8fd7ce6
Binary files /dev/null and b/public/assets/avatars/presets/modern_018.png differ
diff --git a/public/assets/avatars/presets/modern_019.png b/public/assets/avatars/presets/modern_019.png
new file mode 100644
index 0000000..7f309ae
Binary files /dev/null and b/public/assets/avatars/presets/modern_019.png differ
diff --git a/public/assets/avatars/presets/modern_020.png b/public/assets/avatars/presets/modern_020.png
new file mode 100644
index 0000000..b6d8331
Binary files /dev/null and b/public/assets/avatars/presets/modern_020.png differ
diff --git a/public/assets/avatars/presets/modern_021.png b/public/assets/avatars/presets/modern_021.png
new file mode 100644
index 0000000..473b078
Binary files /dev/null and b/public/assets/avatars/presets/modern_021.png differ
diff --git a/public/assets/avatars/presets/modern_022.png b/public/assets/avatars/presets/modern_022.png
new file mode 100644
index 0000000..b5e9360
Binary files /dev/null and b/public/assets/avatars/presets/modern_022.png differ
diff --git a/public/assets/avatars/presets/modern_023.png b/public/assets/avatars/presets/modern_023.png
new file mode 100644
index 0000000..45f742f
Binary files /dev/null and b/public/assets/avatars/presets/modern_023.png differ
diff --git a/public/assets/avatars/presets/modern_024.png b/public/assets/avatars/presets/modern_024.png
new file mode 100644
index 0000000..10f9dc9
Binary files /dev/null and b/public/assets/avatars/presets/modern_024.png differ
diff --git a/public/assets/avatars/presets/modern_025.png b/public/assets/avatars/presets/modern_025.png
new file mode 100644
index 0000000..6e3394f
Binary files /dev/null and b/public/assets/avatars/presets/modern_025.png differ
diff --git a/public/assets/avatars/presets/modern_026.png b/public/assets/avatars/presets/modern_026.png
new file mode 100644
index 0000000..277224f
Binary files /dev/null and b/public/assets/avatars/presets/modern_026.png differ
diff --git a/public/assets/avatars/presets/modern_027.png b/public/assets/avatars/presets/modern_027.png
new file mode 100644
index 0000000..f6bca10
Binary files /dev/null and b/public/assets/avatars/presets/modern_027.png differ
diff --git a/public/assets/avatars/presets/modern_028.png b/public/assets/avatars/presets/modern_028.png
new file mode 100644
index 0000000..e684edd
Binary files /dev/null and b/public/assets/avatars/presets/modern_028.png differ
diff --git a/public/assets/avatars/presets/modern_029.png b/public/assets/avatars/presets/modern_029.png
new file mode 100644
index 0000000..1de9e0a
Binary files /dev/null and b/public/assets/avatars/presets/modern_029.png differ
diff --git a/public/assets/avatars/presets/modern_030.png b/public/assets/avatars/presets/modern_030.png
new file mode 100644
index 0000000..920c022
Binary files /dev/null and b/public/assets/avatars/presets/modern_030.png differ
diff --git a/public/assets/avatars/presets/modern_031.png b/public/assets/avatars/presets/modern_031.png
new file mode 100644
index 0000000..76818d5
Binary files /dev/null and b/public/assets/avatars/presets/modern_031.png differ
diff --git a/public/assets/avatars/presets/modern_032.png b/public/assets/avatars/presets/modern_032.png
new file mode 100644
index 0000000..c9935bf
Binary files /dev/null and b/public/assets/avatars/presets/modern_032.png differ
diff --git a/public/assets/avatars/presets/modern_033.png b/public/assets/avatars/presets/modern_033.png
new file mode 100644
index 0000000..3f525a4
Binary files /dev/null and b/public/assets/avatars/presets/modern_033.png differ
diff --git a/public/assets/avatars/presets/modern_034.png b/public/assets/avatars/presets/modern_034.png
new file mode 100644
index 0000000..abc2cf6
Binary files /dev/null and b/public/assets/avatars/presets/modern_034.png differ
diff --git a/public/assets/avatars/presets/modern_035.png b/public/assets/avatars/presets/modern_035.png
new file mode 100644
index 0000000..519d719
Binary files /dev/null and b/public/assets/avatars/presets/modern_035.png differ
diff --git a/public/assets/avatars/presets/modern_036.png b/public/assets/avatars/presets/modern_036.png
new file mode 100644
index 0000000..b841220
Binary files /dev/null and b/public/assets/avatars/presets/modern_036.png differ
diff --git a/public/assets/avatars/presets/modern_037.png b/public/assets/avatars/presets/modern_037.png
new file mode 100644
index 0000000..503d6f9
Binary files /dev/null and b/public/assets/avatars/presets/modern_037.png differ
diff --git a/public/assets/avatars/presets/modern_038.png b/public/assets/avatars/presets/modern_038.png
new file mode 100644
index 0000000..dd9c212
Binary files /dev/null and b/public/assets/avatars/presets/modern_038.png differ
diff --git a/public/assets/avatars/presets/modern_039.png b/public/assets/avatars/presets/modern_039.png
new file mode 100644
index 0000000..79e07ea
Binary files /dev/null and b/public/assets/avatars/presets/modern_039.png differ
diff --git a/public/assets/avatars/presets/modern_040.png b/public/assets/avatars/presets/modern_040.png
new file mode 100644
index 0000000..4178d83
Binary files /dev/null and b/public/assets/avatars/presets/modern_040.png differ
diff --git a/public/assets/avatars/presets/modern_041.png b/public/assets/avatars/presets/modern_041.png
new file mode 100644
index 0000000..7897a54
Binary files /dev/null and b/public/assets/avatars/presets/modern_041.png differ
diff --git a/public/assets/avatars/presets/modern_042.png b/public/assets/avatars/presets/modern_042.png
new file mode 100644
index 0000000..046e054
Binary files /dev/null and b/public/assets/avatars/presets/modern_042.png differ
diff --git a/public/assets/avatars/presets/modern_043.png b/public/assets/avatars/presets/modern_043.png
new file mode 100644
index 0000000..efda0ca
Binary files /dev/null and b/public/assets/avatars/presets/modern_043.png differ
diff --git a/public/assets/avatars/presets/modern_044.png b/public/assets/avatars/presets/modern_044.png
new file mode 100644
index 0000000..0fd464f
Binary files /dev/null and b/public/assets/avatars/presets/modern_044.png differ
diff --git a/public/assets/avatars/presets/modern_045.png b/public/assets/avatars/presets/modern_045.png
new file mode 100644
index 0000000..5a6e70b
Binary files /dev/null and b/public/assets/avatars/presets/modern_045.png differ
diff --git a/public/assets/avatars/presets/modern_046.png b/public/assets/avatars/presets/modern_046.png
new file mode 100644
index 0000000..8ab2272
Binary files /dev/null and b/public/assets/avatars/presets/modern_046.png differ
diff --git a/public/assets/avatars/presets/modern_047.png b/public/assets/avatars/presets/modern_047.png
new file mode 100644
index 0000000..6ec9a20
Binary files /dev/null and b/public/assets/avatars/presets/modern_047.png differ
diff --git a/public/assets/avatars/presets/modern_048.png b/public/assets/avatars/presets/modern_048.png
new file mode 100644
index 0000000..e173b4f
Binary files /dev/null and b/public/assets/avatars/presets/modern_048.png differ
diff --git a/public/assets/avatars/presets/modern_049.png b/public/assets/avatars/presets/modern_049.png
new file mode 100644
index 0000000..4ddaf50
Binary files /dev/null and b/public/assets/avatars/presets/modern_049.png differ
diff --git a/public/assets/avatars/presets/modern_050.png b/public/assets/avatars/presets/modern_050.png
new file mode 100644
index 0000000..d72e5ae
Binary files /dev/null and b/public/assets/avatars/presets/modern_050.png differ
diff --git a/public/assets/avatars/presets/modern_051.png b/public/assets/avatars/presets/modern_051.png
new file mode 100644
index 0000000..fe9576a
Binary files /dev/null and b/public/assets/avatars/presets/modern_051.png differ
diff --git a/public/assets/avatars/presets/modern_052.png b/public/assets/avatars/presets/modern_052.png
new file mode 100644
index 0000000..5efa6b1
Binary files /dev/null and b/public/assets/avatars/presets/modern_052.png differ
diff --git a/public/assets/avatars/presets/modern_053.png b/public/assets/avatars/presets/modern_053.png
new file mode 100644
index 0000000..74f66b2
Binary files /dev/null and b/public/assets/avatars/presets/modern_053.png differ
diff --git a/public/assets/avatars/presets/modern_054.png b/public/assets/avatars/presets/modern_054.png
new file mode 100644
index 0000000..135bc27
Binary files /dev/null and b/public/assets/avatars/presets/modern_054.png differ
diff --git a/public/assets/avatars/presets/modern_055.png b/public/assets/avatars/presets/modern_055.png
new file mode 100644
index 0000000..2c854c4
Binary files /dev/null and b/public/assets/avatars/presets/modern_055.png differ
diff --git a/public/assets/avatars/presets/modern_056.png b/public/assets/avatars/presets/modern_056.png
new file mode 100644
index 0000000..acb896f
Binary files /dev/null and b/public/assets/avatars/presets/modern_056.png differ
diff --git a/public/assets/avatars/presets/modern_057.png b/public/assets/avatars/presets/modern_057.png
new file mode 100644
index 0000000..7177e1c
Binary files /dev/null and b/public/assets/avatars/presets/modern_057.png differ
diff --git a/public/assets/avatars/presets/modern_058.png b/public/assets/avatars/presets/modern_058.png
new file mode 100644
index 0000000..7798f15
Binary files /dev/null and b/public/assets/avatars/presets/modern_058.png differ
diff --git a/public/assets/avatars/presets/modern_059.png b/public/assets/avatars/presets/modern_059.png
new file mode 100644
index 0000000..f207d88
Binary files /dev/null and b/public/assets/avatars/presets/modern_059.png differ
diff --git a/public/assets/avatars/presets/modern_060.png b/public/assets/avatars/presets/modern_060.png
new file mode 100644
index 0000000..61d0bbf
Binary files /dev/null and b/public/assets/avatars/presets/modern_060.png differ
diff --git a/public/assets/avatars/presets/modern_061.png b/public/assets/avatars/presets/modern_061.png
new file mode 100644
index 0000000..0134325
Binary files /dev/null and b/public/assets/avatars/presets/modern_061.png differ
diff --git a/public/assets/avatars/presets/modern_062.png b/public/assets/avatars/presets/modern_062.png
new file mode 100644
index 0000000..67107c0
Binary files /dev/null and b/public/assets/avatars/presets/modern_062.png differ
diff --git a/public/assets/avatars/presets/modern_063.png b/public/assets/avatars/presets/modern_063.png
new file mode 100644
index 0000000..b18783b
Binary files /dev/null and b/public/assets/avatars/presets/modern_063.png differ
diff --git a/public/assets/avatars/presets/modern_064.png b/public/assets/avatars/presets/modern_064.png
new file mode 100644
index 0000000..d1b8eb0
Binary files /dev/null and b/public/assets/avatars/presets/modern_064.png differ
diff --git a/public/assets/avatars/presets/modern_065.png b/public/assets/avatars/presets/modern_065.png
new file mode 100644
index 0000000..1af2bbe
Binary files /dev/null and b/public/assets/avatars/presets/modern_065.png differ
diff --git a/public/assets/avatars/presets/modern_066.png b/public/assets/avatars/presets/modern_066.png
new file mode 100644
index 0000000..1d912f1
Binary files /dev/null and b/public/assets/avatars/presets/modern_066.png differ
diff --git a/public/assets/avatars/presets/modern_067.png b/public/assets/avatars/presets/modern_067.png
new file mode 100644
index 0000000..d8dd1f8
Binary files /dev/null and b/public/assets/avatars/presets/modern_067.png differ
diff --git a/public/assets/avatars/presets/modern_068.png b/public/assets/avatars/presets/modern_068.png
new file mode 100644
index 0000000..179e5fe
Binary files /dev/null and b/public/assets/avatars/presets/modern_068.png differ
diff --git a/public/assets/avatars/presets/modern_069.png b/public/assets/avatars/presets/modern_069.png
new file mode 100644
index 0000000..18e63d2
Binary files /dev/null and b/public/assets/avatars/presets/modern_069.png differ
diff --git a/public/assets/avatars/presets/modern_070.png b/public/assets/avatars/presets/modern_070.png
new file mode 100644
index 0000000..fb39ea0
Binary files /dev/null and b/public/assets/avatars/presets/modern_070.png differ
diff --git a/public/assets/avatars/presets/modern_071.png b/public/assets/avatars/presets/modern_071.png
new file mode 100644
index 0000000..5928cd8
Binary files /dev/null and b/public/assets/avatars/presets/modern_071.png differ
diff --git a/public/assets/avatars/presets/modern_072.png b/public/assets/avatars/presets/modern_072.png
new file mode 100644
index 0000000..ab8ef9f
Binary files /dev/null and b/public/assets/avatars/presets/modern_072.png differ
diff --git a/public/assets/avatars/presets/modern_073.png b/public/assets/avatars/presets/modern_073.png
new file mode 100644
index 0000000..a7bd5ba
Binary files /dev/null and b/public/assets/avatars/presets/modern_073.png differ
diff --git a/public/assets/avatars/presets/modern_074.png b/public/assets/avatars/presets/modern_074.png
new file mode 100644
index 0000000..3906c85
Binary files /dev/null and b/public/assets/avatars/presets/modern_074.png differ
diff --git a/public/assets/avatars/presets/modern_075.png b/public/assets/avatars/presets/modern_075.png
new file mode 100644
index 0000000..3bf8a5d
Binary files /dev/null and b/public/assets/avatars/presets/modern_075.png differ
diff --git a/public/assets/avatars/presets/modern_076.png b/public/assets/avatars/presets/modern_076.png
new file mode 100644
index 0000000..0bf1943
Binary files /dev/null and b/public/assets/avatars/presets/modern_076.png differ
diff --git a/public/assets/avatars/presets/modern_077.png b/public/assets/avatars/presets/modern_077.png
new file mode 100644
index 0000000..c3fc9e0
Binary files /dev/null and b/public/assets/avatars/presets/modern_077.png differ
diff --git a/public/assets/avatars/presets/modern_078.png b/public/assets/avatars/presets/modern_078.png
new file mode 100644
index 0000000..1bc700e
Binary files /dev/null and b/public/assets/avatars/presets/modern_078.png differ
diff --git a/public/assets/avatars/presets/modern_079.png b/public/assets/avatars/presets/modern_079.png
new file mode 100644
index 0000000..e4cd130
Binary files /dev/null and b/public/assets/avatars/presets/modern_079.png differ
diff --git a/public/assets/avatars/presets/modern_080.png b/public/assets/avatars/presets/modern_080.png
new file mode 100644
index 0000000..f5d911b
Binary files /dev/null and b/public/assets/avatars/presets/modern_080.png differ
diff --git a/public/assets/avatars/presets/modern_081.png b/public/assets/avatars/presets/modern_081.png
new file mode 100644
index 0000000..cd11baf
Binary files /dev/null and b/public/assets/avatars/presets/modern_081.png differ
diff --git a/public/assets/avatars/presets/modern_082.png b/public/assets/avatars/presets/modern_082.png
new file mode 100644
index 0000000..e8061d7
Binary files /dev/null and b/public/assets/avatars/presets/modern_082.png differ
diff --git a/public/assets/avatars/presets/modern_083.png b/public/assets/avatars/presets/modern_083.png
new file mode 100644
index 0000000..23bb2fd
Binary files /dev/null and b/public/assets/avatars/presets/modern_083.png differ
diff --git a/public/assets/avatars/presets/modern_084.png b/public/assets/avatars/presets/modern_084.png
new file mode 100644
index 0000000..c4bf80e
Binary files /dev/null and b/public/assets/avatars/presets/modern_084.png differ
diff --git a/public/assets/avatars/presets/modern_085.png b/public/assets/avatars/presets/modern_085.png
new file mode 100644
index 0000000..ee90561
Binary files /dev/null and b/public/assets/avatars/presets/modern_085.png differ
diff --git a/public/assets/avatars/presets/modern_086.png b/public/assets/avatars/presets/modern_086.png
new file mode 100644
index 0000000..b11997f
Binary files /dev/null and b/public/assets/avatars/presets/modern_086.png differ
diff --git a/public/assets/avatars/presets/modern_087.png b/public/assets/avatars/presets/modern_087.png
new file mode 100644
index 0000000..83b7504
Binary files /dev/null and b/public/assets/avatars/presets/modern_087.png differ
diff --git a/public/assets/avatars/presets/modern_088.png b/public/assets/avatars/presets/modern_088.png
new file mode 100644
index 0000000..86f8252
Binary files /dev/null and b/public/assets/avatars/presets/modern_088.png differ
diff --git a/public/assets/avatars/presets/modern_089.png b/public/assets/avatars/presets/modern_089.png
new file mode 100644
index 0000000..014371a
Binary files /dev/null and b/public/assets/avatars/presets/modern_089.png differ
diff --git a/public/assets/avatars/presets/modern_090.png b/public/assets/avatars/presets/modern_090.png
new file mode 100644
index 0000000..0c1d71a
Binary files /dev/null and b/public/assets/avatars/presets/modern_090.png differ
diff --git a/public/assets/avatars/presets/modern_091.png b/public/assets/avatars/presets/modern_091.png
new file mode 100644
index 0000000..08c43fc
Binary files /dev/null and b/public/assets/avatars/presets/modern_091.png differ
diff --git a/public/assets/avatars/presets/modern_092.png b/public/assets/avatars/presets/modern_092.png
new file mode 100644
index 0000000..0507370
Binary files /dev/null and b/public/assets/avatars/presets/modern_092.png differ
diff --git a/public/assets/avatars/presets/modern_093.png b/public/assets/avatars/presets/modern_093.png
new file mode 100644
index 0000000..13b3469
Binary files /dev/null and b/public/assets/avatars/presets/modern_093.png differ
diff --git a/public/assets/avatars/presets/modern_094.png b/public/assets/avatars/presets/modern_094.png
new file mode 100644
index 0000000..7a331d2
Binary files /dev/null and b/public/assets/avatars/presets/modern_094.png differ
diff --git a/public/assets/avatars/presets/modern_095.png b/public/assets/avatars/presets/modern_095.png
new file mode 100644
index 0000000..dc20b49
Binary files /dev/null and b/public/assets/avatars/presets/modern_095.png differ
diff --git a/public/assets/avatars/presets/modern_096.png b/public/assets/avatars/presets/modern_096.png
new file mode 100644
index 0000000..54c40ed
Binary files /dev/null and b/public/assets/avatars/presets/modern_096.png differ
diff --git a/public/assets/avatars/presets/modern_097.png b/public/assets/avatars/presets/modern_097.png
new file mode 100644
index 0000000..becb4ab
Binary files /dev/null and b/public/assets/avatars/presets/modern_097.png differ
diff --git a/public/assets/avatars/presets/modern_098.png b/public/assets/avatars/presets/modern_098.png
new file mode 100644
index 0000000..7b9ecc3
Binary files /dev/null and b/public/assets/avatars/presets/modern_098.png differ
diff --git a/public/assets/avatars/presets/modern_099.png b/public/assets/avatars/presets/modern_099.png
new file mode 100644
index 0000000..ab25ead
Binary files /dev/null and b/public/assets/avatars/presets/modern_099.png differ
diff --git a/public/assets/avatars/presets/modern_100.png b/public/assets/avatars/presets/modern_100.png
new file mode 100644
index 0000000..6406155
Binary files /dev/null and b/public/assets/avatars/presets/modern_100.png differ
diff --git a/public/assets/css/app.css b/public/assets/css/app.css
index f2e82a2..e8cf479 100755
--- a/public/assets/css/app.css
+++ b/public/assets/css/app.css
@@ -120,6 +120,7 @@ body {
.pkt-avatar--forum { --avatar-size: 52px; border-radius: 16px; }
.pkt-avatar--xl { --avatar-size: 120px; border-radius: 28px; }
.pkt-avatar--xxl { --avatar-size: 168px; border-radius: 36px; }
+.pkt-avatar__img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center top; }
.pkt-avatar--layered::before { content: ""; position: absolute; inset: auto 8% -8% 8%; height: 28%; border-radius: 50%; background: radial-gradient(circle at center, rgba(74, 52, 38, 0.16), transparent 70%); filter: blur(10px); z-index: 0; pointer-events: none; }
.pkt-avatar__layer { position: absolute; inset: 0; display: block; z-index: 1; pointer-events: none; }
.pkt-avatar__layer--outfit { z-index: 1; }
@@ -249,6 +250,21 @@ body {
.avatar-builder__layout { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 24px; align-items: start; }
.avatar-builder__preview { position: sticky; top: 0; display: grid; justify-items: center; gap: 12px; padding: 18px; background: linear-gradient(180deg, #fffdfa, #f8f4ec); border: 1px solid var(--color-border); border-radius: 18px; }
.avatar-builder__controls { display: grid; gap: 18px; }
+.avatar-preset-filters { display: flex; flex-wrap: wrap; gap: 10px; }
+.avatar-preset-filter { border: 1px solid var(--color-border); background: #fff; color: var(--color-text); border-radius: 999px; padding: 10px 14px; font: inherit; font-weight: 700; cursor: pointer; transition: border-color .15s ease, box-shadow .15s ease, background .15s ease, color .15s ease; }
+.avatar-preset-filter:hover { border-color: var(--color-primary); color: var(--color-primary); }
+.avatar-preset-filter.is-active { background: var(--color-primary); color: var(--color-primary-contrast); border-color: var(--color-primary); box-shadow: 0 10px 20px rgba(41, 31, 22, 0.08); }
+.avatar-preset-group { display: none; }
+.avatar-preset-group.is-active { display: block; }
+.avatar-preset-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: 12px; }
+.avatar-preset-card { position: relative; display: grid; gap: 8px; align-content: start; padding: 10px; border: 1px solid var(--color-border); border-radius: 16px; background: #fff; cursor: pointer; transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; }
+.avatar-preset-card:hover { border-color: var(--color-primary); box-shadow: 0 10px 20px rgba(41, 31, 22, 0.08); transform: translateY(-1px); }
+.avatar-preset-card input { position: absolute; opacity: 0; pointer-events: none; }
+.avatar-preset-card__thumb { display: block; aspect-ratio: 1; border-radius: 14px; overflow: hidden; background: linear-gradient(180deg, #f7efe6, #f0e4d7); border: 1px solid rgba(74, 52, 38, 0.08); }
+.avatar-preset-card__thumb img { width: 100%; height: 100%; object-fit: cover; object-position: center top; display: block; }
+.avatar-preset-card__label { font-size: 13px; font-weight: 700; color: var(--color-text); }
+.avatar-preset-card:has(input:checked) { border-color: var(--color-primary); box-shadow: 0 0 0 3px rgba(52,72,90,0.14); }
+@media (max-width: 860px){ .avatar-builder__layout { grid-template-columns: 1fr; } .avatar-builder__preview { position: static; } }
.avatar-swatch-group { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
.avatar-swatch { display: grid; grid-template-columns: 20px 18px minmax(0, 1fr); gap: 10px; align-items: center; padding: 10px 12px; border: 1px solid var(--color-border); border-radius: 14px; background: #fff; cursor: pointer; }
.avatar-swatch__color { width: 18px; height: 18px; border-radius: 999px; background: var(--swatch-color); border: 1px solid rgba(0,0,0,0.12); }
diff --git a/public/assets/js/app.js b/public/assets/js/app.js
index 71ba718..874b275 100755
--- a/public/assets/js/app.js
+++ b/public/assets/js/app.js
@@ -726,15 +726,6 @@ document.addEventListener('DOMContentLoaded', () => {
});
document.addEventListener('pkt:open-consent', openConsentModal);
- const avatarPreviewClassPrefixes = [
- 'pkt-avatar--head-',
- 'pkt-avatar--hair-',
- 'pkt-avatar--beard-',
- 'pkt-avatar--glasses-',
- 'pkt-avatar--hat-',
- 'pkt-avatar--outfit-',
- ];
-
const updateAvatarPreview = (form) => {
const preview = form.querySelector('[data-avatar-preview] .pkt-avatar');
if (!preview) return;
@@ -745,28 +736,13 @@ document.addEventListener('DOMContentLoaded', () => {
const input = form.querySelector(`[data-avatar-field="${field}"]`);
return input ? input.value : '';
};
- const readColor = (field) => {
- const checked = form.querySelector(`[data-avatar-field="${field}"]:checked`);
- return checked ? checked.getAttribute('data-avatar-color') || '' : '';
- };
+ const image = preview.querySelector('.pkt-avatar__img');
+ if (!image) return;
- avatarPreviewClassPrefixes.forEach((prefix) => {
- Array.from(preview.classList)
- .filter((className) => className.startsWith(prefix))
- .forEach((className) => preview.classList.remove(className));
- });
+ const preset = readValue('avatar_preset');
+ if (!preset) return;
- preview.classList.add(`pkt-avatar--head-${readValue('avatar_head_shape')}`);
- preview.classList.add(`pkt-avatar--hair-${readValue('avatar_hair_style')}`);
- preview.classList.add(`pkt-avatar--beard-${readValue('avatar_beard_style')}`);
- preview.classList.add(`pkt-avatar--glasses-${readValue('avatar_glasses_style')}`);
- preview.classList.add(`pkt-avatar--hat-${readValue('avatar_hat_style')}`);
- preview.classList.add(`pkt-avatar--outfit-${readValue('avatar_outfit_style')}`);
- preview.style.setProperty('--avatar-skin', readColor('avatar_skin_tone'));
- preview.style.setProperty('--avatar-hair', readColor('avatar_hair_color'));
- preview.style.setProperty('--avatar-eye', readColor('avatar_eye_color'));
- preview.style.setProperty('--avatar-hat', readColor('avatar_hat_color'));
- preview.style.setProperty('--avatar-outfit', readColor('avatar_outfit_color'));
+ image.src = `/assets/avatars/presets/${preset}.png`;
};
document.querySelectorAll('[data-avatar-builder]').forEach((form) => {
@@ -775,6 +751,37 @@ document.addEventListener('DOMContentLoaded', () => {
field.addEventListener('change', () => updateAvatarPreview(form));
field.addEventListener('input', () => updateAvatarPreview(form));
});
+
+ const setActivePresetGroup = (groupKey) => {
+ form.querySelectorAll('[data-avatar-preset-filter]').forEach((button) => {
+ const active = button.getAttribute('data-avatar-preset-filter') === groupKey;
+ button.classList.toggle('is-active', active);
+ button.setAttribute('aria-selected', active ? 'true' : 'false');
+ });
+ form.querySelectorAll('[data-avatar-preset-group]').forEach((group) => {
+ group.classList.toggle('is-active', group.getAttribute('data-avatar-preset-group') === groupKey);
+ });
+ };
+
+ const checkedPreset = form.querySelector('[data-avatar-field="avatar_preset"]:checked');
+ if (checkedPreset) {
+ const activeGroup = checkedPreset.closest('[data-avatar-preset-group]')?.getAttribute('data-avatar-preset-group');
+ if (activeGroup) setActivePresetGroup(activeGroup);
+ }
+
+ form.querySelectorAll('[data-avatar-preset-filter]').forEach((button) => {
+ button.addEventListener('click', () => {
+ const groupKey = button.getAttribute('data-avatar-preset-filter');
+ if (groupKey) setActivePresetGroup(groupKey);
+ });
+ });
+
+ form.querySelectorAll('[data-avatar-field="avatar_preset"]').forEach((field) => {
+ field.addEventListener('change', () => {
+ const activeGroup = field.closest('[data-avatar-preset-group]')?.getAttribute('data-avatar-preset-group');
+ if (activeGroup) setActivePresetGroup(activeGroup);
+ });
+ });
});
document.querySelectorAll('[data-nav-events]').forEach(link => {
diff --git a/schema.sql b/schema.sql
index 94aa157..2ddd237 100755
--- a/schema.sql
+++ b/schema.sql
@@ -30,7 +30,7 @@ CREATE TABLE user_profiles (
lat DECIMAL(10,7) NULL,
lng DECIMAL(10,7) NULL,
location_tracking_preference ENUM('disabled','prompt','enabled') NOT NULL DEFAULT 'prompt',
- avatar_preset VARCHAR(32) NOT NULL DEFAULT 'modern_01',
+ avatar_preset VARCHAR(32) NOT NULL DEFAULT 'modern_001',
avatar_skin_tone VARCHAR(24) NOT NULL DEFAULT 'warm',
avatar_hair_style VARCHAR(24) NOT NULL DEFAULT 'short',
avatar_hair_color VARCHAR(24) NOT NULL DEFAULT 'brown',
diff --git a/src/App/AccountPages.php b/src/App/AccountPages.php
index 3670e96..c93d88c 100755
--- a/src/App/AccountPages.php
+++ b/src/App/AccountPages.php
@@ -338,7 +338,7 @@ final class AccountPages
'email' => '',
'contact_phone' => '',
'location_tracking_preference' => 'prompt',
- 'avatar_preset' => 'modern_01',
+ 'avatar_preset' => 'modern_001',
'avatar_skin_tone' => 'warm',
'avatar_hair_style' => 'short',
'avatar_hair_color' => 'brown',
@@ -421,6 +421,8 @@ final class AccountPages
$section = 'profile';
}
$avatarOptions = Avatar::options();
+ $avatarPresetOptions = Avatar::presetOptions();
+ $avatarPresetGroups = Avatar::presetGroups();
return compact(
'flash',
@@ -438,6 +440,8 @@ final class AccountPages
'communityCanApply',
'communityRestrictions',
'avatarOptions',
+ 'avatarPresetOptions',
+ 'avatarPresetGroups',
'section',
'allowedSections'
);
diff --git a/src/App/Avatar.php b/src/App/Avatar.php
index 6b2dae9..921b4d7 100644
--- a/src/App/Avatar.php
+++ b/src/App/Avatar.php
@@ -8,7 +8,7 @@ final class Avatar
public static function defaults(): array
{
return [
- 'avatar_preset' => 'modern_01',
+ 'avatar_preset' => 'modern_001',
'avatar_skin_tone' => 'warm',
'avatar_hair_style' => 'parted',
'avatar_hair_color' => 'brown',
@@ -98,6 +98,35 @@ final class Avatar
];
}
+ public static function presetGroups(): array
+ {
+ return [
+ 'fair' => ['label' => 'Helle Hauttöne', 'range' => [1, 20]],
+ 'warm' => ['label' => 'Warme Hauttöne', 'range' => [21, 40]],
+ 'golden' => ['label' => 'Goldene Hauttöne', 'range' => [41, 60]],
+ 'deep' => ['label' => 'Tiefere Hauttöne', 'range' => [61, 80]],
+ 'rich' => ['label' => 'Kräftige Hauttöne', 'range' => [81, 100]],
+ ];
+ }
+
+ public static function presetOptions(): array
+ {
+ $presets = [];
+ foreach (self::presetGroups() as $groupKey => $group) {
+ [$start, $end] = $group['range'];
+ for ($index = $start; $index <= $end; $index++) {
+ $value = sprintf('modern_%03d', $index);
+ $presets[$groupKey][$value] = [
+ 'label' => 'Variante ' . $index,
+ 'group' => $groupKey,
+ 'image' => self::presetPublicPath($value),
+ ];
+ }
+ }
+
+ return $presets;
+ }
+
public static function selectColumns(string $alias = 'p'): string
{
$columns = array_keys(self::defaults());
@@ -127,8 +156,22 @@ final class Avatar
public static function render(array $row, string $name = 'Mitglied', string $size = 'md'): string
{
$avatar = self::normalize($row);
- $options = self::options();
+ $presetPath = self::presetPublicPath($avatar['avatar_preset']);
+ if ($presetPath !== null) {
+ return sprintf(
+ ' ',
+ htmlspecialchars(implode(' ', [
+ 'pkt-avatar',
+ 'pkt-avatar--' . preg_replace('/[^a-z0-9\-]/', '', strtolower($size)),
+ 'pkt-avatar--preset',
+ ]), ENT_QUOTES),
+ htmlspecialchars('Avatar von ' . $name, ENT_QUOTES),
+ htmlspecialchars($presetPath, ENT_QUOTES)
+ );
+ }
+
+ $options = self::options();
$classes = [
'pkt-avatar',
'pkt-avatar--' . preg_replace('/[^a-z0-9\-]/', '', strtolower($size)),
@@ -192,4 +235,15 @@ final class Avatar
{
return dirname(__DIR__, 2) . '/public/assets/avatars/layers/modern/' . $category . '/' . $variant . '.svg';
}
+
+ public static function presetPublicPath(string $preset): ?string
+ {
+ $preset = preg_replace('/[^a-z0-9_]/', '', strtolower($preset)) ?: '';
+ $file = dirname(__DIR__, 2) . '/public/assets/avatars/presets/' . $preset . '.png';
+ if (!is_file($file)) {
+ return null;
+ }
+
+ return '/assets/avatars/presets/' . $preset . '.png';
+ }
}
diff --git a/src/App/ProfileSettings.php b/src/App/ProfileSettings.php
index 0a2874e..6f13a5c 100644
--- a/src/App/ProfileSettings.php
+++ b/src/App/ProfileSettings.php
@@ -29,7 +29,7 @@ final class ProfileSettings
}
$avatarColumns = [
- 'avatar_preset' => "ALTER TABLE user_profiles ADD COLUMN avatar_preset VARCHAR(32) NOT NULL DEFAULT 'modern_01' AFTER location_tracking_preference",
+ 'avatar_preset' => "ALTER TABLE user_profiles ADD COLUMN avatar_preset VARCHAR(32) NOT NULL DEFAULT 'modern_001' AFTER location_tracking_preference",
'avatar_skin_tone' => "ALTER TABLE user_profiles ADD COLUMN avatar_skin_tone VARCHAR(24) NOT NULL DEFAULT 'warm' AFTER location_tracking_preference",
'avatar_hair_style' => "ALTER TABLE user_profiles ADD COLUMN avatar_hair_style VARCHAR(24) NOT NULL DEFAULT 'short' AFTER avatar_skin_tone",
'avatar_hair_color' => "ALTER TABLE user_profiles ADD COLUMN avatar_hair_color VARCHAR(24) NOT NULL DEFAULT 'brown' AFTER avatar_hair_style",