6 stepper animations. Copy any short prompt for free, and open full prompt 1 to see how detailed they are. Full prompts 2–6 are in the pack.
Basics: stage 470×222px, background #13131C, all coordinates in px from the stage's top-left, everything clipped to the stage (top corners rounded 40px). The animation is a 4s loop that plays by itself and is seamless; the video is 12s = three loops. T = seconds since the video start; u = (T + 0.25) mod 4 (the first frame is already 0.25s after a tap). A tap every second at u = 0, 1, 2, 3 (video T = 0.75, 1.75, 2.75 …). Tap k (0–3): button side SIDE = [+, +, −, −], value after the tap VALS = [2, 3, 2, 1]; the value before tap k is VALS[(k+3) mod 4]. state(u): k = floor(u), dt = u − k (seconds since the last tap, 0–1), from = VALS[(k+3) mod 4], to = VALS[k], side = SIDE[k] (+1 for plus, −1 for minus). So the number goes 1 → 2 → 3 → 2 → 1 and loops. The stepper (identical in all six cells): item label "Orbit Mug" 700 21px #E9E8F5 left-aligned at (44, 40) and "Quantity" 600 16px #7F7D9C right-aligned at (426, 40), font "Segoe UI Variable Display","Segoe UI",sans-serif. Label text uses the alphabetic baseline at y 40. Pill: rr(40, 60, 390, 120, radius 60) filled #1C1B2B with shadow rgba(0,0,0,0.45) blur 18 offsetY 6; then a vertical gloss gradient over it from y 60 rgba(255,255,255,0.05) to y 180 transparent; stroke #3A3852 2px. Round buttons radius 44, centers minus (104, 120), plus (366, 120). Each button (inside translate(center), scale(sc)): a circle filled #2A2840; on top, at opacity en (enabled amount), the circle filled with a diagonal gradient from (−44, −44) #6E5BFF to (44, 44) #38C6FF with shadow rgba(110,91,255,0.5) blur 14; then a vertical gloss from y −44 rgba(255,255,255,0.16) to y 44 transparent (the button's white gloss is drawn at full opacity, not multiplied by en); optional white overlay rgba(255,255,255,hl) and dark overlay rgba(10,8,30,dark); then the glyph, rotated by rot: a horizontal line from (−15, 0) to (15, 0) and, for plus, a vertical one from (0, −15) to (0, 15), 6.5px, round caps, color mix(#6A6886, white, en). Enabled amount of the minus (the plus is always 1): for u ≥ 3 (the value is 1) en = 1 − ease(seg(u, 3.12, 3.35)); for u < 1 en = ease(seg(u, 0, 0.2)); otherwise 1 — so at the minimum the minus fades to a dark disabled button and comes back right after the next plus. The number: 800 78px white digit, centered at (235, 120). Draw each digit once into an offscreen 240×240 canvas at double size (800 156px, textAlign center, alphabetic baseline at y 120 + 156·0.355) and place it with drawImage(img, −60, −60, 120, 120) after translate(x, y) and scale(sc·sx, sc·sy), at opacity a, optional shadow glow — never fillText at a moving position (it snaps to whole pixels). Per-side helpers: sideSince(u, s) = seconds since the last tap on side s (0–4); sidePress(u, s, depth) = the minimum of pressK over the taps of side s. Press squash pressK(a, depth) (a = seconds since a tap, wrapped to −2…+2): 1 for a < −0.1 or a > 0.6; 1 − depth·(a+0.1)/0.1 just before the tap; 1 − depth·(1 − springF(22, 0.45)(a)) after. springF(ω₀, ζ)(t) = 0 for t ≤ 0, else 1 − e^(−ζω₀t)(cos ω_d t + (ζω₀/ω_d) sin ω_d t), ω_d = ω₀√(1−ζ²). Draw order: label, pill, effects under the buttons, buttons, number, finger. Tap indicator for each of the 4 taps at (button center x + 8, 128) (drawn last): visible for −0.42 ≤ a < 0.4; circle radius 22.575, fill rgba(215,215,230,0.38), shadow black 35% blur 10, border 3.5px white 92%; scale lerp(1.25, 1, ease((a+0.42)/0.32)) for a < −0.1, lerp(1, 0.8, (a+0.1)/0.1) for −0.1 ≤ a < 0, lerp(0.8, 1, ease(a/0.2)) after; opacity clamp((a+0.42)/0.18) before, clamp(1 − (a−0.12)/0.25) after; for 0 ≤ a < 0.4 a 3px white ring radius 22.575·(1 + 3.2a) at opacity 0.7(1 − a/0.4), drawn under the circle. The ring is not affected by the circle's opacity or scale: its opacity is exactly 0.7(1 − a/0.4) and its center is the unscaled indicator position. Easing (k clamped 0–1): ease = 1 − (1−k)³; easeIO = 4k³ for k < 0.5 else 1 − (−2k+2)³/2; easeBack = 1 + 2.9(k−1)³ + 1.9(k−1)². seg(x, a, b) = clamp((x−a)/(b−a)); bump(x, a, b) = sin(π·seg). mix = per-channel RGB blend. Every value depends only on u, so 4.0s equals 0s. The tapped button squishes and lights up softly; the old number shrinks away and the new one pops up from small with a little overshoot. - Each button s: sc = sidePress(u, s, 0.14), hl = 0.3·bump(sideSince(u, s), 0, 0.4); the minus uses en. - Old number: e1 = ease(seg(dt, 0, 0.16)); scale lerp(1, 0.55, e1), opacity 1 − e1. - New number: p = seg(dt, 0.06, 0.46); scale lerp(0.35, 1, easeBack(p)), opacity clamp(4p).