The single requestAnimationFrame used to trigger the fade-in was
unreliable - the browser could coalesce the hidden and visible states
into one paint, so items appeared instantly instead of fading/flying
in. Switched to a double-rAF, which reliably guarantees a paint of the
hidden state first. Also moves the menu content and close button to
the left side per feedback.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The nav links no longer show inline on desktop - clicking the
hamburger icon now opens the same fullscreen overlay menu on every
screen size, instead of only on mobile.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nav links move back to the left side of the header (theme toggle back
to the right), logo is bigger, and the mobile fullscreen menu now
animates items back out in reverse order when closing instead of just
disappearing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mirrors the old site's Bildergalerie structure: a brand tile grid at
/galerie, project tiles within a brand, and a photo grid with a
lightbox for each project. Backed by new gallery_brands/gallery_projects/
gallery_photos tables and admin CRUD pages, gated by a new gallery.manage
permission.
Also fixes a real bug found while testing photo uploads: Apache's
mod_dir was redirecting POST /api/uploads to /api/uploads/ (a trailing
slash) because api/uploads/ exists as a real directory, silently
dropping the multipart body on every image upload across the whole
app. Fixed via DirectorySlash Off in .htaccess.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Swaps navbar layout (theme toggle left, nav links right), replaces the
mobile dropdown with a fullscreen overlay whose items fly in top-to-bottom,
and renames the site-wide "slate" gray to "neutral" to remove a blue
undertone that clashed with the brand green. Also converts the flat
saturated-green YouTube and stats sections into dark backgrounds with
green used only as an accent, matching typical premium car-audio branding.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds a Website settings tab (hero image, phone, WhatsApp, email) that
feeds the navbar, footer and contact page via a new SiteSettingsContext,
redesigns the navbar with a bigger centered logo plus phone/WhatsApp/shop
links, and adds a VIN/chassis-number field to the contact form, admin
inbox and notification email.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Neben dem Dark/Light-Umschalter erscheint jetzt fuer eingeloggte
Admin-Nutzer ein zusaetzliches Icon, das direkt zu /admin fuehrt -
sowohl Desktop- als auch mobile Navigation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Der Workflow hat den Inhalt von hifi/ bisher direkt auf die Wurzel des
deploy-Branch gepusht (working-directory: hifi). Das passt aber nicht
zum bestehenden Plesk-Dokumentenstamm (.../hifi als Unterordner) - die
frisch gebauten Dateien landeten dadurch eine Ebene zu hoch und wurden
nie tatsaechlich ausgeliefert, egal wie oft neu gepullt/bereitgestellt
wurde. Jetzt wird in ein separates Verzeichnis kopiert, sodass der
hifi/-Ordner samt Prefix im deploy-Branch erhalten bleibt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Symptom: Admin-Login zeigte "Cannot read properties of null (reading
'requires_2fa')". Ursache: falls vor den header()-Aufrufen in index.php
irgendeine Ausgabe passiert (z.B. eine PHP-Notice - passiert offenbar auf
PHP 8.4 anders als lokal auf 8.2), geht der Content-Type-Header verloren,
und der Client hat JSON-Antworten dann still als null behandelt statt
sie zu parsen. Backend puffert Ausgaben jetzt und verwirft ungewollten
Output vor den Headern; Client versucht JSON-Parsing jetzt unabhaengig
vom Content-Type-Header und wirft einen klaren Fehler statt still null
zurueckzugeben.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Baut bei jedem Push auf main automatisch das PHP-Backend (composer
install) und das React-Frontend (npm run build), und veroeffentlicht
das fertige Ergebnis im "deploy"-Branch. Plesk kann diesen Branch
ziehen, ohne selbst Composer/npm ausfuehren zu muessen - kein manuelles
Hochladen von Build-Artefakten mehr noetig.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Die fixierte "Bereit fuer deinen Sound-Umbau?"-Leiste auf der Startseite
ueberdeckte am Seitenende die letzte Footer-Zeile (Impressum/Datenschutz/
AGB-Links), da fixed-position Elemente unabhaengig vom Dokumentenfluss
ueber allem liegen. Footer reserviert jetzt auf der Startseite zusaetzlichen
unteren Abstand fuer die Leiste, auf allen anderen Seiten unveraendert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
lucide-react/dynamic erzeugt pro Icon eine eigene Chunk-Datei, was beim
Deploy auf Shared-Hosting (Datei-Upload/Zip-Entpacken über Plesk) an
Datei-Limits scheitert. Per manualChunks jetzt alle Icons in eine
gemeinsame Datei gebündelt (1757 -> 12 Dateien im Build-Output).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Statt Env-Var-gesteuertem Dualbetrieb (lokal /hifi, live /) läuft jetzt
alles einheitlich unter der Domain-Wurzel - auch lokal (siehe neuer
VirtualHost auf Port 8080 in der Apache-Konfiguration, unabhängig von
Port 80 mit /hifi). Dabei einen Doppel-Slash-Bug in der Routenberechnung
gefunden und behoben (base_path '/' + '/api' ergab faelschlich '//api').
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bisher war /hifi an mehreren Stellen fest einprogrammiert (vite base,
Router basename, API-Client, Upload-URLs, .htaccess). Fuer den geplanten
Deploy auf IONOS unter der Domain-Wurzel wird das jetzt ueber
VITE_BASE_PATH (Frontend-Build) bzw. eine optionale base_path.php
(Backend, gleiches Muster wie db.php/setup.php) gesteuert - lokal ohne
diese Werte bleibt alles unveraendert bei /hifi.
.htaccess.ionos enthaelt die Root-Domain-Variante fuer den CI-Build.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
config.php and SetupController beide luden db.php bisher ungeprueft per
require, was auf einem frischen Server (vor der Ersteinrichtung) zu
einem fatalen Fehler gefuehrt haette, noch bevor /setup ueberhaupt
erreichbar ist. Faellt jetzt auf eine leere Config zurueck.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Passwortgeschuetzter Assistent fuer die Ersteinrichtung auf einem neuen
Server: Datenbank-Zugangsdaten testen & speichern, Datenbankstruktur
anlegen, ersten Admin-Account erstellen. Sperrt sich danach dauerhaft
selbst, sobald ein Admin-Account existiert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>