185 lines
8.1 KiB
PHP
185 lines
8.1 KiB
PHP
<!DOCTYPE html>
|
||
@php
|
||
// Farbpalette der Interior-Welt (Nachtrag 18): ohne Schalter setzt der Server die Klasse aus
|
||
// config('app.palette'); mit Schalter entscheidet das Skript im <head> anhand des localStorage.
|
||
$paletteFixed = config('app.theme', 'b2in') === 'b2in'
|
||
&& b2in_world() === 'interior'
|
||
&& ! config('app.palette_switch')
|
||
&& b2in_palette() === ''
|
||
&& config('app.palette') === 'modern';
|
||
@endphp
|
||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}"{!! $paletteFixed ? ' class="palette-modern"' : '' !!}>
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||
|
||
@unless (config('app.indexable'))
|
||
{{-- Vorschau-/Testinstanz: darf nicht in den Suchindex. --}}
|
||
<meta name="robots" content="noindex, nofollow">
|
||
@endunless
|
||
|
||
<title>@yield('title', $domainName ?? config('app.name', 'Laravel'))</title>
|
||
|
||
<meta name="description" content="@yield('meta_description', 'B2in Interior verbindet starke Einrichtungsmarken mit persönlicher Beratung – von der Maßanfertigung bis zur vollständigen Ausstattung für Zuhause und Projekte.')">
|
||
@hasSection('meta_image')
|
||
<meta property="og:image" content="@yield('meta_image')">
|
||
@else
|
||
<meta property="og:image" content="{{ asset('img/assets/b2in-og-default.jpg') }}">
|
||
@endif
|
||
<meta property="og:title" content="@yield('title', $domainName ?? config('app.name', 'Laravel'))">
|
||
<meta property="og:description" content="@yield('meta_description', 'B2in Interior verbindet starke Einrichtungsmarken mit persönlicher Beratung – von der Maßanfertigung bis zur vollständigen Ausstattung für Zuhause und Projekte.')">
|
||
<meta property="og:type" content="website">
|
||
<meta property="og:url" content="{{ url()->current() }}">
|
||
<link rel="canonical" href="{{ url()->current() }}">
|
||
<meta property="og:locale" content="de_DE">
|
||
<meta name="twitter:card" content="summary_large_image">
|
||
|
||
@stack('meta')
|
||
|
||
<!-- Favicons (wie Backend) -->
|
||
<link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
|
||
<link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
|
||
<link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png">
|
||
<link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
|
||
<link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
|
||
<link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
|
||
<link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
|
||
<link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
|
||
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
|
||
<link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.png">
|
||
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
|
||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
|
||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
|
||
<link rel="shortcut icon" href="{{ asset(\App\Helpers\ThemeHelper::getFaviconPath()) }}">
|
||
<link rel="manifest" href="/favicon/manifest.json">
|
||
<meta name="msapplication-TileColor" content="#f7f4ef">
|
||
<meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png">
|
||
<meta name="theme-color" content="#f7f4ef">
|
||
|
||
@php
|
||
$theme = config('app.theme', 'b2in');
|
||
// Farb-Schalter nur auf den Interior-Seiten von b2in, solange die Palette abgestimmt wird.
|
||
$showPaletteSwitch = $theme === 'b2in' && b2in_world() === 'interior' && config('app.palette_switch');
|
||
// Entwurf /entwurf (Nachtrag 19): feste Palette „greige“ am Body, kein Browser-Schalter.
|
||
$paletteDraft = b2in_palette() === 'greige';
|
||
$hideAnnouncementBar = trim($__env->yieldContent('announcement_bar', 'on')) === 'off';
|
||
@endphp
|
||
|
||
@if ($showPaletteSwitch && ! $paletteDraft)
|
||
{{-- Läuft vor dem Stylesheet: setzt die gemerkte Palette, bevor die Seite gezeichnet wird.
|
||
?palette=modern|classic in der URL überschreibt und merkt sich die Wahl; ohne
|
||
gemerkte Wahl gilt config('app.palette'). --}}
|
||
<script>
|
||
(function () {
|
||
var fromUrl = new URLSearchParams(window.location.search).get('palette');
|
||
var palette = null;
|
||
try {
|
||
if (fromUrl === 'modern' || fromUrl === 'classic') {
|
||
localStorage.setItem('b2in-palette', fromUrl);
|
||
}
|
||
palette = localStorage.getItem('b2in-palette');
|
||
} catch (e) {
|
||
palette = fromUrl;
|
||
}
|
||
if (palette === null) {
|
||
palette = @js(config('app.palette'));
|
||
}
|
||
if (palette === 'modern') {
|
||
document.documentElement.classList.add('palette-modern');
|
||
}
|
||
})();
|
||
</script>
|
||
@endif
|
||
|
||
@vite([
|
||
\App\Helpers\ThemeHelper::getThemeCssPath(),
|
||
'resources/js/app.js'
|
||
], 'build/' . $theme)
|
||
|
||
<!-- Sticky Header Script -->
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
const topbar = document.getElementById('topbar');
|
||
const header = document.getElementById('header');
|
||
|
||
if (!topbar || !header) return;
|
||
|
||
let topbarHeight = topbar.offsetHeight;
|
||
let isHeaderSticky = false;
|
||
let ticking = false;
|
||
|
||
function updateHeaderPosition() {
|
||
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
||
|
||
if (scrollTop >= topbarHeight && !isHeaderSticky) {
|
||
header.classList.remove('header-normal');
|
||
header.classList.add('header-sticky');
|
||
isHeaderSticky = true;
|
||
} else if (scrollTop < topbarHeight && isHeaderSticky) {
|
||
header.classList.remove('header-sticky');
|
||
header.classList.add('header-normal');
|
||
isHeaderSticky = false;
|
||
}
|
||
ticking = false;
|
||
}
|
||
|
||
updateHeaderPosition();
|
||
|
||
window.addEventListener('scroll', function() {
|
||
if (!ticking) {
|
||
requestAnimationFrame(updateHeaderPosition);
|
||
ticking = true;
|
||
}
|
||
}, { passive: true });
|
||
|
||
window.addEventListener('resize', function() {
|
||
topbarHeight = topbar.offsetHeight;
|
||
updateHeaderPosition();
|
||
}, { passive: true });
|
||
});
|
||
</script>
|
||
|
||
{{-- Gilt für alle Seiten: das Terminanfrage-Widget im Layout nutzt x-cloak, die einzelnen
|
||
Seiten bringen die Regel bisher nur teilweise selbst mit. --}}
|
||
<style>
|
||
[x-cloak] {
|
||
display: none !important;
|
||
}
|
||
</style>
|
||
|
||
<!-- Additional Styles -->
|
||
@stack('styles')
|
||
</head>
|
||
|
||
<body class="antialiased bg-background text-foreground world-{{ b2in_world() }}{{ $paletteDraft ? ' palette-greige' : '' }}">
|
||
|
||
{{-- GTM noscript (nur bei GTM-Nutzung) --}}
|
||
<x-cookie-consent::gtm-noscript />
|
||
|
||
{{-- Ankündigungsleiste – eine Seite kann sie mit @section('announcement_bar', 'off') abschalten --}}
|
||
@unless ($hideAnnouncementBar)
|
||
<livewire:web.components.ui.announcement-bar />
|
||
@endunless
|
||
|
||
{{-- TopBar (Backup: Sprachwechsel & Social Icons – folgt später) --}}
|
||
{{-- <livewire:web.components.ui.top-bar /> --}}
|
||
|
||
@yield('content')
|
||
|
||
{{-- Terminanfrage: schwebend unten rechts, auf allen Seiten --}}
|
||
<livewire:web.components.ui.appointment-widget />
|
||
|
||
@if ($showPaletteSwitch)
|
||
<x-palette-switch :draft="$paletteDraft" />
|
||
@endif
|
||
|
||
{{-- Cookie Consent Manager (vor Livewire-Scripts) --}}
|
||
<x-cookie-consent::manager />
|
||
|
||
<!-- Additional Scripts -->
|
||
@stack('scripts')
|
||
</body>
|
||
|
||
</html>
|