Doku und Werkzeuge: Tickets, Audit, Logos, Playwright-MCP

- dev/: Ticketliste, Audit und Vorschläge vom 17.09., Logo-SVGs,
  Lifeline-Bildwerkzeuge.
- AGENTS.md auf den aktuellen Stand (syncQueue statt syncService, kein
  legacy-Ordner mehr).
- .codex/ und __pycache__/ ignoriert; Playwright-MCP in .mcp.json.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-25 07:00:35 +00:00
parent 83c6c5813d
commit 10251e4f41
15 changed files with 2163 additions and 0 deletions

3
.gitignore vendored
View file

@ -53,6 +53,9 @@ Icon
# Project specific
# Local agent/tool configs (may hold API keys)
.codex/
__pycache__/
_static/
_work/
_storage/

View file

@ -22,6 +22,9 @@
"-y",
"@modelcontextprotocol/server-sequential-thinking"
]
},
"playwright": {
"url": "https://playwright.test/mcp"
}
}
}

85
AGENTS.md Normal file
View file

@ -0,0 +1,85 @@
# Repository guidance
## Scope and sources
This file applies to the repository. Follow `backend/AGENTS.md` for additional
Laravel-specific instructions when working under `backend/`.
Check neighboring code before changing conventions. Prefer current source,
package manifests, and `docker-compose.yml` over older setup examples; some
README and architecture documents contain placeholders or describe planned work.
## Project map
- `frontend/`: Quasar 2 SPA using Vue 3, Pinia, Vue Router, Vite, and Dexie.
The active experience uses `src/pages/LifeWavePage.vue`,
`src/layouts/LifeWaveLayout.vue`, and components such as `TimelineView.vue`,
`FloatingLines.vue`, and `EventPanel.vue`.
- `frontend/src/stores/`: authentication, settings, and event state.
`src/services/apiClient.js` centralizes API requests and bearer tokens;
`src/services/syncQueue.js` holds the offline write queue every remote
write goes through (see `test/vitest/events-offline.spec.js`);
`src/db/index.js` defines versioned IndexedDB schemas.
- `backend/`: Laravel 12 API and website, with Passport authentication,
Livewire/Volt, Flux UI, and Tailwind CSS 4. API routes are in `routes/api.php`;
application code is in `app/`, Blade views in `resources/views/`, and
migrations in `database/migrations/`.
- `dot-line-system/`: separate Vite/TypeScript visualization experiment.
Root `test/` contains HTML animation experiments, not an automated test suite.
- `frontend/dev/db-api-connect/`: API migration plans and implementation log.
Read the relevant documents for changes to persistence or API contracts,
distinguishing planned features from implemented behavior.
## Commands and validation
There is no root package manifest. Run commands from the relevant application.
| Directory | Command | Purpose |
| --- | --- | --- |
| `frontend/` | `npm ci` | Install locked dependencies |
| `frontend/` | `npm run dev` | Start Quasar; this script also runs `npm install` |
| `frontend/` | `npm run lint` | Check JavaScript and Vue source with ESLint |
| `frontend/` | `npm run build` | Build the production SPA |
| `backend/` | `composer install` | Install PHP dependencies |
| `backend/` | `npm ci` | Install backend asset dependencies |
| `backend/` | `composer dev` | Run server, queue listener, logs, and Vite |
| `backend/` | `npm run build` | Build backend assets |
| `backend/` | `php artisan test --compact --filter=TestName` | Run targeted Pest tests |
| `backend/` | `php artisan test --compact` | Run the backend suite |
| `backend/` | `vendor/bin/pint --dirty --format agent` | Format changed PHP per backend guidance |
For frontend code changes, run lint and the production build as appropriate.
`npm test` in `frontend/` is a placeholder that exits successfully without
running tests; do not report it as test coverage. Manually check affected UI
behavior when possible. Backend tests live in `backend/tests/`; API feature
tests cover authentication, events, settings, and media. The PHPUnit config
forces an in-memory SQLite database, while the application uses MySQL.
Report any checks that could not run and the reason.
The root Compose file defines `laravel.test` (PHP 8.4) and `quasar.app` (Node 20).
It relies on an external `proxy` network and shared `global-mysql`,
`global-mailpit`, and `global-redis` services. It does not provision those
services or Traefik. With that infrastructure available, use
`docker compose up -d`; application commands can run through
`docker compose exec laravel.test ...` or `docker compose exec quasar.app ...`.
## Implementation conventions
- Use existing Quasar components and Vue/Pinia patterns. Frontend formatting is
two spaces, single quotes, no semicolons, and a 100-character print width.
Format changed files rather than running a repository-wide formatting pass.
- Router definitions live in `frontend/src/router/routes.js`; Quasar currently
uses hash routing. Keep network access in the existing API client and stores.
The API base can be configured with `VITE_API_BASE`.
- Laravel/MySQL is the intended authoritative store; IndexedDB and localStorage
support caching and offline behavior during the migration. Inspect the current
stores before assuming all writes use the sync queue. Preserve user scoping,
existing cached data, and stable event/client IDs when changing persistence.
- Enforce ownership on the backend for user settings, events, and media.
Preserve authorized media delivery and test cross-user access restrictions.
- Follow backend guidance for typed PHP, Eloquent, Form Requests, Artisan
generators, Pest tests, and Pint. Keep environment lookups in config files.
- Keep `frontend/src/config/appVersion.js`, `frontend/package.json`, and version
documentation consistent. Document data-model and API-contract changes in
the existing DB/API migration documents.
- Keep credentials out of source and logs. Avoid editing dependency directories
or generated build output; retain lockfiles when changing dependencies.

443
dev/AUDIT-2026-09-17.md Normal file
View file

@ -0,0 +1,443 @@
# Projektaudit: Quasar-Frontend und Laravel-Backend
**Datum:** 17.09.2026
**Geprüfter Commit:** `f79dcb992839cba04e824b3d9e23231efa7b6bdc` vom 07.07.2026
**Umfang:** Entwicklungsstand, aktive Anwendung, API, Persistenz, Authentifizierung, Medien, Abhängigkeiten und Qualitätssicherung.
**Ergebnis dieser Arbeit:** Audit und Maßnahmenvorschläge; keine Änderungen an Anwendungscode, Datenmodell oder Abhängigkeiten.
**Kontextnachtrag vom 17.09.2026:** Projektziel und Maßnahmenreihenfolge nach Rückmeldung des Projektverantwortlichen angepasst. Die technischen Befunde und bisherigen Prüfergebnisse bleiben bestehen; ihre Dringlichkeit wird nach Entwicklungsphase eingeordnet. Für diesen Nachtrag wurden Auth-Store und Seeder erneut gelesen, keine Builds, Tests oder Registry-Prüfungen wiederholt.
## 1. Einschätzung
Das Projekt befindet sich nach Auskunft des Projektverantwortlichen in Entwicklung und wird aktuell getestet. Das nächste Ziel ist eine kleine Demo, die das Produkt vorstellt und Interesse weckt. Social Media soll dabei helfen, Interessenten und spätere Kunden zu erreichen. Bei ausreichendem Interesse kommt eine Crowdfunding-Kampagne infrage; sie ist noch keine beschlossene Projektphase.
Aktuell gibt es keine regulären Kundenkonten im vorgesehenen Testbetrieb. Die sechs auswählbaren API-Konten dienen bewusst dazu, serverseitiges Speichern und Benutzerwechsel zu testen. Hinzu kommt ein lokaler Demo-Zugang ohne API-Anmeldung. Dieses Testmodell passt zum Entwicklungsziel; sechs feste Testkonten und vereinfachte Zugangsdaten sind für sich genommen kein Entwicklungsfehler.
Das Projekt hat eine brauchbare Grundlage für diese Demo. Die Quasar-Oberfläche, lokale Demo-Daten, API-Anmeldung, Event-CRUD, Benutzereinstellungen und geschützte Bildauslieferung sind implementiert. Die serverseitige Einschränkung der meisten Datenzugriffe auf den angemeldeten Benutzer ist sauber erkennbar und durch API-Tests teilweise abgesichert.
**Für den nächsten Entwicklungsschritt stehen zuverlässige Demo-Abläufe im Vordergrund:** Speichern und Wiederladen, vollständige Event-Felder, korrektes Umschalten zwischen Testkonten und eine verständliche Fehleranzeige. Die nachgewiesenen Speicher- und Benutzerwechselprobleme beeinträchtigen bereits die Testbarkeit und eine Präsentation mit Beispieldaten. Anforderungen an einen späteren Betrieb mit echten privaten Konten werden gesondert vorgemerkt.
**Prioritäten:**
- **P1 – hoch:** im jeweils genannten Nutzungsszenario vorrangig bearbeiten; aktuell vor allem wesentliche Demo- und Speicherfehler, bei öffentlichem Betrieb zusätzlich erreichbare Sicherheitsrisiken.
- **P2 – mittel:** im nächsten Stabilisierungsschritt beheben; teilweise abhängig von Fehlersituationen, Datenmenge oder Nutzung.
- **P3 – niedrig / Optimierung:** Wartbarkeit, Performance und Entwicklungsabläufe verbessern.
### 1.1 Bewertung nach Entwicklungsphase
| Phase | Schwerpunkt | Konsequenz für diesen Audit |
| --- | --- | --- |
| Aktueller Teststand mit sechs API-Testkonten und lokalem Demo-Zugang | Persistenz, Darstellung und Benutzerwechsel überprüfen | Testkonten beibehalten; A04–A08 als Funktionsfehler priorisieren. Vollständige Kundenregistrierung oder ein ausgebautes Kontensystem sind dafür nicht erforderlich. |
| Geplante Werbedemo | Produkt verständlich und zuverlässig präsentieren | Bei einer betreuten Präsentation stehen die gezeigten Abläufe im Vordergrund. Falls Besucher selbst API-Konten und Uploads nutzen dürfen, zusätzlich Missbrauch und Veränderung gemeinsamer Beispieldaten berücksichtigen. Das spätere Zugangsmodell ist noch offen. |
| Öffentliche Erreichbarkeit von API oder Entwicklungsdiensten | Verfügbarkeit und Schutz der Infrastruktur | Sicherheitsupdates für erreichbare Schwachstellen, Zugriffsschutz sowie angemessene Request-/Upload-Limits werden auch ohne echte Kundenkonten relevant. Ob die derzeitige Testinstallation öffentlich erreichbar ist, wurde nicht geprüft. |
| Möglicher späterer Betrieb mit echten Konten und privaten Inhalten | Verbindliche Benutzertrennung, Zugriffsschutz und Datenlebenszyklus | Demo-Seeding von echten Konten trennen und die vorgemerkten Sicherheits-/Betriebsanforderungen vor dieser Nutzung abarbeiten. |
Die Nutzerangaben beschreiben den vorgesehenen Testbetrieb; Datenbankinhalte und Live-Erreichbarkeit wurden nicht kontrolliert. Es wurde kein Angriff auf einen Live-Server ausgeführt. Ein verwundbarer Paketstand oder ein Seeder ohne Umgebungsschutz ist kein Beweis dafür, dass eine Installation bereits kompromittiert ist.
## 2. Entwicklung und tatsächlicher Stand
### 2.1 Verlauf
| Stand | Entwicklung | Einordnung |
| --- | --- | --- |
| 20.02.2026, `98084de` | LifeWave-Oberfläche, Timeline, Shader, Event-Panel und mobile Vorarbeiten | Schwerpunkt auf Darstellung und Interaktion |
| 25.02.2026, `70a7776` | Passport, Event-API, Migrationen, API-Tests, IndexedDB und Synchronisationsservice | Beginn der Backend-/Offline-Anbindung |
| April 2026 | Weitere UI-/Medienarbeit und zusätzliche Prototypquellen | Mehrere Entwicklungsstände liegen nebeneinander |
| 05.06.2026, `c151499` | Hybrid-Anmeldung, Remote-Events, Settings und geschützte Medien | Aktueller wesentlicher Integrationsstand |
| 07.07.2026, `f79dcb9` | Performance- und Sync-Anpassungen überwiegend unter `frontend/_src` | Änderungen dort gehören nicht automatisch zur aktiven App |
Maßgeblich sind [Router](../frontend/src/router/routes.js) und [Quasar-Konfiguration](../frontend/quasar.config.js): Die aktive Oberfläche verwendet `src/pages/LifeWavePage.vue` und `src/layouts/LifeWaveLayout.vue`. `frontend/_src`, `frontend/src/legacy`, `dot-line-system` und die HTML-Experimente unter `test` sind keine gleichwertigen Teile dieses produktiven Ausführungspfads.
### 2.2 Architektur
| Bereich | Tatsächliches Verhalten |
| --- | --- |
| Frontend | Quasar 2 / Vue 3, Pinia, Vue Router mit Hash-Routing, Vite, Dexie, Three.js |
| Lokaler Demo-Benutzer | Events und Medien in IndexedDB, Settings in localStorage; neue Demo-Mutationen werden nicht in die API-SyncQueue geschrieben |
| Sechs Remote-Testbenutzer | Bewusst persistierende API-Konten für Events, Settings und Uploads; IndexedDB/localStorage dienen zusätzlich als Cache |
| Authentifizierung | Passport-Bearer-Token in IndexedDB; Benutzerprofil zusätzlich in localStorage |
| Backend | Laravel 12 mit Passport; daneben Website und Livewire-/Volt-Einstellungen |
| Medien | Private Dateien, benutzergebundene Auslieferung; Thumbnail, Preview und verkleinertes Original |
| Synchronisation | Separater älterer Service existiert; kein durchgehend funktionierender Offline-Schreibpfad für die aktive Remote-App |
| Infrastruktur | Compose mit PHP 8.4 und Node 20; externe Dienste und externes `proxy`-Netz werden vorausgesetzt |
Aus den Lockfiles: Quasar `2.18.6`, Vue `3.5.29`, Pinia `3.0.4`, Dexie `4.3.0`, Three.js `0.183.1`, Frontend-Vite `7.3.1`; Laravel `12.52.0`, Passport `13.5.0`, Livewire `4.1.4`, Volt `1.10.2`, Pest `3.8.5`, Backend-Vite `6.4.0`.
Der erneute Codeabgleich bestätigt die sechs auswählbaren Remote-Testkonten und `local-demo` im [Auth-Store](../frontend/src/stores/auth.js). Der [Backend-Seeder](../backend/database/seeders/DatabaseSeeder.php) legt daneben einen zusätzlichen allgemeinen `Test User` an, der nicht zur sechs Einträge umfassenden Frontend-Auswahl gehört. Der lokale Demo-Zugang wird im Frontend definiert und ist kein siebtes API-Konto. Damit sind lokale Demo-Speicherung und serverseitige Persistenztests bewusst getrennte Abläufe.
### 2.3 Dokumentation weicht vom Code ab
Der [Implementierungsplan](../frontend/dev/db-api-connect/implementation-plan.md) bezeichnet wesentliche Phasen als abgeschlossen und fordert die Speicherung von `location` und `key_image_title`. Diese Felder fehlen weiterhin im Backend. Außerdem verweist der Sync-Nachtrag vom Juli ausdrücklich auf `_src`; die aktive Implementierung unter `src` enthält diese Änderungen nicht.
`frontend/package.json`, `appVersion.js` und das Root-README nennen `0.0.1`; der Implementierungsplan nennt `0.5.0`, das Migrationsprotokoll weitere Zwischenversionen. Historische Versionsangaben sind sinnvoll, müssen aber klar vom aktuellen Release-Stand unterschieden werden. Ein konsistenter Implementierungsstatus und ein verbindlicher API-Vertrag fehlen.
## 3. Ausgeführte Prüfungen
| Prüfung | Ergebnis |
| --- | --- |
| Frontend: `npm run lint` | Erfolgreich |
| Frontend: `npm run build` | Erfolgreich; Warnung wegen eines großen JavaScript-Chunks |
| Backend: `npm run build` | Erfolgreich; leerer `app`-JS-Chunk gemeldet |
| Backend: `php artisan test --compact` | **62 bestanden, 1 fehlgeschlagen, 210 Assertions**; Fehler bei der Profilseite, siehe A17; beim zweiten Lauf bestätigt |
| Backend: `php artisan route:list --path=api -v` | 18 API-Routen; kein Login-/API-Throttle in der registrierten Middleware sichtbar |
| Frontend: `npm audit --json` | 21 betroffene Pakete: 13 high, 5 moderate, 3 low |
| Backend-Assets: `npm audit --json` | 11 betroffene Pakete: 1 critical, 9 high, 1 moderate |
| Backend-PHP: `composer audit --locked --format=json` | 45 Advisory-Einträge zu 14 Paketen; siehe A01 |
| Event-Store: Wechsel vor Ablauf des Debounce | Änderungsverlust isoliert reproduziert, siehe A06 |
| Event-Store: Antworten in umgekehrter Reihenfolge beim Benutzerwechsel | Falscher Benutzerkontext isoliert reproduziert, siehe A04 |
| Datum in `America/Los_Angeles` | `2026-01-01` wird mit aktueller Konvertierung als `31.12.2025` dargestellt, siehe A18 |
Die Checks liefen mit lokal vorhandenem Node `24.14.1` und PHP `8.4.19`. Es wurden keine Paketupdates installiert. PHPUnit erzwingt SQLite `:memory:`; diese Ergebnisse ersetzen keinen MySQL-Integrationstest. Die API-Tests innerhalb der Suite meldeten keinen Fehler.
Für die beiden Store-Reproduktionen wurde der tatsächliche `events.js`-Funktionscode mit Vue-Reaktivität ausgeführt; API, Datenbankzugriffe und Store-Registrierung wurden kontrolliert ersetzt. Das prüft die Ablaufprobleme, ersetzt jedoch keinen Browser-/IndexedDB-End-to-End-Test. Es entstanden keine zusätzlichen Testdateien im Repository.
Nicht durchgeführt: vollständige Browser-/Mobilgeräte-QA, Lasttest, Live-Penetrationstest, Prüfung produktiver Konfiguration, Backups oder realer Nutzerdaten. Die Paketmeldungen stammen aus den am Auditdatum abgefragten Registern; ihre Zahl kann sich ändern. `npm test` im Frontend wurde nicht als Testnachweis verwendet, da das Skript lediglich erfolgreich beendet.
## 4. Kernbefunde und phasenabhängige Prioritäten
### A01 – Bekannte Sicherheitslücken in Abhängigkeiten
**Priorität:** P2 im abgeschirmten Entwicklungsbetrieb; P1 für erreichbare relevante Schwachstellen vor öffentlicher Nutzung. **Nachweis:** Registry-Prüfungen des ursprünglichen Audits; konkrete Ausnutzbarkeit je Advisory gesondert bewerten.
**Einordnung für die Demo:** Paketmeldungen bedeuten nicht, dass zuerst ein vollständiges Produktionssystem aufgebaut werden muss. Erreichbarkeit und betroffener Ausführungspfad bestimmen die Dringlichkeit. Öffentlich erreichbare Entwicklungsdienste können auch bei ausschließlichen Testkonten ein Risiko für die Infrastruktur sein.
Die drei Paketprüfungen melden bekannte Schwachstellen. Besonders relevant:
| Paket / Bereich | Befund und Bedeutung |
| --- | --- |
| Passport `13.5.0` | Liegt im betroffenen Bereich einer TokenGuard-Lücke für `client_credentials`-Tokens; Fix für dieses Advisory ab `13.7.1`. Die dokumentierte Benutzerverwechslung hängt unter anderem von Client-/Benutzer-IDs und verwendeten Grants ab. Im Projekt werden Personal-Access-Tokens erzeugt; eine konkrete Ausnutzung wurde nicht nachgewiesen. [Hersteller-Advisory](https://github.com/laravel/passport/security/advisories/GHSA-349c-2h2f-mxf6) |
| Vite `7.3.1` / `6.4.0` | Bekannter Dateizugriff über den WebSocket eines erreichbaren Dev-Servers. Compose veröffentlicht Entwicklungsports und routet Entwicklungsdienste über Traefik. Eine tatsächliche externe Erreichbarkeit wurde nicht geprüft. Das Advisory betrifft den Dev-Server, nicht automatisch die ausgelieferte statische SPA. [Hersteller-Advisory](https://github.com/vitejs/vite/security/advisories/GHSA-p9ff-h696-f583) |
| Quasar `2.18.6` | Prototype Pollution in `extend()`; Fix für dieses Advisory ab `2.22.0`. Voraussetzung ist ein geeigneter Deep-Merge mit kontrollierbaren Eingaben; kein entsprechender Exploitpfad in dieser App bestätigt. [Hersteller-Advisory](https://github.com/quasarframework/quasar/security/advisories/GHSA-3r53-75j5-3g7j) |
| Weitere Pakete | Unter anderem Laravel, Guzzle, CommonMark, Livewire, Symfony-Komponenten sowie Build-Werkzeuge. Der kritische npm-Befund im Backend betrifft `shell-quote` und ist kein Nachweis einer kritischen Lücke in einer Laravel-API-Route. |
Die Composer-Ausgabe enthält 45 Meldungseinträge: 15 high, 24 medium, 5 low und einen ohne Schweregrad. Einträge können denselben Sachverhalt aus unterschiedlichen Quellen betreffen; die Zahl bezeichnet keine 45 bestätigten unabhängigen Angriffe auf die Anwendung.
**Maßnahme:** Sicherheitsupdates in einem separaten, überprüfbaren Änderungsschritt einspielen, Lockfiles aktualisieren und danach Builds, API-Tests und Browser-Abläufe prüfen. Laufzeitpakete und nur beim Entwickeln verwendete Werkzeuge getrennt priorisieren. Dev-Server nur für den vorgesehenen Entwicklungskreis erreichbar machen. Die genannten Fixversionen schließen jeweils das zitierte Advisory, nicht zwangsläufig alle inzwischen gemeldeten Lücken.
### A02 – Bewusste Testzugänge und spätere Trennung vom Echtbetrieb
**Priorität:** P3 als Vorbereitung im aktuellen Teststand; P1 vor einer Nutzung derselben Umgebung mit echten privaten Konten/Inhalten. **Nachweis:** Code, bestehender Seeder-Test und Klarstellung des Projektverantwortlichen.
**Fundstellen:** [DatabaseSeeder.php](../backend/database/seeders/DatabaseSeeder.php), Z. 16–34; [LoginPage.vue](../frontend/src/pages/LoginPage.vue), Z. 62–76; [Deployment-Protokoll](../frontend/dev/db-api-connect/migration-log.md), Abschnitt 05.06.2026.
Die sechs festen API-Zugänge sind ausdrücklich zum Testen gewollt. Sie ermöglichen wiederholbare Persistenz- und Benutzerwechseltests und können für den aktuellen Zweck bestehen bleiben. Ein öffentliches Demokonto mit bewusst gemeinsamen Beispieldaten benötigt ebenfalls kein Versprechen individueller Vertraulichkeit.
Der technische Übergangspunkt bleibt relevant: `updateOrCreate` setzt beim erneuten Seeden auch Passwörter bestehender Konten zurück. Eine Beschränkung auf lokale oder ausdrücklich freigegebene Demo-Umgebungen fehlt. Das Protokoll dokumentiert den Seeder-Aufruf auch beim damaligen Live-Deployment; daraus folgt nicht, dass dort echte Kundenkonten existieren.
**Auswirkung im Testbetrieb:** Veränderungen gemeinsam verwendeter Testdaten und Passwort-Resets können Tests oder Vorführungen beeinflussen. Der ursprüngliche Hinweis auf den Zugriff auf private Kundeninhalte beschreibt ein späteres Nutzungsszenario, keinen festgestellten aktuellen Datenbestand.
**Maßnahme:** Die sechs Testkonten für die Persistenztests beibehalten; Seed-/Reset-Verhalten dokumentieren. Für eine öffentlich interaktive Demo entscheiden, ob Besucher gemeinsame Beispieldaten bearbeiten oder nur den lokalen Demo-Modus nutzen. Vor Einführung echter Konten Demo-Seeding ausdrücklich von deren Einrichtung und Daten trennen; bestehende individuelle Passwörter dann nicht durch einen allgemeinen Seeder überschreiben.
### A03 – API-Login ohne Rate-Limit
**Priorität:** P2 im begrenzten Testbetrieb; P1 vor öffentlichem API-Zugriff. **Nachweis:** Quellcode und registrierte Routen.
**Fundstellen:** [api.php](../backend/routes/api.php), Z. 11; [AuthController.php](../backend/app/Http/Controllers/Api/AuthController.php), Z. 16–30; [bootstrap/app.php](../backend/bootstrap/app.php), Middleware-Konfiguration.
`POST /api/login` prüft Zugangsdaten und erzeugt Tokens, ohne Fehlversuche zu begrenzen. Ein möglicher Schutz der separaten Web-Anmeldung greift für diesen eigenen API-Controller nicht. Auch für Uploads und Sync ist kein anwendungseigenes Throttling sichtbar. Ein vorgelagerter Infrastruktur-Schutz ist unbekannt.
**Auswirkung:** Wiederholte Passwortversuche sowie Last durch Passwort-Hash-Prüfungen und Token-Erzeugung. Bei bewusst bekannten Demo-Zugängen steht zunächst die Verfügbarkeit der öffentlich erreichbaren Demo im Vordergrund; für individuelle Konten kommt der Schutz vor Passwortversuchen hinzu.
**Maßnahme:** Login-Limiter pro normalisierter Identität und IP, ergänzend passende Limits für API und Uploads. Mit Tests für HTTP 429 und die Rücksetzung nach erfolgreichen/zeitlich abgelaufenen Versuchen absichern.
### A04 – Verspätete Antworten überschreiten den Benutzerkontext
**Priorität:** P1. **Nachweis:** Event-Store isoliert reproduziert; verwandtes Muster in Settings und Uploads durch Codeprüfung.
**Fundstellen:** [events.js](../frontend/src/stores/events.js), Z. 170–233, 308–325, 607–658 und 712–720; [settings.js](../frontend/src/stores/settings.js), Z. 225–252.
`loadRemoteEvents()` bindet die Anfrage nicht dauerhaft an den Benutzer, für den sie gestartet wurde. `normalizeRemoteEvent()` liest nach dem Warten die dann aktuelle `currentUserId`. Antworten schreiben ohne Prüfung einer Sitzungs-/Anfragegeneration in den gemeinsamen Store und Cache.
**Reproduktion:** Anfrage von A offen lassen, auf B wechseln, zuerst Bs Antwort und danach As Antwort auflösen. Ergebnis: aktiver Benutzer B, angezeigter Event `private A`, lokal mit `userId: B` versehen. Das ist ein Fehler im Frontend; die API musste dafür keinen fremden Zugriff erlauben.
`private A` war lediglich der künstliche Titel im isolierten Reproduktionstest, kein ausgelesener privater Kundeninhalt. Im aktuellen Testmodell verfälscht der Fehler die Zuordnung zwischen den sechs Testkonten und damit die Persistenztests; diese Bedeutung bleibt auch ohne echte Kundenkonten hoch.
Bei Settings kann die verspätete Antwort ebenfalls den aktuellen Zustand überschreiben. Bei Medien wird `editingEventId` nach asynchronen Schritten erneut gelesen; ein Panelwechsel während eines Uploads kann die Antwort dem falschen Event zuordnen.
**Maßnahme:** Benutzer-ID, Sitzungsgeneration und Event-ID beim Start festhalten; nach jedem relevanten `await` prüfen; alte Requests abbrechen oder deren Ergebnisse verwerfen. Dasselbe Prinzip für Cache-Schreibvorgänge und Settings anwenden. Regressionsfälle mit verzögerten Antworten aufnehmen.
### A05 – Ort und Bildtitel werden für Remote-Events nicht gespeichert
**Priorität:** P1. **Nachweis:** durchgängiger Abgleich von UI, Payload, Request, Model, Migration und Resource.
**Fundstellen:** [events.js](../frontend/src/stores/events.js), Z. 179–188, 197–207 und 527–537; [StoreEventRequest.php](../backend/app/Http/Requests/StoreEventRequest.php); [Event.php](../backend/app/Models/Event.php); [EventResource.php](../backend/app/Http/Resources/EventResource.php); [Event-Migration](../backend/database/migrations/2026_02_24_161710_create_events_table.php).
Das Panel bearbeitet `location` und `keyImageTitle`. `eventPayload()` überträgt beide nicht; im Backend fehlen Validierung, Spalten, Mapping und Antwortfelder. Beim Zusammenführen der Serverantwort setzt die Normalisierung sie wieder auf leere Werte. Das betrifft somit bereits bestätigte Speicherantworten, nicht erst einen späteren Gerätewechsel.
**Maßnahme:** Beide Felder über die gesamte Datenkette ergänzen und mit einem Create-/Update-/Reload-Roundtrip testen. Migration und API-Vertrag dokumentieren. Globale Farbverläufe liegen dagegen bereits in Settings; gleichnamige Event-Altlasten nicht ungeprüft zu neuen Pflichtfeldern machen.
### A06 – Automatisches Speichern verliert Änderungen beim Eventwechsel
**Priorität:** P1. **Nachweis:** isoliert mit dem tatsächlichen Store-Code reproduziert.
**Fundstellen:** [events.js](../frontend/src/stores/events.js), Z. 500–519 und 551–564; zusätzlich Z. 266–285 für überlappende PUT-Anfragen.
Die Formularwerte werden mit 300 ms Verzögerung gespeichert. `openPanel()` ersetzt die ausgewählte Event-ID und Formularwerte, ohne zuvor den ausstehenden Speicherauftrag des bisherigen Events abzuschließen. Der Timer arbeitet anschließend mit den neuen Werten.
**Reproduktion:** Event A öffnen, Titel ändern und innerhalb der Verzögerung Event B öffnen. Im kontrollierten Lauf wurde nur `/events/e2` mit Bs unverändertem Titel gespeichert; As Titel blieb `original A`.
Zusätzlich sind mehrere PUT-Anfragen desselben Events nicht serialisiert oder versioniert. Eine ältere Antwort kann den lokalen Zustand zurücksetzen; eine ältere, später verarbeitete Anfrage kann auch neuere Serverwerte überschreiben. Settings verwenden ebenfalls unkoordinierte vollständige PUT-Snapshots.
**Maßnahme:** Vor dem Eventwechsel den alten Entwurf mit seiner festen ID sichern. Pro Event eine geordnete Schreibfolge oder Revisionen verwenden und veraltete Antworten ignorieren. Für konkurrierende Geräte ein Konfliktverfahren vorsehen. Debounce allein garantiert keine Schreibreihenfolge.
### A07 – Speicherfehler bleiben unsichtbar und können Daten verlieren lassen
**Priorität:** P1. **Nachweis:** Codeprüfung der Fehler- und Wiederladepfade.
**Fundstellen:** [events.js](../frontend/src/stores/events.js), Z. 225–232, 252–257, 286–305, 338–369 und 594–604; [settings.js](../frontend/src/stores/settings.js), Z. 194–210; [EventPanel.vue](../frontend/src/components/EventPanel.vue), Z. 454–458 und 484–488; [quasar.config.js](../frontend/quasar.config.js), `framework.plugins`.
Remote-Änderungen werden zunächst lokal dargestellt. Fehler beim Erstellen/Ändern setzen teilweise nur `syncStatus: 'error'`; beim Löschen wird der Eintrag vor der Serverbestätigung entfernt und ein Fehler lediglich geloggt. Es gibt keine aktive Retry-Queue für diese Schreibvorgänge. Beim nächsten erfolgreichen Laden ersetzt der Serverstand den Cache: nie gespeicherte Änderungen verschwinden, fehlgeschlagene Löschungen tauchen wieder auf.
Ein fehlgeschlagenes initiales Remote-Laden ergibt eine leere Eventliste, obwohl ein Cache vorhanden sein kann. Die Oberfläche unterscheidet diesen Fehler nicht zuverlässig von einem leeren Konto. Upload-Fehlermeldungen verwenden `$q.notify?.(...)`, aber Quasar registriert nur `Dark`; die optionale Verkettung verschluckt das fehlende Notify-Plugin.
**Maßnahme:** Sichtbare Zustände für Laden, Speichern, gespeichert und fehlgeschlagen; Entwürfe und fehlgeschlagene Mutationen erhalten; Löschfehler zurückrollen oder als ausstehend anzeigen. Entweder einen vollständigen Offline-/Retry-Vertrag implementieren oder Offline-Schreiben ausdrücklich begrenzen. Notify korrekt registrieren und Validierungsfehler am betroffenen Feld anzeigen.
### A08 – Cursor-Paginierung kann Events mit gleichem Datum überspringen
**Priorität:** P1. **Nachweis:** Controller und Pagination-Implementierung geprüft; kein eigener Datenbank-Reproduktionstest hinzugefügt.
**Fundstelle:** [EventController.php](../backend/app/Http/Controllers/Api/EventController.php), Z. 19–33.
Die Abfrage sortiert ausschließlich nach `date`. Dieses Feld ist nicht eindeutig. Liegt eine Seitengrenze innerhalb mehrerer Events desselben Tages, springt der nächste Cursor zu einem späteren Datum; noch nicht gelieferte Events dieses Tages werden übersprungen. Bereits `limit=1` und zwei Events am selben Tag reichen als Regressionsszenario. Der aktive Client lädt zwar Folgeseiten, kann übersprungene Datensätze aber nicht wiederherstellen.
Laravel verlangt hierfür eine eindeutige Sortierspalte oder eindeutige Spaltenkombination. [Laravel-Dokumentation](https://laravel.com/docs/12.x/pagination#cursor-vs-offset-pagination)
**Maßnahme:** Stabil nach Datum und eindeutiger ID sortieren; über mehrere Seiten mit gleichen Datumswerten testen. `limit`, `since` und Cursor-Eingaben validieren; Filter beim Erzeugen der Folgelinks erhalten. Aktuell begrenzt `min(..., 200)` nur die Obergrenze und ersetzt keine Eingabevalidierung.
### A09 – Sync-Endpunkt umgeht die normalen Event-Validierungen
**Priorität:** P1. **Nachweis:** Codeprüfung; Endpunkt ist für angemeldete Benutzer erreichbar.
**Fundstelle:** [EventController.php](../backend/app/Http/Controllers/Api/EventController.php), Z. 127–193.
Validiert werden Action, UUID und der äußere Payload-Typ. Werte wie Titel, Datum, Emotion, URL und Notiz werden aus dem Payload direkt übernommen. Die Regeln von `StoreEventRequest` und `UpdateEventRequest` greifen hier nicht. Beispielsweise passiert `emotion: 2` die Sync-Validierung, obwohl normales CRUD nur den Bereich −1 bis 1 erlaubt. Fehler werden mit dem unveränderten Exception-Text an den Client zurückgegeben; darunter können SQL- und Schema-Details sein. Ein Update eines nicht existierenden Events wird außerdem als `ok` quittiert.
**Maßnahme:** Gemeinsame Feldregeln für CRUD und Sync, aktionsabhängige Payload-Validierung und klar definierte Ergebnisse für fehlende Events. Technische Exception-Details serverseitig protokollieren, nach außen stabile Fehlercodes liefern. Eigentümerfilter beibehalten: Eine direkte Änderung fremder Events wurde in diesem Controller nicht festgestellt.
## 5. Weitere Fehler und Stabilitätsrisiken
### A10 – Bildcache ist nicht nach Benutzer getrennt
**Priorität:** P2; relevant auf gemeinsam verwendeten Browserprofilen. **Nachweis:** Codeprüfung.
**Fundstellen:** [useImageCache.js](../frontend/src/composables/useImageCache.js), Z. 9, 86–95 und 166–177; [db/index.js](../frontend/src/db/index.js), `imageCache`; [auth.js](../frontend/src/stores/auth.js), Z. 144–153.
Memory- und IndexedDB-Cache verwenden die Bild-URL als Schlüssel. Cachetreffer benötigen weder aktuellen Token noch passenden Benutzer. Beim Abmelden werden die Bildcaches nicht geleert. Settings-Hintergrund-URLs enthalten keine Benutzer-ID, sondern nur einen optionalen Zeitparameter. Event-Medien haben unterschiedliche IDs, bleiben aber unter ihrer alten URL lokal abrufbar. Das ist eine lokale Datenschutzlücke, kein nachgewiesener fehlender Ownership-Check des Servers.
**Maßnahme:** API-Origin, Benutzer-ID, Medien-ID/URL und Bildvariante in Cache-Schlüssel aufnehmen; Caches beim Benutzerwechsel kontrolliert verwerfen. Blob-URLs freigeben und ein Größenlimit vorsehen. `clearEventImages()` existiert, wird vom aktiven Anwendungscode aber nicht aufgerufen; vollständig geladene Bilder sind zudem nicht durchgängig im IndexedDB-Index für diese Bereinigung enthalten.
### A11 – Abgelaufener Token und Frontend-Anmeldestatus laufen auseinander
**Priorität:** P2. **Nachweis:** Codeprüfung.
**Fundstellen:** [apiClient.js](../frontend/src/services/apiClient.js), Z. 105–107; [auth.js](../frontend/src/stores/auth.js), Z. 67–90 und 144–153; [router/index.js](../frontend/src/router/index.js), Router-Guard.
Bei HTTP 401 wird der Token entfernt, das Benutzerprofil in localStorage und der Auth-Store bleiben jedoch angemeldet. Der Router leitet einen Besuch von `/login` dann erneut zur App um. Die API ist weiterhin geschützt, aber die UI kann in einem nicht mehr speicherfähigen Zustand hängen bleiben.
Logout wartet außerdem nicht auf die Token-Widerruf-Anfrage und ignoriert Fehler. Die bestehende Logout-Prüfung mit `Passport::actingAs` bestätigt HTTP 204, nicht den vollständigen Lebenszyklus eines zuvor real ausgestellten Tokens.
**Maßnahme:** Zentrale sitzungsgebundene 401-Behandlung für Token, Profil, Requests und Navigation; keine neue Sitzung wegen einer verspäteten 401-Antwort der alten Sitzung löschen. Widerruf mit festgehaltenem Token ausführen und Token-Laufzeiten festlegen. Test: Login → echter Tokenzugriff → Logout → derselbe Token wird abgewiesen.
### A12 – Älterer Synchronisationsservice ist unvollständig und nicht benutzergebunden
**Priorität:** P2; vor einer Aktivierung als Offline-Lösung zwingend bearbeiten. **Nachweis:** Codeprüfung einschließlich tatsächlicher Aufrufer.
**Fundstellen:** [syncService.js](../frontend/src/services/syncService.js), Z. 10–12, 31–42, 77–79 und 99–161; [events.js](../frontend/src/stores/events.js), Z. 349–369.
Konkrete Probleme:
- Die gesamte Queue wird ohne `userId`-Filter mit dem aktuell gespeicherten Token gesendet. Bei vorhandenen Altaufträgen können so Daten im falschen Konto angelegt werden.
- `lastSyncCursor` ist global; neue eingehende Events werden ohne `userId` gespeichert.
- Es wird nur eine Seite abgeholt, anschließend aber bereits die lokale aktuelle Uhrzeit als Sync-Marke gespeichert. Weitere Seiten und Änderungen während des Abrufs können verloren gehen.
- Löschungen besitzen keine Tombstones und werden deshalb beim Delta-Abruf nicht übertragen.
- Die Rekursion für den nächsten 100er-Batch endet sofort am noch gesetzten `isSyncing`-Flag.
- Erfolgreiches Remote-Laden kehrt in `init()` vor `startAutoSync()` zurück. Unabhängig davon startet der beim Import registrierte `online`-Listener die Queue-Verarbeitung bei einem Reconnect.
Neue Demo-Daten erzeugen aktuell keine Queue-Einträge. Deshalb wäre die Aussage „alle Demo-Daten werden hochgeladen“ falsch. Das Risiko betrifft insbesondere Altbestände und eine spätere Nutzung dieses Services.
**Maßnahme:** Einen verbindlichen Persistenzweg festlegen. Bis zur Fertigstellung alte Queue-Verarbeitung kontrolliert deaktivieren oder strikt pro Benutzer betreiben. Danach vollständige Pagination, serverseitige Sync-Marken, Löschmarker, Retry und Konfliktbehandlung ergänzen.
### A13 – Event-Löschung hinterlässt Bilddateien
**Priorität:** P2. **Nachweis:** Löschpfade, Modelle und Fremdschlüssel geprüft.
**Fundstellen:** [EventController.php](../backend/app/Http/Controllers/Api/EventController.php), Z. 113–121 und 188–190; [Event-Medien-Migration](../backend/database/migrations/2026_06_03_131801_create_event_media_table.php); [Event.php](../backend/app/Models/Event.php).
Das Löschen eines Events entfernt über `cascadeOnDelete` dessen Medien-Datensätze, aber keine Dateien. Die Datei-Löschlogik liegt ausschließlich im Mediencontroller und wird beim Löschen des gesamten Events nicht aufgerufen. Die Models enthalten keinen entsprechenden Cleanup. Dasselbe Grundproblem besteht beim kaskadierenden Löschen eines Benutzers; Settings-Hintergründe benötigen ebenfalls einen eigenen Löschpfad.
**Auswirkung:** Private Dateien verbleiben ohne Datensatz auf dem Datenträger, der Speicherverbrauch wächst. Daraus folgt keine automatische öffentliche Abrufbarkeit, aber die erwartete Datenlöschung ist unvollständig.
**Maßnahme:** Gemeinsamen Löschservice bzw. zuverlässigen Cleanup-Job für alle Löschwege entwickeln. Dateipfade vor der Datenbanklöschung erfassen; ein reiner Model-Observer reicht für Query-Builder-Massenlöschungen und Datenbank-Kaskaden nicht. Löschung aller drei Varianten testen.
### A14 – Medienersatz kann bei Teilfehlern alte und neue Bilder verlieren
**Priorität:** P2. **Nachweis:** Codeprüfung; Speicherfehler wurden nicht künstlich ausgelöst.
**Fundstellen:** [EventMediaController.php](../backend/app/Http/Controllers/Api/EventMediaController.php), Z. 39–75; [SettingsMediaController.php](../backend/app/Http/Controllers/Api/SettingsMediaController.php), `store()`; [filesystems.php](../backend/config/filesystems.php), lokaler Datenträger.
Datei-Schreibergebnisse werden nicht geprüft, während der Datenträger `throw: false` verwendet. Beim Key-Image-Ersatz werden bisherige Bilder gelöscht, bevor der neue Datensatz vollständig gespeichert ist. Ein voller Datenträger oder ein Datenbankfehler kann dadurch zu einer positiven Antwort mit fehlenden Dateien, verlorenen bisherigen Bildern oder verwaisten neuen Dateien führen. Parallele Key-Image-Uploads sind ebenfalls nicht als eine Operation geschützt.
**Maßnahme:** Schreibfehler explizit behandeln, neue Dateien zunächst vollständig bereitstellen, Metadaten konsistent umschalten und alte Dateien erst danach entfernen. Fehler mit kompensierender Bereinigung behandeln. Eine Datenbanktransaktion allein macht Dateisystemoperationen nicht atomar.
### A15 – Bildgröße wird erst nach vollständigem Dekodieren reduziert
**Priorität:** P2. **Nachweis:** Request-Regeln und GD-Verarbeitung geprüft.
**Fundstellen:** [StoreEventMediaRequest.php](../backend/app/Http/Requests/StoreEventMediaRequest.php); [StoreSettingsMediaRequest.php](../backend/app/Http/Requests/StoreSettingsMediaRequest.php); [EventMediaImageProcessor.php](../backend/app/Services/EventMediaImageProcessor.php), `process()`; [SettingsMediaController.php](../backend/app/Http/Controllers/Api/SettingsMediaController.php), `processBackground()`.
Das Limit von 10 MB begrenzt die komprimierte Datei, nicht ihre Pixelzahl. `imagecreatefromstring()` dekodiert das Bild vollständig, bevor es verkleinert wird. Große stark komprimierte Bilder können deshalb viel Speicher und CPU verbrauchen. Pro Benutzer/Event existieren außerdem keine erkennbaren Medienquoten.
**Maßnahme:** Maximale Dimensionen und Pixelzahl vor dem teuren Verarbeitungsschritt prüfen, Upload-Rate und Speichermengen begrenzen. Bei wachsendem Volumen Bildverarbeitung in begrenzte Worker auslagern. Fehler kontrolliert zurückmelden; die vorhandene Prüfung von Dateitypen beibehalten.
### A16 – Settings werden strukturell zu wenig validiert
**Priorität:** P2. **Nachweis:** Request und unmittelbare Verbraucher geprüft.
**Fundstellen:** [UpdateSettingsRequest.php](../backend/app/Http/Requests/UpdateSettingsRequest.php), Z. 24–39; [settings.js](../frontend/src/stores/settings.js), Z. 127 und 245–249.
`floatingLines` und `presets` werden nur als Arrays validiert. Für Elemente, Schlüssel, Anzahlen, Farben und Zahlenbereiche fehlen überwiegend Regeln. Beispielsweise kann `presets: [null]` die äußere Array-Regel erfüllen, während das Frontend anschließend `preset.id` liest. Unbekannte Schlüssel im Gesamt-Settings-Array können ebenfalls in die gespeicherten Daten gelangen. Das eröffnet in erster Linie Fehlzustände des eigenen Kontos und Ressourcenverbrauch, keine bestätigte Fremddatenänderung.
**Maßnahme:** Versioniertes Settings-Schema mit erlaubten Schlüsseln, Elementvalidierung, Grenzwerten und Größenlimit einführen. Geladene Cache- und API-Daten zusätzlich defensiv normalisieren. [Laravel-Hinweis zu Array-Validierung](https://laravel.com/docs/12.x/validation#validating-arrays)
### A17 – Laravel-Profilseite liefert HTTP 500
**Priorität:** P2. **Nachweis:** vorhandener Feature-Test zweimal fehlgeschlagen.
**Fundstellen:** [ProfileUpdateTest.php](../backend/tests/Feature/Settings/ProfileUpdateTest.php), Z. 6–10; [web.php](../backend/routes/web.php), Z. 17; [Profil-Komponente](../backend/resources/views/livewire/settings/profile.blade.php); [vorhandenes Layout](../backend/resources/views/components/layouts/app.blade.php).
`profile page is displayed` erwartet HTTP 200 und erhält HTTP 500. Die konkrete Exception lautet `No hint path defined for [layouts]`. Der installierte Livewire-Stand erwartet standardmäßig `layouts::app`; das vorhandene App-Layout liegt unter `components/layouts/app.blade.php`, eine passende Anwendungskonfiguration ist nicht vorhanden.
**Maßnahme:** Layout-Zuordnung für den verwendeten Livewire-/Volt-Stand explizit und konsistent konfigurieren. Die Profilseite und die benachbarten Settings-Seiten als vollständige HTTP-Seiten prüfen. Erfolgreiche komponenteninterne Methoden-Tests beweisen nicht, dass die Seite gerendert werden kann.
### A18 – Kalenderdaten werden in westlichen Zeitzonen verschoben
**Priorität:** P2. **Nachweis:** Datumsausdruck unter `America/Los_Angeles` ausgeführt.
**Fundstellen:** [TimelineView.vue](../frontend/src/components/TimelineView.vue), Z. 129–155; [EventPanel.vue](../frontend/src/components/EventPanel.vue), Z. 336–339.
`new Date('YYYY-MM-DD')` wird anschließend mit lokalen Monats-/Jahres-/Datumsfunktionen dargestellt. Dadurch wird `2026-01-01` in der überprüften Zeitzone zu `31.12.2025`. Neben dem Eventdatum können somit auch Monats- und Jahreszuordnungen der Timeline falsch sein.
**Maßnahme:** Reine Kalenderdaten als solche behandeln: Datumsteile ohne UTC-Zeitpunkt parsen oder UTC-Auswertung und Darstellung konsequent vereinheitlichen. Mindestens UTC, Europa/Berlin und Amerika/Los_Angeles testen.
### A19 – Zulässige URL-Länge passt nicht zur MySQL-Spalte
**Priorität:** P2. **Nachweis:** Schema-/Request-Abgleich; nicht gegen MySQL ausgeführt.
**Fundstellen:** [StoreEventRequest.php](../backend/app/Http/Requests/StoreEventRequest.php) und [UpdateEventRequest.php](../backend/app/Http/Requests/UpdateEventRequest.php), Regel `image`; [Event-Migration](../backend/database/migrations/2026_02_24_161710_create_events_table.php), Spalte `image`.
Die API erlaubt 500 Zeichen, die Migration erzeugt eine normale String-Spalte mit standardmäßig 255 Zeichen. Unter MySQL kann eine formal gültige Anfrage mit längerer URL deshalb beim Speichern scheitern. SQLite-Tests decken diese Längenbeschränkung nicht gleichwertig ab. Die eigenen kurzen Medienpfade erreichen das Limit normalerweise nicht, externe URLs können es erreichen.
**Maßnahme:** Vertrag und Spaltenlänge angleichen oder externe Bild-URLs bewusst einschränken; Grenzwertprüfung zusätzlich unter MySQL ausführen.
## 6. Optimierungen und Wartbarkeit
### O01 – Datenladen und Bildspeicher begrenzen
Der aktive Event-Store lädt sämtliche Seiten einschließlich Medienmetadaten, bevor der endgültige Zustand gesetzt wird. Die DOM-Virtualisierung reduziert den Renderaufwand, aber weder Gesamttransfer noch Cache-Schreibmenge. Für große Timelines bieten sich seitenweises Anzeigen und bei Bedarf geladene Galerie-Metadaten an. Vorher A08 beheben, damit Datensätze nicht bereits an Seitengrenzen fehlen.
Medien werden serverseitig über `Storage::get()` vollständig in den PHP-Speicher geladen. Bei höherem Volumen Streaming bzw. autorisierte Webserver-Auslieferung und kontrolliertes HTTP-Caching prüfen. Der clientseitige Bildcache braucht ein Budget und eine Eviction-Strategie; gleiche parallele Bildanfragen lassen sich außerdem zusammenfassen.
### O02 – Bundle und öffentliche Assets verkleinern
Der gemessene `LifeWaveLayout`-Chunk hat **714,12 kB minifiziert / 195,67 kB gzip**. `frontend/public/images` belegt rund **59 MiB**, das erzeugte SPA-Verzeichnis rund **106 MiB**. Die Verzeichnisgröße bedeutet nicht, dass beim Start alles übertragen wird; Quasar kopiert aber auch ungenutzte öffentliche Assets in das Build-Ergebnis.
Große Beispielbilder verkleinern, ungenutzte Assets aus dem Produktionspfad entfernen und selten geöffnete Panels bei Bedarf laden. Three.js-/Shader-Anteil gezielt mit einem Bundle-Report prüfen. Die existierende Timeline-Virtualisierung, Begrenzung auf 16 Shaderpunkte, adaptive Pixelauflösung und Freigabe der WebGL-Ressourcen sind positive Ansätze und sollten erhalten bleiben.
### O03 – Settings-Schreiblast reduzieren
Änderungen von Scrollposition oder Darstellung lösen nach kurzer Verzögerung PUTs des gesamten Settings-Dokuments einschließlich Presets aus. Bei vielen Presets entsteht unnötiger Transfer und konkurrierende Snapshots erhöhen das Überschreibungsrisiko.
Persistente Benutzerpräferenzen von flüchtigem Viewport-Zustand trennen, nur geänderte Bereiche übertragen oder die Schreibfrequenz begrenzen. Beim lokalen Demo-Modus kann ein großes Base64-Hintergrundbild zusätzlich die localStorage-Quota erreichen; `localStorage.setItem()` in `persist()` behandelt diesen Fehler nicht. Größere Bilder gehören in den Blob-Speicher.
### O04 – Reproduzierbare Entwicklung und automatische Prüfgates
`frontend/package.json` führt vor jedem Dev-Start `npm install` aus; Compose startet ebenfalls `npm install` vor `npm run dev`. Damit wird beim Containerstart zweimal installiert. Installation und Start trennen, für kontrollierte Builds den vorhandenen Lockfile mit `npm ci` verwenden.
Im Repository wurde keine GitHub-Actions-Prüfpipeline unter `.github/workflows` gefunden. Lint, beide Builds, Backend-Tests und Paketprüfungen sollten nachvollziehbare CI-Gates erhalten. Frontend-Tests für Auth-/Store-Abläufe fehlen besonders; `npm test` ist nur ein Platzhalter. MySQL-Prüfungen ergänzen die vorhandenen schnellen SQLite-Tests.
Die generierten Buildwarnungen zu veralteten Browserslist-Daten und npm-Konfigurationsschlüsseln sind Wartungsthemen. Sie verursachten in dieser Prüfung keinen Buildabbruch.
### O05 – Prototypen und Statusdokumentation eindeutig zuordnen
`src`, `_src`, `legacy` und die Visualisierungsexperimente sollten klar als aktiv, archiviert oder experimentell markiert sein. Änderungen am falschen Baum bleiben sonst wirkungslos. Das Root-README enthält weiterhin Platzhalter; Setup, externe Infrastruktur, Demo-/Remote-Verhalten und Versionsstand sollten aus dem aktuellen Code beschrieben werden.
Größere Stores und das Event-Panel bündeln UI, Entwurf, API und Cache. Nach Absicherung der kritischen Abläufe lohnt sich eine Aufteilung in klar abgegrenzte Verantwortlichkeiten. Ein großer Umbau vor Regressionstests würde die bereits vorhandenen Ablaufprobleme schwerer überprüfbar machen.
## 7. Was bereits gut gelöst ist
- Geschützte API-Routen verwenden `auth:api`; Event-Abfragen werden über die Benutzerrelation eingeschränkt.
- Direkte Medienauslieferung prüft den Besitzer; Settings-Hintergrundpfade werden aus dem authentifizierten Benutzer abgeleitet.
- Fremdzugriffe auf Events, Settings und Medien sind teilweise ausdrücklich durch Feature-Tests abgedeckt.
- Normales Event-CRUD verwendet Form Requests und explizites Feldmapping; dort wird kein beliebiges Request-Objekt massenhaft übernommen.
- Private Medien liegen auf dem privaten Datenträger; Dateipfade werden serverseitig erzeugt, Bildtypen eingeschränkt und Bilder neu kodiert.
- Medien werden beim Event-Laden eager geladen; die offensichtliche N+1-Abfrage pro Event wird damit vermieden.
- Stabile Client-UUIDs, Indizes für Benutzer/Datum und Benutzer/Änderungszeit sind eine passende Grundlage für weitere Synchronisationsarbeit.
- CORS enthält konkrete erlaubte Origins. Fehlendes Login-Throttling wird dadurch allerdings nicht ersetzt.
- Im aktiven Frontend wurde bei der gezielten Suche keine Verwendung von `v-html`, `innerHTML` oder `eval()` gefunden. Das ist keine vollständige XSS-Freigabe, aber ein positiver Ausgangspunkt.
## 8. Empfohlene Reihenfolge
### 8.1 Jetzt: bestehende Testversion zu einer verlässlichen Demo entwickeln
1. **Demo-Kernabläufe reparieren:** A04–A08. Kontenwechsel, vollständige Feldspeicherung, zuverlässiges Autosave, sichtbare Fehler und vollständiges Wiederladen haben Vorrang.
2. **Vorführung mit reproduzierbaren Daten vorbereiten:** Die sechs API-Konten für Persistenztests und ausgewählte Beispielgeschichten verwenden. Den lokalen Demo-Modus separat testen. Festlegen, wie ein definierter Präsentationsstand wiederhergestellt wird, ohne laufende Tests unbeabsichtigt zurückzusetzen.
3. **Betroffene Nebenabläufe stabilisieren:** A09–A19 nach tatsächlicher Demo-Nutzung abarbeiten. Besonders relevant sind Anmeldung nach Tokenablauf, Uploads, Medienersatz und Löschung. A17 blockiert eine Vorführung der Laravel-Profilseite; wenn nur die Quasar-Oberfläche gezeigt wird, ist dieser Fehler kein unmittelbarer Hindernisgrund für genau diese Präsentation.
4. **Gezielt absichern:** Tests für die nachgewiesenen Store-Fehler ergänzen und die gezeigten Abläufe auf den vorgesehenen Browsern/Mobilgeräten durchspielen. Eine vollständige Offline-Synchronisation ist für eine bewusst online genutzte Werbedemo nicht erforderlich; Fehler und Offline-Grenzen müssen trotzdem verständlich bleiben.
### 8.2 Vor öffentlicher, interaktiver Nutzung
Zugangsmodell festlegen: betreute Präsentation, lokal ausprobierbare Demo oder gemeinsame serverseitige Testkonten. Werden API-Schreibzugriffe oder Uploads öffentlich angeboten, A01/A03 sowie die Validierungs- und Ressourcenbegrenzungen aus A09/A15/A16 vor dieser Freigabe bearbeiten. Für gemeinsame Konten sind Veränderungen durch andere Besucher erwartbares Verhalten; eine Kennzeichnung als gemeinsame Beispieldaten und ein kontrollierter Reset helfen der Vorführbarkeit.
Falls API oder Entwicklungsdienste bereits öffentlich erreichbar sind, ist dieser Teil entsprechend vorgezogen. Der Status der Erreichbarkeit ist im Audit offen.
### 8.3 Vor echten individuellen Konten
Demo-Seeding gemäß A02 trennen, Benutzer-/Cache-/Token-Isolation vollständig absichern und zuverlässige Speicherung sowie Medienlöschung verbindlich machen. Weitergehende Kontenverwaltung und Betriebsanforderungen an dieser Phase ausrichten. Die mögliche spätere Crowdfunding-Kampagne ändert an der technischen Reihenfolge für die aktuelle Demo zunächst nichts.
### Abnahmekriterien für die Demo-Stabilisierung
- Testkonto A laden, währenddessen zu B wechseln: keine Daten, Bilder oder Settings von A im Kontext B; auch bei verspäteter 401-Antwort bleibt B korrekt angemeldet.
- Event A ändern und unmittelbar B öffnen: As Änderung bleibt nach Reload erhalten.
- Zwei Schreibanfragen absichtlich verzögern/umordnen: der jüngere Stand gewinnt kontrolliert.
- Ort und Bildtitel nach Create, Update, Reload und erneutem Login unverändert vorhanden.
- Mehrere Events mit identischem Datum über mehrere Cursorseiten vollständig und ohne Dubletten geladen.
- Netzwerk-/422-/500-Fehler beim Schreiben sichtbar; keine still verworfenen Entwürfe oder bestätigten Löschungen ohne Servererfolg.
- Lokalen Demo-Modus separat prüfen: Anlegen und Reload funktionieren browserlokal; neue Demo-Mutationen gehen nicht an die API.
- Definierte Beispieldaten lassen sich für die Vorführung nachvollziehbar herstellen; persistierte Testdaten bleiben zwischen normalen Sitzungen erhalten.
- Frontend-Build/Lint und die Tests der kritischen Abläufe erfolgreich; betroffene Vorführpfade im Browser geprüft.
### Ergänzende Kriterien für öffentliche API-Nutzung und späteren Echtbetrieb
- Ungültige Sync-Payloads werden abgewiesen; technische Exception-Texte erscheinen nicht in API-Antworten.
- Event-/Benutzerlöschung beseitigt zugehörige Dateien; fehlgeschlagener Bildersatz erhält das bisherige Bild.
- API-Login wird bei wiederholten Fehlversuchen begrenzt; reales Token ist nach erfolgreichem Logout unbrauchbar.
- Öffentlich nutzbare Uploads haben angemessene Mengen-/Größenlimits; relevante Sicherheitsupdates sind geprüft.
- Vor echten Konten: kein allgemeiner Seeder setzt deren individuelle Passwörter zurück oder vermischt ihre Daten mit Präsentationsdaten.
- Gesamte Backend-Suite grün; MySQL-Integration und automatische Prüfungen ergänzen die Demo-Tests.
## 9. Paketprüfung: kompakte Bestandsaufnahme
Die folgenden Zahlen dokumentieren den Registry-Stand vom 17.09.2026 und dienen der Nachverfolgung. npm zählt betroffene Pakete einschließlich transitiv betroffener Pakete; Composer zählt hier Advisory-Einträge. Die Zahlen dürfen daher nicht direkt addiert oder als Anzahl ausnutzbarer Anwendungslücken interpretiert werden.
| Composer-Paket | Meldungseinträge |
| --- | ---: |
| guzzlehttp/guzzle | 9 |
| guzzlehttp/psr7 | 4 |
| laravel/framework | 3 |
| laravel/passport | 1 |
| league/commonmark | 12 |
| livewire/livewire | 1 |
| phpseclib/phpseclib | 4 |
| symfony/http-foundation | 1 |
| symfony/http-kernel | 1 |
| symfony/mailer | 1 |
| symfony/mime | 2 |
| symfony/polyfill-intl-idn | 1 |
| symfony/routing | 2 |
| symfony/yaml | 3 |
Frontend-npm meldet: `@humanfs/node`, `@quasar/app-vite`, `baseline-browser-mapping`, `body-parser`, `brace-expansion`, `browserslist`, `esbuild`, `flatted`, `immutable`, `js-yaml`, `lodash`, `nanoid`, `node-forge`, `path-to-regexp`, `picomatch`, `postcss`, `postcss-selector-parser`, `qs`, `quasar`, `serialize-javascript`, `vite`.
Backend-npm meldet: `axios`, `browserslist`, `follow-redirects`, `form-data`, `lodash`, `nanoid`, `picomatch`, `postcss`, `rollup`, `shell-quote`, `vite`.
Reproduzierbare Basisbefehle: `npm audit --json` jeweils in `frontend/` und `backend/`, sowie `composer audit --locked --format=json` in `backend/`. Nach Updates die dann aktuellen Einzelmeldungen und ihre tatsächlichen Ausführungspfade erneut bewerten.

View file

@ -0,0 +1,341 @@
# Frontend: Vorschläge für UI, Nutzererlebnis und Werbedemo
**Stand:** 17.09.2026, aktueller Arbeitsstand einschließlich der bereits vorgenommenen Änderungen.
**Ziel:** Eine verständliche, überzeugende und flüssig bedienbare Demo, die Produktinteresse weckt.
**Umfang:** Darstellung, Bedienung, Texte, wahrgenommene Performance und sinnvolle Produkterweiterungen. Keine erneute Sicherheitsprüfung und keine Implementierung.
## 1. Einschätzung und Grundlage
Die LifeWave-Darstellung ist das stärkste visuelle Merkmal des Produkts: Eine persönliche Geschichte wird als Folge von Momenten und emotionalen Höhen und Tiefen sichtbar. Diese Eigenständigkeit sollte erhalten bleiben. Den größten Nutzen sehe ich jetzt in einem besseren Einstieg, verständlicher Orientierung und gut lesbaren Inhalten.
Für die Werbedemo sollte ein neuer Besucher ohne Erklärung durch den Entwickler verstehen: **Was sehe ich? Was kann ich hier tun? Warum möchte ich das später selbst nutzen?** Mehr Gestaltungsregler allein beantworten diese Fragen nicht.
Berücksichtigt sind das aktuelle Testmodell mit sechs serverseitig gespeicherten Testkonten und dem lokalen Demo-Zugang sowie das Ziel, über Social Media Interesse aufzubauen und eventuell später Crowdfunding zu starten. Die Testkonten bleiben für die Entwicklung sinnvoll.
### Was betrachtet wurde
- Aktive Loginseite, LifeWave-Layout, Timeline, Ereignispunkte, Event-Panel, Gestaltungsbereich und Benutzermenü.
- Browseransichten in Chromium bei Desktopgröße 1440 × 900, schmaler Ansicht und mobiler Emulation mit 390 × 844 CSS-Pixeln.
- Einstieg in eine frische lokale Demo, Anlegen/Bearbeiten eines Moments, sichtbarer Speicherstatus, Timeline mit eigens erzeugten fiktiven lokalen Beispielen sowie Menü- und Gestaltungspanels.
- Ergänzend die aktuellen UI-Texte und vorgesehenen Interaktionen in den aktiven Frontend-Dateien. Allgemeine App-Einstellungen und Galerieabläufe wurden ergänzend anhand der Komponenten betrachtet; die Browserdurchsicht war kein vollständiger E2E-Test.
Die Browserdaten lagen in isolierten Testprofilen. Es wurden keine API-Testkonten verändert und keine Anwendungscode-Änderungen vorgenommen. Einige automatisierte Navigationsversuche scheiterten an Overlay-/Übergangszuständen; daraus wird hier kein eigenständiger bestätigter Produktfehler abgeleitet.
**Grenzen:** Keine Messung auf echter Smartphone-Hardware, keine verlässliche FPS-/Ladezeitmessung und kein vollständiger Barrierefreiheitstest. Performancewerte weiter unten sind vorgeschlagene Ziele, keine gemessenen Ergebnisse. Die mobile Emulation ersetzt insbesondere keinen Test mit echter Bildschirmtastatur oder Safari.
### Bereits vorhanden und beizubehalten
- Sichtbare Zustände „Wird gespeichert …“, „Gespeichert“ und „Nicht gespeichert“ im Event-Panel; „Gespeichert“ wurde beim lokalen Bearbeiten im Browser gesehen.
- Benachrichtigungen für Lade-/Speicherfehler im aktuellen Layout.
- Tastaturaktivierung und Beschriftung der Ereignispunkte.
- Timeline-Virtualisierung, adaptive Darstellungsqualität und Pausieren der WebGL-Darstellung bei ausgeblendetem Tab.
- Verschiebbare Panels, Bildgalerie und Speichern eigener Gestaltungsvorlagen.
Diese Punkte werden nachfolgend gezielt weitergedacht. Die Liste unterstellt nicht, dass sie noch vollständig fehlen.
## 2. Prioritäten auf einen Blick
**A – vor einer selbstständig nutzbaren Werbedemo empfohlen:** Hürden, die das Verstehen oder die Kernbedienung unmittelbar beeinträchtigen.
**B – sinnvoller nächster Ausbau:** verbessert Komfort, Qualität oder Verlässlichkeit.
**C – später validieren:** Erweiterungsideen, deren Nutzen zunächst mit Interessenten geprüft werden sollte.
„Aufwand“ ist eine grobe relative Einschätzung des Umfangs einschließlich Gestaltung und Abstimmung, keine Zeitschätzung. Abhängigkeiten von Backend, Inhalten oder einem externen Dienst sind ausdrücklich vermerkt.
| ID | Vorschlag | Priorität | Nutzen | Aufwand |
| --- | --- | --- | --- | --- |
| V01 | Direkter Demo-Einstieg mit klarem Produktversprechen | A | Weniger Einstiegshürden | Klein–mittel |
| V02 | Kuratierte Beispielgeschichte zum Erkunden | A | Produktnutzen sofort erlebbar | Mittel |
| V03 | Hilfreicher Leerzustand und kurze Einführung | A | Erster Schritt wird verständlich | Klein |
| V04 | Einheitliche Sprache und Markenbezeichnung | A | Geschlossener, glaubwürdiger Eindruck | Klein; echte Zweisprachigkeit größer |
| V05 | Menüs auf wirksame Aktionen reduzieren | A | Keine Sackgassen | Klein |
| V06 | Kontrast und visuelle Hierarchie verbessern | A | Aktionen sind leichter erkennbar | Klein–mittel |
| V07 | Lesbare Ereignistitel und bessere Punkte ohne Bild | A | Inhalte erhalten mehr Gewicht | Mittel |
| V08 | Zeit- und Emotionsdarstellung verständlich erklären | A | Weniger Fehlinterpretationen | Klein |
| V09 | Direktnavigation und ergänzende Listenansicht | B | Momente schneller wiederfinden | Mittel–groß |
| V10 | Ereignisansicht für Lesen und Bearbeiten gestalten | B | Ruhigeres Erlebnis, bessere Desktopnutzung | Mittel |
| V11 | Panels eindeutig schließen und per Tastatur bedienen | A | Sichere Orientierung | Klein–mittel |
| V12 | Touchbedienung, Vergrößerung und mobile Ränder verbessern | A | Einfacher auf kleinen Bildschirmen | Mittel |
| V13 | Anlegen und Löschen nachvollziehbar machen | A | Weniger versehentliche Änderungen | Mittel |
| V14 | Speicher- und Verbindungsstatus weiterführen | B | Nutzer wissen, wo ihre Änderungen stehen | Mittel |
| V15 | Bildauswahl und Galerie mit Rückmeldungen ergänzen | B | Uploads und Bildausschnitte verständlich | Mittel |
| V16 | Gestaltungsvorlagen vor Detailreglern anbieten | B | Schnelle schöne Ergebnisse | Mittel |
| V17 | Ruhigen Modus und sparsame Darstellung anbieten | A | Zugänglichkeit und mobile Nutzbarkeit | Mittel |
| V18 | Ersten sichtbaren Inhalt beim Laden priorisieren | B | Schnellere wahrgenommene Reaktion | Mittel |
| V19 | Performance nach konkreten Nutzeraktionen beurteilen | B | Optimierungen werden überprüfbar | Klein–mittel |
| V20 | Passenden nächsten Schritt für Interessenten anbieten | A vor Bewerbung | Aus Interesse wird ein Kontakt | Klein–mittel, ggf. Dienst nötig |
| V21 | Kurzes Feedback direkt aus der Demo ermöglichen | B | Produktentscheidungen besser begründen | Klein–mittel, Empfänger nötig |
| V22 | Präsentationsmodus und ausgewählte Ausgabeformate | B/C | Bessere Vorführungen und Social-Media-Inhalte | Mittel–groß |
| V23 | Persönliche Kapitel und Kategorien erproben | C | Größere Geschichten strukturieren | Groß, Datenmodell betroffen |
| V24 | Demo verständlich und kontrolliert zurücksetzen | B | Wiederholbare Tests und Präsentationen | Mittel, bei Remote-Daten Backend nötig |
## 3. Einstieg und Verständlichkeit
### V01 – Direkter Demo-Einstieg mit klarem Produktversprechen
**Beobachtung:** Neue Besucher landen auf „Login“, lesen „Welcome back“ und sehen Kontenauswahl, Passwort sowie „Remember me“. Das entspricht einem Testzugang, erklärt aber den Nutzen für Erstbesucher kaum. Selbst beim lokalen Zugang bleibt das deaktivierte Passwortfeld sichtbar.
**Vorschlag:** Eine kurze Einstiegsfläche mit einem Satz wie „Deine wichtigen Momente als lebendige Lebenslinie“ und zwei klaren Wegen: **„Beispiel ansehen“** und **„Selbst ausprobieren“**. Die sechs Testkonten bleiben über einen separaten Bereich „Testzugänge“ erreichbar. Für den lokalen Einstieg genügt eine Aktion ohne Passwortmaske.
**Wirkung:** Das Produkt wird vor der Kontenauswahl verständlich. Der Hinweis „Deine Eingaben bleiben in diesem Browser“ erläutert den lokalen Modus in Alltagssprache.
**Prüfkriterium:** Eine neue Person kann erklären, was sie erwartet, und ohne Hilfe eine passende Demo-Ansicht öffnen.
### V02 – Eine kurze Beispielgeschichte zum Erkunden
**Beobachtung:** Der lokale Demo-Zugang startet absichtlich leer. Damit ist die zentrale Visualisierung zunächst nicht erlebbar.
**Vorschlag:** Eine ausdrücklich auswählbare fiktive Geschichte mit etwa sechs bis zehn abwechslungsreichen Momenten: ein Anfang, ein Erfolg, ein schwieriger Moment, ein Wendepunkt und ein Ausblick. Wenige passende Bilder und kurze, zusammenhängende Texte reichen. Keine große zufällige Datensammlung für die erste Vorführung.
Die leere eigene Demo bleibt erhalten. Beispielgeschichte und eigene Eingaben werden klar unterschieden; Beispiele werden nicht ungefragt in den eigenen lokalen Bestand eingefügt. Für betreute Präsentationen kann eines der bestehenden API-Testkonten einen definierten Präsentationsstand enthalten.
**Prüfkriterium:** Nach dem Öffnen versteht man anhand der Geschichte, welchen Mehrwert die Welle gegenüber einer bloßen Ereignisliste bietet.
### V03 – Leerzustand mit einer sichtbaren ersten Handlung
**Beobachtung:** Im frischen lokalen Browserzustand sind eine dunkle Fläche, Logo und Symbolschaltflächen sichtbar. Ein erklärender Text oder eine Anleitung zum ersten Moment fehlt.
**Vorschlag:** In der Mitte eine zurückhaltende Einladung: „Deine Lebenslinie beginnt mit einem Moment.“ Darunter **„Ersten Moment hinzufügen“** und optional „Beispiel ansehen“. Zoomregler können bis zum ersten Inhalt zurücktreten. Beim ersten befüllten Aufruf genügen zwei kurze Hinweise: „Seitlich bewegen“ und „Moment antippen“.
**Prüfkriterium:** Der Leerzustand wirkt beabsichtigt; niemand muss das Plus-Symbol erraten oder die Ansicht für einen Ladefehler halten. Die Einführung bleibt überspringbar und später erneut erreichbar.
### V04 – Sprache und Markenauftritt vereinheitlichen
**Beobachtung:** „That’s Me“ und „ThatsMe“ stehen nebeneinander. Texte mischen unter anderem „Login“, „Welcome back“, „Remember me“, „Key Image“, „Emotional Level“, „Speed“ und deutsche Bezeichnungen. Die Sprachauswahl ist vorhanden, viele sichtbare Texte sind weiterhin fest vorgegeben.
**Vorschlag:** Für die erste Werbedemo eine durchgehend deutsche Fassung festlegen. Beispielsweise „Titelbild“, „Wie hast du dich gefühlt?“, „Geschwindigkeit“ und „Vorlage“. Eine einheitliche Schreibweise der Marke wählen. Eine Englisch-Auswahl erst als fertige Option präsentieren, wenn der gezeigte Ablauf tatsächlich durchgehend übersetzt ist.
„Angemeldet bleiben“ nur anzeigen, wenn die Auswahl eine nachvollziehbare Wirkung hat. Für eine lokale Demo ohne Anmeldung wird sie nicht benötigt.
**Prüfkriterium:** Texte, Datumsdarstellung und Schaltflächen wirken wie ein zusammengehöriges Produkt; sichtbare Einstellungen halten ihr Versprechen.
### V05 – Menüs auf funktionierende und relevante Ziele konzentrieren
**Beobachtung:** Das Menü bietet bereits „Plan upgraden“, „Personalisierung“ und mehrere Hilfeziele. Im aktuellen Layout werden als Navigationsziele nur „Einstellungen“ und „Abmelden“ umgesetzt. In den allgemeinen Einstellungen existieren außerdem „Kommt bald“-Bereiche.
**Vorschlag:** Für die Demo ein kompaktes Menü: **„So funktioniert’s“**, **„Darstellung“**, **„Feedback“**, **„Über das Projekt“** und der passende Konto-/Demo-Abschluss. Nur tatsächlich verfügbare Ziele anzeigen. Geplante Funktionen können gebündelt in einem kurzen Ausblick stehen. „Plan upgraden“ weglassen, solange kein buchbarer Plan existiert.
**Prüfkriterium:** Jeder sichtbare Menüpunkt führt zu einem verständlichen Ergebnis. Die Demo vermittelt einen klaren Funktionsumfang.
## 4. Darstellung und Orientierung in der Timeline
### V06 – Bedienelemente vor dem Hintergrund klar erkennbar machen
**Beobachtung:** In der betrachteten hellen Oberflächeneinstellung bleibt die Hauptfläche dunkel; mehrere Symbole erscheinen darauf dunkelgrau. Große helle Ereignispunkte ziehen deutlich mehr Aufmerksamkeit auf sich als die primären Aktionen.
**Vorschlag:** Die Kontraste der Timeline-Bedienelemente auf den tatsächlichen Hintergrund abstimmen. Die zentrale Aktion „Moment hinzufügen“ darf stärker hervortreten, Gestaltungsoptionen bleiben sekundär. Transparenz und Leuchteffekte gezielt einsetzen, damit Text und Schaltflächen auch vor einem Foto ruhig lesbar bleiben.
Das Logo sollte eine erwartbare Funktion haben, etwa zum Anfang führen. Der aktuell darüber erreichbare Wechsel der Helligkeitsdarstellung gehört sichtbar in die Darstellungseinstellungen.
**Prüfkriterium:** Auf dunklem, hellem und bildbasiertem Hintergrund bleiben Aktionen und Beschriftungen klar erkennbar. Kontrast zusätzlich messen, nicht allein nach Screenshot beurteilen.
### V07 – Ereignisinhalte größer, Punkte ohne Bild aussagekräftiger
**Beobachtung:** Die Standardbeschriftung verwendet sehr kleine Titel und Datumszeilen; längere Titel werden früh gekürzt. Im Desktopbeispiel dominieren große weiße Kreise, während nur Textanfänge wie „Ein Neuanfang mi…“ lesbar bleiben.
**Vorschlag:** Als Gestaltungsstart Titel etwa im Bereich 14–16 CSS-Pixel und Datum etwa 12–14 CSS-Pixel erproben. Beim fokussierten Moment zwei Titelzeilen oder eine kleine vollständige Infokarte erlauben. Bilderlose Momente erhalten eine dezente farbige Fläche, ein Symbol oder einen Anfangsbuchstaben statt eines großen rein weißen Kreises.
Größe und Leuchten des Punkts sollten die Geschichte unterstützen. Bei enger Darstellung lieber weniger ausführlich beschriftete Momente gleichzeitig zeigen als alle Texte zu verkleinern.
**Prüfkriterium:** Reale Titel mit 30–50 Zeichen lassen sich auf Mobilgeräten erkennen; der ausgewählte Moment ist ohne Öffnen des Editors eindeutig identifizierbar. Die vorgeschlagenen Schriftgrößen sind Gestaltungswerte, keine behaupteten Normgrenzen.
### V08 – Bedeutung von Höhe, Farbe und Zeitabstand erklären
**Beobachtung:** Die Höhe eines Punkts folgt dem Gefühlswert. Farben können zusätzlich individuell überschrieben werden. Ereignisse stehen gleichmäßig auseinander, obwohl ihre Datumsabstände unterschiedlich sein können.
**Vorschlag:** Eine kurze, ausblendbare Erklärung: „Oben: positiv erlebt · Mitte: neutral · Unten: schwierig erlebt“. Die Farbe ergänzt die Information; eine Textbezeichnung sollte ebenfalls erreichbar sein. Bei freier Punktfarbe deren gestalterische Rolle klar lassen.
Den aktuellen Modus als **Ereignisfolge** erläutern: Die Abstände entsprechen nicht der verstrichenen Zeit. Eine echte Zeitskala wäre eine spätere alternative Ansicht. Für die erste Demo reicht eine verständliche Erklärung der vorhandenen Darstellung.
**Prüfkriterium:** Testpersonen verwechseln einen langen horizontalen Abstand nicht mit einer langen Lebensphase. Die Welle wird als persönliche Einordnung verstanden.
### V09 – Momente direkt wiederfinden
**Beobachtung:** Scrollen, Zoom und Jahresnavigation sind vorhanden. Bei umfangreicheren Geschichten fehlt ein direkter Einstieg zu einem gesuchten Titel oder Datum.
**Vorschlag:** Zunächst **„Zu einem Jahr springen“** und **„Zum neuesten Moment“** ergänzen. Danach eine einfache Suche nach Titel/Ort und eine kompakte chronologische Liste. Ein Treffer führt zum passenden Punkt in der Welle. Eine Gesamtübersicht mit markiertem sichtbarem Ausschnitt erst dann ergänzen, wenn lange Timelines tatsächlich häufig genutzt werden.
**Prüfkriterium:** Ein bekanntes Ereignis wird ohne langes seitliches Suchen gefunden. Eine Listenansicht ergänzt die charakteristische Welle und bietet einen zweiten verständlichen Zugang.
## 5. Erfassen, Lesen und Rückmeldungen
### V10 – Lesen und Bearbeiten als unterschiedliche Situationen gestalten
**Beobachtung:** Das Antippen eines Moments öffnet unmittelbar ein großes Bearbeitungspanel. Auf Desktopbreite erstrecken sich Eingabefelder und Gefühlsregler weit über den Bildschirm; ein Großteil der Timeline wird überdeckt.
**Vorschlag:** Für eine Beispielgeschichte zunächst eine lesbare Detailkarte mit Bild, Datum, Ort und Text zeigen; „Bearbeiten“ ist eine eigene Aktion. Für eigene neu angelegte Momente direkt im Editor bleiben. Auf großen Bildschirmen eine begrenzte Seitenansicht erproben, damit der ausgewählte Moment in der Timeline sichtbar bleibt. Mobil passt das bestehende Panel von unten gut.
Im Editor Titel und Datum früh platzieren. Das optionale Titelbild sollte den Einstieg nicht stärker dominieren als der eigentliche Moment.
**Prüfkriterium:** Besucher können eine Geschichte lesen, ohne versehentlich Inhalte zu verändern. Lange Desktopfelder werden vermieden; auf Mobilgeräten bleibt die Eingabe übersichtlich.
### V11 – Panels mit eindeutigem Abschluss und verlässlicher Tastaturführung
**Beobachtung:** Event- und Gestaltungspanel setzen stark auf Ziehen und den Hintergrund zum Schließen. Eine deutlich beschriftete Abschlussaktion fehlt dort. Im Desktopdurchlauf schloss Escape das Event-Panel nicht.
**Vorschlag:** Eine gut erkennbare Aktion **„Fertig“** bzw. **„Schließen“** im Panelkopf ergänzen. „Fertig“ schließt bei Autosave die Bearbeitung und ersetzt nicht den Speicherstatus. Escape, sinnvolle Fokusreihenfolge und Rückkehr zum zuvor geöffneten Moment vorsehen. Bei Fehlermeldungen bleibt eindeutig, ob Änderungen noch offen sind.
**Prüfkriterium:** Ein Moment lässt sich vollständig ohne Ziehgeste und mit Tastatur öffnen, bearbeiten und verlassen. Tastaturfokus wandert bei geöffnetem Dialog nicht unbemerkt hinter das Panel.
### V12 – Touchziele, Vergrößerung und mobile Bildschirmränder
**Beobachtung:** Einige Schaltflächen sind ausschließlich Symbole; Zoom ist ein sehr schmaler Regler. Die Ereignispunkte haben bereits Tastaturfunktionen, andere Aktionen bieten diese Orientierung noch nicht überall. Die aktuelle Seitendefinition schränkt Browservergrößerung ein.
**Vorschlag:** Aussagekräftige Namen für Symbolaktionen und sichtbare Fokushervorhebung. Für häufige mobile Aktionen ungefähr 44 × 44 CSS-Pixel große Trefferflächen als Komfortziel erproben; die sichtbaren Icons dürfen kleiner bleiben. Seitenvergrößerung unabhängig vom Timeline-Zoom ermöglichen. Untere Aktionen und Panelabschlüsse oberhalb von Geräte- und Tastaturrändern halten.
WCAG 2.2 nennt für das Mindestkriterium 24 × 24 CSS-Pixel bzw. definierte Ausnahmen wie ausreichenden Abstand. Das größere Komfortziel hier ist keine pauschale Behauptung dieser Mindestanforderung. [W3C: Target Size](https://www.w3.org/WAI/WCAG22/Understanding/target-size-minimum.html)
**Prüfkriterium:** Plus, Zurück, Zoom und Schließen sind einhändig gut bedienbar. Mit vergrößertem Text und geöffneter Bildschirmtastatur bleiben Eingabe und Abschluss erreichbar. Auf echten Geräten prüfen.
### V13 – Anlegen und Löschen mit klaren Erwartungen
**Beobachtung:** Schon das Öffnen über Plus erzeugt einen neuen Moment mit Standardtitel. Das Entfernen eines gesamten Events ist direkt erreichbar; für das Titelbild gibt es dagegen bereits eine ausdrückliche Bestätigung.
**Vorschlag:** Ein neuer, noch unberührter Moment wird als Entwurf verständlich behandelt. Wer sofort schließt, sollte nicht überraschend eine Sammlung leerer „Neues Event“-Einträge erzeugen. Für bestehende Momente eine knappe Löschbestätigung oder ein tatsächlich funktionierendes „Rückgängig“ anbieten. Die Bild- und Eventlöschung sprachlich konsistent gestalten.
**Prüfkriterium:** Ein versehentliches Plus ist folgenlos verlassbar. Nutzer erkennen vor dem Löschen, ob nur ein Bild oder der ganze Moment betroffen ist. Rückgängig nur versprechen, wenn es auch vollständig wiederherstellt; das kann Backend-Unterstützung erfordern.
### V14 – Vorhandenen Speicherstatus um Kontext und Handlungen ergänzen
**Beobachtung:** Die neuen Speicheranzeigen und Fehlermeldungen sind eine gute Grundlage. Ein allgemeines „Gespeichert“ erklärt noch nicht den Unterschied zwischen lokaler Demo und API-Testkonto; kurz eingeblendete Meldungen können übersehen werden.
**Vorschlag:** Im lokalen Modus **„In diesem Browser gespeichert“**, bei erfolgreicher API-Speicherung **„Im Testkonto gespeichert“**. Bei nicht bestätigtem Speichern eine bleibende Rückmeldung mit passender Handlung, etwa „Erneut versuchen“. Beim Anzeigen eines älteren lokalen Stands einen dezenten dauerhaften Hinweis statt nur einer kurzlebigen Benachrichtigung verwenden.
**Prüfkriterium:** Nutzer können jederzeit erkennen, ob die letzte Änderung bestätigt ist und wo sie liegt. Wiederholen, Offline-Verhalten und tatsächliche Persistenz müssen dazu passen; hier wird keine bereits vollständige Offline-Lösung unterstellt.
### V15 – Bilder mit Vorschau, Fortschritt und klarer Galerie ergänzen
**Beobachtung:** Titelbild, weitere Bilder und Galerie sind bereits vorhanden. Der Auswahlablauf bietet in der betrachteten UI keine durchgängige Fortschritts-/Wartedarstellung pro Bild.
**Vorschlag:** Nach der Auswahl sofort eine Vorschaukachel mit „Wird vorbereitet“ bzw. „Wird hochgeladen“ zeigen. Bei mehreren Bildern beispielsweise „2 von 5 fertig“. Fehler bleiben am betroffenen Bild erkennbar. Für das runde Timeline-Bild einen anpassbaren Bildausschnitt bzw. Fokuspunkt anbieten.
Die Galerie erhält eine klare Positionsangabe „3 von 8“, Bildtitel und bei Bedarf Bildbeschreibung. „Weitere Bilder“ ist präziser als „Weitere Medien“, solange dort nur Bilder unterstützt werden.
**Prüfkriterium:** Es ist erkennbar, ob die Auswahl angenommen wurde, ob ein Bild noch verarbeitet wird und welches fehlgeschlagen ist. Die Person oder das Motiv bleibt im runden Ausschnitt sichtbar. Fokuspunkt und zusätzliche Bildtexte können eine Erweiterung der gespeicherten Metadaten erfordern.
## 6. Gestaltung und wahrgenommene Performance
### V16 – Gute Vorlagen zuerst, Feinabstimmung danach
**Beobachtung:** Der Gestaltungsbereich enthält viele Regler, darunter Geschwindigkeit, Linienanzahl, Fächerbreite und Kurve. Eigene Vorlagen lassen sich bereits speichern, stehen aber weit unten im Ablauf.
**Vorschlag:** Oben drei bis fünf fertige, visuell unterscheidbare Vorlagen als kleine Vorschaukarten, etwa „Ruhig“, „Leuchtend“, „Minimal“ und „Fotohintergrund“. Danach wenige häufige Optionen; die übrigen Regler unter „Feinabstimmung“. Klar zwischen **Darstellung der Lebenslinie** und **allgemeinen Einstellungen** unterscheiden. FPS-Anzeige für den Testbereich aufbewahren.
**Prüfkriterium:** Ein neuer Besucher findet mit einer Auswahl eine schöne Darstellung. Eigene gespeicherte Vorlagen bleiben verfügbar; Experimentieren lässt sich einfach zurücksetzen.
### V17 – Ruhiger Modus, sparsame Darstellung und sichtbarer Ersatz
**Beobachtung:** Animation und Leuchten sind ein zentrales Gestaltungsmittel. Adaptive Qualität und Tab-Pause existieren bereits. Ein klarer Nutzerweg für reduzierte Bewegung oder eine Darstellung ohne verfügbare WebGL-Grafik ist in der betrachteten Oberfläche nicht erkennbar. „Color Lines“ beschreibt zunächst die Liniengestaltung und sollte nicht automatisch als energiesparender Modus verstanden werden.
**Vorschlag:** **„Bewegung reduzieren“** und bei Bedarf **„Sparsame Darstellung“** anbieten. Systemwünsche zu reduzierter Bewegung berücksichtigen. Während längerer Texteingaben darf der Hintergrund ruhiger werden. Bei nicht verfügbarer Grafik bleibt eine einfache Lebenslinie oder Liste mit denselben Inhalten bedienbar.
Nicht notwendige bewegte Effekte abschalten zu können, hilft Menschen mit Bewegungsempfindlichkeit. [W3C: Animation from Interactions](https://www.w3.org/WAI/WCAG22/Understanding/animation-from-interactions.html)
**Prüfkriterium:** Alle Kernaktionen funktionieren auch ohne bewegten Hintergrund. Ob ein Modus tatsächlich Energie spart, auf realen Geräten messen; ein anderes Farbschema allein ist kein Nachweis.
### V18 – Beim Laden zuerst Orientierung und Inhalte zeigen
**Vorschlag:** Logo, erklärender Text und grundlegende Bedienung früh sichtbar machen. Während Daten geladen werden, „Deine Momente werden geladen“ anzeigen; einen tatsächlich leeren Bestand davon unterscheiden. Bildflächen mit stabilen Platzhaltern reservieren, damit Beschriftungen nicht springen. Bei umfangreichen Geschichten zuerst einen benutzbaren Ausschnitt zeigen.
Ein dezenter Übergang reicht. Lange Startanimationen oder ein künstlich verzögerter Einstieg würden der schnellen Demo-Erfahrung entgegenstehen.
**Prüfkriterium:** Auch bei langsamer Verbindung bleibt erkennbar, was gerade passiert. Die erste Ansicht ist benutzbar, bevor alle Galeriebilder bereitstehen. Dies ist eine Gestaltungsempfehlung; eine aktuelle Produktionsladezeit wurde nicht gemessen.
### V19 – Performance anhand von Nutzeraktionen messen
**Vorschlag:** Für Optimierungen dieselben kurzen Abläufe vergleichen: Demo öffnen, Timeline bewegen, Moment antippen, Text eingeben, Bild auswählen und Panel schließen. Kleine Beispieldaten und eine große Testgeschichte getrennt betrachten. Ein durchschnittliches Smartphone und eine langsame Mobilverbindung sind für die Werbedemo aussagekräftiger als nur ein schneller Entwicklungsrechner.
Als technische Begleitziele bieten sich die üblichen guten Core-Web-Vitals-Bereiche an: LCP bis 2,5 Sekunden, INP bis 200 Millisekunden und CLS bis 0,1, jeweils anhand des 75. Perzentils realer Besuche beurteilt. Für neue Demos zunächst reproduzierbare Labortests nutzen und später reale Nutzung ergänzen. [Web Vitals](https://web.dev/articles/vitals)
Für die Welle zusätzlich flüssige Bewegung und eine sofortige sichtbare Reaktion prüfen. Ein Versuchsziel kann 60 Bilder/s im normalen Modus und stabile 30 Bilder/s in einem bewusst sparsamen Modus sein; das ist ein Projektziel, keine vorhandene Messung oder Zusage.
**Prüfkriterium:** Jede Performanceänderung verbessert einen dokumentierten Nutzerablauf. FPS allein reicht nicht: Text darf nicht verzögert erscheinen und Panels sollen sich unmittelbar öffnen.
## 7. Sinnvolle Erweiterungen für Werbung und Produktlernen
### V20 – Nach der Demo einen passenden nächsten Schritt anbieten
**Beobachtung:** Das angestrebte Ziel ist Interesse am Produkt. In der aktiven App ist dafür noch kein klarer Abschluss der Demo erkennbar; „Plan upgraden“ passt nicht zum aktuellen Projektstand.
**Vorschlag:** Nach dem Erkunden der Geschichte eine zurückhaltende Einladung **„Über den Start informiert werden“** oder **„Interesse am Projekt?“** anbieten. Die Demo bleibt vorher frei erlebbar. Dazu ein kurzer Projektstand: Was lässt sich bereits ausprobieren, was ist geplant?
Ein späterer Crowdfunding-Link kommt hinzu, sobald eine konkrete Kampagne existiert. Für eine Interessentenliste muss ein tatsächlicher Anmeldeweg samt Bestätigung vorhanden sein; das ist eine zusätzliche Funktion bzw. Dienstanbindung, kein reiner Textwechsel.
**Prüfkriterium:** Interessierte wissen, wie sie dranbleiben können. Der nächste Schritt verspricht nur etwas, das tatsächlich angeboten wird.
### V21 – Kurzes, konkretes Feedback ermöglichen
**Vorschlag:** Zwei Fragen reichen zunächst: **„Was würdest du hier festhalten?“** und **„Was war unklar?“** Optional eine kleine Auswahl gewünschter Funktionen. Den Einstieg im Menü und am Ende der Beispielgeschichte anbieten.
Fehlermeldung und allgemeines Produktfeedback sollten unterscheidbar sein. Einen funktionierenden Empfänger bzw. Speicherweg und eine Eingangsbestätigung vorsehen. Keine vorgetäuschte „Gesendet“-Meldung ohne tatsächliche Verarbeitung.
**Prüfkriterium:** Rückmeldungen liefern konkrete Anwendungsfälle und Bedienhürden, anstatt lediglich zu fragen, ob die Animation gefällt.
### V22 – Präsentationsmodus und gezielte Ausgabeformate
**Vorschlag für die nächste Stufe:** Ein Präsentationsmodus blendet Bearbeitungs- und Testelemente aus, zeigt vollständige Titel und erlaubt „Nächster Moment“. Damit lassen sich die vorhandenen Testgeschichten in Gesprächen und Bildschirmaufnahmen erklären. Eine automatisch ablaufende Tour wäre optional, jederzeit pausierbar und später zu prüfen.
**Spätere Ausgabeidee:** Ausgewählte Momente als gestaltete Bildkarte oder kurzer Story-Ausschnitt ausgeben, mit Vorschau in Hochformat und Querformat. Der Nutzer bestimmt, welche Titel, Bilder und Texte enthalten sind. Für die ersten Social-Media-Beiträge reichen kuratierte Bildschirmaufnahmen; ein eigener Videoexport wäre deutlich aufwendiger.
**Prüfkriterium:** Eine kurze Vorführung vermittelt eine zusammenhängende Geschichte. Exportiert oder geteilt werden nur die bewusst ausgewählten Inhalte; das Ergebnis ist auf einem Smartphone lesbar.
### V23 – Persönliche Kapitel und Kategorien zunächst als Idee testen
**Vorschlag:** Größere Geschichten könnten später eigene Kapitel erhalten, etwa „Ausbildung“, „Reisen“ oder „Neuanfang“, dazu wenige frei wählbare Kategorien. In der Welle sollen diese Orientierung geben und sich bei Bedarf filtern lassen.
Vor einer Umsetzung mit Interessenten prüfen, ob sie eher eine Lebensgeschichte, ein Reisetagebuch oder einzelne Erinnerungen festhalten möchten. Davon hängt ab, ob Kapitel, Tags oder mehrere Lebenslinien überhaupt hilfreich sind. Die Funktion würde Datenmodell und Persistenz erweitern.
**Prüfkriterium:** Die Struktur hilft beim Wiederfinden eigener Inhalte. Sie vergrößert nicht unnötig das Formular für jeden neuen Moment.
### V24 – Demo kontrolliert neu beginnen können
**Vorschlag:** Für selbstständiges Ausprobieren klar zwischen **„Eigene lokale Demo leeren“** und **„Beispielgeschichte neu starten“** unterscheiden. Vor dem Löschen eigener lokaler Eingaben eine verständliche Bestätigung zeigen. Für betreute API-Präsentationen einen getrennten, bewusst ausgelösten Reset des definierten Beispielstands vorsehen.
Der lokale Demo-Zugang bleibt leer startbar. Ein öffentlicher Reset darf nicht unbemerkt die gemeinsamen Daten anderer Tester zurücksetzen. Ein Reset der API-Testkonten ist eine zusätzliche Backend-/Betriebsfunktion und gehört nicht als beliebige globale Aktion in jede Besucheransicht.
**Prüfkriterium:** Eine Vorführung lässt sich wiederholen, ohne ungeklärte Altzustände; gleichzeitig bleiben eigene und gemeinsam verwendete Testdaten nachvollziehbar getrennt.
## 8. Empfohlene erste Umsetzungspakete
### Paket 1 – Einstieg und glaubwürdiger Funktionsumfang
V01–V05: direkter Einstieg, eine gute Beispielgeschichte, hilfreicher Leerzustand, konsistente Texte und ein auf verfügbare Funktionen begrenztes Menü. Das dürfte für neue Interessenten den größten sofortigen Unterschied machen.
### Paket 2 – Gut lesbare und sichere Kernbedienung
V06–V08 sowie V11–V13: sichtbare Aktionen, lesbare Momente, verständliche Welle, eindeutige Panelabschlüsse, gute Touchbedienung und nachvollziehbares Anlegen/Löschen. V17 parallel als ruhige Alternative berücksichtigen.
### Paket 3 – Vorführung und Interesse verbinden
V20 plus ein einfacher Präsentationsmodus aus V22; V21 für Feedback. Erst danach weitere Navigation, Gestaltungsvorlagen und Komfortfunktionen nach beobachteten Nutzerproblemen ergänzen. Eigene Videoerzeugung, umfangreiche Kategorien und vollständige Mehrsprachigkeit sind keine Voraussetzung für die erste aussagekräftige Demo.
## 9. Kleiner Nutzertest zur Auswahl der nächsten Schritte
Mit etwa fünf Personen außerhalb der Entwicklung einzeln beobachten; die geringe Zahl liefert qualitative Hinweise, keine repräsentativen Marktwerte. Zu Beginn möglichst wenig erklären.
| Aufgabe | Beobachten |
| --- | --- |
| „Was glaubst du, macht dieses Produkt?“ | Wird das Produktversprechen vor dem Login verstanden? |
| „Schau dir eine Beispielgeschichte an.“ | Wird ein sinnvoller Einstieg gefunden? |
| „Finde einen bestimmten Moment und erkläre die Welle.“ | Sind Navigation, Farbe, Höhe und Zeitabstände verständlich? |
| „Lege einen eigenen Moment an und ändere ihn.“ | Sind Titel, Datum, Gefühl und Speicherstatus klar? |
| „Verlasse die Bearbeitung und finde den Moment wieder.“ | Funktionieren Abschluss und Orientierung ohne Hilfe? |
| „Was würdest du als Nächstes tun?“ | Gibt es einen verständlichen Weg zu Feedback oder Projektupdates? |
Zusätzlich kurze Durchläufe mit Tastatur, größerem Text, reduzierter Bewegung und auf einem echten Smartphone durchführen. Bei Problemen zuerst die betroffene Hauptaktion vereinfachen, bevor weitere Funktionen hinzukommen.
## 10. Bezug zum aktuellen Frontend
Die Links dienen zur Zuordnung der Vorschläge; sie sind keine Implementierungsanleitung.
| Oberfläche | Aktuelle Quelle | Relevante Vorschläge |
| --- | --- | --- |
| Einstieg | [LoginPage.vue](../frontend/src/pages/LoginPage.vue) | V01–V04 |
| Hauptansicht und Menüs | [LifeWaveLayout.vue](../frontend/src/layouts/LifeWaveLayout.vue), [UserMenu.vue](../frontend/src/components/UserMenu.vue) | V03, V05–V06, V14, V20–V22 |
| Timeline und Punkte | [TimelineView.vue](../frontend/src/components/TimelineView.vue), [GlowDot.vue](../frontend/src/components/GlowDot.vue) | V07–V09, V12, V18–V19 |
| Ereignisse und Bilder | [EventPanel.vue](../frontend/src/components/EventPanel.vue) | V10–V15 |
| Darstellung und Einstellungen | [LifeWaveSettings.vue](../frontend/src/components/LifeWaveSettings.vue), [AppSettingsModal.vue](../frontend/src/components/AppSettingsModal.vue) | V04–V05, V16–V17 |
| Animation | [FloatingLines.vue](../frontend/src/components/FloatingLines.vue) | V17–V19 |
| Kleine Bedienelemente und Panels | [AddEventButton.vue](../frontend/src/components/AddEventButton.vue), [ZoomControl.vue](../frontend/src/components/ZoomControl.vue), [ModalCard.vue](../frontend/src/components/ModalCard.vue) | V06, V11–V12 |
| Seitendarstellung | [index.html](../frontend/index.html) | V12 |
Der [technische Audit](./AUDIT-2026-09-17.md) bleibt ein separates Dokument mit seinem jeweiligen Prüfstand. Diese Vorschlagsliste berücksichtigt sichtbare zwischenzeitliche Verbesserungen, bestätigt aber nicht pauschal die Erledigung aller dortigen Befunde.

View file

@ -0,0 +1,356 @@
## Alter 25
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 25 | Januar | Beruf | Ein Kollege fotografiert Jonas stolz vor seinen ausgebreiteten Bauplänen, kurz nachdem er sein erstes eigenständiges Projekt übertragen bekommen hat. | Fremdaufnahme | Positiv |
| 25 | Februar | Alltag | Nach einer hohen Nachzahlung kocht Jonas sonntags große Portionen zum Einfrieren; ein Selfie zeigt ihn mit Kochlöffel vor Töpfen voller Eintopf. | Selfie | Neutral |
| 25 | März | Freundschaft | Jonas und David machen nach ihrer ersten gemeinsamen Laufrunde ein verschwitztes Selfie am Rheinufer. | Selfie | Positiv |
| 25 | April | Freizeit | Mit seiner neuen Systemkamera macht Jonas im Spiegel des Fotoladens ein Selfie – sein erstes Bild mit der neuen Ausrüstung. | Selfie | Positiv |
| 25 | Mai | Familie | Bei der kleinen Feier zu Leas Ausbildungsabschluss macht ein Verwandter ein Foto von Jonas und seiner strahlenden Schwester. | Fremdaufnahme | Positiv |
| 25 | Juni | Beruf | Spätabends macht ein Kollege ein Foto vom fast leeren Büro, in dem nur noch Jonas zwischen Plänen und Pizzakartons sitzt. | Fremdaufnahme | Negativ |
| 25 | Juli | Reisen | Am Lagerfeuer in Slowenien entsteht mit Selbstauslöser ein Gruppenfoto von Jonas und seinen zwei Freunden. | Selfie | Sehr positiv |
| 25 | August | Wohnen | Jonas macht ein Selfie mit Farbe im Gesicht vor der frisch gestrichenen Wohnzimmerwand. | Selfie | Neutral |
| 25 | September | Beruf | Nach dem Jahresgespräch macht ein Kollege beim spontanen Umtrunk ein Foto der Runde. | Fremdaufnahme | Positiv |
| 25 | Oktober | Liebe | Auf der Geburtstagsfeier macht der Gastgeber ein Gruppenfoto, auf dem Jonas und Mara nebeneinanderstehen – ihr erstes gemeinsames Bild überhaupt. | Fremdaufnahme | Positiv |
| 25 | November | Liebe | Bei einem ihrer Treffen macht Mara spontan ein Selfie von beiden vor einem Kölner Café. | Selfie | Positiv |
| 25 | Dezember | Familie | Jonas' Mutter Karin fotografiert die Weihnachtsrunde, auf der Mara erstmals mitten in der Familie zu sehen ist. | Fremdaufnahme | Positiv |
## Alter 26
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 26 | Januar | Liebe | Nach dem Gespräch über die feste Beziehung macht Mara ein Selfie von beiden. | Selfie | Sehr positiv |
| 26 | Februar | Beruf | Ein Kollege fotografiert Jonas, wie er über den neuen technischen Vorschriften für das Sanierungsprojekt brütet. | Fremdaufnahme | Neutral |
| 26 | März | Familie | Bei der Beerdigung seiner Großmutter Erna macht ein Verwandter ein Foto der Trauergemeinde; Jonas steht sichtlich ergriffen neben seinem Vater. | Fremdaufnahme | Sehr negativ |
| 26 | April | Freundschaft | David macht ein Selfie mit seiner neuen Freundin nach dem Lauftreffen; die Runden mit Jonas werden seltener. | Selfie | Neutral |
| 26 | Mai | Liebe | Vor einer Amsterdamer Gracht macht ein Passant ein Foto von Jonas und Mara auf ihrer ersten gemeinsamen Wochenendreise. | Fremdaufnahme | Positiv |
| 26 | Juni | Beruf | Nach der nervenaufreibenden Präsentation macht ein Kollege ein Foto von Jonas mit erleichtertem Grinsen im Besprechungsraum. | Fremdaufnahme | Positiv |
| 26 | Juli | Familie | Sein Vater Thomas fotografiert Jonas beim Abschleifen des restaurierten Schreibtisches im Elternhaus. | Fremdaufnahme | Neutral |
| 26 | August | Freizeit | Nach dem Zieleinlauf seines ersten Halbmarathons macht ein Streckenfotograf ein Bild von Jonas mit erschöpftem, glücklichem Gesicht; Mara und David jubeln im Hintergrund. | Fremdaufnahme | Sehr positiv |
| 26 | September | Liebe | Ein Selfie vom gemeinsamen Abendessen wirkt harmonisch, entstand aber am Abend ihres ersten größeren Streits über Jonas' Überstunden. | Selfie | Negativ |
| 26 | Oktober | Liebe | Nach der Versöhnung machen Jonas und Mara ein Selfie bei ihrem neu eingeführten festen Dienstagsabend. | Selfie | Positiv |
| 26 | November | Beruf | Ein Foto vom Baustellen-Koordinationstreffen zeigt Jonas sichtlich in seinem Element zwischen mehreren Fachplanern. | Fremdaufnahme | Positiv |
| 26 | Dezember | Familie | Karin macht ein Foto von Mara, die zum ersten Mal mit an der Weihnachtstafel der Familie sitzt. | Fremdaufnahme | Positiv |
## Alter 27
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 27 | Januar | Beruf | Ein Foto vom Koordinationsmeeting zeigt Jonas, wie er sichtbar aufblüht, wenn er mehrere Gewerke zusammenbringt statt allein an Plänen zu sitzen. | Fremdaufnahme | Positiv |
| 27 | Februar | Persönliche Entwicklung | Nachdem seine Investition in die Geschäftsidee eines Bekannten gescheitert ist, hilft Jonas beim Ausräumen von dessen halbfertigem Ladenlokal; ein Foto zeigt ihn beim Tragen leerer Regale. | Fremdaufnahme | Negativ |
| 27 | März | Liebe | Mara macht ein Selfie mit dem neuen Wohnungsschlüssel in der Hand vor Jonas' Wohnungstür. | Selfie | Positiv |
| 27 | April | Weiterbildung | Der Kursleiter fotografiert die neue Projektmanagement-Gruppe am ersten Kursabend, Jonas in der zweiten Reihe. | Fremdaufnahme | Positiv |
| 27 | Mai | Freundschaft | David macht ein Selfie mit Jonas und dem neuen Bekannten Cem nach ihrem ersten gemeinsamen Treffen. | Selfie | Positiv |
| 27 | Juni | Familie | Am Krankenbett macht Karin trotz Gipsarm ein Selfie mit Jonas, der die Nacht bei ihr verbracht hat. | Selfie | Negativ |
| 27 | Juli | Reisen | Statt der geplanten Fernreise entsteht nur ein Selfie vom gemeinsamen Grillabend auf dem Balkon. | Selfie | Neutral |
| 27 | August | Beruf | Ein Kollege fotografiert Jonas am improvisierten Vertretungs-Schreibtisch seines erkrankten Projektleiters. | Fremdaufnahme | Positiv |
| 27 | September | Wohnen | Jonas und Mara machen ein Selfie vor einem Wohnungsanzeigen-Brett, nachdem sie beschlossen haben, zusammenzuziehen. | Selfie | Positiv |
| 27 | Oktober | Weiterbildung | Nach der bestandenen Prüfung macht ein Kommilitone ein Foto von Jonas mit dem Prüfungsbogen in der Hand. | Fremdaufnahme | Positiv |
| 27 | November | Freundschaft | Ein Handyfoto, das David wütend vom leeren Beifahrersitz macht, nachdem Jonas den gemeinsamen Trip absagt, markiert den Beginn ihres Streits. | Fremdaufnahme | Negativ |
| 27 | Dezember | Freundschaft | Nach der Versöhnung machen David und Jonas ein Selfie beim gemeinsamen Bier. | Selfie | Positiv |
## Alter 28
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 28 | Januar | Wohnen | Ein Makler fotografiert Jonas und Mara vor einer Wohnung, die sie gerade besichtigt haben. | Fremdaufnahme | Positiv |
| 28 | Februar | Beruf | Kollegen fotografieren Jonas, als er offiziell zum Teilprojektleiter ernannt wird und dem Chef die Hand schüttelt. | Fremdaufnahme | Sehr positiv |
| 28 | März | Wohnen | Mara macht ein Selfie mit dem Zusage-Schreiben für die Drei-Zimmer-Wohnung in der Hand. | Selfie | Sehr positiv |
| 28 | April | Alltag | Um Geld zu sparen, kaufen Jonas und Mara gebrauchte Möbel auf dem Flohmarkt; ein Verkäufer fotografiert die beiden beim Verhandeln über einen alten Schrank. | Fremdaufnahme | Negativ |
| 28 | Mai | Wohnen | Ein Selfie vom ersten gemeinsamen Kartonauspacken zeigt Jonas und Mara umgeben von halb ausgepackten Kisten. | Selfie | Positiv |
| 28 | Juni | Liebe | Ein Selfie vom gemeinsamen Abendessen wirkt entspannt, entstand aber mitten in einer Phase kleinerer Streitigkeiten über Ordnung und Freizeit. | Selfie | Negativ |
| 28 | Juli | Reisen | An der portugiesischen Küste macht ein Strandverkäufer ein Foto von Jonas und Mara, wieder ausgelassen lachend. | Fremdaufnahme | Sehr positiv |
| 28 | August | Weiterbildung | Beim Abschluss seiner Weiterbildung macht der Kursleiter ein Gruppenfoto mit Zertifikaten in der Hand. | Fremdaufnahme | Sehr positiv |
| 28 | September | Beruf | Sein Team macht ein Foto mit Jonas als neuem Teamleiter vor dem Baustellencontainer. | Fremdaufnahme | Positiv |
| 28 | Oktober | Familie | Lea macht ein Selfie mit Jonas und ihrem Partner, als sie ihm stolz von ihrem geplanten Einzug erzählt. | Selfie | Positiv |
| 28 | November | Persönliche Entwicklung | Jonas macht ein Selfie mit der letzten Kreditrückzahlungsbestätigung in der Hand, breit grinsend. | Selfie | Sehr positiv |
| 28 | Dezember | Liebe | Ein Foto von der ersten gemeinsamen Weihnachtstafel in der neuen Wohnung, aufgenommen von Jonas' Vater, zeigt beide Familien um den Tisch versammelt. | Fremdaufnahme | Positiv |
## Alter 29
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 29 | Januar | Persönliche Entwicklung | Als sichtbares Zeichen für sein neues Sparziel macht Jonas ein Selfie mit einem alten Marmeladenglas, das er als "Wohnungskauf-Spardose" beschriftet hat. | Selfie | Neutral |
| 29 | Februar | Persönliche Entwicklung | Ein Ersthelfer-Kollege fotografiert die Szene an der Unfallstelle, im Hintergrund ist Jonas zu erkennen, der bis zum Rettungswagen wartet. | Fremdaufnahme | Positiv |
| 29 | März | Freundschaft | Cem fotografiert Jonas beim Fotografieren auf einer ihrer gemeinsamen Fototouren durch Köln. | Fremdaufnahme | Positiv |
| 29 | April | Familie | Ein Nachbar macht ein Foto von Jonas und seinen Eltern vor dem "Zu verkaufen"-Schild am Elternhaus. | Fremdaufnahme | Neutral |
| 29 | Mai | Liebe | Mara macht ein Selfie mit Jonas vor einem Schaufenster mit Babykleidung, in dem sie beide kurz stehen bleiben. | Selfie | Neutral |
| 29 | Juni | Liebe | Ein Selfie von einem langen Spaziergang am Rhein hält den Abend fest, an dem Jonas offen über seine Unsicherheit beim Thema Elternschaft spricht. | Selfie | Neutral |
| 29 | Juli | Beruf | Kollegen fotografieren Jonas mit einem Umschlag in der Hand, nachdem er für den erfolgreichen Bauabschnitt einen Bonus erhalten hat. | Fremdaufnahme | Positiv |
| 29 | August | Freizeit | Beim mehrtägigen Wanderevent macht ein anderer Teilnehmer ein Foto von Jonas und David, erschöpft, aber lachend am Gipfelkreuz. | Fremdaufnahme | Positiv |
| 29 | September | Familie | Lea macht ein Selfie mit ihrem neuen Ring und schickt es Jonas, der es sofort ausdruckt. | Selfie | Positiv |
| 29 | Oktober | Liebe | Ein Selfie von Jonas und Mara beim Betrachten von Babyfotos in Leas Fotoalbum zeigt, wie sich Jonas erstmals ein eigenes Familienleben vorstellen kann. | Selfie | Positiv |
| 29 | November | Wohnen | Ein Foto vom gemütlichen Wohnzimmerabend, aufgenommen von Mara, zeigt beide bewusst entspannt – Symbol ihrer Entscheidung, weiter zur Miete zu wohnen. | Selfie | Neutral |
| 29 | Dezember | Partnerschaft | Statt eines Rings macht Mara ein Selfie mit den Reiseunterlagen, die Jonas ihr geschenkt hat. | Selfie | Positiv |
## Alter 30
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 30 | Januar | Persönliche Entwicklung | Ein Selfie zu seinem 30. Geburtstag zeigt Jonas nachdenklicher als auf früheren Geburtstagsfotos. | Selfie | Neutral |
| 30 | Februar | Beruf | Ein Kollege fotografiert Jonas beim Zusammenstellen seiner Bewerbungsunterlagen für die intern ausgeschriebene Führungsposition. | Fremdaufnahme | Neutral |
| 30 | März | Beruf | Ein Kollege macht ein Foto vom Team-Meeting, auf dem Jonas sichtlich angespannt neben dem neu ernannten Vorgesetzten sitzt. | Fremdaufnahme | Negativ |
| 30 | April | Liebe | Ein Selfie von einem ruhigen Abend zeigt Jonas und Mara eng nebeneinander, kurz nach seiner beruflichen Enttäuschung. | Selfie | Positiv |
| 30 | Mai | Familie | Der Hochzeitsfotograf macht ein Foto von Jonas, wie er bei Leas Hochzeit seine Rede hält, Tränen in den Augen. | Fremdaufnahme | Sehr positiv |
| 30 | Juni | Reisen | Vor den Niagarafällen macht ein Tourist ein Foto von Jonas und Mara auf ihrer lange geplanten Kanada-Reise. | Fremdaufnahme | Sehr positiv |
| 30 | Juli | Beruf | Ein Foto vom Kick-off-Meeting zeigt Jonas als neuen Leiter eines anspruchsvollen Infrastrukturprojekts. | Fremdaufnahme | Positiv |
| 30 | August | Freizeit | Ein Selfie von einer seltenen Laufrunde zeigt Jonas erschöpfter als früher – seit Monaten läuft er kaum noch. | Selfie | Neutral |
| 30 | September | Liebe | Ein Selfie von Jonas vor einem Schaufenster mit Verlobungsringen, das er heimlich David schickt. | Selfie | Positiv |
| 30 | Oktober | Familie | Sein Vater Thomas fotografiert Jonas am fertig restaurierten Schreibtisch, den beide gemeinsam aufgearbeitet haben. | Fremdaufnahme | Positiv |
| 30 | November | Liebe | David macht ein Selfie mit Jonas, der ihm heimlich den gerade gekauften Verlobungsring zeigt. | Selfie | Positiv |
| 30 | Dezember | Liebe | Ein Wanderer fotografiert Jonas und Mara auf dem Bergaussichtspunkt, kurz nachdem er ihr – sichtlich nervös – einen Antrag gemacht hat. | Fremdaufnahme | Sehr positiv |
## Alter 31
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 31 | Januar | Hochzeit | Ein Selfie von Jonas und Mara vor einem Stapel Hochzeitsmagazine zeigt den Beginn ihrer Planung. | Selfie | Positiv |
| 31 | Februar | Alltag | Ein Selfie vor dem Laptop mit mehreren geöffneten Angebots-Tabs zeigt Jonas' ernüchterten Gesichtsausdruck über die hohen Kosten für Location und Feier. | Selfie | Negativ |
| 31 | März | Hochzeit | Ein Selfie von Jonas und Mara mit der reduzierten Gästeliste in der Hand, erleichtert lachend. | Selfie | Neutral |
| 31 | April | Beruf | Ein Kollege fotografiert Jonas nach dem Gespräch über seine Gehaltserhöhung mit einem breiten Grinsen. | Fremdaufnahme | Positiv |
| 31 | Mai | Familie | Ein Familienfoto beim Treffen wirkt auf den ersten Blick harmonisch, entstand aber unmittelbar nach Spannungen über die Gästeliste. | Fremdaufnahme | Negativ |
| 31 | Juni | Hochzeit | Der Hochzeitsfotograf hält den Moment fest, in dem Jonas und Mara im kleinen Kreis standesamtlich heiraten. | Fremdaufnahme | Sehr positiv |
| 31 | Juli | Reisen | Ein Highlander-Wirt fotografiert Jonas und Mara vor einem schottischen Loch auf ihrer Hochzeitsreise. | Fremdaufnahme | Sehr positiv |
| 31 | August | Alltag | Ein Selfie vom ersten "normalen" Sonntagsfrühstück nach der Hochzeitsreise zeigt beide entspannt in Jogginghosen. | Selfie | Neutral |
| 31 | September | Familie | Ein Selfie von Jonas und Mara nach dem Gespräch über ihren Kinderwunsch, beide sichtlich aufgeregt. | Selfie | Positiv |
| 31 | Oktober | Beruf | Ein Kollege fotografiert Jonas an einem übervollen Schreibtisch, nachdem ein erfahrener Kollege gekündigt hat. | Fremdaufnahme | Negativ |
| 31 | November | Alltag | Ein Selfie von Jonas und Mara am neu eröffneten gemeinsamen Sparkonto-Ordner auf dem Küchentisch. | Selfie | Neutral |
| 31 | Dezember | Familie | Mara macht ein Selfie mit dem Schwangerschaftstest in der Hand, Jonas daneben mit offenem Mund. | Selfie | Sehr positiv |
## Alter 32
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 32 | Januar | Familie | Ein Selfie aus dem Wartezimmer der Frauenärztin zeigt Jonas und Mara vor dem ersten Ultraschall. | Selfie | Sehr positiv |
| 32 | Februar | Wohnen | Ein Selfie vom halb umgeräumten Arbeitszimmer zeigt die ersten Möbelstücke für das künftige Kinderzimmer. | Selfie | Positiv |
| 32 | März | Beruf | Ein Kollege fotografiert Jonas beim Gespräch mit seinem Vorgesetzten über die geplante Elternzeit. | Fremdaufnahme | Neutral |
| 32 | April | Alltag | Ein Selfie von Jonas und Mara am Küchentisch, umgeben von Babyausstattungs-Prospekten und einem handgeschriebenen Budgetzettel. | Selfie | Neutral |
| 32 | Mai | Familie | Ein Kursleiter fotografiert die Gruppe beim Geburtsvorbereitungskurs, Jonas mit sichtlich unsicherem Blick neben Mara. | Fremdaufnahme | Neutral |
| 32 | Juni | Freundschaft | David macht ein Selfie mit seinem neugeborenen Sohn und schickt es Jonas mit den Worten "bald bist du dran". | Selfie | Positiv |
| 32 | Juli | Familie | Ein Selfie von Jonas beim Staubsaugen mit Schürze zeigt, wie er wegen Maras Beschwerden mehr Haushalt übernimmt. | Selfie | Neutral |
| 32 | August | Familie | Das Krankenhauspersonal macht ein Foto von Jonas, der seinen neugeborenen Sohn Emil zum ersten Mal im Arm hält, Tränen auf den Wangen. | Fremdaufnahme | Sehr positiv |
| 32 | September | Familie | Ein müdes Selfie um drei Uhr nachts zeigt Jonas mit dem schreienden Emil auf dem Arm. | Selfie | Negativ |
| 32 | Oktober | Familie | Ein Selfie zeigt Jonas entspannter beim Wickeln, sichtlich routinierter als noch Wochen zuvor. | Selfie | Positiv |
| 32 | November | Familie | Ein Selfie am ersten Tag der Elternzeit zeigt Jonas mit Emil im Tragetuch vor der Bürotür, die er gerade hinter sich lässt. | Selfie | Positiv |
| 32 | Dezember | Familie | Karin fotografiert das erste Weihnachten mit Emil, alle drei Generationen um den Baum versammelt. | Fremdaufnahme | Sehr positiv |
## Alter 33
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 33 | Januar | Familie | Ein Selfie vom Spielplatz zeigt Jonas und Emil an einem gewöhnlichen Vormittag während der Elternzeit. | Selfie | Positiv |
| 33 | Februar | Beruf | Ein Kollege fotografiert Jonas vor einem Whiteboard voller Notizen, während er sich nach seiner Rückkehr wieder einarbeitet. | Fremdaufnahme | Negativ |
| 33 | März | Partnerschaft | Ein Selfie vom gemeinsamen Abendessen zeigt Jonas und Mara, beide mit dem Handy neben dem Teller – Sinnbild für Gespräche, die nur noch um Organisation kreisen. | Selfie | Negativ |
| 33 | April | Partnerschaft | Ein Kellner fotografiert Jonas und Mara beim ersten Abendessen zu zweit seit Emils Geburt. | Fremdaufnahme | Positiv |
| 33 | Mai | Familie | Die Erzieherin macht am ersten Tag ein Foto von Emil in der Kindertagespflege, Jonas im Hintergrund beim Abschied. | Fremdaufnahme | Neutral |
| 33 | Juni | Beruf | Kollegen fotografieren Jonas bei seiner Beförderungsfeier zum Projektleiter mit Sektglas in der Hand. | Fremdaufnahme | Sehr positiv |
| 33 | Juli | Alltag | Ein Selfie vom Kühlschrank mit der neuen, engeren Wochenplan-Tafel zeigt, wie stark die Betreuungskosten den Alltag strukturieren. | Selfie | Neutral |
| 33 | August | Freizeit | Ein Selfie im Morgengrauen am Rhein zeigt Jonas beim ersten Lauf seit Monaten, außer Atem, aber lächelnd. | Selfie | Positiv |
| 33 | September | Familie | Ein Selfie von Jonas und seinem frisch pensionierten Vater beim gemeinsamen Kaffee zeigt Thomas ungewöhnlich still. | Selfie | Neutral |
| 33 | Oktober | Beruf | Ein Kollege fotografiert das Team-Meeting, in dem Jonas die Nachricht von der Kündigung eines Mitarbeiters verkündet. | Fremdaufnahme | Negativ |
| 33 | November | Freundschaft | Ein Selfie von einem Männerwochenende zeigt Jonas und David beim Angeln, beide sichtlich entspannt. | Selfie | Positiv |
| 33 | Dezember | Familie | Ein Familienfoto vom zweiten Weihnachten mit Emil wirkt deutlich entspannter als das Foto vom Vorjahr. | Fremdaufnahme | Positiv |
## Alter 34
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 34 | Januar | Wohnen | Ein Selfie von Jonas und Mara vor einem Immobilienportal auf dem Laptop-Bildschirm zeigt den Beginn ihrer erneuten Wohnungssuche. | Selfie | Neutral |
| 34 | Februar | Alltag | Ein Berater fotografiert Jonas und Mara nach dem ernüchternden Finanzierungsgespräch für einen Immobilienkauf. | Fremdaufnahme | Negativ |
| 34 | März | Wohnen | Ein Selfie vom ersten Besichtigungstermin für eine größere Mietwohnung zeigt beide vor einem leeren Zimmer. | Selfie | Neutral |
| 34 | April | Beruf | Ein Foto vom Baustellenbesuch zeigt Jonas, wie er einem jungen Nachwuchsingenieur etwas erklärt. | Fremdaufnahme | Positiv |
| 34 | Mai | Familie | Ein Selfie-Video-Standbild von Emil, der stolz seinen ersten langen Satz sagt, während Jonas danebensteht. | Selfie | Sehr positiv |
| 34 | Juni | Wohnen | Ein Selfie vor der Tür der neuen Vier-Zimmer-Wohnung mit Schlüssel in der Hand zeigt die ganze Familie. | Selfie | Positiv |
| 34 | Juli | Wohnen | Ein Foto vom chaotischen Umzugstag, aufgenommen von einem Umzugshelfer, zeigt Jonas erschöpft zwischen Kartonstapeln. | Fremdaufnahme | Negativ |
| 34 | August | Freizeit | Ein Selfie von der neu eingerichteten Fotoecke im neuen Zuhause zeigt Jonas mit Kamera in der Hand. | Selfie | Positiv |
| 34 | September | Partnerschaft | Ein Selfie von einem ruhigen Abendspaziergang zeigt Jonas und Mara beim Gespräch über ein mögliches zweites Kind. | Selfie | Neutral |
| 34 | Oktober | Familie | Ein Selfie von Karin mit Emil auf dem Arm zeigt den Beginn ihrer wöchentlichen Nachmittage zusammen. | Selfie | Positiv |
| 34 | November | Beruf | Kollegen fotografieren Jonas bei der internen Lobrede für sein Projekt, das das Budget unterschritten hat. | Fremdaufnahme | Sehr positiv |
| 34 | Dezember | Partnerschaft | Ein Selfie von Jonas und Mara nach einem langen Gespräch zeigt beide ruhig und einig, kein zweites Kind zu planen. | Selfie | Neutral |
## Alter 35
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 35 | Januar | Beruf | Ein Kollege fotografiert Jonas beim Gespräch über das Angebot, stellvertretender Bereichsleiter zu werden. | Fremdaufnahme | Positiv |
| 35 | Februar | Beruf | Kollegen fotografieren Jonas bei seiner ersten Personalleiter-Besprechung in neuer Rolle. | Fremdaufnahme | Positiv |
| 35 | März | Familie | Die Erzieherin macht ein Foto vom ersten Kindergartentag, Emil klammert sich an Jonas' Bein. | Fremdaufnahme | Neutral |
| 35 | April | Beruf | Ein Foto vom Konfliktgespräch zeigt Jonas zwischen zwei angespannten Mitarbeitern vermittelnd. | Fremdaufnahme | Negativ |
| 35 | Mai | Freizeit | Ein Selfie am Nordseestrand zeigt die ganze Familie beim verlängerten Wochenende. | Selfie | Positiv |
| 35 | Juni | Freundschaft | Ein letztes gemeinsames Foto von Cem und Jonas vor dessen Umzugswagen nach Hamburg. | Selfie | Negativ |
| 35 | Juli | Persönliche Entwicklung | Ein Selfie zeigt Jonas' verstaubte Kamera auf dem Schrank – seit Monaten unbenutzt. | Selfie | Neutral |
| 35 | August | Freizeit | Ein Selfie von Jonas mit Kamera im Kölner Viertel markiert den Start seines neuen Fotoprojekts. | Selfie | Positiv |
| 35 | September | Familie | Lea macht ein Selfie mit ihrem sichtbar gewölbten Bauch, Jonas hält bereits eine kleine Mütze in der Hand. | Selfie | Sehr positiv |
| 35 | Oktober | Beruf | Ein Kollege fotografiert die neue Geschäftsführung bei einer Betriebsversammlung, Jonas mit verschränkten Armen im Publikum. | Fremdaufnahme | Negativ |
| 35 | November | Partnerschaft | Ein Selfie von Jonas mit Emil beim Hausaufgaben-Nachmittag, während Mara auf ihrer Fortbildung ist. | Selfie | Neutral |
| 35 | Dezember | Familie | Ein Familienfoto zeigt Jonas mit seinem vierjährigen Sohn vor dem Weihnachtsbaum, bewusst als eigene Tradition inszeniert. | Fremdaufnahme | Positiv |
## Alter 36
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 36 | Januar | Familie | Ein Krankenhausfoto zeigt Jonas als frischgebackenen Onkel mit seiner Nichte Mia im Arm. | Fremdaufnahme | Sehr positiv |
| 36 | Februar | Beruf | Ein Selfie vor einem Stapel neuer Berichtsformulare zeigt Jonas' genervten Blick. | Selfie | Negativ |
| 36 | März | Partnerschaft | Ein Foto vom Abschlussfest der Fortbildung zeigt Mara mit Zertifikat, Jonas applaudierend daneben. | Fremdaufnahme | Positiv |
| 36 | April | Familie | Ein Selfie von Jonas und Emil beim Nachmittagsritual im Park. | Selfie | Neutral |
| 36 | Mai | Alltag | Ein Selfie vor dem neuen Gebrauchtwagen zeigt die ganze Familie beim ersten Ausflug damit. | Selfie | Neutral |
| 36 | Juni | Freizeit | Ein Besucher fotografiert Jonas vor seinen eigenen Fotografien bei seiner ersten kleinen Ausstellung. | Fremdaufnahme | Sehr positiv |
| 36 | Juli | Freundschaft | Ein Selfie beim letzten gemeinsamen Wochenende wirkt entspannt, entstand aber unmittelbar vor dem heftigen Streit, der die Freundschaft mit David monatelang auf Eis legt. | Selfie | Sehr negativ |
| 36 | August | Reisen | Ein Campingplatz-Nachbar fotografiert Jonas, Mara und Emil vor ihrem Zelt in Dänemark. | Fremdaufnahme | Positiv |
| 36 | September | Beruf | Ein Foto von der Krisensitzung zeigt Jonas mit Baukosten-Tabellen an der Wand. | Fremdaufnahme | Negativ |
| 36 | Oktober | Beruf | Ein Kollege fotografiert Jonas bei der unangenehmen Ansage der Sparmaßnahmen vor seinem Team. | Fremdaufnahme | Negativ |
| 36 | November | Familie | Ein Selfie von Jonas und seinem Vater vor dem in die Jahre gekommenen Elternhaus. | Selfie | Neutral |
| 36 | Dezember | Familie | Ein Selfie von Jonas mit seinen Eltern vor einer Wohnungsanzeige für kleinere Wohnungen. | Selfie | Positiv |
## Alter 37
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 37 | Januar | Beruf | Ein Foto von der Betriebsversammlung zeigt die angespannten Gesichter der Belegschaft bei der Ankündigung der Umstrukturierung. | Fremdaufnahme | Negativ |
| 37 | Februar | Beruf | Ein Kollege fotografiert die Abteilungsrunde, in der die geplante Verkleinerung bekannt wird, Jonas mit verschränkten Armen. | Fremdaufnahme | Negativ |
| 37 | März | Familie | Ein Selfie von Jonas und seinen Eltern bei einer weiteren Wohnungsbesichtigung. | Selfie | Neutral |
| 37 | April | Beruf | Ein Kollege macht am letzten Arbeitstag ein Erinnerungsfoto von Jonas vor seinem leergeräumten Schreibtisch. | Fremdaufnahme | Sehr negativ |
| 37 | Mai | Persönliche Entwicklung | Ein Selfie zeigt Jonas unrasiert auf dem Sofa mit dem Laptop – bis David unangekündigt vor der Tür steht und ein Foto von ihrem ersten Treffen seit dem Streit macht. | Fremdaufnahme | Neutral |
| 37 | Juni | Partnerschaft | Ein Selfie von Mara, die ihm tröstend die Hand auf die Schulter legt, während er am Küchentisch Bewerbungen schreibt. | Selfie | Positiv |
| 37 | Juli | Beruf | Ein Selfie zeigt Jonas mit einem Stapel Absagebriefe in der Hand, resigniert lächelnd. | Selfie | Negativ |
| 37 | August | Familie | Ein Selfie vor dem leeren Elternhaus zeigt Jonas mit einer letzten Kiste in der Hand. | Selfie | Neutral |
| 37 | September | Beruf | Ein Selfie vom ersten Treffen mit seinem ehemaligen Auftraggeber in einem Café zeigt Jonas mit Laptop und Kaffeetasse. | Selfie | Positiv |
| 37 | Oktober | Selbstständigkeit | Ein Selfie mit dem Gewerbeanmeldungs-Formular in der Hand markiert den Start seiner Selbstständigkeit. | Selfie | Positiv |
| 37 | November | Beruf | Ein Selfie mit drei Kaffeetassen auf dem Küchentisch symbolisiert die drei neuen Kundenanfragen an einem Tag. | Selfie | Sehr positiv |
| 37 | Dezember | Persönliche Entscheidung | Ein Selfie mit Mara vor einem selbstgemalten "Neustart"-Schild in der Küche. | Selfie | Sehr positiv |
## Alter 38
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 38 | Januar | Selbstständigkeit | Ein Selfie vor seinem neuen Schreibtisch im Gemeinschaftsbüro zeigt Jonas beim Einrichten. | Selfie | Positiv |
| 38 | Februar | Persönliche Entwicklung | Ein Selfie vom leeren Kontoauszug auf dem Bildschirm zeigt Jonas' angespannten Blick in einem schwachen Monat. | Selfie | Negativ |
| 38 | März | Selbstständigkeit | Ein Selfie mit dem unterschriebenen Sechsmonatsvertrag in der Hand. | Selfie | Sehr positiv |
| 38 | April | Familie | Ein Foto vor der Schule, aufgenommen von Mara, zeigt Jonas stolz neben Emil an dessen erstem Schultag mit Schultüte. | Fremdaufnahme | Sehr positiv |
| 38 | Mai | Partnerschaft | Ein Selfie von einem späten Abend am Laptop zeigt Jonas allein am Küchentisch, während Mara im Hintergrund unzufrieden die Arme verschränkt. | Selfie | Negativ |
| 38 | Juni | Partnerschaft | Ein Selfie, das Mara ihrer Schwester schickt, zeigt sie mit gepacktem Koffer vor deren Wohnungstür. | Selfie | Sehr negativ |
| 38 | Juli | Persönliche Entscheidung | Ein Selfie mit einem handgeschriebenen "Feierabend ab 18 Uhr"-Zettel an seinem Bildschirm. | Selfie | Positiv |
| 38 | August | Reisen | Ein Kellner fotografiert die Familie beim entspannten Abendessen in einem österreichischen Gasthof. | Fremdaufnahme | Positiv |
| 38 | September | Partnerschaft | Ein Selfie von Jonas und Mara beim ersten organisierten Paarabend seit Monaten. | Selfie | Positiv |
| 38 | Oktober | Selbstständigkeit | Ein Selfie mit einer Umsatzübersicht auf dem Bildschirm zeigt Jonas zufrieden nach mehreren stabilen Monaten. | Selfie | Positiv |
| 38 | November | Freundschaft | Ein Selfie von David, der Jonas nach dem Geständnis über seine Eheprobleme fest umarmt. | Selfie | Positiv |
| 38 | Dezember | Familie | Ein Familienfoto vor dem Weihnachtsbaum wirkt nach dem schwierigen Frühjahr wieder unbeschwert. | Fremdaufnahme | Positiv |
## Alter 39
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 39 | Januar | Selbstständigkeit | Ein Selfie mit dem unterschriebenen Rahmenvertrag in der Hand. | Selfie | Sehr positiv |
| 39 | Februar | Persönliche Entwicklung | Ein Selfie vom neu eingerichteten Rücklagen-Ordner auf dem Schreibtisch. | Selfie | Neutral |
| 39 | März | Familie | Ein Selfie aus dem Krankenhausflur zeigt Jonas nervös wartend während der Operation seiner Mutter. | Selfie | Negativ |
| 39 | April | Familie | Ein Selfie von Karin, die wieder selbstständig durch ihre Küche geht, mit Jonas im Hintergrund erleichtert lächelnd. | Selfie | Positiv |
| 39 | Mai | Freizeit | Ein Streckenfotograf hält Jonas beim entspannten, zielfreien Halbmarathon-Lauf fest. | Fremdaufnahme | Positiv |
| 39 | Juni | Partnerschaft | Ein Kellner fotografiert Jonas und Mara beim Anstoßen zu ihrem achten Hochzeitstag in Belgien. | Fremdaufnahme | Positiv |
| 39 | Juli | Beruf | Ein Selfie mit seiner neuen freien Mitarbeiterin vor dem gemeinsamen Arbeitsplatz. | Selfie | Positiv |
| 39 | August | Familie | Ein Selfie von Jonas und Emil über aufgeschlagenen Matheheften, beide mit angestrengtem Blick. | Selfie | Neutral |
| 39 | September | Freundschaft | Ein Selfie von Jonas und Cem bei ihrer ersten gemeinsamen Fototour seit Jahren. | Selfie | Positiv |
| 39 | Oktober | Selbstständigkeit | Ein Selfie mit einer überfälligen Rechnung auf dem Bildschirm zeigt Jonas' angespannten Blick. | Selfie | Negativ |
| 39 | November | Persönliche Entwicklung | Ein Selfie an seinem Arbeitsplatz zeigt Jonas zufrieden, mit einem kleinen Firmenschild im Hintergrund. | Selfie | Positiv |
| 39 | Dezember | Familie | Ein Selfie mit seinen Eltern zu Besuch zeigt Karin und Thomas sichtlich älter als auf Fotos von vor ein paar Jahren. | Selfie | Neutral |
## Alter 40
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 40 | Januar | Persönliche Entwicklung | Ein Selfie zu seinem bewusst klein gefeierten 40. Geburtstag zeigt Jonas entspannt mit Mara und Emil. | Selfie | Positiv |
| 40 | Februar | Familie | Ein Selfie von einem Besuch zeigt seinen Vater Thomas ungewöhnlich blass und erschöpft im Sessel. | Selfie | Negativ |
| 40 | März | Familie | Ein Selfie von Jonas, der seinem Vater beim Einkaufen hilft, zeigt beide beim Tütentragen. | Selfie | Neutral |
| 40 | April | Beruf | Ein Selfie mit seiner zweiten freien Fachkraft vor dem gemeinsamen Auftrag. | Selfie | Positiv |
| 40 | Mai | Familie | Ein letztes Handyfoto von Thomas im Krankenbett, aufgenommen von Karin Stunden vor seinem Tod. | Fremdaufnahme | Sehr negativ |
| 40 | Juni | Familie | Ein Foto von der Beerdigung, aufgenommen von einem Verwandten, zeigt Jonas und Lea Arm in Arm hinter dem Sarg. | Fremdaufnahme | Sehr negativ |
| 40 | Juli | Persönliche Entwicklung | Ein Selfie an seinem Schreibtisch zeigt Jonas mit leerem, abwesendem Blick mitten in der Arbeit. | Selfie | Negativ |
| 40 | August | Familie | Ein Selfie vom ruhigen Urlaub mit Mara und Emil zeigt die ersten echten Lächeln seit dem Todesfall. | Selfie | Positiv |
| 40 | September | Freizeit | Ein Selfie zeigt Jonas beim Digitalisieren alter Dias seines Vaters am Leuchttisch. | Selfie | Positiv |
| 40 | Oktober | Familie | Ein Selfie von Jonas und Lea, umgeben von Kisten mit den letzten Sachen ihres Vaters. | Selfie | Negativ |
| 40 | November | Beruf | Ein Selfie mit einem vollen Terminkalender zeigt Jonas' Rückkehr in eine normalere Arbeitsroutine. | Selfie | Neutral |
| 40 | Dezember | Familie | Ein Familienfoto vom ersten Weihnachten ohne Thomas zeigt einen sichtbar leeren Platz am Tisch. | Fremdaufnahme | Sehr negativ |
## Alter 41
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 41 | Januar | Familie | Ein Selfie von Jonas und Karin bei ihrem ersten festen Monatsbesuch. | Selfie | Positiv |
| 41 | Februar | Selbstständigkeit | Ein Selfie vor seinem neuen Firmenschild mit Logo an der Bürotür. | Selfie | Positiv |
| 41 | März | Beruf | Ein Selfie mit seinem ersten Kunden ohne Vorgeschichte im gemeinsamen Netzwerk, Handschlag vor der Kamera. | Selfie | Sehr positiv |
| 41 | April | Familie | Ein Selfie von Emil vor seiner neuen weiterführenden Schule, sichtlich selbstbewusster als früher. | Selfie | Positiv |
| 41 | Mai | Partnerschaft | Ein Selfie von Mara in ihrer Physiotherapiepraxis in neuer leitender Rolle. | Selfie | Positiv |
| 41 | Juni | Alltag | Ein Selfie von Jonas beim Wäscheaufhängen mit Emil, der ihm dabei hilft. | Selfie | Neutral |
| 41 | Juli | Reisen | Ein Selfie aus einer Berghütte zeigt die durchnässte, aber lachende Familie, die sich vor einem plötzlichen Unwetter in Südtirol in Sicherheit gebracht hat. | Selfie | Sehr positiv |
| 41 | August | Freundschaft | Ein Selfie von David, allein auf einer Parkbank, das er Jonas mit der Nachricht "können wir reden?" schickt. | Selfie | Negativ |
| 41 | September | Persönliche Entwicklung | Ein Selfie von Jonas und David bei einem langen Spaziergang, bei dem Jonas vor allem zuhört. | Selfie | Positiv |
| 41 | Oktober | Finanzen | Ein Selfie mit den Unterlagen seiner neuen privaten Altersvorsorge auf dem Tisch. | Selfie | Neutral |
| 41 | November | Freizeit | Ein Besucher fotografiert Jonas vor seiner Fotoserie über Köln im kleinen Kulturzentrum. | Fremdaufnahme | Sehr positiv |
| 41 | Dezember | Familie | Ein Selfie von Karin, die erstmals mehrere Tage bei Jonas und Mara verbringt, mit Emil auf dem Sofa. | Selfie | Positiv |
## Alter 42
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 42 | Januar | Beruf | Ein Selfie am Schreibtisch zeigt Jonas beim Absenden einer Absage an einen lukrativen, aber zeitraubenden Auftrag. | Selfie | Positiv |
| 42 | Februar | Familie | Ein Selfie-Versuch mit Emil misslingt, weil er sich wegdreht – ein kleines Symbol für seine wachsende Distanz. | Selfie | Negativ |
| 42 | März | Persönliche Entwicklung | Ein Selfie von Jonas vor Emils geschlossener Zimmertür, mit dem er sich selbst zum Anklopfen statt Reingehen erinnert. | Selfie | Positiv |
| 42 | April | Finanzen | Ein Selfie mit dem Steuerbescheid in der Hand zeigt Jonas' besorgten Blick. | Selfie | Negativ |
| 42 | Mai | Selbstständigkeit | Ein Selfie mit seinem neuen Steuerberater nach dem ersten gemeinsamen Termin. | Selfie | Positiv |
| 42 | Juni | Partnerschaft | Ein Kellner fotografiert Jonas und Mara vor dem Eiffelturm bei ihrem Wochenende in Paris. | Fremdaufnahme | Sehr positiv |
| 42 | Juli | Familie | Ein Selfie von Jonas, Lea und Karin vor Leas neuem Haus in der Nähe. | Selfie | Positiv |
| 42 | August | Freizeit | Ein Selfie von Jonas und David in Radtrikots vor ihrer ersten gemeinsamen Rennradtour. | Selfie | Positiv |
| 42 | September | Beruf | Ein Selfie mit seiner scheidenden Mitarbeiterin, die ihm ihr neues Vertragsangebot zeigt. | Selfie | Neutral |
| 42 | Oktober | Persönliche Entwicklung | Ein Selfie im Wartezimmer zeigt Jonas' angespannten Blick vor dem Kontrolltermin wegen des auffälligen Blutwerts. | Selfie | Negativ |
| 42 | November | Familie | Ein Selfie direkt nach einem lauten Streit zeigt Emil mit rotem Gesicht und abgewandtem Blick. | Selfie | Negativ |
| 42 | Dezember | Familie | Ein Selfie von Jonas und Emil, versöhnt und nebeneinander grinsend, nach seiner Entschuldigung. | Selfie | Positiv |
## Alter 43
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 43 | Januar | Beruf | Ein Selfie mit dem unterschriebenen mehrjährigen Beratungsvertrag in der Hand. | Selfie | Sehr positiv |
| 43 | Februar | Wohnen | Ein Selfie von Jonas und Mara vor einem Immobilienportal, diesmal entspannter als beim letzten Mal. | Selfie | Neutral |
| 43 | März | Wohnen | Ein Makler fotografiert Jonas und Mara vor einem besichtigten Haus, beide mit unentschlossenem Gesichtsausdruck. | Fremdaufnahme | Neutral |
| 43 | April | Persönliche Entscheidung | Ein Selfie von Jonas und Mara vor ihrer eigenen Wohnungstür, zufrieden mit ihrer Entscheidung dagegen. | Selfie | Positiv |
| 43 | Mai | Familie | Ein Selfie von Karin mit ihrem neuen Partner beim ersten gemeinsamen Spaziergang. | Selfie | Positiv |
| 43 | Juni | Familie | Ein Selfie von Jonas, anfangs mit sichtlich gemischtem Gesichtsausdruck neben Karins neuem Partner. | Selfie | Neutral |
| 43 | Juli | Reisen | Ein Selfie von Jonas und Emil auf einem Berggipfel bei ihrer ersten gemeinsamen Vater-Sohn-Wanderreise. | Selfie | Sehr positiv |
| 43 | August | Familie | Ein Selfie am Lagerfeuer zeigt Jonas und Emil im vertrauten Gespräch über erste Verliebtheit. | Selfie | Positiv |
| 43 | September | Beruf | Ein Foto vom Rednerpult zeigt Jonas bei seinem ersten Fachvortrag. | Fremdaufnahme | Positiv |
| 43 | Oktober | Freizeit | Ein Selfie mit einer Gruppe junger Fotografen beim ehrenamtlichen Workshop. | Selfie | Positiv |
| 43 | November | Freundschaft | Ein Selfie von David mit seiner Frau, wieder Arm in Arm, das er Jonas stolz schickt. | Selfie | Positiv |
| 43 | Dezember | Familie | Ein Familienfoto zeigt Karins neuen Partner erstmals selbstverständlich mit am Weihnachtstisch. | Fremdaufnahme | Positiv |
## Alter 44
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 44 | Januar | Selbstständigkeit | Ein Selfie mit seiner neuen Teilzeit-Ingenieurin am gemeinsamen Schreibtisch. | Selfie | Positiv |
| 44 | Februar | Beruf | Ein Selfie mit einem Stapel Personalunterlagen zeigt Jonas' überraschten Blick über den Mehraufwand. | Selfie | Negativ |
| 44 | März | Familie | Ein Selfie von Emil vor einer Wandtafel mit ausgeschnittenen Berufsbildern. | Selfie | Neutral |
| 44 | April | Familie | Ein Selfie von Jonas und Emil beim offenen Gespräch über dessen Zukunftspläne. | Selfie | Positiv |
| 44 | Mai | Partnerschaft | Ein Selfie von Mara vor ihrer Praxis mit dem Beteiligungsangebot in der Hand. | Selfie | Positiv |
| 44 | Juni | Finanzen | Ein Selfie von Jonas und Mara über ausgebreiteten Finanzunterlagen am Küchentisch. | Selfie | Neutral |
| 44 | Juli | Partnerschaft | Ein Selfie von Mara vor ihrer Praxis, nun als Mitinhaberin, Jonas applaudierend daneben. | Selfie | Positiv |
| 44 | August | Reisen | Ein Strandfotograf macht ein Foto der Familie am Atlantikstrand in Frankreich. | Fremdaufnahme | Positiv |
| 44 | September | Freundschaft | Ein altes Selfie mit Cem, das Jonas beim Durchsehen seines Fotoarchivs findet und wehmütig betrachtet. | Selfie | Neutral |
| 44 | Oktober | Familie | Ein Selfie von Karin mit Koffer, bereit für ihren ersten Winter in Spanien. | Selfie | Positiv |
| 44 | November | Persönliche Entwicklung | Ein Selfie von Jonas nach einem Telefonat mit Karin, deutlich entspannter als frühere ähnliche Fotos. | Selfie | Positiv |
| 44 | Dezember | Beruf | Ein Selfie mit der Jahresbilanz-Tabelle auf dem Bildschirm zeigt Jonas' zufriedenes Grinsen. | Selfie | Sehr positiv |
## Alter 45
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 45 | Januar | Persönliche Entwicklung | Ein Selfie zu seinem 45. Geburtstag zeigt Jonas ruhiger und zufriedener als auf dem Foto zum 40. | Selfie | Positiv |
| 45 | Februar | Beruf | Ein Selfie mit seiner Mitarbeiterin, der er symbolisch einen Aktenordner übergibt. | Selfie | Positiv |
| 45 | März | Familie | Ein Selfie von Emil im Blaumann nach seinem ersten Schülerpraktikum. | Selfie | Positiv |
| 45 | April | Partnerschaft | Ein Selfie von Jonas und Mara beim Planen eines gemeinsamen Wochenendes ohne Kind. | Selfie | Positiv |
| 45 | Mai | Reisen | Ein Selfie mit den gebuchten Flugtickets für ihre Reise zu zweit im Herbst. | Selfie | Positiv |
| 45 | Juni | Freundschaft | Ein Selfie von Jonas, David und zwei alten Freunden bei ihrem ersten gemeinsamen Wochenende seit Jahren. | Selfie | Sehr positiv |
| 45 | Juli | Familie | Ein Familienfoto zeigt Karin mit beiden Kindern, Enkeln und ihrem Partner an ihrem Geburtstagstisch. | Fremdaufnahme | Positiv |
| 45 | August | Freizeit | Ein Foto von der Buchpräsentation zeigt Jonas mit seinem frisch gedruckten Bildband über zwanzig Jahre Köln. | Fremdaufnahme | Sehr positiv |
| 45 | September | Beruf | Ein Selfie nach dem letzten Termin mit einem schwierigen Kunden zeigt Jonas erleichtert statt enttäuscht. | Selfie | Neutral |
| 45 | Oktober | Partnerschaft | Ein Passant fotografiert Jonas und Mara vor der Steilküste in Nordspanien. | Fremdaufnahme | Sehr positiv |
| 45 | November | Persönliche Entwicklung | Ein Selfie beim Herbstspaziergang zeigt Jonas sichtlich gelassener als auf früheren Fotos in ähnlicher Umgebung. | Selfie | Positiv |
| 45 | Dezember | Familie | Ein Familienfoto zum Jahresende zeigt Jonas, Mara und Emil entspannt auf dem Sofa – ein stiller Jahresrückblick in einem einzigen Bild. | Fremdaufnahme | Sehr positiv |

View file

@ -0,0 +1,356 @@
## Alter 25
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 25 | Januar | Beruf | Eine Kollegin fotografiert Sophie, wie sie die E-Mail zur Vertragsverlängerung freudig ihrer Teamrunde zeigt. | Fremdaufnahme | Positiv |
| 25 | Februar | Wohnen | Ein Selfie von Sophie und Alina in der gemeinsamen WG-Küche entsteht kurz nachdem Alina ihren geplanten Auszug angekündigt hat. | Selfie | Neutral |
| 25 | März | Liebe | Ein Selfie von Sophie und Felix am Küchentisch, umgeben von Wohnungsanzeigen, hält ihr erstes ernsthaftes Gespräch über Zusammenziehen fest. | Selfie | Neutral |
| 25 | April | Beruf | Ein Besucher fotografiert Sophie, wie sie die von ihr organisierte Lesungsreihe eröffnet. | Fremdaufnahme | Positiv |
| 25 | Mai | Alltag | Ein Selfie mit ihrem neu gekauften, deutlich günstigeren Gebrauchtfahrrad zeigt Sophie mit gemischten Gefühlen. | Selfie | Negativ |
| 25 | Juni | Freundschaft | Alina fotografiert Sophie mit der letzten Umzugskiste in der leeren WG-Küche, sichtlich gerührt. | Fremdaufnahme | Negativ |
| 25 | Juli | Wohnen | Ein Selfie vor ihrer neuen eigenen Wohnungstür zeigt Sophie mit dem Schlüssel in der Hand. | Selfie | Positiv |
| 25 | August | Liebe | Ein Selfie vom gemeinsamen Abendessen wirkt harmonisch, entstand aber kurz nach Felix' enttäuschter Reaktion auf ihre Entscheidung. | Selfie | Negativ |
| 25 | September | Beruf | Ein Kollege fotografiert Sophie bei einem Pressegespräch zum großen Kulturfestival. | Fremdaufnahme | Positiv |
| 25 | Oktober | Freizeit | Ein Teilnehmer macht ein Gruppenfoto vom ersten Abend ihres neuen Literaturkreises. | Fremdaufnahme | Positiv |
| 25 | November | Familie | Ihr Bruder Daniel fotografiert Sophie beim Spielen mit seiner kleinen Tochter. | Fremdaufnahme | Positiv |
| 25 | Dezember | Liebe | Ein Selfie von Sophie bei ihren Eltern in Erfurt zeigt sie entspannt, während Felix zeitgleich bei seiner eigenen Familie ist. | Selfie | Neutral |
## Alter 26
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 26 | Januar | Liebe | Ein Selfie von einem langen Spaziergang am Auensee hält den Abend fest, an dem beide offen über ihre unterschiedlichen Zukunftsvorstellungen sprechen. | Selfie | Negativ |
| 26 | Februar | Beruf | Ein Teamfoto entsteht bei der Bekanntgabe der wichtigen Förderung für das Kulturfestival. | Fremdaufnahme | Sehr positiv |
| 26 | März | Alltag | Ein Selfie mit ihrem ersten gefüllten Sparglas zeigt Sophie zufrieden nach der kleinen Gehaltserhöhung. | Selfie | Positiv |
| 26 | April | Freundschaft | Sophie und Nina machen nach dem Literaturkreis ihr erstes gemeinsames Foto. | Selfie | Positiv |
| 26 | Mai | Liebe | Ein Selfie von einem Solo-Abend zeigt Sophie entspannt mit Wein und Buch auf dem Sofa, während Felix auf Tournee ist. | Selfie | Neutral |
| 26 | Juni | Beruf | Kollegen gratulieren mit einem Foto, als Sophie ihren unbefristeten Vertrag unterschreibt. | Fremdaufnahme | Sehr positiv |
| 26 | Juli | Reisen | Ein Selfie vor der Karlsbrücke zeigt Sophie und Alina auf ihrer gemeinsamen Reise nach Prag. | Selfie | Positiv |
| 26 | August | Liebe | Ein Selfie vom gemeinsamen Abendessen wirkt unbeschwert, doch beide spüren bereits, wie mühsam sich das Zusammenleben nach Felix' Rückkehr anfühlt. | Selfie | Negativ |
| 26 | September | Persönliche Entwicklung | Ein altes Selfie mit Felix aus den Anfangsjahren, das Sophie nachdenklich durchscrollt, lässt sie fragen, ob sie nur aus Gewohnheit festhält. | Selfie | Neutral |
| 26 | Oktober | Familie | Ein Screenshot eines Videotelefonats zeigt Sophie und ihre Mutter Petra im aufmunternden Gespräch. | Selfie | Positiv |
| 26 | November | Liebe | Ein letztes gemeinsames Selfie vor der vereinbarten Auszeit wirkt bewusst distanziert. | Selfie | Negativ |
| 26 | Dezember | Liebe | Ein Familienfoto bei Weihnachten wirkt normal, verdeckt aber die wachsende Distanz zwischen Sophie und Felix. | Fremdaufnahme | Negativ |
## Alter 27
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 27 | Januar | Liebe | Ein letztes gemeinsames Selfie, aufgenommen direkt nach dem einvernehmlichen Trennungsgespräch, zeigt beide sichtlich erleichtert und traurig zugleich. | Selfie | Sehr negativ |
| 27 | Februar | Freundschaft | Nina fotografiert einen Mädelsabend mit Wein und Trostschokolade, mit dem Alina und Nina Sophie durch die erste Zeit nach der Trennung helfen. | Fremdaufnahme | Positiv |
| 27 | März | Alltag | Ein Selfie zeigt Sophie neben einer Kiste mit Dingen, die sie an Felix erinnern, bereit für den Wertstoffhof. | Selfie | Neutral |
| 27 | April | Beruf | Ein Kollege fotografiert Sophie spätabends noch allein im Büro. | Fremdaufnahme | Neutral |
| 27 | Mai | Persönliche Entwicklung | Ein Selfie vor einem Wandkalender zeigt Sophie, wie sie spontan ein Wochenende nur für sich einträgt. | Selfie | Positiv |
| 27 | Juni | Reisen | Ein Selfie vor der Kathedrale von Lissabon zeigt Sophie strahlend auf ihrer ersten Solo-Reise. | Selfie | Sehr positiv |
| 27 | Juli | Freundschaft | Ein Video-Chat-Screenshot mit Felix wirkt entspannt und unbeschwert. | Selfie | Positiv |
| 27 | August | Weiterbildung | Ein Kursfoto vom ersten Abend ihrer Weiterbildung im digitalen Kulturmanagement zeigt Sophie in der Gruppe. | Fremdaufnahme | Positiv |
| 27 | September | Beruf | Ein Foto vom leeren Veranstaltungsraum, den das abgesagte Projekt genutzt hätte, zeigt Sophie sichtlich enttäuscht davor. | Fremdaufnahme | Negativ |
| 27 | Oktober | Alltag | Eine Standbetreiberin fotografiert Sophie beim Stöbern nach gebrauchten Fachbüchern auf dem Bücherflohmarkt. | Fremdaufnahme | Neutral |
| 27 | November | Familie | Daniel fotografiert Sophie beim Spielen mit seiner Tochter während ihres langen Wochenendbesuchs. | Fremdaufnahme | Positiv |
| 27 | Dezember | Persönliche Entwicklung | Ein Familienfoto zu Weihnachten zeigt Sophie entspannt lachend, ohne den Blick auf die Vergangenheit gerichtet. | Fremdaufnahme | Positiv |
## Alter 28
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 28 | Januar | Beruf | Ein Teamfoto entsteht bei Sophies Beförderung zur Projektkoordinatorin. | Fremdaufnahme | Sehr positiv |
| 28 | Februar | Weiterbildung | Ein Selfie zeigt Sophie übermüdet zwischen Lernkarten und leeren Kaffeetassen. | Selfie | Negativ |
| 28 | März | Freundschaft | Ein Selfie von Sophie und Nina bei einem ihrer immer häufigeren Treffen zu zweit. | Selfie | Positiv |
| 28 | April | Weiterbildung | Ein Foto von der Zertifikatsübergabe zeigt Sophie stolz mit ihrem Abschluss. | Fremdaufnahme | Sehr positiv |
| 28 | Mai | Liebe | Ein Konzert-Selfie von Sophie und Nina zeigt einen Blick zwischen beiden, der mehr als Freundschaft andeutet. | Selfie | Neutral |
| 28 | Juni | Persönliche Entwicklung | Ein Selfie vor dem Spiegel an einem grüblerischen Abend allein. | Selfie | Neutral |
| 28 | Juli | Liebe | Ein Selfie hält den Moment fest, in dem Nina Sophie gesteht, sich in sie verliebt zu haben. | Selfie | Sehr positiv |
| 28 | August | Liebe | Ein erstes gemeinsames Pärchen-Selfie von Sophie und Nina. | Selfie | Sehr positiv |
| 28 | September | Freundschaft | Ein Selfie im Vergleich zu einem alten Freundschaftsfoto zeigt beide noch etwas unsicher in der neuen Rolle. | Selfie | Neutral |
| 28 | Oktober | Familie | Ein Foto vom Abendessen bei Sophies Eltern zeigt alle entspannt lachend, nachdem sie ihnen von Nina erzählt hat. | Fremdaufnahme | Positiv |
| 28 | November | Beruf | Ein Foto von der Besprechung, in der Sophie das neue Kulturprojekt angeboten wird. | Fremdaufnahme | Positiv |
| 28 | Dezember | Liebe | Ein Familienfoto zu Weihnachten in Erfurt zeigt Nina erstmals mitten in der Familie. | Fremdaufnahme | Sehr positiv |
## Alter 29
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 29 | Januar | Beruf | Ein Team-Kickoff-Foto zeigt Sophie als neue Leiterin des Kulturprojekts. | Fremdaufnahme | Positiv |
| 29 | Februar | Beruf | Ein Selfie am übervollen Schreibtisch zeigt Sophie erschöpft zwischen Aktenordnern und Budgettabellen. | Selfie | Negativ |
| 29 | März | Liebe | Ein Passant fotografiert Sophie und Nina vor Nyhavn während ihres Kopenhagen-Wochenendes. | Fremdaufnahme | Positiv |
| 29 | April | Freizeit | Ein Selfie zeigt Sophie stolz mit einer gebrauchten Kamera, gekauft von ihrem ersten gesparten Geld. | Selfie | Positiv |
| 29 | Mai | Freundschaft | Ein Selfie von Sophie und Alina mit dem Ultraschallbild in der Hand feiert Alinas Schwangerschaft. | Selfie | Sehr positiv |
| 29 | Juni | Beruf | Ein Selfie zeigt Sophie mit besorgtem Blick nach dem Telefonat, in dem sich ein Kooperationspartner zurückzieht. | Selfie | Negativ |
| 29 | Juli | Beruf | Ein Handschlag-Foto mit dem neu gefundenen Kooperationspartner. | Fremdaufnahme | Positiv |
| 29 | August | Partnerschaft | Ein Selfie vom Küchentisch hält den Abend fest, an dem Nina erstmals eine gemeinsame Wohnung anspricht. | Selfie | Positiv |
| 29 | September | Wohnen | Ein Selfie beim gemeinsamen Frühstück zeigt beide, jede noch mit eigenem Wohnungsschlüssel gut sichtbar auf dem Tisch. | Selfie | Neutral |
| 29 | Oktober | Familie | Ein Foto von der Taufe zeigt Sophie als frischgebackene Patentante mit Baby Paul im Arm. | Fremdaufnahme | Sehr positiv |
| 29 | November | Freizeit | Ein Selfie mit tonverschmierten Händen im gemeinsamen Keramikkurs. | Selfie | Positiv |
| 29 | Dezember | Beruf | Ein Jubel-Foto des Teams entsteht bei der Zusage zur Weiterfinanzierung des Kulturprojekts. | Fremdaufnahme | Sehr positiv |
## Alter 30
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 30 | Januar | Persönliche Entwicklung | Ein Foto vom Geburtstagsfest mit Freunden zeigt Sophie zu ihrem 30. Geburtstag entspannt lachend. | Fremdaufnahme | Positiv |
| 30 | Februar | Wohnen | Ein Selfie von Sophie und Nina vor einem Wohnungsanzeigen-Aushang markiert den Beginn der Suche. | Selfie | Positiv |
| 30 | März | Wohnen | Ein Selfie nach einer enttäuschenden Wohnungsbesichtigung zeigt beide sichtlich frustriert vor einer zu teuren Altbauwohnung. | Selfie | Negativ |
| 30 | April | Wohnen | Ein Selfie vor der Tür der neuen, bezahlbaren Altbauwohnung. | Selfie | Sehr positiv |
| 30 | Mai | Wohnen | Ein Selfie beim Kistenauspacken zeigt Sophie und Nina umgeben von halb ausgepackten Umzugskartons. | Selfie | Sehr positiv |
| 30 | Juni | Partnerschaft | Ein Selfie vom gemeinsamen Abendessen wirkt entspannt, entstand jedoch inmitten wiederkehrender Diskussionen über gemeinsame und getrennte Freizeit. | Selfie | Negativ |
| 30 | Juli | Partnerschaft | Ein Selfie zeigt beide lachend mit ihren jeweiligen Kalendern, in denen feste Zeiten für eigene Hobbys eingetragen sind. | Selfie | Positiv |
| 30 | August | Beruf | Ein Foto am Schreibtisch der erkrankten Geschäftsführerin zeigt Sophie in Vertretungsfunktion. | Fremdaufnahme | Positiv |
| 30 | September | Beruf | Ein Foto von einer Strategiesitzung zeigt Sophie, wie sie sich engagiert zu Wort meldet. | Fremdaufnahme | Positiv |
| 30 | Oktober | Familie | Ein Foto ihres Vaters Michael im Vereinstrikot seines neuen Ehrenamts, das er Sophie schickt. | Fremdaufnahme | Neutral |
| 30 | November | Alltag | Ein Selfie vor dem Bankautomaten nach der Eröffnung ihres gemeinsamen Kontos. | Selfie | Neutral |
| 30 | Dezember | Liebe | Ein Selfie vor ihrem ersten gemeinsamen Weihnachtsbaum in der eigenen Wohnung. | Selfie | Sehr positiv |
## Alter 31
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 31 | Januar | Beruf | Ein Teamfoto zur Ernennung von Sophie zur stellvertretenden Geschäftsführerin. | Fremdaufnahme | Sehr positiv |
| 31 | Februar | Beruf | Ein Foto von einer langen Sitzung zeigt Sophie mit einem hohen Aktenstapel vor sich. | Fremdaufnahme | Neutral |
| 31 | März | Familie | Ein Videocall-Screenshot mit ihrer Mutter Petra, die von ihrer geplanten Arbeitszeitreduzierung erzählt. | Selfie | Neutral |
| 31 | April | Partnerschaft | Ein Selfie vom Küchentisch hält den Abend fest, an dem Nina erstmals konkret über einen späteren Kinderwunsch spricht. | Selfie | Neutral |
| 31 | Mai | Persönliche Entwicklung | Ein Selfie vor einem Schaufenster mit Kinderwagen zeigt Sophies nachdenklichen Blick. | Selfie | Neutral |
| 31 | Juni | Partnerschaft | Ein Selfie von einem entspannten Spaziergang zeigt beide einig, das Thema nicht unter Zeitdruck zu setzen. | Selfie | Positiv |
| 31 | Juli | Reisen | Ein Gruppenfoto am Strand zeigt Sophie, Nina und zwei Freunde auf ihrer zweiwöchigen Griechenland-Reise. | Fremdaufnahme | Sehr positiv |
| 31 | August | Beruf | Ein Selfie am überfüllten Schreibtisch zeigt Sophie erschöpft, nachdem eine Kollegin überraschend gekündigt hat. | Selfie | Negativ |
| 31 | September | Freundschaft | Ein Foto vor dem beladenen Umzugsauto zeigt Sophie und Alina beim letzten spontanen Treffen vor Alinas Umzug an den Stadtrand. | Selfie | Neutral |
| 31 | Oktober | Freizeit | Ein gemütliches Selfie mit Buch und Tee zeigt Sophie beim Wiederentdecken des Lesens für sich selbst. | Selfie | Positiv |
| 31 | November | Partnerschaft | Ein Passant fotografiert den Moment, in dem Nina Sophie während ihres Wochenendausflugs einen Antrag macht. | Fremdaufnahme | Sehr positiv |
| 31 | Dezember | Liebe | Ein Selfie mit den neuen Verlobungsringen zeigt beide strahlend. | Selfie | Positiv |
## Alter 32
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 32 | Januar | Hochzeit | Ein Selfie von Sophie und Nina über aufgeschlagenen Hochzeitsmagazinen. | Selfie | Positiv |
| 32 | Februar | Familie | Ein Videocall-Screenshot mit Daniel, der anbietet, bei der Hochzeitsorganisation zu helfen. | Selfie | Positiv |
| 32 | März | Beruf | Ein Foto von der Krisensitzung zeigt Sophie angespannt nach der Kürzung einer wichtigen Förderung. | Fremdaufnahme | Negativ |
| 32 | April | Beruf | Ein erleichtertes Teamfoto entsteht, nachdem Sophie durch Umplanung Entlassungen verhindern kann. | Fremdaufnahme | Sehr positiv |
| 32 | Mai | Partnerschaft | Ein Selfie zeigt Nina allein mit Hochzeitskatalogen am Küchentisch, während Sophie im Hintergrund am Laptop arbeitet. | Selfie | Negativ |
| 32 | Juni | Hochzeit | Ein Selfie von Sophie und Nina, versöhnt lächelnd, mit der deutlich reduzierten Gästeliste in der Hand. | Selfie | Positiv |
| 32 | Juli | Familie | Der Hochzeitsfotograf hält den Moment der freien Zeremonie von Sophie und Nina mit Familie und Freunden fest. | Fremdaufnahme | Sehr positiv |
| 32 | August | Reisen | Ein Selfie im Zugabteil zeigt beide auf ihrer Hochzeitsreise durch Südfrankreich und Nordspanien. | Selfie | Sehr positiv |
| 32 | September | Alltag | Ein Selfie von einem gewöhnlichen Sofa-Abend zeigt beide bewusst unspektakulär entspannt. | Selfie | Neutral |
| 32 | Oktober | Familie | Ein Selfie vom Abendgespräch, in dem Nina das Thema Kinder erneut mit konkreteren Vorstellungen anspricht. | Selfie | Neutral |
| 32 | November | Partnerschaft | Ein Selfie vor einem Kinderzimmer-Möbelgeschäft zeigt Sophie nachdenklich, aber offener als zuvor. | Selfie | Positiv |
| 32 | Dezember | Persönliche Entscheidung | Ein Foto aus dem Wartezimmer einer Kinderwunschberatungsstelle zeigt beide vor ihrem ersten Infogespräch. | Fremdaufnahme | Positiv |
## Alter 33
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 33 | Januar | Familie | Ein Foto im Wartezimmer der Kinderwunschberatung zeigt Sophie und Nina bei ihrem ersten gemeinsamen Termin. | Fremdaufnahme | Neutral |
| 33 | Februar | Partnerschaft | Ein Selfie zeigt beide über Formularen und Broschüren zur Familiengründung am Küchentisch. | Selfie | Negativ |
| 33 | März | Beruf | Ein Foto vom Gespräch mit dem Vorstand zeigt Sophie beim Angebot, die Geschäftsführung zu übernehmen. | Fremdaufnahme | Sehr positiv |
| 33 | April | Persönliche Entscheidung | Ein Handschlag-Foto mit dem Vorstand besiegelt ihre Zusage mit schrittweisem Übergang. | Fremdaufnahme | Positiv |
| 33 | Mai | Familie | Ein Selfie von Sophie und Nina, entschlossen lächelnd, nach der Entscheidung, den Kinderwunsch weiterzuverfolgen. | Selfie | Positiv |
| 33 | Juni | Finanzen | Ein Selfie mit einem neuen, beschrifteten Sparordner "Familienplanung" auf dem Küchentisch. | Selfie | Neutral |
| 33 | Juli | Freundschaft | Ein Kaffee-Selfie von Sophie und Alina zeigt Alina, wie sie zuhört, ohne zu einer Entscheidung zu drängen. | Selfie | Positiv |
| 33 | August | Beruf | Ein Foto am Schreibtisch zeigt Sophie mit geöffneten Budgettabellen bei der Jahresplanung. | Fremdaufnahme | Neutral |
| 33 | September | Familie | Ein Selfie von einem stillen Abend zu zweit, kurz nachdem der erste Versuch nicht geklappt hat. | Selfie | Negativ |
| 33 | Oktober | Partnerschaft | Ein Selfie beim spontanen Kinoabend zeigt beide bewusst ohne das Thema Familienplanung. | Selfie | Positiv |
| 33 | November | Freizeit | Ein Kellner fotografiert Sophie und Nina vor dem Stephansdom bei ihrem spontanen Wien-Wochenende. | Fremdaufnahme | Positiv |
| 33 | Dezember | Familie | Ein Foto vom Gespräch mit Petra und Michael zeigt deren unterstützende Reaktion auf die Pläne des Paares. | Fremdaufnahme | Positiv |
## Alter 34
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 34 | Januar | Familie | Ein Selfie zeigt beide mit einem Kalender, in dem sie den nächsten Versuch markiert haben. | Selfie | Neutral |
| 34 | Februar | Beruf | Ein Foto von der Vorstandssitzung zeigt Sophie zunehmend in strategische Entscheidungen eingebunden. | Fremdaufnahme | Positiv |
| 34 | März | Familie | Ein Selfie mit dem positiven Schwangerschaftstest zeigt Ninas und Sophies überglückliche Gesichter. | Selfie | Sehr positiv |
| 34 | April | Partnerschaft | Ein Selfie am Küchentisch zeigt beide zwischen Freude und Sorge um den Verlauf der Schwangerschaft schwankend. | Selfie | Positiv |
| 34 | Mai | Familie | Ein Selfie aus dem Wartezimmer der Frauenärztin zeigt Sophie mit dem Ultraschallbild in der Hand. | Selfie | Sehr positiv |
| 34 | Juni | Wohnen | Ein Selfie im halb eingerichteten Kinderzimmer zeigt Sophie beim Aufbauen des Kinderbetts. | Selfie | Positiv |
| 34 | Juli | Beruf | Ein Foto vom Gespräch, in dem Sophie ein zusätzliches Großprojekt ablehnt, um ihre Belastung zu begrenzen. | Fremdaufnahme | Positiv |
| 34 | August | Familie | Ein Foto beim Übergeben mehrerer Kisten mit Babyausstattung zeigt Alina und Sophie lachend. | Fremdaufnahme | Positiv |
| 34 | September | Alltag | Ein Selfie mit einem handgeschriebenen Haushaltsplan an der Pinnwand für die Zeit nach der Geburt. | Selfie | Neutral |
| 34 | Oktober | Familie | Ein Selfie beim Kochen zeigt Sophie, während die hochschwangere Nina sich auf dem Sofa ausruht. | Selfie | Neutral |
| 34 | November | Partnerschaft | Ein Selfie vom gemeinsamen Abendessen wirkt ruhig, entstand aber nach einem angespannten Gespräch über Verantwortung und Arbeitszeiten. | Selfie | Negativ |
| 34 | Dezember | Familie | Ein Selfie vor dem Weihnachtsbaum zeigt die hochschwangere Nina und Sophie, ruhig und erwartungsvoll. | Selfie | Positiv |
## Alter 35
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 35 | Januar | Familie | Das Krankenhauspersonal fotografiert Sophie mit ihrer neugeborenen Tochter Clara im Arm. | Fremdaufnahme | Sehr positiv |
| 35 | Februar | Familie | Ein übermüdetes nächtliches Selfie zeigt Sophie mit Clara während der Elternzeit. | Selfie | Negativ |
| 35 | März | Familie | Ein Selfie am Fenster im Morgenlicht zeigt Sophie zunehmend sicher mit Clara auf dem Arm. | Selfie | Positiv |
| 35 | April | Partnerschaft | Ein Selfie vom Frühstückstisch wirkt normal, entstand aber am Morgen nach einem heftigen Streit über die Aufgabenverteilung. | Selfie | Negativ |
| 35 | Mai | Partnerschaft | Ein Selfie zeigt beide vor einer neu aufgehängten Wochenplan-Tafel. | Selfie | Positiv |
| 35 | Juni | Familie | Ein Foto von Petra mit Clara im Park zeigt die Großeltern erstmals einen ganzen Nachmittag allein mit ihr. | Fremdaufnahme | Positiv |
| 35 | Juli | Freundschaft | Ein altes Gruppenfoto mit Freunden, das Sophie durchscrollt, lässt sie merken, wie lange das letzte Treffen her ist. | Selfie | Neutral |
| 35 | August | Persönliche Entwicklung | Ein Selfie im Café mit Buch zeigt Sophie bei einem kleinen Freiraum für sich selbst. | Selfie | Positiv |
| 35 | September | Beruf | Ein Selfie zeigt Sophie mit Clara auf dem Arm beim Lesen einer Vereins-Rundmail auf dem Handy. | Selfie | Neutral |
| 35 | Oktober | Familie | Ein Video-Standbild von Clara beim ersten Krabbeln. | Fremdaufnahme | Positiv |
| 35 | November | Partnerschaft | Ein Kellner fotografiert Sophie und Nina beim ersten Abendessen ohne Kind seit der Geburt. | Fremdaufnahme | Sehr positiv |
| 35 | Dezember | Familie | Ein Familienfoto am Weihnachtsbaum zeigt Claras erstes, lebhaftes Weihnachtsfest. | Fremdaufnahme | Sehr positiv |
## Alter 36
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 36 | Januar | Beruf | Ein Foto am ersten Arbeitstag zurück im Büro zeigt Sophie mit reduzierter Stundenzahl. | Fremdaufnahme | Neutral |
| 36 | Februar | Familie | Die Erzieherin fotografiert Clara und Sophie am ersten Tag der Kita-Eingewöhnung. | Fremdaufnahme | Neutral |
| 36 | März | Beruf | Ein Selfie am Schreibtisch zeigt Sophie mit einem Foto von Clara als Bildschirmhintergrund gut sichtbar. | Selfie | Neutral |
| 36 | April | Partnerschaft | Ein Selfie zeigt Nina, wie sie Sophie stolz ihren neuen Teilzeitvertrag zeigt. | Selfie | Positiv |
| 36 | Mai | Beruf | Ein Teamfoto zur offiziellen Ernennung von Sophie als Geschäftsführerin. | Fremdaufnahme | Sehr positiv |
| 36 | Juni | Beruf | Ein erschöpftes Selfie am Schreibtisch zeigt einen Kalender voller Termine trotz reduzierter Arbeitszeit. | Selfie | Negativ |
| 36 | Juli | Familie | Ein Selfie im Park mit Clara zeigt Sophie an einem Nachmittag, den sie bewusst nicht im Büro verbringt. | Selfie | Positiv |
| 36 | August | Reisen | Ein Foto am Ostseestrand zeigt die Familie bei ihrer ersten längeren Reise mit Clara. | Fremdaufnahme | Positiv |
| 36 | September | Familie | Ein Video-Standbild von Clara bei ihren ersten verständlichen Wörtern. | Fremdaufnahme | Sehr positiv |
| 36 | Oktober | Beruf | Ein Teamfoto entsteht bei der Vorstellung der neuen flexiblen Arbeitszeitmodelle. | Fremdaufnahme | Positiv |
| 36 | November | Alltag | Ein Selfie mit Kita-Rechnung und Haushaltsbuch auf dem Küchentisch. | Selfie | Neutral |
| 36 | Dezember | Partnerschaft | Ein Selfie zeigt Sophie und Nina mit Clara zwischen sich, zufrieden als eingespieltes Elternteam. | Selfie | Positiv |
## Alter 37
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 37 | Januar | Beruf | Ein Foto von der Strategie-Klausur zeigt Sophie mit ihrem Team an der Pinnwand. | Fremdaufnahme | Positiv |
| 37 | Februar | Familie | Ein Selfie zeigt Sophie mit der kranken Clara auf dem Sofa, Fieberthermometer sichtbar. | Selfie | Negativ |
| 37 | März | Beruf | Ein Foto vom Team nach der Ablehnung des wichtigen Förderantrags zeigt enttäuschte Gesichter. | Fremdaufnahme | Negativ |
| 37 | April | Beruf | Ein Foto von der überarbeiteten Projektplanung an der Wand zeigt Sophie erleichtert über den geretteten Kern des Programms. | Fremdaufnahme | Neutral |
| 37 | Mai | Partnerschaft | Ein Selfie vom gemeinsamen Abendessen zeigt Sophie mit Handy in der Hand, Nina daneben sichtlich genervt. | Selfie | Negativ |
| 37 | Juni | Partnerschaft | Ein Selfie zeigt das Handy demonstrativ im Schrank verstaut, beide lachend über die neue Regelung. | Selfie | Positiv |
| 37 | Juli | Freundschaft | Ein Selfie von Sophie und Alina bei ihrem ersten Wochenende nur zu zweit seit Jahren. | Selfie | Sehr positiv |
| 37 | August | Familie | Die Erzieherin fotografiert Clara mit ihren neuen Kindergartenfreunden. | Fremdaufnahme | Positiv |
| 37 | September | Beruf | Ein Foto von der Vertragsunterzeichnung mit der neuen Stiftung als Förderpartner. | Fremdaufnahme | Sehr positiv |
| 37 | Oktober | Familie | Ein Krankenhausbesuchs-Selfie zeigt Sophie und ihren Vater Michael nach dessen Knieoperation. | Selfie | Negativ |
| 37 | November | Familie | Ein Foto von einem Besuch bei den Eltern lässt Sophie bewusst wahrnehmen, wie sehr Petra und Michael altern. | Selfie | Neutral |
| 37 | Dezember | Alltag | Ein entspanntes Familienfoto zeigt die Feiertage zu Hause, ganz ohne Reisestress. | Fremdaufnahme | Positiv |
## Alter 38
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 38 | Januar | Persönliche Entwicklung | Ein altes Selfie von einem früheren Schreibworkshop, das Sophie wehmütig wiederfindet. | Selfie | Neutral |
| 38 | Februar | Freizeit | Ein Selfie am Laptop mit Kaffeetasse zeigt die ersten Zeilen ihres neuen Essayprojekts. | Selfie | Positiv |
| 38 | März | Beruf | Ein Foto von der Krisensitzung mit Zahlen an der Wand zeigt den erneuten finanziellen Druck des Vereins. | Fremdaufnahme | Negativ |
| 38 | April | Beruf | Ein Foto vom leeren Schreibtisch der bewusst unbesetzt gelassenen Stelle. | Fremdaufnahme | Negativ |
| 38 | Mai | Familie | Nina fotografiert Clara beim ersten Fahrradfahren, Sophie hinterherlaufend. | Fremdaufnahme | Sehr positiv |
| 38 | Juni | Partnerschaft | Ein Selfie am Küchentisch mit Wohnungsanzeigen zeigt beide beim Gespräch über eine größere Wohnung. | Selfie | Neutral |
| 38 | Juli | Wohnen | Ein Makler fotografiert Sophie und Nina vor einer besichtigten, aber nicht passenden Wohnung. | Fremdaufnahme | Neutral |
| 38 | August | Freizeit | Ein Selfie mit dem gedruckten Kulturmagazin zeigt Sophies ersten veröffentlichten Essay. | Selfie | Sehr positiv |
| 38 | September | Beruf | Ein Foto von einem Treffen mit neuen Kontakten, die durch die Veröffentlichung entstanden sind. | Fremdaufnahme | Positiv |
| 38 | Oktober | Wohnen | Ein Selfie mit dem Zusage-Schreiben für die größere Mietwohnung. | Selfie | Positiv |
| 38 | November | Wohnen | Ein Umzugshelfer fotografiert Sophie erschöpft zwischen Umzugskartons. | Fremdaufnahme | Negativ |
| 38 | Dezember | Familie | Ein Selfie zeigt Clara stolz in ihrem neuen, größeren Zimmer. | Selfie | Positiv |
## Alter 39
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 39 | Januar | Beruf | Ein Foto vom Bildschirm mit der Anfrage für regelmäßige Fachbeiträge zeigt Sophie überrascht lächelnd. | Selfie | Positiv |
| 39 | Februar | Persönliches Projekt | Ein Selfie mit ihrem ersten veröffentlichten Artikel auf dem Tablet. | Selfie | Positiv |
| 39 | März | Partnerschaft | Ein Selfie vom Abend zeigt Sophie am Laptop schreibend, während Nina im Hintergrund allein fernsieht. | Selfie | Negativ |
| 39 | April | Alltag | Ein Selfie am Schreibtisch mit dem Kalendereintrag "Schreibabend" gut sichtbar. | Selfie | Positiv |
| 39 | Mai | Familie | Ein Foto vom ersten Schultag zeigt Clara stolz mit ihrer Schultüte. | Fremdaufnahme | Sehr positiv |
| 39 | Juni | Familie | Ein Selfie mit Claras neuem Stundenplan an der Pinnwand. | Selfie | Neutral |
| 39 | Juli | Reisen | Ein Passant fotografiert die Familie am schwedischen See bei ihrem ruhigen Sommerurlaub. | Fremdaufnahme | Sehr positiv |
| 39 | August | Beruf | Ein Foto von der ersten Sitzung des städtischen Kulturbeirats zeigt Sophie als neues Mitglied. | Fremdaufnahme | Positiv |
| 39 | September | Familie | Ein Foto von Petras Abschiedsfeier zum endgültigen Ruhestand. | Fremdaufnahme | Neutral |
| 39 | Oktober | Freundschaft | Ein Gruppenfoto zeigt Sophie, Nina, Alina und ihre Partnerin bei einem gemeinsamen Abend. | Selfie | Positiv |
| 39 | November | Persönliches Projekt | Ein Selfie mit dem Überweisungsbeleg ihres ersten Honorars für einen längeren Essay. | Selfie | Positiv |
| 39 | Dezember | Persönliche Entwicklung | Ein Selfie am Schreibtisch zeigt zwei Ordner nebeneinander, beschriftet "Verein" und "Schreiben". | Selfie | Positiv |
## Alter 40
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 40 | Januar | Persönliche Entwicklung | Ein großes Geburtstagsfoto zeigt Sophie umringt von Familie, alten und neuen Freunden zu ihrem 40. Geburtstag. | Fremdaufnahme | Sehr positiv |
| 40 | Februar | Beruf | Ein erschöpftes Selfie am Schreibtisch zeigt Sophies deutliche Ermüdung nach fast vier Jahren Geschäftsführung. | Selfie | Negativ |
| 40 | März | Beruf | Ein Foto vom Übergabegespräch zeigt Sophie beim Delegieren an ihre Stellvertreterin. | Fremdaufnahme | Positiv |
| 40 | April | Persönliches Projekt | Ein Selfie mit der E-Mail-Anfrage des Verlags auf dem Bildschirm. | Selfie | Sehr positiv |
| 40 | Mai | Persönliches Projekt | Ein Selfie am Laptop mit ausgedrucktem Konzept-Entwurf für ihr erstes Buch. | Selfie | Positiv |
| 40 | Juni | Partnerschaft | Ein Selfie beim Abendessen zeigt Nina mit ernstem Blick, die vor zu vielen gleichzeitigen Projekten warnt. | Selfie | Neutral |
| 40 | Juli | Persönliche Entscheidung | Ein Foto vom Gespräch mit dem Vorstand zeigt Sophies Entscheidung, ihre Arbeitszeit zu reduzieren. | Fremdaufnahme | Positiv |
| 40 | August | Familie | Ein Foto von Clara mit ihren Großeltern Petra und Michael während ihrer ersten Woche allein bei ihnen. | Fremdaufnahme | Positiv |
| 40 | September | Partnerschaft | Ein Passant fotografiert Sophie und Nina vor dem Edinburgh Castle während ihrer kinderfreien Reisewoche. | Fremdaufnahme | Sehr positiv |
| 40 | Oktober | Persönliches Projekt | Ein Selfie mit der Zusage-E-Mail des Verlags für ihr überarbeitetes Buchkonzept. | Selfie | Sehr positiv |
| 40 | November | Finanzen | Ein Selfie am Schreibtisch mit zwei Gehaltsabrechnungen nebeneinander, eine deutlich kleiner als die andere. | Selfie | Neutral |
| 40 | Dezember | Familie | Ein Selfie von Sophie und Clara am Küchentisch, beide schreibend an ihren jeweiligen Geschichten. | Selfie | Positiv |
## Alter 41
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 41 | Januar | Beruf | Ein Foto vom neuen, kürzeren Wochenplan an der Bürotür zeigt Sophies Vier-Tage-Woche. | Fremdaufnahme | Positiv |
| 41 | Februar | Persönliches Projekt | Ein Selfie am Schreibtisch mit der ersten Kapitelüberschrift ihres Buches auf dem Bildschirm. | Selfie | Positiv |
| 41 | März | Familie | Ein Videocall-Screenshot zeigt einen sichtlich besorgten Daniel nach dem Verlust seiner Stelle. | Selfie | Negativ |
| 41 | April | Familie | Ein Selfie zeigt Sophie und Daniel gemeinsam am Laptop über seinen Bewerbungsunterlagen. | Selfie | Positiv |
| 41 | Mai | Beruf | Ein Foto von einer angespannten Teamsitzung zeigt den Widerstand gegen Sophies geplante Programmänderung. | Fremdaufnahme | Negativ |
| 41 | Juni | Beruf | Ein Foto vom Team nach der gefundenen Einigung zeigt deutlich entspanntere Gesichter. | Fremdaufnahme | Positiv |
| 41 | Juli | Familie | Nina fotografiert Clara an ihrem neuen Schlagzeug, im Hintergrund hält sich jemand die Ohren zu. | Fremdaufnahme | Neutral |
| 41 | August | Freundschaft | Ein Foto von der Eröffnungsfeier zeigt Sophie hinter der Theke von Alinas neuem Café. | Fremdaufnahme | Positiv |
| 41 | September | Persönliches Projekt | Ein Selfie mit dem ausgedruckten halben Manuskriptstapel. | Selfie | Sehr positiv |
| 41 | Oktober | Partnerschaft | Ein Selfie vom gemeinsamen Abend wirkt ruhig, entstand aber nach einer erneuten Diskussion über zu wenig gemeinsame Zeit. | Selfie | Negativ |
| 41 | November | Partnerschaft | Ein Selfie vor einem neu aufgehängten "Date Night"-Kalender zeigt beide entschlossen. | Selfie | Positiv |
| 41 | Dezember | Familie | Ein Videocall-Screenshot zeigt einen erleichterten Daniel nach seiner neuen Stelle. | Selfie | Positiv |
## Alter 42
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 42 | Januar | Persönliches Projekt | Ein Selfie mit dem ausgedruckten kompletten ersten Manuskript-Entwurf. | Selfie | Sehr positiv |
| 42 | Februar | Beruf | Eine Kollegin fotografiert Sophie in einem nachdenklichen Moment am Bürofenster. | Fremdaufnahme | Neutral |
| 42 | März | Persönliches Projekt | Ein frustriertes Selfie zeigt Sophie über dem mit Anmerkungen übersäten Lektorat ihres Manuskripts. | Selfie | Negativ |
| 42 | April | Persönliche Entwicklung | Ein Selfie am Schreibtisch zeigt Sophie zufrieden über der überarbeiteten, verbesserten Fassung. | Selfie | Positiv |
| 42 | Mai | Familie | Ein Selfie am Küchentisch zeigt Sophie und Clara im ernsten Gespräch über deren Schulfreundschaft-Probleme. | Selfie | Negativ |
| 42 | Juni | Familie | Ein Selfie zeigt beide entspannter, nachdem Sophie bewusst nur zugehört hat. | Selfie | Positiv |
| 42 | Juli | Reisen | Ein Passant fotografiert Sophie, Nina und Clara vor dem Kolosseum während ihrer dreiwöchigen Italienreise. | Fremdaufnahme | Sehr positiv |
| 42 | August | Beruf | Ein Foto vom Gespräch zeigt Sophies Stellvertreterin, die Interesse an der Geschäftsführung signalisiert. | Fremdaufnahme | Positiv |
| 42 | September | Beruf | Ein Foto von der Vorstandssitzung zeigt die Entwicklung des Übergabeplans. | Fremdaufnahme | Positiv |
| 42 | Oktober | Persönliches Projekt | Ein Selfie mit der Zusage-E-Mail des Verlags für die endgültige Buchfassung. | Selfie | Sehr positiv |
| 42 | November | Finanzen | Ein Selfie mit dem ersten Honorarscheck für ihr Buch. | Selfie | Positiv |
| 42 | Dezember | Partnerschaft | Ein Hotelmitarbeiter fotografiert Sophie vor dem Schreib- und Literaturhotel, das Nina ihr zum Hochzeitstag geschenkt hat. | Fremdaufnahme | Sehr positiv |
## Alter 43
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 43 | Januar | Beruf | Ein Foto von der Team-Ankündigung zeigt Sophie, wie sie ihren geplanten Rücktritt als Geschäftsführerin verkündet. | Fremdaufnahme | Neutral |
| 43 | Februar | Beruf | Ein Foto von einer angespannten Teamsitzung zeigt enttäuschte Kollegen. | Fremdaufnahme | Negativ |
| 43 | März | Persönliche Entwicklung | Ein altes Team-Gruppenfoto, das Sophie nachdenklich betrachtet, lässt sie merken, wie stark ihre Identität mit dem Verein verbunden ist. | Selfie | Neutral |
| 43 | April | Persönliches Projekt | Ein Selfie mit dem druckfrischen ersten Buch in der Hand. | Selfie | Sehr positiv |
| 43 | Mai | Persönliches Projekt | Ein Foto von der ausverkauften Lesung zeigt Sophie am Rednerpult, sichtlich überwältigt. | Fremdaufnahme | Sehr positiv |
| 43 | Juni | Beruf | Ein Foto zeigt Sophie und ihre Nachfolgerin gemeinsam am Schreibtisch beim Einarbeiten. | Fremdaufnahme | Positiv |
| 43 | Juli | Familie | Ein Foto von Clara am Büchertisch zeigt sie, wie sie Sophie erstmals bei einer Lesung hilft. | Fremdaufnahme | Positiv |
| 43 | August | Reisen | Ein Selfie am Ostseestrand zeigt Sophie nachdenklich während ihrer Solo-Tage. | Selfie | Positiv |
| 43 | September | Freundschaft | Ein Selfie vor Alinas Café zeigt beide beim Planen gemeinsamer Lesungen und Kulturabende. | Selfie | Positiv |
| 43 | Oktober | Beruf | Ein Foto vom Übergabefest zeigt Sophie beim Feiern ihres Wechsels in eine projektbezogene Rolle. | Fremdaufnahme | Positiv |
| 43 | November | Familie | Ein Selfie beim Besuch zeigt Sophie und ihren Vater Michael im Garten. | Selfie | Neutral |
| 43 | Dezember | Beruf | Ein Abschiedsfoto mit dem Team zeigt Sophie mit einem großen Blumenstrauß nach ihrer letzten Woche als Geschäftsführerin. | Fremdaufnahme | Sehr positiv |
## Alter 44
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 44 | Januar | Beruf | Ein Selfie am neuen, kleineren Schreibtisch ohne Führungsverantwortung. | Selfie | Positiv |
| 44 | Februar | Persönliches Projekt | Ein Selfie mit einem Terminkalender voller neuer Workshop- und Vortragsanfragen. | Selfie | Positiv |
| 44 | März | Finanzen | Ein Selfie mit einer Haushaltsbuch-App auf dem Handy zeigt Sophies genauere Finanzplanung. | Selfie | Neutral |
| 44 | April | Partnerschaft | Ein Foto von Nina in ihrem neuen, verantwortungsvolleren Büro. | Fremdaufnahme | Positiv |
| 44 | Mai | Familie | Ein Selfie im Hintergrund zeigt Clara mit Kopfhörern, kaum Blickkontakt suchend. | Selfie | Neutral |
| 44 | Juni | Persönliche Entwicklung | Ein altes Foto der kleinen Clara neben einem aktuellen Foto der Teenagerin zeigt den Wandel deutlich. | Selfie | Neutral |
| 44 | Juli | Reisen | Ein Passant fotografiert Sophie und Nina bei ihrer ersten reinen Paarreise seit Jahren. | Fremdaufnahme | Sehr positiv |
| 44 | August | Beruf | Ein Foto vom neuen Projektort zeigt Sophie bei ihrer sechsmonatigen Beratungstätigkeit in einer anderen Stadt. | Fremdaufnahme | Positiv |
| 44 | September | Freundschaft | Ein aktuelles Gruppenfoto im Vergleich zu einem älteren zeigt den lockereren Kontakt zu früheren Kollegen. | Selfie | Neutral |
| 44 | Oktober | Persönliches Projekt | Ein Selfie mit einem Notizbuch voller erster Ideen für ihr zweites Buch. | Selfie | Positiv |
| 44 | November | Familie | Ein Foto vom Familientreffen bei den Eltern zeigt das Gespräch über Unterstützung im Alter. | Fremdaufnahme | Neutral |
| 44 | Dezember | Familie | Ein Foto vom Familientisch mit Unterlagen zu Vollmachten und Wohnfragen. | Fremdaufnahme | Positiv |
## Alter 45
| Alter | Monat | Lebensbereich | Bildmotiv | Foto | Bewertung |
| --- | --- | --- | --- | --- | --- |
| 45 | Januar | Persönliche Entwicklung | Ein entspanntes Selfie zu ihrem 45. Geburtstag zeigt Sophie zufrieden mit ihrer freieren Lebensphase. | Selfie | Positiv |
| 45 | Februar | Beruf | Ein Foto von der Auftragsunterzeichnung zeigt Sophie bei ihrer neuen Kulturstrategie-Beratung. | Fremdaufnahme | Sehr positiv |
| 45 | März | Familie | Ein Selfie zeigt Clara mit Prospekten zu einem möglichen Auslands-Schuljahr. | Selfie | Neutral |
| 45 | April | Partnerschaft | Ein Selfie von einem gemütlichen Abend zu zweit zeigt Sophie und Nina beim Planen ihrer nächsten gemeinsamen Jahre. | Selfie | Positiv |
| 45 | Mai | Persönliches Projekt | Ein Selfie mit der E-Mail eines Verlags, der Interesse an ihrem zweiten Buch zeigt. | Selfie | Sehr positiv |
| 45 | Juni | Freundschaft | Ein Foto zeigt Sophie und Alina, wie sie ein altes Jugendfoto neben ein aktuelles halten, um zwanzig Jahre Freundschaft zu feiern. | Fremdaufnahme | Sehr positiv |
| 45 | Juli | Familie | Ein Foto ihrer Eltern von unterwegs, das sie Sophie von ihrer ersten langen Ruhestandsreise schicken. | Fremdaufnahme | Positiv |
| 45 | August | Freizeit | Ein Selfie am Schreibtisch mit Blick nach draußen zeigt Sophie entspannt während ihrer vier freien Wochen. | Selfie | Positiv |
| 45 | September | Beruf | Ein Foto vom Gespräch zeigt Sophie, wie sie ein Angebot für eine erneute Vollzeit-Führungsposition ablehnt. | Fremdaufnahme | Positiv |
| 45 | Oktober | Persönliches Projekt | Ein Selfie mit dem unterschriebenen Vertrag für ihr zweites Buch. | Selfie | Sehr positiv |
| 45 | November | Partnerschaft | Ein Passant fotografiert Sophie und Nina bei ihrer Jubiläumsreise zum Hochzeitstag. | Fremdaufnahme | Sehr positiv |
| 45 | Dezember | Persönliche Entwicklung | Ein Familienfoto zum Jahresende zeigt Sophie, Nina und Clara entspannt auf dem Sofa – ein stiller Rückblick auf zwei große Beziehungen, eine Familie und eine lange Karriere. | Fremdaufnahme | Sehr positiv |

View file

@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 30.8.1, SVG Export Plug-In . SVG Version: 9.03 Build 0) -->
<svg version="1.0" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 595.3 149" style="enable-background:new 0 0 595.3 149;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F7F3E9;}
.st1{fill:none;stroke:#D59040;stroke-width:4;stroke-miterlimit:10;}
.st2{opacity:0.7;fill:url(#SVGID_1_);}
.st3{opacity:0.7;fill:url(#SVGID_00000010268479788305058960000017491844122260017031_);}
.st4{fill:#F5C26B;}
.st5{opacity:0.4;fill:#F5C26B;}
.st6{fill:none;stroke:#D59040;stroke-miterlimit:10;}
</style>
<path class="st0" d="M90.7,109.9c-0.2-0.3-0.5-0.4-1-0.4c-0.5,0-0.9,0.2-1.3,0.6c-0.4,0.4-0.8,0.9-1.2,1.4c-0.4,0.6-1.1,1-1.9,1.4
c-0.8,0.4-2,0.6-3.5,0.6c-2.1,0-3.7-0.7-4.9-2.1c-1.2-1.4-1.8-3.5-1.8-6.2V65.4h11.3c1.3,0,2.3-0.2,3-0.6c0.7-0.4,1-0.9,1-1.6
c0-0.5-0.2-0.8-0.5-1.1c-0.3-0.2-0.9-0.4-1.6-0.4H75.2v-11c0-0.6-0.2-1.1-0.5-1.4C74.4,49.1,74,49,73.4,49c-0.5,0-1,0.2-1.4,0.5
c-0.4,0.4-0.8,0.9-1.2,1.7l-3.1,8.3c-0.3,0.9-0.8,1.5-1.5,1.8c-0.7,0.3-1.6,0.5-2.8,0.5h-4c-0.6,0-1.1,0.1-1.4,0.4
c-0.3,0.2-0.5,0.6-0.5,1.1c0,0.4,0.2,0.7,0.5,1c0.4,0.3,1.1,0.6,2.1,0.9l3.6,0.8c1,0.3,1.8,0.7,2.2,1.2c0.4,0.5,0.6,1.2,0.6,2.2
v37.1c0,4.1,1.1,7.2,3.4,9.2c2.3,2,5.3,3,9,3c2.3,0,4.3-0.4,6.1-1.2c1.8-0.8,3.2-1.8,4.2-2.9c1-1.2,1.5-2.3,1.5-3.5
C91,110.5,90.9,110.1,90.7,109.9z"/>
<path class="st0" d="M114.8,32.5v78.4c0,0.9,0.2,1.6,0.7,2.1c0.5,0.5,1.1,0.9,2,1l3.1,0.6c1.3,0.3,1.9,0.9,1.9,1.6
c0,1-0.7,1.6-2.2,1.6h-19.7c-0.7,0-1.2-0.1-1.6-0.4c-0.4-0.3-0.5-0.6-0.5-1.1c0-0.4,0.2-0.7,0.5-1c0.3-0.3,0.8-0.5,1.4-0.6l3.3-0.7
c0.9-0.2,1.5-0.5,2-1c0.5-0.5,0.7-1.2,0.7-2.2V39.4c0-0.8-0.1-1.4-0.5-1.7c-0.3-0.4-0.8-0.6-1.5-0.6l-5-0.1c-0.6,0-1.1-0.2-1.4-0.4
c-0.3-0.2-0.4-0.5-0.4-0.9c0-0.4,0.1-0.7,0.4-1c0.3-0.3,0.8-0.5,1.6-0.8l8.7-2.9c1-0.4,1.8-0.6,2.5-0.8c0.7-0.2,1.2-0.2,1.7-0.2
c0.8,0,1.4,0.2,1.8,0.6C114.7,31,114.8,31.7,114.8,32.5z"/>
<path class="st0" d="M258.1,109.9c-0.2-0.3-0.5-0.4-1-0.4c-0.5,0-0.9,0.2-1.3,0.6c-0.4,0.4-0.8,0.9-1.2,1.4c-0.4,0.6-1.1,1-1.9,1.4
c-0.8,0.4-2,0.6-3.5,0.6c-2.1,0-3.7-0.7-4.9-2.1c-1.2-1.4-1.8-3.5-1.8-6.2V65.4h11.3c1.3,0,2.3-0.2,3-0.6c0.7-0.4,1-0.9,1-1.6
c0-0.5-0.2-0.8-0.5-1.1c-0.3-0.2-0.9-0.4-1.6-0.4h-13.2v-11c0-0.6-0.2-1.1-0.5-1.4c-0.3-0.3-0.7-0.5-1.3-0.5c-0.5,0-1,0.2-1.4,0.5
c-0.4,0.4-0.8,0.9-1.2,1.7l-3.1,8.3c-0.3,0.9-0.8,1.5-1.5,1.8c-0.7,0.3-1.6,0.5-2.8,0.5h-4c-0.6,0-1.1,0.1-1.4,0.4
c-0.3,0.2-0.5,0.6-0.5,1.1c0,0.4,0.2,0.7,0.5,1c0.4,0.3,1.1,0.6,2.1,0.9l3.6,0.8c1,0.3,1.8,0.7,2.2,1.2c0.4,0.5,0.6,1.2,0.6,2.2
v37.1c0,4.1,1.1,7.2,3.4,9.2c2.3,2,5.3,3,9,3c2.3,0,4.3-0.4,6.1-1.2c1.8-0.8,3.2-1.8,4.2-2.9c1-1.2,1.5-2.3,1.5-3.5
C258.4,110.5,258.3,110.1,258.1,109.9z"/>
<path class="st0" d="M407.3,76l-2-1.9l2.9-2.5c4.6-4,8.5-6.8,11.9-8.4c3.4-1.6,6.7-2.4,9.9-2.4c5,0,9,1.5,12,4.6
c3,3.1,4.5,7.3,4.5,12.7v32.5c0,1,0.3,1.8,0.8,2.4c0.5,0.6,1.3,1,2.2,1.2l2.9,0.6c0.6,0.2,1.1,0.4,1.4,0.6c0.3,0.3,0.5,0.6,0.5,1
c0,0.4-0.2,0.8-0.5,1.1c-0.3,0.3-0.9,0.4-1.6,0.4h-19.9c-1.5,0-2.2-0.5-2.2-1.6c0-0.8,0.6-1.3,1.9-1.6l3.3-0.6
c1-0.2,1.7-0.6,2.1-1.1c0.4-0.6,0.7-1.3,0.7-2.3V79.4c0-4.5-1.1-7.8-3.3-10c-2.2-2.2-5.2-3.3-8.9-3.3c-2.2,0-4.7,0.6-7.3,1.8
c-2.6,1.2-5.5,3.1-8.6,5.8L407.3,76z"/>
<path class="st0" d="M511.4,100.7c-0.2-0.4-0.6-0.5-1.1-0.5c-0.4,0-0.7,0.1-0.9,0.3c-0.3,0.2-0.5,0.6-0.8,1.2c-1,3.3-3,6-6.2,8.2
s-6.9,3.2-11.3,3.2c-6.4,0-11.5-2.2-15.5-6.5c-4-4.3-6-10.5-6-18.6h36.3c1.9,0,3.3-0.4,4.3-1.2c1-0.8,1.4-2,1.4-3.5
c0-4.4-1-8.3-2.9-11.7c-1.9-3.3-4.6-6-8-7.9c-3.4-1.9-7.4-2.9-11.9-2.9c-5.6,0-10.4,1.3-14.5,4c-4.1,2.7-7.3,6.2-9.5,10.7
c-2.2,4.5-3.4,9.6-3.4,15.2c0,5.8,1.1,10.8,3.4,15c2.3,4.3,5.4,7.6,9.6,9.9s8.9,3.5,14.4,3.5c4.2,0,7.9-0.8,11.2-2.3s6-3.6,8.1-6.2
c2.1-2.6,3.2-5.5,3.6-8.6C511.7,101.5,511.6,101,511.4,100.7z M471.8,75.5c1.5-3.5,3.6-6.2,6.4-8.2c2.7-2,5.9-3,9.5-3
c4.5,0,8.1,1.6,10.8,4.9c2.7,3.3,4.1,7.6,4.1,13c0,1.7-1,2.5-2.9,2.5h-30C469.9,81.3,470.6,78.2,471.8,75.5z"/>
<path class="st1" d="M17.4,97.3"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="277.5667" y1="76.1994" x2="294.7258" y2="150.1156">
<stop offset="0" style="stop-color:#F5C26B"/>
<stop offset="1" style="stop-color:#D59040"/>
</linearGradient>
<path class="st2" d="M532,80.7c-38.5,17.9-77.7,27-119.2,27.8c-44.6,0.9-87.5-7.8-129-16.1c-39.1-7.8-79.6-15.9-120.9-15.9
c-0.3,0-0.6,0-0.8,0c-46.7,0.1-89.8,10.9-131.8,32.9l1.9,3.5C73.5,91.2,116,80.6,162,80.5c0.3,0,0.6,0,0.8,0
c40.9,0,81.2,8.1,120.1,15.9c40,8,80.6,16.2,123.5,16.2c40.3,0,82.5-7.2,128-28.5C533.5,83,532.7,81.9,532,80.7z"/>
<linearGradient id="SVGID_00000079453371929638128150000013207070431988704682_" gradientUnits="userSpaceOnUse" x1="278.2577" y1="78.0403" x2="295.4174" y2="151.9591">
<stop offset="0" style="stop-color:#F5C26B"/>
<stop offset="1" style="stop-color:#D59040"/>
</linearGradient>
<path style="opacity:0.7;fill:url(#SVGID_00000079453371929638128150000013207070431988704682_);" d="M533,82.2
c-38.8,18.2-78.3,27.4-120.2,28.2c-44.6,0.9-87.5-7.8-129-16.1c-39.1-7.8-79.6-15.9-120.9-15.9c-0.3,0-0.6,0-0.8,0
c-46.7,0.1-89.8,10.9-131.8,32.9l1.9,3.5C73.5,93.2,116,82.6,162,82.5c0.3,0,0.6,0,0.8,0c40.9,0,81.2,8.1,120.1,15.9
c40,8,80.6,16.2,123.5,16.2c40.7,0,83.3-7.4,129.3-29.1C534.7,84.4,533.8,83.4,533,82.2z"/>
<path class="st0" d="M113.2,76l-1.9-1.9l2.9-2.5c4.6-4,8.5-6.8,11.9-8.4c3.4-1.6,6.7-2.4,10-2.4c5,0,9,1.5,12.1,4.6
c3,3.1,4.6,7.3,4.6,12.7v32.5c0,1,0.3,1.8,0.8,2.4c0.5,0.6,1.2,1,2.2,1.2l2.9,0.6c0.6,0.2,1.1,0.4,1.4,0.6c0.3,0.3,0.5,0.6,0.5,1
c0,0.4-0.2,0.8-0.5,1.1c-0.3,0.3-0.9,0.4-1.6,0.4h-19.8c-1.5,0-2.2-0.5-2.2-1.6c0-0.8,0.6-1.3,1.9-1.6l3.3-0.6
c1-0.2,1.7-0.6,2.1-1.1c0.4-0.6,0.7-1.3,0.7-2.3V79.4c0-4.5-1.1-7.8-3.4-10c-2.2-2.2-5.2-3.3-8.9-3.3c-2.2,0-4.7,0.6-7.3,1.8
c-2.6,1.2-5.5,3.1-8.7,5.8L113.2,76z"/>
<path class="st0" d="M220.9,111.7c-0.2-0.2-0.4-0.4-0.7-0.4c-0.3,0-0.6,0.1-0.8,0.3c-0.2,0.2-0.4,0.4-0.6,0.6
c-0.3,0.5-0.6,1-1.1,1.4c-0.4,0.5-1.2,0.7-2.3,0.7c-0.9,0-1.6-0.3-2.1-0.9c-0.5-0.6-0.8-1.7-0.8-3.1V76.6c0-4.8-1.5-8.6-4.6-11.5
c-3.1-2.9-7.7-4.3-14-4.3c-4.6,0-8.5,0.7-11.8,2.1c-3.3,1.4-5.8,3.2-7.6,5.5c-1.8,2.2-2.7,4.5-2.7,6.9c0,1.4,0.4,2.5,1.2,3.3
c0.8,0.8,1.9,1.3,3.3,1.3c1.6,0,2.8-0.4,3.8-1.1c0.9-0.8,1.4-1.9,1.4-3.4v-4.1c0-2.1,0.9-3.9,2.6-5.4c1.8-1.5,4.5-2.2,8.2-2.2
c3.8,0,6.7,1.1,8.8,3.2c2,2.1,3.1,5.3,3.1,9.4v15.5c-1.4-0.5-2.9-0.9-4.6-1.3c-2.4-0.6-5.1-0.8-7.9-0.8c-7.1,0-12.6,1.5-16.6,4.5
c-4,3-6,6.7-6,11.2c0,4.3,1.6,7.6,4.7,10.1c3.1,2.4,7.1,3.7,12,3.7c4.2,0,8.2-0.9,11.9-2.8c2.6-1.3,4.9-2.9,6.9-4.9
c0.1,2.5,0.8,4.4,2.2,5.6c1.5,1.4,3.6,2.1,6.3,2.1c1.8,0,3.2-0.3,4.4-1c1.2-0.7,2.1-1.5,2.7-2.5c0.6-1,0.9-2,0.9-2.9
C221.2,112.3,221.1,112,220.9,111.7z M188.9,114.8c-3.2,0-5.8-0.9-7.9-2.8c-2.1-1.8-3.1-4.5-3.1-7.9c0-3.6,1.3-6.4,3.9-8.5
c2.6-2.1,6.2-3.1,10.9-3.1c2.4,0,4.7,0.3,6.8,0.8c1.6,0.4,3.1,0.9,4.6,1.4v13.5c-1.8,1.8-3.8,3.2-6,4.3
C195.2,114.1,192.1,114.8,188.9,114.8z"/>
<path class="st0" d="M297.5,64.3c-3.2,0-5.8,0.9-7.7,2.6c-1.9,1.7-2.9,4-2.9,6.9c0,1.8,0.4,3.3,1.3,4.7c0.9,1.4,2.3,2.7,4.5,3.8
c2.1,1.1,5.1,2.2,8.9,3.3c4.9,1.2,8.8,2.8,11.7,4.6s5,3.8,6.2,6c1.2,2.2,1.8,4.6,1.8,7.3c0,4.6-1.7,8.4-5,11.3
c-3.4,2.9-8.1,4.4-14.2,4.4c-2.3,0-4.3-0.2-5.8-0.7c-1.5-0.4-2.8-0.9-3.9-1.3c-1.1-0.4-2-0.6-2.8-0.6c-0.8,0-1.3,0.2-1.7,0.7
c-0.4,0.4-0.7,0.9-1,1.3c-0.3,0.4-0.8,0.6-1.4,0.6c-0.4,0-0.7-0.1-1-0.4c-0.2-0.3-0.5-0.7-0.8-1.3l-4.8-13.2c-0.3-0.8-0.4-1.4-0.3-2
c0.1-0.6,0.5-1,1-1.2c0.6-0.2,1.1-0.2,1.5,0c0.4,0.3,0.8,0.7,1.1,1.2c1.8,3.5,3.7,6.2,5.7,8.2c2.1,2,4.3,3.3,6.6,4.1
c2.3,0.8,4.7,1.1,7.2,1.1c4.2,0,7.3-0.9,9.4-2.7c2.1-1.8,3.1-4.2,3.1-7.1c0-1.7-0.5-3.3-1.4-4.8c-0.9-1.5-2.5-2.9-4.7-4.1
c-2.3-1.3-5.4-2.5-9.5-3.5c-4.6-1.2-8.3-2.6-11-4.2c-2.7-1.6-4.7-3.5-5.9-5.7c-1.2-2.2-1.8-4.7-1.8-7.6s0.7-5.4,2.1-7.7
c1.4-2.3,3.4-4,6.1-5.3c2.6-1.3,5.8-2,9.4-2c2.3,0,4.2,0.2,5.7,0.7c1.5,0.5,2.7,1,3.7,1.4c1,0.5,1.8,0.7,2.5,0.7
c0.8,0,1.4-0.2,1.8-0.7c0.4-0.5,0.7-1,1-1.4c0.3-0.5,0.8-0.7,1.3-0.7c0.3,0,0.6,0.1,0.9,0.3c0.3,0.2,0.5,0.6,0.6,1.2l4,12.5
c0.3,0.9,0.4,1.7,0.4,2.4s-0.4,1.2-1,1.5c-0.6,0.2-1,0.1-1.5-0.2s-0.9-1-1.3-1.8c-2.1-4.4-4.8-7.6-8-9.5
C304.4,65.2,301,64.3,297.5,64.3z"/>
<path class="st0" d="M414.7,114.7l-2.9-0.6c-0.9-0.2-1.6-0.6-2.2-1.2c-0.5-0.6-0.8-1.3-0.8-2.3V78.1c0-5.4-1.5-9.6-4.5-12.7
c-3-3.1-7-4.6-12-4.6c-3.2,0-6.5,0.8-9.9,2.4c-3.2,1.5-7,4.2-11.2,7.8v-7.2c0-0.8-0.2-1.4-0.6-1.8s-1-0.6-1.8-0.6
c-0.4,0-1,0.1-1.7,0.2c-0.7,0.1-1.5,0.4-2.5,0.8l-8.7,2.9c-0.8,0.2-1.3,0.5-1.6,0.8c-0.3,0.3-0.4,0.6-0.4,1c0,0.4,0.1,0.7,0.4,0.9
c0.3,0.2,0.7,0.4,1.4,0.4l5,0.1c0.7,0,1.2,0.2,1.5,0.6c0.3,0.4,0.5,0.9,0.5,1.7v40.1c0,1-0.2,1.7-0.7,2.2c-0.5,0.5-1.1,0.8-2,1
l-3.3,0.7c-0.6,0.2-1.1,0.4-1.4,0.6c-0.3,0.3-0.5,0.6-0.5,1c0,0.4,0.2,0.8,0.5,1.1c0.4,0.3,0.9,0.4,1.6,0.4h19.7
c1.5,0,2.2-0.5,2.2-1.6c0-0.8-0.6-1.3-1.9-1.6l-3.1-0.6c-0.8-0.2-1.5-0.5-1.9-1c-0.5-0.5-0.7-1.2-0.7-2.1V74.6l1.2-1
c3.2-2.6,6-4.6,8.6-5.8c2.6-1.2,5-1.8,7.3-1.8c3.7,0,6.6,1.1,8.9,3.3s3.3,5.6,3.3,10v31.1c0,1-0.2,1.8-0.7,2.3
c-0.4,0.6-1.1,0.9-2.1,1.1l-3.3,0.6c-1.2,0.3-1.9,0.9-1.9,1.6c0,1,0.7,1.6,2.2,1.6h19.7c1.4,0,2.1-0.5,2.1-1.6
C416.5,115.6,415.9,115,414.7,114.7z"/>
<path class="st0" d="M269.5,42.7c2.2,0,3.8,0.6,5,1.7c1.1,1.1,1.7,2.6,1.7,4.3c0,1.9-0.7,3.4-2,4.6c-1.4,1.2-3,1.8-5,1.8
c-2.4,0-4.3-0.9-5.8-2.6c-1.5-1.7-2.3-4.6-2.3-8.5c0-3.8,0.8-7,2.3-9.6c1.5-2.6,3.3-4.6,5.4-5.9c2.1-1.4,3.8-2.2,5.4-2.4
c0.7-0.1,1.2-0.1,1.6,0.1c0.4,0.2,0.6,0.5,0.7,1c0,0.4-0.1,0.8-0.4,1.1c-0.3,0.4-1,0.8-2,1.2c-1.7,0.7-3.1,1.6-4.4,2.7
c-1.3,1.1-2.2,2.4-2.9,3.8c-0.7,1.4-1,2.7-1,4c0,0.9,0.2,1.6,0.7,2c0.4,0.5,1.2,0.7,2.4,0.7H269.5z"/>
<circle class="st4" cx="33.2" cy="111" r="5.2"/>
<g>
<circle class="st5" cx="553" cy="67.7" r="24.7"/>
<circle class="st5" cx="553" cy="67.7" r="17.7"/>
<circle class="st4" cx="553" cy="67.7" r="11.1"/>
</g>
<path class="st6" d="M-43.7-26.5"/>
<path class="st1" d="M46.8-46"/>
</svg>

After

Width:  |  Height:  |  Size: 9.6 KiB

View file

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 30.8.1, SVG Export Plug-In . SVG Version: 9.03 Build 0) -->
<svg version="1.0" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 595.3 149" style="enable-background:new 0 0 595.3 149;" xml:space="preserve">
<style type="text/css">
.st0{fill:#292A2B;}
.st1{fill:none;stroke:#D59040;stroke-width:4;stroke-miterlimit:10;}
.st2{opacity:0.7;fill:url(#SVGID_1_);}
.st3{opacity:0.7;fill:url(#SVGID_00000033328845987633311050000001729256314044772286_);}
.st4{fill:#F5C26B;}
.st5{opacity:0.4;fill:#D59040;}
.st6{fill:#D59040;}
</style>
<path class="st0" d="M90.7,109.9c-0.2-0.3-0.5-0.4-1-0.4c-0.5,0-0.9,0.2-1.3,0.6c-0.4,0.4-0.8,0.9-1.2,1.4c-0.4,0.6-1.1,1-1.9,1.4
c-0.8,0.4-2,0.6-3.5,0.6c-2.1,0-3.7-0.7-4.9-2.1c-1.2-1.4-1.8-3.5-1.8-6.2V65.4h11.3c1.3,0,2.3-0.2,3-0.6c0.7-0.4,1-0.9,1-1.6
c0-0.5-0.2-0.8-0.5-1.1c-0.3-0.2-0.9-0.4-1.6-0.4H75.2v-11c0-0.6-0.2-1.1-0.5-1.4C74.4,49.1,74,49,73.4,49c-0.5,0-1,0.2-1.4,0.5
c-0.4,0.4-0.8,0.9-1.2,1.7l-3.1,8.3c-0.3,0.9-0.8,1.5-1.5,1.8c-0.7,0.3-1.6,0.5-2.8,0.5h-4c-0.6,0-1.1,0.1-1.4,0.4
c-0.3,0.2-0.5,0.6-0.5,1.1c0,0.4,0.2,0.7,0.5,1c0.4,0.3,1.1,0.6,2.1,0.9l3.6,0.8c1,0.3,1.8,0.7,2.2,1.2c0.4,0.5,0.6,1.2,0.6,2.2
v37.1c0,4.1,1.1,7.2,3.4,9.2c2.3,2,5.3,3,9,3c2.3,0,4.3-0.4,6.1-1.2c1.8-0.8,3.2-1.8,4.2-2.9c1-1.2,1.5-2.3,1.5-3.5
C91,110.5,90.9,110.1,90.7,109.9z"/>
<path class="st0" d="M114.8,32.5v78.4c0,0.9,0.2,1.6,0.7,2.1c0.5,0.5,1.1,0.9,2,1l3.1,0.6c1.3,0.3,1.9,0.9,1.9,1.6
c0,1-0.7,1.6-2.2,1.6h-19.7c-0.7,0-1.2-0.1-1.6-0.4c-0.4-0.3-0.5-0.6-0.5-1.1c0-0.4,0.2-0.7,0.5-1c0.3-0.3,0.8-0.5,1.4-0.6l3.3-0.7
c0.9-0.2,1.5-0.5,2-1c0.5-0.5,0.7-1.2,0.7-2.2V39.4c0-0.8-0.1-1.4-0.5-1.7c-0.3-0.4-0.8-0.6-1.5-0.6l-5-0.1c-0.6,0-1.1-0.2-1.4-0.4
c-0.3-0.2-0.4-0.5-0.4-0.9c0-0.4,0.1-0.7,0.4-1c0.3-0.3,0.8-0.5,1.6-0.8l8.7-2.9c1-0.4,1.8-0.6,2.5-0.8c0.7-0.2,1.2-0.2,1.7-0.2
c0.8,0,1.4,0.2,1.8,0.6C114.7,31,114.8,31.7,114.8,32.5z"/>
<path class="st0" d="M258.1,109.9c-0.2-0.3-0.5-0.4-1-0.4c-0.5,0-0.9,0.2-1.3,0.6c-0.4,0.4-0.8,0.9-1.2,1.4c-0.4,0.6-1.1,1-1.9,1.4
c-0.8,0.4-2,0.6-3.5,0.6c-2.1,0-3.7-0.7-4.9-2.1c-1.2-1.4-1.8-3.5-1.8-6.2V65.4h11.3c1.3,0,2.3-0.2,3-0.6c0.7-0.4,1-0.9,1-1.6
c0-0.5-0.2-0.8-0.5-1.1c-0.3-0.2-0.9-0.4-1.6-0.4h-13.2v-11c0-0.6-0.2-1.1-0.5-1.4c-0.3-0.3-0.7-0.5-1.3-0.5c-0.5,0-1,0.2-1.4,0.5
c-0.4,0.4-0.8,0.9-1.2,1.7l-3.1,8.3c-0.3,0.9-0.8,1.5-1.5,1.8c-0.7,0.3-1.6,0.5-2.8,0.5h-4c-0.6,0-1.1,0.1-1.4,0.4
c-0.3,0.2-0.5,0.6-0.5,1.1c0,0.4,0.2,0.7,0.5,1c0.4,0.3,1.1,0.6,2.1,0.9l3.6,0.8c1,0.3,1.8,0.7,2.2,1.2c0.4,0.5,0.6,1.2,0.6,2.2
v37.1c0,4.1,1.1,7.2,3.4,9.2c2.3,2,5.3,3,9,3c2.3,0,4.3-0.4,6.1-1.2c1.8-0.8,3.2-1.8,4.2-2.9c1-1.2,1.5-2.3,1.5-3.5
C258.4,110.5,258.3,110.1,258.1,109.9z"/>
<path class="st0" d="M407.3,76l-2-1.9l2.9-2.5c4.6-4,8.5-6.8,11.9-8.4c3.4-1.6,6.7-2.4,9.9-2.4c5,0,9,1.5,12,4.6
c3,3.1,4.5,7.3,4.5,12.7v32.5c0,1,0.3,1.8,0.8,2.4c0.5,0.6,1.3,1,2.2,1.2l2.9,0.6c0.6,0.2,1.1,0.4,1.4,0.6c0.3,0.3,0.5,0.6,0.5,1
c0,0.4-0.2,0.8-0.5,1.1c-0.3,0.3-0.9,0.4-1.6,0.4h-19.9c-1.5,0-2.2-0.5-2.2-1.6c0-0.8,0.6-1.3,1.9-1.6l3.3-0.6
c1-0.2,1.7-0.6,2.1-1.1c0.4-0.6,0.7-1.3,0.7-2.3V79.4c0-4.5-1.1-7.8-3.3-10c-2.2-2.2-5.2-3.3-8.9-3.3c-2.2,0-4.7,0.6-7.3,1.8
c-2.6,1.2-5.5,3.1-8.6,5.8L407.3,76z"/>
<path class="st0" d="M511.4,100.7c-0.2-0.4-0.6-0.5-1.1-0.5c-0.4,0-0.7,0.1-0.9,0.3c-0.3,0.2-0.5,0.6-0.8,1.2c-1,3.3-3,6-6.2,8.2
s-6.9,3.2-11.3,3.2c-6.4,0-11.5-2.2-15.5-6.5c-4-4.3-6-10.5-6-18.6h36.3c1.9,0,3.3-0.4,4.3-1.2c1-0.8,1.4-2,1.4-3.5
c0-4.4-1-8.3-2.9-11.7c-1.9-3.3-4.6-6-8-7.9c-3.4-1.9-7.4-2.9-11.9-2.9c-5.6,0-10.4,1.3-14.5,4c-4.1,2.7-7.3,6.2-9.5,10.7
c-2.2,4.5-3.4,9.6-3.4,15.2c0,5.8,1.1,10.8,3.4,15c2.3,4.3,5.4,7.6,9.6,9.9s8.9,3.5,14.4,3.5c4.2,0,7.9-0.8,11.2-2.3s6-3.6,8.1-6.2
c2.1-2.6,3.2-5.5,3.6-8.6C511.7,101.5,511.6,101,511.4,100.7z M471.8,75.5c1.5-3.5,3.6-6.2,6.4-8.2c2.7-2,5.9-3,9.5-3
c4.5,0,8.1,1.6,10.8,4.9c2.7,3.3,4.1,7.6,4.1,13c0,1.7-1,2.5-2.9,2.5h-30C469.9,81.3,470.6,78.2,471.8,75.5z"/>
<path class="st1" d="M17.4,97.3"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="277.5667" y1="76.1994" x2="294.7258" y2="150.1156">
<stop offset="0" style="stop-color:#F5C26B"/>
<stop offset="1" style="stop-color:#D59040"/>
</linearGradient>
<path class="st2" d="M532,80.7c-38.5,17.9-77.7,27-119.2,27.8c-44.6,0.9-87.5-7.8-129-16.1c-39.1-7.8-79.6-15.9-120.9-15.9
c-0.3,0-0.6,0-0.8,0c-46.7,0.1-89.8,10.9-131.8,32.9l1.9,3.5C73.5,91.2,116,80.6,162,80.5c0.3,0,0.6,0,0.8,0
c40.9,0,81.2,8.1,120.1,15.9c40,8,80.6,16.2,123.5,16.2c40.3,0,82.5-7.2,128-28.5C533.5,83,532.7,81.9,532,80.7z"/>
<linearGradient id="SVGID_00000136391255565502544090000014781660229579327890_" gradientUnits="userSpaceOnUse" x1="278.2577" y1="78.0403" x2="295.4174" y2="151.9591">
<stop offset="0" style="stop-color:#F5C26B"/>
<stop offset="1" style="stop-color:#D59040"/>
</linearGradient>
<path style="opacity:0.7;fill:url(#SVGID_00000136391255565502544090000014781660229579327890_);" d="M533,82.2
c-38.8,18.2-78.3,27.4-120.2,28.2c-44.6,0.9-87.5-7.8-129-16.1c-39.1-7.8-79.6-15.9-120.9-15.9c-0.3,0-0.6,0-0.8,0
c-46.7,0.1-89.8,10.9-131.8,32.9l1.9,3.5C73.5,93.2,116,82.6,162,82.5c0.3,0,0.6,0,0.8,0c40.9,0,81.2,8.1,120.1,15.9
c40,8,80.6,16.2,123.5,16.2c40.7,0,83.3-7.4,129.3-29.1C534.7,84.4,533.8,83.4,533,82.2z"/>
<path class="st0" d="M113.2,76l-1.9-1.9l2.9-2.5c4.6-4,8.5-6.8,11.9-8.4c3.4-1.6,6.7-2.4,10-2.4c5,0,9,1.5,12.1,4.6
c3,3.1,4.6,7.3,4.6,12.7v32.5c0,1,0.3,1.8,0.8,2.4c0.5,0.6,1.2,1,2.2,1.2l2.9,0.6c0.6,0.2,1.1,0.4,1.4,0.6c0.3,0.3,0.5,0.6,0.5,1
c0,0.4-0.2,0.8-0.5,1.1c-0.3,0.3-0.9,0.4-1.6,0.4h-19.8c-1.5,0-2.2-0.5-2.2-1.6c0-0.8,0.6-1.3,1.9-1.6l3.3-0.6
c1-0.2,1.7-0.6,2.1-1.1c0.4-0.6,0.7-1.3,0.7-2.3V79.4c0-4.5-1.1-7.8-3.4-10c-2.2-2.2-5.2-3.3-8.9-3.3c-2.2,0-4.7,0.6-7.3,1.8
c-2.6,1.2-5.5,3.1-8.7,5.8L113.2,76z"/>
<path class="st0" d="M220.9,111.7c-0.2-0.2-0.4-0.4-0.7-0.4c-0.3,0-0.6,0.1-0.8,0.3c-0.2,0.2-0.4,0.4-0.6,0.6
c-0.3,0.5-0.6,1-1.1,1.4c-0.4,0.5-1.2,0.7-2.3,0.7c-0.9,0-1.6-0.3-2.1-0.9c-0.5-0.6-0.8-1.7-0.8-3.1V76.6c0-4.8-1.5-8.6-4.6-11.5
c-3.1-2.9-7.7-4.3-14-4.3c-4.6,0-8.5,0.7-11.8,2.1c-3.3,1.4-5.8,3.2-7.6,5.5c-1.8,2.2-2.7,4.5-2.7,6.9c0,1.4,0.4,2.5,1.2,3.3
c0.8,0.8,1.9,1.3,3.3,1.3c1.6,0,2.8-0.4,3.8-1.1c0.9-0.8,1.4-1.9,1.4-3.4v-4.1c0-2.1,0.9-3.9,2.6-5.4c1.8-1.5,4.5-2.2,8.2-2.2
c3.8,0,6.7,1.1,8.8,3.2c2,2.1,3.1,5.3,3.1,9.4v15.5c-1.4-0.5-2.9-0.9-4.6-1.3c-2.4-0.6-5.1-0.8-7.9-0.8c-7.1,0-12.6,1.5-16.6,4.5
c-4,3-6,6.7-6,11.2c0,4.3,1.6,7.6,4.7,10.1c3.1,2.4,7.1,3.7,12,3.7c4.2,0,8.2-0.9,11.9-2.8c2.6-1.3,4.9-2.9,6.9-4.9
c0.1,2.5,0.8,4.4,2.2,5.6c1.5,1.4,3.6,2.1,6.3,2.1c1.8,0,3.2-0.3,4.4-1c1.2-0.7,2.1-1.5,2.7-2.5c0.6-1,0.9-2,0.9-2.9
C221.2,112.3,221.1,112,220.9,111.7z M188.9,114.8c-3.2,0-5.8-0.9-7.9-2.8c-2.1-1.8-3.1-4.5-3.1-7.9c0-3.6,1.3-6.4,3.9-8.5
c2.6-2.1,6.2-3.1,10.9-3.1c2.4,0,4.7,0.3,6.8,0.8c1.6,0.4,3.1,0.9,4.6,1.4v13.5c-1.8,1.8-3.8,3.2-6,4.3
C195.2,114.1,192.1,114.8,188.9,114.8z"/>
<path class="st0" d="M297.5,64.3c-3.2,0-5.8,0.9-7.7,2.6c-1.9,1.7-2.9,4-2.9,6.9c0,1.8,0.4,3.3,1.3,4.7c0.9,1.4,2.3,2.7,4.5,3.8
c2.1,1.1,5.1,2.2,8.9,3.3c4.9,1.2,8.8,2.8,11.7,4.6s5,3.8,6.2,6c1.2,2.2,1.8,4.6,1.8,7.3c0,4.6-1.7,8.4-5,11.3
c-3.4,2.9-8.1,4.4-14.2,4.4c-2.3,0-4.3-0.2-5.8-0.7c-1.5-0.4-2.8-0.9-3.9-1.3c-1.1-0.4-2-0.6-2.8-0.6c-0.8,0-1.3,0.2-1.7,0.7
c-0.4,0.4-0.7,0.9-1,1.3c-0.3,0.4-0.8,0.6-1.4,0.6c-0.4,0-0.7-0.1-1-0.4c-0.2-0.3-0.5-0.7-0.8-1.3l-4.8-13.2c-0.3-0.8-0.4-1.4-0.3-2
c0.1-0.6,0.5-1,1-1.2c0.6-0.2,1.1-0.2,1.5,0c0.4,0.3,0.8,0.7,1.1,1.2c1.8,3.5,3.7,6.2,5.7,8.2c2.1,2,4.3,3.3,6.6,4.1
c2.3,0.8,4.7,1.1,7.2,1.1c4.2,0,7.3-0.9,9.4-2.7c2.1-1.8,3.1-4.2,3.1-7.1c0-1.7-0.5-3.3-1.4-4.8c-0.9-1.5-2.5-2.9-4.7-4.1
c-2.3-1.3-5.4-2.5-9.5-3.5c-4.6-1.2-8.3-2.6-11-4.2c-2.7-1.6-4.7-3.5-5.9-5.7c-1.2-2.2-1.8-4.7-1.8-7.6s0.7-5.4,2.1-7.7
c1.4-2.3,3.4-4,6.1-5.3c2.6-1.3,5.8-2,9.4-2c2.3,0,4.2,0.2,5.7,0.7c1.5,0.5,2.7,1,3.7,1.4c1,0.5,1.8,0.7,2.5,0.7
c0.8,0,1.4-0.2,1.8-0.7c0.4-0.5,0.7-1,1-1.4c0.3-0.5,0.8-0.7,1.3-0.7c0.3,0,0.6,0.1,0.9,0.3c0.3,0.2,0.5,0.6,0.6,1.2l4,12.5
c0.3,0.9,0.4,1.7,0.4,2.4s-0.4,1.2-1,1.5c-0.6,0.2-1,0.1-1.5-0.2s-0.9-1-1.3-1.8c-2.1-4.4-4.8-7.6-8-9.5
C304.4,65.2,301,64.3,297.5,64.3z"/>
<path class="st0" d="M414.7,114.7l-2.9-0.6c-0.9-0.2-1.6-0.6-2.2-1.2c-0.5-0.6-0.8-1.3-0.8-2.3V78.1c0-5.4-1.5-9.6-4.5-12.7
c-3-3.1-7-4.6-12-4.6c-3.2,0-6.5,0.8-9.9,2.4c-3.2,1.5-7,4.2-11.2,7.8v-7.2c0-0.8-0.2-1.4-0.6-1.8s-1-0.6-1.8-0.6
c-0.4,0-1,0.1-1.7,0.2c-0.7,0.1-1.5,0.4-2.5,0.8l-8.7,2.9c-0.8,0.2-1.3,0.5-1.6,0.8c-0.3,0.3-0.4,0.6-0.4,1c0,0.4,0.1,0.7,0.4,0.9
c0.3,0.2,0.7,0.4,1.4,0.4l5,0.1c0.7,0,1.2,0.2,1.5,0.6c0.3,0.4,0.5,0.9,0.5,1.7v40.1c0,1-0.2,1.7-0.7,2.2c-0.5,0.5-1.1,0.8-2,1
l-3.3,0.7c-0.6,0.2-1.1,0.4-1.4,0.6c-0.3,0.3-0.5,0.6-0.5,1c0,0.4,0.2,0.8,0.5,1.1c0.4,0.3,0.9,0.4,1.6,0.4h19.7
c1.5,0,2.2-0.5,2.2-1.6c0-0.8-0.6-1.3-1.9-1.6l-3.1-0.6c-0.8-0.2-1.5-0.5-1.9-1c-0.5-0.5-0.7-1.2-0.7-2.1V74.6l1.2-1
c3.2-2.6,6-4.6,8.6-5.8c2.6-1.2,5-1.8,7.3-1.8c3.7,0,6.6,1.1,8.9,3.3s3.3,5.6,3.3,10v31.1c0,1-0.2,1.8-0.7,2.3
c-0.4,0.6-1.1,0.9-2.1,1.1l-3.3,0.6c-1.2,0.3-1.9,0.9-1.9,1.6c0,1,0.7,1.6,2.2,1.6h19.7c1.4,0,2.1-0.5,2.1-1.6
C416.5,115.6,415.9,115,414.7,114.7z"/>
<path class="st0" d="M269.5,42.7c2.2,0,3.8,0.6,5,1.7c1.1,1.1,1.7,2.6,1.7,4.3c0,1.9-0.7,3.4-2,4.6c-1.4,1.2-3,1.8-5,1.8
c-2.4,0-4.3-0.9-5.8-2.6c-1.5-1.7-2.3-4.6-2.3-8.5c0-3.8,0.8-7,2.3-9.6c1.5-2.6,3.3-4.6,5.4-5.9c2.1-1.4,3.8-2.2,5.4-2.4
c0.7-0.1,1.2-0.1,1.6,0.1c0.4,0.2,0.6,0.5,0.7,1c0,0.4-0.1,0.8-0.4,1.1c-0.3,0.4-1,0.8-2,1.2c-1.7,0.7-3.1,1.6-4.4,2.7
c-1.3,1.1-2.2,2.4-2.9,3.8c-0.7,1.4-1,2.7-1,4c0,0.9,0.2,1.6,0.7,2c0.4,0.5,1.2,0.7,2.4,0.7H269.5z"/>
<circle class="st4" cx="33.2" cy="111" r="5.2"/>
<g>
<circle class="st5" cx="553" cy="67.7" r="24.7"/>
<circle class="st5" cx="553" cy="67.7" r="17.7"/>
<circle class="st6" cx="553" cy="67.7" r="11.1"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

17
dev/ticktes.md Normal file
View file

@ -0,0 +1,17 @@
Mittel: Orientierung und Klarheit
Zwei Dinge heißen "Einstellungen". Der Regler-Button unten links öffnet das Wellen-Panel mit Titel "Einstellungen". Das Benutzermenü hat einen Eintrag "Einstellungen", der ein Modal mit Titel "Allgemein" öffnet. Vorschlag: Wellen-Panel in "Darstellung" umbenennen, Modal in "Einstellungen".
Das Wellen-Panel ist ein Entwickler-Panel. Vierzehn Slider mit technischen Namen wie "Fächerbreite", "Feinheit", "Wellen-Amp" oder "Feinheit 5.0 bis 10.0". Presets, der eigentliche Einstieg für Endnutzer, stehen ganz unten. Hintergrundbilder sind Buttons mit Zahlen 1 bis 10 statt Vorschaubilder. Vorschlag: Presets und Hintergrundbilder nach oben, alle Slider unter "Erweitert" einklappen.
Tote Menüeinträge. "Plan upgraden", "Personalisierung" und das gesamte Hilfe-Untermenü in UserMenu.vue tun beim Klick nichts. Entweder ausblenden oder als "bald verfügbar" kennzeichnen. Dazu der Tippfehler "Tastaturkuerzel" und ein fest orangefarbener Avatar, der die Akzentfarbe ignoriert.
Platzhalter und wirkungslose Optionen im Einstellungs-Modal. Zwei von drei Tabs zeigen nur "Kommt bald". Die Sprachauswahl hat keine Wirkung, es gibt kein i18n im Projekt. Die FPS-Anzeige ist eine Entwickleroption unter "Allgemein". Akzentfarben heißen "Red", "Orange" in einer deutschen Oberfläche.
Farbwahl beim Emotion-Slider ist unklar. Der Button "Aus Verlauf" setzt die eigene Punktfarbe zurück, das sagt das Label nicht. "Automatisch" wäre verständlicher.
Fehlerzustand beim Speichern ohne Ausweg. "Nicht gespeichert" erscheint als 11-Pixel-Text ohne Möglichkeit, es erneut zu versuchen.
Login, Touch und Barrierefreiheit
Login-Seite mischt Sprachen: "Welcome back", "Login", "Remember me" neben deutschen Texten. Der Haken "Remember me" ist nicht angebunden, login() in auth.js:134 kennt den Wert nicht. Das Feld heißt "E-Mail", ist aber ein Dropdown.
Kontrast des Login-Buttons. Weiße Schrift auf dem Gelbgrün-Verlauf liegt weit unter dem WCAG-Mindestkontrast. Dunkle Schrift oder ein dunklerer Verlauf würden das lösen.
Touch-Ziele zu klein. Zoom-Buttons haben 28 Pixel, die Zoom-Spur ist 3 Pixel breit. Monats-Labels haben 12 Pixel bei 35 Prozent Deckkraft. Empfohlen sind 44 Pixel.
Icon-Buttons ohne Beschriftung. Header-Nutzer, Regler-Button und Plus-Button haben kein aria-label. Die Dots selbst sind gut gelöst mit role und aria-label.
Kleinigkeiten im Code: Die Klasse für ausgeblendete Dots setzt Deckkraft auf 1, die Hervorhebung beim Auswählen wirkt daher nur über die Skalierung. Der Ghost-Dot wird nie angezeigt, weil beim Anlegen sofort eine Editing-ID gesetzt ist.

View file

@ -0,0 +1,86 @@
#!/usr/bin/env python3
"""Generate the age anchor portraits for every character of a lifeline.
Base portrait: text-only (children optionally with the parents as references).
Each further anchor: references = base portrait + previous anchor, so identity
stays pinned to the base while aging progresses step by step.
Existing files are kept; delete a file to regenerate it.
"""
import json, os, subprocess, sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from gemini import generate, ROOT
lifeline = sys.argv[1]
bible = json.load(open(f'{ROOT}/backend/database/data/lifelines/characters/{lifeline}.json', encoding='utf-8'))
out_root = f'{ROOT}/backend/storage/app/private/lifeline-images/characters/{lifeline}'
PORTRAIT = bible.get('portrait', "Head-and-shoulders portrait, looking straight into the camera, neutral bright daylight, plain light wall background, plain clothing, natural skin, no retouching, no text.")
def era_for(year):
for span, desc in bible['era'].items():
a, b = map(int, span.split('-'))
if a <= year <= b: return desc
return ''
def preview(png):
subprocess.run(['php', '-r', '$im=imagecreatefromstring(file_get_contents($argv[1])); imagejpeg(imagescale($im,500),$argv[2],80);', png, png.replace('.png', '.preview.jpg')])
def run(key, c):
portrait = c.get('portrait', PORTRAIT)
d = f'{out_root}/{key}'; os.makedirs(d, exist_ok=True)
base_age = c.get('base', c['anchors'][0])
base = f'{d}/{base_age}.png'
if not os.path.exists(base):
desc = c.get('baseDescription', c['description'])
year = c['birthYear'] + base_age
prompt = f"Photo from {year} ({era_for(year)}): {portrait} {c.get('ageLabels', {}).get(str(base_age), f'A {base_age}-year-old')} named {c['name']}: {desc}"
generate(prompt, [], base, aspect='3:4'); preview(base)
print(f'{key} {base_age} (base) ok', flush=True)
prev = base
# anchors older than base, ascending; then anchors younger than base, descending
older = [a for a in c['anchors'] if a > base_age]
younger = sorted([a for a in c['anchors'] if a < base_age], reverse=True)
for seq in (older, younger):
prev = base
for age in seq:
png = f'{d}/{age}.png'
if os.path.exists(png):
prev = png; continue
year = c['birthYear'] + age
diff = age - (int(os.path.basename(prev)[:-4]))
direction = 'older' if diff > 0 else 'younger'
change = c['aging'].get(str(age), '')
if age == 0 and c.get('parents'):
parents = c.get('parents', [])
shown = 'the child of the person shown' if len(parents) == 1 else 'the child of the two people shown' if parents else ''
prompt = (f"Photo from {year}: a newborn baby a few days old, {shown}. {change}. "
f"Close-up of the baby's face wrapped in a white blanket, soft hospital light, {bible['style']}")
refs = []
for pk in parents:
pc = bible['characters'][pk]
page = year - pc['birthYear']
refs.append(f"{out_root}/{pk}/{min(pc['anchors'], key=lambda a: abs(a - page))}.png")
else:
label = c.get('ageLabels', {}).get(str(age), f"{age} years old")
prompt = (f"Photo from {year} ({era_for(year)}): {portrait} The exact same individual as in the reference photos, {c['name']}, "
f"now {label}, {abs(diff)} years {direction} than in the second reference photo. Keep every identifying feature "
f"unchanged: face shape, eyes, nose, mouth, ears and any moles, freckles or markings ({c['description']}). Age-related changes only: {change}.")
# From `adultBase` on, the identity reference is that adult anchor
# instead of the (teenage) base portrait.
ident = base
if c.get('adultBase') and age > c['adultBase'] and os.path.exists(f"{d}/{c['adultBase']}.png"):
ident = f"{d}/{c['adultBase']}.png"
refs = [ident, prev] if prev != ident else [ident]
generate(prompt, refs, png, aspect='3:4'); preview(png)
print(f'{key} {age} ok', flush=True)
prev = png
failed = []
for key, c in bible['characters'].items():
if not c.get('anchors'):
continue
try:
run(key, c)
except Exception as ex:
print(f'{key} FAILED, skipping remaining anchors of this character: {ex}', flush=True)
failed.append(key)
print('failed: ' + ', '.join(failed) if failed else 'all anchors ok')

View file

@ -0,0 +1,22 @@
#!/usr/bin/env python3
"""Build a local contact sheet (HTML) for a lifeline's generated images."""
import base64, html, json, os, sys
handle = sys.argv[1]
data = json.load(open(f'/workspace/backend/database/data/lifelines/{handle}.json', encoding='utf-8'))
d = f'/workspace/backend/storage/app/private/lifeline-images/{handle}'
MON = ['','Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez']
cards = []
for e in data['events']:
slug = f"{e['age']:02d}-{e['month']:02d}"
p = f'{d}/{slug}.preview.jpg'
year = data['person']['birthYear'] + e['age']
img = f'<img src="data:image/jpeg;base64,{base64.b64encode(open(p,"rb").read()).decode()}">' if os.path.exists(p) else '<div class="missing">kein Bild</div>'
cards.append(f'<figure><div class="img">{img}</div><figcaption><b>{slug} · {MON[e["month"]]} {year}</b> · {html.escape(e["rating"])}<br><strong>{html.escape(e["title"])}</strong><br><small>{html.escape(e["note"])}</small></figcaption></figure>')
out = f'{d}/contact-sheet.html'
open(out, 'w', encoding='utf-8').write(f'''<!doctype html><meta charset="utf-8"><title>{html.escape(data["person"]["name"])} – Kontaktbogen</title>
<style>body{{font-family:system-ui;background:#111;color:#eee;margin:0;padding:20px}}h1{{font-weight:600}}
.grid{{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:18px}}figure{{margin:0;background:#1c1c1c;border-radius:10px;overflow:hidden}}
.img{{aspect-ratio:4/3;background:#000;display:flex;align-items:center;justify-content:center}}img{{width:100%;height:100%;object-fit:contain}}
figcaption{{padding:10px 12px;font-size:13px;line-height:1.4}}small{{color:#aaa}}.missing{{color:#888}}</style>
<h1>{html.escape(data["person"]["name"])} – {len(cards)} Events</h1><div class="grid">{"".join(cards)}</div>''')
print(out)

View file

@ -0,0 +1,155 @@
#!/usr/bin/env python3
"""Generate one key image per lifeline event with Nano Banana 2, using the
character bible and age anchors as references. Skips existing files.
python3 events.py nadja # all events
python3 events.py nadja 32-05 ... # only these slugs
python3 events.py nadja --dry-run # print prompts only
"""
import json, os, subprocess, sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from gemini import generate, ROOT
lifeline = sys.argv[1]
only = {a for a in sys.argv[2:] if not a.startswith('--')}
dry = '--dry-run' in sys.argv
data = json.load(open(f'{ROOT}/backend/database/data/lifelines/{lifeline}.json', encoding='utf-8'))
bible = json.load(open(f'{ROOT}/backend/database/data/lifelines/characters/{lifeline}.json', encoding='utf-8'))
chars_dir = f'{ROOT}/backend/storage/app/private/lifeline-images/characters/{lifeline}'
out = f'{ROOT}/backend/storage/app/private/lifeline-images/{lifeline}'
os.makedirs(out, exist_ok=True)
MONTHS = ['', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
def era_for(year):
for span, desc in bible['era'].items():
a, b = map(int, span.split('-'))
if a <= year <= b: return desc
return ''
def age_of(c, year, month):
"""Age in years; month-exact when the character has a birthMonth."""
if 'birthMonth' in c:
return ((year * 12 + month) - (c['birthYear'] * 12 + c['birthMonth'])) / 12
return year - c['birthYear']
def age_label(c, age):
if age < 2 and 'birthMonth' in c:
months = round(age * 12)
return 'a newborn baby' if months < 1 else f'a baby {months} months old'
return c.get('ageLabels', {}).get(str(int(age)), f'{int(age)} years old')
def anchor_for(key, year, month, forced=None):
c = bible['characters'][key]
age = age_of(c, year, month)
nearest = forced if forced in c['anchors'] else min(c['anchors'], key=lambda a: abs(a - age))
return f'{chars_dir}/{key}/{nearest}.png', age, nearest
import re
def detect_characters(e, year, month=1):
"""Characters named in the Bildmotiv (`note`), main character always first.
A character with a `diedYear` is not placed into scenes after it."""
text = e['note']
main = bible['characters'][lifeline]
others = []
for key, c in bible['characters'].items():
if key == lifeline: continue
if c.get('diedYear') and year > c['diedYear']: continue
if year < c['birthYear']: continue
aliases = c.get('aliases', [c['name']])
if not any(re.search(r'\b' + re.escape(a) + r"(s|')?\b", text) for a in aliases):
continue
# "<Name> fotografiert ..." / "<Name> macht ein Foto ..." puts that
# person behind the camera, not in the picture (a selfie is different).
behind_camera = any(
re.search(r'\b' + re.escape(a) + r'\b[^.;]{0,30}\b(fotografiert|macht ein Foto|macht ein Familienfoto|macht ein Gruppenfoto)\b', text)
or re.search(r'\baufgenommen von [^.;]{0,25}\b' + re.escape(a) + r'\b', text)
for a in aliases) and 'Selfie' not in text
if not behind_camera:
others.append(key)
# The main character is in the picture unless the motif is explicitly a
# photo *of* someone else ("Ein Selfie von Emil ...", "Ein Foto von Petra
# mit Clara", "Nina fotografiert Clara", a video-call screenshot of Daniel).
main_named = any(re.search(r'\b' + re.escape(a) + r"(s|')?\b", text) for a in main.get('aliases', [main['name']]))
other_names = [a for k in others for a in bible['characters'][k].get('aliases', [bible['characters'][k]['name']])]
photo_of_other = other_names and re.match(
r'^(Ein|Eine|Ein letztes|Ein altes)?\s*(Selfie|Foto|Handyfoto|Video-Standbild|Videocall-Screenshot|Video-Chat-Screenshot|Screenshot|Selfie-Video-Standbild)[^,.]*?\b(von|zeigt|zeigt einen|zeigt eine|mit)\s+(einen |eine |einem |sichtlich |erleichterten |besorgten )?(' + '|'.join(map(re.escape, other_names)) + r')\b', text)
photographer_of_other = other_names and re.match(r'^\w+ fotografiert (' + '|'.join(map(re.escape, other_names)) + r')\b', text)
# "beide" / "zu zweit" / "das Paar" without a name means the partner of
# that period; "Familie" means partner plus the children already born.
ym = f'{year:04d}-{month:02d}'
if re.search(r'\b(beide|zu zweit|Paar\w*|Familie\w*)\b', text):
for p in bible.get('partners', []):
if p['from'] <= ym <= p.get('to', '9999-12') and p['key'] not in others:
others.append(p['key'])
if re.search(r'\bFamilie\w*', text):
for k in bible.get('family', []):
c = bible['characters'][k]
if k not in others and year >= c['birthYear'] and not (c.get('diedYear') and year > c['diedYear']):
others.append(k)
# A band lifeline: "die Band" / "die vier" means all members of that period.
if bible.get('band') and re.search(r'\b(Band|die vier|alle vier|Nachtschicht|alle)\b', text):
for k in bible['band'] + [d['key'] for d in bible.get('bandDrummer', []) if d.get('from', '0000-00') <= ym <= d.get('to', '9999-12')]:
if k not in others:
others.append(k)
if not main.get('anchors'):
return others
if main_named or not (photo_of_other or photographer_of_other):
return [lifeline] + others
return others
def year_month_age(c, year, month):
return age_of(c, year, month)
def scene_for(e):
if e.get('imagePrompt'): return e['imagePrompt']
# "Heinz fotografiert das Auto, ..." -> the photographer is named separately
# so the model does not paint a person holding a camera into the scene.
m = re.match(r'^((?:Ein|Eine|Der|Die)\s+)?([\wäöüÄÖÜß]+(?:\s[\wäöüÄÖÜß]+)?) (fotografiert|macht ein Foto von|macht ein Familienfoto von|macht ein Gruppenfoto von) (.+)$', e['note'], re.S)
if m and e.get('photo') != 'Selfie':
who, rest = (m.group(1) or '') + m.group(2), m.group(4)
return (f"Photo taken by {who}, who is behind the camera and NOT visible in the picture. "
f"The following German description defines exactly what the picture shows: \"{rest}\"")
return (f"The following German description of the photo motif defines the scene exactly, including who took the photo "
f"(a photographer named in the description is not in the picture unless it is a selfie): \"{e['note']}\"")
def build(e):
year = data['person']['birthYear'] + e['age']
keys = e['imageCharacters'] if e.get('imageCharacters') is not None else detect_characters(e, year, e['month'])
refs, people = [], []
for i, k in enumerate(keys, 1):
path, age, nearest = anchor_for(k, year, e['month'], e.get('imageAnchorAges', {}).get(k))
c = bible['characters'][k]
aging = c['aging'].get(str(max((a for a in c['anchors'] if a <= age), default=nearest)), '')
refs.append(path)
people.append(f"Reference photo {i} is {c['name']}, now {age_label(c, age)} ({c['description']} {aging}).")
kind = ("Smartphone selfie taken at arm's length with the front camera: slight wide-angle distortion, the people close to the lens, one arm reaching out of frame; the phone itself is never visible in the picture."
if e.get('photo') == 'Selfie' else
"Candid photo taken by another person who stands behind the camera and is NOT visible in the picture: nobody in the picture holds a camera or a phone, no arm or hand with a camera in the foreground. Natural framing, subjects not posing stiffly.")
prompt = (f"Photo from {MONTHS[e['month']]} {year}, {era_for(year)}. {kind} Scene: {scene_for(e)}. "
f"{' '.join(people)} Every individual must match its reference photo exactly (same face shape, eyes, nose, mouth, hair or coat colour, distinguishing marks), "
f"only clothing, expression, pose and setting change. Clothing must NOT be copied from the reference photos: it changes from photo to photo and suits the scene and season. "
f"{bible.get('familyNote', '')} No other recognisable people in focus. No date stamp or printed date on the photo. {bible['style']}")
return prompt, refs
done = skipped = failed = 0
for e in data['events']:
slug = f"{e['age']:02d}-{e['month']:02d}"
if only and slug not in only: continue
png = f'{out}/{slug}.png'
if os.path.exists(png) and not dry:
skipped += 1; continue
prompt, refs = build(e)
if dry:
print(f'--- {slug} {e["title"]} refs: {[os.path.relpath(r, chars_dir) for r in refs]}'); continue
try:
generate(prompt, refs, png, aspect=e.get('imageAspect') or ('3:4' if e.get('photo') == 'Selfie' else '4:3'))
subprocess.run(['php', '-r', '$im=imagecreatefromstring(file_get_contents($argv[1])); imagejpeg(imagescale($im,700),$argv[2],80);', png, f'{out}/{slug}.preview.jpg'])
json.dump({'prompt': prompt, 'refs': refs, 'model': os.environ.get('LIFELINE_IMAGE_MODEL', 'gemini-3.1-flash-image')}, open(f'{out}/{slug}.json', 'w'), indent=1)
print(f'{slug} ok {e["title"]}', flush=True); done += 1
except Exception as ex:
print(f'{slug} FAILED {ex}', flush=True); failed += 1
if not dry: print(f'done={done} skipped={skipped} failed={failed}')

View file

@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""Minimal Gemini image client (Nano Banana 2) – REST only, no SDK.
Reads GOOGLE_API_KEY from backend/.env. Usage as a module:
from gemini import generate
generate(prompt, refs=[path,...], out='x.png', aspect='4:3')
"""
import base64, json, os, re, sys, time, urllib.request, urllib.error
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
MODEL = os.environ.get('LIFELINE_IMAGE_MODEL', 'gemini-3.1-flash-image')
def api_key():
for line in open(os.path.join(ROOT, 'backend', '.env')):
m = re.match(r'^GOOGLE_API_KEY=(.*)$', line.strip())
if m:
return m.group(1).strip().strip('"').strip("'")
sys.exit('GOOGLE_API_KEY missing in backend/.env')
def _mime(path):
with open(path, 'rb') as f:
head = f.read(8)
return 'image/png' if head.startswith(b'\x89PNG') else 'image/jpeg'
def generate(prompt, refs=(), out=None, aspect='4:3', size='1K', retries=3):
parts = []
for p in refs:
parts.append({'inline_data': {'mime_type': _mime(p), 'data': base64.b64encode(open(p, 'rb').read()).decode()}})
parts.append({'text': prompt})
body = {
'contents': [{'role': 'user', 'parts': parts}],
'generationConfig': {'responseModalities': ['IMAGE'], 'imageConfig': {'aspectRatio': aspect, 'imageSize': size}},
}
req = urllib.request.Request(
f'https://generativelanguage.googleapis.com/v1beta/models/{MODEL}:generateContent',
data=json.dumps(body).encode(), method='POST',
headers={'Content-Type': 'application/json', 'x-goog-api-key': api_key()},
)
for attempt in range(retries):
try:
with urllib.request.urlopen(req, timeout=180) as r:
res = json.load(r)
except urllib.error.HTTPError as e:
msg = e.read().decode()[:400]
if e.code in (429, 500, 503) and attempt < retries - 1:
time.sleep(10 * (attempt + 1)); continue
raise RuntimeError(f'HTTP {e.code}: {msg}')
cands = res.get('candidates') or []
for part in (cands[0].get('content', {}).get('parts', []) if cands else []):
data = part.get('inlineData') or part.get('inline_data')
if data:
raw = base64.b64decode(data['data'])
if out:
open(out, 'wb').write(raw)
return raw
reason = (cands[0].get('finishReason') if cands else None) or res.get('promptFeedback')
if attempt < retries - 1:
time.sleep(5); continue
raise RuntimeError(f'no image returned: {reason} {json.dumps(res)[:300]}')
if __name__ == '__main__':
import argparse
a = argparse.ArgumentParser()
a.add_argument('prompt'); a.add_argument('--ref', action='append', default=[]); a.add_argument('--out', required=True)
a.add_argument('--aspect', default='4:3'); a.add_argument('--size', default='1K')
ns = a.parse_args()
generate(ns.prompt, ns.ref, ns.out, ns.aspect, ns.size); print(ns.out)

View file

@ -0,0 +1,17 @@
#!/usr/bin/env python3
"""Build 4x3 review montages (m1.jpg, m2.jpg, ...) of a lifeline's preview images."""
import json, os, subprocess, sys
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
handle = sys.argv[1]
cols = int(sys.argv[2]) if len(sys.argv) > 2 else 4
rows = int(sys.argv[3]) if len(sys.argv) > 3 else 3
per = cols * rows
d = json.load(open(f'{ROOT}/backend/database/data/lifelines/{handle}.json', encoding='utf-8'))
out = f'{ROOT}/backend/storage/app/private/lifeline-images/{handle}'
slugs = [f"{e['age']:02d}-{e['month']:02d}" for e in d['events'] if os.path.exists(f"{out}/{e['age']:02d}-{e['month']:02d}.preview.jpg")]
php = '''$slugs=json_decode($argv[1]);$cols=(int)$argv[3];$rows=(int)$argv[4];$w=(int)(1400/$cols);$h=(int)($w*0.85);$c=imagecreatetruecolor($w*$cols,$h*$rows);imagefill($c,0,0,0x202020);
foreach($slugs as $i=>$s){$im=imagecreatefromjpeg("$s.preview.jpg");$sw=imagesx($im);$sh=imagesy($im);$k=min($w/$sw,$h/$sh);$dw=(int)($sw*$k);$dh=(int)($sh*$k);imagecopyresampled($c,$im,($i%$cols)*$w+(int)(($w-$dw)/2),intdiv($i,$cols)*$h+(int)(($h-$dh)/2),0,0,$dw,$dh,$sw,$sh);imagestring($c,5,($i%$cols)*$w+6,intdiv($i,$cols)*$h+4,$s,0xFFFF00);}
imagejpeg($c,$argv[2],76);'''
for n in range(0, len(slugs), per):
subprocess.run(['php', '-r', php, json.dumps(slugs[n:n+per]), f'{out}/m{n//per+1:02d}.jpg', str(cols), str(rows)], cwd=out)
print(f'{(len(slugs)+per-1)//per} montages for {len(slugs)} images')