Kennzahlen als Glas-Karten über einem ruhenden Akzent-Glow. Die Ziffern zählen beim Sichtbarwerden per IntersectionObserver hoch, dezente Icons je Wert. Bei prefers-reduced-motion erscheint sofort der Endwert und der Glow ruht — keine Zählanimation.
<section class="zc-craft" aria-label="Zahlen und Erfolge">
<div class="zc-craft-glow" aria-hidden="true"></div>
<div class="zc-craft-head">
<p class="zc-craft-eyebrow">Unsere Bilanz</p>
<h2 class="zc-craft-title">Zahlen, die für sich <span>sprechen</span>.</h2>
</div>
<ul class="zc-craft-grid">
<li class="zc-craft-card">
<span class="zc-craft-ic" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>
</span>
<span class="zc-craft-num" data-count="16">0</span>
<span class="zc-craft-label">Jahre Erfahrung</span>
</li>
<li class="zc-craft-card">
<span class="zc-craft-ic" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M4 12h16M4 17h10"/></svg>
</span>
<span class="zc-craft-num" data-count="1200" data-suffix="+" data-group="1">0</span>
<span class="zc-craft-label">Projekte</span>
</li>
<li class="zc-craft-card">
<span class="zc-craft-ic" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3.5l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 17l-5.2 2.6 1-5.8-4.3-4.1 5.9-.9z"/></svg>
</span>
<span class="zc-craft-num" data-count="4.9" data-decimals="1" data-suffix=" ★">0</span>
<span class="zc-craft-label">Bewertung</span>
</li>
<li class="zc-craft-card">
<span class="zc-craft-ic" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>
</span>
<span class="zc-craft-num" data-count="98" data-suffix="%">0</span>
<span class="zc-craft-label">Weiterempfehlung</span>
</li>
</ul>
</section>
<style>
.zc-craft{position:relative;width:100%;overflow:hidden;isolation:isolate;
background:radial-gradient(130% 130% at 15% 0%,#1c1c28 0%,#141319 55%,#101014 100%);
border:1px solid #26262c;border-radius:20px;padding:2rem 1.5rem;color:#e9e9ee}
@media(min-width:720px){.zc-craft{padding:2.8rem 2.6rem}}
.zc-craft-glow{position:absolute;width:340px;height:340px;top:-120px;left:50%;margin-left:-170px;
border-radius:50%;z-index:-1;filter:blur(70px);opacity:.4;
background:radial-gradient(circle,var(--akzent,#7c87ff) 0%,transparent 70%);
animation:zc-pulse 9s ease-in-out infinite alternate;will-change:transform,opacity}
@keyframes zc-pulse{0%{transform:scale(.9);opacity:.32}100%{transform:scale(1.15);opacity:.5}}
.zc-craft-head{margin:0 0 1.8rem;text-align:center}
.zc-craft-eyebrow{margin:0 0 .6rem;display:inline-flex;align-items:center;gap:.6em;font-size:.74rem;
font-weight:600;letter-spacing:.16em;text-transform:uppercase;color:var(--akzent,#7c87ff)}
.zc-craft-eyebrow::before,.zc-craft-eyebrow::after{content:"";width:26px;height:1px;
background:linear-gradient(90deg,transparent,var(--akzent,#7c87ff))}
.zc-craft-eyebrow::after{background:linear-gradient(90deg,var(--akzent,#7c87ff),transparent)}
.zc-craft-title{margin:0;font-size:clamp(1.5rem,3.6vw,2.1rem);line-height:1.15;
letter-spacing:-.02em;color:#f4f4f5;overflow-wrap:break-word}
.zc-craft-title span{color:var(--akzent,#7c87ff)}
.zc-craft-grid{list-style:none;margin:0;padding:0;display:grid;gap:1rem;grid-template-columns:1fr}
@media(min-width:560px){.zc-craft-grid{grid-template-columns:repeat(2,1fr)}}
@media(min-width:880px){.zc-craft-grid{grid-template-columns:repeat(4,1fr)}}
.zc-craft-card{position:relative;display:flex;flex-direction:column;align-items:center;gap:.5rem;
padding:1.5rem 1rem 1.35rem;border-radius:16px;text-align:center;
background:rgba(255,255,255,.035);border:1px solid rgba(255,255,255,.09);
-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
box-shadow:inset 0 1px 0 rgba(255,255,255,.06);
transition:transform .3s cubic-bezier(.2,.7,.2,1),border-color .3s ease,box-shadow .3s ease}
.zc-craft-card:hover{transform:translateY(-4px);border-color:rgba(124,135,255,.4);
box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 18px 40px rgba(0,0,0,.4),0 0 0 1px rgba(124,135,255,.15)}
.zc-craft-ic{width:34px;height:34px;display:grid;place-items:center;border-radius:10px;
color:var(--akzent,#7c87ff);background:rgba(124,135,255,.12);border:1px solid rgba(124,135,255,.28)}
.zc-craft-ic svg{width:19px;height:19px}
.zc-craft-num{font-size:clamp(1.9rem,5vw,2.5rem);font-weight:800;line-height:1;letter-spacing:-.02em;
color:#f4f4f5;font-variant-numeric:tabular-nums}
.zc-craft-num i{font-style:normal;color:var(--akzent,#7c87ff)}
.zc-craft-label{font-size:.8rem;color:#a1a1aa;line-height:1.35;max-width:16ch}
@media (prefers-reduced-motion:reduce){.zc-craft-glow{animation:none}.zc-craft-card{transition:none}}
</style>
<script>
(function(){
var reduce = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
// Zahl mit Tausenderpunkt + optionalen Nachkommastellen formatieren
function fmt(val, decimals, group){
var s = decimals ? val.toFixed(decimals).replace(".", ",") : String(Math.round(val));
if(group){
var parts = s.split(",");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
s = parts.join(",");
}
return s;
}
function run(el){
var end = parseFloat(el.getAttribute("data-count")) || 0;
var decimals = parseInt(el.getAttribute("data-decimals") || "0", 10);
var group = el.getAttribute("data-group") === "1";
var suffix = el.getAttribute("data-suffix") || "";
if(reduce){ el.textContent = fmt(end, decimals, group) + suffix; return; }
var dur = 1400, t0 = null;
function step(ts){
if(t0 === null) t0 = ts;
var p = Math.min((ts - t0) / dur, 1);
var eased = 1 - Math.pow(1 - p, 3); // easeOutCubic
el.textContent = fmt(end * eased, decimals, group) + suffix;
if(p < 1) requestAnimationFrame(step);
else el.textContent = fmt(end, decimals, group) + suffix;
}
requestAnimationFrame(step);
}
var nums = document.querySelectorAll(".zc-craft-num[data-count]");
if(!("IntersectionObserver" in window)){ nums.forEach(run); return; }
var io = new IntersectionObserver(function(entries){
entries.forEach(function(e){
if(e.isIntersecting){ run(e.target); io.unobserve(e.target); }
});
}, { threshold: 0.4 });
nums.forEach(function(n){ io.observe(n); });
})();
</script>