Icons in a share a count, but they do not all use every slot. A hamburger has three strokes and a cross has two. The third slot still exists, so it has to be somewhere and it has to paint nothing.
Two questions hide in that sentence, and this page is about telling them apart. By the end of it you will know where a spare stroke should sit, why the obvious way of getting rid of it does not get rid of it, and why the fix costs a second animated property rather than a cleverer position.
Conflating them is the mistake. A slot that is not in use needs:
a spare slot at the centre of the canvas means a stroke that grows out of the middle of nowhere. Parking it on a sibling slot's geometry means it is born by splitting off that stroke, which reads as division rather than apparition.
That is a claim about motion, so here it is as motion. One slider, both choices.
parked is the three-line function from the rig: a slot with no geometry
of its own, carrying the number of the sibling it hides on. Here is the whole of the
minus icon from that chapter's rig, which is the only part of it this section needs.
import { lineSlot, parked } from "@/lib/morph";
// `minus` needs one of the rig's three slots. The other two park on slot 0, which is the
// stroke they will be born by splitting away from rather than appearing out of the canvas.
export const minusIcon = [lineSlot(6, 12, 18, 12), parked(0), parked(0)];The tempting shortcut is to rely on the overlap. If the parked slot sits exactly on its host, surely it is invisible and no opacity is needed.
It is not, and this was measured rather than reasoned about.
The reason is edges compositing twice. An edge pixel the renderer decided was 50% covered is painted at 50%, then painted again over itself, and two 50% layers resolve to 75% rather than 50%. The core of the stroke is fully opaque in both passes and so stays correct, which is why the artefact is an outline rather than a general darkening.
Measured at 24 CSS pixels, which is the size Lucide is drawn for and the size these icons are most often rendered at, the worst per-pixel alpha delta along the shared outline is 48 out of 255. The grid is also 24, and that is a coincidence rather than a relationship: the grid is a coordinate space and this is a render size, and the artefact gets proportionally worse at smaller sizes because the edge is a larger share of the stroke.
Transparency makes it plainly visible rather than subtle. At stroke-opacity: 0.5 the doubled
stroke measures 192 against 128 for a single one, so a translucent stroke darkens wherever a
slot is parked and no amount of squinting is needed to see it.
So the compiler always emits a suppression track alongside the geometry. Parking decides where, and opacity decides whether.
Nothing that matters. The headline is zero runtime JavaScript, not one animated property, and two CSS properties is still zero JavaScript. Optimising for one property was optimising the wrong number.
So: a parked slot sits on a sibling, because that decides how it is born next time, and it is faded out, because sitting on a sibling does not hide it. Both, always. Either one alone is a morph that looks wrong in a way nothing reports.
Part 6 is the other case where slot index is the right answer and the interpolation between two slots still is not.
Where a spare stroke goes, and why hiding it under another is not enough.
You will need it in Part 8.