capad.fyi · hero · riso, developed

Edges, then behaviour

You picked C, and you were right on both counts. The pixelation was entirely my fault: the earlier sheet inlined every photo at 300px wide so nine mockups would fit under a 512 KB cap, then option C displayed that one photo at up to 48% of a 1440px frame — roughly 690px. A 2.3× upscale. Nothing to do with your files. And you were right that it was the wrong picture too: the retouched face_revel crop replaces it in all nine panels below, because a tighter frame with a larger face is simply a better hero. It is also the only one of your files that is not an upscale — at 1092×1440 it is smaller than the originals, so what improved is the retouch and the crop, not the pixel count.

The sources here are 900px WebP at q78 with a lossless alpha plane — 148 KB as base64, measured, not guessed. At C's largest size (~691px) that is a 1.3× downscale, so it should look crisp rather than soft. If it still reads soft, that is a different problem and worth saying so.

Two things to settle before locking C in: what the edge of the cut-out should do, and what the ink layers should do over time. Both are below, and both are live rather than described.

900px sources · q78 · lossless alpha 5 edge treatments 4 live behaviours no JS needed to read this page
1

The edge, five ways

A cut-out has a hard alpha boundary. A risograph print does not: ink wicks into the paper, the screen has a finite dot frequency, and the plate is never quite in register with its neighbour. Each treatment below attacks the boundary specifically, leaving the interior of the photograph untouched.

Why this matters more than it sounds. The alpha edge is the only part of these images that is not photographic, so it is the part that gives away that this is a composited PNG. A halftone or a wick hides that seam; a crisp cut announces it. E1 is included as the control, and it is worth looking at next to the others precisely because it now looks too clean.

E1 crisp

Baseline. The alpha boundary stays razor sharp and reads as a cut-out pasted on paper. Correct if you want the collage to look assembled; wrong if you want it to look printed.

E2 ink bleed

Ink wicking into absorbent stock. A blurred copy sits under each crisp screen. Keeps the face sharp while the boundary goes soft. Cheapest of the four — one extra blurred layer, no filter, no mask.

E3 halftone

The signature riso texture. Each screen gets its own dot frequency and mask offset, because three identical dot patterns is what makes CSS halftone look like a screensaver. Caveat: the dots are a fixed size, so highlights print as heavy as shadows. A real screen varies dot size by tone.

E4 photocopy chew

Ragged, eroded silhouette. Turbulence displaces the alpha boundary by about 5px so the edge erodes irregularly, like a fourth-generation photocopy. The most characterful and the most expensive — see below.

E5 registration fringe

Leans into the misalignment. Instead of hiding the offset, it commits: 4.2px of drift and a brightened red screen, so the fringe at every silhouette reads as a deliberate second colour rather than a mistake.

CostE2 cheapest (one blurred layer). E3 three masks, composited once — static, so it rasterises once. E4 a live feTurbulence + feDisplacementMap over the whole plate. E5 free.
The one to watchE4. An SVG displacement filter is per-pixel and not compositable. Static it rasterises once and is fine. But it must be dropped under perf-lite / perf-soft and under (pointer: coarse), or it re-runs on a weak rasteriser. That is a real gate to write, not a free win.
Combines with the behaviours?Yes. Edges and motion are independent — the edge treatment is a filter/mask on the layer, the behaviour only moves --mis.
My pick: E3 or E5. E3 because halftone is the one texture that is unmistakably screen-print and would not be mistaken for a filter; E5 because it costs nothing and turns the thing you disliked (misregistration) into the identity. E2 is the safe middle. E4 is my favourite visually and the one I would argue hardest for, knowing it needs a perf gate.
2

Four behaviours, live

These are running, not screenshots. Move the pointer, drag, or scroll — the meter shows the current registration offset in pixels. All four animate the same single custom property, so they compose with whichever edge treatment you pick.

One mechanism, four characters. Every behaviour below writes --mis and nothing else. That is deliberate: it means the behaviours are interchangeable, they cost one custom-property write per frame rather than a layout or paint, and the same property can be handed to CSS (@property is registered, so it genuinely interpolates) or to prefers-reduced-motion for free. With JS off, or motion reduced, every panel sits at a fixed 2.4px offset and still reads correctly.

B1 pointer

mis 1.4px
I build the tools that shouldn’t need to exist. Aadarsh Upadhyay
developer toolsSee the work
move the pointer

The inks follow the cursor. Offset tracks the pointer across the plate, and the print visibly separates as you move away from centre. This is the one that matches the site you already have — the liquid cursor and the glass specular both already answer the pointer, so this is the same idea arriving in a different material. My pick.

B2 idle breathing

mis animating
A print that is never quite in register. Aadarsh Upadhyay
developer toolsSee the work

Pure CSS, zero JS. A 7s sine on --mis between 1.2 and 5px. Slow enough to read as a machine running slightly out of register rather than as an animation. Costs nothing while you scroll past because it is a compositor-friendly custom property.

B3 drag to register

mis 1.4px
Pull the plates back into register. Aadarsh Upadhyay
developer toolsSee the work
drag left and right

A printer’s registration slider. Drag horizontally and the three screens converge or separate; hit zero and the print snaps into register. The most tactile of the four and the most self-explanatory — you discover the mechanic by touching it, with no instructions.

B4 scroll-linked

mis 1.4px
Registration drifts as you read down. Aadarsh Upadhyay
developer toolsSee the work
scroll this page

Tied to scroll position through the section. The plates come into register as the panel centres and drift apart as it leaves. Uses the second photo. Honest warning: scroll-linked animation is the one people notice as missing on a trackpad with smooth scrolling, so it will feel dead to some visitors and lively to others.

CostAll four write one custom property per pointermove or per scroll tick. No layout, no paint, no filter re-run. B2 is CSS only. This is close to free, which is why the behaviours are worth arguing about separately from the edges.
Reduced motionB2 stops via prefers-reduced-motion. The pointer, drag and scroll behaviours are all direct-manipulation responses to a user gesture, so they stay — a drag that does nothing would be a broken control, not an accessibility win.
CombinesPick one behaviour and one edge independently. E3 + B1 is my guess at the strongest combination.
TouchB3 is a drag, and a drag on a phone competes with scrolling. It needs a touch-action decision and probably a wider hit area than a hero should have.
Recommendation: E3 + B1. Halftone for the surface, pointer for the behaviour. They share an idea — the print is a physical thing responding to a physical input — and that coherence is most of what was missing from the version you liked. If you want zero JS and zero risk, E5 + B2 is the same idea with the interaction removed.