feat(landing): Adapt section spacing, use UPageCard for spotlight effect

This commit is contained in:
2026-01-03 18:08:17 +01:00
parent b3311155c7
commit 2754ed4724
5 changed files with 30 additions and 167 deletions

View File

@@ -1,7 +1,7 @@
<template>
<UPageSection
:ui="{
root: 'py-16 lg:py-20 bg-gray-50 dark:bg-gray-900/50'
root: 'bg-gray-50 dark:bg-gray-900/50'
}"
>
<template #title>

View File

@@ -2,7 +2,7 @@
<UPageSection
id="unternehmen"
:ui="{
root: 'scroll-mt-20 py-16 lg:py-20 bg-gray-50 dark:bg-gray-900/50'
root: 'scroll-mt-20 bg-gray-50 dark:bg-gray-900/50'
}"
>
<template #title>

View File

@@ -2,7 +2,7 @@
<UPageSection
id="betriebsraete"
:ui="{
root: 'scroll-mt-20 py-16 lg:py-20'
root: 'scroll-mt-20'
}"
>
<template #title>

View File

@@ -2,7 +2,7 @@
<UPageSection
id="features"
:ui="{
root: 'scroll-mt-20 py-16 lg:py-20'
root: 'scroll-mt-20'
}"
>
<template #title>
@@ -10,7 +10,10 @@
<span
class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-cyan-100 dark:bg-cyan-900/30 text-cyan-700 dark:text-cyan-300 text-sm font-medium mb-4"
>
<UIcon name="i-lucide-sparkles" class="w-4 h-4" />
<UIcon
name="i-lucide-sparkles"
class="w-4 h-4"
/>
Features
</span>
<h2
@@ -28,170 +31,24 @@
</p>
</template>
<!-- Bento Grid -->
<div ref="gridRef" class="mt-12 bento-grid">
<!-- Large featured card -->
<div class="bento-item-large group card-spotlight animate-fade-in-up" @mousemove="handleMouseMove">
<div
class="h-full p-8 rounded-3xl bg-gradient-to-br from-primary-500 to-cyan-500 text-white relative overflow-hidden"
>
<!-- Background pattern -->
<div class="absolute inset-0 opacity-10">
<div class="absolute inset-0 grid-pattern" />
</div>
<div class="relative z-10">
<div
class="w-14 h-14 rounded-2xl bg-white/20 backdrop-blur-sm flex items-center justify-center mb-6 group-hover:scale-110 transition-transform"
>
<UIcon name="i-lucide-route" class="w-7 h-7 text-white" />
</div>
<h3 class="font-heading text-2xl sm:text-3xl font-bold mb-4">Geführter Mitbestimmungsprozess</h3>
<p class="text-white/90 text-lg leading-relaxed mb-6">
Vorgegebene, erweiterbare Eingabeparameter strukturieren den gesamten Ablauf von der Systembeschreibung
bis zur Vereinbarung.
</p>
<!-- Visual element -->
<div class="flex items-center gap-3 mt-8">
<div class="flex -space-x-2">
<div class="w-8 h-8 rounded-full bg-white/30 flex items-center justify-center text-xs font-bold">1</div>
<div class="w-8 h-8 rounded-full bg-white/30 flex items-center justify-center text-xs font-bold">2</div>
<div class="w-8 h-8 rounded-full bg-white/30 flex items-center justify-center text-xs font-bold">3</div>
<div class="w-8 h-8 rounded-full bg-white/30 flex items-center justify-center text-xs font-bold">4</div>
</div>
<span class="text-sm text-white/80">Strukturierte Prozessschritte</span>
</div>
</div>
</div>
</div>
<!-- Regular cards -->
<div
v-for="(feature, index) in features.slice(1, 5)"
<div class="grid sm:grid-cols-2 lg:grid-cols-3 gap-6 mt-12">
<UPageCard
v-for="(feature, index) in features"
:key="index"
class="group card-spotlight animate-fade-in-up"
:style="{ animationDelay: `${(index + 1) * 100}ms` }"
@mousemove="handleMouseMove"
>
<div
class="h-full p-6 rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 transition-all hover:shadow-xl hover:shadow-primary-500/10"
>
<div
class="w-12 h-12 rounded-xl bg-gradient-to-br from-primary-100 to-cyan-100 dark:from-primary-900/50 dark:to-cyan-900/50 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform"
>
<UIcon :name="feature.icon" class="w-6 h-6 text-primary-600 dark:text-primary-400" />
</div>
<h3 class="font-heading text-lg font-bold text-gray-900 dark:text-white mb-2">{{ feature.title }}</h3>
<p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed">{{ feature.description }}</p>
</div>
</div>
<!-- Tall card -->
<div
class="bento-item-tall group card-spotlight animate-fade-in-up"
style="animation-delay: 500ms"
@mousemove="handleMouseMove"
>
<div
class="h-full p-6 rounded-2xl bg-gradient-to-b from-accent-50 to-violet-50 dark:from-accent-950/50 dark:to-violet-950/50 border border-accent-200 dark:border-accent-800 hover:shadow-xl hover:shadow-accent-500/10 transition-all"
>
<div
class="w-12 h-12 rounded-xl bg-gradient-to-br from-accent-500 to-violet-500 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform shadow-lg shadow-accent-500/25"
>
<UIcon name="i-lucide-history" class="w-6 h-6 text-white" />
</div>
<h3 class="font-heading text-lg font-bold text-gray-900 dark:text-white mb-2">Versionierung & Audit-Trail</h3>
<p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed mb-6">
Änderungen werden versioniert und lückenlos nachvollziehbar dokumentiert inklusive Historie und Vergleich.
</p>
<!-- Visual timeline -->
<div class="space-y-3 mt-auto">
<div class="flex items-center gap-3">
<div class="w-2 h-2 rounded-full bg-accent-500" />
<div class="flex-1 h-px bg-accent-200 dark:bg-accent-800" />
<span class="text-xs text-accent-600 dark:text-accent-400">v1.0</span>
</div>
<div class="flex items-center gap-3">
<div class="w-2 h-2 rounded-full bg-accent-500" />
<div class="flex-1 h-px bg-accent-200 dark:bg-accent-800" />
<span class="text-xs text-accent-600 dark:text-accent-400">v1.1</span>
</div>
<div class="flex items-center gap-3">
<div class="w-3 h-3 rounded-full bg-accent-500 ring-4 ring-accent-200 dark:ring-accent-800" />
<div class="flex-1 h-px bg-accent-300 dark:bg-accent-700" />
<span class="text-xs font-semibold text-accent-700 dark:text-accent-300">v2.0</span>
</div>
</div>
</div>
</div>
<!-- Wide card -->
<div
class="bento-item-wide group card-spotlight animate-fade-in-up"
style="animation-delay: 600ms"
@mousemove="handleMouseMove"
>
<div
class="h-full p-6 rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 transition-all hover:shadow-xl hover:shadow-primary-500/10"
>
<div class="flex flex-col sm:flex-row sm:items-start gap-6">
<div
class="w-12 h-12 rounded-xl bg-gradient-to-br from-primary-100 to-cyan-100 dark:from-primary-900/50 dark:to-cyan-900/50 flex items-center justify-center shrink-0 group-hover:scale-110 transition-transform"
>
<UIcon name="i-lucide-file-text" class="w-6 h-6 text-primary-600 dark:text-primary-400" />
</div>
<div>
<h3 class="font-heading text-lg font-bold text-gray-900 dark:text-white mb-2">
Automatische BV-/DV-Generierung
</h3>
<p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed">
Nach Abschluss der Eingaben erzeugt das System strukturierte, übersichtliche und signaturbereite
Betriebs-/Dienstvereinbarungen.
</p>
</div>
</div>
</div>
</div>
<!-- Remaining cards -->
<div
v-for="(feature, index) in features.slice(5)"
:key="index + 5"
class="group card-spotlight animate-fade-in-up"
:style="{ animationDelay: `${(index + 7) * 100}ms` }"
@mousemove="handleMouseMove"
>
<div
class="h-full p-6 rounded-2xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 hover:border-primary-300 dark:hover:border-primary-700 transition-all hover:shadow-xl hover:shadow-primary-500/10"
>
<div
class="w-12 h-12 rounded-xl bg-gradient-to-br from-primary-100 to-cyan-100 dark:from-primary-900/50 dark:to-cyan-900/50 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform"
>
<UIcon :name="feature.icon" class="w-6 h-6 text-primary-600 dark:text-primary-400" />
</div>
<h3 class="font-heading text-lg font-bold text-gray-900 dark:text-white mb-2">{{ feature.title }}</h3>
<p class="text-sm text-gray-600 dark:text-gray-300 leading-relaxed">{{ feature.description }}</p>
</div>
</div>
:icon="feature.icon"
:title="feature.title"
:description="feature.description"
variant="subtle"
spotlight
spotlight-color="primary"
class="animate-fade-in-up"
:style="{ animationDelay: `${index * 100}ms` }"
/>
</div>
</UPageSection>
</template>
<script setup lang="ts">
const gridRef = ref<HTMLElement | null>(null)
// Spotlight effect handler
function handleMouseMove(event: MouseEvent) {
const card = event.currentTarget as HTMLElement
const rect = card.getBoundingClientRect()
const x = ((event.clientX - rect.left) / rect.width) * 100
const y = ((event.clientY - rect.top) / rect.height) * 100
card.style.setProperty('--mouse-x', `${x}%`)
card.style.setProperty('--mouse-y', `${y}%`)
}
const features = [
{
icon: 'i-lucide-route',
@@ -211,16 +68,22 @@ const features = [
description:
'Kritikalität wird transparent bewertet und direkt beim Ausfüllen zurückgespielt für schnelle Orientierung und weniger Schleifen.'
},
{
icon: 'i-lucide-history',
title: 'Versionierung & Audit-Trail',
description:
'Änderungen werden versioniert und lückenlos nachvollziehbar dokumentiert inklusive Historie und Vergleich.'
},
{
icon: 'i-lucide-message-square',
title: 'Zusammenarbeit per Kommentaren',
description: 'Inline-Kommentare ermöglichen Abstimmung direkt an einzelnen Inhalten ohne Medienbrüche.'
},
{
icon: 'i-lucide-history',
title: 'Versionierung & Audit-Trail',
icon: 'i-lucide-file-text',
title: 'Automatische BV-/DV-Generierung',
description:
'Änderungen werden versioniert und lückenlos nachvollziehbar dokumentiert inklusive Historie und Vergleich.'
'Nach Abschluss der Eingaben erzeugt das System strukturierte, übersichtliche und signaturbereite Betriebs-/Dienstvereinbarungen.'
},
{
icon: 'i-lucide-pen-tool',

View File

@@ -1,7 +1,7 @@
<template>
<UPageSection
:ui="{
root: 'py-16 lg:py-20 scroll-mt-20'
root: 'scroll-mt-20'
}"
>
<div class="grid lg:grid-cols-2 gap-12 lg:gap-16 items-center">