AMPERION_Webpage/layouts/_default/leistung.html
2025-08-12 19:57:23 +02:00

425 lines
18 KiB
HTML
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.

{{ define "main" }}
{{ partial "page-title.html" . }}
{{/* ==== BILDER SAMMELN (Front-Matter oder Auto-Discovery) ==== */}}
{{ $photos := .Params.images }}
{{ if not $photos }}
{{ $slug := .Params.slug | default .File.TranslationBaseName }}
{{ $cands := slice
(printf "static/images/leistungen/%s1.webp" $slug)
(printf "static/images/leistungen/%s2.webp" $slug)
}}
{{ $auto := slice }}
{{ range $cands }}
{{ if fileExists . }}
{{ $auto = $auto | append (dict "src" (replace . "static" "") "alt" $slug ) }}
{{ end }}
{{ end }}
{{ $photos = $auto }}
{{ end }}
{{/* Erstes Bild für Hero, zweites fürs Ergebnis vormerken */}}
{{ $heroPhoto := cond (gt (len $photos) 0) (index $photos 0) nil }}
{{ $ergebnisPhoto := cond (gt (len $photos) 1) (index $photos 1) nil }}
{{ $.Scratch.Set "ergebnisPhoto" $ergebnisPhoto }}
<!-- ===== Inline-Styles ===== -->
<style>
.container-wide{width:100%;margin-left:auto;margin-right:auto;padding-left:16px;padding-right:16px}
@media (min-width:1200px){.container-wide{max-width:1280px}}
@media (min-width:1400px){.container-wide{max-width:1360px}}
@media (min-width:1600px){.container-wide{max-width:1440px}}
.service-hero__media{border-radius:12px;overflow:hidden;box-shadow:0 6px 30px rgba(0,0,0,.06)}
.service-hero__media img{display:block;width:100%;height:auto}
.service-hero__text p{margin-bottom:1rem}
/* USP inline unter dem Text Icons oben, #F5A623 */
.usp-inline{display:grid;grid-template-columns:1fr;gap:12px;margin-top:20px}
@media (min-width:992px){.usp-inline{grid-template-columns:repeat(3,1fr)}}
.usp-item{
display:flex; flex-direction:column;
align-items:center; /* vorher: flex-start */
text-align:center; /* Text mittig */
gap:8px; padding:12px 14px; border-radius:12px;
background:#fff; box-shadow:0 2px 12px rgba(0,0,0,.05);
}
.usp-icon{
color:#F5A623; background:rgba(245,166,35,.12);
width:44px; height:44px; border-radius:12px;
display:flex; align-items:center; justify-content:center;
margin:0 auto 8px; /* zentriert die Iconbox */
}
.usp-icon svg{display:block;width:24px;height:24px}
.usp-text{font-weight:500;margin:0}
</style>
<!-- =========================
HERO: Bild links, Intro rechts (breit)
========================= -->
<section class="service-hero section" style="margin-top:-24px; padding-top:16px;">
<div class="container-wide">
<div class="row align-items-center gx-5">
<!-- Bild links -->
<div class="col-lg-6 order-1 order-lg-1" data-reveal>
{{ with $heroPhoto }}
<figure class="service-hero__media">
<img src='{{ .src | default . | relURL }}'
alt='{{ .alt | default $.Title }}'
width="1200" height="800"
loading="eager" decoding="async" class="img-fluid">
</figure>
{{ end }}
</div>
<!-- Intro-Text rechts + USP darunter -->
<div class="col-lg-6 order-2 order-lg-2" data-reveal>
{{ if .Content }}
<div class="service-hero__text">
{{ .Content }}
{{ with .Params.usp }}
<div class="usp-inline" role="list">
{{ range $i, $u := . }}
<div class="usp-item" role="listitem">
<div class="usp-icon" aria-hidden="true">
{{ if eq (mod $i 3) 0 }}
<!-- Shield -->
<svg viewBox="0 0 24 24" role="img" focusable="false">
<path d="M12 3l7 3v6c0 4.97-3.58 9.43-7 10-3.42-.57-7-5.03-7-10V6l7-3z" fill="currentColor" opacity=".2"/>
<path d="M12 3l7 3v6c0 4.97-3.58 9.43-7 10-3.42-.57-7-5.03-7-10V6l7-3z" fill="none" stroke="currentColor" stroke-width="1.5"/>
</svg>
{{ else if eq (mod $i 3) 1 }}
<!-- Badge -->
<svg viewBox="0 0 24 24" role="img" focusable="false">
<circle cx="12" cy="9" r="5" fill="currentColor" opacity=".2"/>
<circle cx="12" cy="9" r="5" fill="none" stroke="currentColor" stroke-width="1.5"/>
<path d="M8 14l-2 7 6-3 6 3-2-7" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linejoin="round"/>
</svg>
{{ else }}
<!-- Target -->
<svg viewBox="0 0 24 24" role="img" focusable="false">
<circle cx="12" cy="12" r="9" fill="currentColor" opacity=".15"/>
<circle cx="12" cy="12" r="6" fill="none" stroke="currentColor" stroke-width="1.5"/>
<circle cx="12" cy="12" r="2" fill="currentColor"/>
</svg>
{{ end }}
</div>
<p class="usp-text">{{ $u }}</p>
</div>
{{ end }}
</div>
{{ end }}
</div>
{{ end }}
</div>
</div>
</div>
</section>
<!-- =========================
FEATURES (Icon-Left, keine Cards)
Quelle: .Params.features (array of {title, text, icon?})
========================= -->
{{ with .Params.features }}
<section class="service-ticker section" aria-label="Leistungen" style="background-color: #f8f9fa;">
<style>
.service-ticker{padding-top:24px;padding-bottom:24px}
.service-ticker h2{margin:0 0 12px 0}
.ticker-viewport{position:relative;overflow:hidden;background: #f8f9fa;}
.ticker-viewport:before,.ticker-viewport:after{
content:"";position:absolute;top:0;bottom:0;width:64px;pointer-events:none;z-index:2
}
.ticker-viewport:before{left:0;background:linear-gradient(to right,#fff 40%,rgba(255,255,255,0))}
.ticker-viewport:after{right:0;background:linear-gradient(to left,#fff 40%,rgba(255,255,255,0))}
.ticker-track{
display:flex;gap:24px;align-items:center;width:max-content;
animation:marquee var(--dur,30s) linear infinite;
}
.ticker-viewport:hover .ticker-track{animation-play-state:running}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){.ticker-track{animation:none}}
/* === Card-Ticks === */
.tick{
display:flex;align-items:center;gap:16px;
padding:14px 16px;border-radius:14px;background:#fff;
box-shadow:0 2px 14px rgba(0,0,0,.06);
flex:0 0 auto; /* nicht schrumpfen */
width:clamp(280px,36vw,420px); /* feste Kartenbreite für sauberes Scrolling */
}
.tick-icon{
color:#F5A623;background:rgba(245,166,35,.12);
width:44px;height:44px;border-radius:12px;
display:flex;align-items:center;justify-content:center;flex:0 0 44px
}
.tick-icon svg{width:22px;height:22px;display:block}
.tick-text{display:flex;flex-direction:column;gap:2px;white-space:normal}
.tick-title{font-weight:700;font-size:inherit;line-height:1.3;margin:0}
.tick-desc{margin:0;opacity:.88}
</style>
<div class="container-wide">
<h2 class data-reveal>Leistungen</h2>
</div>
<div class="ticker-viewport">
<div class="ticker-track" style="--dur: {{ mul (len .) 15 }}s">
{{ $list := . }}
{{/* ===== 1. Durchlauf ===== */}}
{{ range $i, $f := $list }}
<div class="tick">
<span class="tick-icon" aria-hidden="true">
{{ $icon := $f.icon | default (printf "i-%d" (mod $i 5)) }}
{{ if or (eq $icon "pv") (eq $icon "i-0") }}
<svg viewBox="0 0 24 24" role="img"><path d="M3 9h18v6H3z" fill="currentColor" opacity=".18"/><path d="M3 9h18v6H3M7 9v6M11 9v6M15 9v6M19 9v6" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ else if or (eq $icon "speicher") (eq $icon "i-1") }}
<svg viewBox="0 0 24 24" role="img"><rect x="3" y="7" width="16" height="10" rx="2" fill="none" stroke="currentColor" stroke-width="1.5"/><rect x="19" y="10" width="2" height="4" fill="currentColor"/></svg>
{{ else if or (eq $icon "lade") (eq $icon "i-2") }}
<svg viewBox="0 0 24 24" role="img"><path d="M9 7v4a4 4 0 0 0 4 4h2v4" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M14 3v4M10 3v4M17 7h2a2 2 0 0 1 2 2v2h-4" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ else if or (eq $icon "study") (eq $icon "i-3") }}
<svg viewBox="0 0 24 24" role="img"><path d="M4 18V6m4 12V9m4 9v-6m4 6v-8m4 8V8" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ else }}
<svg viewBox="0 0 24 24" role="img"><path d="M7 3h7l5 5v11a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" fill="currentColor" opacity=".14"/><path d="M14 3v6h6M9 14l2 2 4-4" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ end }}
</span>
<div class="tick-text">
<h3 class="tick-title">{{ $f.title }}</h3>
{{ with $f.text }}<p class="tick-desc">{{ . | $.Page.RenderString (dict "display" "inline") }}</p>{{ end }}
</div>
</div>
{{ end }}
{{/* ===== 2. Durchlauf (Duplikat) ===== */}}
{{ range $i, $f := $list }}
<div class="tick">
<span class="tick-icon" aria-hidden="true">
{{ $icon := $f.icon | default (printf "i-%d" (mod $i 5)) }}
{{ if or (eq $icon "pv") (eq $icon "i-0") }}
<svg viewBox="0 0 24 24" role="img"><path d="M3 9h18v6H3z" fill="currentColor" opacity=".18"/><path d="M3 9h18v6H3M7 9v6M11 9v6M15 9v6M19 9v6" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ else if or (eq $icon "speicher") (eq $icon "i-1") }}
<svg viewBox="0 0 24 24" role="img"><rect x="3" y="7" width="16" height="10" rx="2" fill="none" stroke="currentColor" stroke-width="1.5"/><rect x="19" y="10" width="2" height="4" fill="currentColor"/></svg>
{{ else if or (eq $icon "lade") (eq $icon "i-2") }}
<svg viewBox="0 0 24 24" role="img"><path d="M9 7v4a4 4 0 0 0 4 4h2v4" fill="none" stroke="currentColor" stroke-width="1.5"/><path d="M14 3v4M10 3v4M17 7h2a2 2 0 0 1 2 2v2h-4" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ else if or (eq $icon "study") (eq $icon "i-3") }}
<svg viewBox="0 0 24 24" role="img"><path d="M4 18V6m4 12V9m4 9v-6m4 6v-8m4 8V8" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ else }}
<svg viewBox="0 0 24 24" role="img"><path d="M7 3h7l5 5v11a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z" fill="currentColor" opacity=".14"/><path d="M14 3v6h6M9 14l2 2 4-4" fill="none" stroke="currentColor" stroke-width="1.5"/></svg>
{{ end }}
</span>
<div class="tick-text">
<h3 class="tick-title">{{ $f.title }}</h3>
{{ with $f.text }}<p class="tick-desc">{{ . | $.Page.RenderString (dict "display" "inline") }}</p>{{ end }}
</div>
</div>
{{ end }}
</div>
</div>
</section>
{{ end }}
<!-- =========================
OUTCOMES (Nutzen/Ergebnisse)
Quelle: .Params.outcomes (array of strings)
========================= -->
{{ with .Params.outcomes }}
<section class="service-outcomes section" aria-label="Ergebnis & Mehrwert">
<style>
.out-row{align-items:center}
.out-media{border-radius:12px;overflow:hidden;box-shadow:0 6px 30px rgba(0,0,0,.06)}
.out-media img{display:block;width:100%;height:auto}
.checklist{list-style:none;padding:0;margin:0;display:grid;gap:12px}
.checklist li{display:flex;gap:10px;align-items:flex-start}
.checklist .check{flex:0 0 22px;color:#0AA8A7;margin-top:2px}
</style>
<div class="container-wide" >
<div class="row out-row gx-5">
<!-- Text links -->
<div class="col-lg-6" data-reveal>
<h2 class="mb-3">Ergebnis & Mehrwert</h2>
<ul class="checklist">
{{ range . }}
<li data-reveal>
<svg class="check" viewBox="0 0 24 24" width="22" height="22" aria-hidden="true">
<path d="M20 6L9 17l-5-5" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
<span>{{ . }}</span>
</li>
{{ end }}
</ul>
</div>
<!-- Bild rechts (nimmt das 2. Bild aus dem Hero-Setup) -->
<div class="col-lg-6" data-reveal>
{{ $erg := $.Scratch.Get "ergebnisPhoto" }}
{{ with $erg }}
<figure class="out-media">
<img src='{{ .src | relURL }}' alt='{{ .alt | default $.Title }}'
width="1200" height="800" loading="lazy" decoding="async">
</figure>
{{ else }}
{{ with $heroPhoto }}
<figure class="out-media">
<img src='{{ .src | relURL }}' alt='{{ .alt | default $.Title }}'
width="1200" height="800" loading="lazy" decoding="async">
</figure>
{{ end }}
{{ end }}
</div>
</div>
</div>
</section>
{{ end }}
<!-- =========================
CTA (animierter Hintergrund wie auf Index),
aber: TEXT/Buttons aus Front-Matter binden.
========================= -->
{{ $impressum := site.GetPage "page" "impressum" }}
{{ $ctaEnabled := or (.Params.cta.enable) (or .Params.cta_text .Params.cta_label) }}
{{ if $ctaEnabled }}
<section id="cta" class="cta">
<!-- Animierter Hintergrund (DEIN bestehendes Markup) -->
<div class="cta__bg" aria-hidden="true">
<div class="cta__grid"></div>
<div class="cta__energy-lines">
<div class="energy-line-h energy-line-h1"></div>
<div class="energy-line-h energy-line-h2"></div>
<div class="energy-line-v energy-line-v1"></div>
<div class="energy-line-v energy-line-v2"></div>
<div class="energy-node energy-node1"></div>
<div class="energy-node energy-node2"></div>
</div>
<div class="cta__gradient-top"></div>
<div class="cta__gradient-bottom"></div>
</div>
<!-- Inhalt: jetzt dynamisch aus Front-Matter -->
<div class="my-container">
<div class="cta__wrap" data-reveal>
<h2 class="cta__title">
{{ .Params.cta_text | default "Lassen Sie uns Ihre Vision mit unserer Expertise zur Realität machen." }}
</h2>
{{/* Optional: Bei Bedarf zweite Zeile aus subtitle wiederverwenden */}}
{{ with .Params.subtitle }}
<p class="cta__lead">{{ . }}</p>
{{ end }}
<div class="cta__actions">
{{ with .Params.cta_label }}
<a class="cta__btn" href="{{ $.Params.cta_href | default "/contact/" }}">
<span aria-hidden="true"></span><span>{{ . }}</span>
</a>
{{ end }}
</div>
{{/* Fallback/Ergänzung: direkte Kontaktwege aus Impressum */}}
{{ if $impressum }}
<a class="cta__btn" href="mailto:{{ $impressum.Params.email }}">
<span aria-hidden="true">✉️</span><span>E-Mail senden</span>
</a>
<a class="cta__btn" href="tel:{{ $impressum.Params.telefon }}">
<span aria-hidden="true">📞</span><span>Anrufen</span>
</a>
{{ end }}
</div>
<div class="cta__social">
<a class="cta__social-link" href="https://www.instagram.com/amperion.at/" target="_blank" rel="noopener" aria-label="Instagram">
<img src="/images/social/instagram.svg" alt="">
</a>
<a class="cta__social-link" href="https://www.linkedin.com/company/amperion-gmbh/" target="_blank" rel="noopener" aria-label="LinkedIn">
<img src="/images/social/linkedin.svg" alt="">
</a>
<a class="cta__social-link" href="https://www.facebook.com/share/1CZ7xm6cdw/?mibextid=wwXIfr" target="_blank" rel="noopener" aria-label="Facebook">
<img src="/images/social/facebook.svg" alt="">
</a>
</div>
</div>
</div>
</section>
{{ end }}
<!-- =========================
Micro-Animationen (IntersectionObserver)
- fügt 'is-visible' hinzu, wenn Elemente ins Viewport kommen
========================= -->
<script>
(function(){
if (window.__serviceRevealInit) return; // vermeiden, dass mehrfach registriert wird
window.__serviceRevealInit = true;
var els = document.querySelectorAll("[data-reveal]");
if (!('IntersectionObserver' in window) || !els.length) {
els.forEach(function(el){ el.classList.add('is-visible'); });
return;
}
var io = new IntersectionObserver(function(entries){
entries.forEach(function(entry){
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
io.unobserve(entry.target);
}
});
}, { threshold: 0.12 });
els.forEach(function(el){ io.observe(el); });
})();
</script>
<!-- =========================
Minimal CSS-Hooks (optional, an deine SCSS anpassen)
========================= -->
<style>
/* Typo hooks */
.kicker{letter-spacing:.08em;text-transform:uppercase;opacity:.85;margin-bottom:.25rem}
.lead{opacity:.9}
/* Media items (icon-left) */
.media-item{display:flex;gap:.9rem;align-items:flex-start}
.media-item .media-icon{flex:0 0 auto;line-height:0;opacity:.9}
.media-item .media-body{flex:1}
/* Features grid spacing */
.service-features .feature{padding:14px 8px;border-radius:12px;transition:transform .25s ease, box-shadow .25s ease}
.service-features .feature:hover{transform:translateY(-2px);box-shadow:0 6px 24px rgba(0,0,0,.06)}
/* Outcomes checklist */
.checklist{list-style:none;padding:0;margin:0}
.checklist li{display:flex;gap:.6rem;align-items:flex-start;margin:.5rem 0}
.checklist .check{color:#F5A623; margin-top:.2rem}
/* Reveal animation */
[data-reveal]{opacity:0;transform:translateY(12px);transition:opacity .5s ease, transform .5s ease}
[data-reveal].is-visible{opacity:1;transform:none}
.service-photo{border-radius:12px;overflow:hidden}
.service-photo img{display:block;width:100%;height:auto}
.service-hero__media{border-radius:12px;overflow:hidden;box-shadow:0 6px 30px rgba(0,0,0,.06)}
.service-hero__media img{display:block;width:100%;height:auto}
.service-hero__text p{margin-bottom:1rem}
</style>
{{ end }}