b2in/resources/views/web/layouts/web-master.blade.php
Kevin Adametz b5ed756d67 Git-Deploy per Tag, Betriebsüberwachung und Release-Seeder für den Livegang
- dev/betrieb/deploy.sh: Deploy nur per Tag, mit --seed (Seeder im Wartungsmodus)
  und --initial (Vorschau/Live einmalig an Ort und Stelle auf Git umstellen)
- dev/betrieb/vorschau-auffrischen.sh: Live-DB und Live-Medien in die Vorschau (Generalprobe)
- InteriorReleaseSeeder: alle Inhaltsschritte des Relaunchs in einem Lauf, idempotent;
  Displays, Playlists und Mediathek bleiben unberührt
- DisplayInteriorBrandingSeeder überschreibt keinen inzwischen gepflegten Claim mehr
- Monitoring: GlitchTip (Server + Browser), /health mit Token, Scheduler-Herzschlag,
  Alarme per Mail und ntfy, Version in about und /health
- public/build versioniert; .gitignore: macOS-Muster Icon traf resources/views/flux/icon/
- Runbook: dev/betrieb/README.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:56:23 +00:00

141 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.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<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');
// Global per B2IN_ANNOUNCEMENT_BAR, einzeln per @section('announcement_bar', 'off').
$hideAnnouncementBar = ! config('app.announcement_bar') || trim($__env->yieldContent('announcement_bar', 'on')) === 'off';
@endphp
@vite([
\App\Helpers\ThemeHelper::getThemeCssPath(),
'resources/js/app.js'
], 'build/' . $theme)
<x-monitoring.browser-errors :build="'build/' . $theme" area="web" />
<!-- 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() }}">
{{-- GTM noscript (nur bei GTM-Nutzung) --}}
<x-cookie-consent::gtm-noscript />
{{-- Ankündigungsleiste – global per B2IN_ANNOUNCEMENT_BAR, je Seite mit @section('announcement_bar', 'off') abschaltbar --}}
@unless ($hideAnnouncementBar)
<livewire:web.components.ui.announcement-bar />
@endunless
@yield('content')
{{-- Terminanfrage: schwebend unten rechts, auf allen Seiten --}}
<livewire:web.components.ui.appointment-widget />
{{-- Cookie Consent Manager (vor Livewire-Scripts) --}}
<x-cookie-consent::manager />
<!-- Additional Scripts -->
@stack('scripts')
</body>
</html>