- 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>
102 lines
6.1 KiB
PHP
102 lines
6.1 KiB
PHP
{{-- 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>
|