b2in/resources/views/livewire/web/components/sections/hero-slider.blade.php
Kevin Adametz 4b07bbdcae Startseite ruhiger, Otterpohl mit Montage, Marken-Bilder und Farbwelt-Entwurf
- Hinweisleiste per B2IN_ANNOUNCEMENT_BAR ausgeblendet (Standard aus)
- Hero: „Räume aus einer Hand.“ als neue Überschrift, zweiter Button entfernt
- Projekttext mit zentralem deutschen Vertragspartner (Punkt statt Gedankenstrich)
- Otterpohl als vierte Kernmarke: Text v2, Abschnitt „Montage“, Titelbild getauscht
- Markenabschnitte: Absätze mit „- “ als Liste mit fetter Einleitung
- Titelbilder und Galerien für CABINET, Rotpunkt, Febrü und Otterpohl (WebP)
- Feedback 17.09. in den Markentexten, Demobilder entfernt, WhatsApp-Nummer
- Palette „Modern“ fest ohne Schalter, Entwurf /entwurf mit Hero-Slideshow
- Seeder-Liste fürs Deployment im Entwicklungsplan

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:34:21 +00:00

102 lines
6.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{{-- Hero des Entwurfs (Nachtrag 19): Rahmen mit feiner Goldkante und grünen Flanken, links
Text mit einem Button, rechts die Slideshow. Das Bild hat ein festes Seitenverhältnis –
das Motiv wird auf großen Bildschirmen nicht mehr unten beschnitten (Briefing Punkt 2).
Der Wechsel läuft langsam (Überblendung 1,4 s, Standard alle 7 s), pausiert bei Hover und
bleibt bei „reduzierter Bewegung“ stehen. --}}
<section id="hero" class="hero-draft section-padding relative">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"
x-data="{
active: 0,
count: {{ count($slides) }},
interval: {{ $this->intervalMs }},
timer: null,
paused: false,
reduced: window.matchMedia('(prefers-reduced-motion: reduce)').matches,
start() {
if (this.reduced || this.count < 2) { return; }
this.stop();
this.timer = setInterval(() => { if (!this.paused && !document.hidden) { this.next(); } }, this.interval);
},
stop() { if (this.timer) { clearInterval(this.timer); this.timer = null; } },
go(i) { this.active = (i + this.count) % this.count; this.start(); },
next() { this.go(this.active + 1); },
prev() { this.go(this.active - 1); },
}"
x-init="start()" x-on:keydown.arrow-right.prevent="next()" x-on:keydown.arrow-left.prevent="prev()">
<div class="hero-frame relative overflow-hidden rounded-[28px]">
<x-web.hero-flank-right />
<x-web.hero-flank-left />
{{-- Rechts wenig Innenabstand: das Bild liegt über der grünen Flanke, wie in der Visualisierung. --}}
<div class="relative grid items-center gap-10 p-6 sm:p-10 lg:grid-cols-12 lg:gap-10 lg:py-5 lg:pl-16 lg:pr-12">
{{-- Text --}}
<div class="space-y-6 lg:col-span-5 lg:py-10 lg:pr-4">
@if (!empty($content['eyebrow']))
<p class="hero-eyebrow">{{ $content['eyebrow'] }}</p>
@endif
<h1 class="hero-title">{!! $content['title'] ?? '' !!}</h1>
@if (!empty($content['subtitle']))
<p class="max-w-md text-base leading-relaxed text-muted-foreground">{!! $content['subtitle'] !!}</p>
@endif
<div>
<a href="{{ $content['cta_link'] ?? '/marken' }}" class="btn-hero">
{{ $content['cta_text'] ?? __('ui.all_brands_cta') }}
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"
aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" />
</svg>
</a>
</div>
</div>
{{-- Slideshow --}}
<div class="hero-image lg:col-span-7">
<div class="hero-image-frame">
<div class="relative aspect-[4/3] overflow-hidden rounded-[calc(1.25rem-1.5px)] bg-muted lg:aspect-[5/4]"
role="group" aria-roledescription="carousel" aria-label="{{ __('ui.hero_slider.label') }}"
x-on:mouseenter="paused = true" x-on:mouseleave="paused = false"
x-on:focusin="paused = true" x-on:focusout="paused = false" tabindex="0">
@forelse ($slides as $index => $slide)
<figure wire:key="hero-slide-{{ $index }}" data-hero-slide="{{ $index }}"
class="hero-slide absolute inset-0 m-0 {{ $index === 0 ? 'opacity-100' : 'opacity-0' }}"
x-bind:class="active === {{ $index }} ? 'opacity-100' : 'opacity-0 pointer-events-none'"
x-bind:aria-hidden="(active !== {{ $index }}).toString()">
<img src="{{ theme_image_url($slide['image']) }}" alt="{{ $slide['alt'] }}"
class="h-full w-full object-cover" @if ($index > 0) loading="lazy" @endif />
@if ($slide['label'] !== '')
<figcaption
class="absolute bottom-5 left-5 rounded-full bg-card/85 px-3 py-1 text-[10px] font-medium uppercase tracking-[0.18em] text-foreground/80 backdrop-blur-sm">
{{ $slide['label'] }}
</figcaption>
@endif
</figure>
@empty
<div class="flex h-full items-center justify-center text-sm text-muted-foreground">
{{ __('ui.hero_slider.empty') }}
</div>
@endforelse
</div>
</div>
</div>
</div>
</div>
{{-- Punkte unter dem Rahmen --}}
@if (count($slides) > 1)
<div class="mt-6 flex items-center justify-center gap-3" role="tablist" aria-label="{{ __('ui.hero_slider.dots') }}">
@foreach ($slides as $index => $slide)
<button type="button" role="tab" wire:key="hero-dot-{{ $index }}" x-on:click="go({{ $index }})"
x-bind:aria-selected="(active === {{ $index }}).toString()"
x-bind:class="active === {{ $index }} ? 'bg-primary w-14' : 'bg-border w-10 hover:bg-muted-foreground/40'"
class="h-1 cursor-pointer rounded-full transition-all duration-500 {{ $index === 0 ? 'bg-primary w-14' : 'bg-border w-10' }}"
aria-label="{{ __('ui.hero_slider.dot', ['n' => $index + 1, 'total' => count($slides), 'label' => $slide['label']]) }}">
</button>
@endforeach
</div>
@endif
</div>
</section>