@@ -0,0 +1,508 @@
# HMS Licht & Ton – Design-Richtlinien für KI-Agenten
> **VERBINDLICH:** Diese Regeln MÜSSEN bei jeder Erweiterung der Website eingehalten werden.
> Abweichungen sind Fehler. Der freigegebene Prototyp ist die Quelle der Wahrheit.
> Prototyp: `https://webspace.media-on.de/hms-prototype/index.html?v=8`
> Referenz-Dateien: `docs/prototype-app.js`, `docs/prototype-index.html`, `frontend/assets/css/prototype-style.css`
---
## 1. Farbsystem (Dark Theme + Orange Akzent)
### Hauptfarben (Agent Zero Dark Theme Grautöne)
| Token | Hex | Verwendung |
|-------|-----|------------|
| `--bg` | `#131313` | Seiten-Hintergrund |
| `--panel` | `#1a1a1a` | Panels, Cards, Header |
| `--surface` | `#212121` | Input-Felder, Surface-Level |
| `--row` | `#272727` | List-Items, Zwischenebenen |
| `--card` | `#2d2d2d` | Card-Hintergrund |
| `--border` | `#444444a8` | Borders (mit Alpha) |
| `--border-strong` | `#555555` | Strong Borders (Inputs) |
| `--secondary` | `#656565` | Sekundärfarbe, Icons, grauer Text |
| `--primary` | `#737a81` | Primärfarbe (leicht bläuliches Grau) |
| `--text` | `#ffffff` | Haupttext |
| `--text-muted` | `#d4d4d4` | Gedimmter Text |
### Orange Akzent (DEZENT – keine großen Flächen!)
| Token | Wert | Verwendung |
|-------|------|------------|
| `--color-accent` | `#EC6925` | Buttons, Badges, Text-Akzente, Logo-Border |
| `--color-accent-hover` | `#d4581a` | Button Hover |
| `--color-accent-light` | `rgba(236, 105, 37, 0.08)` | Badge-Hintergrund, Nav-Active |
| `--color-accent-border` | `rgba(236, 105, 37, 0.25)` | Card Hover Border |
| `--color-accent-dark` | `#b8461a` | Dunkle Variante |
### Status-Farben
| Token | Hex/RGBA | Verwendung |
|-------|----------|------------|
| `--color-success` | `#4ade80` | Erfolg-Meldungen |
| `--color-success-bg` | `rgba(74, 222, 128, 0.08)` | Erfolg-Hintergrund |
| `--color-error` | `#f87171` | Fehler, Pflichtfelder |
| `--color-error-bg` | `rgba(248, 113, 113, 0.08)` | Fehler-Hintergrund |
| `--color-warning` | `#fbbf24` | Warnungen |
| `--color-info` | `#60a5fa` | Info |
### FARB-REGELN
- **Orange NIEMALS als große Fläche** – nur für Buttons, Badges, kleine Text-Highlights, Border
- **Hintergründe IMMER Grautöne** (#131313 bis #2d2d2d )
- **Text IMMER `var(--text)` (#ffffff ) oder `var(--text-muted)` (#d4d4d4 )**
- **Sekundärer Text `var(--secondary)` (#656565 )** für sehr gedimmte Infos
- **Inline Styles mit CSS Variablen:** `style="color: var(--text)"` , `style="background: var(--panel)"`
---
## 2. Typography
- **Font Family:** Inter (Google Fonts), Weights: 400, 500, 600, 700, 800
- **Größen:** Tailwind Utilities (`text-xs` , `text-sm` , `text-base` , `text-lg` , `text-xl` , `text-2xl` , `text-3xl` , `text-4xl` , `text-5xl` , `text-6xl` )
- **Headings:** `font-bold` oder `font-semibold` , `leading-tight` für große Headlines
- **Body:** `leading-relaxed` für längere Texte
- **Line Height:** 1.6 (Body), 1.1-1.3 (Headings)
---
## 3. Layout-System
### Container
- **Max-Width:** `max-w-7xl` (1280px)
- **Padding:** `px-4 sm:px-6 lg:px-8`
- **Center:** `mx-auto`
### Sections
- **Vertical Padding:** `py-12 sm:py-16` (Standard), `py-16 sm:py-20` (große Sections), `py-20 sm:py-32` (Hero)
- **Background Alternation:** `var(--bg)` → `var(--panel)` → `var(--bg)` für visuelle Trennung
- **Section Dividers:** `.hms-section-divider` (subtiler Gradient)
### Grid
- **Cards Grid:** `grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6`
- **Speaker Grid:** `.hms-speaker-grid` (auto-fill, minmax 160px)
- **Gallery Grid:** `.hms-gallery` (auto-fill, minmax 300px)
- **2-Spalten Layout:** `grid lg:grid-cols-2 gap-8` oder `gap-12`
### Responsive Breakpoints
- `sm:` 640px (Tablet Portrait)
- `md:` 768px (Desktop Nav visible, Mobile Burger hidden)
- `lg:` 1024px (Desktop, 3-4 Column Grids)
- **Mobile-First:** Alle Layouts starten 1-Spalte
---
## 4. CSS Komponenten-Klassen (hms-*)
### ÜBERSICHT: Alle hms-* Klassen aus prototype-style.css
Diese Klassen sind in `assets/css/main.css` definiert und MÜSSEN verwendet werden.
Keine eigenen Klassen erfinden!
### Buttons
``` html
<!-- Primary: Orange bg, white text -->
< button class = "hms-btn hms-btn-primary" > Button Text< / button >
<!-- Secondary: Surface bg, muted text, border -->
< button class = "hms-btn hms-btn-secondary" > Button Text< / button >
<!-- Ghost: Transparent, muted text -->
< button class = "hms-btn hms-btn-ghost" > Button Text< / button >
```
- **Padding:** `px-8 py-4` für große Buttons, `px-4 py-2` für kleine, `px-3 py-1.5` für Mini
- **Font:** `font-semibold` oder `font-medium` , `text-sm` für Standard
- **Hover-Effekte:** Primary → box-shadow glow + translateY(-1px); Secondary → border accent
- **Disabled:** `--secondary` bg, `cursor: not-allowed`
### Cards
``` html
< div class = "hms-card p-6" >
< h3 class = "text-lg font-semibold mb-2" style = "color: var(--text)" > Title< / h3 >
< p class = "text-sm leading-relaxed" style = "color: var(--text-muted)" > Description< / p >
< / div >
```
- **Background:** `var(--panel)` (#1a1a1a )
- **Border:** `1px solid var(--border)` (#444444a8 )
- **Border-Radius:** `4px` (--radius-lg)
- **Hover:** Box-shadow wird stärker, Border wird heller
### Equipment Cards
``` html
< div class = "hms-eq-card" @ click = "..." role = "article" tabindex = "0" >
< div class = "aspect-[4/3] flex items-center justify-center relative overflow-hidden" style = "background: var(--surface)" >
< img v-if = "item.image" :src = "item.image" class = "absolute inset-0 w-full h-full object-cover" / >
< div v-else class = "text-4xl" style = "color: var(--secondary)" > 📦< / div >
< span v-if = "item.category" class = "hms-badge hms-badge-primary absolute top-3 left-3" > {{ item.category }}< / span >
< / div >
< div class = "p-4" >
< h3 class = "font-semibold text-sm mb-1 truncate" style = "color: var(--text)" > {{ item.name }}< / h3 >
< p class = "text-xs mb-3 line-clamp-2" style = "color: var(--secondary)" > {{ item.description }}< / p >
< div class = "flex items-center justify-between" >
< span class = "text-xs" style = "color: var(--secondary)" > {{ item.code }}< / span >
< button class = "hms-btn hms-btn-ghost text-xs px-3 py-1.5" style = "color: var(--color-accent)" > + Hinzufügen< / button >
< / div >
< / div >
< / div >
```
### Badges
``` html
< span class = "hms-badge hms-badge-primary" > Badge Text< / span >
< span class = "hms-badge hms-badge-gray" > Gray Badge< / span >
< span class = "hms-badge hms-badge-success" > Success< / span >
< span class = "hms-badge hms-badge-error" > Error< / span >
```
- **Border-Radius:** `9999px` (pill shape)
- **Primary:** Orange bg (12% alpha), orange text, orange border (20% alpha)
### Inputs
``` html
< input class = "hms-input" type = "text" placeholder = "..." / >
< input class = "hms-input hms-input-error" / > <!-- mit Fehler -->
< select class = "hms-input" > < option > ...< / option > < / select >
< textarea class = "hms-input" rows = "5" > < / textarea >
```
- **Background:** `var(--surface)` (#212121 )
- **Border:** `1px solid var(--border-strong)` (#555555 )
- **Focus:** Orange border + subtle orange box-shadow
- **Error:** Red border + red box-shadow
- **Padding:** `var(--space-md) var(--space-lg)`
### Filter Chips
``` html
< button class = "hms-chip" :class = "{ active: isActive }" > Filter< / button >
```
- **Inactive:** Surface bg, muted text, border
- **Active:** Orange bg, white text, orange border
### Navigation Buttons
``` html
< button class = "hms-nav-btn px-4 py-2 rounded-lg text-sm font-medium"
:style = "isActive ? { color: 'var(--color-accent)', background: 'var(--color-accent-light)' } : { color: 'var(--text-muted)' }"
:aria-current = "isActive ? 'page' : undefined" >
Nav Item
< / button >
```
- **Hover:** Orange text + accent-light bg + Unterstrich-Animation
- **Active:** Orange text + accent-light bg
### Skeleton Loading
``` html
< div class = "hms-skeleton h-4 w-3/4" > < / div >
```
- Shimmer Animation von `prototype-style.css`
### Spinner
``` html
< span class = "hms-spinner" style = "width:18px;height:18px;border-width:2px" > < / span >
```
### Icon Circle (Service Icons)
``` html
< div class = "hms-icon-circle mb-4" > < span aria-hidden = "true" > 🔊< / span > < / div >
```
- 48x48px, surface bg, border, centered content
### Hero
``` html
< section class = "hms-hero py-20 sm:py-32" >
< div class = "hms-hero-bg" style = "background-image: url('...')" > < / div >
< div class = "hms-hero-overlay" > < / div >
< div class = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10" >
<!-- Content -->
< / div >
< / section >
```
- **hms-hero-bg:** Absolute, background-size cover, opacity 0.35
- **hms-hero-overlay:** Linear gradient von rgba(19,19,19,0.6) zu var(--bg)
- **Content:** `relative z-10` über Overlay
---
## 5. Inline Style Pattern
### REGEL: Inline Styles verwenden IMMER CSS Variablen
``` html
<!-- RICHTIG -->
< h1 style = "color: var(--text)" > Title< / h1 >
< p style = "color: var(--text-muted)" > Text< / p >
< div :style = "{ background: 'var(--panel)', borderColor: 'var(--border)' }" >
<!-- FALSCH -->
< h1 style = "color: #ffffff" > Title< / h1 >
< p style = "color: #d4d4d4" > Text< / p >
```
### Häufige Inline Styles aus dem Prototyp
- `style="color: var(--text)"` – Haupttext
- `style="color: var(--text-muted)"` – Gedimmter Text
- `style="color: var(--secondary)"` – Sehr gedimmter Text
- `style="color: var(--color-accent)"` – Orange Akzent
- `style="background: var(--panel)"` – Panel BG
- `style="background: var(--bg)"` – Seiten BG
- `style="background: var(--surface)"` – Surface BG
- `:style="{ borderColor: 'var(--border)' }"` – Border Color
- `:style="{ background: 'var(--color-success-bg)', color: 'var(--color-success)' }"` – Success State
---
## 6. Komponenten-Struktur
### Bestehende Komponenten (NICHT neu erfinden)
| Komponente | Datei | Zweck |
|---|---|---|
| HmsLogo | `components/HmsLogo.vue` | Echtes SVG Logo (H + orange Border) |
| SpeakerIcon | `components/SpeakerIcon.vue` | 6 Lautsprecher-Typ SVG Icons |
| AppHeader | `components/AppHeader.vue` | Sticky Header, Nav, Cart, Mobile Burger |
| AppFooter | `components/AppFooter.vue` | 4-Spalten Footer |
| ServiceCard | `components/ServiceCard.vue` | Service Card mit Icon Circle |
| EquipmentCard | `components/EquipmentCard.vue` | Equipment Card mit Badge, Image, Add-to-Cart |
| LoadingSkeleton | `components/LoadingSkeleton.vue` | Skeleton Loading Cards |
| EmptyState | `components/EmptyState.vue` | Empty State mit Icon + Action |
| ErrorState | `components/ErrorState.vue` | Error State mit Retry |
### Neue Komponenten erstellen – Checklist
1. CSS Klassen aus `prototype-style.css` verwenden (hms-*)
2. Inline Styles mit CSS Variablen
3. Tailwind Utilities für Layout/Spacing
4. TypeScript mit `lang="ts"`
5. `useHead()` für Meta Tags
6. ARIA Attributes (role, aria-label, aria-current, etc.)
7. Responsive (mobile-first, sm/md/lg breakpoints)
---
## 7. UX States (MUSS in jeder View implementiert)
### Loading State
``` html
< loading-skeleton :count = "6" / >
```
### Empty State
``` html
< empty-state icon = "🔍" title = "Keine Ergebnisse" message = "..." action-label = "Zurück" @ action = "..." / >
```
### Error State
``` html
< error-state title = "Fehler" message = "..." @ retry = "..." / >
```
### Success State
``` html
< div class = "text-center py-8" role = "status" >
< div class = "inline-flex items-center justify-center w-16 h-16 rounded-full mb-4"
:style = "{ background: 'var(--color-success-bg)', color: 'var(--color-success)' }" >
< svg class = "w-8 h-8" . . . > ✓< / svg >
< / div >
< h3 class = "text-lg font-semibold mb-2" style = "color: var(--text)" > Erfolg< / h3 >
< p class = "text-sm mb-6" style = "color: var(--secondary)" > Nachricht< / p >
< / div >
```
### Submitting State
``` html
< button :disabled = "submitting" class = "hms-btn hms-btn-primary" >
< span v-if = "submitting" class = "hms-spinner" style = "width:18px;height:18px;border-width:2px" > < / span >
< span v-else > Senden< / span >
< / button >
```
---
## 8. Accessibility (WCAG 2.1 AA)
### MUSS-Regeln
- **Skip Link:** `<a class="skip-link" href="#main">Zum Inhalt springen</a>` am Seitenanfang
- **Semantic HTML:** `<header>` , `<main>` , `<footer>` , `<nav>` , `<section>` , `<article>`
- **ARIA:** `role` , `aria-label` , `aria-current="page"` , `aria-expanded` , `aria-invalid` , `aria-describedby` , `role="alert"` , `role="status"`
- **Focus Visible:** `*:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }`
- **Form Labels:** Jedes Input hat `<label for="...">` , Pflichtfelder mit `<span style="color: var(--color-error)">*</span>`
- **Heading Hierarchy:** h1 > h2 > h3, keine Levels überspringen
- **Keyboard Navigation:** Alle interaktiven Elemente per Tab erreichbar, `tabindex="0"` auf klickbare Cards
- **Alt Text:** Alle Bilder haben `alt="..."`
- `aria-hidden="true"` auf dekorativen Icons
- `loading="lazy"` auf alle Bilder
---
## 9. Meta Tags & SEO
### MUSS pro Seite
``` typescript
useHead ( {
title : 'Seite – HMS Licht & Ton' ,
meta : [
{ name : 'robots' , content : 'noindex, nofollow, noarchive, nosnippet' } ,
] ,
} ) ;
```
### JSON-LD (nur Home)
- `LocalBusiness` Schema mit Adresse, Öffnungszeiten, Services
### OpenGraph
- `og:type` , `og:title` , `og:description` , `og:locale` , `og:site_name` , `og:url`
### REGELN
- **noindex** auf ALLEN Seiten (Domain nicht öffentlich indexiert)
- **KEINE sitemap.xml**
- Inter Font via Google Fonts preconnect
- `theme-color: #EC6925` (nur im Head, nicht als Design-Fläche!)
---
## 10. Bilder
### Hero Background
- Unsplash Konzert-Bild: `background-image: url('https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?w=1920&q=80')`
- **Opacity:** 0.35 (über `.hms-hero-bg` )
- **Overlay:** Linear gradient zu `var(--bg)`
### Referenzen
- 9 echte HMS-Fotos: `img/ref1.jpg` bis `img/ref9.jpg`
- **Hover:** `group-hover:scale-110` (Zoom-Effekt)
- **Gradient Overlay:** `bg-gradient-to-t from-black/50 to-transparent` bei Hover
### Equipment
- Platzhalter `📦` Emoji wenn kein Bild vorhanden
- `loading="lazy"` auf allen Bildern
### About Section
- Unsplash Setup-Bild: `https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=800&q=80`
---
## 11. Spacing & Radius
### Spacing Tokens
| Token | Wert |
|-------|-------|
| `--space-xs` | 0.25rem (4px) |
| `--space-sm` | 0.5rem (8px) |
| `--space-md` | 1rem (16px) |
| `--space-lg` | 1.5rem (24px) |
| `--space-xl` | 2rem (32px) |
| `--space-2xl` | 3rem (48px) |
| `--space-3xl` | 4rem (64px) |
| `--space-4xl` | 6rem (96px) |
### Border Radius (MINIMAL!)
| Token | Wert |
|-------|-------|
| `--radius-sm` | 2px |
| `--radius-md` | 3px |
| `--radius-lg` | 4px |
| `--radius-xl` | 4px |
| `--radius-full` | 9999px (nur Badges, Pills) |
### Shadows
| Token | Wert |
|-------|-------|
| `--shadow-sm` | `0 1px 2px 0 rgb(0 0 0 / 0.3)` |
| `--shadow-md` | `0 4px 6px -1px rgb(0 0 0 / 0.4), 0 2px 4px -2px rgb(0 0 0 / 0.3)` |
| `--shadow-lg` | `0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3)` |
| `--shadow-xl` | `0 20px 25px -5px rgb(0 0 0 / 0.5), 0 8px 10px -6px rgb(0 0 0 / 0.3)` |
---
## 12. Transitions
| Token | Dauer |
|-------|-------|
| `--transition-fast` | 150ms ease |
| `--transition-base` | 250ms ease |
| `--transition-slow` | 400ms ease |
---
## 13. Build & Test
### Frontend
``` bash
cd frontend && npm run build # Build (MUSS 0 errors)
cd frontend && npx vitest run # Unit Tests (MUSS alle pass)
cd frontend && npx playwright test --grep 'Pattern' # E2E Tests
curl -s http://localhost:3000/ # Smoke Test
```
### Backend
``` bash
cd backend && python -m pytest tests/ -v --cov= app # Tests (MUSS alle pass)
curl -s http://localhost:8000/api/health # Health Check
```
### Deployment
- Server: coolify-01 (46.225.91.159)
- Pfad: `/data/hms-licht-ton/`
- Branch: `feature/T04-rentman-integration` (oder `main` nach Merge)
- Docker Compose: `docker compose up -d`
- Domain: `https://hms.media-on.de` (Traefik + Let's Encrypt)
---
## 14. VERBOTEN
- ❌ Eigene CSS Klassen erfinden (nur `hms-*` verwenden)
- ❌ Generische `.btn-primary` oder `.nav-link` Klassen
- ❌ Hardcoded Hex-Werte in Inline Styles (immer `var(--...)` )
- ❌ Fake-Logo (immer echtes SVG aus `assets/logo.svg` )
- ❌ Große Orange-Flächen
- ❌ Abgerundete Ecken > 4px (außer Badges/Pills = 9999px)
- ❌ Client-only rendering für SSR Pages (`/mietkatalog` , `/mietkatalog/**` )
- ❌ Fehlende ARIA Attributes
- ❌ Fehlende UX States (Loading, Empty, Error, Success)
- ❌ Fehlendes `noindex` Meta Tag
- ❌ Eigene Templates die nicht dem Prototyp entsprechen
---
## 15. Referenz-Dateien
| Datei | Zweck |
|---|---|
| `docs/prototype-app.js` | Original Vue 3 SPA Prototyp (761 Zeilen, 19 Komponenten) |
| `docs/prototype-index.html` | Original HTML mit Meta Tags, JSON-LD |
| `frontend/assets/css/prototype-style.css` | Original CSS mit allen hms-* Klassen (13KB) |
| `frontend/assets/css/main.css` | Aktive CSS (enthält prototype-style.css + Tailwind directives) |
| `frontend/assets/logo.svg` | Echtes HMS Logo (503 bytes, weißes H + orange Border) |
| `frontend/public/logo.svg` | Static copy für Nuxt public dir |
| `docs/ui_design.md` | Original UI Design Dokumentation |
| `docs/design-rules.md` | DIES DATEI – Design Richtlinien für KI-Agenten |
---
## 16. Schnell-Referenz: Neue Seite erstellen
``` vue
< template >
< div class = "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12" >
< h1 class = "text-3xl sm:text-4xl font-bold mb-2" style = "color: var(--text)" > Seiten - Titel < / h1 >
< p class = "mb-8" style = "color: var(--secondary)" > Untertitel < / p >
<!-- Loading -- >
< loading-skeleton v-if = "loading" :count="6" / >
<!-- Error -- >
< error-state v-else-if = "error" title="Fehler" message="..." @retry="loadData" / >
<!-- Content -- >
< div v-else class = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6" >
< div v-for = "item in items" :key="item.id" class="hms-card p-6" >
< h3 class = "text-lg font-semibold mb-2" style = "color: var(--text)" > { { item . title } } < / h3 >
< p class = "text-sm leading-relaxed" style = "color: var(--text-muted)" > { { item . description } } < / p >
< button class = "hms-btn hms-btn-primary mt-4" > Aktion < / button >
< / div >
< / div >
<!-- Empty -- >
< empty-state v-if = "!loading && !error && items.length === 0"
icon = "🔍" title = "Keine Daten" message = "..." action -label = " Zurück " @action ="..." / >
< / div >
< / template >
< script setup lang = "ts" >
useHead ( {
title : 'Seite – HMS Licht & Ton' ,
meta : [ { name : 'robots' , content : 'noindex, nofollow, noarchive, nosnippet' } ] ,
} ) ;
< / script >
```
---
* Dieses Dokument ist die verbindliche Design-Richtlinie für alle Erweiterungen der HMS Licht & Ton Website. *