Visibility
The visibility source is scroll-triggered, not scroll-linked. It writes two binary signals per bound element: --live-visible (1 while the whole element is on screen) and --const-has-entered (latches to 1 once the element is entirely in view, never resets). The continuous ratio is left to native view() timelines; the one-way latch is the part those can’t express. Scroll the panels below into and out of view.
--live-visible is 1 while the whole element is on screen.
--const-has-entered latches once the element is entirely in view and never resets.
So it reveals once and stays. Scroll back up; it won't reverse.
The wiring
Section titled “The wiring”Each panel opts in with its own attribute — no list to query, and panels added later are picked up automatically:
<script type="module">import 'prop-for-that/auto'</script>
<section data-props-for="visibility">…</section><section data-props-for="visibility">…</section>/* reveal once, then keep it */.panel { opacity: calc(0.25 + var(--const-has-entered) * 0.75); transition: opacity 0.5s;}
/* the dot lights only while in view */.dot { background: color-mix(in oklab, var(--accent) calc(var(--live-visible) * 100%), gray);}