Image card grid built as a plain, fully editable Etch tree: section > container > header (eyebrow, h2, intro) > a plain grid of "Particle Card" component instances (add, remove, reorder in Layers). Card props: primaryImage, primaryImageAlt, secondaryImage, secondaryImageAlt, title, arrowLabel (the small caption next to the corner arrow), url (the whole card becomes a link when filled) and trigger (select hover|click|tap — hover reveals on pointer enter/leave, click and tap both toggle a pressed state that stays revealed until the card is activated again, which is also what every card falls back to on touch regardless of the chosen trigger, since hover has no meaning there). On activation, a grid of small grain "dot" tiles scattered over the primary photo (built once per card by an inline script, sized by container width, not @keyframes) fades and drifts out in the direction set by data-direction on the Grid element (up|down|left|right|out from the centre), revealing the second photo beneath; deactivating reverses the same transition back. Every tile's transition-delay is pre-computed from its position along that direction so the dissolve reads as one continuous sweep rather than a random flicker. The title and arrow sit in a bottom caption bar that stays visible throughout. Without JS the grain layer never builds and a plain CSS opacity cross-fade on hover/focus still swaps the two photos, so the card degrades gracefully; prefers-reduced-motion swaps instantly with a fast cross-fade and skips the per-tile stagger and drift. :focus-visible ring on the card link, alt text on both images, AA caption contrast.