Files
hms-licht-ton/docs/design-rules.md
T
2026-07-10 23:08:41 +02:00

18 KiB
Raw Blame History

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

<!-- 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

<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

<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

<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

<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

<button class="hms-chip" :class="{ active: isActive }">Filter</button>
  • Inactive: Surface bg, muted text, border
  • Active: Orange bg, white text, orange border

Navigation Buttons

<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

<div class="hms-skeleton h-4 w-3/4"></div>
  • Shimmer Animation von prototype-style.css

Spinner

<span class="hms-spinner" style="width:18px;height:18px;border-width:2px"></span>

Icon Circle (Service Icons)

<div class="hms-icon-circle mb-4"><span aria-hidden="true">🔊</span></div>
  • 48x48px, surface bg, border, centered content

Hero

<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

<!-- 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

<loading-skeleton :count="6" />

Empty State

<empty-state icon="🔍" title="Keine Ergebnisse" message="..." action-label="Zurück" @action="..." />

Error State

<error-state title="Fehler" message="..." @retry="..." />

Success State

<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

<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

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

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

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

<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.