Automatisch erstellte Preview-Seite

This commit is contained in:
2026-07-18 05:05:46 +00:00
commit e180aab691
21 changed files with 4009 additions and 0 deletions

620
index.html Normal file
View File

@@ -0,0 +1,620 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./support.js"></script>
</head>
<body>
<x-dc>
<helmet>
<link href="assets/fonts.css" rel="stylesheet">
<link href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css" rel="stylesheet">
<script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #0d0f12; font-family: 'Archivo', system-ui, sans-serif; -webkit-font-smoothing: antialiased; }
a { color: #f0f0ec; text-decoration: none; }
a:hover { color: var(--accent, #F0912F); }
@keyframes lw-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
@keyframes lw-fadein { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@media (max-width: 1080px) {
.lw-review { display: none !important; }
}
@media (max-width: 860px) {
.lw-navlinks { display: none !important; }
.lw-burger { display: inline-flex !important; }
.lw-benefits { grid-template-columns: repeat(2, 1fr) !important; row-gap: 26px !important; }
}
@media (max-width: 520px) {
.lw-benefits { grid-template-columns: 1fr !important; }
}
@media (max-width: 980px) {
.lw-services { grid-template-columns: repeat(2, 1fr) !important; }
}
@media (max-width: 620px) {
.lw-services { grid-template-columns: 1fr !important; }
}
@media (max-width: 980px) {
.lw-refs { grid-template-columns: repeat(2, 1fr) !important; grid-auto-rows: 200px !important; }
}
@media (max-width: 620px) {
.lw-refs { grid-template-columns: 1fr !important; grid-auto-rows: 220px !important; }
.lw-ref-wide { grid-column: auto !important; grid-row: auto !important; }
}
@media (max-width: 860px) {
.lw-about { grid-template-columns: 1fr !important; }
.lw-contact { grid-template-columns: 1fr !important; }
.lw-footer-cols { grid-template-columns: repeat(2, 1fr) !important; }
.lw-footer-bottom { flex-direction: column !important; align-items: flex-start !important; }
.lw-footer-bottom > div:last-child { text-align: left !important; }
.lw-footer-bottom > div:last-child > div { justify-content: flex-start !important; }
}
</style>
</helmet>
<div ref="{{ rootRef }}" style="width: 100%; --accent: #F0912F; background: #0d0f12;">
<!-- HERO -->
<div style="position: relative; min-height: 100vh; overflow: hidden;">
<!-- BACKGROUND -->
<div style="position: absolute; inset: 0; z-index: 0; background: radial-gradient(120% 90% at 78% 12%, #1c2530 0%, #12161b 42%, #0a0c0f 100%);"></div>
<div style="position: absolute; inset: 0; z-index: 1; filter: hue-rotate(85deg) saturate(1.15);">
<img src="assets/hero-tankklappe.jpg" alt="" style="display: block; width: 100%; height: 100%; object-fit: cover;">
</div>
<!-- blue tint -->
<div style="position: absolute; inset: 0; z-index: 2; pointer-events: none; background: rgba(18,60,120,0.32); mix-blend-mode: multiply;"></div>
<!-- legibility overlay (click-through) -->
<div style="position: absolute; inset: 0; z-index: 2; pointer-events: none; background: linear-gradient(180deg, rgba(9,11,14,0.82) 0%, rgba(9,11,14,0.34) 30%, rgba(9,11,14,0.30) 55%, rgba(9,11,14,0.86) 100%);"></div>
<div style="position: absolute; inset: 0; z-index: 2; pointer-events: none; background: radial-gradient(90% 70% at 22% 42%, rgba(9,11,14,0.55) 0%, rgba(9,11,14,0) 60%);"></div>
<!-- thin accent glow top -->
<div style="position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 4; background: linear-gradient(90deg, transparent, var(--accent, #F0912F), transparent); opacity: 0.5;"></div>
<!-- NAV -->
<nav ref="{{ navRef }}" style="position: fixed; top: 0; left: 0; right: 0; z-index: 40; transition: background .35s ease, backdrop-filter .35s ease, border-color .35s ease, padding .35s ease; padding: 22px clamp(20px, 4vw, 56px); border-bottom: 1px solid transparent;">
<div style="max-width: 1320px; margin: 0 auto; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 24px;">
<!-- left links -->
<div class="lw-navlinks" style="display: flex; gap: 34px; align-items: center;">
<a href="#services" style="font-size: 15px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase;">Services</a>
<a href="#referenzen" style="font-size: 15px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase;">Referenzen</a>
</div>
<!-- logo — PLATZHALTER: assets/logo-placeholder.svg durch Ihr Logo ersetzen -->
<a href="#top" style="display: flex; align-items: center; justify-self: center;">
<img src="assets/logo-placeholder.svg" alt="Karosserie und Lack Stahl" style="height: 26px; width: auto; display: block;">
</a>
<!-- right links -->
<div class="lw-navlinks" style="display: flex; gap: 34px; align-items: center; justify-content: flex-end;">
<a href="#ueber-uns" style="font-size: 15px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase;">Über uns</a>
<a href="#kontakt" style="font-size: 15px; font-weight: 600; letter-spacing: .02em; text-transform: uppercase;">Kontakt</a>
</div>
<!-- mobile menu button -->
<button class="lw-burger" aria-label="Menü" style="display: none; grid-column: 3; justify-self: end; background: transparent; border: 1.5px solid rgba(255,255,255,.28); border-radius: 10px; padding: 9px 11px; cursor: pointer; color: #f4f3ef; align-items: center; gap: 8px;">
<span style="display: block; width: 18px; height: 2px; background: currentColor; box-shadow: 0 6px 0 currentColor, 0 -6px 0 currentColor;"></span>
</button>
</div>
</nav>
<!-- HERO CONTENT -->
<div style="position: relative; z-index: 10; display: flex; flex-direction: column; min-height: 100vh; padding: clamp(120px, 16vh, 190px) clamp(20px, 4vw, 56px) 0;">
<div style="max-width: 1320px; margin: 0 auto; width: 100%; display: flex; flex-direction: column; flex: 1;">
<!-- spacer -->
<div style="flex: 1; min-height: 40px;"></div>
<!-- headline block -->
<div style="max-width: 720px; margin: 0 auto; text-align: center; animation: lw-fadein .7s ease both;">
<h1 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; line-height: 1.08; letter-spacing: -0.005em; color: #f5f4f0; font-size: clamp(36px, 4.8vw, 64px); margin-bottom: 22px;">
<span style="display: block;">Rein mit
<span ref="{{ wordSlotRef }}" style="display: inline-block; position: relative; overflow: hidden; vertical-align: bottom; text-align: left;">
<span ref="{{ wordRef }}" style="display: inline-block; color: var(--accent, #F0912F); font-style: italic; will-change: transform, opacity;">Kratzer</span>
</span>
</span>
<span style="display: block;">Raus wie neu.</span>
</h1>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.5; color: #c5c9ce; max-width: 560px; margin: 0 auto; font-weight: 500;">
Wir reparieren alles! Mit Originalteilen und neuester Technik zu fairen Preisen. Als wäre nichts passiert.
</p>
</div>
<!-- spacer -->
<div style="flex: 1; min-height: 40px;"></div>
<!-- BENEFIT STRIP -->
<div class="lw-benefits" style="display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(18px, 3vw, 48px); padding: 28px 0 46px;">
<div style="display: flex; flex-direction: column; justify-content: flex-end; gap: 12px;">
<p style="font-size: 15.5px; line-height: 1.4; color: #e7e9ec; font-weight: 600;">Fahrzeug-Reparatur wie in der Vertragswerkstatt — nur günstiger</p>
</div>
<div style="display: flex; flex-direction: column; justify-content: flex-end; gap: 12px;">
<img src="assets/benefit01.svg" alt="" width="22" height="27" style="opacity: .95;">
<p style="font-size: 15.5px; line-height: 1.4; color: #e7e9ec; font-weight: 600;">Wir nutzen Premium-Lacke</p>
</div>
<div style="display: flex; flex-direction: column; justify-content: flex-end; gap: 12px;">
<img src="assets/benefit02.svg" alt="" width="30" height="24" style="opacity: .95;">
<p style="font-size: 15.5px; line-height: 1.4; color: #e7e9ec; font-weight: 600;">Wir verbauen nur Originalteile</p>
</div>
<div style="display: flex; flex-direction: column; gap: 14px;">
<!-- Google badge -->
<a href="{{ googleUrl }}" target="_blank" rel="noopener" style="display: inline-flex; flex-direction: column; gap: 3px; align-self: flex-start; background: #000; border: 1px solid rgba(255,255,255,.12); border-radius: 44px; padding: 11px 20px; transition: transform .3s ease, box-shadow .3s ease;" style-hover="transform: scale(1.05); box-shadow: 0 6px 20px rgba(0,0,0,.4);">
<span style="color: #fff; font-weight: 700; font-size: 15px; letter-spacing: .01em;">Karosserie und Lack Stahl</span>
<span style="display: inline-flex; align-items: center; gap: 7px;">
<span style="color: #DBDED9; font-weight: 600; font-size: 15px;">{{ ratingLabel }}</span>
<img src="assets/review.svg" alt="Bewertung" width="66" height="10">
<span style="color: #DBDED9; font-weight: 300; font-size: 15px;">{{ countLabel }}</span>
</span>
</a>
<img src="assets/benefit03.svg" alt="" width="20" height="30" style="opacity: .95;">
<p style="font-size: 15.5px; line-height: 1.4; color: #e7e9ec; font-weight: 600;">Wir arbeiten mit der gleichen Genauigkeit</p>
</div>
</div>
</div>
</div>
</div>
<!-- LEISTUNGEN SECTION -->
<section id="services" data-screen-label="Leistungen" style="position: relative; overflow: hidden; background: #0D2A46; padding: clamp(80px, 12vh, 140px) clamp(20px, 4vw, 56px);">
<svg viewBox="0 0 1440 900" preserveAspectRatio="xMidYMid slice" aria-hidden="true" style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;">
<path d="M-100,780 C300,620 500,930 900,760 C1180,640 1350,700 1540,560" fill="none" stroke="#164a7d" stroke-width="150" stroke-linecap="round" opacity="0.75"></path>
<path d="M-120,320 C260,480 620,120 980,300 C1240,430 1380,320 1560,400" fill="none" stroke="#123a63" stroke-width="190" stroke-linecap="round" opacity="0.8"></path>
<path d="M-80,90 C380,220 760,-40 1120,120 C1330,215 1450,140 1560,190" fill="none" stroke="#1d5c99" stroke-width="110" stroke-linecap="round" opacity="0.55"></path>
<path d="M-100,560 C340,420 700,660 1080,500 C1300,410 1420,470 1560,410" fill="none" stroke="#0f3154" stroke-width="230" stroke-linecap="round" opacity="0.9"></path>
</svg>
<div style="position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13,42,70,.45) 0%, rgba(13,42,70,.10) 40%, rgba(13,42,70,.45) 100%); pointer-events: none;"></div>
<div style="position: relative; max-width: 1320px; margin: 0 auto;">
<div style="max-width: 760px; margin-bottom: clamp(40px, 6vh, 64px);">
<span style="display: inline-block; font-size: 13px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: #9FD1F5; margin-bottom: 16px;">Leistungen</span>
<h2 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; line-height: 1.1; color: #f5f4f0; font-size: clamp(30px, 3.6vw, 52px); margin-bottom: 18px;">Alles rund um den Lack aus einer Hand</h2>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.55; color: #c9d6e2; font-weight: 500;">Ob Neuwagen, Alltagsauto oder Klassiker: Wir bringen jede Oberfläche zurück in Bestform. Präzise vorbereitet, sauber lackiert, perfekt finiert.</p>
</div>
<div class="lw-services" style="display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(18px, 2.4vw, 30px);">
<div style="background: #F1F0EB; border-radius: 24px; padding: 34px 30px; display: flex; flex-direction: column; gap: 12px; box-shadow: 2px 4px 14px rgba(0,0,0,.25);">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: 23px; color: #0D2A46;">Lackierungen aller Art</h3>
<p style="font-size: 15.5px; line-height: 1.55; color: #45535f; font-weight: 500; flex: 1;">Vom Kotflügel bis zur Komplettlackierung markenunabhängig, farbtongenau und in dauerhafter Qualität.</p>
<span style="font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #1e7fc2;">Uni · Metallic · Perleffekt</span>
</div>
<div style="background: #F1F0EB; border-radius: 24px; padding: 34px 30px; display: flex; flex-direction: column; gap: 12px; box-shadow: 2px 4px 14px rgba(0,0,0,.25);">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: 23px; color: #0D2A46;">Smart Repair</h3>
<p style="font-size: 15.5px; line-height: 1.55; color: #45535f; font-weight: 500; flex: 1;">Kleine Kratzer, Steinschläge und Parkdellen punktgenau beseitigt schnell, günstig und ohne sichtbaren Übergang.</p>
<span style="font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #1e7fc2;">Spot-Repair · Same Day</span>
</div>
<div style="background: #F1F0EB; border-radius: 24px; padding: 34px 30px; display: flex; flex-direction: column; gap: 12px; box-shadow: 2px 4px 14px rgba(0,0,0,.25);">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: 23px; color: #0D2A46;">Oldtimer &amp; Klassiker</h3>
<p style="font-size: 15.5px; line-height: 1.55; color: #45535f; font-weight: 500; flex: 1;">Restaurierung mit Fingerspitzengefühl: originalgetreue Farbtöne und ein Finish, das dem Wert Ihres Fahrzeugs gerecht wird.</p>
<span style="font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #1e7fc2;">Restauration · Karosserie</span>
</div>
<div style="background: #F1F0EB; border-radius: 24px; padding: 34px 30px; display: flex; flex-direction: column; gap: 12px; box-shadow: 2px 4px 14px rgba(0,0,0,.25);">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: 23px; color: #0D2A46;">Lackaufbereitung &amp; Politur</h3>
<p style="font-size: 15.5px; line-height: 1.55; color: #45535f; font-weight: 500; flex: 1;">Professionelles Polieren, Versiegeln und Aufbereiten für tiefen Glanz und langanhaltenden Schutz Ihres Lacks.</p>
<span style="font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #1e7fc2;">Politur · Versiegelung</span>
</div>
<div style="background: #F1F0EB; border-radius: 24px; padding: 34px 30px; display: flex; flex-direction: column; gap: 12px; box-shadow: 2px 4px 14px rgba(0,0,0,.25);">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: 23px; color: #0D2A46;">Felgen &amp; Motorrad</h3>
<p style="font-size: 15.5px; line-height: 1.55; color: #45535f; font-weight: 500; flex: 1;">Felgenaufbereitung und Motorradlackierung im gleichen hohen Standard für den perfekten Auftritt bis ins Detail.</p>
<span style="font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #1e7fc2;">Felgen · Zweirad</span>
</div>
<!-- LEISTUNGS-VIDEO — bewusst beibehalten (assets/leistungen-video.mp4) -->
<div style="position: relative; border-radius: 24px; overflow: hidden; box-shadow: 2px 4px 14px rgba(0,0,0,.25);">
<video ref="{{ videoRef }}" src="assets/leistungen-video.mp4" autoplay muted loop playsinline style="position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;"></video>
<div style="position: absolute; inset: 0; background: linear-gradient(180deg, rgba(8,20,34,0) 45%, rgba(8,20,34,.78) 100%); pointer-events: none;"></div>
<div style="position: absolute; left: 30px; right: 30px; bottom: 26px; display: flex; flex-direction: column; gap: 8px;">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: 23px; color: #f5f4f0;">Design- &amp; Sonderlackierung</h3>
<p style="font-size: 14.5px; line-height: 1.5; color: #d8e2ec; font-weight: 500;">Individuelle Farbwünsche, Sondereffekte und Akzente wir setzen Ihre Ideen sauber und hochwertig um.</p>
<span style="font-size: 13px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #9FD1F5;">Custom · Effektlack</span>
</div>
</div>
</div>
</div>
</section>
<!-- REFERENZEN SECTION — Vorher/Nachher-Vergleich entfernt, durch Foto-Galerie ersetzt -->
<section id="referenzen" data-screen-label="Referenzen" style="position: relative; overflow: hidden; background: #0D2A46; padding: clamp(80px, 12vh, 140px) clamp(20px, 4vw, 56px);">
<img src="assets/bg-radkasten.jpg" alt="" style="position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: hue-rotate(85deg) saturate(1.2); pointer-events: none;">
<div style="position: absolute; inset: 0; background: rgba(18,60,120,0.38); mix-blend-mode: multiply; pointer-events: none;"></div>
<div style="position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,18,30,.8) 0%, rgba(10,18,30,.45) 45%, rgba(10,18,30,.8) 100%); pointer-events: none;"></div>
<div style="position: relative; max-width: 1320px; margin: 0 auto;">
<div style="max-width: 760px; margin-bottom: clamp(40px, 6vh, 64px);">
<span style="display: inline-block; font-size: 13px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: #9FD1F5; margin-bottom: 16px;">Referenzen</span>
<h2 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; line-height: 1.1; color: #f5f4f0; font-size: clamp(30px, 3.6vw, 52px); margin-bottom: 18px;">Echte Arbeiten aus unserer Werkstatt</h2>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.55; color: #c9d6e2; font-weight: 500;">Ein Auszug aus unseren Projekten. Ziehen Sie eigene Fotos (z.&nbsp;B. Vorher/Nachher) einfach per Drag &amp; Drop in die Platzhalter.</p>
</div>
<!-- Foto-Galerie — jeder Platzhalter ist per Drag & Drop mit einem eigenen Foto befüllbar -->
<div class="lw-refs" style="display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 240px; gap: clamp(14px, 1.8vw, 22px);">
<div class="lw-ref-wide" style="position: relative; grid-column: span 2; grid-row: span 2; border-radius: 24px; overflow: hidden; box-shadow: 2px 6px 24px rgba(0,0,0,.45); background: rgba(255,255,255,.05); border: 1.5px dashed rgba(255,255,255,.3);">
<x-import component-from-global-scope="image-slot" from="./assets/image-slot.js" id="ref-1" shape="rect" fit="cover" placeholder="Projektfoto 1 hier ablegen" hint-size="100%,100%" style="display:block;width:100%;height:100%;"></x-import>
</div>
<div style="position: relative; border-radius: 24px; overflow: hidden; box-shadow: 2px 6px 24px rgba(0,0,0,.45); background: rgba(255,255,255,.05); border: 1.5px dashed rgba(255,255,255,.3);">
<x-import component-from-global-scope="image-slot" from="./assets/image-slot.js" id="ref-2" shape="rect" fit="cover" placeholder="Foto 2" hint-size="100%,100%" style="display:block;width:100%;height:100%;"></x-import>
</div>
<div style="position: relative; border-radius: 24px; overflow: hidden; box-shadow: 2px 6px 24px rgba(0,0,0,.45); background: rgba(255,255,255,.05); border: 1.5px dashed rgba(255,255,255,.3);">
<x-import component-from-global-scope="image-slot" from="./assets/image-slot.js" id="ref-3" shape="rect" fit="cover" placeholder="Foto 3" hint-size="100%,100%" style="display:block;width:100%;height:100%;"></x-import>
</div>
<div style="position: relative; border-radius: 24px; overflow: hidden; box-shadow: 2px 6px 24px rgba(0,0,0,.45); background: rgba(255,255,255,.05); border: 1.5px dashed rgba(255,255,255,.3);">
<x-import component-from-global-scope="image-slot" from="./assets/image-slot.js" id="ref-4" shape="rect" fit="cover" placeholder="Foto 4" hint-size="100%,100%" style="display:block;width:100%;height:100%;"></x-import>
</div>
<div style="position: relative; border-radius: 24px; overflow: hidden; box-shadow: 2px 6px 24px rgba(0,0,0,.45); background: rgba(255,255,255,.05); border: 1.5px dashed rgba(255,255,255,.3);">
<x-import component-from-global-scope="image-slot" from="./assets/image-slot.js" id="ref-5" shape="rect" fit="cover" placeholder="Foto 5" hint-size="100%,100%" style="display:block;width:100%;height:100%;"></x-import>
</div>
</div>
<p style="margin-top: clamp(28px, 4vh, 44px); text-align: center; font-size: 15px; color: #c9d6e2; font-weight: 500;">Mehr laufende Projekte gibt es auf unserer <a href="" target="_blank" rel="noopener" style="color: #9FD1F5; font-weight: 700;">Facebook-Seite</a>.</p>
</div>
</section>
<!-- ÜBER UNS SECTION -->
<section id="ueber-uns" data-screen-label="Über uns" style="position: relative; overflow: hidden; background: #0D2A46; padding: clamp(80px, 12vh, 140px) clamp(20px, 4vw, 56px);">
<svg viewBox="0 0 1440 900" preserveAspectRatio="xMidYMid slice" aria-hidden="true" style="position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none;">
<path d="M-100,120 C340,260 720,-20 1100,140 C1320,230 1450,160 1560,210" fill="none" stroke="#1d5c99" stroke-width="120" stroke-linecap="round" opacity="0.5"></path>
<path d="M-120,480 C280,340 640,620 1020,460 C1280,350 1400,420 1560,360" fill="none" stroke="#123a63" stroke-width="210" stroke-linecap="round" opacity="0.8"></path>
<path d="M-100,800 C320,660 560,940 960,780 C1220,670 1380,730 1560,610" fill="none" stroke="#164a7d" stroke-width="150" stroke-linecap="round" opacity="0.7"></path>
</svg>
<div style="position: absolute; inset: 0; background: linear-gradient(180deg, rgba(13,42,70,.45) 0%, rgba(13,42,70,.10) 40%, rgba(13,42,70,.45) 100%); pointer-events: none;"></div>
<div style="position: relative; max-width: 1320px; margin: 0 auto;">
<div style="max-width: 900px; margin-bottom: clamp(50px, 8vh, 90px);">
<span style="display: inline-block; font-size: 13px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: #9FD1F5; margin-bottom: 16px;">Über uns</span>
<h2 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; line-height: 1.12; color: #f5f4f0; font-size: clamp(32px, 4vw, 58px);">Wir kombinieren handwerkliches Wissen und viel Erfahrung mit modernster Technik.</h2>
</div>
<!-- Reihe 1: Vorstellung + Profilbild-Platzhalter -->
<div class="lw-about" style="display: grid; grid-template-columns: 1.1fr 0.9fr; gap: clamp(28px, 4vw, 64px); align-items: center; margin-bottom: clamp(50px, 8vh, 90px);">
<div style="display: flex; flex-direction: column; gap: 16px;">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: clamp(24px, 2.2vw, 32px); line-height: 1.2; color: #f5f4f0;">Hallo, ich bin<br>Herbert Stahl,</h3>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.6; color: #c9d6e2; font-weight: 500;">Lack- und Karosserie-Experte und Inhaber der Karosserie und Lack Stahl GmbH in Unterschleißheim.</p>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.6; color: #c9d6e2; font-weight: 500;">Mit meinem Werkstatt-Team aus professionellen Fachkräften erfülle ich Ihre individuellen Wünsche zum bestmöglichen Preis — von der Smart-Repair bis zur kompletten Restauration.</p>
</div>
<div style="justify-self: center; width: min(340px, 100%);">
<div style="position: relative; width: 100%; aspect-ratio: 4/5; border-radius: 24px; overflow: hidden; box-shadow: 2px 6px 24px rgba(0,0,0,.4); background: rgba(255,255,255,.05); border: 1.5px dashed rgba(255,255,255,.3);">
<x-import component-from-global-scope="image-slot" from="./assets/image-slot.js" id="profil-inhaber" shape="rect" fit="cover" placeholder="Profilbild der Inhaberin / des Inhabers hier ablegen" hint-size="100%,100%" style="display:block;width:100%;height:100%;"></x-import>
</div>
</div>
</div>
<!-- Reihe 2: Kundenstimmen + Philosophie -->
<div class="lw-about" style="display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(28px, 4vw, 64px); align-items: center;">
<div style="position: relative; border-radius: 24px; padding: 28px; background: rgba(10,20,34,.55); border: 1px solid rgba(255,255,255,.12); backdrop-filter: blur(10px); box-shadow: 2px 6px 24px rgba(0,0,0,.35);">
<div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
<span style="display: inline-flex; align-items: center; justify-content: center; width: 42px; height: 42px; border-radius: 50%; background: var(--accent, #2FA4F0); color: #0d0f12; font-weight: 800; font-size: 17px; flex-shrink: 0;">{{ reviewInitial }}</span>
<div style="display: flex; flex-direction: column; gap: 3px; min-width: 0;">
<span style="color: #f4f3ef; font-weight: 700; font-size: 15px;">{{ reviewAuthor }}</span>
<span style="color: #F2BD3F; font-size: 14px; letter-spacing: 2px; line-height: 1;">★★★★★</span>
</div>
</div>
<p ref="{{ reviewTextRef }}" style="color: #cdd6e0; font-size: 15px; line-height: 1.6; font-weight: 500; transition: opacity .4s ease;">{{ reviewText }}</p>
<span style="display: block; margin-top: 14px; padding-top: 12px; border-top: 1px solid rgba(255,255,255,.1); color: #8b9cae; font-size: 12.5px; font-weight: 600;">{{ reviewMeta }}</span>
</div>
<div style="display: flex; flex-direction: column; gap: 16px;">
<h3 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; font-size: clamp(24px, 2.2vw, 32px); line-height: 1.2; color: #f5f4f0;">Meine Philosophie</h3>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.6; color: #c9d6e2; font-weight: 500;">Für Sie meine Kunden soll meisterhafte Arbeit bezahlbar sein. Unser Service sieht aus wie aus der Vertragswerkstatt, hat die gleiche Qualität, ist aber deutlich günstiger.</p>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.6; color: #c9d6e2; font-weight: 500;">Es ist für mich oberstes Gesetz, dass Sie nur 1A-Qualität bekommen, statt billiger „Pinselarbeiten". Mit hastig erledigten, minderwertigen Flickarbeiten kann ich nicht dienen.</p>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.6; color: #c9d6e2; font-weight: 500;">Mein Credo: Glückliche Kunden kommen wieder. Mein Team und ich sind unheimlich stolz auf Ihre Zufriedenheit und begeisterten Bewertungen.</p>
</div>
</div>
</div>
</section>
<!-- KONTAKT SECTION -->
<section id="kontakt" data-screen-label="Kontakt &amp; Anfahrt" style="position: relative; overflow: hidden; background: #10151b; padding: clamp(80px, 12vh, 140px) clamp(20px, 4vw, 56px);">
<img src="assets/bg-vorderlicht.jpg" alt="" style="position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; filter: hue-rotate(85deg) saturate(1.2); pointer-events: none;">
<div style="position: absolute; inset: 0; background: rgba(18,60,120,0.38); mix-blend-mode: multiply; pointer-events: none;"></div>
<div style="position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,18,30,.88) 0%, rgba(10,18,30,.55) 45%, rgba(10,18,30,.88) 100%); pointer-events: none;"></div>
<div style="position: relative; max-width: 1320px; margin: 0 auto;">
<div style="max-width: 760px; margin-bottom: clamp(40px, 6vh, 64px);">
<span style="display: inline-block; font-size: 13px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: #9FD1F5; margin-bottom: 16px;">Kontakt &amp; Anfahrt</span>
<h2 style="font-family: 'Source Serif 4', Georgia, serif; font-weight: 600; line-height: 1.1; color: #f5f4f0; font-size: clamp(30px, 3.6vw, 52px); margin-bottom: 18px;">Sprechen wir über Ihr Fahrzeug</h2>
<p style="font-size: clamp(15px, 1.3vw, 18px); line-height: 1.55; color: #c9d6e2; font-weight: 500;">Rufen Sie an, schreiben Sie uns oder kommen Sie direkt vorbei wir beraten Sie gern und unverbindlich.</p>
</div>
<div class="lw-contact" style="display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(24px, 3vw, 40px); align-items: stretch;">
<!-- Kontakt-Infos -->
<div style="display: flex; flex-direction: column; gap: 18px; border-radius: 24px; padding: clamp(26px, 3vw, 40px); background: rgba(10,20,34,.6); border: 1px solid rgba(255,255,255,.12); backdrop-filter: blur(10px); box-shadow: 2px 6px 24px rgba(0,0,0,.35);">
<div style="display: flex; flex-direction: column; gap: 4px;">
<span style="font-size: 12.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #9FD1F5;">Adresse</span>
<p style="font-size: 16px; line-height: 1.5; color: #e7ecf1; font-weight: 600;">Karosserie und Lack Stahl GmbH<br>Röntgenstraße 1, 85716 Unterschleißheim</p>
</div>
<div style="display: flex; flex-direction: column; gap: 4px;">
<span style="font-size: 12.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #9FD1F5;">Telefon</span>
<p style="font-size: 16px; line-height: 1.5; color: #e7ecf1; font-weight: 600;"><a href="tel:tel:+49893211798" style="color: #e7ecf1;">089 3211798</a><br><span style="font-weight: 500; color: #b8c4d0;">Fax: </span></p>
</div>
<div style="display: flex; flex-direction: column; gap: 4px;">
<span style="font-size: 12.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #9FD1F5;">E-Mail</span>
<p style="font-size: 16px; line-height: 1.5; font-weight: 600;"><a href="mailto:info@stahl-gmbh.net" style="color: #e7ecf1;">info@stahl-gmbh.net</a></p>
</div>
<div style="display: flex; flex-direction: column; gap: 4px;">
<span style="font-size: 12.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #9FD1F5;">Öffnungszeiten</span>
<p style="font-size: 16px; line-height: 1.6; color: #e7ecf1; font-weight: 600;">Mo-Fr<br><span style="font-weight: 500; color: #b8c4d0;">07:00-12:00 und 13:00-19:00</span><br>Sa<br><span style="font-weight: 500; color: #b8c4d0;">07:00-14:00</span></p>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px;">
<a href="tel:tel:+49893211798" style="display: inline-flex; align-items: center; gap: 8px; font-size: 14.5px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: #0d0f12; background: var(--accent, #2FA4F0); padding: 13px 22px; border-radius: 44px; transition: transform .2s ease, box-shadow .2s ease;" style-hover="transform: translateY(-2px); box-shadow: 0 10px 26px rgba(47,164,240,.4);">Jetzt anrufen</a>
<a href="mailto:info@stahl-gmbh.net" style="display: inline-flex; align-items: center; font-size: 14.5px; font-weight: 700; letter-spacing: .02em; text-transform: uppercase; color: #f4f3ef; padding: 13px 22px; border-radius: 44px; border: 1.5px solid rgba(255,255,255,.3); transition: border-color .2s ease, background .2s ease;" style-hover="border-color: var(--accent, #2FA4F0); background: rgba(255,255,255,.05);">E-Mail schreiben</a>
</div>
</div>
<!-- Karte -->
<div style="position: relative; border-radius: 24px; overflow: hidden; box-shadow: 2px 6px 24px rgba(0,0,0,.4); min-height: 420px; background: #0a0e13;">
<div ref="{{ mapRef }}" style="position: absolute; inset: 0;"></div>
</div>
</div>
</div>
</section>
<!-- FOOTER (sticky reveal) -->
<footer data-screen-label="Footer" style="position: relative; height: 70vh; clip-path: polygon(0% 0, 100% 0%, 100% 100%, 0 100%);">
<div style="position: relative; height: calc(100vh + 70vh); top: -100vh;">
<div style="height: 70vh; position: sticky; top: calc(100vh - 70vh);">
<div style="height: 100%; width: 100%; display: flex; flex-direction: column; justify-content: space-between; overflow: hidden; position: relative; background: linear-gradient(135deg, #0a1526 0%, #0D2A46 55%, #0a1526 100%); padding: clamp(32px, 6vh, 64px) clamp(20px, 4vw, 56px);">
<!-- Glow-Elemente -->
<div style="position: absolute; top: -120px; right: -120px; width: 380px; height: 380px; border-radius: 50%; background: rgba(47,164,240,.09); filter: blur(70px); pointer-events: none;"></div>
<div style="position: absolute; bottom: -140px; left: -100px; width: 380px; height: 380px; border-radius: 50%; background: rgba(29,92,153,.12); filter: blur(70px); pointer-events: none;"></div>
<!-- Link-Spalten -->
<div class="lw-footer-cols" style="position: relative; z-index: 1; display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(24px, 4vw, 80px); max-width: 1320px; width: 100%; margin: 0 auto;">
<div style="display: flex; flex-direction: column; gap: 9px;">
<h3 style="font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #7f97ac; border-bottom: 1px solid rgba(255,255,255,.12); padding-bottom: 7px; margin-bottom: 6px;">Navigation</h3>
<a href="#top" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Start</a>
<a href="#services" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Services</a>
<a href="#referenzen" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Referenzen</a>
<a href="#ueber-uns" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Über uns</a>
<a href="#kontakt" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Kontakt</a>
</div>
<div style="display: flex; flex-direction: column; gap: 9px;">
<h3 style="font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #7f97ac; border-bottom: 1px solid rgba(255,255,255,.12); padding-bottom: 7px; margin-bottom: 6px;">Leistungen</h3>
<a href="#services" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Lackierungen aller Art</a>
<a href="#services" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Smart Repair</a>
<a href="#services" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Oldtimer &amp; Klassiker</a>
<a href="#services" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Felgen &amp; Motorrad</a>
</div>
<div style="display: flex; flex-direction: column; gap: 9px;">
<h3 style="font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #7f97ac; border-bottom: 1px solid rgba(255,255,255,.12); padding-bottom: 7px; margin-bottom: 6px;">Kontakt</h3>
<span style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Röntgenstraße 1<br>85716 Unterschleißheim</span>
<a href="tel:tel:+49893211798" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">089 3211798</a>
<a href="mailto:info@stahl-gmbh.net" style="font-size: 14px; color: #c9d6e2; font-weight: 500;">info@stahl-gmbh.net</a>
</div>
<div style="display: flex; flex-direction: column; gap: 9px;">
<h3 style="font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: #7f97ac; border-bottom: 1px solid rgba(255,255,255,.12); padding-bottom: 7px; margin-bottom: 6px;">Öffnungszeiten</h3>
<span style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Mo-Fr<br>07:00-12:00 und 13:00-19:00</span>
<span style="font-size: 14px; color: #c9d6e2; font-weight: 500;">Sa · 07:00-14:00</span>
</div>
</div>
<!-- Untere Zeile -->
<div class="lw-footer-bottom" style="position: relative; z-index: 1; display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; max-width: 1320px; width: 100%; margin: 0 auto;">
<div style="min-width: 0;">
<img src="assets/logo-placeholder.svg" alt="Karosserie und Lack Stahl" style="width: min(46vw, 360px); height: auto; display: block; opacity: .95;">
<div style="display: flex; align-items: center; gap: 14px; margin-top: 16px;">
<span style="width: 44px; height: 2px; background: linear-gradient(90deg, #2FA4F0, transparent);"></span>
<span style="font-size: 13.5px; color: #8fa4b8; font-weight: 500;">Autolackiererei &amp; Karosserie · Unterschleißheim</span>
</div>
</div>
<div style="text-align: right; flex-shrink: 0;">
<p style="font-size: 13px; color: #8fa4b8; font-weight: 500; margin-bottom: 12px;">© 2026 Karosserie und Lack Stahl GmbH · Alle Rechte vorbehalten</p>
<div style="display: flex; justify-content: flex-end; align-items: center; gap: 14px;">
<a href="" target="_blank" rel="noopener" aria-label="Facebook" style="width: 36px; height: 36px; border-radius: 50%; background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.14); display: inline-flex; align-items: center; justify-content: center; color: #c9d6e2; font-weight: 800; font-size: 15px; transition: background .2s ease, transform .2s ease;" style-hover="background: var(--accent, #2FA4F0); color: #0a1526; transform: scale(1.1);">f</a>
<a href="#impressum" style="font-size: 13px; color: #8fa4b8; font-weight: 500;">Impressum</a>
<a href="#datenschutz" style="font-size: 13px; color: #8fa4b8; font-weight: 500;">Datenschutz</a>
</div>
</div>
</div>
</div>
</div>
</div>
</footer>
</div>
</x-dc>
<script type="text/x-dc" data-dc-script data-props="{&quot;$preview&quot;:{&quot;width&quot;:1440,&quot;height&quot;:900},&quot;accentColor&quot;:{&quot;editor&quot;:&quot;color&quot;,&quot;default&quot;:&quot;#2FA4F0&quot;,&quot;tsType&quot;:&quot;string&quot;,&quot;section&quot;:&quot;Design&quot;,&quot;options&quot;:[&quot;#2FA4F0&quot;,&quot;#F0912F&quot;,&quot;#E23744&quot;,&quot;#16462C&quot;,&quot;#C9A227&quot;]},&quot;showReviewCard&quot;:{&quot;editor&quot;:&quot;boolean&quot;,&quot;default&quot;:true,&quot;tsType&quot;:&quot;boolean&quot;,&quot;section&quot;:&quot;Inhalt&quot;},&quot;rotateWords&quot;:{&quot;editor&quot;:&quot;boolean&quot;,&quot;default&quot;:true,&quot;tsType&quot;:&quot;boolean&quot;,&quot;section&quot;:&quot;Inhalt&quot;}}">
class Component extends DCLogic {
state = {
loading: true,
reviews: [],
idx: 0,
// 4,1 / 46 — werden nur als Text angezeigt, dürfen daher Platzhalter bleiben
rating: "4,1",
count: "46",
};
// Demo-/Fallback-Bewertungen (angezeigt, wenn /api/reviews nicht erreichbar ist, z. B. in der Vorschau)
// Durch echte Beispiel-Bewertungen ersetzen ODER über das eigene /api/reviews-Backend live laden.
DEMO = {
rating: "4,1",
user_ratings_total: "46",
reviews: [
{ author_name: "Markus F.", rating: 5, text: "Unfallschaden schnell und sauber repariert, Leihwagen inklusive. Alles top organisiert." },
{ author_name: "Christine E.", rating: 5, text: "Freundliches Team, faire Abwicklung direkt mit der Versicherung. Sehr zufrieden." },
{ author_name: "Daniel W.", rating: 5, text: "Kompetente Karosserie- und Lackarbeit, Farbton einwandfrei getroffen." },
],
};
PLACE_ID = "";
WORDS = ["Unfall", "Delle", "Beule", "Kratzer"];
componentDidMount() {
this.applyAccent();
this.sizeWordSlot();
this.onResize = () => this.sizeWordSlot();
window.addEventListener("resize", this.onResize);
if (document.fonts && document.fonts.ready) document.fonts.ready.then(() => this.sizeWordSlot());
this.loadReviews();
if (this.props.rotateWords !== false) this.startWordRotator();
this.onScroll = () => this.updateNav();
window.addEventListener("scroll", this.onScroll, { passive: true });
this.updateNav();
this.initMap();
// Immer oben starten (kein Wiederherstellen der Scroll-Position)
if ("scrollRestoration" in history) history.scrollRestoration = "manual";
if (!location.hash) requestAnimationFrame(() => window.scrollTo(0, 0));
}
initMap() {
if (this._map || !this.mapEl) return;
if (!window.maplibregl) { setTimeout(() => this.initMap(), 250); return; }
// / — Koordinaten des eigenen Standorts eintragen.
// Vorbelegt mit der geografischen Mitte Deutschlands, damit die Karte auch ohne Eintrag funktioniert.
const LNG = 10.4515, LAT = 51.1657;
const map = new maplibregl.Map({
container: this.mapEl,
style: "https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json",
center: [LNG, LAT],
zoom: 14.5,
attributionControl: { compact: true },
cooperativeGestures: true,
});
map.addControl(new maplibregl.NavigationControl({ showCompass: false }), "bottom-right");
const el = document.createElement("div");
el.style.cssText = "width:20px;height:20px;border-radius:50%;background:#2FA4F0;border:3px solid #fff;box-shadow:0 0 0 6px rgba(47,164,240,.3),0 4px 12px rgba(0,0,0,.5);cursor:pointer;";
const popupHtml =
'<div style="font-family:Archivo,sans-serif;padding:4px 2px;min-width:190px;">' +
'<div style="font-weight:800;font-size:14px;color:#0D2A46;margin-bottom:3px;">Karosserie und Lack Stahl GmbH</div>' +
'<div style="font-size:12.5px;color:#45535f;line-height:1.45;margin-bottom:8px;">Röntgenstraße 1<br>85716 Unterschleißheim</div>' +
'<a href="https://www.google.com/maps/dir/?api=1&destination=Röntgenstraße 1, 85716 Unterschleißheim" target="_blank" rel="noopener" style="display:inline-block;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:#fff;background:#2FA4F0;padding:7px 13px;border-radius:20px;text-decoration:none;">Route planen</a>' +
"</div>";
const popup = new maplibregl.Popup({ offset: 20, closeButton: false }).setHTML(popupHtml);
new maplibregl.Marker({ element: el }).setLngLat([LNG, LAT]).setPopup(popup).addTo(map);
popup.setLngLat([LNG, LAT]).addTo(map);
this._map = map;
}
componentDidUpdate() { this.applyAccent(); }
componentWillUnmount() {
clearInterval(this._wordTimer);
clearInterval(this._revTimer);
if (this._map) { this._map.remove(); this._map = null; }
window.removeEventListener("scroll", this.onScroll);
window.removeEventListener("resize", this.onResize);
}
// fix the rotating-word slot to the widest word so "Rein mit" never shifts
sizeWordSlot() {
const slot = this.wordSlot, word = this.word;
if (!slot || !word) return;
const probe = document.createElement("span");
probe.style.cssText = "position:absolute;visibility:hidden;white-space:nowrap;";
const cs = getComputedStyle(word);
probe.style.font = cs.font;
probe.style.fontStyle = cs.fontStyle;
probe.style.letterSpacing = cs.letterSpacing;
document.body.appendChild(probe);
let max = 0;
for (const w of this.WORDS) { probe.textContent = w; max = Math.max(max, probe.getBoundingClientRect().width); }
probe.remove();
slot.style.width = Math.ceil(max + 2) + "px";
}
applyAccent() {
if (this.root) this.root.style.setProperty("--accent", this.props.accentColor || "#F0912F");
}
updateNav() {
if (!this.nav) return;
const s = window.scrollY > 30;
this.nav.style.background = s ? "rgba(11,13,16,0.92)" : "transparent";
this.nav.style.backdropFilter = s ? "blur(14px)" : "none";
this.nav.style.borderBottomColor = s ? "rgba(255,255,255,0.10)" : "transparent";
this.nav.style.paddingTop = s ? "14px" : "22px";
this.nav.style.paddingBottom = s ? "14px" : "22px";
}
async loadReviews() {
let data = null;
try {
// In der produktiven Next.js-App trifft das den Server-Route-Handler
// /api/reviews (Place ID + GOOGLE_PLACES_API_KEY bleiben server-seitig).
const res = await fetch("/api/reviews", { cache: "no-store" });
if (res.ok) {
const j = await res.json();
if (j && Array.isArray(j.reviews) && j.reviews.length) data = j;
}
} catch (e) { /* fall through to demo */ }
if (!data) data = this.DEMO;
const reviews = (data.reviews || []).filter(r => r && r.text).slice(0, 5);
this.setState({
loading: false,
reviews,
rating: data.rating || this.DEMO.rating,
count: data.user_ratings_total || this.DEMO.user_ratings_total,
}, () => { if (reviews.length > 1) this.startReviewRotator(); });
}
startReviewRotator() {
this._revTimer = setInterval(() => {
const el = this.reviewText;
const next = (this.state.idx + 1) % this.state.reviews.length;
const swap = () => this.setState({ idx: next }, () => { if (this.reviewText) this.reviewText.style.opacity = 1; });
if (el) { el.style.opacity = 0; setTimeout(swap, 380); } else { swap(); }
}, 5200);
}
startWordRotator() {
let i = this.WORDS.indexOf("Kratzer");
this._wordTimer = setInterval(() => {
const el = this.word;
if (!el) return;
i = (i + 1) % this.WORDS.length;
const next = this.WORDS[i];
el.animate(
[{ transform: "translateY(0)", opacity: 1 }, { transform: "translateY(-110%)", opacity: 0 }],
{ duration: 300, easing: "cubic-bezier(.6,0,.4,1)", fill: "forwards" }
).onfinish = () => {
el.textContent = next;
el.animate(
[{ transform: "translateY(110%)", opacity: 0 }, { transform: "translateY(0)", opacity: 1 }],
{ duration: 340, easing: "cubic-bezier(.2,.7,.3,1)", fill: "forwards" }
);
};
}, 2400);
}
renderVals() {
const st = this.state;
const r = st.reviews[st.idx] || null;
const author = r ? r.author_name : "";
const initial = author ? author.trim().charAt(0).toUpperCase() : "";
const ratingLabel = String(st.rating).replace(".", ",");
return {
rootRef: (el) => { this.root = el; },
videoRef: (el) => { if (el) { el.muted = true; el.volume = 0; } },
mapRef: (el) => { this.mapEl = el; if (el) this.initMap(); },
navRef: (el) => { this.nav = el; },
wordRef: (el) => { this.word = el; },
wordSlotRef: (el) => { this.wordSlot = el; },
reviewTextRef: (el) => { this.reviewText = el; },
dot0Ref: () => {}, dot1Ref: () => {}, dot2Ref: () => {},
showReviewCard: this.props.showReviewCard !== false,
loading: st.loading,
hasReview: !st.loading && !!r,
reviewAuthor: author,
reviewInitial: initial,
reviewText: r ? ("“" + r.text + "”") : "",
reviewMeta: "Google Bewertung",
ratingLabel: ratingLabel,
countLabel: "(" + st.count + ")",
googleUrl: "https://www.google.com/maps/place/?q=place_id:" + this.PLACE_ID,
};
}
}
</script>
</body>
</html>