Start with what needs a decision.
The overview leads with the review queue, sorted by urgency, and each row states why it is there. One click opens the filtered register.
I designed the original 4SafeCom interface in 2015. This is my 2026 redesign, organised around the reviewer's next action.
4SafeCom keeps safety records, training and reviews in one system. The original interface was organised by module. This version asks a different question on every screen: what needs a decision, and what happens after it?
Self-initiated redesign · Fictional data · Prototyped with AI assistance · Not yet tested with users
A working prototype with ten connected modules. Decisions are saved in this browser only.

4SafeCom’s public materials describe safety information scattered across paper, spreadsheets and email. I used that to frame one task, reviewing contractor documents, and went back to my 2015 Photoshop files for the visual foundation.
How can a reviewer see what needs attention, make a decision and understand what happens next?
Before drawing the review screen I mapped three responsibilities and the four steps a document passes through.
If changes are needed: explain the issue, the contractor resubmits, and the document returns to the queue. Approving a document does not grant permission to work.
The overview leads with the review queue, sorted by urgency, and each row states why it is there. One click opens the filtered register.
The document, the planned work period and a short requirement list share one screen. On smaller screens they stack in that order.
A requirement marked not met writes the review note and blocks approval. The receipt names who acts next and offers the next document.
My first training concept was a matrix of employees against courses. Once the course columns ran past the screen, matching a person to a status took too much scanning.
I split it into two views. Each answers one question and keeps the person, the course and the status in the same row.
Shared rule. Location, course and status filters combine, and “WHMIS + Overdue” must match the same course record, not any overdue course.
I reviewed the previous revision myself at desktop, tablet and phone widths, checking it against what I learned about the business and its clients while working at the company. The core flow held up. Four things did not match the goals above.
A personal exploration, not a commission. I returned to a product I designed while working at the company and used what I learned there about the business and its clients to rethink it.
Prioritised work, a review with its evidence, and training views that each answer one question.
Can they find the right record, explain a change request and spot overdue training? Their errors decide the next revision.
Published positioning and fragmented-information challenges.
Safety, operations and HR users; document tracking and approvals.
A clothing rack you browse by sweeping across it, where every garment turns like cloth on a hanger, not like a flipped card.
Live prototype. Hover or drag across the rack; tap the front-facing tee to open it.
The starting point was a short screen recording of an interactive product display I came across online (I no longer have the link): garments hang side-on on a rail, and the one under your cursor swings round to face you. I wanted to see whether I could rebuild it with Codex and Claude Code.
Before generating any assets I broke the reference into beats, so each could be designed and tested on its own.
The pointer enters a slot. The garment waits 40 ms, long enough to ignore a pass-through, short enough to feel instant.
latency 40 / 20 msHit-testing uses the live slot widths, with a 3 px margin on the active one so it doesn’t flicker at the edges.
hysteresis 3 pxThe turn is a spring, not a timeline. It can reverse mid-turn at any moment without a jump.
ω 11 · ζ 0.82When it arrives, filmed fabric takes over: the hem swings past, settles, and the hanger rocks gently on its hook.
pendulum 1° · 1.5 sThe next garment waits about 0.1 s for the last one to start turning back, so a fast sweep reads as a wave.
stagger 0.1 sI tracked the rotation in the reference recording frame by frame: how far the garment had turned at each moment, how much it overshot, and when it stopped. The charts compare those checkpoints with the spring in the final prototype.
The reference snaps to the front in about 0.37 s and stops dead. The first build “lacked weight”, so the final spring starts more slowly and lands later on purpose. The extra swing on the way back mostly comes from the filmed release clip, where the hem narrows past its resting width, rather than from the spring.
I started with drawn garments to prove the layout: a fixed rail, narrow side-on slots and one wide open slot. It got the rhythm right but looked like a diagram. Flat shapes have no folds, so nothing could lag.
Layout works, material doesn’t
Next I generated keyframe sheets of a black tee with a white star, so the star would show the rotation clearly. Five angles gave obvious steps. Nine angles, with the deformation described in the prompt, were smoother, but every frame was a static pose. The cloth didn’t move between them.
Real fabric, but frozen

Playing the same frames in reverse looked wrong: the hem led instead of trailing. I split the motion into two sets, turning in and turning out, each with its own drag and overshoot. Their first and last frames match, so the prototype can switch between them mid-gesture without a seam.
Hem trails in both directions

To raise the frame rate I added in-betweens with optical flow (OpenCV DIS) and a warp-and-blend step on premultiplied alpha, so the hanger edges stay clean. It was smoother, but the timing still felt light: the garment moved, but it didn’t seem to weigh anything.
Smooth, still weightless
I switched source: short AI videos of the tee turning on its hook, generated from the keyframes. Video gives real secondary motion for free. It also brought artefacts, so I measured garment width on every frame to find the turn phases, rejected clips where the shirt spun past to its back, and used skin detection to drop frames where a hand appeared.
Fabric moves on its own
The first video build froze mid-motion when it reached the front. I compared how the three videos came to rest and rebuilt the ending: the release clip now ends on a calm frame, then a light pendulum takes over and rocks the hanger around its hook until it stops.
Arrives, swings, rests
The turn to the front was still too short to read in slow motion, so I placed in-betweens by amount of motion: more where the fabric moves fast, fewer where it hangs still. That gives 65 frames to the front and 71 back to the side. Every one is visible in the scrubber below.
Smooth at any speedEach garment holds one number, its turn u, from 0 (side) to 1 (front). The pointer only sets a target. Everything else follows from that.
Hover, drag or tap sets which slot is active. Leaving the rail clears it after 60 ms.
40 ms to start, 20 ms to return, plus 0.1 s stagger while the previous garment is still open.
A damped spring moves u. u maps to a frame in the turn-in or turn-out set, crossfaded so nothing shows through.
On arrival, the filmed ending plays at 1.15× video time, then a decaying pendulum rocks the hanger.
// rail never changes length: the open garment borrows width from the rest
const T = REST * N, EX = OPEN - (T - OPEN) / (N - 1);
widths = garments.map(g => (T - Σ EX·u) / N + EX * g.u);
// turn: semi-implicit spring, stepped at 240 Hz
g.v += (ω*ω*(target - g.u) - 2*ζ*ω*g.v) * dt; g.u += g.v * dt;Drag the slider to step through the turn. Frames marked ○ are the filmed release, played back in real time after the garment arrives.
The spring handles what must respond to the hand: start, reverse, return. The footage handles what no one controls: fabric settling. Neither alone was enough.
Matching the measured timing exactly felt correct but light. The better result came from knowing the baseline precisely and then departing from it on purpose.
Generate the full colourway set from one master clip, test the sweep on low-end phones (136 frames per garment is the budget to watch), and add a reduced-motion mode that keeps the turn and drops the swing.
It began as a challenge to myself: could I rebuild an interaction I’d seen online with AI coding tools? Matching it turned out to be the first step, not the finish.
Garment frames generated with AI from my own prompts.
A designer toy brand you step into on the web: seven scenes pulled apart into depth, and a 21-page brand book you turn by scrolling.
Character concept, logo, colour system, packaging, layouts and interaction design: mine. Scene renders generated with Google Flow from my prompts; interaction code written with Codex and Claude Code.
Bloom Pony is my own IP: a blind-box designer toy, a pony with no expression whose series grow from the flower on its head, six figures and one secret per series, four series. This project is an experiment in designing its interactive interface. Brand books are usually static PDFs that people flip through and forget; here the reader steps into the world instead.
Each of the seven scenes began as a single flat render. I cut out every element, rebuilt the background behind it and restacked the layers by distance, giving the image space and keeping the pony at the centre of the stage. The hard part was hiding the seams: matching rebuilt backgrounds to the original light, cleaning halos from soft edges, keeping contact shadows on the right layer, and tuning layer count and depth until the parallax felt natural.
Drag the strip to browse · ← → to change scene
The brand book is 21 pages, turned by scrolling or swiping, so the reader moves through it in order. Each turn is eased: a quick flick moves exactly one page instead of skipping several, and holding a key keeps turning. Text sits in small floating windows above full-screen work, so the work always fills the screen.

My first brief to Codex didn’t explain the concept clearly, and its automatic layering broke the scenes apart. I went back, layered every image by hand, and then had the coding tools assemble them into the page.