fixed justify and improved sigils

This commit is contained in:
2026-05-18 12:14:28 +02:00
parent 2651b29d02
commit b38b86e5ab
5 changed files with 370 additions and 151 deletions
+62 -2
View File
@@ -23,11 +23,16 @@
<script>
import { buildCybersigil } from '../lib/cybersigil';
let teardown: (() => void) | null = null;
function initCyberFx() {
const root = document.documentElement;
if (!root.classList.contains('cybersigil')) return;
const fx = document.querySelector<HTMLElement>('.cs-fx');
if (!fx) return;
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const fine = window.matchMedia('(pointer: fine)').matches;
/* ─── Generated sigil growths in the four corners ─── */
/* One sigil per page load; the four corner transforms in global.css
@@ -42,10 +47,11 @@
});
}
/* ─── One slow-spinning sigil filling the background ─── */
/* ─── One sigil filling the background. count:6 (was 9) — fewer branch
* nodes ⇒ far fewer perpetually-animating strokes, same silhouette. ─── */
const wire = document.querySelector<HTMLElement>('.cs-fx-wire');
if (wire && !wire.classList.contains('cs-fx-wire--sig')) {
wire.innerHTML = buildCybersigil({ count: 9 });
wire.innerHTML = buildCybersigil({ count: 6 });
wire.classList.add('cs-fx-wire--sig');
}
@@ -72,6 +78,60 @@
targets.forEach((t) => io.observe(t));
}
}
/* ─── Ambient: entrance fade-in (opacity:0 → target via the CSS
* transition on first apply), scroll-depth recede, scroll + pointer
* parallax. Parallax is gated on fine pointers and reduced-motion;
* the depth fade is just opacity tied to scroll position. ─── */
if (teardown) teardown();
const off: Array<() => void> = [];
let depth = 0, px = 0, py = 0, raf = 0;
const apply = () => {
raf = 0;
fx.style.opacity = String(1 - 0.5 * depth);
if (!reduced) {
fx.style.setProperty('--cs-px', px.toFixed(1) + 'px');
fx.style.setProperty('--cs-py', (py + depth * 24).toFixed(1) + 'px');
fx.style.setProperty('--cs-cx', (-px * 0.42).toFixed(1) + 'px');
fx.style.setProperty('--cs-cy', (-py * 0.42).toFixed(1) + 'px');
}
};
const schedule = () => { if (!raf) raf = requestAnimationFrame(apply); };
const onScroll = () => {
const vh = window.innerHeight || 1;
depth = Math.max(0, Math.min(1, window.scrollY / vh));
schedule();
};
window.addEventListener('scroll', onScroll, { passive: true });
window.addEventListener('resize', onScroll);
off.push(() => window.removeEventListener('scroll', onScroll));
off.push(() => window.removeEventListener('resize', onScroll));
onScroll();
if (!reduced && fine) {
const onPointer = (e: PointerEvent | MouseEvent) => {
const w = window.innerWidth || 1, h = window.innerHeight || 1;
px = (e.clientX / w - 0.5) * 26; // ≈ ±13px drift
py = (e.clientY / h - 0.5) * 26;
schedule();
};
window.addEventListener('pointermove', onPointer, { passive: true });
off.push(() => window.removeEventListener('pointermove', onPointer));
}
/* Freeze every loop while the tab is hidden — idle-battery win. */
const onVis = () => fx.classList.toggle('is-paused', document.hidden);
document.addEventListener('visibilitychange', onVis);
off.push(() => document.removeEventListener('visibilitychange', onVis));
onVis();
teardown = () => {
if (raf) cancelAnimationFrame(raf);
off.forEach((fn) => fn());
teardown = null;
};
}
initCyberFx();