COMPONENT
Lamp
Text that strikes like a fluorescent tube the first time it comes into view. One class, one attribute, and nothing whatsoever without a script — with none, the element is text this stylesheet has never touched.
Scroll to it, or press replay
SELECTED WORK
<h2 class="lamp" x-ds-reveal>SELECTED WORK</h2>Every rule in this component is keyed on data-ds-reveal, and only x-ds-reveal ever writes it. With no JavaScript the attribute never appears, not one declaration matches, and the heading is text this stylesheet has never touched — not text that happens to be visible. A reveal that hides its host in CSS and waits for a script to undo it is one broken bundle away from a blank page, and search engines are the last to be told.
The glow is currentColor
A lamp glows in its own light, so there is nothing to configure and nothing to re-theme: cream text blooms cream, accent text blooms accent, and a theme nobody has written yet is already correct. Same reasoning as ripple, and the alternative here is worse — a colour role would have to answer which of the eleven inks, and every answer is wrong on some surface.
The travelling strike
.lamp-spread adds a mask, so the light catches at one point and runs outward through the letters instead of arriving everywhere at once. It catches at a fraction of the element, because CSS cannot mask relative to a run of text — on a heading that fills its box that is exactly right, and on a short word in a very wide box the light catches past the end of it and the effect degrades to the plain lamp. That is why the plain lamp is the base case.
Scroll to it, or press replay
SELECTED WORK
<h2 class="lamp lamp-spread" x-ds-reveal>SELECTED WORK</h2>A row of them
Four tubes striking in unison read as one event rather than four objects, so a row wants staggering. --lamp-delay is zero by default and set per instance.
Scroll to it, or press replay
<div class="hairline-grid" style="--cell: 150px; width: 100%">
<div class="hairline-cell">
<span class="fact-n lamp" x-ds-reveal>ENGINE</span>
</div>
<div class="hairline-cell">
<span class="fact-n lamp" x-ds-reveal style="--lamp-delay: 140ms">FRONT</span>
</div>
<div class="hairline-cell">
<span class="fact-n lamp" x-ds-reveal style="--lamp-delay: 280ms">RESCUE</span>
</div>
<div class="hairline-cell">
<span class="fact-n lamp" x-ds-reveal style="--lamp-delay: 420ms">CREATION</span>
</div>
</div>Reference
Read from components/lamp.css when this page was built, so it cannot fall behind the stylesheet.
.lamp.lamp-spread--lamp-duration — falls back to --ds-lamp-duration--lamp-strike — falls back to --ds-lamp-strike--lamp-bloom — falls back to --ds-lamp-bloomNotes
Where it must not go
Not on the largest thing above the fold. Chrome refuses to count an opacity: 0 element as painted, so hiding whatever a page's Largest Contentful Paint element happens to be defers LCP by the whole reveal. Measured on a real page: hiding four sub-headings moved LCP by nothing at all, because they were never the largest; hiding the hero title moved it from 268ms to 1112ms.
Layout is untouched either way. Opacity and masks are composited, so Cumulative Layout Shift measured identical to four decimal places with and without. The cost is never reflow; it is only ever LCP, and only on one element per page.
Tuning it
em, so one value serves a chip and a headline..lamp-spread catches, as a fraction across the element.