This commit is contained in:
Bastian Masanek
2025-10-30 08:24:44 +01:00
commit 6e50ec7034
73 changed files with 27355 additions and 0 deletions

2241
docs/ARCHITECTURE.md Normal file

File diff suppressed because it is too large Load Diff

2392
docs/CIDAAS_INTEGRATION.md Normal file

File diff suppressed because it is too large Load Diff

923
docs/DESIGN_SYSTEM.md Normal file
View File

@@ -0,0 +1,923 @@
# experimenta Design System
**Version:** 1.0
**Letzte Aktualisierung:** 2025-10-29
**Font:** Roboto (Open Source Alternative zu DIN OT)
Dieses Design System definiert die visuelle Identität und Komponenten-Bibliothek für **my.experimenta.science**. Es basiert auf dem Corporate Design der experimenta Science Center Website und den bereitgestellten Design-Vorlagen.
---
## Inhaltsverzeichnis
1. [Farbpalette](#farbpalette)
2. [Typografie](#typografie)
3. [Spacing & Layout](#spacing--layout)
4. [Komponenten](#komponenten)
5. [Animationen & Transitions](#animationen--transitions)
6. [Accessibility](#accessibility)
---
## Farbpalette
### Primärfarben
**Experimenta Magenta** (Hauptfarbe)
```css
--color-primary: #e6007e;
--color-primary-hover: #c2006a;
--color-primary-light: #ff4081;
```
**Verwendung:** Primary Buttons, Links, aktive Zustände, Brand-Elemente
**Experimenta Pink**
```css
--color-secondary: #e91e63;
--color-secondary-dark: #c2185b;
```
**Verwendung:** Secondary Buttons, Footer Headings, Social Media Icons
**Experimenta Orange** (Akzent)
```css
--color-accent: #f59d24;
--color-accent-hover: #ffb347;
```
**Verwendung:** Border-Akzente (links), Hover-Effekte, Highlights, Labels
**Experimenta Rot** (Button-Gradient)
```css
--color-red: #e40521;
```
**Verwendung:** Button-Gradienten, Error-Zustände (zusammen mit Magenta)
### Background-Farben
**Dark Gradient** (Haupt-Background)
```css
--bg-gradient-primary: linear-gradient(135deg, #2e1065 0%, #1a0a3a 50%, #0f051d 100%);
```
**Purple Variants**
```css
--color-purple-dark: #2e1065; /* Start des Gradienten */
--color-purple-deeper: #1a0a3a; /* Mitte des Gradienten */
--color-purple-darkest: #0f051d; /* Ende des Gradienten */
```
**Header Background**
```css
--bg-header: rgba(46, 16, 101, 0.95); /* Mit backdrop-filter: blur(10px) */
```
**Footer Background**
```css
--bg-footer: linear-gradient(135deg, #1a0a3a 0%, #0f051d 100%);
```
### Glassmorphism (Cards & Containers)
```css
--glass-background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
--glass-backdrop: blur(15px);
--glass-border: 1px solid rgba(255, 255, 255, 0.2);
--glass-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
```
**Section Backgrounds (auf Glassmorphism Cards)**
```css
--bg-section: rgba(255, 255, 255, 0.08); /* Leicht heller als Card */
--bg-section-hover: rgba(255, 255, 255, 0.15);
```
### Semantische Farben
**Success**
```css
--color-success: #46c74a;
--color-success-dark: #3ba83e;
--color-success-gradient: linear-gradient(90deg, #46c74a 0%, #66d96a 50%, #46c74a 100%);
```
**Error**
```css
--color-error: #e53e3e;
--color-error-dark: #c53030;
```
**Warning**
```css
--color-warning: #f59d24;
--color-warning-dark: #dd8a1e;
```
**Info**
```css
--color-info: #4299e1;
--color-info-dark: #3182ce;
```
### Text-Farben
```css
--text-primary: #ffffff; /* Haupt-Text auf dunklem BG */
--text-secondary: rgba(255, 255, 255, 0.9); /* Sekundär-Text */
--text-muted: rgba(255, 255, 255, 0.8); /* Footer, Labels */
--text-disabled: rgba(255, 255, 255, 0.5); /* Disabled Elemente */
/* Text auf hellem Background (falls benötigt) */
--text-dark: #333333;
--text-dark-secondary: #666666;
```
### Border-Farben
```css
--border-accent: 4px solid #f59d24; /* Links-Border für Sections */
--border-light: 1px solid rgba(255, 255, 255, 0.2); /* Card Borders */
--border-footer: 1px solid rgba(255, 255, 255, 0.1); /* Footer Divider */
```
---
## Typografie
### Font-Family
**Roboto** (Open Source, ähnlich zu DIN OT)
```css
font-family: 'Roboto', sans-serif;
```
**Import:**
```html
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet"
/>
```
**Gewichte:**
- `300` - Light (Headlines)
- `400` - Regular (Body Text)
- `500` - Medium (Buttons, Labels)
- `700` - Bold (Footer Links, Strong Text)
### Font-Scale (Desktop)
| Element | Size | Weight | Line Height | Letter Spacing |
| -------------- | ---- | ------ | ----------- | -------------- |
| **H1** | 36px | 300 | 1.2 | -1px |
| **H2** | 30px | 300 | 1.3 | -0.5px |
| **H3** | 24px | 400 | 1.4 | 0 |
| **H4** | 20px | 500 | 1.4 | 0 |
| **H5** | 18px | 500 | 1.5 | 0.5px |
| **H6** | 16px | 600 | 1.5 | 0.5px |
| **Body** | 18px | 400 | 1.7 | 0 |
| **Body Small** | 16px | 400 | 1.6 | 0 |
| **Caption** | 14px | 400 | 1.6 | 0 |
| **Tiny** | 12px | 400 | 1.5 | 0 |
### Responsive Font-Scale
**Tablet (≤768px):**
```css
H1: 28px
H2: 24px
H3: 20px
Body: 16px
```
**Mobile (≤480px):**
```css
H1: 24px
H2: 20px
H3: 18px
Body: 14px
```
### Tailwind Klassen
```html
<!-- Headlines -->
<h1 class="text-4xl md:text-3xl sm:text-2xl font-light tracking-tight">
<h2 class="text-3xl md:text-2xl sm:text-xl font-light">
<h3 class="text-2xl md:text-xl sm:text-lg font-normal">
<!-- Body Text -->
<p class="text-lg md:text-base sm:text-sm leading-relaxed">
<!-- Labels -->
<span class="text-lg md:text-base sm:text-sm font-medium tracking-wide"></span>
</p>
</h3>
</h2>
</h1>
```
---
## Spacing & Layout
### Spacing-System (8px Grid)
```css
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 30px;
--space-10: 40px;
--space-15: 60px;
--space-20: 80px;
```
### Container Max-Widths
```css
--container-main: 800px; /* Main Content (forms, text) */
--container-wide: 1200px; /* Footer, wide sections */
--container-full: 1760px; /* Full-width content (aus Website) */
```
### Border-Radius
```css
--radius-sm: 6px; /* Small elements (badges) */
--radius-md: 12px; /* Sections, Info-Cards */
--radius-lg: 15px; /* Standard Cards (mobile) */
--radius-xl: 20px; /* Standard Cards (desktop) */
--radius-2xl: 25px; /* Buttons */
--radius-full: 100%; /* Icons, Avatar */
```
### Breakpoints
```css
/* Mobile First */
--breakpoint-sm: 480px; /* Small phones */
--breakpoint-md: 768px; /* Tablets */
--breakpoint-lg: 1024px; /* Small desktops */
--breakpoint-xl: 1280px; /* Large desktops */
```
**Verwendung in Tailwind:**
```html
<!-- Mobile First: base = mobile, md = tablet, lg = desktop -->
<div class="p-4 md:p-8 lg:p-15"></div>
```
### Standard Paddings
**Cards:**
```css
/* Desktop */
padding: 60px 40px;
/* Tablet */
@media (max-width: 768px) {
padding: 40px 20px;
}
/* Mobile */
@media (max-width: 480px) {
padding: 30px 15px;
}
```
**Sections:**
```css
padding: 30px;
/* Tablet */
@media (max-width: 768px) {
padding: 25px 20px;
}
/* Mobile */
@media (max-width: 480px) {
padding: 20px 15px;
}
```
---
## Komponenten
### 1. Buttons
#### Primary Button
**Style:**
```css
background: #e6007e;
background-image: linear-gradient(to left, #e6007e, #e6007e, #e40521, #e6007e);
background-size: 300%;
color: #ffffff;
padding: 10px 30px;
border-radius: 25px;
font-size: 18px;
font-weight: 500;
transition:
background-position 1s,
all 0.3s ease;
/* Hover */
background-position: 100%;
```
**Tailwind:**
```html
<button class="btn-primary">Zur experimenta Startseite</button>
```
**CSS Klasse (Tailwind Config):**
```css
.btn-primary {
@apply bg-gradient-to-l from-primary via-red to-primary;
@apply bg-[length:300%] bg-left;
@apply text-white px-8 py-2.5 rounded-full;
@apply text-lg font-medium;
@apply transition-all duration-300;
@apply hover:bg-right;
}
```
#### Secondary Button
```html
<button class="btn-secondary">Abbrechen</button>
```
```css
.btn-secondary {
@apply bg-transparent border-2 border-accent text-accent;
@apply px-8 py-2.5 rounded-full;
@apply text-lg font-medium;
@apply transition-all duration-300;
@apply hover:bg-accent hover:text-white;
}
```
#### Button Sizes
```html
<!-- Large (default) -->
<button class="btn-primary text-lg px-8 py-2.5">
<!-- Medium -->
<button class="btn-primary text-base px-6 py-2">
<!-- Small (mobile) -->
<button class="btn-primary text-base px-6 py-2 md:px-8 md:py-2.5"></button>
</button>
</button>
```
---
### 2. Cards
#### Glass-morphism Card (Main Pattern)
**Style:**
```css
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
backdrop-filter: blur(15px);
border-radius: 20px;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
padding: 60px 40px;
```
**Tailwind:**
```html
<div class="card-glass">
<!-- Content -->
</div>
```
**CSS Klasse:**
```css
.card-glass {
@apply bg-gradient-to-br from-white/10 to-white/5;
@apply backdrop-blur-xl;
@apply rounded-2xl border border-white/20;
@apply shadow-2xl;
@apply p-15 md:p-10 sm:p-8;
}
```
#### Info Section Card
**Style:**
```css
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 30px;
border-left: 4px solid #f59d24;
```
**Tailwind:**
```html
<div class="card-info">
<h3 class="text-accent font-medium mb-4">Überschrift</h3>
<p class="text-white/90">Inhalt...</p>
</div>
```
**CSS Klasse:**
```css
.card-info {
@apply bg-white/8 rounded-xl;
@apply p-8 md:p-6 sm:p-5;
@apply border-l-4 border-accent;
}
```
---
### 3. Status Messages
#### Success Message
```html
<div class="status-message status-success">
<div class="status-icon"></div>
<h1>Verlängerung erfolgreich!</h1>
<p>Ihre Jahreskarte wurde verlängert.</p>
</div>
```
**CSS:**
```css
.status-icon {
@apply flex items-center justify-center;
@apply w-25 h-25 rounded-full;
@apply text-6xl text-white;
@apply mb-8;
@apply animate-pulse;
}
.status-success .status-icon {
@apply bg-success;
}
```
#### Error Message
```html
<div class="status-message status-error">
<div class="status-icon"></div>
<h1>Ein Fehler ist aufgetreten</h1>
<p>Bitte versuchen Sie es erneut.</p>
</div>
```
```css
.status-error .status-icon {
@apply bg-error;
}
```
---
### 4. Progress Bar
```html
<div class="progress-container">
<div class="progress-header">
<h3 class="progress-title">Verlängerungsfortschritt</h3>
<div class="progress-stats">5 / 10</div>
</div>
<div class="progress-bar-wrapper">
<div class="progress-bar" style="width: 50%"></div>
<div class="progress-percentage">50%</div>
</div>
</div>
```
**CSS:**
```css
.progress-container {
@apply bg-white/8 rounded-2xl;
@apply p-8 md:p-6;
@apply border-l-4 border-accent;
}
.progress-bar-wrapper {
@apply relative w-full h-8;
@apply bg-white/10 rounded-full;
@apply overflow-hidden;
@apply shadow-inner;
}
.progress-bar {
@apply h-full rounded-full;
@apply bg-gradient-to-r from-success via-[#66d96a] to-success;
@apply bg-[length:200%] animate-shimmer;
@apply transition-all duration-500;
}
.progress-percentage {
@apply absolute inset-0;
@apply flex items-center justify-center;
@apply text-base font-semibold text-white;
@apply drop-shadow-lg;
}
```
---
### 5. Forms
#### Input Field
```html
<div class="form-field">
<label for="email" class="form-label">E-Mail-Adresse</label>
<input type="email" id="email" class="form-input" placeholder="ihre.email@example.com" />
</div>
```
**CSS:**
```css
.form-label {
@apply block text-lg font-medium text-white/90;
@apply mb-3;
}
.form-input {
@apply w-full px-4 py-3;
@apply bg-white/10 border border-white/20;
@apply rounded-xl;
@apply text-white placeholder:text-white/50;
@apply focus:outline-none focus:ring-2 focus:ring-accent;
@apply transition-all duration-300;
}
.form-input:hover {
@apply bg-white/15;
}
```
#### Checkbox
```html
<label class="form-checkbox">
<input type="checkbox" class="checkbox-input" />
<span class="checkbox-label">Adresse für zukünftige Bestellungen speichern</span>
</label>
```
**CSS:**
```css
.form-checkbox {
@apply flex items-start gap-3 cursor-pointer;
}
.checkbox-input {
@apply w-5 h-5 mt-0.5;
@apply rounded border-2 border-white/30;
@apply bg-white/10;
@apply checked:bg-accent checked:border-accent;
@apply focus:ring-2 focus:ring-accent;
@apply cursor-pointer;
}
.checkbox-label {
@apply text-base text-white/90;
}
```
---
### 6. Links
```html
<a href="#" class="link-primary">Mehr erfahren</a> <a href="#" class="link-accent">Hier klicken</a>
```
**CSS:**
```css
.link-primary {
@apply text-primary underline;
@apply font-medium;
@apply transition-colors duration-300;
@apply hover:text-primary-light;
}
.link-accent {
@apply text-accent underline;
@apply font-medium;
@apply transition-colors duration-300;
@apply hover:text-accent-hover;
}
```
---
### 7. Logo
**SVG Logo** (Experimenta X-Logo)
Wird in den Design-Vorlagen verwendet. Sollte als Vue-Komponente gespeichert werden:
```vue
<!-- components/ExperimentaLogo.vue -->
<template>
<svg
class="logo"
viewBox="0 0 382.94 87.17"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<!-- SVG paths from design examples -->
</svg>
</template>
<style scoped>
.logo {
width: 300px;
height: auto;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}
/* Tablet */
@media (max-width: 768px) {
.logo {
width: 250px;
}
}
/* Mobile */
@media (max-width: 480px) {
.logo {
width: 200px;
}
}
</style>
```
---
## Animationen & Transitions
### Pulse (für Status Icons)
```css
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
.animate-pulse {
animation: pulse 2s ease-in-out infinite;
}
```
### Shimmer (für Progress Bars)
```css
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
.animate-shimmer {
animation: shimmer 3s ease-in-out infinite;
}
```
### Button Gradient Animation
```css
.btn-primary {
background-size: 300%;
background-position: left;
transition:
background-position 1s ease,
all 0.3s ease;
}
.btn-primary:hover {
background-position: right;
}
```
### Hover Transitions
```css
/* Standard Hover */
.hover-scale {
@apply transition-transform duration-300;
@apply hover:scale-105;
}
/* Logo Hover */
.logo:hover {
transform: scale(1.05);
transition: all 0.3s ease;
}
/* Social Links Hover */
.social-link:hover {
transform: translateY(-3px);
transition: all 0.3s ease;
}
```
---
## Accessibility
### Farb-Kontraste
Alle Text-Farben wurden auf **WCAG AA Standard** getestet:
- **Weiß auf Dark Purple**: ✅ AAA (Kontrast > 7:1)
- **Magenta Buttons**: ✅ AA (Kontrast > 4.5:1)
- **Orange Akzente**: ✅ AA (Kontrast > 4.5:1)
### Focus States
```css
/* Alle interaktiven Elemente */
.focus-visible {
@apply focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 focus:ring-offset-purple-darkest;
}
```
### Screen Reader Support
```html
<!-- Buttons -->
<button aria-label="Zur experimenta Startseite zurückkehren">Zurück</button>
<!-- Status Messages -->
<div role="alert" aria-live="polite">
<p>Ihre Jahreskarte wurde erfolgreich verlängert.</p>
</div>
```
### Keyboard Navigation
- **Tab-Reihenfolge**: Logisch von oben nach unten
- **Focus Indicators**: Sichtbarer Fokus-Ring auf allen interaktiven Elementen
- **Skip Links**: "Zum Hauptinhalt springen" Link am Anfang
---
## Verwendung in Nuxt 4
### 1. Tailwind Config importieren
Siehe `tailwind.config.ts` für die vollständige Theme-Konfiguration.
### 2. Komponenten verwenden
```vue
<template>
<div class="card-glass">
<div class="status-icon bg-success"></div>
<h1 class="text-4xl md:text-3xl sm:text-2xl font-light tracking-tight mb-8">Erfolgreich!</h1>
<p class="text-lg md:text-base leading-relaxed text-white/90">Ihre Aktion war erfolgreich.</p>
<button class="btn-primary mt-8">Weiter</button>
</div>
</template>
```
### 3. shadcn-nuxt Komponenten anpassen
Die shadcn-nuxt Komponenten können mit den experimenta-Farben überschrieben werden:
```vue
<!-- components/ui/button/Button.vue -->
<Button class="btn-primary">Click me</Button>
```
---
## Beispiel: Complete Page Layout
```vue
<template>
<div class="min-h-screen bg-gradient-primary">
<!-- Header -->
<header class="bg-header backdrop-blur-lg sticky top-0 z-50 py-8">
<div class="container-wide mx-auto px-5">
<ExperimentaLogo />
</div>
</header>
<!-- Main Content -->
<main class="container-main mx-auto px-5 py-10">
<div class="card-glass">
<!-- Success Icon -->
<div class="status-icon bg-success"></div>
<!-- Headline -->
<h1 class="text-4xl md:text-3xl sm:text-2xl font-light tracking-tight mb-8">
Verlängerung erfolgreich!
</h1>
<!-- Body Text -->
<p class="text-lg md:text-base leading-relaxed text-white/90 mb-6">
Ihre Pädagogische Jahreskarte wurde erfolgreich verlängert.
</p>
<!-- Info Section -->
<div class="card-info mt-8">
<h3 class="text-accent font-medium text-lg mb-4">Ihre Vorteile</h3>
<p class="text-white/90">
Mit der Jahreskarte erhalten Sie ein Jahr lang freien Eintritt...
</p>
</div>
<!-- Button -->
<button class="btn-primary mt-8">Zur experimenta Startseite</button>
</div>
</main>
<!-- Footer -->
<footer class="bg-footer mt-20">
<div class="container-wide mx-auto px-5 py-15">
<div
class="border-t border-white/10 pt-8 flex flex-wrap justify-between items-center gap-5"
>
<p class="text-white/80">
© 2025 experimenta gGmbH Das Science Center. Alle Rechte vorbehalten.
</p>
<div class="flex gap-8">
<a href="#" class="link-primary">Kontakt</a>
<a href="#" class="link-primary">Impressum</a>
<a href="#" class="link-primary">Datenschutz</a>
</div>
</div>
</div>
</footer>
</div>
</template>
```
---
## Weiterführende Ressourcen
- **Roboto Font:** [Google Fonts](https://fonts.google.com/specimen/Roboto)
- **Tailwind CSS v4:** [Tailwind Docs](https://tailwindcss.com/docs)
- **shadcn-nuxt:** [shadcn-nuxt Docs](https://www.shadcn-vue.com/docs/installation/nuxt.html)
- **WCAG Accessibility:** [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
---
**Maintainer:** Experimenta Team
**Fragen?**`docs@experimenta.science`

103
docs/EXPERIMENTA_BUTTON.md Normal file
View File

@@ -0,0 +1,103 @@
# experimenta Button Component
## Beschreibung
Der experimenta-Button ist eine spezielle Button-Variante, die das offizielle experimenta-Design umsetzt. Der Button verfügt über einen animierten Gradient-Effekt beim Hovern, der von Pink (#e6007e) zu Rot (#e40521) wechselt.
## Design-Eigenschaften
- **Farben**: Pink (#e6007e) zu Rot (#e40521) Gradient
- **Border-Radius**: 25px (abgerundete Ecken)
- **Padding**: 10px 30px (Desktop), 8px 24px (Mobile)
- **Font-Size**: 18px (Desktop), 16px (Mobile)
- **Hover-Effekt**: Animierter Gradient, der sich über 1 Sekunde von links nach rechts bewegt
- **Transition**: Smooth transition für alle Eigenschaften (0.3s ease)
## Verwendung
### Als Button
```vue
<UiButtonButton variant="experimenta" size="experimenta" @click="handleClick">
Button Text
</UiButtonButton>
```
### Als Link
```vue
<UiButtonButton variant="experimenta" size="experimenta" as="a" href="https://www.experimenta.science/">
Zur experimenta Startseite
</UiButtonButton>
```
### Mit NuxtLink
```vue
<UiButtonButton variant="experimenta" size="experimenta" as="NuxtLink" to="/some-page">
Interne Seite
</UiButtonButton>
```
## Props
- **variant**: `"experimenta"` (erforderlich für das experimenta-Design)
- **size**: `"experimenta"` (empfohlen für das richtige Padding und die Schriftgröße)
- **as**: `"button"` (Standard) | `"a"` | `"NuxtLink"` - Element-Typ
- **href** / **to**: URL/Route (wenn `as="a"` oder `as="NuxtLink"`)
- **@click**: Event-Handler (wenn `as="button"`)
## Responsive Verhalten
Der Button passt sich automatisch an mobile Geräte an:
- **Desktop**: 18px Schriftgröße, 10px 30px Padding
- **Mobile (≤480px)**: 16px Schriftgröße, 8px 24px Padding
## Beispiel
Live-Beispiel auf der Startseite: `app/pages/index.vue`
## Technische Details
### Implementierung
Die Button-Komponente verwendet:
- `class-variance-authority` (CVA) für Varianten-Management
- `reka-ui` Primitive für Flexibilität
- Custom CSS für den Gradient-Effekt (`assets/css/main.css`)
- CSS Custom Properties für Farben (`--color-pink`, `--color-pink-dark`)
### Dateien
- **Komponente**: `app/components/ui/button/Button.vue`
- **Varianten**: `app/components/ui/button/index.ts`
- **Styles**: `assets/css/main.css` (`.btn-experimenta`)
## CSS-Implementierung
Der Gradient-Effekt wird mit Custom CSS implementiert:
```css
.btn-experimenta {
background: var(--color-pink);
background-image: linear-gradient(to left, var(--color-pink), var(--color-pink), var(--color-pink-dark), var(--color-pink));
background-size: 300%;
background-position: 0%;
transition: background-position 1s ease, all 0.3s ease;
cursor: pointer;
}
.btn-experimenta:hover {
background-position: 100%;
}
```
## Barrierefreiheit
Der Button unterstützt:
- ✅ Keyboard-Navigation (Tab, Enter, Space)
- ✅ Focus-Styles
- ✅ Screen-Reader (via Primitive-Komponente)
- ✅ Disabled-State

996
docs/PRD.md Normal file
View File

@@ -0,0 +1,996 @@
# Product Requirements Document (PRD)
## my.experimenta.science E-Commerce App
**Version:** 1.0
**Datum:** 28. Oktober 2025
**Status:** Draft
**Autor:** experimenta Development Team
---
## 1. Executive Summary
### 1.1 Projektvision
Die **my.experimenta.science** App ist eine moderne, komponentenbasierte E-Commerce-Plattform für das experimenta Science Center. Sie soll den bestehenden Webshop zunächst ergänzen.
### 1.2 Ziele
**Primäre Ziele:**
- Vereinfachter Online-Verkauf von Makerspace-Jahreskarten
- Mobile-first Nutzererlebnis mit exzellenter Desktop-Kompatibilität
- Nahtlose Integration mit bestehenden Systemen (NAV ERP, Cidaas)
- Skalierbare Architektur für zukünftige Produkterweiterungen
**Geschäftsziele:**
- Steigerung der Online-Verkäufe durch verbesserte UX
- Reduzierung manueller Prozesse durch Automatisierung
- Erhöhung der Kundenzufriedenheit
- Grundlage für digitale Transformation des Ticketing-Systems
### 1.3 Erfolgsmetriken
- Erfolgreiche Verkäufe von Makerspace-Jahreskarten
- Conversion Rate > 3%
- Page Load Time < 2 Sekunden (mobile)
- Fehlerfreie Synchronisation mit NAV ERP
- Positive Nutzerfeedbacks
---
## 2. Produktübersicht
### 2.1 Was ist my.experimenta.science?
Eine spezialisierte E-Commerce-App, die es Besuchern des experimenta Science Centers ermöglicht, Produkte und Services online zu erwerben:
- Jahreskarten für den Makerspace
- Pädagogische Jahreskarten (Post-MVP)
- Experimenta-Tickets mit Platzreservierung (Post-MVP)
- Laborkurse für Schulen (Post-MVP)
### 2.2 Abgrenzung
**Im Scope (MVP):**
- Registrierung und Login
- Anzeige von Makerspace-Jahreskarten
- Warenkorb-Funktionalität
- Checkout-Prozess
- PayPal-Bezahlung
- NAV ERP Push-Integration
**Out of Scope (MVP):**
- Rollen-System (Pädagogen, Unternehmen)
- Pädagogische Jahreskarten
- Genehmigungsworkflows
- Platzreservierung
- Multi-Payment-Provider
- Laborkurse
---
## 3. Zielgruppen
### 3.1 Primäre Zielgruppe (MVP)
**Privatpersonen:**
- Besucher des experimenta Science Centers
- Interessenten am Makerspace
- Alter: 18-65 Jahre
- Technikaffinität: mittel bis hoch
- Gerät: überwiegend Smartphone, teilweise Desktop
### 3.2 Zukünftige Zielgruppen (Post-MVP)
**Pädagogen/Erzieher:**
- Lehrkräfte an Schulen
- Erzieher in Kindergärten
- Benötigen Genehmigungsprozess für vergünstigte Tickets
**Unternehmen:**
- Firmen mit Interesse an Gruppenbesuchen
- Corporate Events
- Teambuilding-Maßnahmen
---
## 4. User Stories & Use Cases
### 4.1 MVP User Stories
#### US-001: Benutzerregistrierung
**Als** Besucher
**möchte ich** mich mit meiner E-Mail-Adresse registrieren
**damit** ich Produkte kaufen kann
**Akzeptanzkriterien:**
- Registrierungsformular mit Feldern: E-Mail, Passwort, Vorname, Nachname
- Passwort-Anforderungen: mind. 8 Zeichen, Groß-/Kleinbuchstaben, Zahl
- Registrierung erfolgt über Cidaas Registration API
- Custom Registrierungs-Maske im experimenta Design (nicht Cidaas hosted)
- Bestätigungs-E-Mail wird von Cidaas versendet
- E-Mail muss bestätigt werden bevor Login möglich ist
- Nach erster Anmeldung wird User-Profil in lokaler DB angelegt (über OAuth2 Callback)
- User erhält Fehlermeldung wenn E-Mail bereits registriert
- Validierung: Client-seitig (UX) + Server-seitig (Sicherheit)
- Übersetzung in Deutsch und Englisch
**Technische Details:**
- Custom Registrierungsseite: `/auth?tab=register`
- POST `/api/auth/register` → Cidaas Registration API
- Response: "Bitte bestätigen Sie Ihre E-Mail"
- User-Profil wird bei erstem Login erstellt (nicht bei Registrierung)
---
#### US-002: Benutzer-Login
**Als** registrierter Nutzer
**möchte ich** mich mit meinen Zugangsdaten anmelden
**damit** ich auf mein Profil und meine Bestellungen zugreifen kann
**Akzeptanzkriterien:**
- Custom Login-Maske im experimenta Design (nicht Cidaas hosted)
- Login erfolgt über OAuth2 Authorization Code Flow mit PKCE
- E-Mail-Adresse als Identifier (kein Benutzername)
- Weiterleitung zur Cidaas Login-Seite für Credential-Eingabe
- Nach erfolgreicher Authentifizierung: OAuth2 Callback
- User-Profil wird in lokaler DB erstellt (erste Anmeldung) oder aktualisiert
- Session wird erstellt (30 Tage Gültigkeit)
- Automatische Weiterleitung zur ursprünglich angeforderten Seite (oder Homepage)
- Bei fehlgeschlagenem Login: Klare Fehlermeldung
- Rate Limiting: Max. 5 Login-Versuche pro 15 Minuten
- "Passwort vergessen"-Link zu Cidaas Password Reset
**Technische Details:**
- Custom Login-Seite: `/auth?tab=login`
- OAuth2 Flow:
1. POST `/api/auth/login` → Redirect zu Cidaas
2. User authentifiziert sich bei Cidaas
3. Cidaas redirected zu `/api/auth/callback?code=xxx`
4. Server exchanged code für tokens
5. User-Profil wird aus Cidaas UserInfo geholt
6. User-Profil in DB erstellt/aktualisiert (via `experimenta_id`)
7. Encrypted session cookie gesetzt
8. Redirect zu Homepage
- Session: HTTP-only, Secure, SameSite=Lax, 30 Tage
---
#### US-002a: Benutzer-Logout
**Als** angemeldeter Nutzer
**möchte ich** mich sicher abmelden
**damit** meine Daten geschützt bleiben (besonders auf gemeinsam genutzten Geräten)
**Akzeptanzkriterien:**
- Logout-Button ist im Benutzerm enü prominent platziert
- Klick auf Logout löscht die Session sofort
- User wird zur Homepage weitergeleitet
- Session-Cookie wird vollständig entfernt
- Nach Logout ist kein Zugriff auf geschützte Bereiche mehr möglich
- Optional: Single Sign-Out bei Cidaas (Logout aus allen Apps)
**Technische Details:**
- POST `/api/auth/logout`
- `clearUserSession(event)` löscht Session-Cookie
- Redirect zu `/`
---
#### US-002b: Session-Management
**Als** angemeldeter Nutzer
**möchte ich** dass meine Session sicher verwaltet wird
**damit** ich nicht nach jeder Interaktion neu anmelden muss, aber dennoch geschützt bin
**Akzeptanzkriterien:**
- Session bleibt 30 Tage gültig (configurable)
- Session wird bei jeder Interaktion automatisch verlängert (sliding expiration)
- Session-Cookie ist verschlüsselt (AES-256-GCM)
- Session-Cookie ist HTTP-only (nicht via JavaScript auslesbar)
- Session-Cookie nur über HTTPS übertragen (Secure flag)
- CSRF-Schutz durch SameSite=Lax Cookie-Attribut
- Nach Ablauf der Session: Automatisches Logout + Weiterleitung zu `/auth`
- User sieht Meldung: "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an."
**Technische Details:**
- Session Implementierung: `nuxt-auth-utils` Module
- Cookie Name: `experimenta-session`
- Verschlüsselung: AES-256-GCM via `nuxt-auth-utils`
- Max-Age: 2592000 Sekunden (30 Tage)
---
#### US-002c: Geschützte Bereiche
**Als** System
**möchte ich** dass bestimmte Bereiche nur für angemeldete Nutzer zugänglich sind
**damit** nicht-autorisierte Zugriffe verhindert werden
**Akzeptanzkriterien:**
- Geschützte Bereiche: Profil, Bestellhistorie, Checkout (teilweise)
- Unangemeldete User werden zu `/auth` weitergeleitet
- Nach erfolgreichem Login: Automatische Weiterleitung zur ursprünglich angeforderten Seite
- Ursprüngliche URL wird temporär gespeichert (max. 10 Minuten)
- API-Endpoints prüfen Session und geben 401 bei fehlender Authentifizierung
- Klare visuelle Kennzeichnung geschützter Bereiche (z.B. Schloss-Icon)
**Technische Details:**
- Middleware: `middleware/auth.ts`
- Usage: `definePageMeta({ middleware: 'auth' })`
- Redirect-Cookie: `redirect_after_login` (10min TTL)
- Protected API: `requireUserSession(event)` wirft 401
---
#### US-002d: Sicherheit & Rate Limiting
**Als** System
**möchte ich** dass Authentifizierungs-Endpoints vor Missbrauch geschützt sind
**damit** Brute-Force-Angriffe und Spam verhindert werden
**Akzeptanzkriterien:**
- Login: Max. 5 Versuche pro 15 Minuten pro IP-Adresse
- Registrierung: Max. 3 Versuche pro Stunde pro IP-Adresse
- Bei Überschreitung: HTTP 429 (Too Many Requests) mit Retry-After Header
- Klare Fehlermeldung: "Zu viele Versuche. Bitte versuchen Sie es in X Sekunden erneut."
- Rate Limit-Zähler wird bei erfolgreichem Login zurückgesetzt
- PKCE (Proof Key for Code Exchange) wird für OAuth2 verwendet
- State-Parameter schützt vor CSRF-Angriffen
- JWT-Tokens von Cidaas werden validiert (Signatur, Expiration, Issuer, Audience)
**Technische Details:**
- Rate Limiting Middleware: `server/middleware/rate-limit.ts`
- In-Memory Store für Rate Limits (Production: Redis empfohlen)
- PKCE: Code verifier (64 chars random) → SHA-256 Challenge
- State: 32 bytes random string, validiert im Callback
- JWT Validation: `jose` Library mit JWKS Caching
---
#### US-003: Makerspace-Jahreskarte ansehen
**Als** Nutzer
**möchte ich** Details zur Makerspace-Jahreskarte sehen
**damit** ich informiert eine Kaufentscheidung treffen kann
**Akzeptanzkriterien:**
- Produktseite zeigt: Name, Beschreibung, Preis, Bild
- Informationen kommen aus der lokalen DB (synchronisiert von NAV)
- Call-to-Action: "In den Warenkorb"
- Mobile-optimierte Darstellung
---
#### US-004: Produkt in den Warenkorb legen
**Als** Nutzer
**möchte ich** die Jahreskarte in den Warenkorb legen
**damit** ich sie später kaufen kann
**Akzeptanzkriterien:**
- Button "In den Warenkorb" ist prominent platziert
- Warenkorb-Icon zeigt Anzahl der Artikel
- Feedback nach Hinzufügen (z.B. Toast-Notification)
- Warenkorb ist persistent (auch nach Logout)
---
#### US-005: Warenkorb ansehen
**Als** Nutzer
**möchte ich** meinen Warenkorb einsehen und bearbeiten
**damit** ich meine Bestellung überprüfen kann
**Akzeptanzkriterien:**
- Warenkorb zeigt alle hinzugefügten Artikel
- Menge kann angepasst werden
- Artikel können entfernt werden
- Gesamtpreis wird angezeigt
- Button "Zur Kasse" führt zum Checkout
---
#### US-006: Checkout durchführen
**Als** Nutzer
**möchte ich** meine Bestellung abschließen
**damit** ich die Jahreskarte erhalte
**Akzeptanzkriterien:**
- Übersicht der Bestellung (Artikel, Preis)
- Eingabe/Bestätigung von Rechnungsdaten
- Auswahl der Zahlungsmethode (MVP: nur PayPal)
- Weiterleitung zu PayPal
- Nach erfolgreicher Zahlung: Bestätigungsseite
---
#### US-007: Bestellbestätigung erhalten
**Als** Nutzer
**möchte ich** eine Bestätigung meiner Bestellung sehen
**damit** ich weiß, dass der Kauf erfolgreich war
**Akzeptanzkriterien:**
- Bestätigungsseite mit Bestellnummer
- E-Mail mit Bestelldetails und Jahreskarte (PDF/Link)
- Bestellung wird in der Bestellhistorie angezeigt
- Daten werden an NAV ERP übermittelt
---
#### US-008: Gespeicherte Rechnungsadresse verwenden
**Als** wiederkehrender Nutzer
**möchte ich** meine Rechnungsadresse gespeichert haben
**damit** ich sie beim nächsten Kauf nicht erneut eingeben muss
**Akzeptanzkriterien:**
- Beim Checkout wird gespeicherte Adresse automatisch vorausgefüllt
- Option "Adresse für zukünftige Käufe speichern" ist beim ersten Kauf vorausgewählt
- Gespeicherte Adresse kann im Profil bearbeitet werden
- Adresse kann beim Checkout vor Abschluss editiert werden
- Im Profil unter `/profil/adresse` einsehbar und änderbar
---
### 4.2 Post-MVP User Stories
#### US-101: Rollenauswahl nach Registrierung
**Als** neuer Nutzer
**möchte ich** nach dem ersten Login meine Rolle auswählen
**damit** ich auf für mich relevante Produkte zugreifen kann
**Akzeptanzkriterien:**
- Modal/Seite zur Rollenauswahl nach erstem Login
- Optionen: Privatperson, Pädagoge/Erzieher, Unternehmen
- Auswahl wird im User-Profil gespeichert
- Pädagogen-Rolle löst Genehmigungsprozess aus
---
#### US-102: Pädagogische Jahreskarte beantragen
**Als** Pädagoge
**möchte ich** eine pädagogische Jahreskarte beantragen
**damit** ich die experimenta kostenlos besuchen kann
**Akzeptanzkriterien:**
- Antragsformular mit Nachweis (Schulnachweis, etc.)
- Status: "In Prüfung"
- Kann reservieren, aber nicht kaufen
- Benachrichtigung bei Genehmigung/Ablehnung
---
## 5. Funktionale Anforderungen
### 5.1 Authentifizierung & Benutzerverwaltung
#### F-001: Cidaas Integration
- Integration mit Cidaas über OIDC/OAuth2
- Custom Registrierungs- und Login-Masken im experimenta Design
- E-Mail-basierte Registrierung (minimal)
- Session Management
#### F-002: User-Profil Verwaltung
- User-Profile werden in lokaler PostgreSQL-DB gespeichert
- Cidaas dient nur zur Authentifizierung
- Verknüpfung über Cidaas User-ID
- Profildaten: E-Mail, Name, Adresse (für Rechnungen)
---
### 5.2 Produktverwaltung
#### F-003: Produkt-Synchronisation
- NAV ERP sendet Produktdaten per Push an Server-Endpunkt
- Endpunkt: `POST /api/erp/products`
- Produktdaten werden in lokaler DB gespeichert
- Felder: ID, Name, Beschreibung, Preis, Lagerbestand, Status
#### F-004: Produktanzeige
- Produktseite für Makerspace-Jahreskarten
- Responsives Layout (mobile-first)
- Bilder und Texte aus lokaler DB (synchronisiert via X-API)
- Preisanzeige in Euro
---
### 5.3 Warenkorb & Checkout
#### F-005: Warenkorb-Funktionalität
- Session-basierter Warenkorb für nicht-angemeldete User
- DB-persistenter Warenkorb für angemeldete User
- CRUD-Operationen: Hinzufügen, Entfernen, Mengenänderung
- Warenkorb-Icon mit Badge (Artikelanzahl)
#### F-006: Checkout-Prozess
- Schritt 1: Warenkorb-Übersicht
- Schritt 2: Rechnungsdaten
- Schritt 3: Zahlungsmethode (MVP: nur PayPal)
- Schritt 4: Bestellübersicht & Bestätigung
#### F-007: PayPal Integration
- PayPal Checkout Integration
- Redirect zu PayPal für Zahlung
- Webhook für Payment-Bestätigung
- Fehlerbehandlung bei fehlgeschlagener Zahlung
---
### 5.4 Bestellverwaltung
#### F-008: Bestellung speichern
- Bestellung wird nach erfolgreicher Zahlung in DB gespeichert
- Status: "Bezahlt", "In Bearbeitung", "Abgeschlossen"
- Bestellnummer generieren
- Timestamp & User-ID verknüpfen
#### F-009: Bestellbestätigung
- Bestätigungsseite nach erfolgreichem Kauf
- E-Mail mit Bestelldetails
- PDF-Ticket/Jahreskarte als Anhang oder Download-Link
#### F-010: Bestellhistorie
- User kann eigene Bestellungen einsehen
- Filtermöglichkeiten: Status, Datum
- Details-Ansicht pro Bestellung
---
### 5.5 ERP & API Integrationen
#### F-011: NAV ERP Push-Endpunkt
- REST-API Endpunkt: `POST /api/erp/products`
- Authentifizierung via API-Key oder OAuth
- Payload: Produktdaten (JSON)
- Validierung & Speicherung in DB
- Logging & Error Handling
#### F-012: X-API Integration
- Abruf von Veranstaltungstexten und Bildern
- Caching in lokaler DB
- Regelmäßige Synchronisation (Cronjob)
#### F-013: Bestellung an NAV senden (via X-API)
- Nach erfolgreichem Kauf: Bestellung an NAV übermitteln
- REST-API Call zu X-API Endpoint `/shopware/order`
- **Authentifizierung:** HTTP Basic Auth (Username + Password)
- X-API konvertiert JSON zu SOAP für NAV ERP
- Retry-Mechanismus bei Fehlern (exponentieller Backoff)
- Status-Tracking
- **Environments:**
- Development: `https://x-api-dev.experimenta.science`
- Staging: `https://x-api-stage.experimenta.science`
- Production: `https://x-api.experimenta.science`
---
## 6. Nicht-funktionale Anforderungen
### 6.1 Performance
- **Page Load Time:** < 2 Sekunden (mobile, 4G)
- **Time to Interactive:** < 3 Sekunden
- **API Response Time:** < 500ms (95th percentile)
- **Checkout Response:** < 1 Sekunde (nach PayPal Erfolg)
- **Concurrent Users:** 500+ gleichzeitige Nutzer
- **Queue Processing:** Order submission innerhalb 5 Minuten nach Payment
### 6.2 Skalierbarkeit
- Horizontal skalierbar (Docker Container)
- Stateless Server-Design
- DB Connection Pooling
- Redis für Caching-Strategie (Redis optional)
### 6.3 Sicherheit
- **HTTPS only** (TLS 1.3)
- **DSGVO-konform:** Datensparsamkeit, Einwilligungen, Löschkonzept
- **PCI-DSS-konform:** Keine Speicherung von Kreditkartendaten
- **Input Validation:** Alle User-Inputs validieren
- **Rate Limiting:** API-Endpunkte gegen Missbrauch schützen
- **Secrets Management:** Keine Secrets im Code (Environment Variables)
### 6.4 Verfügbarkeit
- **Uptime:** 99.5% (außer geplante Wartung)
- **Backup:** Tägliche DB-Backups
- **Disaster Recovery:** Wiederherstellung innerhalb 24h
### 6.5 Usability
- **Mobile-first Design:** Optimiert für Smartphones
- **Responsive:** Funktioniert auf allen Geräten (320px - 4K)
- **Accessibility:** WCAG 2.1 Level AA konform
- **Intuitive Navigation:** Maximal 3 Klicks zum Ziel
- **Corporate Design:** experimenta Styleguide (Farben, Fonts)
### 6.6 Wartbarkeit
- **Clean Code:** ESLint, Prettier
- **Dokumentation:** Inline-Kommentare, README
- **Testing:** Unit Tests (>80% Coverage), E2E Tests
- **CI/CD:** Automatisierte Builds & Deployments
- **Monitoring:** Logging, Error Tracking (Sentry optional)
---
## 7. User Experience & Design
### 7.1 Design-Prinzipien
- **Mobile-first:** Primär für Smartphones optimiert
- **Minimal:** Fokus auf Kernfunktionen, keine Ablenkungen
- **Schnell:** Kurze Ladezeiten, optimierte Assets
- **Konsistent:** Einheitliches Design im gesamten System
### 7.2 Corporate Design Integration
- Farben aus experimenta Styleguide
- Schriftarten aus experimenta Styleguide
- Logo-Nutzung gemäß Brand Guidelines
- Icons: Material Design Icons oder Heroicons
### 7.3 Key Screens (MVP)
#### Homepage
- Hero-Bereich mit Call-to-Action
- Makerspace-Jahreskarte prominent anzeigen
- Login/Registrierung Button (Header)
- Warenkorb-Icon (Header)
#### Produktseite
- Großes Produktbild
- Name, Beschreibung, Preis
- "In den Warenkorb" Button (sticky)
- Zusätzliche Informationen (Accordion)
#### Warenkorb
- Liste der Artikel
- Menge anpassen, entfernen
- Gesamtpreis
- "Zur Kasse" Button
#### Checkout
- Multi-Step Form (Progress Indicator)
- Rechnungsdaten (Formular)
- Zahlungsmethode (PayPal Button)
- Bestellübersicht
#### Bestätigung
- Erfolgs-Icon
- Bestellnummer
- Zusammenfassung
- Link zur Bestellhistorie
---
## 8. Technische Anforderungen
### 8.1 Tech Stack
Siehe [TECH_STACK.md](./TECH_STACK.md) für Details.
**Übersicht:**
- Frontend: Nuxt 4
- UI-Framework: Nuxt UI oder shadcn-vue
- Backend: Nuxt Server APIs
- Datenbank: PostgreSQL
- ORM: Drizzle
- Auth: Cidaas (OIDC/OAuth2)
- Payment: PayPal SDK
- Deployment: Docker, Hetzner Proxmox
- CI/CD: GitLab
### 8.2 Hosting & Infrastructure
- **Hosting:** Hetzner Dedicated Server / VPS
- **Virtualisierung:** Proxmox Container
- **Container Runtime:** Docker
- **Reverse Proxy:** Nginx oder Traefik
- **SSL:** Let's Encrypt (automatisch)
- **Domain:** my.experimenta.science
### 8.3 CI/CD Pipeline
- **Repository:** GitLab (intern gehostet)
- **Pipeline:** GitLab CI/CD
- **Deploy-Strategie:** Blue-Green oder Rolling Deployment
- **SSH-Zugang:** GitLab Runner mit SSH-Key oder Runner auf Server
- **Stages:** Build → Test → Deploy (Staging) → Deploy (Production)
---
## 9. Datenmodell (MVP)
### 9.1 Hauptentitäten
#### User
```typescript
{
id: string(UUID)
cidaas_user_id: string(unique)
email: string
first_name: string ? last_name : string ? phone : string ? created_at : timestamp
updated_at: timestamp
}
```
#### Product
```typescript
{
id: string (UUID)
nav_product_id: string (unique)
name: string
description: text
price: decimal
image_url: string?
stock: integer
status: enum (active, inactive)
created_at: timestamp
updated_at: timestamp
}
```
#### Cart
```typescript
{
id: string (UUID)
user_id: string? (FK to User, null for anonymous)
session_id: string? (for anonymous users)
created_at: timestamp
updated_at: timestamp
}
```
#### CartItem
```typescript
{
id: string (UUID)
cart_id: string (FK to Cart)
product_id: string (FK to Product)
quantity: integer
price_snapshot: decimal (Preis zum Zeitpunkt des Hinzufügens)
created_at: timestamp
}
```
#### Order
```typescript
{
id: string (UUID)
order_number: string (unique, z.B. "EXP-2025-00001")
user_id: string (FK to User)
status: enum (pending, paid, processing, completed, cancelled)
total_amount: decimal
payment_method: enum (paypal)
payment_id: string? (PayPal Transaction ID)
billing_address: jsonb
created_at: timestamp
updated_at: timestamp
}
```
#### OrderItem
```typescript
{
id: string (UUID)
order_id: string (FK to Order)
product_id: string (FK to Product)
quantity: integer
price: decimal
created_at: timestamp
}
```
---
## 10. API-Spezifikation
### 10.1 Public API Endpoints
#### Authentication
- `POST /api/auth/login` - Initiiert Cidaas Login
- `POST /api/auth/callback` - OAuth Callback von Cidaas
- `POST /api/auth/logout` - Beendet Session
#### Products
- `GET /api/products` - Liste aller aktiven Produkte
- `GET /api/products/:id` - Details zu einem Produkt
#### Cart
- `GET /api/cart` - Warenkorb abrufen
- `POST /api/cart/items` - Artikel hinzufügen
- `PATCH /api/cart/items/:id` - Menge ändern
- `DELETE /api/cart/items/:id` - Artikel entfernen
#### Orders
- `POST /api/orders` - Bestellung erstellen
- `GET /api/orders` - Bestellhistorie
- `GET /api/orders/:id` - Bestelldetails
#### Payment
- `POST /api/payment/paypal/create` - PayPal Order erstellen
- `POST /api/payment/paypal/capture` - PayPal Zahlung erfassen
- `POST /api/payment/paypal/webhook` - PayPal Webhook
---
### 10.2 Internal API Endpoints (ERP Integration)
#### NAV ERP Push
- `POST /api/erp/products` - Produkte von NAV empfangen
- `POST /api/erp/stock` - Lagerbestände aktualisieren
**Authentication:** API-Key oder OAuth Client Credentials
**Payload Example (Produkt):**
```json
{
"nav_product_id": "MS-JK-2025",
"name": "Makerspace Jahreskarte 2025",
"description": "Jahresticket für unbegrenzten Zugang zum Makerspace",
"price": 99.0,
"stock": 500,
"status": "active",
"image_url": "https://api.experimenta.science/images/ms-jk.jpg"
}
```
---
## 11. Abhängigkeiten & Risiken
### 11.1 Externe Abhängigkeiten
- **Cidaas:** Verfügbarkeit und Stabilität der Auth-Platform
- **NAV ERP:** Zuverlässigkeit der Push-Integration
- **X-API:** Verfügbarkeit der Veranstaltungsdaten
- **PayPal:** Uptime des Payment-Gateways
- **Hetzner:** Infrastruktur-Verfügbarkeit
### 11.2 Technische Risiken
- **Cidaas Integration:** Komplexität der Custom-UI Integration
- **ERP Synchronisation:** Dateninkonsistenzen, Timing-Probleme
- **Payment Failures:** Umgang mit fehlgeschlagenen Transaktionen
- **Skalierung:** Performance bei hohem Nutzeraufkommen
### 11.3 Mitigationsstrategien
- **Cidaas:** Ausführliches Testing, Fallback-Mechanismen
- **ERP:** Retry-Logik, Monitoring, manuelle Sync-Option
- **Payment:** Klare Error-Messages, Support-Kontakt prominent
- **Skalierung:** Load Testing, horizontale Skalierung vorbereiten
---
## 12. Zeitplan & Meilensteine
### 12.1 MVP (Phase 1) - 8-12 Wochen
**Sprint 1-2 (Woche 1-4): Foundation**
- Projekt-Setup (Nuxt 4, Drizzle, PostgreSQL)
- Datenbank-Schema erstellen
- Basic Layout & Routing
- Cidaas Integration (Auth)
**Sprint 3-4 (Woche 5-8): Core Features**
- Produktseite implementieren
- Warenkorb-Funktionalität
- NAV ERP Push-Endpunkt
- User-Profil
**Sprint 5-6 (Woche 9-12): Checkout & Payment**
- Checkout-Flow implementieren
- PayPal Integration
- Bestellbestätigung & E-Mail
- Testing & Bug Fixes
**Sprint 7 (Optional): Launch Preparation**
- UAT (User Acceptance Testing)
- Performance-Optimierung
- Dokumentation
- Production Deployment
---
### 12.2 Post-MVP Roadmap
**Phase 2 (Q2 2025): Pädagogen & Rollen**
- Rollen-System implementieren
- Pädagogische Jahreskarten
- Genehmigungsworkflow
- Admin-Panel (Basic)
**Phase 3 (Q3 2025): Experimenta-Tickets**
- Ticket-Varianten
- Science Dome Platzreservierung
- Kalender-Integration
- Multi-Payment-Provider
**Phase 4 (Q4 2025): Laborkurse**
- Kurs-Verwaltung
- Schulen-Accounts
- Gruppenbuchungen
- Erweiterte Reporting-Funktionen
---
## 13. Testing-Strategie
### 13.1 Test-Arten
**Unit Tests:**
- Nuxt Composables
- Utility Functions
- Drizzle Queries (Mocked)
- Ziel: >80% Coverage
**Integration Tests:**
- API Endpoints
- Database Operations
- Auth Flow
**E2E Tests:**
- User Flows (Registrierung bis Kauf)
- Payment Flow (mit Sandbox)
- Responsive Design
### 13.2 Test-Tools
- **Vitest:** Unit & Integration Tests
- **Playwright:** E2E Tests
- **MSW (Mock Service Worker):** API Mocking
- **Testing Library:** Component Tests
---
## 14. Monitoring & Support
### 14.1 Monitoring
- **Application Monitoring:** Error Tracking (Sentry optional)
- **Performance Monitoring:** Core Web Vitals
- **Uptime Monitoring:** Ping-Service
- **Logging:** Strukturiertes Logging (JSON)
### 14.2 Support
- **E-Mail-Support:** support@experimenta.science
- **FAQ-Seite:** Häufige Fragen & Antworten
- **Status-Page:** System-Status & geplante Wartungen
---
## 15. Open Questions
### 15.1 Zu klären
- [ ] Welches UI-Framework: Nuxt UI vs. shadcn-vue?
- [ ] Detailliertes Design der Custom Cidaas Login/Registrierungs-UI
- [ ] Exakte Struktur der NAV ERP Push-Payload
- [ ] X-API Dokumentation & Zugang
- [ ] E-Mail-Versand: Eigener SMTP oder Service (SendGrid, etc.)?
- [ ] Ticket-Format: PDF, QR-Code, oder anderes?
- [ ] Admin-Panel: Ab wann benötigt?
### 15.2 Entscheidungen treffen
- [ ] GitLab Runner: Auf Server oder SSH-Zugang?
- [ ] Caching-Strategie: Redis verwenden?
- [ ] Staging-Environment: Separate Instanz?
---
## 16. Glossar
| Begriff | Bedeutung |
| ---------------- | ---------------------------------------------------------- |
| **MVP** | Minimum Viable Product - Erste funktionsfähige Version |
| **NAV ERP** | Microsoft Dynamics NAV - ERP-System der experimenta |
| **X-API** | Externe API für Veranstaltungsdaten |
| **Cidaas** | Customer Identity and Access Management Platform von Widas |
| **OIDC** | OpenID Connect - Authentifizierungsprotokoll |
| **JK** | Jahreskarte |
| **MS** | Makerspace |
| **Päd. JK** | Pädagogische Jahreskarte |
| **Science Dome** | 150-Sitzer Kino/Planetarium der experimenta |
---
## 17. Anhang
### 17.1 Referenzen
- [Nuxt 4 Dokumentation](https://nuxt.com)
- [Drizzle ORM](https://orm.drizzle.team)
- [Cidaas Dokumentation](https://docs.cidaas.com)
- [PayPal Developer Docs](https://developer.paypal.com)
### 17.2 Änderungshistorie
| Version | Datum | Autor | Änderungen |
| ------- | ---------- | -------- | ---------------------- |
| 1.0 | 2025-10-28 | Dev Team | Initiales PRD erstellt |
---
**Ende des Dokuments**

1698
docs/TECH_STACK.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,132 @@
<script setup lang="ts">
/**
* ExperimentaButton Component
*
* Experimenta-branded button with animated gradient background.
* Based on the experimenta Design System.
*
* @example
* <ExperimentaButton>Click me</ExperimentaButton>
* <ExperimentaButton variant="secondary">Cancel</ExperimentaButton>
* <ExperimentaButton size="small">Small</ExperimentaButton>
*/
interface Props {
/** Button variant */
variant?: 'primary' | 'secondary'
/** Button size */
size?: 'small' | 'medium' | 'large'
/** Disabled state */
disabled?: boolean
/** Button type */
type?: 'button' | 'submit' | 'reset'
/** Link behavior (renders as <a> tag) */
href?: string
/** Target for links */
target?: '_blank' | '_self' | '_parent' | '_top'
}
withDefaults(defineProps<Props>(), {
variant: 'primary',
size: 'large',
disabled: false,
type: 'button',
})
const emit = defineEmits<{
click: [event: MouseEvent]
}>()
function handleClick(event: MouseEvent) {
emit('click', event)
}
</script>
<template>
<component
:is="href ? 'a' : 'button'"
:href="href"
:target="href ? target : undefined"
:type="!href ? type : undefined"
:disabled="!href ? disabled : undefined"
:class="[
'btn-experimenta',
`btn-${variant}`,
`btn-${size}`,
{
'btn-disabled': disabled,
},
]"
@click="handleClick"
>
<slot />
</component>
</template>
<style scoped>
/* Base Button Styles */
.btn-experimenta {
@apply inline-block cursor-pointer;
@apply font-medium text-white;
@apply transition-all;
@apply outline-0 border-0;
@apply rounded-2xl;
text-decoration: none;
line-height: 1.7em;
}
/* Primary Variant */
.btn-primary {
background: #e6007e;
background-image: linear-gradient(to left, #e6007e, #e6007e, #e40521, #e6007e);
background-size: 300%;
background-position: left;
transition:
background-position 1s ease,
all 0.3s ease;
}
.btn-primary:hover:not(.btn-disabled) {
background-position: right;
}
/* Secondary Variant */
.btn-secondary {
@apply bg-transparent border-2 border-accent text-accent;
}
.btn-secondary:hover:not(.btn-disabled) {
@apply bg-accent text-white;
}
/* Sizes */
.btn-large {
@apply text-lg px-8 py-2.5;
}
.btn-medium {
@apply text-base px-6 py-2;
}
.btn-small {
@apply text-base px-6 py-2;
}
/* Responsive */
@media (max-width: 480px) {
.btn-large {
@apply text-base px-6 py-2;
}
}
/* Disabled State */
.btn-disabled {
@apply opacity-50 cursor-not-allowed;
}
/* Focus State (Accessibility) */
.btn-experimenta:focus-visible {
@apply outline-none ring-2 ring-accent ring-offset-2;
ring-offset-color: var(--color-purple-darkest, #0f051d);
}
</style>

View File

@@ -0,0 +1,115 @@
<script setup lang="ts">
/**
* ExperimentaCard Component
*
* Glass-morphism card component based on the experimenta Design System.
*
* @example
* <ExperimentaCard>Content here</ExperimentaCard>
* <ExperimentaCard variant="info">Info section</ExperimentaCard>
* <ExperimentaCard title="Card Title">Content</ExperimentaCard>
*/
interface Props {
/** Card variant */
variant?: 'glass' | 'info' | 'contact' | 'progress'
/** Card title (optional) */
title?: string
/** Title color (only for info/contact variants) */
titleColor?: 'accent' | 'primary'
/** Show left accent border */
accentBorder?: boolean
}
withDefaults(defineProps<Props>(), {
variant: 'glass',
titleColor: 'accent',
accentBorder: false,
})
</script>
<template>
<div
:class="[
'card-experimenta',
`card-${variant}`,
{
'card-accent-border': accentBorder || variant !== 'glass',
},
]"
>
<!-- Title Slot or Prop -->
<h3 v-if="title || $slots.title" :class="['card-title', `title-${titleColor}`]">
<slot name="title">{{ title }}</slot>
</h3>
<!-- Main Content -->
<slot />
</div>
</template>
<style scoped>
/* Base Card Styles */
.card-experimenta {
@apply rounded-xl;
@apply p-8 md:p-6 sm:p-5;
@apply transition-all duration-300;
}
/* Glass-morphism Variant (Main Card) */
.card-glass {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
backdrop-filter: blur(15px);
@apply border border-white/20;
@apply shadow-glass;
@apply rounded-2xl;
@apply p-15 md:p-10 sm:p-8;
}
@media (max-width: 768px) {
.card-glass {
@apply rounded-lg;
}
}
/* Info Variant */
.card-info {
@apply bg-white/8;
}
/* Contact Variant */
.card-contact {
@apply bg-white/8;
@apply text-center;
}
/* Progress Variant */
.card-progress {
@apply bg-white/8;
@apply rounded-2xl md:rounded-lg;
}
/* Accent Border (Left) */
.card-accent-border {
@apply border-l-4 border-accent;
}
/* Card Title */
.card-title {
@apply font-medium mb-4;
@apply text-lg md:text-base;
}
.title-accent {
@apply text-accent;
}
.title-primary {
@apply text-primary;
}
/* Hover Effect (Optional) */
.card-experimenta:hover {
@apply shadow-2xl;
}
</style>

View File

@@ -0,0 +1,216 @@
<script setup lang="ts">
/**
* ExperimentaLogo Component
*
* Official experimenta Science Center logo (X-Logo with gradients).
* SVG is taken from the design templates.
*
* @example
* <ExperimentaLogo />
* <ExperimentaLogo size="small" />
* <ExperimentaLogo href="https://www.experimenta.science" />
*/
interface Props {
/** Logo size */
size?: 'small' | 'medium' | 'large'
/** Link URL (if logo should be clickable) */
href?: string
/** Link target */
target?: '_blank' | '_self'
/** Accessible label */
ariaLabel?: string
}
withDefaults(defineProps<Props>(), {
size: 'large',
href: undefined,
target: '_self',
ariaLabel: 'experimenta Science Center Logo',
})
</script>
<template>
<component
:is="href ? 'a' : 'div'"
:href="href"
:target="href ? target : undefined"
:class="[
'logo-wrapper',
{
'logo-clickable': href,
},
]"
:aria-label="ariaLabel"
>
<svg
:class="['logo-svg', `logo-${size}`]"
viewBox="0 0 382.94 87.17"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
role="img"
:aria-label="ariaLabel"
>
<defs>
<!-- Gradients for logo -->
<linearGradient
id="logo-gradient-a"
x1="102.63"
y1="152.32"
x2="135.19"
y2="191.11"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ce0f60" />
<stop offset="0.47" stop-color="#de0b75" />
<stop offset="0.59" stop-color="#e4097d" />
</linearGradient>
<linearGradient
id="logo-gradient-b"
x1="104.87"
y1="170.45"
x2="104.87"
y2="170.45"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ab1a4e" />
<stop offset="0.43" stop-color="#9f1d4f" />
<stop offset="0.57" stop-color="#9b1e4f" />
</linearGradient>
<linearGradient
id="logo-gradient-c"
x1="68.79"
y1="182.84"
x2="154.66"
y2="182.84"
xlink:href="#logo-gradient-b"
/>
<linearGradient
id="logo-gradient-d"
x1="94.04"
y1="182.21"
x2="114.5"
y2="126"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.22" stop-color="#e4097d" />
<stop offset="0.32" stop-color="#e4115e" />
<stop offset="0.45" stop-color="#e5193d" />
<stop offset="0.55" stop-color="#e51e28" />
<stop offset="0.62" stop-color="#e52021" />
<stop offset="0.9" stop-color="#f7a822" />
</linearGradient>
</defs>
<!-- X Logo -->
<polygon
points="143.78 50 151.18 39.6 144.43 39.6 139.68 46.33 135.13 39.6 127.79 39.6 135.32 50.08 127.29 61.23 134.09 61.23 139.3 53.78 144.43 61.23 151.59 61.23 143.78 50"
fill="#fff"
/>
<!-- "experimenta" Text -->
<path
d="M245.79,175.33a9.2,9.2,0,0,0-1.85-3.39,7.28,7.28,0,0,0-2.9-2,10.29,10.29,0,0,0-3.65-.63c-3.12,0-5.47.95-7,2.82l-.56-2.23h-7.72v5.29h3.13v24.7h6.13v-8.4a8.29,8.29,0,0,0,1.7.42,17.3,17.3,0,0,0,2.6.19,11.8,11.8,0,0,0,4.53-.82,9.29,9.29,0,0,0,3.39-2.39,10.78,10.78,0,0,0,2.11-3.78,15.69,15.69,0,0,0,.74-5A16,16,0,0,0,245.79,175.33Zm-12.76,0a5.26,5.26,0,0,1,2.73-.75,4,4,0,0,1,3.12,1.4,5.85,5.85,0,0,1,1.25,4,10.56,10.56,0,0,1-.4,3.12,5.84,5.84,0,0,1-1.1,2.09,4.11,4.11,0,0,1-1.62,1.18,7.15,7.15,0,0,1-4.21.12,4.71,4.71,0,0,1-1.43-.58v-8.48A3.79,3.79,0,0,1,233,175.35Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<!-- Additional text paths omitted for brevity - see design-example1.html for full SVG -->
<!-- Gradient Logo Mark (X with colors) -->
<path
d="M93.1,181.53l20.42-19.22c.87-.76,1.61-1.66,2.61-1.8,1.19-.17,3,1.09,3.3,1.28s10.7,6.64,12.57,7.77l15.75,9.71c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53h0s-17.5-10.32-22.43-13.18a22.83,22.83,0,0,0-11-3c-4.71.09-8.62,2.32-12.24,5h0l-24,18.2,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83A17.88,17.88,0,0,0,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#logo-gradient-a)"
/>
<path
d="M104.87,170.45h0"
transform="translate(-68.76 -130.29)"
fill="url(#logo-gradient-b)"
/>
<path
d="M93.1,181.53h0l11.77-11.08a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11-7.26,5.5s-4.11,2.67-4,6.32c.15,4.65,5.34,6.69,5.34,6.69l30.63,13.13a35.93,35.93,0,0,0,11.38,2.53c3.39.08,6.83-1.14,10.49-2.24l24.76-8.46c1.26-.41,3.26-1.65,3.26-3.17,0-1.2-1.57-2.73-3.33-3.51a16.28,16.28,0,0,0-8.57-1.19c-4.7.44-25.95,7.65-25.95,7.65L93.16,184.23a1.28,1.28,0,0,1-.91-1.58A2.68,2.68,0,0,1,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#logo-gradient-c)"
/>
<path
d="M147.75,179.27c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53L132,169.56l-27.13.89h0a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73h0a66.73,66.73,0,0,0,7.06.19C107.65,182,144.08,180.38,147.75,179.27Z"
transform="translate(-68.76 -130.29)"
fill="#e4097d"
/>
<path
d="M104.87,170.45a3.26,3.26,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.67-9-3-3.55a1.94,1.94,0,0,1-.41-1.27,2.18,2.18,0,0,1,1-1.83L110,141.9a6.43,6.43,0,0,1,1.81-.87,5.82,5.82,0,0,1,1.86.09l16.49,2.64a24.38,24.38,0,0,0,9.39-.52c1.94-.49,4.31-1.25,5.39-2.91s-.6-2.9-1.11-3.27c-2.08-1.5-4.67-1.92-7.18-2.32l-25.48-4.08a23.84,23.84,0,0,0-10.88.57A19.61,19.61,0,0,0,95,133.6L71.44,149.36a6.34,6.34,0,0,0-1.08,9.38l.21.27,13.12,17a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73Z"
transform="translate(-68.76 -130.29)"
fill="url(#logo-gradient-d)"
/>
</svg>
</component>
</template>
<style scoped>
/* Logo Wrapper */
.logo-wrapper {
@apply flex items-center;
@apply transition-all duration-300;
}
.logo-clickable {
@apply cursor-pointer no-underline;
}
.logo-clickable:hover .logo-svg {
transform: scale(1.05);
}
/* Logo SVG */
.logo-svg {
@apply h-auto;
@apply transition-transform duration-300;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}
/* Logo Sizes */
.logo-large {
@apply w-[300px];
}
.logo-medium {
@apply w-[250px];
}
.logo-small {
@apply w-[200px];
}
/* Responsive */
@media (max-width: 768px) {
.logo-large {
@apply w-[250px] max-w-[90%];
}
.logo-medium {
@apply w-[200px] max-w-[85%];
}
}
@media (max-width: 480px) {
.logo-large {
@apply w-[200px] max-w-[85%];
}
.logo-medium {
@apply w-[180px] max-w-[80%];
}
.logo-small {
@apply w-[150px] max-w-[75%];
}
}
/* Focus State */
.logo-clickable:focus-visible {
@apply outline-none ring-2 ring-accent ring-offset-2;
ring-offset-color: var(--color-purple-darkest, #0f051d);
}
</style>

View File

@@ -0,0 +1,125 @@
<script setup lang="ts">
/**
* ExperimentaStatusMessage Component
*
* Status message component with animated icon.
* Used for success, error, warning, and info states.
*
* @example
* <ExperimentaStatusMessage type="success" title="Erfolg!">
* Ihre Aktion war erfolgreich.
* </ExperimentaStatusMessage>
*
* <ExperimentaStatusMessage type="error" title="Fehler">
* Ein Fehler ist aufgetreten.
* </ExperimentaStatusMessage>
*/
interface Props {
/** Status type */
type: 'success' | 'error' | 'warning' | 'info'
/** Status title */
title?: string
/** Custom icon (overrides default) */
icon?: string
}
const props = withDefaults(defineProps<Props>(), {
icon: undefined,
})
// Default icons for each type
const defaultIcons = {
success: '✓',
error: '✖',
warning: '!',
info: 'i',
}
const displayIcon = computed(() => props.icon || defaultIcons[props.type])
</script>
<template>
<div class="status-message">
<!-- Animated Status Icon -->
<div :class="['status-icon', `status-icon-${type}`]" role="img" :aria-label="`${type} icon`">
{{ displayIcon }}
</div>
<!-- Title -->
<h1 v-if="title || $slots.title" class="status-title">
<slot name="title">{{ title }}</slot>
</h1>
<!-- Message Content -->
<div class="status-content">
<slot />
</div>
</div>
</template>
<style scoped>
/* Status Message Container */
.status-message {
@apply text-center;
}
/* Status Icon */
.status-icon {
@apply flex items-center justify-center;
@apply w-25 h-25 rounded-full;
@apply text-6xl text-white;
@apply mb-8 mx-auto;
@apply animate-pulse;
}
/* Icon Colors by Type */
.status-icon-success {
@apply bg-success;
}
.status-icon-error {
@apply bg-error;
}
.status-icon-warning {
@apply bg-warning;
}
.status-icon-info {
@apply bg-info;
}
/* Responsive Icon Size */
@media (max-width: 480px) {
.status-icon {
@apply text-5xl;
}
}
/* Status Title */
.status-title {
@apply text-4xl md:text-3xl sm:text-2xl;
@apply font-light tracking-tight;
@apply mb-8;
@apply text-white;
}
/* Status Content */
.status-content {
@apply text-lg md:text-base sm:text-sm;
@apply text-white/90;
@apply leading-relaxed;
}
/* Pulse Animation Override (Custom) */
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
</style>

View File

@@ -0,0 +1,400 @@
# experimenta Vue Komponenten-Beispiele
Dieser Ordner enthält **Referenz-Implementierungen** der experimenta Design System Komponenten als Vue 3 Single File Components (SFC).
Diese Komponenten dienen als **Vorlagen und Beispiele** für die Entwicklung eigener Komponenten oder können direkt in das Projekt kopiert werden.
---
## Verfügbare Komponenten
### 1. ExperimentaButton.vue
Animierter Button mit Gradient-Hintergrund nach experimenta Design System.
**Features:**
- Primary & Secondary Variants
- Responsive Größen (Small, Medium, Large)
- Link-Verhalten (kann als `<a>` oder `<button>` gerendert werden)
- Hover-Animation mit Gradient-Shift
- Accessibility-Ready (Focus States, ARIA Labels)
**Verwendung:**
```vue
<script setup>
import ExperimentaButton from './ExperimentaButton.vue'
</script>
<template>
<!-- Primary Button (default) -->
<ExperimentaButton @click="handleClick"> Zur Startseite </ExperimentaButton>
<!-- Secondary Button -->
<ExperimentaButton variant="secondary"> Abbrechen </ExperimentaButton>
<!-- As Link -->
<ExperimentaButton href="https://www.experimenta.science" target="_blank">
Zur experimenta Website
</ExperimentaButton>
<!-- Small Size -->
<ExperimentaButton size="small"> Small Button </ExperimentaButton>
<!-- Disabled -->
<ExperimentaButton disabled> Disabled Button </ExperimentaButton>
</template>
```
---
### 2. ExperimentaCard.vue
Glass-morphism Card-Komponente mit verschiedenen Variants.
**Features:**
- Glass-morphism Styling (Backdrop Blur)
- Info, Contact, Progress Variants
- Optional: Akzent-Border (links)
- Slot-basiertes Design (flexibel)
**Verwendung:**
```vue
<script setup>
import ExperimentaCard from './ExperimentaCard.vue'
</script>
<template>
<!-- Glass Card (Main) -->
<ExperimentaCard>
<h1>Willkommen!</h1>
<p>Dies ist eine Glass-morphism Card.</p>
</ExperimentaCard>
<!-- Info Card mit Titel -->
<ExperimentaCard variant="info" title="Ihre Vorteile">
<p>Mit der Jahreskarte erhalten Sie...</p>
</ExperimentaCard>
<!-- Card mit Custom Title Slot -->
<ExperimentaCard variant="contact">
<template #title>
<span>Kontakt</span>
</template>
<p>E-Mail: info@experimenta.science</p>
</ExperimentaCard>
<!-- Progress Card -->
<ExperimentaCard variant="progress">
<!-- Progress Bar Content -->
</ExperimentaCard>
</template>
```
---
### 3. ExperimentaStatusMessage.vue
Status-Nachrichten mit animierten Icons (Success, Error, Warning, Info).
**Features:**
- 4 Status-Typen mit passenden Farben
- Animiertes Icon (Pulse Animation)
- Responsive Icon-Größe
- Slot-basierte Inhalte
**Verwendung:**
```vue
<script setup>
import ExperimentaStatusMessage from './ExperimentaStatusMessage.vue'
</script>
<template>
<!-- Success Message -->
<ExperimentaStatusMessage type="success" title="Verlängerung erfolgreich!">
<p>Ihre Jahreskarte wurde erfolgreich verlängert.</p>
</ExperimentaStatusMessage>
<!-- Error Message -->
<ExperimentaStatusMessage type="error" title="Ein Fehler ist aufgetreten">
<p>Bitte versuchen Sie es erneut.</p>
</ExperimentaStatusMessage>
<!-- Custom Icon -->
<ExperimentaStatusMessage type="warning" title="Achtung" icon="⚠">
<p>Dies ist eine Warnung.</p>
</ExperimentaStatusMessage>
<!-- Custom Title Slot -->
<ExperimentaStatusMessage type="info">
<template #title>
<span>Information</span>
</template>
<p>Hier ist eine Info.</p>
</ExperimentaStatusMessage>
</template>
```
---
### 4. ExperimentaLogo.vue
Offizielles experimenta X-Logo mit Farbverläufen.
**Features:**
- SVG-basiert (skalierbar, scharf)
- 3 Größen (Small, Medium, Large)
- Responsive (passt sich automatisch an)
- Optional als Link verwendbar
- Hover-Animation
**Verwendung:**
```vue
<script setup>
import ExperimentaLogo from './ExperimentaLogo.vue'
</script>
<template>
<!-- Logo (default: large) -->
<ExperimentaLogo />
<!-- Logo als Link -->
<ExperimentaLogo href="https://www.experimenta.science" target="_blank" />
<!-- Small Logo -->
<ExperimentaLogo size="small" />
<!-- Medium Logo -->
<ExperimentaLogo size="medium" />
</template>
```
---
## Integration in Nuxt 4
### Option 1: Komponenten in `components/` verschieben
Kopiere die gewünschten Komponenten nach `components/`:
```bash
cp docs/design-examples/components/ExperimentaButton.vue components/
```
Nuxt erkennt sie automatisch (Auto-Imports):
```vue
<template>
<div>
<ExperimentaButton>Click me</ExperimentaButton>
</div>
</template>
```
---
### Option 2: Als Composable verwenden
Erstelle eine Composable-Funktion in `composables/useExperimenta.ts`:
```typescript
export function useExperimenta() {
return {
// Export component references
ExperimentaButton: () => import('@/docs/design-examples/components/ExperimentaButton.vue'),
ExperimentaCard: () => import('@/docs/design-examples/components/ExperimentaCard.vue'),
// ...
}
}
```
---
## Anpassungen & Erweiterungen
### shadcn-nuxt Integration
Diese Komponenten können **shadcn-nuxt Komponenten ersetzen** oder ergänzen:
```vue
<!-- Statt shadcn Button: -->
<Button>Click me</Button>
<!-- Verwende experimenta Button: -->
<ExperimentaButton>Click me</ExperimentaButton>
```
### Tailwind Klassen verwenden
Alle Komponenten verwenden Tailwind CSS Utilities. Du kannst sie anpassen:
```vue
<ExperimentaButton class="mt-8">
Custom Margin
</ExperimentaButton>
```
### Custom Variants hinzufügen
Beispiel: Eine neue Button-Variant hinzufügen:
```vue
<!-- In ExperimentaButton.vue -->
<script setup lang="ts">
interface Props {
variant?: 'primary' | 'secondary' | 'tertiary' // Neu: tertiary
}
</script>
<style scoped>
/* Neue Variant definieren */
.btn-tertiary {
@apply bg-info text-white;
}
.btn-tertiary:hover {
@apply bg-info-dark;
}
</style>
```
---
## TypeScript Support
Alle Komponenten sind **TypeScript-ready** mit vollständigen Prop-Definitionen.
Beispiel für Type-Safe Usage:
```vue
<script setup lang="ts">
import ExperimentaButton from './ExperimentaButton.vue'
function handleClick(event: MouseEvent) {
console.log('Button clicked', event)
}
</script>
<template>
<ExperimentaButton variant="primary" size="large" :disabled="false" @click="handleClick">
Click me
</ExperimentaButton>
</template>
```
---
## Accessibility (A11y)
Alle Komponenten folgen **WCAG 2.1 AA Standards**:
-**Keyboard Navigation** (Tab, Enter, Space)
-**Focus Indicators** (sichtbarer Focus-Ring)
-**ARIA Labels** (Screen Reader Support)
-**Color Contrast** (mindestens 4.5:1 Ratio)
---
## Testing
Beispiel für Vitest Unit Tests:
```typescript
// ExperimentaButton.spec.ts
import { mount } from '@vue/test-utils'
import ExperimentaButton from './ExperimentaButton.vue'
describe('ExperimentaButton', () => {
it('renders primary button by default', () => {
const wrapper = mount(ExperimentaButton, {
slots: { default: 'Click me' },
})
expect(wrapper.find('.btn-primary').exists()).toBe(true)
expect(wrapper.text()).toBe('Click me')
})
it('emits click event', async () => {
const wrapper = mount(ExperimentaButton)
await wrapper.trigger('click')
expect(wrapper.emitted('click')).toBeTruthy()
})
it('renders as link when href is provided', () => {
const wrapper = mount(ExperimentaButton, {
props: { href: 'https://example.com' },
})
expect(wrapper.element.tagName).toBe('A')
expect(wrapper.attributes('href')).toBe('https://example.com')
})
})
```
---
## Storybook Integration (Optional)
Erstelle Stories für visuelle Dokumentation:
```typescript
// ExperimentaButton.stories.ts
import type { Meta, StoryObj } from '@storybook/vue3'
import ExperimentaButton from './ExperimentaButton.vue'
const meta: Meta<typeof ExperimentaButton> = {
title: 'Components/ExperimentaButton',
component: ExperimentaButton,
tags: ['autodocs'],
}
export default meta
type Story = StoryObj<typeof ExperimentaButton>
export const Primary: Story = {
args: {
variant: 'primary',
},
render: (args) => ({
components: { ExperimentaButton },
setup() {
return { args }
},
template: '<ExperimentaButton v-bind="args">Click me</ExperimentaButton>',
}),
}
export const Secondary: Story = {
args: {
variant: 'secondary',
},
render: (args) => ({
components: { ExperimentaButton },
setup() {
return { args }
},
template: '<ExperimentaButton v-bind="args">Cancel</ExperimentaButton>',
}),
}
```
---
## Weitere Ressourcen
- **Design System Dokumentation**: `docs/DESIGN_SYSTEM.md`
- **Tailwind Config**: `tailwind.config.ts`
- **CSS Custom Properties**: `assets/css/tailwind.css`
- **Design-Vorlagen**: `design-examples/*.html`
---
**Fragen oder Feedback?** → docs@experimenta.science

View File

@@ -0,0 +1,981 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jahreskarte verlängert | experimenta</title>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet"
/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
width: 100%;
overflow-x: hidden;
}
body {
font-family: 'Roboto', sans-serif;
background: linear-gradient(135deg, #2e1065 0%, #1a0a3a 50%, #0f051d 100%);
background-attachment: fixed;
background-repeat: no-repeat;
background-size: cover;
color: white;
line-height: 1.6;
min-height: 100vh;
width: 100%;
overflow-x: hidden;
margin: 0;
padding: 0;
}
/* Simplified Header */
.header-wrapper {
background: rgba(46, 16, 101, 0.95);
backdrop-filter: blur(10px);
position: relative;
z-index: 100;
padding: 30px 0;
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: center;
align-items: center;
}
.logo {
display: flex;
align-items: center;
text-decoration: none;
color: white;
transition: all 0.3s ease;
}
.logo:hover {
transform: scale(1.05);
}
.logo-svg {
width: 300px;
height: auto;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}
/* Main Content */
.main-content {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
text-align: center;
width: 100%;
box-sizing: border-box;
}
.success-message {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
backdrop-filter: blur(15px);
border-radius: 20px;
padding: 60px 40px;
margin: 40px 0;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
width: 100%;
box-sizing: border-box;
}
.success-icon {
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
background-color: #46c74a;
width: 100px;
height: 100px;
border-radius: 100%;
font-size: 4rem;
color: #fff;
margin-bottom: 30px;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
h1 {
font-size: 36px;
margin-bottom: 30px;
color: white;
font-weight: 300;
letter-spacing: -1px;
}
.success-text {
font-size: 18px;
margin-bottom: 25px;
color: rgba(255, 255, 255, 0.9);
line-height: 1.7;
}
/* Progress Bar Styles */
.progress-container {
margin: 40px 0;
padding: 30px;
background: rgba(255, 255, 255, 0.08);
border-radius: 15px;
border-left: 4px solid #f59d24;
}
.progress-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
flex-wrap: wrap;
gap: 10px;
}
.progress-title {
font-size: 20px;
font-weight: 500;
color: #f59d24;
margin: 0;
}
.progress-stats {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
font-weight: 400;
}
.progress-bar-wrapper {
position: relative;
width: 100%;
height: 30px;
background: rgba(255, 255, 255, 0.1);
border-radius: 15px;
overflow: hidden;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
}
.progress-bar {
height: 100%;
background: linear-gradient(90deg, #46c74a 0%, #66d96a 50%, #46c74a 100%);
border-radius: 15px;
transition: width 0s ease-out;
position: relative;
width: 0%;
background-size: 200% 100%;
animation: shimmer 3s ease-in-out infinite;
}
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
.progress-percentage {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 16px;
font-weight: 600;
color: white;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.7);
z-index: 2;
width: 100%;
text-align: center;
}
.card-info {
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 30px;
margin: 30px 0;
border-left: 4px solid #f59d24;
}
.card-info h3 {
color: #f59d24;
margin-bottom: 15px;
font-size: 18px;
}
.card-info p {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
}
.contact-info {
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 40px 30px;
margin: 30px 0;
text-align: center;
border-left: 4px solid #f59d24;
}
.contact-info p {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 30px;
line-height: 1.6;
}
.contact-item {
margin: 0;
padding: 0;
background: none;
border: none;
}
.contact-item strong {
color: #f59d24;
display: block;
margin-bottom: 12px;
font-size: 18px;
font-weight: 600;
letter-spacing: 0.5px;
}
.contact-item a {
color: white;
text-decoration: none;
font-size: 18px;
font-weight: 400;
transition: color 0.3s ease;
word-break: break-all;
overflow-wrap: break-word;
}
.contact-item a:hover {
color: #ffb347;
}
.info-section {
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 30px;
margin: 30px 0;
text-align: center;
border-left: 4px solid #f59d24;
}
.info-section p {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
margin: 0;
line-height: 1.6;
}
.info-section a {
color: #f59d24;
text-decoration: underline;
font-weight: 500;
font-size: 18px;
transition: color 0.3s ease;
}
.info-section a:hover {
color: #ff4081;
}
.back-button {
background: #e6007e;
background-image: linear-gradient(to left, #e6007e, #e6007e, #e40521, #e6007e);
background-size: 300%;
color: #ffffff;
padding: 10px 30px;
border: none;
border-radius: 25px;
font-size: 18px;
font-weight: 500;
cursor: pointer;
transition:
background-position 1s,
all 0.3s ease;
text-decoration: none;
display: inline-block;
margin-top: 30px;
text-transform: none;
line-height: 1.7em;
position: relative;
outline: 0;
border-width: 0px;
}
.back-button:hover {
background-position: 100%;
}
/* Simplified Footer */
.footer {
background: linear-gradient(135deg, #1a0a3a 0%, #0f051d 100%);
margin-top: 80px;
position: relative;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
padding: 60px 20px 30px;
}
.footer-main {
display: grid;
grid-template-columns: 2.5fr 1fr 1fr 1.5fr;
gap: 50px;
margin-bottom: 50px;
}
.footer-section h3 {
color: #e91e63;
margin-bottom: 20px;
font-size: 1.1rem;
font-weight: 500;
}
.footer-section p {
margin-bottom: 15px;
color: rgba(255, 255, 255, 0.8);
line-height: 1.6;
font-size: 14px;
}
.footer-links {
list-style: none;
}
.footer-links li {
margin-bottom: 8px;
}
.footer-links a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
font-size: 14px;
transition: color 0.3s ease;
}
.footer-links a:hover {
color: #ff4081;
}
.footer-logo {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.footer-logo-svg {
width: 200px;
height: auto;
}
.partner-section {
margin: 30px 0;
}
.partner-logos {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
margin-top: 15px;
}
.partner-logo {
background: rgba(255, 255, 255, 0.1);
padding: 15px 20px;
border-radius: 6px;
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
text-align: center;
min-width: 120px;
transition: all 0.3s ease;
}
.partner-logo:hover {
background: rgba(255, 255, 255, 0.15);
}
.social-links {
display: flex;
gap: 12px;
margin-top: 20px;
}
.social-links a {
width: 40px;
height: 40px;
background: rgba(233, 30, 99, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
text-decoration: none;
transition: all 0.3s ease;
font-size: 18px;
}
.social-links a:hover {
background: #e91e63;
transform: translateY(-3px);
}
.footer-bottom {
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 30px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
}
.footer-bottom p {
color: rgba(255, 255, 255, 0.8);
font-size: 16px;
font-weight: normal;
margin: 0;
}
.footer-bottom-links {
display: flex;
gap: 30px;
}
.footer-bottom-links a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
font-size: 16px;
font-weight: bold;
transition: color 0.3s ease;
}
.footer-bottom-links a:hover {
color: #ff4081;
}
.recognition-section {
text-align: center;
margin: 40px 0;
padding: 30px;
background: rgba(255, 255, 255, 0.03);
border-radius: 8px;
}
.recognition-section h4 {
color: #e91e63;
margin-bottom: 15px;
font-size: 1.1rem;
}
/* Responsive Design */
@media (max-width: 768px) {
body {
background-attachment: scroll;
}
.header-content {
padding: 0 15px;
width: 100%;
box-sizing: border-box;
}
.logo-svg {
width: 250px;
max-width: 90%;
}
.main-content {
padding: 40px 15px;
max-width: 100%;
}
.success-message {
padding: 40px 20px;
margin: 20px 0;
border-radius: 15px;
}
h1 {
font-size: 28px;
line-height: 1.2;
}
.progress-container {
padding: 25px 20px;
margin: 20px 0;
}
.progress-header {
flex-direction: column;
align-items: flex-start;
gap: 15px;
}
.progress-title {
font-size: 18px;
}
.progress-stats {
font-size: 16px;
}
.progress-bar-wrapper {
height: 25px;
}
.progress-percentage {
font-size: 14px;
}
.card-info,
.contact-info,
.info-section {
margin: 20px 0;
padding: 25px 20px;
border-radius: 12px;
}
.card-info h3 {
font-size: 16px;
}
.card-info p,
.contact-info p,
.info-section p,
.contact-item a,
.contact-item strong,
.info-section a {
font-size: 16px;
}
.success-text {
font-size: 16px;
}
.footer-main {
grid-template-columns: 1fr;
text-align: center;
}
.footer-bottom {
flex-direction: column;
text-align: center;
gap: 15px;
}
.footer-bottom p,
.footer-bottom-links a {
font-size: 14px;
}
.footer-bottom-links {
gap: 20px;
}
.footer-logo-svg {
width: 180px;
}
}
@media (max-width: 480px) {
html,
body {
width: 100%;
overflow-x: hidden;
}
.logo-svg {
width: 200px;
max-width: 85%;
}
h1 {
font-size: 24px;
line-height: 1.2;
margin-bottom: 20px;
}
.main-content {
padding: 30px 10px;
}
.success-message {
padding: 30px 15px;
margin: 15px 0;
border-radius: 12px;
}
.progress-container {
padding: 20px 15px;
margin: 15px 0;
}
.progress-title {
font-size: 16px;
}
.progress-stats {
font-size: 14px;
}
.progress-bar-wrapper {
height: 20px;
}
.progress-percentage {
font-size: 12px;
}
.card-info,
.contact-info,
.info-section {
padding: 20px 15px;
margin: 15px 0;
}
.card-info h3 {
font-size: 14px;
}
.card-info p,
.contact-info p,
.info-section p,
.contact-item a,
.contact-item strong,
.info-section a {
font-size: 14px;
}
.success-text {
font-size: 14px;
}
.success-icon {
font-size: 3rem;
}
.back-button {
padding: 8px 24px;
font-size: 16px;
margin-top: 20px;
}
.footer-bottom p,
.footer-bottom-links a {
font-size: 12px;
}
.footer-bottom-links {
gap: 15px;
}
}
</style>
</head>
<body>
<!-- Simplified Header -->
<header class="header-wrapper">
<div class="header-content">
<a href="https://www.experimenta.science/" class="logo">
<svg
class="logo-svg"
viewBox="0 0 382.94 87.17"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs>
<linearGradient
id="a"
x1="102.63"
y1="152.32"
x2="135.19"
y2="191.11"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ce0f60" />
<stop offset="0.47" stop-color="#de0b75" />
<stop offset="0.59" stop-color="#e4097d" />
</linearGradient>
<linearGradient
id="b"
x1="104.87"
y1="170.45"
x2="104.87"
y2="170.45"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ab1a4e" />
<stop offset="0.43" stop-color="#9f1d4f" />
<stop offset="0.57" stop-color="#9b1e4f" />
</linearGradient>
<linearGradient
id="c"
x1="68.79"
y1="182.84"
x2="154.66"
y2="182.84"
xlink:href="#b"
/>
<linearGradient
id="d"
x1="94.04"
y1="182.21"
x2="114.5"
y2="126"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.22" stop-color="#e4097d" />
<stop offset="0.32" stop-color="#e4115e" />
<stop offset="0.45" stop-color="#e5193d" />
<stop offset="0.55" stop-color="#e51e28" />
<stop offset="0.62" stop-color="#e52021" />
<stop offset="0.9" stop-color="#f7a822" />
</linearGradient>
</defs>
<polygon
points="143.78 50 151.18 39.6 144.43 39.6 139.68 46.33 135.13 39.6 127.79 39.6 135.32 50.08 127.29 61.23 134.09 61.23 139.3 53.78 144.43 61.23 151.59 61.23 143.78 50"
fill="#fff"
/>
<path
d="M245.79,175.33a9.2,9.2,0,0,0-1.85-3.39,7.28,7.28,0,0,0-2.9-2,10.29,10.29,0,0,0-3.65-.63c-3.12,0-5.47.95-7,2.82l-.56-2.23h-7.72v5.29h3.13v24.7h6.13v-8.4a8.29,8.29,0,0,0,1.7.42,17.3,17.3,0,0,0,2.6.19,11.8,11.8,0,0,0,4.53-.82,9.29,9.29,0,0,0,3.39-2.39,10.78,10.78,0,0,0,2.11-3.78,15.69,15.69,0,0,0,.74-5A16,16,0,0,0,245.79,175.33Zm-12.76,0a5.26,5.26,0,0,1,2.73-.75,4,4,0,0,1,3.12,1.4,5.85,5.85,0,0,1,1.25,4,10.56,10.56,0,0,1-.4,3.12,5.84,5.84,0,0,1-1.1,2.09,4.11,4.11,0,0,1-1.62,1.18,7.15,7.15,0,0,1-4.21.12,4.71,4.71,0,0,1-1.43-.58v-8.48A3.79,3.79,0,0,1,233,175.35Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M270.8,174.1a8.1,8.1,0,0,0-2.42-2.86,9.3,9.3,0,0,0-3.24-1.5,14.1,14.1,0,0,0-7.91.28,10.48,10.48,0,0,0-3.7,2.14,10,10,0,0,0-2.49,3.58,12.71,12.71,0,0,0-.9,5,13.24,13.24,0,0,0,.79,4.74,9.75,9.75,0,0,0,6,5.88,14.71,14.71,0,0,0,4.91.77,15.93,15.93,0,0,0,3-.26,14.61,14.61,0,0,0,2.59-.68,13.18,13.18,0,0,0,2.05-.92,8,8,0,0,0,1.47-1l.19-.18L269,184.85l-.33.28a8.34,8.34,0,0,1-2.51,1.36,11.84,11.84,0,0,1-4,.57,9.83,9.83,0,0,1-2.28-.26,6,6,0,0,1-1.85-.81,4.16,4.16,0,0,1-1.28-1.39,4.33,4.33,0,0,1-.5-1.75h15l.05-.28a19.77,19.77,0,0,0,.43-4A9.75,9.75,0,0,0,270.8,174.1Zm-11.06.54a6.52,6.52,0,0,1,1.95-.29,4.29,4.29,0,0,1,3.24,1.11,4.13,4.13,0,0,1,1.05,2.72h-9.55a4.05,4.05,0,0,1,.5-1.39,4.45,4.45,0,0,1,1.18-1.33A5.21,5.21,0,0,1,259.74,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M194.59,174.1a8,8,0,0,0-2.43-2.86,9.26,9.26,0,0,0-3.23-1.5A14.09,14.09,0,0,0,181,170a10.48,10.48,0,0,0-3.7,2.14,10,10,0,0,0-2.49,3.58,12.7,12.7,0,0,0-.91,5,13.23,13.23,0,0,0,.8,4.74,9.75,9.75,0,0,0,6,5.88,14.71,14.71,0,0,0,4.91.77,15.82,15.82,0,0,0,3-.26,14.38,14.38,0,0,0,2.59-.68,12.91,12.91,0,0,0,2.06-.92,8,8,0,0,0,1.47-1l.19-.18-2.11-4.18-.34.28a8.22,8.22,0,0,1-2.51,1.36,11.78,11.78,0,0,1-4,.57,9.7,9.7,0,0,1-2.28-.26,6,6,0,0,1-1.86-.81,4.23,4.23,0,0,1-1.27-1.39,4.33,4.33,0,0,1-.5-1.75h15l.06-.28a20.47,20.47,0,0,0,.42-4A9.75,9.75,0,0,0,194.59,174.1Zm-11.06.54a6.52,6.52,0,0,1,1.95-.29,4.31,4.31,0,0,1,3.24,1.11,4.07,4.07,0,0,1,1,2.72h-9.54a4,4,0,0,1,.49-1.39,4.35,4.35,0,0,1,1.19-1.33A5.21,5.21,0,0,1,183.53,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M298.09,178.12v-.34c0-3-.49-5.07-1.52-6.37a5.07,5.07,0,0,0-4.22-2,6.89,6.89,0,0,0-3.69,1,11.46,11.46,0,0,0-2.44,2l-.58-2.52h-10v5.29h5.18v11h-5.18v5.3H296v-5.3h-9.08v-8.47a8.94,8.94,0,0,1,1.61-1.76,3.84,3.84,0,0,1,2.48-.76,1.2,1.2,0,0,1,1.11.54,3.85,3.85,0,0,1,.39,2v.34Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M350.79,173.27a5.61,5.61,0,0,0-1.16-2.29,4.05,4.05,0,0,0-1.79-1.21,7.17,7.17,0,0,0-2.24-.33,6.19,6.19,0,0,0-3.12.82,5,5,0,0,0-1.79,1.7,3.66,3.66,0,0,0-1.7-1.81,6.39,6.39,0,0,0-2.92-.71,6,6,0,0,0-3.17.82,5.75,5.75,0,0,0-1.71,1.57l-.53-1.93h-4.78v21.62h6V176.07a1.89,1.89,0,0,1,.72-.94,2,2,0,0,1,1.92-.27,1.05,1.05,0,0,1,.53.44,3.5,3.5,0,0,1,.41,1.11,9.26,9.26,0,0,1,.17,2v13.16h6V175.94a1.5,1.5,0,0,1,.63-.9,2.12,2.12,0,0,1,1.18-.31,1.62,1.62,0,0,1,1.29.63,3.88,3.88,0,0,1,.56,2.42v13.74h6V176.86A14.23,14.23,0,0,0,350.79,173.27Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M375.88,174.1a8,8,0,0,0-2.43-2.86,9.3,9.3,0,0,0-3.24-1.5,14.1,14.1,0,0,0-7.91.28,10.44,10.44,0,0,0-3.69,2.14,10.11,10.11,0,0,0-2.5,3.58,12.71,12.71,0,0,0-.9,5,13.46,13.46,0,0,0,.79,4.74,9.89,9.89,0,0,0,2.32,3.6,10,10,0,0,0,3.71,2.28,14.65,14.65,0,0,0,4.9.77,15.93,15.93,0,0,0,3-.26,14.61,14.61,0,0,0,2.59-.68,13.77,13.77,0,0,0,2.06-.92,8.18,8.18,0,0,0,1.47-1l.19-.18-2.12-4.18-.33.28a8.34,8.34,0,0,1-2.51,1.36,11.82,11.82,0,0,1-4,.57,9.7,9.7,0,0,1-2.28-.26,5.93,5.93,0,0,1-1.86-.81,4.23,4.23,0,0,1-1.27-1.39,4.18,4.18,0,0,1-.5-1.75h15l.06-.28a20.52,20.52,0,0,0,.43-4A9.75,9.75,0,0,0,375.88,174.1Zm-11.06.54a6.5,6.5,0,0,1,1.94-.29,4.33,4.33,0,0,1,3.25,1.11,4.18,4.18,0,0,1,1.05,2.72h-9.55a3.84,3.84,0,0,1,.49-1.39,4.35,4.35,0,0,1,1.19-1.33A5.21,5.21,0,0,1,364.82,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M401.33,174a7,7,0,0,0-1.61-2.75,5.79,5.79,0,0,0-2.46-1.46,10.19,10.19,0,0,0-3-.44,9,9,0,0,0-7,3.07l-.57-2.48h-7.94v5.29h3v16.33h6.13V177.67a4.13,4.13,0,0,1,1.59-2,4.48,4.48,0,0,1,2.62-.83,3.6,3.6,0,0,1,2.67,1,4.72,4.72,0,0,1,1,3.43v12.24h6.14V178.15A13.05,13.05,0,0,0,401.33,174Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M425.62,183.62l-1.41,1.17a9.47,9.47,0,0,1-1.29.89,7,7,0,0,1-3.53.92,3.83,3.83,0,0,1-3.12-1.32,7,7,0,0,1-1.14-4.45v-5.64h11V169.9h-11v-6.43L409,165.21v4.69h-4.14v5.29H409v5.64c0,3.87.83,6.74,2.46,8.54s4.09,2.73,7.31,2.73a12.69,12.69,0,0,0,2.7-.3,14.51,14.51,0,0,0,2.64-.84,15.43,15.43,0,0,0,2.35-1.24,8.09,8.09,0,0,0,1.85-1.59l.17-.2Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M449,186.22c0-.27-.06-.54-.1-.81-.05-.71-.08-1.36-.08-1.94,0-.78.05-1.66.14-2.65s.16-2.25.16-3.67a10.5,10.5,0,0,0-.44-3.12,6,6,0,0,0-1.45-2.44,6.56,6.56,0,0,0-2.6-1.57,11.86,11.86,0,0,0-3.81-.54,22.68,22.68,0,0,0-5.29.55,23.45,23.45,0,0,0-3.93,1.32l-.28.12,1.49,4.95.36-.17a22.8,22.8,0,0,1,2.83-1.07,12,12,0,0,1,3.71-.53,4.18,4.18,0,0,1,2.5.62,2.33,2.33,0,0,1,.77,2v.8a2.53,2.53,0,0,1,0,.47l-1.71-.15c-.56,0-1.1-.08-1.61-.08a17.54,17.54,0,0,0-3.92.41,9.29,9.29,0,0,0-3.07,1.26,5.82,5.82,0,0,0-2,2.22,7.07,7.07,0,0,0-.68,3.19,6.12,6.12,0,0,0,1.94,4.7,7.43,7.43,0,0,0,5.19,1.76,8.26,8.26,0,0,0,4.33-1,7.94,7.94,0,0,0,2.17-1.9l.49,2.56h7.66v-5.3Zm-12.43-2.67a2.4,2.4,0,0,1,.88-.71,4.48,4.48,0,0,1,1.31-.43,7.73,7.73,0,0,1,1.51-.15,13.48,13.48,0,0,1,1.73.11c.38,0,.69.09.94.13v2.13a4.16,4.16,0,0,1-4.08,2.05,2.92,2.92,0,0,1-2-.55,2.07,2.07,0,0,1-.57-1.57A1.68,1.68,0,0,1,436.52,183.55Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<polygon
points="249.76 48.18 241.03 39.45 230.96 49.53 230.96 52.96 233.6 50.29 240.61 57.31 238.01 59.91 239.67 61.58 253.68 47.56 253.68 44.27 249.76 48.18"
fill="#fff"
/>
<path
d="M314.12,162.94a5.56,5.56,0,1,1-5.55-5.55A5.55,5.55,0,0,1,314.12,162.94Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M275.61,204.76l.56,0,.9-.06,1.06-.05,1,0a6.75,6.75,0,0,1,2.74.49,4.2,4.2,0,0,1,1.72,1.32,5.15,5.15,0,0,1,.88,2,11.58,11.58,0,0,1,.25,2.5,11.24,11.24,0,0,1-.25,2.4,5.62,5.62,0,0,1-.9,2.09,4.62,4.62,0,0,1-1.79,1.48,6.81,6.81,0,0,1-2.95.56l-.73,0-.91,0-.89-.06a4.37,4.37,0,0,1-.65-.06Zm3.57,2c-.22,0-.44,0-.66,0l-.48.05v8.34l.22,0h.29l.29,0h.24a3.13,3.13,0,0,0,1.64-.38,2.41,2.41,0,0,0,.92-1,4.31,4.31,0,0,0,.39-1.4,13.77,13.77,0,0,0,.09-1.57,13.6,13.6,0,0,0-.08-1.4,4.16,4.16,0,0,0-.38-1.34,2.46,2.46,0,0,0-.88-1A2.85,2.85,0,0,0,279.18,206.76Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M286.81,208.92a11,11,0,0,1,1.65-.55,9.5,9.5,0,0,1,2.21-.23,5.19,5.19,0,0,1,1.58.22,2.63,2.63,0,0,1,1.05.64,2.38,2.38,0,0,1,.57,1,4.26,4.26,0,0,1,.18,1.28c0,.61,0,1.13-.06,1.55s-.06.81-.06,1.14,0,.53,0,.84a3.93,3.93,0,0,1,.06.48h1.15v2h-3L292,216h-.08a3.31,3.31,0,0,1-1,1,3.46,3.46,0,0,1-1.77.4,3,3,0,0,1-2.1-.71,2.45,2.45,0,0,1-.78-1.89,2.86,2.86,0,0,1,.27-1.29,2.28,2.28,0,0,1,.8-.89,4,4,0,0,1,1.25-.52,7.54,7.54,0,0,1,1.64-.16l.67,0c.24,0,.52,0,.87.07a2.07,2.07,0,0,0,0-.35v-.34a1.13,1.13,0,0,0-.39-1,1.86,1.86,0,0,0-1.15-.29,5.11,5.11,0,0,0-1.62.23,9.05,9.05,0,0,0-1.22.46Zm3,6.53a2.12,2.12,0,0,0,1.27-.31,2.1,2.1,0,0,0,.61-.67v-1.06a4.92,4.92,0,0,0-.52-.08,6.06,6.06,0,0,0-.76-.05,3.05,3.05,0,0,0-.67.07,2.22,2.22,0,0,0-.6.19,1.31,1.31,0,0,0-.42.35.86.86,0,0,0-.16.51,1,1,0,0,0,.29.78A1.39,1.39,0,0,0,289.84,215.45Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M302.86,214.76a.64.64,0,0,0-.44-.57,6.8,6.8,0,0,0-1.07-.39q-.64-.18-1.41-.36a6.44,6.44,0,0,1-1.4-.52,3.49,3.49,0,0,1-1.08-.84,1.93,1.93,0,0,1-.44-1.3,2.2,2.2,0,0,1,.3-1.16,2.59,2.59,0,0,1,.8-.85,3.82,3.82,0,0,1,1.21-.52,6.09,6.09,0,0,1,1.52-.18,7.73,7.73,0,0,1,1.53.13,7.07,7.07,0,0,1,1.15.3,4.28,4.28,0,0,1,.83.4l.6.4-1,1.58-.61-.33-.73-.31a6.89,6.89,0,0,0-.81-.23,3.81,3.81,0,0,0-.82-.09,3.15,3.15,0,0,0-1.21.2.63.63,0,0,0-.46.6c0,.21.14.39.43.52a6.8,6.8,0,0,0,1.08.36l1.4.37a8.06,8.06,0,0,1,1.41.5,3.52,3.52,0,0,1,1.08.81,1.89,1.89,0,0,1,.43,1.28,2.57,2.57,0,0,1-1,2.13,4.69,4.69,0,0,1-2.92.77,7,7,0,0,1-2.64-.45,6,6,0,0,1-1.79-1.06l1.07-1.67a4.73,4.73,0,0,0,.61.43,5.31,5.31,0,0,0,.86.44,7.61,7.61,0,0,0,1,.33,4.55,4.55,0,0,0,1.08.13,2.26,2.26,0,0,0,1-.19A.68.68,0,0,0,302.86,214.76Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M311.81,213.14h1.95v1.76l.11,0a5.28,5.28,0,0,0,.9.29,4.3,4.3,0,0,0,1,.12,2.61,2.61,0,0,0,1.54-.4,1.27,1.27,0,0,0,.55-1.08,1.22,1.22,0,0,0-.45-1,4.42,4.42,0,0,0-1.12-.66c-.44-.19-.93-.37-1.46-.57a7.09,7.09,0,0,1-1.46-.72,4.15,4.15,0,0,1-1.12-1.09,3,3,0,0,1-.45-1.71,3.35,3.35,0,0,1,.31-1.46,3.4,3.4,0,0,1,.87-1.15,4.1,4.1,0,0,1,1.35-.75,5.29,5.29,0,0,1,1.74-.27,11.64,11.64,0,0,1,2.13.2,6.05,6.05,0,0,1,1.68.53v3.62h-2v-2l-.11,0c-.26-.07-.54-.12-.84-.17a6.8,6.8,0,0,0-.9-.06,2.27,2.27,0,0,0-1.34.34,1,1,0,0,0-.49.91,1.19,1.19,0,0,0,.45,1,5.35,5.35,0,0,0,1.12.67c.45.2.93.4,1.46.61a7.15,7.15,0,0,1,1.46.74,4,4,0,0,1,1.12,1.09,2.86,2.86,0,0,1,.45,1.65,3.92,3.92,0,0,1-.35,1.69,3.41,3.41,0,0,1-1,1.2,4.33,4.33,0,0,1-1.51.73,7.68,7.68,0,0,1-3.14.14,7.59,7.59,0,0,1-1.07-.27,8.12,8.12,0,0,1-.86-.34l-.6-.3Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M330.86,216.36a5.24,5.24,0,0,1-1.71.83,7.74,7.74,0,0,1-2,.27,5.92,5.92,0,0,1-2.05-.33,4.16,4.16,0,0,1-1.51-1,4.12,4.12,0,0,1-.94-1.48,5.6,5.6,0,0,1-.32-1.92,5,5,0,0,1,.38-2,3.93,3.93,0,0,1,1-1.48,4.55,4.55,0,0,1,1.57-.92,6.21,6.21,0,0,1,2-.31,7.43,7.43,0,0,1,1.87.23,9.76,9.76,0,0,1,1.34.45v3.13h-2v-1.64a5.22,5.22,0,0,0-1.1-.12,3.35,3.35,0,0,0-1,.15,2.32,2.32,0,0,0-.87.48,2.6,2.6,0,0,0-.63.82,3.12,3.12,0,0,0,0,2.25,2.51,2.51,0,0,0,.55.83,2.42,2.42,0,0,0,.88.56,3.13,3.13,0,0,0,1.17.21,4.15,4.15,0,0,0,1.66-.29,7.06,7.06,0,0,0,1-.49Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M332.69,215.26h3.13v-5h-3.13v-2h5.44v6.94h3.29v2h-8.73Zm2.7-9.36a1.26,1.26,0,0,1,.41-.94,1.58,1.58,0,0,1,1.14-.39,1.74,1.74,0,0,1,1.19.39,1.19,1.19,0,0,1,.44.94,1.16,1.16,0,0,1-.44.94,1.84,1.84,0,0,1-1.19.36,1.66,1.66,0,0,1-1.14-.36A1.23,1.23,0,0,1,335.39,205.9Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M351.63,216.27a3.11,3.11,0,0,1-.6.42,5.25,5.25,0,0,1-.85.38,6.28,6.28,0,0,1-1.08.29,7,7,0,0,1-1.24.1,5.9,5.9,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4.14,4.14,0,0,1-.95-1.48,6,6,0,0,1,0-4,4.07,4.07,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.88-.29,5.78,5.78,0,0,1,1.4.18,3.92,3.92,0,0,1,1.33.61,3.23,3.23,0,0,1,1,1.17,3.87,3.87,0,0,1,.39,1.85,8.31,8.31,0,0,1-.18,1.65h-6.41a2,2,0,0,0,.24,1,1.91,1.91,0,0,0,.59.64,2.56,2.56,0,0,0,.84.37,4.57,4.57,0,0,0,1,.11,5.35,5.35,0,0,0,1.75-.24,3.81,3.81,0,0,0,1.12-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.34,2.34,0,0,0-.74.37,2,2,0,0,0-.54.61,1.71,1.71,0,0,0-.25.81h4.37a1.76,1.76,0,0,0-2-1.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M352.84,208.32H356l.27,1.17h.07a3.42,3.42,0,0,1,1.17-1,3.68,3.68,0,0,1,1.84-.43,4.11,4.11,0,0,1,1.23.18,2.26,2.26,0,0,1,1,.59,2.84,2.84,0,0,1,.65,1.11,5.39,5.39,0,0,1,.24,1.73v5.53H360.1v-5.05a2.14,2.14,0,0,0-.49-1.56,1.7,1.7,0,0,0-1.24-.48,2,2,0,0,0-1.2.38,1.9,1.9,0,0,0-.74.95v5.76h-2.31v-6.93h-1.28Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M372.83,216.36a5.09,5.09,0,0,1-1.7.83,7.74,7.74,0,0,1-2.05.27,5.88,5.88,0,0,1-2.05-.33,4.29,4.29,0,0,1-1.52-1,4,4,0,0,1-.93-1.48,5.6,5.6,0,0,1-.32-1.92,5,5,0,0,1,.37-2,4.17,4.17,0,0,1,1-1.48,4.6,4.6,0,0,1,1.58-.92,6.21,6.21,0,0,1,2-.31,7.43,7.43,0,0,1,1.87.23,9.1,9.1,0,0,1,1.33.45v3.13h-1.95v-1.64a5.24,5.24,0,0,0-1.11-.12,3.28,3.28,0,0,0-1,.15,2.32,2.32,0,0,0-.87.48,2.46,2.46,0,0,0-.63.82,3,3,0,0,0,0,2.25,2.36,2.36,0,0,0,.55.83,2.42,2.42,0,0,0,.88.56,3.13,3.13,0,0,0,1.17.21,4.19,4.19,0,0,0,1.66-.29,7.71,7.71,0,0,0,1-.49Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M383.11,216.27a3.34,3.34,0,0,1-.59.42,5.81,5.81,0,0,1-.86.38,6.16,6.16,0,0,1-1.07.29,7.11,7.11,0,0,1-1.25.1,5.85,5.85,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4,4,0,0,1-1-1.48,5.67,5.67,0,0,1-.33-2,5.26,5.26,0,0,1,.38-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.89-.29,5.7,5.7,0,0,1,1.39.18,3.75,3.75,0,0,1,1.33.61,3.36,3.36,0,0,1,1,1.17,4,4,0,0,1,.38,1.85,8.31,8.31,0,0,1-.18,1.65h-6.4a2,2,0,0,0,.24,1,1.79,1.79,0,0,0,.58.64,2.66,2.66,0,0,0,.84.37,4.6,4.6,0,0,0,1,.11,5.39,5.39,0,0,0,1.75-.24,3.87,3.87,0,0,0,1.11-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.45,2.45,0,0,0-.74.37,2,2,0,0,0-.54.61,1.83,1.83,0,0,0-.25.81h4.38a2,2,0,0,0-.49-1.4A1.94,1.94,0,0,0,379.27,209.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M397.17,213h1.95v3.56a4.32,4.32,0,0,1-1.45.64,7.37,7.37,0,0,1-4-.11,5,5,0,0,1-1.85-1.12,5.51,5.51,0,0,1-1.28-2,8.35,8.35,0,0,1-.48-3,7.5,7.5,0,0,1,.54-3.07,5.58,5.58,0,0,1,1.39-2,5.16,5.16,0,0,1,1.91-1.09,6.82,6.82,0,0,1,2.06-.33,7.84,7.84,0,0,1,1.81.18,6.52,6.52,0,0,1,1.21.41v3.7H397v-2a7.11,7.11,0,0,0-1.14-.09,3.27,3.27,0,0,0-1.29.26,2.83,2.83,0,0,0-1,.79,3.77,3.77,0,0,0-.69,1.34,6.48,6.48,0,0,0-.25,1.92,6,6,0,0,0,.23,1.75,4,4,0,0,0,.67,1.36,3,3,0,0,0,1.09.88,3.26,3.26,0,0,0,1.46.31,6.12,6.12,0,0,0,1.14-.1Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M409.26,216.27a3.11,3.11,0,0,1-.6.42,5.25,5.25,0,0,1-.85.38,6.41,6.41,0,0,1-1.07.29,7.19,7.19,0,0,1-1.25.1,5.9,5.9,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4.14,4.14,0,0,1-.95-1.48,5.44,5.44,0,0,1-.33-2,5.26,5.26,0,0,1,.38-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.88-.29,5.78,5.78,0,0,1,1.4.18,3.92,3.92,0,0,1,1.33.61,3.23,3.23,0,0,1,1,1.17,3.87,3.87,0,0,1,.39,1.85,9.12,9.12,0,0,1-.18,1.65H403a2,2,0,0,0,.24,1,1.79,1.79,0,0,0,.58.64,2.47,2.47,0,0,0,.84.37,4.57,4.57,0,0,0,1,.11,5.35,5.35,0,0,0,1.75-.24,3.81,3.81,0,0,0,1.12-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.34,2.34,0,0,0-.74.37,2,2,0,0,0-.54.61,1.83,1.83,0,0,0-.25.81h4.37a1.75,1.75,0,0,0-2-1.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M410.47,208.32h3.11l.27,1.17h.07a3.46,3.46,0,0,1,1.18-1,3.64,3.64,0,0,1,1.83-.43a4.06,4.06,0,0,1,1.23.18,2.26,2.26,0,0,1,1,.59,2.84,2.84,0,0,1,.65,1.11,5.39,5.39,0,0,1,.24,1.73v5.53h-2.31v-5.05a2.1,2.1,0,0,0-.49-1.56,1.7,1.7,0,0,0-1.24-.48,2,2,0,0,0-1.2.38,1.9,1.9,0,0,0-.74.95v5.76h-2.31v-6.93h-1.28Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M422.81,210.28h-1.75v-2h1.75v-2l2.32-.66v2.69h4.66v2h-4.66v2.54a3.07,3.07,0,0,0,.51,2,1.8,1.8,0,0,0,1.44.62,3,3,0,0,0,.87-.12,2.85,2.85,0,0,0,.71-.29,4.07,4.07,0,0,0,.57-.39l.47-.39,1.07,1.6a4.11,4.11,0,0,1-.76.65,7,7,0,0,1-1,.51,5.78,5.78,0,0,1-1.09.35,5.4,5.4,0,0,1-1.12.12,3.84,3.84,0,0,1-3-1.11,5.17,5.17,0,0,1-1-3.53Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M440.74,216.27a3.34,3.34,0,0,1-.59.42,5.81,5.81,0,0,1-.86.38,6.16,6.16,0,0,1-1.07.29,7.11,7.11,0,0,1-1.25.1,5.85,5.85,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4,4,0,0,1-1-1.48,5.67,5.67,0,0,1-.32-2,5.26,5.26,0,0,1,.37-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.89-.29,5.7,5.7,0,0,1,1.39.18,3.83,3.83,0,0,1,1.33.61,3.36,3.36,0,0,1,1,1.17,4,4,0,0,1,.38,1.85,8.31,8.31,0,0,1-.18,1.65h-6.4a2,2,0,0,0,.24,1,1.81,1.81,0,0,0,.59.64,2.51,2.51,0,0,0,.83.37,4.67,4.67,0,0,0,1,.11,5.39,5.39,0,0,0,1.75-.24,3.87,3.87,0,0,0,1.11-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.45,2.45,0,0,0-.74.37,2,2,0,0,0-.79,1.42h4.38a2,2,0,0,0-.49-1.4A1.94,1.94,0,0,0,436.9,209.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M442.43,215.26h2.21v-5h-2.21v-2h4l.26,1.17h.07a5,5,0,0,1,1.14-1,2.84,2.84,0,0,1,1.5-.39,2,2,0,0,1,1.68.78,4.28,4.28,0,0,1,.61,2.61h-2.08a1.72,1.72,0,0,0-.19-.93.64.64,0,0,0-.59-.3,1.74,1.74,0,0,0-1.15.36,3.6,3.6,0,0,0-.74.82v3.79h3.86v2h-8.38Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M93.1,181.53l20.42-19.22c.87-.76,1.61-1.66,2.61-1.8,1.19-.17,3,1.09,3.3,1.28s10.7,6.64,12.57,7.77l15.75,9.71c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53h0s-17.5-10.32-22.43-13.18a22.83,22.83,0,0,0-11-3c-4.71.09-8.62,2.32-12.24,5h0l-24,18.2,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83A17.88,17.88,0,0,0,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#a)"
/>
<path d="M104.87,170.45h0" transform="translate(-68.76 -130.29)" fill="url(#b)" />
<path
d="M93.1,181.53h0l11.77-11.08a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11-7.26,5.5s-4.11,2.67-4,6.32c.15,4.65,5.34,6.69,5.34,6.69l30.63,13.13a35.93,35.93,0,0,0,11.38,2.53c3.39.08,6.83-1.14,10.49-2.24l24.76-8.46c1.26-.41,3.26-1.65,3.26-3.17,0-1.2-1.57-2.73-3.33-3.51a16.28,16.28,0,0,0-8.57-1.19c-4.7.44-25.95,7.65-25.95,7.65L93.16,184.23a1.28,1.28,0,0,1-.91-1.58A2.68,2.68,0,0,1,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#c)"
/>
<path
d="M147.75,179.27c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53L132,169.56l-27.13.89h0a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73h0a66.73,66.73,0,0,0,7.06.19C107.65,182,144.08,180.38,147.75,179.27Z"
transform="translate(-68.76 -130.29)"
fill="#e4097d"
/>
<path
d="M104.87,170.45a3.26,3.26,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.67-9-3-3.55a1.94,1.94,0,0,1-.41-1.27,2.18,2.18,0,0,1,1-1.83L110,141.9a6.43,6.43,0,0,1,1.81-.87,5.82,5.82,0,0,1,1.86.09l16.49,2.64a24.38,24.38,0,0,0,9.39-.52c1.94-.49,4.31-1.25,5.39-2.91s-.6-2.9-1.11-3.27c-2.08-1.5-4.67-1.92-7.18-2.32l-25.48-4.08a23.84,23.84,0,0,0-10.88.57A19.61,19.61,0,0,0,95,133.6L71.44,149.36a6.34,6.34,0,0,0-1.08,9.38l.21.27,13.12,17a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73Z"
transform="translate(-68.76 -130.29)"
fill="url(#d)"
/>
</svg>
</a>
</div>
</header>
<!-- Main Content -->
<main class="main-content">
<div class="success-message">
<div class="success-icon"></div>
<h1>Jahreskarten-Verlängerungen</h1>
<!-- Progress Bar Section -->
<div class="progress-container">
<div class="progress-header">
<h3 class="progress-title">Verlängerungsfortschritt</h3>
<div class="progress-stats">{{payload.count}} / {{payload.total}}</div>
</div>
<div class="progress-bar-wrapper">
<div class="progress-bar" id="progressBar"></div>
<div class="progress-percentage" id="progressPercentage">{{payload.perc}}%</div>
</div>
</div>
<a href="https://www.experimenta.science/" class="back-button"
>Zur experimenta Startseite</a
>
</div>
</main>
<!-- Footer -->
<footer class="footer">
<div class="footer-content">
<div class="footer-bottom">
<p>© 2025 experimenta gGmbH Das Science Center. Alle Rechte vorbehalten.</p>
<div class="footer-bottom-links">
<a href="https://www.experimenta.science/kontakt/">Kontakt</a>
<a href="https://www.experimenta.science/impressum/">Impressum</a>
<a href="https://www.experimenta.science/datenschutz/">Datenschutz</a>
</div>
</div>
</div>
</footer>
<script>
// Wait for page to load, then animate progress bar
document.addEventListener('DOMContentLoaded', function () {
// Get the percentage value from the template variable
const percentage = parseFloat('{{payload.perc}}') || 0
const progressBar = document.getElementById('progressBar')
// Animate the progress bar after a short delay
setTimeout(function () {
progressBar.style.width = percentage + '%'
}, 0)
})
</script>
</body>
</html>

View File

@@ -0,0 +1,867 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Jahreskarte verlängert | experimenta</title>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet"
/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
width: 100%;
overflow-x: hidden;
}
body {
font-family: 'Roboto', sans-serif;
background: linear-gradient(135deg, #2e1065 0%, #1a0a3a 50%, #0f051d 100%);
background-attachment: fixed;
background-repeat: no-repeat;
background-size: cover;
color: white;
line-height: 1.6;
min-height: 100vh;
width: 100%;
overflow-x: hidden;
margin: 0;
padding: 0;
}
/* Simplified Header */
.header-wrapper {
background: rgba(46, 16, 101, 0.95);
backdrop-filter: blur(10px);
position: relative;
z-index: 100;
padding: 30px 0;
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: center;
align-items: center;
}
.logo {
display: flex;
align-items: center;
text-decoration: none;
color: white;
transition: all 0.3s ease;
}
.logo:hover {
transform: scale(1.05);
}
.logo-svg {
width: 300px;
height: auto;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}
/* Main Content */
.main-content {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
text-align: center;
width: 100%;
box-sizing: border-box;
}
.success-message {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
backdrop-filter: blur(15px);
border-radius: 20px;
padding: 60px 40px;
margin: 40px 0;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
width: 100%;
box-sizing: border-box;
}
.success-icon {
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
background-color: #46c74a;
width: 100px;
height: 100px;
border-radius: 100%;
font-size: 4rem;
color: #fff;
margin-bottom: 30px;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
h1 {
font-size: 36px;
margin-bottom: 30px;
color: white;
font-weight: 300;
letter-spacing: -1px;
}
.success-text {
font-size: 18px;
margin-bottom: 25px;
color: rgba(255, 255, 255, 0.9);
line-height: 1.7;
}
.card-info {
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 30px;
margin: 30px 0;
border-left: 4px solid #f59d24;
}
.card-info h3 {
color: #f59d24;
margin-bottom: 15px;
font-size: 18px;
}
.card-info p {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
}
.contact-info {
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 40px 30px;
margin: 30px 0;
text-align: center;
border-left: 4px solid #f59d24;
}
.contact-info p {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 30px;
line-height: 1.6;
}
.contact-item {
margin: 0;
padding: 0;
background: none;
border: none;
}
.contact-item strong {
color: #f59d24;
display: block;
margin-bottom: 12px;
font-size: 18px;
font-weight: 600;
letter-spacing: 0.5px;
}
.contact-item a {
color: white;
text-decoration: none;
font-size: 18px;
font-weight: 400;
transition: color 0.3s ease;
word-break: break-all;
overflow-wrap: break-word;
}
.contact-item a:hover {
color: #ffb347;
}
.info-section {
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 30px;
margin: 30px 0;
text-align: center;
border-left: 4px solid #f59d24;
}
.info-section p {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
margin: 0;
line-height: 1.6;
}
.info-section a {
color: #f59d24;
text-decoration: underline;
font-weight: 500;
font-size: 18px;
transition: color 0.3s ease;
}
.info-section a:hover {
color: #ff4081;
}
.back-button {
background: #e6007e;
background-image: linear-gradient(to left, #e6007e, #e6007e, #e40521, #e6007e);
background-size: 300%;
color: #ffffff;
padding: 10px 30px;
border: none;
border-radius: 25px;
font-size: 18px;
font-weight: 500;
cursor: pointer;
transition:
background-position 1s,
all 0.3s ease;
text-decoration: none;
display: inline-block;
margin-top: 30px;
text-transform: none;
line-height: 1.7em;
position: relative;
outline: 0;
border-width: 0px;
}
.back-button:hover {
background-position: 100%;
}
/* Simplified Footer */
.footer {
background: linear-gradient(135deg, #1a0a3a 0%, #0f051d 100%);
margin-top: 80px;
position: relative;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
padding: 60px 20px 30px;
}
.footer-main {
display: grid;
grid-template-columns: 2.5fr 1fr 1fr 1.5fr;
gap: 50px;
margin-bottom: 50px;
}
.footer-section h3 {
color: #e91e63;
margin-bottom: 20px;
font-size: 1.1rem;
font-weight: 500;
}
.footer-section p {
margin-bottom: 15px;
color: rgba(255, 255, 255, 0.8);
line-height: 1.6;
font-size: 14px;
}
.footer-links {
list-style: none;
}
.footer-links li {
margin-bottom: 8px;
}
.footer-links a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
font-size: 14px;
transition: color 0.3s ease;
}
.footer-links a:hover {
color: #ff4081;
}
.footer-logo {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.footer-logo-svg {
width: 200px;
height: auto;
}
.partner-section {
margin: 30px 0;
}
.partner-logos {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
margin-top: 15px;
}
.partner-logo {
background: rgba(255, 255, 255, 0.1);
padding: 15px 20px;
border-radius: 6px;
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
text-align: center;
min-width: 120px;
transition: all 0.3s ease;
}
.partner-logo:hover {
background: rgba(255, 255, 255, 0.15);
}
.social-links {
display: flex;
gap: 12px;
margin-top: 20px;
}
.social-links a {
width: 40px;
height: 40px;
background: rgba(233, 30, 99, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
text-decoration: none;
transition: all 0.3s ease;
font-size: 18px;
}
.social-links a:hover {
background: #e91e63;
transform: translateY(-3px);
}
.footer-bottom {
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 30px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
}
.footer-bottom p {
color: rgba(255, 255, 255, 0.8);
font-size: 16px;
font-weight: normal;
margin: 0;
}
.footer-bottom-links {
display: flex;
gap: 30px;
}
.footer-bottom-links a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
font-size: 16px;
font-weight: bold;
transition: color 0.3s ease;
}
.footer-bottom-links a:hover {
color: #ff4081;
}
.recognition-section {
text-align: center;
margin: 40px 0;
padding: 30px;
background: rgba(255, 255, 255, 0.03);
border-radius: 8px;
}
.recognition-section h4 {
color: #e91e63;
margin-bottom: 15px;
font-size: 1.1rem;
}
/* Responsive Design */
@media (max-width: 768px) {
body {
background-attachment: scroll;
}
.header-content {
padding: 0 15px;
width: 100%;
box-sizing: border-box;
}
.logo-svg {
width: 250px;
max-width: 90%;
}
.main-content {
padding: 40px 15px;
max-width: 100%;
}
.success-message {
padding: 40px 20px;
margin: 20px 0;
border-radius: 15px;
}
h1 {
font-size: 28px;
line-height: 1.2;
}
.card-info,
.contact-info,
.info-section {
margin: 20px 0;
padding: 25px 20px;
border-radius: 12px;
}
.card-info h3 {
font-size: 16px;
}
.card-info p,
.contact-info p,
.info-section p,
.contact-item a,
.contact-item strong,
.info-section a {
font-size: 16px;
}
.success-text {
font-size: 16px;
}
.footer-main {
grid-template-columns: 1fr;
text-align: center;
}
.footer-bottom {
flex-direction: column;
text-align: center;
gap: 15px;
}
.footer-bottom p,
.footer-bottom-links a {
font-size: 14px;
}
.footer-bottom-links {
gap: 20px;
}
.footer-logo-svg {
width: 180px;
}
}
@media (max-width: 480px) {
html,
body {
width: 100%;
overflow-x: hidden;
}
.logo-svg {
width: 200px;
max-width: 85%;
}
h1 {
font-size: 24px;
line-height: 1.2;
margin-bottom: 20px;
}
.main-content {
padding: 30px 10px;
}
.success-message {
padding: 30px 15px;
margin: 15px 0;
border-radius: 12px;
}
.card-info,
.contact-info,
.info-section {
padding: 20px 15px;
margin: 15px 0;
}
.card-info h3 {
font-size: 14px;
}
.card-info p,
.contact-info p,
.info-section p,
.contact-item a,
.contact-item strong,
.info-section a {
font-size: 14px;
}
.success-text {
font-size: 14px;
}
.success-icon {
font-size: 3rem;
}
.back-button {
padding: 8px 24px;
font-size: 16px;
margin-top: 20px;
}
.footer-bottom p,
.footer-bottom-links a {
font-size: 12px;
}
.footer-bottom-links {
gap: 15px;
}
}
</style>
</head>
<body>
<!-- Simplified Header -->
<header class="header-wrapper">
<div class="header-content">
<a href="https://www.experimenta.science/" class="logo">
<svg
class="logo-svg"
viewBox="0 0 382.94 87.17"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs>
<linearGradient
id="a"
x1="102.63"
y1="152.32"
x2="135.19"
y2="191.11"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ce0f60" />
<stop offset="0.47" stop-color="#de0b75" />
<stop offset="0.59" stop-color="#e4097d" />
</linearGradient>
<linearGradient
id="b"
x1="104.87"
y1="170.45"
x2="104.87"
y2="170.45"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ab1a4e" />
<stop offset="0.43" stop-color="#9f1d4f" />
<stop offset="0.57" stop-color="#9b1e4f" />
</linearGradient>
<linearGradient
id="c"
x1="68.79"
y1="182.84"
x2="154.66"
y2="182.84"
xlink:href="#b"
/>
<linearGradient
id="d"
x1="94.04"
y1="182.21"
x2="114.5"
y2="126"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.22" stop-color="#e4097d" />
<stop offset="0.32" stop-color="#e4115e" />
<stop offset="0.45" stop-color="#e5193d" />
<stop offset="0.55" stop-color="#e51e28" />
<stop offset="0.62" stop-color="#e52021" />
<stop offset="0.9" stop-color="#f7a822" />
</linearGradient>
</defs>
<polygon
points="143.78 50 151.18 39.6 144.43 39.6 139.68 46.33 135.13 39.6 127.79 39.6 135.32 50.08 127.29 61.23 134.09 61.23 139.3 53.78 144.43 61.23 151.59 61.23 143.78 50"
fill="#fff"
/>
<path
d="M245.79,175.33a9.2,9.2,0,0,0-1.85-3.39,7.28,7.28,0,0,0-2.9-2,10.29,10.29,0,0,0-3.65-.63c-3.12,0-5.47.95-7,2.82l-.56-2.23h-7.72v5.29h3.13v24.7h6.13v-8.4a8.29,8.29,0,0,0,1.7.42,17.3,17.3,0,0,0,2.6.19,11.8,11.8,0,0,0,4.53-.82,9.29,9.29,0,0,0,3.39-2.39,10.78,10.78,0,0,0,2.11-3.78,15.69,15.69,0,0,0,.74-5A16,16,0,0,0,245.79,175.33Zm-12.76,0a5.26,5.26,0,0,1,2.73-.75,4,4,0,0,1,3.12,1.4,5.85,5.85,0,0,1,1.25,4,10.56,10.56,0,0,1-.4,3.12,5.84,5.84,0,0,1-1.1,2.09,4.11,4.11,0,0,1-1.62,1.18,7.15,7.15,0,0,1-4.21.12,4.71,4.71,0,0,1-1.43-.58v-8.48A3.79,3.79,0,0,1,233,175.35Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M270.8,174.1a8.1,8.1,0,0,0-2.42-2.86,9.3,9.3,0,0,0-3.24-1.5,14.1,14.1,0,0,0-7.91.28,10.48,10.48,0,0,0-3.7,2.14,10,10,0,0,0-2.49,3.58,12.71,12.71,0,0,0-.9,5,13.24,13.24,0,0,0,.79,4.74,9.75,9.75,0,0,0,6,5.88,14.71,14.71,0,0,0,4.91.77,15.93,15.93,0,0,0,3-.26,14.61,14.61,0,0,0,2.59-.68,13.18,13.18,0,0,0,2.05-.92,8,8,0,0,0,1.47-1l.19-.18L269,184.85l-.33.28a8.34,8.34,0,0,1-2.51,1.36,11.84,11.84,0,0,1-4,.57,9.83,9.83,0,0,1-2.28-.26,6,6,0,0,1-1.85-.81,4.16,4.16,0,0,1-1.28-1.39,4.33,4.33,0,0,1-.5-1.75h15l.05-.28a19.77,19.77,0,0,0,.43-4A9.75,9.75,0,0,0,270.8,174.1Zm-11.06.54a6.52,6.52,0,0,1,1.95-.29,4.29,4.29,0,0,1,3.24,1.11,4.13,4.13,0,0,1,1.05,2.72h-9.55a4.05,4.05,0,0,1,.5-1.39,4.45,4.45,0,0,1,1.18-1.33A5.21,5.21,0,0,1,259.74,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M194.59,174.1a8,8,0,0,0-2.43-2.86,9.26,9.26,0,0,0-3.23-1.5A14.09,14.09,0,0,0,181,170a10.48,10.48,0,0,0-3.7,2.14,10,10,0,0,0-2.49,3.58,12.7,12.7,0,0,0-.91,5,13.23,13.23,0,0,0,.8,4.74,9.75,9.75,0,0,0,6,5.88,14.71,14.71,0,0,0,4.91.77,15.82,15.82,0,0,0,3-.26,14.38,14.38,0,0,0,2.59-.68,12.91,12.91,0,0,0,2.06-.92,8,8,0,0,0,1.47-1l.19-.18-2.11-4.18-.34.28a8.22,8.22,0,0,1-2.51,1.36,11.78,11.78,0,0,1-4,.57,9.7,9.7,0,0,1-2.28-.26,6,6,0,0,1-1.86-.81,4.23,4.23,0,0,1-1.27-1.39,4.33,4.33,0,0,1-.5-1.75h15l.06-.28a20.47,20.47,0,0,0,.42-4A9.75,9.75,0,0,0,194.59,174.1Zm-11.06.54a6.52,6.52,0,0,1,1.95-.29,4.31,4.31,0,0,1,3.24,1.11,4.07,4.07,0,0,1,1,2.72h-9.54a4,4,0,0,1,.49-1.39,4.35,4.35,0,0,1,1.19-1.33A5.21,5.21,0,0,1,183.53,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M298.09,178.12v-.34c0-3-.49-5.07-1.52-6.37a5.07,5.07,0,0,0-4.22-2,6.89,6.89,0,0,0-3.69,1,11.46,11.46,0,0,0-2.44,2l-.58-2.52h-10v5.29h5.18v11h-5.18v5.3H296v-5.3h-9.08v-8.47a8.94,8.94,0,0,1,1.61-1.76,3.84,3.84,0,0,1,2.48-.76,1.2,1.2,0,0,1,1.11.54,3.85,3.85,0,0,1,.39,2v.34Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M350.79,173.27a5.61,5.61,0,0,0-1.16-2.29,4.05,4.05,0,0,0-1.79-1.21,7.17,7.17,0,0,0-2.24-.33,6.19,6.19,0,0,0-3.12.82,5,5,0,0,0-1.79,1.7,3.66,3.66,0,0,0-1.7-1.81,6.39,6.39,0,0,0-2.92-.71,6,6,0,0,0-3.17.82,5.75,5.75,0,0,0-1.71,1.57l-.53-1.93h-4.78v21.62h6V176.07a1.89,1.89,0,0,1,.72-.94,2,2,0,0,1,1.92-.27,1.05,1.05,0,0,1,.53.44,3.5,3.5,0,0,1,.41,1.11,9.26,9.26,0,0,1,.17,2v13.16h6V175.94a1.5,1.5,0,0,1,.63-.9,2.12,2.12,0,0,1,1.18-.31,1.62,1.62,0,0,1,1.29.63,3.88,3.88,0,0,1,.56,2.42v13.74h6V176.86A14.23,14.23,0,0,0,350.79,173.27Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M375.88,174.1a8,8,0,0,0-2.43-2.86,9.3,9.3,0,0,0-3.24-1.5,14.1,14.1,0,0,0-7.91.28,10.44,10.44,0,0,0-3.69,2.14,10.11,10.11,0,0,0-2.5,3.58,12.71,12.71,0,0,0-.9,5,13.46,13.46,0,0,0,.79,4.74,9.89,9.89,0,0,0,2.32,3.6,10,10,0,0,0,3.71,2.28,14.65,14.65,0,0,0,4.9.77,15.93,15.93,0,0,0,3-.26,14.61,14.61,0,0,0,2.59-.68,13.77,13.77,0,0,0,2.06-.92,8.18,8.18,0,0,0,1.47-1l.19-.18-2.12-4.18-.33.28a8.34,8.34,0,0,1-2.51,1.36,11.82,11.82,0,0,1-4,.57,9.7,9.7,0,0,1-2.28-.26,5.93,5.93,0,0,1-1.86-.81,4.23,4.23,0,0,1-1.27-1.39,4.18,4.18,0,0,1-.5-1.75h15l.06-.28a20.52,20.52,0,0,0,.43-4A9.75,9.75,0,0,0,375.88,174.1Zm-11.06.54a6.5,6.5,0,0,1,1.94-.29,4.33,4.33,0,0,1,3.25,1.11,4.18,4.18,0,0,1,1.05,2.72h-9.55a3.84,3.84,0,0,1,.49-1.39,4.35,4.35,0,0,1,1.19-1.33A5.21,5.21,0,0,1,364.82,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M401.33,174a7,7,0,0,0-1.61-2.75,5.79,5.79,0,0,0-2.46-1.46,10.19,10.19,0,0,0-3-.44,9,9,0,0,0-7,3.07l-.57-2.48h-7.94v5.29h3v16.33h6.13V177.67a4.13,4.13,0,0,1,1.59-2,4.48,4.48,0,0,1,2.62-.83,3.6,3.6,0,0,1,2.67,1,4.72,4.72,0,0,1,1,3.43v12.24h6.14V178.15A13.05,13.05,0,0,0,401.33,174Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M425.62,183.62l-1.41,1.17a9.47,9.47,0,0,1-1.29.89,7,7,0,0,1-3.53.92,3.83,3.83,0,0,1-3.12-1.32,7,7,0,0,1-1.14-4.45v-5.64h11V169.9h-11v-6.43L409,165.21v4.69h-4.14v5.29H409v5.64c0,3.87.83,6.74,2.46,8.54s4.09,2.73,7.31,2.73a12.69,12.69,0,0,0,2.7-.3,14.51,14.51,0,0,0,2.64-.84,15.43,15.43,0,0,0,2.35-1.24,8.09,8.09,0,0,0,1.85-1.59l.17-.2Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M449,186.22c0-.27-.06-.54-.1-.81-.05-.71-.08-1.36-.08-1.94,0-.78.05-1.66.14-2.65s.16-2.25.16-3.67a10.5,10.5,0,0,0-.44-3.12,6,6,0,0,0-1.45-2.44,6.56,6.56,0,0,0-2.6-1.57,11.86,11.86,0,0,0-3.81-.54,22.68,22.68,0,0,0-5.29.55,23.45,23.45,0,0,0-3.93,1.32l-.28.12,1.49,4.95.36-.17a22.8,22.8,0,0,1,2.83-1.07,12,12,0,0,1,3.71-.53,4.18,4.18,0,0,1,2.5.62,2.33,2.33,0,0,1,.77,2v.8a2.53,2.53,0,0,1,0,.47l-1.71-.15c-.56,0-1.1-.08-1.61-.08a17.54,17.54,0,0,0-3.92.41,9.29,9.29,0,0,0-3.07,1.26,5.82,5.82,0,0,0-2,2.22,7.07,7.07,0,0,0-.68,3.19,6.12,6.12,0,0,0,1.94,4.7,7.43,7.43,0,0,0,5.19,1.76,8.26,8.26,0,0,0,4.33-1,7.94,7.94,0,0,0,2.17-1.9l.49,2.56h7.66v-5.3Zm-12.43-2.67a2.4,2.4,0,0,1,.88-.71,4.48,4.48,0,0,1,1.31-.43,7.73,7.73,0,0,1,1.51-.15,13.48,13.48,0,0,1,1.73.11c.38,0,.69.09.94.13v2.13a4.16,4.16,0,0,1-4.08,2.05,2.92,2.92,0,0,1-2-.55,2.07,2.07,0,0,1-.57-1.57A1.68,1.68,0,0,1,436.52,183.55Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<polygon
points="249.76 48.18 241.03 39.45 230.96 49.53 230.96 52.96 233.6 50.29 240.61 57.31 238.01 59.91 239.67 61.58 253.68 47.56 253.68 44.27 249.76 48.18"
fill="#fff"
/>
<path
d="M314.12,162.94a5.56,5.56,0,1,1-5.55-5.55A5.55,5.55,0,0,1,314.12,162.94Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M275.61,204.76l.56,0,.9-.06,1.06-.05,1,0a6.75,6.75,0,0,1,2.74.49,4.2,4.2,0,0,1,1.72,1.32,5.15,5.15,0,0,1,.88,2,11.58,11.58,0,0,1,.25,2.5,11.24,11.24,0,0,1-.25,2.4,5.62,5.62,0,0,1-.9,2.09,4.62,4.62,0,0,1-1.79,1.48,6.81,6.81,0,0,1-2.95.56l-.73,0-.91,0-.89-.06a4.37,4.37,0,0,1-.65-.06Zm3.57,2c-.22,0-.44,0-.66,0l-.48.05v8.34l.22,0h.29l.29,0h.24a3.13,3.13,0,0,0,1.64-.38,2.41,2.41,0,0,0,.92-1,4.31,4.31,0,0,0,.39-1.4,13.77,13.77,0,0,0,.09-1.57,13.6,13.6,0,0,0-.08-1.4,4.16,4.16,0,0,0-.38-1.34,2.46,2.46,0,0,0-.88-1A2.85,2.85,0,0,0,279.18,206.76Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M286.81,208.92a11,11,0,0,1,1.65-.55,9.5,9.5,0,0,1,2.21-.23,5.19,5.19,0,0,1,1.58.22,2.63,2.63,0,0,1,1.05.64,2.38,2.38,0,0,1,.57,1,4.26,4.26,0,0,1,.18,1.28c0,.61,0,1.13-.06,1.55s-.06.81-.06,1.14,0,.53,0,.84a3.93,3.93,0,0,1,.06.48h1.15v2h-3L292,216h-.08a3.31,3.31,0,0,1-1,1,3.46,3.46,0,0,1-1.77.4,3,3,0,0,1-2.1-.71,2.45,2.45,0,0,1-.78-1.89,2.86,2.86,0,0,1,.27-1.29,2.28,2.28,0,0,1,.8-.89,4,4,0,0,1,1.25-.52,7.54,7.54,0,0,1,1.64-.16l.67,0c.24,0,.52,0,.87.07a2.07,2.07,0,0,0,0-.35v-.34a1.13,1.13,0,0,0-.39-1,1.86,1.86,0,0,0-1.15-.29,5.11,5.11,0,0,0-1.62.23,9.05,9.05,0,0,0-1.22.46Zm3,6.53a2.12,2.12,0,0,0,1.27-.31,2.1,2.1,0,0,0,.61-.67v-1.06a4.92,4.92,0,0,0-.52-.08,6.06,6.06,0,0,0-.76-.05,3.05,3.05,0,0,0-.67.07,2.22,2.22,0,0,0-.6.19,1.31,1.31,0,0,0-.42.35.86.86,0,0,0-.16.51,1,1,0,0,0,.29.78A1.39,1.39,0,0,0,289.84,215.45Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M302.86,214.76a.64.64,0,0,0-.44-.57,6.8,6.8,0,0,0-1.07-.39q-.64-.18-1.41-.36a6.44,6.44,0,0,1-1.4-.52,3.49,3.49,0,0,1-1.08-.84,1.93,1.93,0,0,1-.44-1.3,2.2,2.2,0,0,1,.3-1.16,2.59,2.59,0,0,1,.8-.85,3.82,3.82,0,0,1,1.21-.52,6.09,6.09,0,0,1,1.52-.18,7.73,7.73,0,0,1,1.53.13,7.07,7.07,0,0,1,1.15.3,4.28,4.28,0,0,1,.83.4l.6.4-1,1.58-.61-.33-.73-.31a6.89,6.89,0,0,0-.81-.23,3.81,3.81,0,0,0-.82-.09,3.15,3.15,0,0,0-1.21.2.63.63,0,0,0-.46.6c0,.21.14.39.43.52a6.8,6.8,0,0,0,1.08.36l1.4.37a8.06,8.06,0,0,1,1.41.5,3.52,3.52,0,0,1,1.08.81,1.89,1.89,0,0,1,.43,1.28,2.57,2.57,0,0,1-1,2.13,4.69,4.69,0,0,1-2.92.77,7,7,0,0,1-2.64-.45,6,6,0,0,1-1.79-1.06l1.07-1.67a4.73,4.73,0,0,0,.61.43,5.31,5.31,0,0,0,.86.44,7.61,7.61,0,0,0,1,.33,4.55,4.55,0,0,0,1.08.13,2.26,2.26,0,0,0,1-.19A.68.68,0,0,0,302.86,214.76Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M311.81,213.14h1.95v1.76l.11,0a5.28,5.28,0,0,0,.9.29,4.3,4.3,0,0,0,1,.12,2.61,2.61,0,0,0,1.54-.4,1.27,1.27,0,0,0,.55-1.08,1.22,1.22,0,0,0-.45-1,4.42,4.42,0,0,0-1.12-.66c-.44-.19-.93-.37-1.46-.57a7.09,7.09,0,0,1-1.46-.72,4.15,4.15,0,0,1-1.12-1.09,3,3,0,0,1-.45-1.71,3.35,3.35,0,0,1,.31-1.46,3.4,3.4,0,0,1,.87-1.15,4.1,4.1,0,0,1,1.35-.75,5.29,5.29,0,0,1,1.74-.27,11.64,11.64,0,0,1,2.13.2,6.05,6.05,0,0,1,1.68.53v3.62h-2v-2l-.11,0c-.26-.07-.54-.12-.84-.17a6.8,6.8,0,0,0-.9-.06,2.27,2.27,0,0,0-1.34.34,1,1,0,0,0-.49.91,1.19,1.19,0,0,0,.45,1,5.35,5.35,0,0,0,1.12.67c.45.2.93.4,1.46.61a7.15,7.15,0,0,1,1.46.74,4,4,0,0,1,1.12,1.09,2.86,2.86,0,0,1,.45,1.65,3.92,3.92,0,0,1-.35,1.69,3.41,3.41,0,0,1-1,1.2,4.33,4.33,0,0,1-1.51.73,7.68,7.68,0,0,1-3.14.14,7.59,7.59,0,0,1-1.07-.27,8.12,8.12,0,0,1-.86-.34l-.6-.3Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M330.86,216.36a5.24,5.24,0,0,1-1.71.83,7.74,7.74,0,0,1-2,.27,5.92,5.92,0,0,1-2.05-.33,4.16,4.16,0,0,1-1.51-1,4.12,4.12,0,0,1-.94-1.48,5.6,5.6,0,0,1-.32-1.92,5,5,0,0,1,.38-2,3.93,3.93,0,0,1,1-1.48,4.55,4.55,0,0,1,1.57-.92,6.21,6.21,0,0,1,2-.31,7.43,7.43,0,0,1,1.87.23,9.76,9.76,0,0,1,1.34.45v3.13h-2v-1.64a5.22,5.22,0,0,0-1.1-.12,3.35,3.35,0,0,0-1,.15,2.32,2.32,0,0,0-.87.48,2.6,2.6,0,0,0-.63.82,3.12,3.12,0,0,0,0,2.25,2.51,2.51,0,0,0,.55.83,2.42,2.42,0,0,0,.88.56,3.13,3.13,0,0,0,1.17.21,4.15,4.15,0,0,0,1.66-.29,7.06,7.06,0,0,0,1-.49Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M332.69,215.26h3.13v-5h-3.13v-2h5.44v6.94h3.29v2h-8.73Zm2.7-9.36a1.26,1.26,0,0,1,.41-.94,1.58,1.58,0,0,1,1.14-.39,1.74,1.74,0,0,1,1.19.39,1.19,1.19,0,0,1,.44.94,1.16,1.16,0,0,1-.44.94,1.84,1.84,0,0,1-1.19.36,1.66,1.66,0,0,1-1.14-.36A1.23,1.23,0,0,1,335.39,205.9Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M351.63,216.27a3.11,3.11,0,0,1-.6.42,5.25,5.25,0,0,1-.85.38,6.28,6.28,0,0,1-1.08.29,7,7,0,0,1-1.24.1,5.9,5.9,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4.14,4.14,0,0,1-.95-1.48,6,6,0,0,1,0-4,4.07,4.07,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.88-.29,5.78,5.78,0,0,1,1.4.18,3.92,3.92,0,0,1,1.33.61,3.23,3.23,0,0,1,1,1.17,3.87,3.87,0,0,1,.39,1.85,8.31,8.31,0,0,1-.18,1.65h-6.41a2,2,0,0,0,.24,1,1.91,1.91,0,0,0,.59.64,2.56,2.56,0,0,0,.84.37,4.57,4.57,0,0,0,1,.11,5.35,5.35,0,0,0,1.75-.24,3.81,3.81,0,0,0,1.12-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.34,2.34,0,0,0-.74.37,2,2,0,0,0-.54.61,1.71,1.71,0,0,0-.25.81h4.37a1.76,1.76,0,0,0-2-1.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M352.84,208.32H356l.27,1.17h.07a3.42,3.42,0,0,1,1.17-1,3.68,3.68,0,0,1,1.84-.43,4.11,4.11,0,0,1,1.23.18,2.26,2.26,0,0,1,1,.59,2.84,2.84,0,0,1,.65,1.11,5.39,5.39,0,0,1,.24,1.73v5.53H360.1v-5.05a2.14,2.14,0,0,0-.49-1.56,1.7,1.7,0,0,0-1.24-.48,2,2,0,0,0-1.2.38,1.9,1.9,0,0,0-.74.95v5.76h-2.31v-6.93h-1.28Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M372.83,216.36a5.09,5.09,0,0,1-1.7.83,7.74,7.74,0,0,1-2.05.27,5.88,5.88,0,0,1-2.05-.33,4.29,4.29,0,0,1-1.52-1,4,4,0,0,1-.93-1.48,5.6,5.6,0,0,1-.32-1.92,5,5,0,0,1,.37-2,4.17,4.17,0,0,1,1-1.48,4.6,4.6,0,0,1,1.58-.92,6.21,6.21,0,0,1,2-.31,7.43,7.43,0,0,1,1.87.23,9.1,9.1,0,0,1,1.33.45v3.13h-1.95v-1.64a5.24,5.24,0,0,0-1.11-.12,3.28,3.28,0,0,0-1,.15,2.32,2.32,0,0,0-.87.48,2.46,2.46,0,0,0-.63.82,3,3,0,0,0,0,2.25,2.36,2.36,0,0,0,.55.83,2.42,2.42,0,0,0,.88.56,3.13,3.13,0,0,0,1.17.21,4.19,4.19,0,0,0,1.66-.29,7.71,7.71,0,0,0,1-.49Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M383.11,216.27a3.34,3.34,0,0,1-.59.42,5.81,5.81,0,0,1-.86.38,6.16,6.16,0,0,1-1.07.29,7.11,7.11,0,0,1-1.25.1,5.85,5.85,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4,4,0,0,1-1-1.48,5.67,5.67,0,0,1-.33-2,5.26,5.26,0,0,1,.38-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.89-.29,5.7,5.7,0,0,1,1.39.18,3.75,3.75,0,0,1,1.33.61,3.36,3.36,0,0,1,1,1.17,4,4,0,0,1,.38,1.85,8.31,8.31,0,0,1-.18,1.65h-6.4a2,2,0,0,0,.24,1,1.79,1.79,0,0,0,.58.64,2.66,2.66,0,0,0,.84.37,4.6,4.6,0,0,0,1,.11,5.39,5.39,0,0,0,1.75-.24,3.87,3.87,0,0,0,1.11-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.45,2.45,0,0,0-.74.37,2,2,0,0,0-.54.61,1.83,1.83,0,0,0-.25.81h4.38a2,2,0,0,0-.49-1.4A1.94,1.94,0,0,0,379.27,209.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M397.17,213h1.95v3.56a4.32,4.32,0,0,1-1.45.64,7.37,7.37,0,0,1-4-.11,5,5,0,0,1-1.85-1.12,5.51,5.51,0,0,1-1.28-2,8.35,8.35,0,0,1-.48-3,7.5,7.5,0,0,1,.54-3.07,5.58,5.58,0,0,1,1.39-2,5.16,5.16,0,0,1,1.91-1.09,6.82,6.82,0,0,1,2.06-.33,7.84,7.84,0,0,1,1.81.18,6.52,6.52,0,0,1,1.21.41v3.7H397v-2a7.11,7.11,0,0,0-1.14-.09,3.27,3.27,0,0,0-1.29.26,2.83,2.83,0,0,0-1,.79,3.77,3.77,0,0,0-.69,1.34,6.48,6.48,0,0,0-.25,1.92,6,6,0,0,0,.23,1.75,4,4,0,0,0,.67,1.36,3,3,0,0,0,1.09.88,3.26,3.26,0,0,0,1.46.31,6.12,6.12,0,0,0,1.14-.1Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M409.26,216.27a3.11,3.11,0,0,1-.6.42,5.25,5.25,0,0,1-.85.38,6.41,6.41,0,0,1-1.07.29,7.19,7.19,0,0,1-1.25.1,5.9,5.9,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4.14,4.14,0,0,1-.95-1.48,5.44,5.44,0,0,1-.33-2,5.26,5.26,0,0,1,.38-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.88-.29,5.78,5.78,0,0,1,1.4.18,3.92,3.92,0,0,1,1.33.61,3.23,3.23,0,0,1,1,1.17,3.87,3.87,0,0,1,.39,1.85,9.12,9.12,0,0,1-.18,1.65H403a2,2,0,0,0,.24,1,1.79,1.79,0,0,0,.58.64,2.47,2.47,0,0,0,.84.37,4.57,4.57,0,0,0,1,.11,5.35,5.35,0,0,0,1.75-.24,3.81,3.81,0,0,0,1.12-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.34,2.34,0,0,0-.74.37,2,2,0,0,0-.54.61,1.83,1.83,0,0,0-.25.81h4.37a1.75,1.75,0,0,0-2-1.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M410.47,208.32h3.11l.27,1.17h.07a3.46,3.46,0,0,1,1.18-1,3.64,3.64,0,0,1,1.83-.43a4.06,4.06,0,0,1,1.23.18,2.26,2.26,0,0,1,1,.59,2.84,2.84,0,0,1,.65,1.11,5.39,5.39,0,0,1,.24,1.73v5.53h-2.31v-5.05a2.1,2.1,0,0,0-.49-1.56,1.7,1.7,0,0,0-1.24-.48,2,2,0,0,0-1.2.38,1.9,1.9,0,0,0-.74.95v5.76h-2.31v-6.93h-1.28Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M422.81,210.28h-1.75v-2h1.75v-2l2.32-.66v2.69h4.66v2h-4.66v2.54a3.07,3.07,0,0,0,.51,2,1.8,1.8,0,0,0,1.44.62,3,3,0,0,0,.87-.12,2.85,2.85,0,0,0,.71-.29,4.07,4.07,0,0,0,.57-.39l.47-.39,1.07,1.6a4.11,4.11,0,0,1-.76.65,7,7,0,0,1-1,.51,5.78,5.78,0,0,1-1.09.35,5.4,5.4,0,0,1-1.12.12,3.84,3.84,0,0,1-3-1.11,5.17,5.17,0,0,1-1-3.53Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M440.74,216.27a3.34,3.34,0,0,1-.59.42,5.81,5.81,0,0,1-.86.38,6.16,6.16,0,0,1-1.07.29,7.11,7.11,0,0,1-1.25.1,5.85,5.85,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4,4,0,0,1-1-1.48,5.67,5.67,0,0,1-.32-2,5.26,5.26,0,0,1,.37-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.89-.29,5.7,5.7,0,0,1,1.39.18,3.83,3.83,0,0,1,1.33.61,3.36,3.36,0,0,1,1,1.17,4,4,0,0,1,.38,1.85,8.31,8.31,0,0,1-.18,1.65h-6.4a2,2,0,0,0,.24,1,1.81,1.81,0,0,0,.59.64,2.51,2.51,0,0,0,.83.37,4.67,4.67,0,0,0,1,.11,5.39,5.39,0,0,0,1.75-.24,3.87,3.87,0,0,0,1.11-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.45,2.45,0,0,0-.74.37,2,2,0,0,0-.79,1.42h4.38a2,2,0,0,0-.49-1.4A1.94,1.94,0,0,0,436.9,209.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M442.43,215.26h2.21v-5h-2.21v-2h4l.26,1.17h.07a5,5,0,0,1,1.14-1,2.84,2.84,0,0,1,1.5-.39,2,2,0,0,1,1.68.78,4.28,4.28,0,0,1,.61,2.61h-2.08a1.72,1.72,0,0,0-.19-.93.64.64,0,0,0-.59-.3,1.74,1.74,0,0,0-1.15.36,3.6,3.6,0,0,0-.74.82v3.79h3.86v2h-8.38Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M93.1,181.53l20.42-19.22c.87-.76,1.61-1.66,2.61-1.8,1.19-.17,3,1.09,3.3,1.28s10.7,6.64,12.57,7.77l15.75,9.71c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53h0s-17.5-10.32-22.43-13.18a22.83,22.83,0,0,0-11-3c-4.71.09-8.62,2.32-12.24,5h0l-24,18.2,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83A17.88,17.88,0,0,0,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#a)"
/>
<path d="M104.87,170.45h0" transform="translate(-68.76 -130.29)" fill="url(#b)" />
<path
d="M93.1,181.53h0l11.77-11.08a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11-7.26,5.5s-4.11,2.67-4,6.32c.15,4.65,5.34,6.69,5.34,6.69l30.63,13.13a35.93,35.93,0,0,0,11.38,2.53c3.39.08,6.83-1.14,10.49-2.24l24.76-8.46c1.26-.41,3.26-1.65,3.26-3.17,0-1.2-1.57-2.73-3.33-3.51a16.28,16.28,0,0,0-8.57-1.19c-4.7.44-25.95,7.65-25.95,7.65L93.16,184.23a1.28,1.28,0,0,1-.91-1.58A2.68,2.68,0,0,1,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#c)"
/>
<path
d="M147.75,179.27c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53L132,169.56l-27.13.89h0a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73h0a66.73,66.73,0,0,0,7.06.19C107.65,182,144.08,180.38,147.75,179.27Z"
transform="translate(-68.76 -130.29)"
fill="#e4097d"
/>
<path
d="M104.87,170.45a3.26,3.26,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.67-9-3-3.55a1.94,1.94,0,0,1-.41-1.27,2.18,2.18,0,0,1,1-1.83L110,141.9a6.43,6.43,0,0,1,1.81-.87,5.82,5.82,0,0,1,1.86.09l16.49,2.64a24.38,24.38,0,0,0,9.39-.52c1.94-.49,4.31-1.25,5.39-2.91s-.6-2.9-1.11-3.27c-2.08-1.5-4.67-1.92-7.18-2.32l-25.48-4.08a23.84,23.84,0,0,0-10.88.57A19.61,19.61,0,0,0,95,133.6L71.44,149.36a6.34,6.34,0,0,0-1.08,9.38l.21.27,13.12,17a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73Z"
transform="translate(-68.76 -130.29)"
fill="url(#d)"
/>
</svg>
</a>
</div>
</header>
<!-- Main Content -->
<main class="main-content">
<div class="success-message">
<div class="success-icon"></div>
<h1>Verlängerung erfolgreich!</h1>
<p class="success-text">Ihre Pädagogische Jahreskarte wurde erfolgreich verlängert.</p>
<div class="card-info">
<h3>Ihre Vorteile</h3>
<p>
Mit der Jahreskarte erhalten Sie ein Jahr lang freien Eintritt in die Ausstellung,
Sonderausstellung oder zu den regulären Science Dome Shows.
</p>
</div>
<div class="contact-info">
<p>
Bei Fragen zu unseren Angeboten für Bildungseinrichtungen und Pädagogen sind wir gerne
für Sie da.
</p>
<div class="contact-item">
<strong>E-Mail-Adresse</strong>
<a href="mailto:schulkommunikation@experimenta.science"
>schulkommunikation@experimenta.science</a
>
</div>
</div>
<div class="info-section">
<p>
Die neuen Bedingungen der Pädagogischen Jahreskarten finden Sie
<a
href="https://www.experimenta.science/paedagogische-jahreskarte/"
target="_blank"
rel="noopener"
>hier</a
>.
</p>
</div>
<a href="https://www.experimenta.science/" class="back-button"
>Zur experimenta Startseite</a
>
</div>
</main>
<!-- Footer -->
<footer class="footer">
<div class="footer-content">
<div class="footer-bottom">
<p>© 2025 experimenta gGmbH Das Science Center. Alle Rechte vorbehalten.</p>
<div class="footer-bottom-links">
<a href="https://www.experimenta.science/kontakt/">Kontakt</a>
<a href="https://www.experimenta.science/impressum/">Impressum</a>
<a href="https://www.experimenta.science/datenschutz/">Datenschutz</a>
</div>
</div>
</div>
</footer>
{{#payload.id}}
<!-- ID: {{payload.id}}-->{{/payload.id}}
</body>
</html>

View File

@@ -0,0 +1,796 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fehler bei der Verlängerung | experimenta</title>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap"
rel="stylesheet"
/>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
width: 100%;
overflow-x: hidden;
}
body {
font-family: 'Roboto', sans-serif;
background: linear-gradient(135deg, #2e1065 0%, #1a0a3a 50%, #0f051d 100%);
background-attachment: fixed;
background-repeat: no-repeat;
background-size: cover;
color: white;
line-height: 1.6;
min-height: 100vh;
width: 100%;
overflow-x: hidden;
margin: 0;
padding: 0;
}
/* Simplified Header */
.header-wrapper {
background: rgba(46, 16, 101, 0.95);
backdrop-filter: blur(10px);
position: relative;
z-index: 100;
padding: 30px 0;
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
justify-content: center;
align-items: center;
}
.logo {
display: flex;
align-items: center;
text-decoration: none;
color: white;
transition: all 0.3s ease;
}
.logo:hover {
transform: scale(1.05);
}
.logo-svg {
width: 300px;
height: auto;
filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));
}
/* Main Content */
.main-content {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
text-align: center;
width: 100%;
box-sizing: border-box;
}
.error-message {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.05));
backdrop-filter: blur(15px);
border-radius: 20px;
padding: 60px 40px;
margin: 40px 0;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
width: 100%;
box-sizing: border-box;
}
.error-icon {
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
background-color: #e53e3e;
width: 100px;
height: 100px;
border-radius: 100%;
font-size: 4rem;
color: #fff;
margin-bottom: 30px;
animation: pulse 2s ease-in-out infinite;
}
@keyframes pulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
h1 {
font-size: 36px;
margin-bottom: 30px;
color: white;
font-weight: 300;
letter-spacing: -1px;
}
.error-text {
font-size: 18px;
margin-bottom: 25px;
color: rgba(255, 255, 255, 0.9);
line-height: 1.7;
}
.contact-info {
background: rgba(255, 255, 255, 0.08);
border-radius: 12px;
padding: 40px 30px;
margin: 30px 0;
text-align: center;
border-left: 4px solid #f59d24;
}
.contact-info p {
font-size: 18px;
color: rgba(255, 255, 255, 0.9);
margin-bottom: 30px;
line-height: 1.6;
}
.contact-item {
margin: 20px 0;
padding: 0;
background: none;
border: none;
}
.contact-item strong {
color: #f59d24;
display: block;
margin-bottom: 12px;
font-size: 18px;
font-weight: 600;
letter-spacing: 0.5px;
}
.contact-item a {
color: white;
text-decoration: none;
font-size: 18px;
font-weight: 400;
transition: color 0.3s ease;
word-break: break-all;
overflow-wrap: break-word;
}
.contact-item a:hover {
color: #ffb347;
}
.contact-item .phone-number {
color: white;
font-size: 18px;
font-weight: 400;
}
.back-button {
background: #e6007e;
background-image: linear-gradient(to left, #e6007e, #e6007e, #e40521, #e6007e);
background-size: 300%;
color: #ffffff;
padding: 10px 30px;
border: none;
border-radius: 25px;
font-size: 18px;
font-weight: 500;
cursor: pointer;
transition:
background-position 1s,
all 0.3s ease;
text-decoration: none;
display: inline-block;
margin-top: 30px;
text-transform: none;
line-height: 1.7em;
position: relative;
outline: 0;
border-width: 0px;
}
.back-button:hover {
background-position: 100%;
}
/* Simplified Footer */
.footer {
background: linear-gradient(135deg, #1a0a3a 0%, #0f051d 100%);
margin-top: 80px;
position: relative;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
padding: 60px 20px 30px;
}
.footer-main {
display: grid;
grid-template-columns: 2.5fr 1fr 1fr 1.5fr;
gap: 50px;
margin-bottom: 50px;
}
.footer-section h3 {
color: #e91e63;
margin-bottom: 20px;
font-size: 1.1rem;
font-weight: 500;
}
.footer-section p {
margin-bottom: 15px;
color: rgba(255, 255, 255, 0.8);
line-height: 1.6;
font-size: 14px;
}
.footer-links {
list-style: none;
}
.footer-links li {
margin-bottom: 8px;
}
.footer-links a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
font-size: 14px;
transition: color 0.3s ease;
}
.footer-links a:hover {
color: #ff4081;
}
.footer-logo {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.footer-logo-svg {
width: 200px;
height: auto;
}
.partner-section {
margin: 30px 0;
}
.partner-logos {
display: flex;
gap: 20px;
align-items: center;
flex-wrap: wrap;
margin-top: 15px;
}
.partner-logo {
background: rgba(255, 255, 255, 0.1);
padding: 15px 20px;
border-radius: 6px;
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
text-align: center;
min-width: 120px;
transition: all 0.3s ease;
}
.partner-logo:hover {
background: rgba(255, 255, 255, 0.15);
}
.social-links {
display: flex;
gap: 12px;
margin-top: 20px;
}
.social-links a {
width: 40px;
height: 40px;
background: rgba(233, 30, 99, 0.2);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
text-decoration: none;
transition: all 0.3s ease;
font-size: 18px;
}
.social-links a:hover {
background: #e91e63;
transform: translateY(-3px);
}
.footer-bottom {
border-top: 1px solid rgba(255, 255, 255, 0.1);
padding-top: 30px;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
}
.footer-bottom p {
color: rgba(255, 255, 255, 0.8);
font-size: 16px;
font-weight: normal;
margin: 0;
}
.footer-bottom-links {
display: flex;
gap: 30px;
}
.footer-bottom-links a {
color: rgba(255, 255, 255, 0.8);
text-decoration: none;
font-size: 16px;
font-weight: bold;
transition: color 0.3s ease;
}
.footer-bottom-links a:hover {
color: #ff4081;
}
.recognition-section {
text-align: center;
margin: 40px 0;
padding: 30px;
background: rgba(255, 255, 255, 0.03);
border-radius: 8px;
}
.recognition-section h4 {
color: #e91e63;
margin-bottom: 15px;
font-size: 1.1rem;
}
/* Responsive Design */
@media (max-width: 768px) {
body {
background-attachment: scroll;
}
.header-content {
padding: 0 15px;
width: 100%;
box-sizing: border-box;
}
.logo-svg {
width: 250px;
max-width: 90%;
}
.main-content {
padding: 40px 15px;
max-width: 100%;
}
.error-message {
padding: 40px 20px;
margin: 20px 0;
border-radius: 15px;
}
h1 {
font-size: 28px;
line-height: 1.2;
}
.contact-info {
margin: 20px 0;
padding: 25px 20px;
border-radius: 12px;
}
.contact-info p,
.contact-item a,
.contact-item strong,
.contact-item .phone-number {
font-size: 16px;
}
.error-text {
font-size: 16px;
}
.footer-main {
grid-template-columns: 1fr;
text-align: center;
}
.footer-bottom {
flex-direction: column;
text-align: center;
gap: 15px;
}
.footer-bottom p,
.footer-bottom-links a {
font-size: 14px;
}
.footer-bottom-links {
gap: 20px;
}
.footer-logo-svg {
width: 180px;
}
}
@media (max-width: 480px) {
html,
body {
width: 100%;
overflow-x: hidden;
}
.logo-svg {
width: 200px;
max-width: 85%;
}
h1 {
font-size: 24px;
line-height: 1.2;
margin-bottom: 20px;
}
.main-content {
padding: 30px 10px;
}
.error-message {
padding: 30px 15px;
margin: 15px 0;
border-radius: 12px;
}
.contact-info {
padding: 20px 15px;
margin: 15px 0;
}
.contact-info p,
.contact-item a,
.contact-item strong,
.contact-item .phone-number {
font-size: 14px;
}
.error-text {
font-size: 14px;
}
.error-icon {
font-size: 3rem;
}
.back-button {
padding: 8px 24px;
font-size: 16px;
margin-top: 20px;
}
.footer-bottom p,
.footer-bottom-links a {
font-size: 12px;
}
.footer-bottom-links {
gap: 15px;
}
}
</style>
</head>
<body>
<!-- Simplified Header -->
<header class="header-wrapper">
<div class="header-content">
<a href="https://www.experimenta.science/" class="logo">
<svg
class="logo-svg"
viewBox="0 0 382.94 87.17"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs>
<linearGradient
id="a"
x1="102.63"
y1="152.32"
x2="135.19"
y2="191.11"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ce0f60" />
<stop offset="0.47" stop-color="#de0b75" />
<stop offset="0.59" stop-color="#e4097d" />
</linearGradient>
<linearGradient
id="b"
x1="104.87"
y1="170.45"
x2="104.87"
y2="170.45"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.16" stop-color="#bf144c" />
<stop offset="0.29" stop-color="#ab1a4e" />
<stop offset="0.43" stop-color="#9f1d4f" />
<stop offset="0.57" stop-color="#9b1e4f" />
</linearGradient>
<linearGradient
id="c"
x1="68.79"
y1="182.84"
x2="154.66"
y2="182.84"
xlink:href="#b"
/>
<linearGradient
id="d"
x1="94.04"
y1="182.21"
x2="114.5"
y2="126"
gradientUnits="userSpaceOnUse"
>
<stop offset="0.22" stop-color="#e4097d" />
<stop offset="0.32" stop-color="#e4115e" />
<stop offset="0.45" stop-color="#e5193d" />
<stop offset="0.55" stop-color="#e51e28" />
<stop offset="0.62" stop-color="#e52021" />
<stop offset="0.9" stop-color="#f7a822" />
</linearGradient>
</defs>
<polygon
points="143.78 50 151.18 39.6 144.43 39.6 139.68 46.33 135.13 39.6 127.79 39.6 135.32 50.08 127.29 61.23 134.09 61.23 139.3 53.78 144.43 61.23 151.59 61.23 143.78 50"
fill="#fff"
/>
<path
d="M245.79,175.33a9.2,9.2,0,0,0-1.85-3.39,7.28,7.28,0,0,0-2.9-2,10.29,10.29,0,0,0-3.65-.63c-3.12,0-5.47.95-7,2.82l-.56-2.23h-7.72v5.29h3.13v24.7h6.13v-8.4a8.29,8.29,0,0,0,1.7.42,17.3,17.3,0,0,0,2.6.19,11.8,11.8,0,0,0,4.53-.82,9.29,9.29,0,0,0,3.39-2.39,10.78,10.78,0,0,0,2.11-3.78,15.69,15.69,0,0,0,.74-5A16,16,0,0,0,245.79,175.33Zm-12.76,0a5.26,5.26,0,0,1,2.73-.75,4,4,0,0,1,3.12,1.4,5.85,5.85,0,0,1,1.25,4,10.56,10.56,0,0,1-.4,3.12,5.84,5.84,0,0,1-1.1,2.09,4.11,4.11,0,0,1-1.62,1.18,7.15,7.15,0,0,1-4.21.12,4.71,4.71,0,0,1-1.43-.58v-8.48A3.79,3.79,0,0,1,233,175.35Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M270.8,174.1a8.1,8.1,0,0,0-2.42-2.86,9.3,9.3,0,0,0-3.24-1.5,14.1,14.1,0,0,0-7.91.28,10.48,10.48,0,0,0-3.7,2.14,10,10,0,0,0-2.49,3.58,12.71,12.71,0,0,0-.9,5,13.24,13.24,0,0,0,.79,4.74,9.75,9.75,0,0,0,6,5.88,14.71,14.71,0,0,0,4.91.77,15.93,15.93,0,0,0,3-.26,14.61,14.61,0,0,0,2.59-.68,13.18,13.18,0,0,0,2.05-.92,8,8,0,0,0,1.47-1l.19-.18L269,184.85l-.33.28a8.34,8.34,0,0,1-2.51,1.36,11.84,11.84,0,0,1-4,.57,9.83,9.83,0,0,1-2.28-.26,6,6,0,0,1-1.85-.81,4.16,4.16,0,0,1-1.28-1.39,4.33,4.33,0,0,1-.5-1.75h15l.05-.28a19.77,19.77,0,0,0,.43-4A9.75,9.75,0,0,0,270.8,174.1Zm-11.06.54a6.52,6.52,0,0,1,1.95-.29,4.29,4.29,0,0,1,3.24,1.11,4.13,4.13,0,0,1,1.05,2.72h-9.55a4.05,4.05,0,0,1,.5-1.39,4.45,4.45,0,0,1,1.18-1.33A5.21,5.21,0,0,1,259.74,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M194.59,174.1a8,8,0,0,0-2.43-2.86,9.26,9.26,0,0,0-3.23-1.5A14.09,14.09,0,0,0,181,170a10.48,10.48,0,0,0-3.7,2.14,10,10,0,0,0-2.49,3.58,12.7,12.7,0,0,0-.91,5,13.23,13.23,0,0,0,.8,4.74,9.75,9.75,0,0,0,6,5.88,14.71,14.71,0,0,0,4.91.77,15.82,15.82,0,0,0,3-.26,14.38,14.38,0,0,0,2.59-.68,12.91,12.91,0,0,0,2.06-.92,8,8,0,0,0,1.47-1l.19-.18-2.11-4.18-.34.28a8.22,8.22,0,0,1-2.51,1.36,11.78,11.78,0,0,1-4,.57,9.7,9.7,0,0,1-2.28-.26,6,6,0,0,1-1.86-.81,4.23,4.23,0,0,1-1.27-1.39,4.33,4.33,0,0,1-.5-1.75h15l.06-.28a20.47,20.47,0,0,0,.42-4A9.75,9.75,0,0,0,194.59,174.1Zm-11.06.54a6.52,6.52,0,0,1,1.95-.29,4.31,4.31,0,0,1,3.24,1.11,4.07,4.07,0,0,1,1,2.72h-9.54a4,4,0,0,1,.49-1.39,4.35,4.35,0,0,1,1.19-1.33A5.21,5.21,0,0,1,183.53,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M298.09,178.12v-.34c0-3-.49-5.07-1.52-6.37a5.07,5.07,0,0,0-4.22-2,6.89,6.89,0,0,0-3.69,1,11.46,11.46,0,0,0-2.44,2l-.58-2.52h-10v5.29h5.18v11h-5.18v5.3H296v-5.3h-9.08v-8.47a8.94,8.94,0,0,1,1.61-1.76,3.84,3.84,0,0,1,2.48-.76,1.2,1.2,0,0,1,1.11.54,3.85,3.85,0,0,1,.39,2v.34Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M350.79,173.27a5.61,5.61,0,0,0-1.16-2.29,4.05,4.05,0,0,0-1.79-1.21,7.17,7.17,0,0,0-2.24-.33,6.19,6.19,0,0,0-3.12.82,5,5,0,0,0-1.79,1.7,3.66,3.66,0,0,0-1.7-1.81,6.39,6.39,0,0,0-2.92-.71,6,6,0,0,0-3.17.82,5.75,5.75,0,0,0-1.71,1.57l-.53-1.93h-4.78v21.62h6V176.07a1.89,1.89,0,0,1,.72-.94,2,2,0,0,1,1.92-.27,1.05,1.05,0,0,1,.53.44,3.5,3.5,0,0,1,.41,1.11,9.26,9.26,0,0,1,.17,2v13.16h6V175.94a1.5,1.5,0,0,1,.63-.9,2.12,2.12,0,0,1,1.18-.31,1.62,1.62,0,0,1,1.29.63,3.88,3.88,0,0,1,.56,2.42v13.74h6V176.86A14.23,14.23,0,0,0,350.79,173.27Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M375.88,174.1a8,8,0,0,0-2.43-2.86,9.3,9.3,0,0,0-3.24-1.5,14.1,14.1,0,0,0-7.91.28,10.44,10.44,0,0,0-3.69,2.14,10.11,10.11,0,0,0-2.5,3.58,12.71,12.71,0,0,0-.9,5,13.46,13.46,0,0,0,.79,4.74,9.89,9.89,0,0,0,2.32,3.6,10,10,0,0,0,3.71,2.28,14.65,14.65,0,0,0,4.9.77,15.93,15.93,0,0,0,3-.26,14.61,14.61,0,0,0,2.59-.68,13.77,13.77,0,0,0,2.06-.92,8.18,8.18,0,0,0,1.47-1l.19-.18-2.12-4.18-.33.28a8.34,8.34,0,0,1-2.51,1.36,11.82,11.82,0,0,1-4,.57,9.7,9.7,0,0,1-2.28-.26,5.93,5.93,0,0,1-1.86-.81,4.23,4.23,0,0,1-1.27-1.39,4.18,4.18,0,0,1-.5-1.75h15l.06-.28a20.52,20.52,0,0,0,.43-4A9.75,9.75,0,0,0,375.88,174.1Zm-11.06.54a6.5,6.5,0,0,1,1.94-.29,4.33,4.33,0,0,1,3.25,1.11,4.18,4.18,0,0,1,1.05,2.72h-9.55a3.84,3.84,0,0,1,.49-1.39,4.35,4.35,0,0,1,1.19-1.33A5.21,5.21,0,0,1,364.82,174.64Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M401.33,174a7,7,0,0,0-1.61-2.75,5.79,5.79,0,0,0-2.46-1.46,10.19,10.19,0,0,0-3-.44,9,9,0,0,0-7,3.07l-.57-2.48h-7.94v5.29h3v16.33h6.13V177.67a4.13,4.13,0,0,1,1.59-2,4.48,4.48,0,0,1,2.62-.83,3.6,3.6,0,0,1,2.67,1,4.72,4.72,0,0,1,1,3.43v12.24h6.14V178.15A13.05,13.05,0,0,0,401.33,174Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M425.62,183.62l-1.41,1.17a9.47,9.47,0,0,1-1.29.89,7,7,0,0,1-3.53.92,3.83,3.83,0,0,1-3.12-1.32,7,7,0,0,1-1.14-4.45v-5.64h11V169.9h-11v-6.43L409,165.21v4.69h-4.14v5.29H409v5.64c0,3.87.83,6.74,2.46,8.54s4.09,2.73,7.31,2.73a12.69,12.69,0,0,0,2.7-.3,14.51,14.51,0,0,0,2.64-.84,15.43,15.43,0,0,0,2.35-1.24,8.09,8.09,0,0,0,1.85-1.59l.17-.2Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M449,186.22c0-.27-.06-.54-.1-.81-.05-.71-.08-1.36-.08-1.94,0-.78.05-1.66.14-2.65s.16-2.25.16-3.67a10.5,10.5,0,0,0-.44-3.12,6,6,0,0,0-1.45-2.44,6.56,6.56,0,0,0-2.6-1.57,11.86,11.86,0,0,0-3.81-.54,22.68,22.68,0,0,0-5.29.55,23.45,23.45,0,0,0-3.93,1.32l-.28.12,1.49,4.95.36-.17a22.8,22.8,0,0,1,2.83-1.07,12,12,0,0,1,3.71-.53,4.18,4.18,0,0,1,2.5.62,2.33,2.33,0,0,1,.77,2v.8a2.53,2.53,0,0,1,0,.47l-1.71-.15c-.56,0-1.1-.08-1.61-.08a17.54,17.54,0,0,0-3.92.41,9.29,9.29,0,0,0-3.07,1.26,5.82,5.82,0,0,0-2,2.22,7.07,7.07,0,0,0-.68,3.19,6.12,6.12,0,0,0,1.94,4.7,7.43,7.43,0,0,0,5.19,1.76,8.26,8.26,0,0,0,4.33-1,7.94,7.94,0,0,0,2.17-1.9l.49,2.56h7.66v-5.3Zm-12.43-2.67a2.4,2.4,0,0,1,.88-.71,4.48,4.48,0,0,1,1.31-.43,7.73,7.73,0,0,1,1.51-.15,13.48,13.48,0,0,1,1.73.11c.38,0,.69.09.94.13v2.13a4.16,4.16,0,0,1-4.08,2.05,2.92,2.92,0,0,1-2-.55,2.07,2.07,0,0,1-.57-1.57A1.68,1.68,0,0,1,436.52,183.55Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<polygon
points="249.76 48.18 241.03 39.45 230.96 49.53 230.96 52.96 233.6 50.29 240.61 57.31 238.01 59.91 239.67 61.58 253.68 47.56 253.68 44.27 249.76 48.18"
fill="#fff"
/>
<path
d="M314.12,162.94a5.56,5.56,0,1,1-5.55-5.55A5.55,5.55,0,0,1,314.12,162.94Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M275.61,204.76l.56,0,.9-.06,1.06-.05,1,0a6.75,6.75,0,0,1,2.74.49,4.2,4.2,0,0,1,1.72,1.32,5.15,5.15,0,0,1,.88,2,11.58,11.58,0,0,1,.25,2.5,11.24,11.24,0,0,1-.25,2.4,5.62,5.62,0,0,1-.9,2.09,4.62,4.62,0,0,1-1.79,1.48,6.81,6.81,0,0,1-2.95.56l-.73,0-.91,0-.89-.06a4.37,4.37,0,0,1-.65-.06Zm3.57,2c-.22,0-.44,0-.66,0l-.48.05v8.34l.22,0h.29l.29,0h.24a3.13,3.13,0,0,0,1.64-.38,2.41,2.41,0,0,0,.92-1,4.31,4.31,0,0,0,.39-1.4,13.77,13.77,0,0,0,.09-1.57,13.6,13.6,0,0,0-.08-1.4,4.16,4.16,0,0,0-.38-1.34,2.46,2.46,0,0,0-.88-1A2.85,2.85,0,0,0,279.18,206.76Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M286.81,208.92a11,11,0,0,1,1.65-.55,9.5,9.5,0,0,1,2.21-.23,5.19,5.19,0,0,1,1.58.22,2.63,2.63,0,0,1,1.05.64,2.38,2.38,0,0,1,.57,1,4.26,4.26,0,0,1,.18,1.28c0,.61,0,1.13-.06,1.55s-.06.81-.06,1.14,0,.53,0,.84a3.93,3.93,0,0,1,.06.48h1.15v2h-3L292,216h-.08a3.31,3.31,0,0,1-1,1,3.46,3.46,0,0,1-1.77.4,3,3,0,0,1-2.1-.71,2.45,2.45,0,0,1-.78-1.89,2.86,2.86,0,0,1,.27-1.29,2.28,2.28,0,0,1,.8-.89,4,4,0,0,1,1.25-.52,7.54,7.54,0,0,1,1.64-.16l.67,0c.24,0,.52,0,.87.07a2.07,2.07,0,0,0,0-.35v-.34a1.13,1.13,0,0,0-.39-1,1.86,1.86,0,0,0-1.15-.29,5.11,5.11,0,0,0-1.62.23,9.05,9.05,0,0,0-1.22.46Zm3,6.53a2.12,2.12,0,0,0,1.27-.31,2.1,2.1,0,0,0,.61-.67v-1.06a4.92,4.92,0,0,0-.52-.08,6.06,6.06,0,0,0-.76-.05,3.05,3.05,0,0,0-.67.07,2.22,2.22,0,0,0-.6.19,1.31,1.31,0,0,0-.42.35.86.86,0,0,0-.16.51,1,1,0,0,0,.29.78A1.39,1.39,0,0,0,289.84,215.45Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M302.86,214.76a.64.64,0,0,0-.44-.57,6.8,6.8,0,0,0-1.07-.39q-.64-.18-1.41-.36a6.44,6.44,0,0,1-1.4-.52,3.49,3.49,0,0,1-1.08-.84,1.93,1.93,0,0,1-.44-1.3,2.2,2.2,0,0,1,.3-1.16,2.59,2.59,0,0,1,.8-.85,3.82,3.82,0,0,1,1.21-.52,6.09,6.09,0,0,1,1.52-.18,7.73,7.73,0,0,1,1.53.13,7.07,7.07,0,0,1,1.15.3,4.28,4.28,0,0,1,.83.4l.6.4-1,1.58-.61-.33-.73-.31a6.89,6.89,0,0,0-.81-.23,3.81,3.81,0,0,0-.82-.09,3.15,3.15,0,0,0-1.21.2.63.63,0,0,0-.46.6c0,.21.14.39.43.52a6.8,6.8,0,0,0,1.08.36l1.4.37a8.06,8.06,0,0,1,1.41.5,3.52,3.52,0,0,1,1.08.81,1.89,1.89,0,0,1,.43,1.28,2.57,2.57,0,0,1-1,2.13,4.69,4.69,0,0,1-2.92.77,7,7,0,0,1-2.64-.45,6,6,0,0,1-1.79-1.06l1.07-1.67a4.73,4.73,0,0,0,.61.43,5.31,5.31,0,0,0,.86.44,7.61,7.61,0,0,0,1,.33,4.55,4.55,0,0,0,1.08.13,2.26,2.26,0,0,0,1-.19A.68.68,0,0,0,302.86,214.76Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M311.81,213.14h1.95v1.76l.11,0a5.28,5.28,0,0,0,.9.29,4.3,4.3,0,0,0,1,.12,2.61,2.61,0,0,0,1.54-.4,1.27,1.27,0,0,0,.55-1.08,1.22,1.22,0,0,0-.45-1,4.42,4.42,0,0,0-1.12-.66c-.44-.19-.93-.37-1.46-.57a7.09,7.09,0,0,1-1.46-.72,4.15,4.15,0,0,1-1.12-1.09,3,3,0,0,1-.45-1.71,3.35,3.35,0,0,1,.31-1.46,3.4,3.4,0,0,1,.87-1.15,4.1,4.1,0,0,1,1.35-.75,5.29,5.29,0,0,1,1.74-.27,11.64,11.64,0,0,1,2.13.2,6.05,6.05,0,0,1,1.68.53v3.62h-2v-2l-.11,0c-.26-.07-.54-.12-.84-.17a6.8,6.8,0,0,0-.9-.06,2.27,2.27,0,0,0-1.34.34,1,1,0,0,0-.49.91,1.19,1.19,0,0,0,.45,1,5.35,5.35,0,0,0,1.12.67c.45.2.93.4,1.46.61a7.15,7.15,0,0,1,1.46.74,4,4,0,0,1,1.12,1.09,2.86,2.86,0,0,1,.45,1.65,3.92,3.92,0,0,1-.35,1.69,3.41,3.41,0,0,1-1,1.2,4.33,4.33,0,0,1-1.51.73,7.68,7.68,0,0,1-3.14.14,7.59,7.59,0,0,1-1.07-.27,8.12,8.12,0,0,1-.86-.34l-.6-.3Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M330.86,216.36a5.24,5.24,0,0,1-1.71.83,7.74,7.74,0,0,1-2,.27,5.92,5.92,0,0,1-2.05-.33,4.16,4.16,0,0,1-1.51-1,4.12,4.12,0,0,1-.94-1.48,5.6,5.6,0,0,1-.32-1.92,5,5,0,0,1,.38-2,3.93,3.93,0,0,1,1-1.48,4.55,4.55,0,0,1,1.57-.92,6.21,6.21,0,0,1,2-.31,7.43,7.43,0,0,1,1.87.23,9.76,9.76,0,0,1,1.34.45v3.13h-2v-1.64a5.22,5.22,0,0,0-1.1-.12,3.35,3.35,0,0,0-1,.15,2.32,2.32,0,0,0-.87.48,2.6,2.6,0,0,0-.63.82,3.12,3.12,0,0,0,0,2.25,2.51,2.51,0,0,0,.55.83,2.42,2.42,0,0,0,.88.56,3.13,3.13,0,0,0,1.17.21,4.15,4.15,0,0,0,1.66-.29,7.06,7.06,0,0,0,1-.49Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M332.69,215.26h3.13v-5h-3.13v-2h5.44v6.94h3.29v2h-8.73Zm2.7-9.36a1.26,1.26,0,0,1,.41-.94,1.58,1.58,0,0,1,1.14-.39,1.74,1.74,0,0,1,1.19.39,1.19,1.19,0,0,1,.44.94,1.16,1.16,0,0,1-.44.94,1.84,1.84,0,0,1-1.19.36,1.66,1.66,0,0,1-1.14-.36A1.23,1.23,0,0,1,335.39,205.9Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M351.63,216.27a3.11,3.11,0,0,1-.6.42,5.25,5.25,0,0,1-.85.38,6.28,6.28,0,0,1-1.08.29,7,7,0,0,1-1.24.1,5.9,5.9,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4.14,4.14,0,0,1-.95-1.48,6,6,0,0,1,0-4,4.07,4.07,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.88-.29,5.78,5.78,0,0,1,1.4.18,3.92,3.92,0,0,1,1.33.61,3.23,3.23,0,0,1,1,1.17,3.87,3.87,0,0,1,.39,1.85,8.31,8.31,0,0,1-.18,1.65h-6.41a2,2,0,0,0,.24,1,1.91,1.91,0,0,0,.59.64,2.56,2.56,0,0,0,.84.37,4.57,4.57,0,0,0,1,.11,5.35,5.35,0,0,0,1.75-.24,3.81,3.81,0,0,0,1.12-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.34,2.34,0,0,0-.74.37,2,2,0,0,0-.54.61,1.71,1.71,0,0,0-.25.81h4.37a1.76,1.76,0,0,0-2-1.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M352.84,208.32H356l.27,1.17h.07a3.42,3.42,0,0,1,1.17-1,3.68,3.68,0,0,1,1.84-.43,4.11,4.11,0,0,1,1.23.18,2.26,2.26,0,0,1,1,.59,2.84,2.84,0,0,1,.65,1.11,5.39,5.39,0,0,1,.24,1.73v5.53H360.1v-5.05a2.14,2.14,0,0,0-.49-1.56,1.7,1.7,0,0,0-1.24-.48,2,2,0,0,0-1.2.38,1.9,1.9,0,0,0-.74.95v5.76h-2.31v-6.93h-1.28Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M372.83,216.36a5.09,5.09,0,0,1-1.7.83,7.74,7.74,0,0,1-2.05.27,5.88,5.88,0,0,1-2.05-.33,4.29,4.29,0,0,1-1.52-1,4,4,0,0,1-.93-1.48,5.6,5.6,0,0,1-.32-1.92,5,5,0,0,1,.37-2,4.17,4.17,0,0,1,1-1.48,4.6,4.6,0,0,1,1.58-.92,6.21,6.21,0,0,1,2-.31,7.43,7.43,0,0,1,1.87.23,9.1,9.1,0,0,1,1.33.45v3.13h-1.95v-1.64a5.24,5.24,0,0,0-1.11-.12,3.28,3.28,0,0,0-1,.15,2.32,2.32,0,0,0-.87.48,2.46,2.46,0,0,0-.63.82,3,3,0,0,0,0,2.25,2.36,2.36,0,0,0,.55.83,2.42,2.42,0,0,0,.88.56,3.13,3.13,0,0,0,1.17.21,4.19,4.19,0,0,0,1.66-.29,7.71,7.71,0,0,0,1-.49Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M383.11,216.27a3.34,3.34,0,0,1-.59.42,5.81,5.81,0,0,1-.86.38,6.16,6.16,0,0,1-1.07.29,7.11,7.11,0,0,1-1.25.1,5.85,5.85,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4,4,0,0,1-1-1.48,5.67,5.67,0,0,1-.33-2,5.26,5.26,0,0,1,.38-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.89-.29,5.7,5.7,0,0,1,1.39.18,3.75,3.75,0,0,1,1.33.61,3.36,3.36,0,0,1,1,1.17,4,4,0,0,1,.38,1.85,8.31,8.31,0,0,1-.18,1.65h-6.4a2,2,0,0,0,.24,1,1.79,1.79,0,0,0,.58.64,2.66,2.66,0,0,0,.84.37,4.6,4.6,0,0,0,1,.11,5.39,5.39,0,0,0,1.75-.24,3.87,3.87,0,0,0,1.11-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.45,2.45,0,0,0-.74.37,2,2,0,0,0-.79,1.42h4.38a2,2,0,0,0-.49-1.4A1.94,1.94,0,0,0,379.27,209.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M397.17,213h1.95v3.56a4.32,4.32,0,0,1-1.45.64,7.37,7.37,0,0,1-4-.11,5,5,0,0,1-1.85-1.12,5.51,5.51,0,0,1-1.28-2,8.35,8.35,0,0,1-.48-3,7.5,7.5,0,0,1,.54-3.07,5.58,5.58,0,0,1,1.39-2,5.16,5.16,0,0,1,1.91-1.09,6.82,6.82,0,0,1,2.06-.33,7.84,7.84,0,0,1,1.81.18,6.52,6.52,0,0,1,1.21.41v3.7H397v-2a7.11,7.11,0,0,0-1.14-.09,3.27,3.27,0,0,0-1.29.26,2.83,2.83,0,0,0-1,.79,3.77,3.77,0,0,0-.69,1.34,6.48,6.48,0,0,0-.25,1.92,6,6,0,0,0,.23,1.75,4,4,0,0,0,.67,1.36,3,3,0,0,0,1.09.88,3.26,3.26,0,0,0,1.46.31,6.12,6.12,0,0,0,1.14-.1Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M409.26,216.27a3.11,3.11,0,0,1-.6.42,5.25,5.25,0,0,1-.85.38,6.41,6.41,0,0,1-1.07.29,7.19,7.19,0,0,1-1.25.1,5.9,5.9,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4.14,4.14,0,0,1-.95-1.48,5.44,5.44,0,0,1-.33-2,5.26,5.26,0,0,1,.38-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.88-.29,5.78,5.78,0,0,1,1.4.18,3.92,3.92,0,0,1,1.33.61,3.23,3.23,0,0,1,1,1.17,3.87,3.87,0,0,1,.39,1.85,9.12,9.12,0,0,1-.18,1.65H403a2,2,0,0,0,.24,1,1.79,1.79,0,0,0,.58.64,2.47,2.47,0,0,0,.84.37,4.57,4.57,0,0,0,1,.11,5.35,5.35,0,0,0,1.75-.24,3.81,3.81,0,0,0,1.12-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.34,2.34,0,0,0-.74.37,2,2,0,0,0-.54.61,1.83,1.83,0,0,0-.25.81h4.37a1.75,1.75,0,0,0-2-1.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M410.47,208.32h3.11l.27,1.17h.07a3.46,3.46,0,0,1,1.18-1,3.64,3.64,0,0,1,1.83-.43,4.06,4.06,0,0,1,1.23.18,2.26,2.26,0,0,1,1,.59,2.84,2.84,0,0,1,.65,1.11,5.39,5.39,0,0,1,.24,1.73v5.53h-2.31v-5.05a2.1,2.1,0,0,0-.49-1.56,1.7,1.7,0,0,0-1.24-.48,2,2,0,0,0-1.2.38,1.9,1.9,0,0,0-.74.95v5.76h-2.31v-6.93h-1.28Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M422.81,210.28h-1.75v-2h1.75v-2l2.32-.66v2.69h4.66v2h-4.66v2.54a3.07,3.07,0,0,0,.51,2,1.8,1.8,0,0,0,1.44.62,3,3,0,0,0,.87-.12,2.85,2.85,0,0,0,.71-.29,4.07,4.07,0,0,0,.57-.39l.47-.39,1.07,1.6a4.11,4.11,0,0,1-.76.65,7,7,0,0,1-1,.51,5.78,5.78,0,0,1-1.09.35,5.4,5.4,0,0,1-1.12.12,3.84,3.84,0,0,1-3-1.11,5.17,5.17,0,0,1-1-3.53Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M440.74,216.27a3.34,3.34,0,0,1-.59.42,5.81,5.81,0,0,1-.86.38,6.16,6.16,0,0,1-1.07.29,7.11,7.11,0,0,1-1.25.1,5.85,5.85,0,0,1-2-.32,4,4,0,0,1-1.52-.93,4,4,0,0,1-1-1.48,5.67,5.67,0,0,1-.32-2,5.26,5.26,0,0,1,.37-2.06,4.17,4.17,0,0,1,1-1.46,4.36,4.36,0,0,1,1.52-.89,6,6,0,0,1,1.89-.29,5.7,5.7,0,0,1,1.39.18,3.83,3.83,0,0,1,1.33.61,3.36,3.36,0,0,1,1,1.17,4,4,0,0,1,.38,1.85,8.31,8.31,0,0,1-.18,1.65h-6.4a2,2,0,0,0,.24,1,1.81,1.81,0,0,0,.59.64,2.51,2.51,0,0,0,.83.37,4.67,4.67,0,0,0,1,.11,5.39,5.39,0,0,0,1.75-.24,3.87,3.87,0,0,0,1.11-.61Zm-3.84-6.35a2.73,2.73,0,0,0-.87.13,2.45,2.45,0,0,0-.74.37,2,2,0,0,0-.79,1.42h4.38a2,2,0,0,0-.49-1.4A1.94,1.94,0,0,0,436.9,209.92Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M442.43,215.26h2.21v-5h-2.21v-2h4l.26,1.17h.07a5,5,0,0,1,1.14-1,2.84,2.84,0,0,1,1.5-.39,2,2,0,0,1,1.68.78,4.28,4.28,0,0,1,.61,2.61h-2.08a1.72,1.72,0,0,0-.19-.93.64.64,0,0,0-.59-.3,1.74,1.74,0,0,0-1.15.36,3.6,3.6,0,0,0-.74.82v3.79h3.86v2h-8.38Z"
transform="translate(-68.76 -130.29)"
fill="#fff"
/>
<path
d="M93.1,181.53l20.42-19.22c.87-.76,1.61-1.66,2.61-1.8,1.19-.17,3,1.09,3.3,1.28s10.7,6.64,12.57,7.77l15.75,9.71c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53h0s-17.5-10.32-22.43-13.18a22.83,22.83,0,0,0-11-3c-4.71.09-8.62,2.32-12.24,5h0l-24,18.2,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83A17.88,17.88,0,0,0,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#a)"
/>
<path d="M104.87,170.45h0" transform="translate(-68.76 -130.29)" fill="url(#b)" />
<path
d="M93.1,181.53h0l11.77-11.08a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11-7.26,5.5s-4.11,2.67-4,6.32c.15,4.65,5.34,6.69,5.34,6.69l30.63,13.13a35.93,35.93,0,0,0,11.38,2.53c3.39.08,6.83-1.14,10.49-2.24l24.76-8.46c1.26-.41,3.26-1.65,3.26-3.17,0-1.2-1.57-2.73-3.33-3.51a16.28,16.28,0,0,0-8.57-1.19c-4.7.44-25.95,7.65-25.95,7.65L93.16,184.23a1.28,1.28,0,0,1-.91-1.58A2.68,2.68,0,0,1,93.1,181.53Z"
transform="translate(-68.76 -130.29)"
fill="url(#c)"
/>
<path
d="M147.75,179.27c4.25-1.29,7.2-4.59,7.46-7.92a5.92,5.92,0,0,0-3-5.65l-2.48-1.53L132,169.56l-27.13.89h0a3.11,3.11,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.57-8.93-14.57,11,3.64,4.7a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73h0a66.73,66.73,0,0,0,7.06.19C107.65,182,144.08,180.38,147.75,179.27Z"
transform="translate(-68.76 -130.29)"
fill="#e4097d"
/>
<path
d="M104.87,170.45a3.26,3.26,0,0,1-1.35-.18,4.24,4.24,0,0,1-1.33-1.11l-7.67-9-3-3.55a1.94,1.94,0,0,1-.41-1.27,2.18,2.18,0,0,1,1-1.83L110,141.9a6.43,6.43,0,0,1,1.81-.87,5.82,5.82,0,0,1,1.86.09l16.49,2.64a24.38,24.38,0,0,0,9.39-.52c1.94-.49,4.31-1.25,5.39-2.91s-.6-2.9-1.11-3.27c-2.08-1.5-4.67-1.92-7.18-2.32l-25.48-4.08a23.84,23.84,0,0,0-10.88.57A19.61,19.61,0,0,0,95,133.6L71.44,149.36a6.34,6.34,0,0,0-1.08,9.38l.21.27,13.12,17a16.1,16.1,0,0,0,6.48,4.83,17.88,17.88,0,0,0,2.93.73Z"
transform="translate(-68.76 -130.29)"
fill="url(#d)"
/>
</svg>
</a>
</div>
</header>
<!-- Main Content -->
<main class="main-content">
<div class="error-message">
<div class="error-icon"></div>
<h1>Ein Fehler ist aufgetreten</h1>
<p class="error-text">
Bei der Verlängerung Ihrer Pädagogischen Jahreskarte ist leider ein Fehler aufgetreten.
</p>
<div class="contact-info">
<p>Bitte setzen Sie sich mit uns in Verbindung, damit wir Ihnen weiterhelfen können.</p>
<div class="contact-item">
<strong>Telefon</strong>
<span class="phone-number">+49 (0) 7131 88795 0</span>
</div>
<div class="contact-item">
<strong>E-Mail-Adresse</strong>
<a href="mailto:buchung@experimenta.science">buchung@experimenta.science</a>
</div>
<div class="contact-item">
<strong>Öffnungszeiten Besucherservice</strong>
<span class="phone-number">Montag bis Freitag von 8 bis 17 Uhr</span>
</div>
</div>
<a href="https://www.experimenta.science/" class="back-button"
>Zur experimenta Startseite</a
>
</div>
</main>
<!-- Footer -->
<footer class="footer">
<div class="footer-content">
<div class="footer-bottom">
<p>© 2025 experimenta gGmbH Das Science Center. Alle Rechte vorbehalten.</p>
<div class="footer-bottom-links">
<a href="https://www.experimenta.science/kontakt/">Kontakt</a>
<a href="https://www.experimenta.science/impressum/">Impressum</a>
<a href="https://www.experimenta.science/datenschutz/">Datenschutz</a>
</div>
</div>
</div>
</footer>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 MiB