first commit

This commit is contained in:
2026-09-30 16:19:00 -06:00
commit 43c1b29b02
177 changed files with 40567 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
{{/*
Stat tiles. Values that start with a number ("80%+", "100+", "30X") count
up from zero when the row scrolls into view; others show as written.
Without JS or with reduced motion, every value simply shows.
*/}}
{{ $s := . }}
{{ partial "sections/head.html" $s }}
<div class="stat-row">
{{ range $s.items }}
<div class="stat">
<span class="stat-value">{{ .value }}</span>
<span class="stat-label">{{ .label }}</span>
</div>
{{ end }}
</div>
<script>
(function () {
var row = document.currentScript.previousElementSibling;
if (!('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches) return;
var counters = [];
row.querySelectorAll('.stat-value').forEach(function (el) {
var m = el.textContent.trim().match(/^(\d+)(.*)$/);
if (!m) return;
var shown = document.createElement('span'), full = el.textContent.trim();
shown.setAttribute('aria-hidden', 'true');
shown.textContent = '0' + m[2];
el.innerHTML = '<span class="visually-hidden"></span>';
el.firstChild.textContent = full;
el.appendChild(shown);
counters.push({ node: shown, to: +m[1], suffix: m[2] });
});
if (!counters.length) return;
new IntersectionObserver(function (entries, io) {
if (!entries[0].isIntersecting) return;
io.disconnect();
var start = performance.now(), dur = 1200;
(function tick(now) {
var t = Math.min(1, (now - start) / dur), eased = 1 - Math.pow(1 - t, 3);
counters.forEach(function (c) { c.node.textContent = Math.round(c.to * eased) + c.suffix; });
if (t < 1) requestAnimationFrame(tick);
})(start);
}, { threshold: 0.6 }).observe(row);
})();
</script>
{{ if $s.ctas }}<div class="cta-row mt-2">{{ partial "sections/ctas.html" $s.ctas }}</div>{{ end }}