Behebt strukturelle Mobile-Bugs (320/390px) über presseecho, businessportal24 und den pressekonto-Hub hinweg: - Focus-/Kategorie-/Newsroom-Hero: Text im Flow (min-h + flex) statt fester Höhe, responsive Typo — Overlay überläuft nicht mehr nach oben. - Quality-Summary: Grid stackt auf Mobile (behebt Seiten-Overflow). - Hub: Utility-Bar mit Wrap, Header mit Mobile-Burger, Footer stackt, Architektur-Diagramm als gestapelte Mobile-Variante. - Sticky-Header (Portal): fehlende .header-sticky-CSS ergänzt und Script mit Platzhalter, damit der Header beim Scrollen sichtbar bleibt. - Header-Overflow bei 320px entschärft (Portal + Hub); Hub-Hero-H1 verkleinert, damit die Wortmarke "businessportal24" umbricht. - Mobile-Nav um Preise/FAQ/API ergänzt; Industry-Index-Dichte, Touch-Targets und Preise-Einzel-PM-Block für kleine Screens verbessert. - Homepages/Shared: px-8 → px-4 sm:px-6 lg:px-8. Co-authored-by: Cursor <cursoragent@cursor.com>
428 lines
27 KiB
PHP
428 lines
27 KiB
PHP
@props([
|
|
'navigation' => null,
|
|
'brand' => null,
|
|
])
|
|
|
|
@php
|
|
$themeKey = config('app.theme');
|
|
$brand = $brand ?? config('domains.domains.'.$themeKey.'.brand', [
|
|
'name' => 'businessportal',
|
|
'accent' => '24',
|
|
'tagline_short' => 'Pressemitteilungen · DACH',
|
|
]);
|
|
$brandName = $brand['name'] ?? 'businessportal';
|
|
$brandAccent = $brand['accent'] ?? '';
|
|
$brandTagline = __('web.footer.tagline_short');
|
|
@endphp
|
|
|
|
@php
|
|
$activeEdition = app()->getLocale();
|
|
\Carbon\Carbon::setLocale($activeEdition);
|
|
$today = now();
|
|
|
|
// Ausgaben = Sprachen (DE/EN). Wechsel führt zur Startseite der jeweiligen Ausgabe.
|
|
$editions = [
|
|
['code' => 'de', 'label' => 'DE', 'flag' => '🇩🇪'],
|
|
['code' => 'en', 'label' => 'EN', 'flag' => '🌐'],
|
|
];
|
|
|
|
// Navigation = echte Rubriken der aktiven Ausgabe. Es gibt keine separate
|
|
// Übersichtsseite; jeder Eintrag führt direkt auf die Kategorieseite.
|
|
// Die meistbespielten Rubriken erscheinen als Tabs, der Rest im
|
|
// „Mehr“-Dropdown (Desktop) bzw. in der Mobile-Liste.
|
|
$moreNavigation = [];
|
|
|
|
if ($navigation === null) {
|
|
$categoryItems = \App\Support\CategoryNavigation::items(null)->map(fn (array $category): array => [
|
|
'label' => $category['label'],
|
|
'href' => $category['href'],
|
|
'active' => request()->routeIs('kategorie') && request()->route('slug') === $category['slug'],
|
|
]);
|
|
|
|
$moreNavigation = $categoryItems->slice(9)->values()->all();
|
|
$navigation = collect([
|
|
['label' => __('web.nav.home'), 'href' => route('web.home'), 'active' => request()->routeIs('web.home')],
|
|
])->concat($categoryItems->take(9))->all();
|
|
}
|
|
|
|
$moreActive = collect($moreNavigation)->contains(fn (array $item): bool => $item['active'] ?? false);
|
|
$activeLabel = collect($navigation)->concat($moreNavigation)->firstWhere('active', true)['label'] ?? __('web.nav.menu');
|
|
@endphp
|
|
|
|
<header>
|
|
{{-- Top Utility Bar (dunkel) --}}
|
|
<div id="topbar" class="bg-topbar-grad text-ink-on-dark-2 border-b border-black">
|
|
<div class="max-w-layout mx-auto px-4 sm:px-6 lg:px-8 flex items-stretch text-[11.5px] tracking-wide">
|
|
<span class="flex items-center pr-3 sm:pr-4 py-2 whitespace-nowrap border-r border-ink-on-dark-rule text-[10.5px] sm:text-[11.5px]">
|
|
<span class="hidden sm:inline">{{ ucfirst($today->isoFormat('dd, D. MMMM YYYY')) }}</span>
|
|
<span class="sm:hidden">{{ ucfirst($today->isoFormat('dd, D. MMM')) }}</span>
|
|
</span>
|
|
|
|
<span class="hidden md:flex items-center px-3.5 text-[9.5px] uppercase font-semibold tracking-[0.16em] text-ink-3 whitespace-nowrap">
|
|
{{ __('web.header.edition') }}
|
|
</span>
|
|
|
|
@foreach ($editions as $edition)
|
|
<a href="{{ route('web.home', ['edition' => $edition['code']]) }}"
|
|
class="flex items-center gap-1 sm:gap-1.5 px-2 sm:px-2.5 py-2.5 text-[11px] sm:text-[11.5px] whitespace-nowrap -mb-px border-b-2 transition-colors
|
|
@if ($edition['code'] === $activeEdition) font-semibold text-ink-on-dark bg-white/[0.06] border-brand
|
|
@else font-medium text-ink-on-dark-2 border-transparent hover:text-ink-on-dark hover:bg-white/[0.04] @endif"
|
|
aria-label="{{ __('web.header.edition') }} {{ $edition['label'] }}"
|
|
@if ($edition['code'] === $activeEdition) aria-current="true" @endif>
|
|
<span class="text-[11px] sm:text-[12px] leading-none">{{ $edition['flag'] }}</span>
|
|
<span>{{ $edition['label'] }}</span>
|
|
</a>
|
|
@endforeach
|
|
|
|
<span class="flex-1"></span>
|
|
|
|
{{-- Sprache: mobil verkürzt; ab lg mit FAQ/API --}}
|
|
<span class="flex items-center gap-3 sm:gap-4 py-2 whitespace-nowrap">
|
|
<span class="inline-flex items-center gap-1.5">
|
|
<svg width="11" height="11" viewBox="0 0 12 12" fill="none" class="opacity-60" aria-hidden="true">
|
|
<circle cx="6" cy="6" r="5" stroke="currentColor" stroke-width="1" />
|
|
<path d="M1 6h10M6 1c2 1.5 2 8.5 0 10M6 1c-2 1.5-2 8.5 0 10" stroke="currentColor" stroke-width="1" fill="none" />
|
|
</svg>
|
|
<strong class="text-ink-on-dark font-semibold">
|
|
<span class="hidden lg:inline">{{ $activeEdition === 'en' ? 'English' : 'Deutsch' }}</span>
|
|
<span class="lg:hidden">{{ strtoupper($activeEdition) }}</span>
|
|
</strong>
|
|
</span>
|
|
<span class="hidden lg:inline-block w-px h-[14px] bg-ink-on-dark-rule"></span>
|
|
<a href="{{ route('preise') }}" class="cursor-pointer font-medium text-ink-on-dark hover:text-brand transition-colors">{{ __('web.header.pricing') }}</a>
|
|
<span class="hidden lg:inline-block w-px h-[14px] bg-ink-on-dark-rule"></span>
|
|
<a href="{{ route('faq') }}" class="hidden lg:inline cursor-pointer hover:text-ink-on-dark transition-colors">FAQ</a>
|
|
<a href="{{ route('api') }}" class="hidden lg:inline cursor-pointer hover:text-ink-on-dark transition-colors">API</a>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Header (Logo + Suche mittig + Buttons rechtsbündig + Burger) --}}
|
|
<div id="header" class="header-normal bg-bg border-b border-bg-rule"
|
|
x-data="{ searchOpen: false, loginOpen: false }"
|
|
@keydown.escape.window="searchOpen = false; loginOpen = false"
|
|
@keydown.window.prevent.cmd.k="$refs.desktopSearch ? $refs.desktopSearch.focus() : searchOpen = true"
|
|
@keydown.window.prevent.ctrl.k="$refs.desktopSearch ? $refs.desktopSearch.focus() : searchOpen = true">
|
|
<div class="max-w-layout mx-auto px-3 sm:px-6 lg:px-8 py-3 lg:py-[18px] flex items-center gap-2 sm:gap-4 lg:gap-6">
|
|
<a href="{{ route('web.home') }}" class="block cursor-pointer group flex-shrink-0 min-w-0" aria-label="{{ $brandName }}{{ $brandAccent }} {{ __('web.header.homepage') }}">
|
|
<div class="text-[19px] sm:text-[24px] lg:text-[28px] font-semibold leading-none tracking-[-0.5px] truncate">
|
|
<x-web.brand-mark :brand="$themeKey" />
|
|
</div>
|
|
<div class="eyebrow muted mt-1 text-[9.5px] tracking-[0.18em] hidden sm:block">
|
|
{{ $brandTagline }}
|
|
</div>
|
|
</a>
|
|
|
|
{{-- Suchfeld nur ab md sichtbar, mittig im verbleibenden Raum --}}
|
|
<div class="hidden md:flex flex-1 justify-center min-w-0">
|
|
<form action="{{ route('suche') }}" method="get" class="w-full max-w-[460px]">
|
|
<label class="sr-only" for="site-search">{{ __('web.header.search_label') }}</label>
|
|
<div class="flex items-center gap-2.5 px-3.5 py-2.5 border border-bg-rule bg-bg-elev text-[13px] text-ink-3 rounded-[2px] focus-within:border-brand transition-colors">
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
|
|
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
|
</svg>
|
|
<input id="site-search" type="search" name="q" x-ref="desktopSearch"
|
|
placeholder="{{ __('web.header.search_placeholder') }}"
|
|
class="flex-1 bg-transparent border-0 p-0 text-[13px] text-ink placeholder:text-ink-3 focus:outline-none focus:ring-0 min-w-0">
|
|
<span class="hidden xl:inline-block text-[10.5px] text-ink-4 border border-bg-rule px-1.5 py-0.5 rounded-[2px] font-mono">⌘K</span>
|
|
</div>
|
|
<div class="hidden lg:flex justify-end mt-1.5">
|
|
<a href="{{ route('suche') }}" class="inline-flex items-center gap-1.5 text-[11.5px] text-ink-3 underline underline-offset-2 decoration-[#1C1A17]/40 cursor-pointer hover:text-ink hover:decoration-brand transition-colors">
|
|
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
<path d="M2 3h8M3.5 6h5M5 9h2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" />
|
|
</svg>
|
|
{{ __('web.header.advanced_search') }}
|
|
</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<span class="flex-1 md:hidden"></span>
|
|
|
|
{{-- Buttons rechtsbündig --}}
|
|
<div class="flex items-center gap-1 sm:gap-2 flex-shrink-0">
|
|
{{-- Such-Icon nur auf mobile --}}
|
|
<button type="button"
|
|
@click="searchOpen = true"
|
|
class="md:hidden inline-flex items-center justify-center w-10 h-10 text-ink rounded-[2px] cursor-pointer hover:bg-bg-elev transition-colors"
|
|
aria-label="{{ __('web.header.search_open') }}">
|
|
<svg width="20" height="20" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
|
|
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
|
</svg>
|
|
</button>
|
|
|
|
{{-- Anmelden: öffnet Modal mit Pressekonto-Erklärung --}}
|
|
<button type="button"
|
|
@click="loginOpen = true"
|
|
class="inline-flex items-center gap-2 px-2 sm:px-3 lg:px-4 py-2 lg:py-2.5 text-[13px] font-semibold text-ink rounded-[2px] cursor-pointer hover:text-brand transition-colors"
|
|
aria-label="{{ __('web.header.login') }}"
|
|
aria-haspopup="dialog">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true">
|
|
<circle cx="12" cy="8" r="4" stroke="currentColor" stroke-width="1.8" />
|
|
<path d="M4 21c0-4 4-7 8-7s8 3 8 7" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
</svg>
|
|
<span class="hidden sm:inline">{{ __('web.header.login') }}</span>
|
|
</button>
|
|
|
|
{{-- Veröffentlichen --}}
|
|
<a href="{{ route('veroeffentlichen') }}"
|
|
class="inline-flex items-center gap-1.5 sm:gap-2 px-2.5 sm:px-4 lg:px-[18px] py-2 lg:py-2.5 text-[12.5px] sm:text-[13px] font-semibold text-white bg-brand cursor-pointer hover:bg-brand-deep rounded-[2px] transition-colors whitespace-nowrap"
|
|
aria-label="{{ __('web.header.publish_aria') }}">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" class="sm:hidden" aria-hidden="true">
|
|
<path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" />
|
|
</svg>
|
|
<span class="sm:hidden">PM</span>
|
|
<span class="hidden sm:inline">{{ __('web.header.publish') }}</span>
|
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" class="hidden sm:inline" aria-hidden="true">
|
|
<path d="M3 6h6M6 3l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Anmelde-Modal: erklärt Pressekonto (Hub) und verlinkt dorthin --}}
|
|
@php
|
|
$portalUrl = rtrim(config('domains.domain_portal_url', config('app.url')), '/');
|
|
@endphp
|
|
<div x-show="loginOpen"
|
|
x-transition.opacity.duration.150ms
|
|
class="fixed inset-0 z-50 bg-ink/70 backdrop-blur-sm flex items-start sm:items-center justify-center p-4 sm:p-6 overflow-y-auto"
|
|
@click.self="loginOpen = false"
|
|
role="dialog"
|
|
aria-modal="true"
|
|
aria-labelledby="login-modal-title"
|
|
style="display: none;">
|
|
<div x-show="loginOpen"
|
|
x-transition.duration.200ms
|
|
class="relative w-full max-w-[520px] bg-bg border border-bg-rule-strong shadow-2xl mt-10 sm:mt-0">
|
|
<button type="button"
|
|
@click="loginOpen = false"
|
|
class="absolute top-3 right-3 inline-flex items-center justify-center w-10 h-10 text-ink-3 rounded-[2px] cursor-pointer hover:text-ink hover:bg-bg-elev transition-colors"
|
|
aria-label="{{ __('web.header.login_modal_close') }}">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="M6 6l12 12M6 18L18 6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
</svg>
|
|
</button>
|
|
|
|
<div class="px-6 sm:px-8 pt-7 pb-6">
|
|
<div class="eyebrow mb-2">{{ __('web.header.login_modal_eyebrow') }}</div>
|
|
<h2 id="login-modal-title" class="font-serif text-[24px] sm:text-[26px] font-semibold text-ink tracking-[-0.4px] leading-[1.15] m-0 mb-3.5">
|
|
{{ __('web.header.login_modal_title') }}
|
|
</h2>
|
|
<p class="text-[13.5px] leading-[1.65] text-ink-2 m-0 mb-6">
|
|
{{ __('web.header.login_modal_text') }}
|
|
</p>
|
|
|
|
<div class="flex flex-col sm:flex-row gap-2.5">
|
|
<a href="{{ $portalUrl }}/login"
|
|
class="inline-flex items-center justify-center gap-2 px-[18px] py-2.5 text-[13px] font-semibold text-white bg-brand cursor-pointer hover:bg-brand-deep rounded-[2px] transition-colors">
|
|
{{ __('web.header.login_modal_login') }}
|
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
<path d="M3 6h6M6 3l3 3-3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</a>
|
|
<a href="{{ $portalUrl }}"
|
|
class="inline-flex items-center justify-center gap-2 px-[18px] py-2.5 text-[13px] font-semibold text-ink border border-bg-rule-strong cursor-pointer hover:border-brand hover:text-brand rounded-[2px] transition-colors">
|
|
{{ __('web.header.login_modal_hub') }}
|
|
</a>
|
|
</div>
|
|
|
|
<p class="text-[11.5px] text-ink-3 m-0 mt-4">
|
|
{{ __('web.header.login_modal_note') }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Such-Overlay --}}
|
|
<div x-show="searchOpen"
|
|
x-transition.opacity.duration.150ms
|
|
class="fixed inset-0 z-50 bg-ink/70 backdrop-blur-sm"
|
|
@click.self="searchOpen = false"
|
|
style="display: none;">
|
|
<div x-show="searchOpen"
|
|
x-transition.duration.200ms
|
|
class="bg-bg border-b border-bg-rule shadow-xl">
|
|
<div class="max-w-layout mx-auto px-4 sm:px-6 py-6">
|
|
<div class="flex items-start justify-between mb-4">
|
|
<div>
|
|
<div class="eyebrow mb-1">{{ __('web.header.search_eyebrow') }}</div>
|
|
<h2 class="font-serif text-[22px] font-semibold text-ink">{{ __('web.header.search_title') }}</h2>
|
|
</div>
|
|
<button type="button"
|
|
@click="searchOpen = false"
|
|
class="inline-flex items-center justify-center w-10 h-10 text-ink rounded-[2px] cursor-pointer hover:bg-bg-elev transition-colors"
|
|
aria-label="{{ __('web.header.search_close') }}">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="M6 6l12 12M6 18L18 6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<form action="{{ route('suche') }}" method="get">
|
|
<label class="sr-only" for="site-search-mobile">{{ __('web.header.search_title') }}</label>
|
|
<div class="flex items-center gap-2.5 px-4 py-3.5 border border-bg-rule-strong bg-bg-elev text-[15px] text-ink-3 rounded-[2px]">
|
|
<svg width="20" height="20" viewBox="0 0 16 16" fill="none" aria-hidden="true">
|
|
<circle cx="7" cy="7" r="5" stroke="currentColor" stroke-width="1.5" />
|
|
<path d="M11 11l3 3" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" />
|
|
</svg>
|
|
<input id="site-search-mobile" type="search" name="q"
|
|
placeholder="{{ __('web.header.search_placeholder') }}"
|
|
x-ref="searchInput"
|
|
x-init="$watch('searchOpen', value => value && setTimeout(() => $refs.searchInput.focus(), 50))"
|
|
class="flex-1 bg-transparent border-0 p-0 text-[15px] text-ink placeholder:text-ink-3 focus:outline-none focus:ring-0 min-w-0">
|
|
<button type="submit"
|
|
class="px-3 py-1.5 text-[12px] font-semibold bg-brand text-white rounded-[2px] cursor-pointer hover:bg-brand-deep transition-colors">
|
|
{{ __('web.header.search_submit') }}
|
|
</button>
|
|
</div>
|
|
<div class="mt-3 flex justify-between text-[11.5px] text-ink-3">
|
|
<a href="{{ route('suche') }}" class="inline-flex items-center gap-1.5 cursor-pointer hover:text-ink transition-colors underline underline-offset-2 decoration-[#1C1A17]/40">
|
|
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
<path d="M2 3h8M3.5 6h5M5 9h2" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" />
|
|
</svg>
|
|
{{ __('web.header.advanced_search') }}
|
|
</a>
|
|
<span class="hidden sm:inline-flex items-center gap-1.5">
|
|
{{ __('web.header.press') }}
|
|
<kbd class="font-mono text-[10.5px] text-ink-4 border border-bg-rule px-1.5 py-0.5 rounded-[2px]">Esc</kbd>
|
|
{{ __('web.header.to_close') }}
|
|
</span>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{{-- Main Navigation (Underline-Tabs Desktop, Burger Mobile) --}}
|
|
<nav class="bg-bg border-b border-bg-rule relative"
|
|
x-data="{ menuOpen: false }"
|
|
@keydown.escape.window="menuOpen = false"
|
|
@click.outside="menuOpen = false"
|
|
aria-label="{{ __('web.nav.aria_label') }}">
|
|
|
|
{{-- Desktop: horizontale Tabs --}}
|
|
<div class="hidden lg:flex max-w-layout mx-auto px-8 items-stretch">
|
|
@foreach ($navigation as $item)
|
|
<a href="{{ $item['href'] }}"
|
|
class="px-4 py-3.5 text-[13.5px] whitespace-nowrap border-b-2 -mb-px cursor-pointer transition-colors
|
|
@if ($item['active'] ?? false) font-semibold text-ink border-brand
|
|
@else font-medium text-ink-2 border-transparent hover:text-ink hover:border-bg-rule-strong/30 @endif">
|
|
{{ $item['label'] }}
|
|
</a>
|
|
@endforeach
|
|
|
|
@if (count($moreNavigation) > 0)
|
|
{{-- Restliche Rubriken (jenseits der Top 9) im Dropdown --}}
|
|
<div class="relative flex items-stretch"
|
|
x-data="{ moreOpen: false }"
|
|
@keydown.escape.window="moreOpen = false"
|
|
@click.outside="moreOpen = false">
|
|
<button type="button"
|
|
@click="moreOpen = !moreOpen"
|
|
class="flex items-center gap-1.5 px-4 py-3.5 text-[13.5px] whitespace-nowrap border-b-2 -mb-px cursor-pointer transition-colors
|
|
@if ($moreActive) font-semibold text-ink border-brand
|
|
@else font-medium text-ink-2 border-transparent hover:text-ink hover:border-bg-rule-strong/30 @endif"
|
|
:aria-expanded="moreOpen.toString()"
|
|
aria-controls="desktop-nav-more">
|
|
{{ __('web.nav.more') }}
|
|
<svg width="10" height="10" viewBox="0 0 12 12" fill="none" class="transition-transform"
|
|
:class="{ 'rotate-180': moreOpen }" aria-hidden="true">
|
|
<path d="M2 4l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</button>
|
|
|
|
<div id="desktop-nav-more"
|
|
x-show="moreOpen"
|
|
x-transition.origin.top
|
|
x-cloak
|
|
class="absolute top-full right-0 z-40 min-w-[220px] bg-bg-elev border border-bg-rule shadow-lg py-1.5"
|
|
style="display: none;">
|
|
@foreach ($moreNavigation as $item)
|
|
<a href="{{ $item['href'] }}"
|
|
class="block px-4 py-2.5 text-[13.5px] whitespace-nowrap cursor-pointer transition-colors
|
|
@if ($item['active'] ?? false) font-semibold text-brand bg-brand/[0.04]
|
|
@else font-medium text-ink-2 hover:text-ink hover:bg-bg @endif">
|
|
{{ $item['label'] }}
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
|
|
{{-- Mobile: aktive Kategorie + Burger --}}
|
|
<div class="lg:hidden max-w-layout mx-auto px-4 sm:px-6">
|
|
<button type="button"
|
|
@click="menuOpen = !menuOpen"
|
|
class="flex items-center justify-between w-full py-3 cursor-pointer group"
|
|
:aria-expanded="menuOpen.toString()"
|
|
aria-controls="mobile-nav-menu"
|
|
aria-label="{{ __('web.nav.open_menu') }}">
|
|
<span class="flex items-center gap-3">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="text-ink"
|
|
:class="{ 'hidden': menuOpen }" aria-hidden="true">
|
|
<path d="M3 6h18M3 12h18M3 18h18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
|
</svg>
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="text-ink hidden"
|
|
:class="{ 'hidden': !menuOpen, '!block': menuOpen }" aria-hidden="true">
|
|
<path d="M6 6l12 12M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
|
</svg>
|
|
<span class="text-[10px] font-bold tracking-[0.18em] uppercase text-ink-3 group-hover:text-ink transition-colors">{{ __('web.nav.section') }}</span>
|
|
<span class="font-serif text-[15px] font-semibold text-ink leading-none">{{ $activeLabel }}</span>
|
|
</span>
|
|
<svg width="14" height="14" viewBox="0 0 12 12" fill="none" class="text-ink-3 transition-transform"
|
|
:class="{ 'rotate-180': menuOpen }" aria-hidden="true">
|
|
<path d="M2 4l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
{{-- Mobile Dropdown --}}
|
|
<div id="mobile-nav-menu"
|
|
x-show="menuOpen"
|
|
x-transition.origin.top
|
|
x-cloak
|
|
class="lg:hidden border-t border-bg-rule bg-bg-elev absolute left-0 right-0 z-40 shadow-lg"
|
|
style="display: none;">
|
|
<div class="max-w-layout mx-auto px-4 sm:px-6 py-2">
|
|
@foreach (collect($navigation)->concat($moreNavigation) as $item)
|
|
<a href="{{ $item['href'] }}"
|
|
class="flex items-center justify-between px-3 py-3 text-[14px] border-b border-bg-rule cursor-pointer transition-colors
|
|
@if ($item['active'] ?? false) font-semibold text-brand bg-brand/[0.04]
|
|
@else font-medium text-ink-2 hover:text-ink hover:bg-bg @endif">
|
|
<span>{{ $item['label'] }}</span>
|
|
@if ($item['active'] ?? false)
|
|
<svg width="14" height="14" viewBox="0 0 12 12" fill="none" aria-hidden="true">
|
|
<path d="M2 6l3 3 5-6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
@else
|
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" class="text-ink-3" aria-hidden="true">
|
|
<path d="M4 2l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
@endif
|
|
</a>
|
|
@endforeach
|
|
|
|
{{-- Service-Links: auf Mobile sonst nur im Footer erreichbar (FAQ/API liegen in der Topbar hinter lg:). --}}
|
|
<div class="mt-1 pt-1">
|
|
@foreach ([['label' => __('web.header.pricing'), 'href' => route('preise')], ['label' => 'FAQ', 'href' => route('faq')], ['label' => 'API', 'href' => route('api')]] as $service)
|
|
<a href="{{ $service['href'] }}"
|
|
class="flex items-center justify-between px-3 py-3 text-[13.5px] border-b border-bg-rule last:border-b-0 font-medium text-ink-3 hover:text-ink hover:bg-bg cursor-pointer transition-colors">
|
|
<span>{{ $service['label'] }}</span>
|
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" class="text-ink-4" aria-hidden="true">
|
|
<path d="M4 2l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
</svg>
|
|
</a>
|
|
@endforeach
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
{{-- Befüllt sich selbst (TickerData) — auf allen Seiten identisch. --}}
|
|
<x-web.live-ticker />
|
|
</header>
|