diff --git a/src/lib/components/organisms/Services.svelte b/src/lib/components/organisms/Services.svelte index 5b53664..9e21a39 100644 --- a/src/lib/components/organisms/Services.svelte +++ b/src/lib/components/organisms/Services.svelte @@ -133,6 +133,28 @@ $effect(() => () => cancelAnimationFrame(frame)); + // A release's title kindles as an event, not scrubbed: once the blaze strikes the node (its + // centre crosses the scan line, 60% down the viewport, where the trunk's tip rides), the + // title plays its reveal on the clock. Scrolling back above the line puts it out again. + let nodes: HTMLElement[] = $state([]); + let kindled = $state(services.map(() => false)); + + $effect(() => { + const observer = new IntersectionObserver( + (entries) => { + for (const entry of entries) { + const index = nodes.indexOf(entry.target as HTMLElement); + const { top, height } = entry.boundingClientRect; + const line = entry.rootBounds?.bottom ?? innerHeight * 0.6; + kindled[index] = top + height / 2 < line; + } + }, + { rootMargin: '0px 0px -40% 0px', threshold: [0, 0.5, 1] } + ); + for (const node of nodes) observer.observe(node); + return () => observer.disconnect(); + }); + // The cell edges between seeds, each drawn once, without the field's border: clip the field // by the bisector to every other seed, and track which seed made each edge of the cell. function voronoi( @@ -259,9 +281,9 @@
    - {#each services as service (service)} -
  1. -
  2. +