API System

JSON-Schnittstellen für Android/iOS Apps und externe Plattform-Integrationen.

6 Endpunkte · 4 KI-Prompts · CORS-fähig · Kein Auth nötig · Multi-Hoster Streaming

Beiträge

GET public_api.php?action=get_posts

Haupt-Endpunkt zum Abrufen des Viral-Feeds. Unterstützt Paginierung und Filterung nach Inhaltstyp. Bilder-Pfade werden automatisch in gültige absolute URLs umgewandelt.

ParameterTypBeschreibung
limit
(optional)
IntegerMaximale Anzahl Posts (Standard: 50, Maximum: 100).
offset
(optional)
IntegerOffset für Paginierung / Infinite Scrolling.
type
(optional)
StringFilter: image, video, audio, meme, movie, quote, link, nsfw.

Response Beispiel:

{
  "success": true,
  "data": [
    {
      "id": 4,
      "type": "movie",
      "title": "The Matrix",
      "content": "Ein Computerhacker erfährt von mysteriösen Rebellen...",
      "media_path": "https://deine-domain.de/uploads/posters/abc123.jpg",
      "embed_url": "[\"https://voe.sx/e/abc123\",\"https://streamtape.com/e/xyz789\"]",
      "embed_urls": [
        "https://voe.sx/e/abc123",
        "https://streamtape.com/e/xyz789"
      ],
      "tmdb_id": 603,
      "is_nsfw": 0,
      "likes": 42,
      "created_at": "2026-04-08 15:42:10"
    }
  ]
}
Endpunkt testen →
GET public_api.php?action=get_post

Ruft die gesamten Details eines einzelnen Beitrags ab.

ParameterTypBeschreibung
id
(erforderlich)
IntegerDie eindeutige Datenbank-ID des Beitrags.
Endpunkt testen →

Darsteller

GET public_api.php?action=get_actors

Liste aller Darsteller, sortiert nach TMDB-Popularität. Unterstützt Namenssuche und Paginierung.

ParameterTypBeschreibung
limit
(optional)
IntegerAnzahl der Darsteller (Standard: 50, Max: 100).
offset
(optional)
IntegerOffset für Paginierung.
search
(optional)
StringSuche nach Name (LIKE-Suche).

Response Beispiel:

{
  "success": true,
  "data": [
    {
      "id": 1,
      "tmdb_id": 287,
      "name": "Brad Pitt",
      "profile_path": "https://image.tmdb.org/t/p/w500/...",
      "biography": "...",
      "birthday": "1963-12-18",
      "deathday": null,
      "place_of_birth": "Shawnee, Oklahoma, USA",
      "known_for_department": "Acting",
      "popularity": 45.2,
      "created_at": "2026-04-08 17:30:00"
    }
  ]
}
Endpunkt testen →
GET public_api.php?action=get_actor

Detaillierte Informationen zu einem einzelnen Darsteller inkl. Biografie, Geburts-/Sterbedatum, Geburtsort.

ParameterTypBeschreibung
id
(erforderlich)
IntegerDie Datenbank-ID des Darstellers.
Endpunkt testen →

Film ↔ Darsteller

GET public_api.php?action=get_movie_cast

Gibt alle Darsteller eines Films zurück, inklusive Rollenname (character_name) und Reihenfolge. Nutzt die TMDB Film-ID.

ParameterTypBeschreibung
tmdb_id
(erforderlich)
IntegerDie TMDB Film-ID (z.B. 603 für The Matrix).

Response Beispiel:

{
  "success": true,
  "data": [
    {
      "id": 5,
      "tmdb_id": 6384,
      "name": "Keanu Reeves",
      "profile_path": "https://image.tmdb.org/t/p/w500/...",
      "birthday": "1964-09-02",
      "deathday": null,
      "character_name": "Thomas A. Anderson / Neo",
      "cast_order": 0
    }
  ]
}
GET public_api.php?action=get_actor_movies

Gibt alle Filme/Beiträge zurück, in denen ein bestimmter Darsteller mitwirkt. Enthält den zugehörigen Beitrag mit Poster-URL und den Rollennamen.

ParameterTypBeschreibung
id
(erforderlich)
IntegerDie Datenbank-ID des Darstellers.

Response Beispiel:

{
  "success": true,
  "data": [
    {
      "post": {
        "id": 4,
        "type": "movie",
        "title": "The Matrix",
        "media_path": "https://deine-domain.de/uploads/posters/abc123.jpg",
        "embed_url": "[\"https://voe.sx/e/abc123\"]",
        "embed_urls": ["https://voe.sx/e/abc123"],
        "tmdb_id": 603
      },
      "character_name": "Thomas A. Anderson / Neo",
      "cast_order": 0
    }
  ]
}

KI-gestützte App-Erstellung

Kopiere einen der folgenden Prompts, um sofort eine App oder Integration mit dieser API zu erstellen.

PROMPT Antigravity (Agentic Coding)

Diesen Prompt kannst du direkt in Antigravity (oder einen vergleichbaren KI-Coding-Agenten) einfügen, um eine vollständige Web-App zu erstellen.

Erstelle eine moderne, responsive Web-App (Single Page Application) die den ViralFeed API-Server konsumiert.

## API Basis-URL
https://viral.xdoco.com//public_api.php

## Verfügbare Endpunkte

1. GET ?action=get_posts
   - Parameter: limit (int, max 100), offset (int), type (string: image|video|audio|quote|link|meme|movie|nsfw)
   - Response: { success: true, data: [{ id, type, title, content, media_path, embed_url (JSON string), embed_urls (Array von Streaming-URLs, z.B. ["https://voe.sx/e/...","https://streamtape.com/e/..."]), tmdb_id, is_nsfw, likes, created_at }] }

2. GET ?action=get_post&id={id}
   - Response: { success: true, data: { id, type, title, content, media_path, embed_url, embed_urls, tmdb_id, is_nsfw, likes, created_at } }

3. GET ?action=get_actors
   - Parameter: limit (int), offset (int), search (string)
   - Response: { success: true, data: [{ id, tmdb_id, name, profile_path, biography, birthday, deathday, place_of_birth, known_for_department, popularity }] }

4. GET ?action=get_actor&id={id}
   - Response: { success: true, data: { ...vollständiges Darsteller-Objekt... } }

5. GET ?action=get_movie_cast&tmdb_id={tmdb_id}
   - Gibt alle Darsteller eines Films zurück, inkl. character_name und cast_order
   - Response: { success: true, data: [{ id, tmdb_id, name, profile_path, birthday, deathday, character_name, cast_order, ... }] }

6. GET ?action=get_actor_movies&id={id}
   - Gibt alle Filme/Beiträge zurück, in denen ein Darsteller mitwirkt
   - Response: { success: true, data: [{ post: { id, title, media_path, embed_urls, tmdb_id, ... }, character_name, cast_order }] }

## Streaming / Embed-URLs
- Filme können bis zu 5 Streaming-URLs von verschiedenen Hostern enthalten (VOE, Streamtape, gDrive, DoodStream, Vidoza, Filemoon, Mixdrop, etc.)
- Das Feld `embed_urls` ist ein Array mit allen hinterlegten Streaming-URLs für den jeweiligen Film.
- Der Hoster kann automatisch aus der URL erkannt werden (z.B. "voe.sx" → VOE, "streamtape.com" → Streamtape, "drive.google.com" → gDrive).
- In der App: Zeige pro Film je einen Play-Button je Hoster. Beim Klick öffne die URL in einem iframe (WebView) oder externem Browser.

## Anforderungen
- Erstelle ein modernes, dunkles UI-Design mit Glassmorphismus-Effekten und sanften Animationen.
- Haupt-Feed mit Infinite Scrolling für Posts.
- Bei Film-Posts (type=movie): Zeige die Top 7 Darsteller als klickbare Kreisbilder unter dem Poster (via get_movie_cast mit der tmdb_id des Films).
- Bei Film-Posts mit embed_urls: Zeige für jede URL einen farbigen Play-Button mit dem erkannten Hoster-Namen (VOE=Indigo, Streamtape=Rot, gDrive=Grün, DoodStream=Amber, Vidoza=Blau, Filemoon=Lila, Mixdrop=Teal). Beim Klick öffne den Stream in einem Popup-Modal mit iframe.
- Eigene Seite für die Darsteller-Datenbank mit A-Z Alphabet-Navigation.
- Darsteller sollen als Grid von Profil-Karten dargestellt werden.
- Verstorbene Darsteller (deathday != null): Zeige ein ✝-Symbol und das Sterbedatum.
- Detailansicht für Darsteller mit Biografie, Geburts-/Sterbedatum, Geburtsort, Popularität.
- In der Darsteller-Detailansicht: Zeige Filmografie (get_actor_movies) als horizontale Poster-Scroll-Leiste mit Rollenname.
- Rendere media_path-URLs als Bilder, Videos oder Audio-Player je nach Typ.
- NSFW-Inhalte (is_nsfw=1) sollen initial geblurred sein mit einem "Inhalt anzeigen"-Overlay.
- Zeige Like-Zähler an jedem Beitrag.
- Filme (type=movie) sollen als Card mit Poster-Bild dargestellt werden.
- Zitate (type=quote) sollen in einem stylischen Blockquote-Design gerendert werden.
- Die App muss vollständig responsive sein (Mobile-first).
- Nutze CORS-kompatible fetch()-Aufrufe. Die API erlaubt Cross-Origin-Requests.
PROMPT Gemini Pro in Canvas

Diesen Prompt kannst du in Google Gemini Pro (Canvas-Modus) einfügen, um eine interaktive Web-Oberfläche als Canvas-Artifact zu generieren.

Erstelle mir eine komplette, interaktive HTML/CSS/JS Web-App als Canvas-Artifact, die den folgenden JSON-API-Server konsumiert und einen modernen Content-Feed mit Darsteller-Datenbank darstellt.

## API Endpunkt (CORS-fähig, kein Auth nötig)
Basis-URL: https://viral.xdoco.com//public_api.php

### Posts laden:
GET ?action=get_posts&limit=20&offset=0&type=image
Response: { "success": true, "data": [{ "id": int, "type": string, "title": string, "content": string, "media_path": string, "embed_url": string (JSON), "embed_urls": string[] (Array von Streaming-URLs), "tmdb_id": int|null, "is_nsfw": int (0/1), "likes": int, "created_at": string }] }

### Einzelnen Post laden:
GET ?action=get_post&id=1

### Darsteller laden:
GET ?action=get_actors&limit=20&search=brad
Response: { "success": true, "data": [{ "id": int, "tmdb_id": int, "name": string, "profile_path": string, "biography": string, "birthday": string, "deathday": string|null, "place_of_birth": string, "known_for_department": string, "popularity": float }] }

### Einzelnen Darsteller laden:
GET ?action=get_actor&id=1

### Film-Besetzung laden:
GET ?action=get_movie_cast&tmdb_id=603
Response: { "success": true, "data": [{ ...alle Actor-Felder..., "character_name": string, "cast_order": int }] }

### Filmografie eines Darstellers:
GET ?action=get_actor_movies&id=1
Response: { "success": true, "data": [{ "post": { "title": string, "media_path": string, "embed_urls": string[], ... }, "character_name": string, "cast_order": int }] }

## Design-Vorgaben
- Dunkles, modernes Design (Background: #0f172a, Cards: #1e293b)
- Schriftart: Google Fonts "Outfit"
- Gradient-Akzente in Lila (#8b5cf6) und Pink (#ec4899)
- Glassmorphismus-Cards mit border-radius: 1rem und subtilen Border-Effekten
- Haupt-Feed für Posts mit Filter-Chips (Typ-Filterung)
- Bei Film-Posts: Top 7 Darsteller als klickbare Kreisbilder unter dem Poster (via get_movie_cast)
- Bei Film-Posts mit embed_urls: Zeige für jede URL einen farbigen Play-Button mit erkanntem Hoster-Namen (VOE, Streamtape, gDrive, etc.). Beim Klick öffne den Stream in einem Popup-Modal mit iframe (16:9 Aspect Ratio).
- Separate Sektion für Darsteller mit A-Z Alphabet-Navigation
- Verstorbene Darsteller: ✝-Symbol und rotes Badge mit Sterbedatum anzeigen
- Darsteller-Detail-Modal mit: Biografie, Geburts-/Sterbedatum, Geburtsort, Filmografie (get_actor_movies als horizontale Poster-Leiste)
- "Mehr laden"-Button am Ende für Pagination via offset
- Responsive Grid/Feed-Layout
- Bilder als <img>, Videos als <video>, Audio als <audio> rendern
- NSFW-Posts: geblurrt mit Overlay
- Alles in einer einzigen HTML-Datei (inline CSS + JS), kein Framework nötig
ANDROID Android Studio – Native App

Erstelle eine vollständige native Android-App in Kotlin/Jetpack Compose. Vor dem Prompt findest du eine Kurzanleitung zur Projekt-Einrichtung.

⚙️ Android Studio – Projekt einrichten

  1. Öffne Android StudioFile → New → New Project
  2. Wähle "Empty Activity" (Compose) als Template
  3. Vergib als Package-Name z.B. com.viralfeed.app
  4. Setze Minimum SDK auf API 26 (Android 8.0)
  5. Sprache: Kotlin, Build: Kotlin DSL (build.gradle.kts)
  6. Klicke Finish und warte bis der Gradle-Sync abgeschlossen ist
  7. Kopiere den Prompt unten und füge ihn in Gemini in Android Studio (oder Antigravity) ein
  8. Alle generierten Dateien können direkt überschrieben werden
Ich bin ein Senior Android Developer. Erstelle mir eine vollständige, produktionsreife native Android-App in Kotlin mit Jetpack Compose, die die folgende REST-API konsumiert.

WICHTIG: Erstelle ALLE Dateien die für das Android Studio Projekt benötigt werden KOMPLETT und VOLLSTÄNDIG.

Package-Name: com.viralfeed.app

## API Server (CORS-fähig, kein Auth, reines JSON)
Basis-URL: https://viral.xdoco.com//public_api.php

### Endpunkte:

1. GET ?action=get_posts&limit={limit}&offset={offset}&type={type}
   Response: { "success": true, "data": [{ "id": int, "type": string, "title": string, "content": string, "media_path": string (absolute URL), "embed_url": string (JSON), "embed_urls": string[] (Streaming-URLs), "tmdb_id": int|null, "is_nsfw": int (0/1), "likes": int, "created_at": string }] }
   Mögliche types: image, video, audio, quote, link, meme, movie, nsfw

2. GET ?action=get_post&id={id}

3. GET ?action=get_actors&limit={limit}&offset={offset}&search={query}
   Response: { "success": true, "data": [{ "id": int, "tmdb_id": int, "name": string, "profile_path": string, "biography": string, "birthday": string, "deathday": string|null, "place_of_birth": string, "known_for_department": string, "popularity": float }] }

4. GET ?action=get_actor&id={id}

5. GET ?action=get_movie_cast&tmdb_id={tmdb_id}
   Response: { "success": true, "data": [{ ...alle Actor-Felder..., "character_name": string, "cast_order": int }] }

6. GET ?action=get_actor_movies&id={id}
   Response: { "success": true, "data": [{ "post": { "id": int, "title": string, "media_path": string, "embed_urls": string[], "tmdb_id": int }, "character_name": string, "cast_order": int }] }

## Architektur & Tech-Stack:
- MVVM Architecture (ViewModel + Repository Pattern)
- Jetpack Compose für die gesamte UI
- Retrofit2 + OkHttp für Netzwerk-Requests
- Coil für asynchrones Image Loading
- Jetpack Navigation Compose (Bottom Navigation: Feed, Darsteller)
- Material3 Design mit dunklem Theme
- Kotlin Coroutines + Flow für asynchrone Datenströme

## App-Screens & Features:

### 1. Feed Screen (Hauptseite)
- LazyColumn mit Infinite Scrolling (offset-basierte Pagination)
- Filter-Chips oben: Alle, Bilder, Videos, Audio, Memes, Filme, Zitate, Links, NSFW
- Jede Card zeigt: Typ-Badge, Titel, Datum, Like-Count mit Herz-Icon
- media_path als AsyncImage (Coil) für Bilder/Memes/Movie-Poster
- Bei Film-Posts: Top 7 Darsteller als klickbare kreisförmige Profilbilder unter dem Poster (via get_movie_cast mit tmdb_id). Klick auf Darsteller öffnet Darsteller-Detail.
- Bei Film-Posts mit embed_urls: Zeige für jede URL einen farbigen Button mit Hoster-Namen (VOE=Indigo, Streamtape=Rot, gDrive=Grün, etc.). Beim Klick öffne die URL in einem WebView-Dialog oder Custom Chrome Tab.
- NSFW-Posts: Geblurrtes Bild mit Overlay-Button "Inhalt anzeigen"
- Pull-to-Refresh

### 2. Darsteller Screen (Bottom Navigation Tab)
- A-Z Alphabet-Navigation oben (Sticky, horizontal scrollbar)
- Grid-Ansicht aller Darsteller, gefiltert nach Anfangsbuchstabe
- Echtzeit-Suche über Suchfeld
- Verstorbene Darsteller: ✝-Symbol auf dem Bild + rotes Badge mit Sterbedatum
- Klick öffnet Darsteller-Detail

### 3. Darsteller-Detail Screen
- Profilbild, Name, Abteilung (Tag)
- Geburtsdatum mit Altersberechnung (bei Verstorbenen: "wurde X Jahre")
- Sterbedatum in Rot wenn verstorben
- Geburtsort
- Popularitäts-Wert
- Biografie-Text
- Filmografie-Sektion: Horizontale LazyRow mit Film-Postern + Rollenname (via get_actor_movies)
- Share-Button (Android Share Intent)

## Design-Vorgaben:
- Dark Theme als Standard
- Primary Color: #8B5CF6 (Lila)
- Secondary Color: #EC4899 (Pink)  
- Background: #0F172A
- Surface/Card: #1E293B
- Verstorbene Darsteller: Rot (#F87171) für Sterbedatum
- Abgerundete Cards (16.dp)
- Subtile Elevation und Border-Effekte
- Smooth Animations bei Listenelementen

Erstelle jede einzelne Datei separat mit vollem Inhalt und dem korrekten relativen Pfad im Projekt.
STANDALONE Mini TMDB – Single-File PHP

Erstellt ein eigenständiges PHP-Skript, das ohne das Hauptsystem direkt auf die gespeicherten SQLite-Datenbanken zugreift und eine eigene Film- & Darsteller-Seite rendert. Einfach die generierte Datei in denselben Ordner legen.

📁 Voraussetzungen

  • Die generierte PHP-Datei muss im selben Verzeichnis wie die SQLite-Dateien liegen
  • Benötigte Dateien: database.sqlite und actors.sqlite
  • Kein API-Key, kein Auth, keine weiteren Dependencies nötig
  • Funktioniert komplett unabhängig vom ViralFeed-Hauptsystem
Erstelle ein einzelnes, komplett eigenständiges PHP-Skript (Single-File, z.B. "mini_tmdb.php"), das direkt auf bestehende SQLite-Datenbanken zugreift und eine eigene Film- und Darsteller-Browsing-Seite rendert – komplett unabhängig vom Hauptsystem.

## Ziel
Eine Mini-TMDB-Seite als einzelne PHP-Datei, die Filme/Serien und Darsteller aus den vorhandenen SQLite-Datenbanken liest und als moderne, durchsuchbare Webseite darstellt. Kein API-Server nötig, kein Auth, keine externen Dependencies.

## Datenbank-Dateien (im selben Verzeichnis)

### 1. database.sqlite
Tabelle `posts`:
- id INTEGER PRIMARY KEY AUTOINCREMENT
- type TEXT (relevante Werte: "movie")
- title TEXT (Filmtitel)
- content TEXT (Beschreibungstext)
- media_path TEXT (Poster-URL, z.B. "uploads/posters/abc123.jpg" oder externe URL)
- embed_url TEXT (JSON-Array mit bis zu 5 Streaming-URLs, z.B. '["https://voe.sx/e/abc","https://streamtape.com/e/xyz"]')
- tmdb_id INTEGER (TMDB Film-ID)
- is_nsfw INTEGER (0 oder 1)
- likes INTEGER
- created_at DATETIME

### 2. actors.sqlite
Tabelle `actors`:
- id INTEGER PRIMARY KEY AUTOINCREMENT
- tmdb_id INTEGER UNIQUE
- name TEXT NOT NULL
- profile_path TEXT (URL zum Profilbild)
- biography TEXT
- birthday TEXT (Format: YYYY-MM-DD)
- deathday TEXT (Format: YYYY-MM-DD, NULL wenn lebend)
- place_of_birth TEXT
- known_for_department TEXT (z.B. "Acting")
- popularity REAL
- created_at DATETIME

Tabelle `movie_actors` (Junction-Tabelle, verknüpft Filme mit Darstellern):
- id INTEGER PRIMARY KEY AUTOINCREMENT
- movie_tmdb_id INTEGER NOT NULL (bezieht sich auf posts.tmdb_id)
- actor_tmdb_id INTEGER NOT NULL (bezieht sich auf actors.tmdb_id)
- character_name TEXT (Rollenname)
- cast_order INTEGER DEFAULT 0 (Reihenfolge der Besetzung)
- UNIQUE(movie_tmdb_id, actor_tmdb_id)

## PHP Datenbank-Zugriff
```php
$db = new PDO('sqlite:' . __DIR__ . '/database.sqlite');
$actorsDb = new PDO('sqlite:' . __DIR__ . '/actors.sqlite');
```

## Wichtige SQL-Abfragen

Alle Filme laden:
SELECT * FROM posts WHERE type = 'movie' ORDER BY created_at DESC

Alle Darsteller laden:
SELECT * FROM actors ORDER BY popularity DESC

Darsteller eines Films (via tmdb_id des Films):
SELECT a.*, ma.character_name, ma.cast_order 
FROM movie_actors ma 
JOIN actors a ON a.tmdb_id = ma.actor_tmdb_id 
WHERE ma.movie_tmdb_id = ? 
ORDER BY ma.cast_order ASC

Filme eines Darstellers (via tmdb_id des Actors):
SELECT p.*, ma.character_name, ma.cast_order 
FROM movie_actors ma 
JOIN posts p ON p.tmdb_id = ma.movie_tmdb_id AND p.type = 'movie'
WHERE ma.actor_tmdb_id = ? 
ORDER BY ma.cast_order ASC

## Anforderungen an das Script

### Seiten / Ansichten (via GET-Parameter, z.B. ?page=actors&id=5)
1. **Startseite / Filme** (?page=movies oder Standard): Grid aller gespeicherten Filme mit Poster, Titel und Erscheinungsjahr. Suchfeld für Filmtitel. Klick auf Film öffnet Film-Detail.
2. **Film-Detail** (?page=movie&id={post_id}): Poster, Titel, Beschreibung, Erstellungsdatum. Wenn embed_url vorhanden: Parse das JSON-Array und zeige für jede URL einen farbigen Play-Button nebeneinander. Der Hoster wird automatisch aus der URL erkannt (voe.sx→VOE, streamtape→Streamtape, drive.google→gDrive, doodstream→DoodStream, vidoza→Vidoza, filemoon→Filemoon, mixdrop→Mixdrop). Jeder Hoster bekommt eine eigene Farbe. Beim Klick öffnet sich ein Popup-Modal mit einem iframe (16:9 Aspect Ratio) und dem Filmtitel im Header. Das Modal kann via ×-Button, ESC-Taste oder Klick auf den Overlay geschlossen werden. Darunter: Besetzung als horizontale Scroll-Leiste mit Profilbild, Name und Rollenname. Klick auf Darsteller→Darsteller-Detail.
3. **Darsteller-Übersicht** (?page=actors): A-Z Alphabet-Navigation (sticky). Grid-Karten mit Profilbild, Name, Abteilung, Geburtstag. Verstorbene Darsteller: ✝-Symbol und rotes Sterbedatum-Badge. Suchfeld für Namen.
4. **Darsteller-Detail** (?page=actor&id={actor_id}): Profilbild, Name, Geburtsdatum mit Alter (bei Verstorbenen: "wurde X Jahre alt"), Sterbedatum in Rot, Geburtsort, Popularität, Biografie. Filmografie: Alle Filme dieses Darstellers als Poster-Grid mit Titel und Rollenname. Klick auf Film→Film-Detail.

### Navigation
- Sticky Navbar mit Logo "Mini TMDB" und Links zu Filme/Darsteller
- Aktiver Nav-Link hervorgehoben

### Design-Vorgaben
- ALLES in einer einzigen PHP-Datei (Inline CSS + HTML + PHP Logik)
- Dunkles, modernes Design (Background: #0f172a, Cards: #1e293b, Text: #f8fafc)
- Google Fonts "Outfit" einbinden
- Gradient-Akzente in Orange (#f59e0b) und Rot (#ef4444) – als Unterscheidung zum Hauptsystem
- Glassmorphismus-Cards mit backdrop-filter, border-radius: 1rem
- Slide-up Animationen für Cards (CSS @keyframes)
- Verstorbene Darsteller: ✝-Badge in Rot (#f87171) mit halbtransparentem Hintergrund
- Hover-Effekte auf allen klickbaren Cards (translateY, box-shadow)
- Smooth Transitions überall (transition: all 0.3s ease)
- Keine JavaScript-Frameworks, nur minimales Vanilla JS falls nötig (z.B. für Suchfilter)

### Mobile-First Layout (WICHTIG!)
Das gesamte Layout MUSS nach dem Mobile-First-Prinzip erstellt werden:
- **Base-CSS = Smartphone**: Alle Standard-Styles sind für kleine Bildschirme (320px–480px) optimiert
- **Breakpoints aufwärts mit min-width**: Nur `@media (min-width: ...)` verwenden, KEINE max-width Queries
  - `@media (min-width: 640px)` – Tablets
  - `@media (min-width: 1024px)` – Desktop
- **Grid-Layout**: Standard = 1 Spalte auf Mobile. Grid wächst über Breakpoints:
  - Mobile: `grid-template-columns: repeat(2, 1fr)` für Film-/Darsteller-Karten
  - Tablet (640px+): `grid-template-columns: repeat(3, 1fr)`
  - Desktop (1024px+): `grid-template-columns: repeat(4, 1fr)` oder `repeat(5, 1fr)`
- **Navigation**: Auf Mobile eine kompakte Hamburger-Navigation oder sticky Bottom-Nav mit Icons. Ab Tablet: Klassische horizontale Navbar
- **Touch-Targets**: Alle klickbaren Elemente mindestens 44×44px groß (Apple HIG Standard)
- **A-Z Navigation**: Auf Mobile horizontal scrollbar mit kompakteren Buttons (min 36px), auf Desktop volle Breite
- **Suchfelder**: `width: 100%` auf Mobile, eingegrenzt ab Tablet
- **Font-Sizes**: Basis 14px auf Mobile, ab Tablet 16px
- **Padding/Margins**: Kompakter auf Mobile (0.75rem–1rem), großzügiger ab Desktop (1.5rem–2rem)
- **Film-Detail-Seite**: Poster + Text untereinander auf Mobile. Ab Tablet: nebeneinander (Poster links, Info rechts)
- **Darsteller-Detail**: Profilbild über dem Text auf Mobile, nebeneinander ab Tablet
- **Besetzungs-Scroll**: Horizontal scrollbar mit touch-snap (`scroll-snap-type: x mandatory`)
- **Container**: `max-width: 1200px; margin: 0 auto; padding: 0 1rem;` – skaliert natürlich auf allen Größen
- **Bilder**: `width: 100%; height: auto;` als Standard, `object-fit: cover` bei Karten

### Technische Anforderungen
- PDO mit ERRMODE_EXCEPTION
- Prepared Statements für alle Queries mit Parametern
- htmlspecialchars() für alle Ausgaben
- date()-Formatierung für Datumsanzeigen (deutsches Format: d.m.Y)
- mb_substr() für UTF-8 sichere String-Operationen
- Fallback-Darstellung wenn kein Profilbild/Poster vorhanden (Gradient-Placeholder mit Icon oder Initial)