diff --git a/.gitignore b/.gitignore
index 3a00970..bd07db5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,3 +59,7 @@ __pycache__/
_static/
_work/
_storage/
+# Background review renders (large); README and overview are versioned
+dev/backgrounds/*
+!dev/backgrounds/README.md
+!dev/backgrounds/uebersicht.jpg
diff --git a/dev/backgrounds/README.md b/dev/backgrounds/README.md
new file mode 100644
index 0000000..f472ca6
--- /dev/null
+++ b/dev/backgrounds/README.md
@@ -0,0 +1,56 @@
+# Hintergründe für die LifeWave – Sichtungsordner
+
+Zehn Hintergründe, von grafisch bis fotografisch, alle quadratisch 2048 px,
+damit `background-size: cover` hoch und quer gleichmäßig beschneidet. Die
+Bildmitte ist überall ruhig, weil dort die Welle mit ihren Punkten läuft.
+
+Palette: Tinte #292a2b / #1a1b1c, Gold #f5c26b / #d59040, Papier #f7f3ea.
+
+| Nr. | Name | Quelle | Linienmodus | Passendes Preset |
+| --- | --- | --- | --- | --- |
+| 01 | Tinte | Gemini, ink-gewaschenes Papier | Glow | Gold |
+| 02 | Goldstaub | Gemini, Goldstaub auf Samt | Glow | Gold, Seide |
+| 03 | Horizont | Gemini, Nachglühen über leerer Ebene | Glow, Trennung | Abendrot |
+| 04 | Papier | Gemini, Baumwollpapier | Einfarbig | Papier |
+| 05 | Leinen | Gemini, flaches Anthrazit-Leinen | Glow | Seide |
+| 06a | Aquarell warm | Gemini, Sepia/Ocker in den Ecken | Einfarbig | Papier |
+| 06b | Aquarell dunkel | Gemini, Indigo-Tusche oben und unten | Einfarbig dunkel | Aurora |
+| 07 | Kohle | Gemini, Schiefertafel | Glow, Einfarbig hell | Mondsichel |
+| 08 | Nebel | Gemini | Glow | Aurora, Milchstraße |
+| 09 | Dämmerung | Gemini | Glow | Abendrot |
+| 10 | Nachthimmel | Gemini | Glow, Mondsichel | Mondsichel, Aurora |
+
+Alle elf liegen in `photo/`, die unveränderten 2K-Ausgaben in `photo/original/`.
+`uebersicht.jpg` zeigt den aktuellen Stand. Frühere Fassungen zum Vergleich:
+`v1/` (erster Durchgang, grafische als SVG gerendert), `v2/` (zweiter
+Durchgang von Tinte, Papier, Leinen und Aquarell warm, mit Blattkanten und
+Falten). Die SVG-Quellen in `v1/graphic/` bleiben als Rückfall, falls eine
+Version ohne KI gewünscht ist.
+
+## Neu erzeugen
+
+```bash
+cd dev/tools/backgrounds
+python3 generate_photo.py # alle elf, je eine Gemini-Anfrage
+python3 generate_photo.py 08-nebel # nur eines
+python3 build_graphic.py # SVG-Fassung der grafischen (v1), ohne API
+```
+
+Die Fotos brauchen `GOOGLE_API_KEY` in `backend/.env`, siehe
+`documentation/bildgenerierung-gemini-api.md`. Jede Anfrage zählt gegen das
+Tageslimit von 100.
+
+## Übernahme in die App
+
+Seit 2026-09-25 eingebaut: alle elf aus `photo/` plus die vier Fassungen aus
+`v2/` (Tinte Blatt, Papier Bütten, Leinen Falten, Aquarell Streifen), also
+15 zur Auswahl. Dateien liegen unter `frontend/public/images/backgrounds/`
+(2048 px, JPEG q5) mit Vorschauen in `thumbs/`; Namen, Reihenfolge und
+Helligkeit (`tone`, steuert die Logo-Variante) in
+`frontend/src/config/backgrounds.js`. Die alten `bg-image-1…10` sind
+entfernt; gespeicherte Einstellungen mit einem alten Pfad werden auf den
+nächstliegenden Nachfolger umgeschrieben.
+
+Aussortieren heißt: Eintrag aus der Config nehmen und Datei löschen. Presets
+in `wavePresets.js` zeigen auf: Nachthimmel, Leinen, Nebel, Tinte, Kohle,
+Horizont, Dämmerung.
diff --git a/dev/backgrounds/uebersicht.jpg b/dev/backgrounds/uebersicht.jpg
new file mode 100644
index 0000000..eb37b1e
Binary files /dev/null and b/dev/backgrounds/uebersicht.jpg differ
diff --git a/dev/tools/backgrounds/build_graphic.py b/dev/tools/backgrounds/build_graphic.py
new file mode 100644
index 0000000..d2bdc9e
--- /dev/null
+++ b/dev/tools/backgrounds/build_graphic.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python3
+"""Builds the graphic LifeWave backgrounds as SVG and renders them to JPEG.
+
+Square 2048 px, so `background-size: cover` crops them evenly in portrait and
+landscape. Palette: ink #292a2b / #1a1b1c, gold #f5c26b / #d59040, paper
+#f7f3ea. Deterministic: same seed, same file.
+
+Usage: python3 build_graphic.py [out_dir] (default dev/backgrounds/graphic)
+"""
+import os, random, subprocess, sys
+
+ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
+OUT = sys.argv[1] if len(sys.argv) > 1 else os.path.join(ROOT, 'dev', 'backgrounds', 'graphic')
+S = 2048
+
+GRAIN = '''
+
+
+
+
+ '''
+
+def svg(defs, body):
+ return f'\n'
+
+def ink():
+ defs = '''
+
+
+ ''' + GRAIN.format(alpha=0.06)
+ body = f''
+ return svg(defs, body)
+
+def gold_dust():
+ rnd = random.Random(2026)
+ specks = []
+ for _ in range(5200):
+ # Denser and brighter towards the bottom; the middle band stays calm.
+ y = S * (1 - rnd.random() ** 0.45)
+ x = rnd.random() * S
+ r = rnd.choice([1.0, 1.3, 1.6, 2.0, 2.6, 3.4, 4.2])
+ depth = y / S
+ o = min(0.95, (0.08 + 1.1 * depth ** 1.6) * rnd.uniform(0.35, 1.0))
+ c = '#f5c26b' if rnd.random() < 0.7 else '#d59040'
+ specks.append(f'')
+ defs = '''
+
+
+
+
+
+
+ ''' + GRAIN.format(alpha=0.05)
+ body = (f''
+ f''
+ f'{"".join(specks[:2200])}{"".join(specks[2200:])}'
+ f'')
+ return svg(defs, body)
+
+def horizon():
+ defs = '''
+
+
+
+
+ ''' + GRAIN.format(alpha=0.05)
+ body = (f''
+ f''
+ f''
+ f'')
+ return svg(defs, body)
+
+def paper():
+ defs = '''
+
+
+
+
+
+
+
+ ''' + GRAIN.format(alpha=0.05)
+ body = (f''
+ f''
+ f'')
+ return svg(defs, body)
+
+def charcoal():
+ rnd = random.Random(11)
+ smudges = ''.join(
+ f''
+ for _ in range(9))
+ defs = '''
+
+
+
+
+
+
+
+
+ ''' + GRAIN.format(alpha=0.08)
+ body = (f''
+ f''
+ f'{smudges}'
+ f'')
+ return svg(defs, body)
+
+BACKGROUNDS = [
+ ('01-tinte', ink), ('02-goldstaub', gold_dust), ('03-horizont', horizon),
+ ('04-papier', paper), ('07-kohle', charcoal),
+]
+
+if __name__ == '__main__':
+ os.makedirs(OUT, exist_ok=True)
+ for name, fn in BACKGROUNDS:
+ svg_path = os.path.join(OUT, f'{name}.svg')
+ png_path = os.path.join(OUT, f'{name}.png')
+ jpg_path = os.path.join(OUT, f'{name}.jpg')
+ open(svg_path, 'w').write(fn())
+ subprocess.run(['rsvg-convert', '-w', str(S), '-h', str(S), svg_path, '-o', png_path], check=True)
+ subprocess.run(['ffmpeg', '-v', 'error', '-y', '-i', png_path, '-q:v', '3', jpg_path], check=True)
+ os.remove(png_path)
+ print(jpg_path, os.path.getsize(jpg_path) // 1024, 'KB')
diff --git a/dev/tools/backgrounds/generate_photo.py b/dev/tools/backgrounds/generate_photo.py
new file mode 100644
index 0000000..0fd062e
--- /dev/null
+++ b/dev/tools/backgrounds/generate_photo.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+"""Generates the photographic LifeWave backgrounds with Gemini (Nano Banana 2).
+
+Square, because the app crops with `cover` in both orientations. Every
+prompt asks for an empty middle band and no focal point: the wave and its
+dots are the subject, the background only sets the mood.
+
+Usage: python3 generate_photo.py [name ...] (default: all five)
+"""
+import os, sys, time
+
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'lifeline-images'))
+from gemini import generate # noqa: E402
+
+ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
+OUT = os.path.join(ROOT, 'dev', 'backgrounds', 'photo')
+
+COMMON = (' Square format, fills the frame edge to edge. No text, no watermark, no people, no animals, '
+ 'no buildings, no objects. The centre band of the image is calm and almost uniform, because a '
+ 'thin glowing line will be drawn over it later. Photographic, subdued, low contrast, fine grain.')
+
+PROMPTS = {
+ # Second pass: the graphic ideas rendered as photographed material, so
+ # they carry inner detail without gaining a subject.
+ '01-tinte': (
+ 'Macro photograph of the surface of deep charcoal-black handmade paper washed with black ink, so close that '
+ 'the paper extends beyond every edge of the frame, no sheet edges, no border, no background. '
+ 'Subtle mottled variations of anthracite and graphite, faint cotton fibres visible on close inspection, '
+ 'a soft darker vignette towards the edges, raking light from the upper left giving the surface a gentle '
+ 'matte relief. Nothing written on it, no objects.' + COMMON),
+ '02-goldstaub': (
+ 'Macro photograph of fine gold dust and a few tiny gold leaf flakes scattered on dark anthracite velvet. '
+ 'The dust gathers along the bottom edge and thins out quickly upwards, the upper two thirds of the frame '
+ 'are almost empty dark velvet with only a handful of distant specks. Warm gold reflections, very shallow '
+ 'depth of field so most specks are soft bokeh. Elegant, dark, sparse.' + COMMON),
+ '03-horizont': (
+ 'Minimalist photograph of a vast empty plain at the very end of dusk. Black featureless land in the lower '
+ 'third, a deep graphite night sky above, and between them only a thin, soft band of warm amber and gold '
+ 'afterglow along the horizon at two thirds of the height. No sun, no clouds, no trees, no lights. '
+ 'Cinematic, very dark, the glow is the only colour.' + COMMON),
+ '04-papier': (
+ 'Macro photograph of the surface of warm cream handmade cotton paper, so close that the paper extends beyond '
+ 'every edge of the frame, no sheet edges, no deckle edge, no border, no background. Soft uneven surface with '
+ 'fine fibres, lit with raking light from the side so the texture shows as gentle relief, a subtle '
+ 'darker vignette in the corners. No writing, no lines, no objects, no folds.' + COMMON),
+ '05-leinen': (
+ 'Photograph of heavy dark charcoal-grey linen with a visible slub weave, lit from the side so the threads '
+ 'catch a faint warm sheen. The fabric lies flat and even across the whole frame, no folds, no creases, no '
+ 'seams, only the weave itself with a very gentle variation of light. Rich, tactile, dark, low contrast.' + COMMON),
+ '06a-aquarell-warm': (
+ 'Extreme close-up of a watercolour wash on cold-pressed paper, the paper runs beyond every edge of the '
+ 'frame, no border, no tape marks, no stripes, no bands, one continuous sheet. Blooms of warm sepia, golden '
+ 'ochre and a little dusty indigo pigment gather in the corners with visible granulation and soft '
+ 'cauliflower edges, the middle stays pale warm cream. No shapes, no drips, no splatter.' + COMMON),
+ '06b-aquarell-dunkel': (
+ 'Extreme close-up of an ink wash on heavy paper, the paper runs beyond every edge of the frame, no border. '
+ 'Deep indigo and graphite ink bleeds in from the top and bottom edges with visible granulation, the '
+ 'middle band softens into a muted grey-blue wash, tiny specks of gold pigment caught in the darker '
+ 'areas. Moody, dark overall. No shapes, no drips.' + COMMON),
+ '07-kohle': (
+ 'Photograph of a dark slate chalkboard surface, matte anthracite with a faint haze of chalk dust and the '
+ 'ghost traces of wiped chalk strokes near the top and bottom edges, the centre almost clean. Fine mineral '
+ 'texture of the slate visible up close, soft even light.' + COMMON),
+ '08-nebel': (
+ 'Photograph of gentle hills at dawn in dense morning fog, almost monochrome grey-blue, dark toned. '
+ 'A faint treeline is barely visible at the very bottom, the rest of the frame is soft, empty fog with a '
+ 'slight brightening towards the top. No sun, no sky detail.' + COMMON),
+ '09-daemmerung': (
+ 'Long-exposure photograph of a calm sea at dusk. The horizon sits in the lower third. Deep blue-grey '
+ 'sky above fading into a narrow warm amber band right at the horizon, perfectly smooth water below, '
+ 'darker than the sky. No sun disc, no detailed clouds, no boats, no shore.' + COMMON),
+ '10-nachthimmel': (
+ 'Photograph of a deep midnight-blue night sky turning to black, with faint thin wisps of high cloud. '
+ 'No stars, no moon, no ground, no horizon, no light source. A smooth dark gradient with a hint of '
+ 'texture from the clouds.' + COMMON),
+}
+
+if __name__ == '__main__':
+ names = sys.argv[1:] or list(PROMPTS)
+ os.makedirs(OUT, exist_ok=True)
+ for name in names:
+ out = os.path.join(OUT, f'{name}.jpg')
+ for size in ('2K', '1K'):
+ try:
+ generate(PROMPTS[name], out=out, aspect='1:1', size=size)
+ print(out, size, os.path.getsize(out) // 1024, 'KB')
+ break
+ except RuntimeError as error:
+ print(name, size, 'failed:', str(error)[:200])
+ time.sleep(2)
diff --git a/documentation/bildgenerierung-gemini-api.md b/documentation/bildgenerierung-gemini-api.md
new file mode 100644
index 0000000..3533354
--- /dev/null
+++ b/documentation/bildgenerierung-gemini-api.md
@@ -0,0 +1,119 @@
+# Google-Gemini-Bild-API: Zugang
+
+Stand: 25.09.2026
+
+## Überblick
+
+Die Key-Images der Demo-Lifelines entstehen über die Google Gemini API, Modell `gemini-3.1-flash-image` (Produktname „Nano Banana 2"). Der Zugang läuft ausschließlich über REST mit einem API-Key aus dem Google AI Studio – kein SDK, kein OAuth, kein Google-Cloud-Projekt-Setup nötig.
+
+Genutzt wird der Zugang nur von den Entwickler-Werkzeugen unter `dev/tools/lifeline-images/`:
+
+| Datei | Aufgabe |
+| --- | --- |
+| `gemini.py` | Einziger API-Client: liest den Key, baut den Request, speichert das Bild |
+| `anchors.py` | Erzeugt die Altersanker je Figur (Porträt-Kette) |
+| `events.py` | Erzeugt ein Bild pro Lifeline-Event mit Ankern als Referenz |
+| `contact_sheet.py`, `montage.py` | Reine Sichtungs-Werkzeuge, ohne API-Zugriff |
+
+Die Laravel-Anwendung selbst spricht nie mit der API. Sie importiert nur fertige Dateien per `php artisan lifelines:import-images `.
+
+## Zugangsdaten
+
+Der Key steht als `GOOGLE_API_KEY` in `backend/.env` – sonst nirgends. `.env` ist in `backend/.gitignore` ausgeschlossen, der Key liegt also nicht im Repository.
+
+```
+GOOGLE_API_KEY=
+```
+
+`gemini.py` liest die Datei direkt zeilenweise und schneidet Anführungszeichen ab; fehlt der Eintrag, bricht das Skript mit `GOOGLE_API_KEY missing in backend/.env` ab. Der Key wird nur als HTTP-Header `x-goog-api-key` gesendet, nie in eine URL, einen Log oder eine Ausgabe geschrieben.
+
+Regeln für den Umgang:
+
+- Der Key gehört nur in die lokale Entwicklungsumgebung. Auf Produktion wird er **nicht** benötigt – dort landen ausschließlich die fertigen PNG-Dateien und der Import-Befehl.
+- Generierte Bilder und Anker liegen unter `backend/storage/app/private/lifeline-images/` und sind ebenfalls vom Repository ausgeschlossen.
+- Der Key ist ein Zahlungsmittel: Wer ihn hat, generiert auf Kosten des hinterlegten Guthabens. Nicht in Tickets, Chats oder Screenshots weitergeben.
+- Bei Verdacht auf Weitergabe: im AI Studio löschen und neu erzeugen (siehe letzter Abschnitt).
+
+## Endpunkt und Request
+
+Ein Aufruf ist ein POST auf `generateContent` des Bildmodells:
+
+```
+POST https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-image:generateContent
+Content-Type: application/json
+x-goog-api-key:
+```
+
+Der Body enthält einen einzigen Nutzer-Turn. Referenzbilder stehen als `inline_data` **vor** dem Text; ihre Reihenfolge ist bedeutsam, weil der Prompt sie als „Reference photo 1/2/3" anspricht:
+
+```json
+{
+ "contents": [{ "role": "user", "parts": [
+ { "inline_data": { "mime_type": "image/jpeg", "data": "" } },
+ { "text": "" }
+ ]}],
+ "generationConfig": {
+ "responseModalities": ["IMAGE"],
+ "imageConfig": { "aspectRatio": "4:3", "imageSize": "1K" }
+ }
+}
+```
+
+Parameter, die wir setzen:
+
+| Feld | Werte | Bedeutung |
+| --- | --- | --- |
+| `responseModalities` | `["IMAGE"]` | Nur Bild zurück, kein Begleittext |
+| `imageConfig.aspectRatio` | `4:3` bzw. `3:4` | Querformat; `3:4` für Selfies und Porträt-Anker |
+| `imageConfig.imageSize` | `1K` | Auflösungsstufe |
+| Modell-ID | Umgebungsvariable `LIFELINE_IMAGE_MODEL` | Überschreibt die Vorgabe `gemini-3.1-flash-image` |
+
+Einen `seed` verwenden wir nicht mehr; falls doch gesetzt, akzeptiert die API nur Werte bis 1.000.000.
+
+## Antwort verarbeiten
+
+Das Bild steckt base64-kodiert im ersten Kandidaten:
+
+```
+candidates[0].content.parts[*].inlineData.data
+```
+
+Zwei Eigenheiten, die im Client berücksichtigt sind:
+
+- Das Feld heißt je nach Antwort `inlineData` oder `inline_data` – beide Schreibweisen prüfen.
+- Die gelieferten Daten sind faktisch JPEG, obwohl wir die Dateien mit der Endung `.png` ablegen. Beim Hochladen als Referenz wird der MIME-Typ deshalb aus den Magic Bytes bestimmt (`\x89PNG` → `image/png`, sonst `image/jpeg`) und nicht aus der Dateiendung.
+
+Kommt kein Bild zurück, steht der Grund in `candidates[0].finishReason` oder in `promptFeedback`. Der Client wiederholt den Aufruf bis zu dreimal (5 s Pause; bei HTTP 429/500/503 gestaffelt 10/20 s) und wirft danach einen Fehler mit dem Grund im Text.
+
+## Kontingente, Abrechnung, Fehlerbilder
+
+Guthaben und Tageslimit sind zwei getrennte Grenzen. Beide haben wir beim Aufbau der Bildsets erreicht, sie sehen im Log sehr ähnlich aus:
+
+| HTTP | Meldung | Ursache | Abhilfe |
+| --- | --- | --- | --- |
+| 402 | `Your prepayment credits are depleted` | Prepaid-Guthaben aufgebraucht | Im AI Studio unter Billing aufladen; wirkt sofort |
+| 429 | `Quota exceeded for metric: generate_requests_per_model_per_day, limit: 100` | Tageslimit von 100 Anfragen pro Modell erreicht | Warten bis Mitternacht Pacific (ca. 9 Uhr MESZ) oder höhere Stufe beantragen |
+| 200 mit `finishReason: IMAGE_OTHER` | `The model could not generate the image based on the prompt provided` | Inhaltsfilter des Modells, deterministisch pro Prompt | Prompt umformulieren – Wiederholen hilft nicht |
+
+Zum Tageslimit: Es zählt Anfragen, nicht erfolgreiche Bilder. Fehlversuche und Wiederholungen zählen mit. Ein vollständiger Durchlauf für eine große Lifeline (Jonas, 252 Bilder) sprengt das Limit deshalb und muss über mehrere Tage laufen. Der aktuelle Verbrauch ist unter [ai.dev/rate-limit](https://ai.dev/rate-limit) einsehbar.
+
+Zu `IMAGE_OTHER`: Der Filter reagiert auf Formulierungen, nicht auf Zufall. In unseren Sets waren die Auslöser unter anderem Rollenangaben wie „Singer of the band" (Prominenten-Filter), oberkörperfreie Referenzbilder und Kombinationen aus erschöpften Gesichtsbeschreibungen mit Bettszenen. Vorgehen: Prompt halbieren und die Hälften einzeln testen, bis die auslösende Passage feststeht.
+
+## Key anlegen oder rotieren
+
+1. [aistudio.google.com](https://aistudio.google.com/) mit dem Google-Konto öffnen, das die Rechnung trägt.
+2. Unter **Get API key** einen Key für das gewünschte Projekt erzeugen. Der Wert wird nur einmal vollständig angezeigt.
+3. Für das Bildmodell muss im Projekt Billing aktiv sein und Guthaben vorhanden – unter [ai.studio/projects](https://ai.studio/projects) zu prüfen. Ohne Guthaben antwortet die API mit HTTP 402.
+4. Key in `backend/.env` als `GOOGLE_API_KEY=` eintragen. Kein `php artisan config:clear` nötig, da nur die Python-Werkzeuge ihn lesen.
+5. Prüfen mit einem einzelnen Bild, zum Beispiel:
+
+ ```
+ cd dev/tools/lifeline-images
+ python3 gemini.py "Ein roter Apfel auf einem weißen Tisch, Foto." --out /tmp/test.png
+ ```
+
+ Erfolg gibt den Pfad aus; bei Problemen erscheint die HTTP-Fehlermeldung im Klartext.
+
+6. Alten Key nach der Umstellung im AI Studio löschen.
+
+Das Tageslimit hängt an Projekt und Abrechnungsstufe, nicht am einzelnen Key. Ein neuer Key im selben Projekt umgeht das Limit also nicht.
diff --git a/frontend/public/images/backgrounds/aquarell-streifen.jpg b/frontend/public/images/backgrounds/aquarell-streifen.jpg
new file mode 100644
index 0000000..5d103fa
Binary files /dev/null and b/frontend/public/images/backgrounds/aquarell-streifen.jpg differ
diff --git a/frontend/public/images/backgrounds/aquarell.jpg b/frontend/public/images/backgrounds/aquarell.jpg
new file mode 100644
index 0000000..c323070
Binary files /dev/null and b/frontend/public/images/backgrounds/aquarell.jpg differ
diff --git a/frontend/public/images/backgrounds/daemmerung.jpg b/frontend/public/images/backgrounds/daemmerung.jpg
new file mode 100644
index 0000000..aaae026
Binary files /dev/null and b/frontend/public/images/backgrounds/daemmerung.jpg differ
diff --git a/frontend/public/images/backgrounds/goldstaub.jpg b/frontend/public/images/backgrounds/goldstaub.jpg
new file mode 100644
index 0000000..0d2a556
Binary files /dev/null and b/frontend/public/images/backgrounds/goldstaub.jpg differ
diff --git a/frontend/public/images/backgrounds/horizont.jpg b/frontend/public/images/backgrounds/horizont.jpg
new file mode 100644
index 0000000..c5282ec
Binary files /dev/null and b/frontend/public/images/backgrounds/horizont.jpg differ
diff --git a/frontend/public/images/backgrounds/kohle.jpg b/frontend/public/images/backgrounds/kohle.jpg
new file mode 100644
index 0000000..96eacf1
Binary files /dev/null and b/frontend/public/images/backgrounds/kohle.jpg differ
diff --git a/frontend/public/images/backgrounds/leinen-falten.jpg b/frontend/public/images/backgrounds/leinen-falten.jpg
new file mode 100644
index 0000000..8a875b3
Binary files /dev/null and b/frontend/public/images/backgrounds/leinen-falten.jpg differ
diff --git a/frontend/public/images/backgrounds/leinen.jpg b/frontend/public/images/backgrounds/leinen.jpg
new file mode 100644
index 0000000..03320c1
Binary files /dev/null and b/frontend/public/images/backgrounds/leinen.jpg differ
diff --git a/frontend/public/images/backgrounds/nachthimmel.jpg b/frontend/public/images/backgrounds/nachthimmel.jpg
new file mode 100644
index 0000000..30f4881
Binary files /dev/null and b/frontend/public/images/backgrounds/nachthimmel.jpg differ
diff --git a/frontend/public/images/backgrounds/nebel.jpg b/frontend/public/images/backgrounds/nebel.jpg
new file mode 100644
index 0000000..5c6fa78
Binary files /dev/null and b/frontend/public/images/backgrounds/nebel.jpg differ
diff --git a/frontend/public/images/backgrounds/papier-buetten.jpg b/frontend/public/images/backgrounds/papier-buetten.jpg
new file mode 100644
index 0000000..1582788
Binary files /dev/null and b/frontend/public/images/backgrounds/papier-buetten.jpg differ
diff --git a/frontend/public/images/backgrounds/papier.jpg b/frontend/public/images/backgrounds/papier.jpg
new file mode 100644
index 0000000..50213af
Binary files /dev/null and b/frontend/public/images/backgrounds/papier.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/aquarell-streifen.jpg b/frontend/public/images/backgrounds/thumbs/aquarell-streifen.jpg
new file mode 100644
index 0000000..f767cdb
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/aquarell-streifen.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/aquarell.jpg b/frontend/public/images/backgrounds/thumbs/aquarell.jpg
new file mode 100644
index 0000000..5a450fb
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/aquarell.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/daemmerung.jpg b/frontend/public/images/backgrounds/thumbs/daemmerung.jpg
new file mode 100644
index 0000000..d6e66f7
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/daemmerung.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/goldstaub.jpg b/frontend/public/images/backgrounds/thumbs/goldstaub.jpg
new file mode 100644
index 0000000..efa6089
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/goldstaub.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/horizont.jpg b/frontend/public/images/backgrounds/thumbs/horizont.jpg
new file mode 100644
index 0000000..26b1c4c
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/horizont.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/kohle.jpg b/frontend/public/images/backgrounds/thumbs/kohle.jpg
new file mode 100644
index 0000000..81ae7f2
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/kohle.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/leinen-falten.jpg b/frontend/public/images/backgrounds/thumbs/leinen-falten.jpg
new file mode 100644
index 0000000..b61464d
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/leinen-falten.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/leinen.jpg b/frontend/public/images/backgrounds/thumbs/leinen.jpg
new file mode 100644
index 0000000..73a500d
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/leinen.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/nachthimmel.jpg b/frontend/public/images/backgrounds/thumbs/nachthimmel.jpg
new file mode 100644
index 0000000..07e6cae
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/nachthimmel.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/nebel.jpg b/frontend/public/images/backgrounds/thumbs/nebel.jpg
new file mode 100644
index 0000000..29c8fc0
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/nebel.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/papier-buetten.jpg b/frontend/public/images/backgrounds/thumbs/papier-buetten.jpg
new file mode 100644
index 0000000..78140ae
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/papier-buetten.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/papier.jpg b/frontend/public/images/backgrounds/thumbs/papier.jpg
new file mode 100644
index 0000000..cdfa477
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/papier.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/tinte-blatt.jpg b/frontend/public/images/backgrounds/thumbs/tinte-blatt.jpg
new file mode 100644
index 0000000..04a0a6e
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/tinte-blatt.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/tinte.jpg b/frontend/public/images/backgrounds/thumbs/tinte.jpg
new file mode 100644
index 0000000..36025f3
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/tinte.jpg differ
diff --git a/frontend/public/images/backgrounds/thumbs/tusche.jpg b/frontend/public/images/backgrounds/thumbs/tusche.jpg
new file mode 100644
index 0000000..d963681
Binary files /dev/null and b/frontend/public/images/backgrounds/thumbs/tusche.jpg differ
diff --git a/frontend/public/images/backgrounds/tinte-blatt.jpg b/frontend/public/images/backgrounds/tinte-blatt.jpg
new file mode 100644
index 0000000..5b483a8
Binary files /dev/null and b/frontend/public/images/backgrounds/tinte-blatt.jpg differ
diff --git a/frontend/public/images/backgrounds/tinte.jpg b/frontend/public/images/backgrounds/tinte.jpg
new file mode 100644
index 0000000..e1c8f77
Binary files /dev/null and b/frontend/public/images/backgrounds/tinte.jpg differ
diff --git a/frontend/public/images/backgrounds/tusche.jpg b/frontend/public/images/backgrounds/tusche.jpg
new file mode 100644
index 0000000..e879151
Binary files /dev/null and b/frontend/public/images/backgrounds/tusche.jpg differ
diff --git a/frontend/public/images/bg-image-1.jpg b/frontend/public/images/bg-image-1.jpg
deleted file mode 100644
index 7138f9f..0000000
Binary files a/frontend/public/images/bg-image-1.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-10.jpg b/frontend/public/images/bg-image-10.jpg
deleted file mode 100644
index 7c9a991..0000000
Binary files a/frontend/public/images/bg-image-10.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-2.jpg b/frontend/public/images/bg-image-2.jpg
deleted file mode 100644
index 2a6b8a1..0000000
Binary files a/frontend/public/images/bg-image-2.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-3.jpg b/frontend/public/images/bg-image-3.jpg
deleted file mode 100644
index e5036fd..0000000
Binary files a/frontend/public/images/bg-image-3.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-4.jpg b/frontend/public/images/bg-image-4.jpg
deleted file mode 100644
index 5084322..0000000
Binary files a/frontend/public/images/bg-image-4.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-5.jpg b/frontend/public/images/bg-image-5.jpg
deleted file mode 100644
index 2cc7fb7..0000000
Binary files a/frontend/public/images/bg-image-5.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-6.jpg b/frontend/public/images/bg-image-6.jpg
deleted file mode 100644
index f0a89dc..0000000
Binary files a/frontend/public/images/bg-image-6.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-7.jpg b/frontend/public/images/bg-image-7.jpg
deleted file mode 100644
index 631e527..0000000
Binary files a/frontend/public/images/bg-image-7.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-8.jpg b/frontend/public/images/bg-image-8.jpg
deleted file mode 100644
index 7c9a991..0000000
Binary files a/frontend/public/images/bg-image-8.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-image-9.jpg b/frontend/public/images/bg-image-9.jpg
deleted file mode 100644
index 87e3fbd..0000000
Binary files a/frontend/public/images/bg-image-9.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-1.jpg b/frontend/public/images/bg-thumbs/bg-image-1.jpg
deleted file mode 100644
index 76c2b5e..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-1.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-10.jpg b/frontend/public/images/bg-thumbs/bg-image-10.jpg
deleted file mode 100644
index 8cdbcf5..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-10.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-2.jpg b/frontend/public/images/bg-thumbs/bg-image-2.jpg
deleted file mode 100644
index 3bff6bd..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-2.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-3.jpg b/frontend/public/images/bg-thumbs/bg-image-3.jpg
deleted file mode 100644
index 79a76dc..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-3.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-4.jpg b/frontend/public/images/bg-thumbs/bg-image-4.jpg
deleted file mode 100644
index ec3ebe2..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-4.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-5.jpg b/frontend/public/images/bg-thumbs/bg-image-5.jpg
deleted file mode 100644
index ec26bce..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-5.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-6.jpg b/frontend/public/images/bg-thumbs/bg-image-6.jpg
deleted file mode 100644
index 53f5eba..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-6.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-7.jpg b/frontend/public/images/bg-thumbs/bg-image-7.jpg
deleted file mode 100644
index a59792d..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-7.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-8.jpg b/frontend/public/images/bg-thumbs/bg-image-8.jpg
deleted file mode 100644
index 8cdbcf5..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-8.jpg and /dev/null differ
diff --git a/frontend/public/images/bg-thumbs/bg-image-9.jpg b/frontend/public/images/bg-thumbs/bg-image-9.jpg
deleted file mode 100644
index ce39c3f..0000000
Binary files a/frontend/public/images/bg-thumbs/bg-image-9.jpg and /dev/null differ
diff --git a/frontend/quasar.config.js b/frontend/quasar.config.js
index 3c322d0..c765688 100644
--- a/frontend/quasar.config.js
+++ b/frontend/quasar.config.js
@@ -176,9 +176,9 @@ export default defineConfig((ctx) => {
cfg.globPatterns = [
'**/*.{js,css,html,ico,svg,woff,woff2,json,webmanifest}',
'icons/*.png',
- 'images/bg-thumbs/*.jpg'
+ 'images/backgrounds/thumbs/*.jpg'
]
- cfg.globIgnores = [ ...(cfg.globIgnores || []), 'images/bg-image-*.jpg', 'images/gallery/**', 'videos/**', 'audio/**', 'demo/**', 'js/**' ]
+ cfg.globIgnores = [ ...(cfg.globIgnores || []), 'images/backgrounds/*.jpg', 'images/gallery/**', 'videos/**', 'audio/**', 'demo/**', 'js/**' ]
cfg.navigateFallbackDenylist = [ ...(cfg.navigateFallbackDenylist || []), /^\/api\//, /^\/event-media\// ]
cfg.runtimeCaching = [
{
diff --git a/frontend/src/components/BrandLogo.vue b/frontend/src/components/BrandLogo.vue
index 9ce6abe..1e5c7b8 100644
--- a/frontend/src/components/BrandLogo.vue
+++ b/frontend/src/components/BrandLogo.vue
@@ -14,6 +14,7 @@ import { computed } from 'vue'
import { useQuasar } from 'quasar'
import { useSettingsStore } from 'stores/settings'
import { logoVariantForBackground } from 'src/utils/brand'
+import { findBackgroundImage } from 'src/config/backgrounds'
import logoPositive from 'assets/logo-thatsme-positiv.svg'
import logoNegative from 'assets/logo-thatsme-negativ.svg'
@@ -41,6 +42,7 @@ const resolvedVariant = computed(() => {
bgEdge: fl.bgEdge,
bgCenter: fl.bgCenter,
backgroundImage: fl.backgroundImage,
+ imageTone: findBackgroundImage(fl.backgroundImage)?.tone ?? null,
isDark: $q.dark.isActive
})
})
diff --git a/frontend/src/components/LifeWaveSettings.vue b/frontend/src/components/LifeWaveSettings.vue
index 464de3d..153a1c0 100644
--- a/frontend/src/components/LifeWaveSettings.vue
+++ b/frontend/src/components/LifeWaveSettings.vue
@@ -92,7 +92,10 @@