Available for new projects
Tell me about your brand, your product or your next campaign. I review every inquiry personally and reply with a clear plan within 48 hours.
Lab
A portfolio can claim it cares about detail. Here you can touch it. Every bench runs the same component that ships in production, with its controls exposed.
The button leans toward the cursor before you get there.
It follows the pointer on a damped spring, so it moves a little and settles on its own. It turns off entirely on touch screens, where there's no cursor to lean toward, and under reduced motion. Drag the strength: past 25 it stops reading as precision and starts reading as a toy.
Four entrances, not one repeated everywhere.
Each section enters the way it should: content rises a little, closings rise more, anything already moving horizontally just fades, and panels take a minimal zoom. These are CSS animations fired by an IntersectionObserver, so the compositor handles them, not the main thread.
Point at one piece and the others step back.
The grid focuses itself: the one you're looking at stays, its siblings drop in opacity. Pure CSS with :has(), no state and no JavaScript, and it only touches opacity, so it costs no repaint. Hover one of the three.
An 11×8 grid drawn in code, not an exported image.
The invader is the site's secondary mark, written as a grid inside the component rather than loaded from a file. That's why it scales sharp at any size and recolours from a token. Stretch it all the way.
If you want to know how the rest is put together, the colophon covers the data, language, accessibility and deployment decisions.