Some checks failed
CI / lint (push) Successful in 1m24s
CI / test (push) Successful in 2m24s
CI / validate-json (push) Successful in 57s
CI / markdown-links (push) Successful in 29s
Deploy site / deploy (push) Successful in 7s
Build ISO / build-iso (push) Failing after 14m59s
Adopts the visual feel of Pascal's prototype while keeping Furtka's
voice, brand palette, and bilingual structure intact.
What changed
- Three.js wireframe torus-knot behind the hero, color/opacity tied
to the existing --accent / --scene-opacity CSS vars so light and
dark modes both work without a scene re-init.
- Scroll-driven camera zoom + core scale + tilt; canvas opacity fades
past hero so feature cards stay readable.
- GSAP + ScrollTrigger reveal hero on load and stagger feature cards
in as they enter the viewport. Lenis smooths scroll.
- "What works today" / "What's coming next" lists move from markdown
bullets into front-matter arrays and render as scroll-reveal cards
(7 + 4 cards, EN/DE parallel; copy is 1:1 from the original lists).
- Hero scaled up: gradient text on the wordmark (fg → accent),
drop-shadow glow in dark mode, brighter lede color.
- Primary CTA -> /releases listing on Forgejo (Forgejo has no
/releases/latest), with a pulsing glow + arrow slide on hover.
- Version bump 26.8-alpha -> 26.15-alpha to match the actual release.
Performance / a11y
- Vendor JS (Three.js r128, GSAP 3.12.2 + ScrollTrigger, Lenis 1.0.33)
vendored locally under assets/js/vendor/ - no third-party CDN at
runtime. ~728 KB total, fingerprinted via Hugo's pipeline with SRI.
- Canvas + scripts gated to homepage only ({{ if .IsHome }}); the
Impressum/Datenschutz pages stay plain.
- prefers-reduced-motion: scene + GSAP early-return, CSS forces cards
to their resting state. No-JS users see all content.
- All scripts deferred so first paint isn't blocked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
25 lines
848 B
JavaScript
25 lines
848 B
JavaScript
(function () {
|
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
|
if (!window.gsap || !window.ScrollTrigger || !window.Lenis) return;
|
|
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
|
const lenis = new Lenis({ lerp: 0.1, smoothWheel: true });
|
|
lenis.on('scroll', ScrollTrigger.update);
|
|
gsap.ticker.add((time) => { lenis.raf(time * 1000); });
|
|
gsap.ticker.lagSmoothing(0);
|
|
|
|
// Hero stagger — runs once on load.
|
|
gsap.to('.hero .reveal', {
|
|
y: 0, opacity: 1, duration: 1.1, ease: 'power3.out', stagger: 0.12
|
|
});
|
|
|
|
// Card reveals — batched so cards in the same row come in together.
|
|
ScrollTrigger.batch('[data-gsap="card"]', {
|
|
start: 'top 90%',
|
|
onEnter: (els) => gsap.to(els, {
|
|
y: 0, opacity: 1, scale: 1,
|
|
duration: 0.9, ease: 'power3.out', stagger: 0.08, overwrite: true
|
|
})
|
|
});
|
|
})();
|