AI CSS Animations

Minimal Light-Mode Product Film

A minimal light-mode product film for a daily planner: one precise interaction at a time on a vast warm-white field (a task checked, a row dragged, a time set), then the camera pulls back to the whole app window.

Written and rendered by AI CSS Animations Oct 19, 2026

Type
prompt
Made with
Claude Opus 5.5 in Claude Code
Built in
HTML/CSS
Topics
SaaS promo · Product UI
What Claude made from the prompt below in Claude Code: one HTML file rendered frame by frame to video. Silent preview.

About this style

Minimal product films descend from the International Typographic Style, developed in Switzerland in the 1950s, with its grids, sans serifs and generous white space, and from the restrained advertising of design-led consumer electronics. Software teams adopted the approach for launch videos of tools that sell calm, craft or speed: few elements, a light background, one interaction at a time, and motion tuned with custom easing curves so every movement feels physical and deliberate. The restraint is the message: if the film has nothing extra, the product seems to have nothing extra either. It works only when the details are exact, with optical alignment, a small set of easing curves used consistently, a single accent color and nothing on screen that does not earn its place.

The prompt

Make a 10-second minimal light-mode product film for a daily planner: on a vast warm-white field, one precise interaction at a time, framed close (a task checked off, a row dragged into place, a time set), then the camera pulls back and the whole app window assembles around them, and one last task is checked.

<inputs>
If I don't give you something, use the default and don't ask.
- Product: Plainday, a calm daily planner (fictional). Wordmark: "Plainday" with a small accent dot before it.
- Tagline: "Plan less. Do the day." Sub-line under the wordmark: "Free for personal use".
- The day: Today, Tue 21 Oct. Tasks, in their starting order: 1 "Review Q4 roadmap draft" 09:30 (done); 2 "Reply to Ines about the venue" 11:00 (done); 3 "Send invoice to Halden & Co." 12:15; 4 "Book flights for Lisbon" 16:00; 5 "Call the printer" (no time yet).
- Interactions: check task 3 (2 → 3 of 5 done); drag "Call the printer" above "Book flights for Lisbon"; give it the time 14:30; finally check it (3 → 4 of 5 done).
- Step labels: "01  Check it off" · "02  Drag to reorder" · "03  Give it a time"
- Length: 10 seconds.
</inputs>

<direction>
- Look: a quiet, exact product film. Huge white space, one element in play at a time, a single accent color, motion so precise it feels physical. The camera moves like a slow lens on a single continuous surface, never cutting. The craft is in alignment, spacing and easing, not in effects.
- Palette: field #F7F7F5; window surface #FFFFFF; ink #121212; secondary #8B8B86; tertiary #B9B9B3; hairlines #E6E5E1; soft fills #F2F1EE; accent #FF5A1F, used only for the checkbox fill, the drag insertion line, the selected time and the new timeline block's edge. Shadows only as rgba(18,18,18,0.06–0.10). Nothing else.
- Type: Geist 600 for "Today", the tagline and the wordmark; Geist 500 for task titles and UI; Geist Mono 400 for times, counts, hour labels and step labels. Sizes below are in world pixels (the camera scales them).
- Easing, exactly three curves and nothing else: glide = cubic-bezier(0.22, 1, 0.36, 1) for entrances and position moves; swap = cubic-bezier(0.65, 0, 0.35, 1) for camera moves and crossfades; press = a critically damped spring (stiffness 420, damping 41, mass 1) for presses, releases and checkbox scale. No overshoot anywhere.
- The world is the stage at 1× with the app window at x 440–1480, y 236–856 (1040 × 620, radius 18, #FFFFFF, 1px hairline border, shadow 0 24px 60px rgba(18,18,18,0.06)):
  - Header: "Today" (Geist 600, 28px) at x 484, baseline 288, and "Tue 21 Oct" (Geist 500, 18px, secondary) 14px after it; at the right, "2 of 5 done" (Geist Mono, 15px, secondary) right-aligned at x 1080, baseline 284, over a 140 × 2px track (x 940–1080, y 296) with an ink fill at 40%. A hairline under the header at y 316, the full window width.
  - Task list, x 484–1080, five 68px rows from y 332 (rows end at 400, 468, 536, 604, 672), each with a hairline at its bottom: a 22px circle checkbox (1.5px tertiary ring) centered at x 495; the title at x 528 (Geist 500, 19px, ink); the time right-aligned at x 1080 (Geist Mono, 15px, secondary), or "Add time" in tertiary when there is none. Done rows: the checkbox filled accent with a white check, the title in tertiary with a 1.5px strike line. "+ New task" (Geist 500, 17px, tertiary) at x 528, baseline 716.
  - Right panel, x 1112–1480 behind a vertical hairline at x 1112: "Timeline" (Geist 600, 15px) at x 1144, baseline 288; hour labels 09:00 to 17:00 (Geist Mono, 13px, tertiary) at x 1144 on baselines 352 + 56 per hour, each with a hairline from x 1200 to 1456; blocks from x 1206 to 1456, 26px tall, top at y 347 + 56 × (hours after 09:00), #F2F1EE fill, radius 6, title in Geist 500, 13px: 09:30 Review Q4 roadmap, 11:00 Reply to Ines, 12:15 Invoice to Halden, 16:00 Book flights; done blocks in tertiary with a strike.
  - Above the window, the tagline centered at baseline y 170 (Geist 600, 44px, ink, letter-spacing −0.02em); below it, the wordmark centered at baseline y 944 (a 10px accent dot, then "Plainday" in Geist 600, 22px) and "Free for personal use" (Geist 400, 15px, secondary) at baseline 972.
- One element at a time: during the close-ups only the elements in play are visible on the empty field (no window, no other rows); the rest of the window assembles only at the pull-back.
- Camera: a single transform on the world: translate so the focus point lands at the frame center (960, 540), then scale. Close-up 1: focus (782, 502), scale 1.7. Close-up 2: focus (782, 604), scale 1.5. Close-up 3: focus (900, 600), scale 2.0. The pull-back: focus (960, 556), scale 1.0. Moves between them use swap.
- The cursor: an original 22px ink arrow with a 1.5px #FFFFFF edge and a soft rgba(18,18,18,0.12) shadow, drawn in screen space (constant size) at the screen position of its world target, moving on glide along a gentle arc, pressing to 0.9 scale with the press spring.
- Interaction 1, check: the cursor presses the checkbox of "Send invoice to Halden & Co."; the circle fills accent from its center (radius 0 → 11 on glide, 0.24 s); a white check draws in 0.18 s; the title fades to tertiary while a 1.5px strike line draws left to right across it (0.32 s, glide).
- Interaction 2, drag: the cursor grabs "Call the printer" (row 5); the row lifts (scale 1.015, background #FFFFFF, shadow to 0 10px 30px rgba(18,18,18,0.10) on press); it rises 68px on glide over 0.55 s while a 2px accent insertion line shows at y 536; when it passes halfway, "Book flights for Lisbon" slides down 68px on glide; the drop settles the shadow away on press.
- Interaction 3, time: the cursor clicks "Add time" on "Call the printer"; a segmented pill appears below it (228 × 40, radius 20, at x 852–1080, y 612–652, #FFFFFF with a hairline and a soft shadow), scaling 0.96 → 1 and fading in on glide (0.2 s), with "14:00 · 14:30 · 15:00" in Geist Mono 15px; the cursor moves to 14:30, the segment takes a #F2F1EE hover, then on the click fills accent with white text (0.18 s); the pill closes (scale 0.98 and fade, 0.16 s) and "Add time" crossfades to "14:30" in secondary.
- The pull-back: the camera eases to 1× on swap over 0.9 s while the window surface, header, the other rows, the hairlines and the right panel fade and rise 8px into place on glide, 40 ms apart; the timeline's new 14:30 block "Call the printer" arrives with a 2px accent left edge; the counter reads "3 of 5 done" at 60%. The tagline and wordmark fade in on glide.
- Step labels, in screen space at x 120, baseline 1000 (Geist Mono, 14px, secondary) after a 24px hairline: "01  Check it off", "02  Drag to reorder", "03  Give it a time", each crossfading with its interaction on swap and gone at the pull-back.
- Premium: vast, even white space; nothing moving except the one thing in play; three easing curves applied consistently; numbers and times that agree everywhere; crisp text at every zoom. Cheap: bouncy springs, gradients, glows, dark mode, a busy window shown all at once, blurry zoomed text, a different easing for every move.
- Banned: overshoot or bounce, gradients, glows, blur effects, more than one accent color, dark backgrounds, sound-wave or confetti flourishes, will-change on the zooming world (it would rasterize at 1× and blur when scaled), real company names, logos and UI copied from existing products, anything flashing more than 3 times a second.
</direction>

<structure>
- 0.0–0.4s: the empty field; row 3 alone (its checkbox, title and 12:15) fades in at close-up 1; "01  Check it off" appears.
- 0.4–1.9s: interaction 1: the cursor arrives (0.4–0.9 s), presses (1.0 s), the fill, check and strike play (1.0–1.4 s), and the cursor rests.
- 1.9–2.2s: the camera moves to close-up 2 as row 3 fades out and rows 4 and 5 fade in; the step label swaps.
- 2.2–3.5s: interaction 2: the grab (2.5 s), the lift, the move and the drop (2.55–3.2 s).
- 3.5–3.8s: the camera moves to close-up 3, row 5 fading out; the step label swaps.
- 3.8–5.0s: interaction 3: the click on "Add time" (4.0 s), the pill, the hover, the click on 14:30 (4.5 s), the pill closing and the time crossfade (4.6–4.9 s).
- 5.0–5.9s: the pull-back to 1× while the window assembles; the tagline and wordmark fade in; the cursor glides to rest just below the window at (1160, 884).
- 5.9–6.3s: hold. The 6.0 s frame is the hero: the whole window with every row in order (09:30, 11:00, 12:15, 14:30, 16:00), "3 of 5 done", the timeline with the new block, the tagline and the wordmark, in wide white space.
- 6.4–7.6s: one last precise interaction at 1×: the cursor checks "Call the printer" (press at 6.9 s); its row and its timeline block go to the done style; the counter rolls to "4 of 5 done" and the progress fill glides from 60% to 80%.
- 7.6–8.0s: the cursor glides out of frame to the bottom-right.
- 8.0–10.0s: hold, nothing moving.
For other lengths, stretch the rests between interactions, never the interactions; keep at least 1 s of hold.
</structure>

<build>
- One self-contained index.html (inline CSS and JS), a 1920×1080 (16:9) stage scaled to fit the window, designed for 60fps. No image, video, texture or model files: every shape and texture is generated in code.
- window.seek(t), t in seconds, computes every visual from t alone: no CSS transitions or CSS animations, no setTimeout/setInterval, no state carried between frames, randomness only from a seeded PRNG. Anything cumulative is solved analytically from t or precomputed once at load at a fixed step. Past the end, seek clamps to the last frame.
- Without ?render in the URL, drive seek from requestAnimationFrame so it plays in a browser (loop after a 1s end hold); with ?render, don't start that loop.
- Google Fonts via <link> are fine; await document.fonts.load() for each face before defining window.seek.
- Engine: HTML/CSS: plain DOM elements for the window, rows, panel, pill and cursor, with their transform, opacity, colors, widths and text set from t in seek through inline styles, never through transitions. Implement the three curves in JS: a cubic-bezier solver (Newton steps with a bisection fallback) and the closed-form critically damped spring. The world is one absolutely positioned 1920 × 1080 element under a single transform for the camera; the cursor and step labels live outside it in screen space. Strike lines and the check are inline SVG paths revealed with stroke-dashoffset set from t.
</build>

<check>
Before showing me, step through one frame per second (t = 0…10): screenshot each and look at it. Fix overlaps, clipped or cramped text, and anything off-style or Banned. Check that each close-up shows only the elements in play on an otherwise empty field; text is crisp at every zoom; nothing overshoots; the accent appears only in its four uses; counts, times and order agree everywhere ("3 of 5 done" at 6.0 s with times 09:30, 11:00, 12:15, 14:30, 16:00; "4 of 5 done" at the end); the 6.0 s frame shows the whole window, the tagline and the wordmark; and the final frame is the full window with 4 of 5 done and no cursor. Confirm seek(10) and seek(11) match, so the final frame holds.
</check>

Ours, and free to use under CC0: copy it, change it, ship it. No credit needed.

Similar prompts

More like this on the motion design inspiration board: UI animation inspirationSaaS video inspiration