vibecodeagent 0.0.0-stage → 0.1.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +37 -2
  3. package/THIRD-PARTY-NOTICES.txt +1427 -0
  4. package/dist/agen.js +138895 -0
  5. package/dist/bin.js +1245 -0
  6. package/dist/daemon.js +163664 -0
  7. package/dist/node_modules/node-ensure/index.js +10 -0
  8. package/dist/node_modules/node-ensure/package.json +31 -0
  9. package/dist/node_modules/pdf-parse/lib/pdf-parse.js +102 -0
  10. package/dist/node_modules/pdf-parse/lib/pdf.js/v1.10.100/build/pdf.js +18538 -0
  11. package/dist/node_modules/pdf-parse/lib/pdf.js/v1.10.100/build/pdf.worker.js +45507 -0
  12. package/dist/node_modules/pdf-parse/package.json +49 -0
  13. package/dist/node_modules/sql.js/dist/sql-wasm.js +186 -0
  14. package/dist/node_modules/sql.js/dist/sql-wasm.wasm +0 -0
  15. package/dist/node_modules/sql.js/package.json +58 -0
  16. package/dist/resources/skills/builtin/.gitkeep +0 -0
  17. package/dist/resources/skills/builtin/NOTICE.md +35 -0
  18. package/dist/resources/skills/builtin/README.md +74 -0
  19. package/dist/resources/skills/builtin/backend-engineering/SKILL.md +102 -0
  20. package/dist/resources/skills/builtin/backend-engineering/references/api-contracts.md +320 -0
  21. package/dist/resources/skills/builtin/backend-engineering/references/auth-and-secrets.md +268 -0
  22. package/dist/resources/skills/builtin/backend-engineering/references/concurrency-and-jobs.md +386 -0
  23. package/dist/resources/skills/builtin/backend-engineering/references/data-modelling.md +367 -0
  24. package/dist/resources/skills/builtin/backend-engineering/references/deploy-and-config.md +228 -0
  25. package/dist/resources/skills/builtin/backend-engineering/references/migrations.md +320 -0
  26. package/dist/resources/skills/builtin/backend-engineering/references/observability.md +301 -0
  27. package/dist/resources/skills/builtin/backend-engineering/references/plan-template.md +152 -0
  28. package/dist/resources/skills/builtin/backend-engineering/references/review-audit.md +213 -0
  29. package/dist/resources/skills/builtin/backend-engineering/references/security.md +251 -0
  30. package/dist/resources/skills/builtin/backend-engineering/references/stack-go.md +238 -0
  31. package/dist/resources/skills/builtin/backend-engineering/references/stack-node.md +274 -0
  32. package/dist/resources/skills/builtin/backend-engineering/references/stack-python.md +296 -0
  33. package/dist/resources/skills/builtin/backend-engineering/references/testing-and-perf.md +298 -0
  34. package/dist/resources/skills/builtin/backend-engineering/references/validation-and-errors.md +266 -0
  35. package/dist/resources/skills/builtin/dasar-vibecode/SKILL.md +312 -0
  36. package/dist/resources/skills/builtin/excel-maker/SKILL.md +71 -0
  37. package/dist/resources/skills/builtin/frontend-design/SKILL.md +131 -0
  38. package/dist/resources/skills/builtin/frontend-design/data/app-interface.csv +33 -0
  39. package/dist/resources/skills/builtin/frontend-design/data/catalog-summary.json +78 -0
  40. package/dist/resources/skills/builtin/frontend-design/data/charts.csv +26 -0
  41. package/dist/resources/skills/builtin/frontend-design/data/colors.csv +193 -0
  42. package/dist/resources/skills/builtin/frontend-design/data/data-provenance.json +1348 -0
  43. package/dist/resources/skills/builtin/frontend-design/data/google-font-licenses.json +20185 -0
  44. package/dist/resources/skills/builtin/frontend-design/data/google-fonts.csv +1935 -0
  45. package/dist/resources/skills/builtin/frontend-design/data/icons.csv +106 -0
  46. package/dist/resources/skills/builtin/frontend-design/data/landing.csv +35 -0
  47. package/dist/resources/skills/builtin/frontend-design/data/motion.csv +18 -0
  48. package/dist/resources/skills/builtin/frontend-design/data/phosphor-icons-upstream.json +32582 -0
  49. package/dist/resources/skills/builtin/frontend-design/data/products.csv +193 -0
  50. package/dist/resources/skills/builtin/frontend-design/data/react-performance.csv +45 -0
  51. package/dist/resources/skills/builtin/frontend-design/data/stacks/angular.csv +51 -0
  52. package/dist/resources/skills/builtin/frontend-design/data/stacks/astro.csv +54 -0
  53. package/dist/resources/skills/builtin/frontend-design/data/stacks/avalonia.csv +57 -0
  54. package/dist/resources/skills/builtin/frontend-design/data/stacks/flutter.csv +53 -0
  55. package/dist/resources/skills/builtin/frontend-design/data/stacks/html-tailwind.csv +60 -0
  56. package/dist/resources/skills/builtin/frontend-design/data/stacks/javafx.csv +76 -0
  57. package/dist/resources/skills/builtin/frontend-design/data/stacks/jetpack-compose.csv +53 -0
  58. package/dist/resources/skills/builtin/frontend-design/data/stacks/laravel.csv +51 -0
  59. package/dist/resources/skills/builtin/frontend-design/data/stacks/nextjs.csv +62 -0
  60. package/dist/resources/skills/builtin/frontend-design/data/stacks/nuxt-ui.csv +71 -0
  61. package/dist/resources/skills/builtin/frontend-design/data/stacks/nuxtjs.csv +68 -0
  62. package/dist/resources/skills/builtin/frontend-design/data/stacks/react-native.csv +52 -0
  63. package/dist/resources/skills/builtin/frontend-design/data/stacks/react.csv +62 -0
  64. package/dist/resources/skills/builtin/frontend-design/data/stacks/shadcn.csv +69 -0
  65. package/dist/resources/skills/builtin/frontend-design/data/stacks/svelte.csv +56 -0
  66. package/dist/resources/skills/builtin/frontend-design/data/stacks/swiftui.csv +51 -0
  67. package/dist/resources/skills/builtin/frontend-design/data/stacks/threejs.csv +54 -0
  68. package/dist/resources/skills/builtin/frontend-design/data/stacks/uno.csv +60 -0
  69. package/dist/resources/skills/builtin/frontend-design/data/stacks/uwp.csv +56 -0
  70. package/dist/resources/skills/builtin/frontend-design/data/stacks/vue.csv +50 -0
  71. package/dist/resources/skills/builtin/frontend-design/data/stacks/winui.csv +60 -0
  72. package/dist/resources/skills/builtin/frontend-design/data/stacks/wpf.csv +57 -0
  73. package/dist/resources/skills/builtin/frontend-design/data/styles.csv +89 -0
  74. package/dist/resources/skills/builtin/frontend-design/data/typography.csv +75 -0
  75. package/dist/resources/skills/builtin/frontend-design/data/ui-reasoning.csv +193 -0
  76. package/dist/resources/skills/builtin/frontend-design/data/ux-guidelines.csv +120 -0
  77. package/dist/resources/skills/builtin/frontend-design/references/animation-patterns.md +705 -0
  78. package/dist/resources/skills/builtin/frontend-design/references/app-polish.md +117 -0
  79. package/dist/resources/skills/builtin/frontend-design/references/apple-fluid.md +278 -0
  80. package/dist/resources/skills/builtin/frontend-design/references/art-direction.md +280 -0
  81. package/dist/resources/skills/builtin/frontend-design/references/case-studies.md +599 -0
  82. package/dist/resources/skills/builtin/frontend-design/references/craft.md +128 -0
  83. package/dist/resources/skills/builtin/frontend-design/references/expo.md +251 -0
  84. package/dist/resources/skills/builtin/frontend-design/references/layout-systems.md +533 -0
  85. package/dist/resources/skills/builtin/frontend-design/references/libraries.md +72 -0
  86. package/dist/resources/skills/builtin/frontend-design/references/motion.md +222 -0
  87. package/dist/resources/skills/builtin/frontend-design/references/picker.md +197 -0
  88. package/dist/resources/skills/builtin/frontend-design/references/plan-template.md +73 -0
  89. package/dist/resources/skills/builtin/frontend-design/references/prototype.md +85 -0
  90. package/dist/resources/skills/builtin/frontend-design/references/recipes-expo.md +385 -0
  91. package/dist/resources/skills/builtin/frontend-design/references/recipes-web.md +421 -0
  92. package/dist/resources/skills/builtin/frontend-design/references/review-audit.md +107 -0
  93. package/dist/resources/skills/builtin/frontend-design/references/sonner.md +143 -0
  94. package/dist/resources/skills/builtin/frontend-design/references/technical-stack.md +543 -0
  95. package/dist/resources/skills/builtin/frontend-design/references/theming.md +60 -0
  96. package/dist/resources/skills/builtin/frontend-design/references/typography.md +393 -0
  97. package/dist/resources/skills/builtin/frontend-design/references/ux-rules.md +256 -0
  98. package/dist/resources/skills/builtin/frontend-design/references/vocabulary.md +169 -0
  99. package/dist/resources/skills/builtin/frontend-design/scripts/core.py +993 -0
  100. package/dist/resources/skills/builtin/frontend-design/scripts/design_system.py +1643 -0
  101. package/dist/resources/skills/builtin/frontend-design/scripts/reasoning_contract.py +123 -0
  102. package/dist/resources/skills/builtin/frontend-design/scripts/search.py +171 -0
  103. package/dist/resources/skills/builtin/frontend-design/scripts/validate_data.py +1091 -0
  104. package/dist/resources/skills/builtin/kerja-agentik/SKILL.md +117 -0
  105. package/dist/resources/skills/builtin/pdf-maker/SKILL.md +51 -0
  106. package/dist/resources/skills/builtin/tinjau-keamanan/SKILL.md +53 -0
  107. package/dist/resources/skills/builtin/word-maker/SKILL.md +58 -0
  108. package/dist/resources/skills/builtin/write-swift/SKILL.md +388 -0
  109. package/package.json +35 -4
@@ -0,0 +1,222 @@
1
+ # Motion Doctrine (Web)
2
+
3
+ The canonical motion reference for this skill. Every duration, curve, and spring config in the other files traces back to here — when another file and this one disagree, this one wins. It turns a request for motion into an implementation that would survive a strict review, and it exists to produce zero lines of code sometimes: the most common animation defect is animating something that should never animate.
4
+
5
+ For React Native / Expo, use [expo.md](expo.md) — the doctrine is the same, the runtime rules are not. For gesture physics, velocity handoff, and fluid-interface details, [apple-fluid.md](apple-fluid.md) goes deeper. For ready-made implementations, [recipes-web.md](recipes-web.md). For award-level scroll choreography, [animation-patterns.md](animation-patterns.md).
6
+
7
+ ## Operating Posture
8
+
9
+ You are a senior design engineer building the animation yourself. Never present motion options as a menu — make the call, state the reasoning in one line, write the code.
10
+
11
+ Two failure modes, and the first is worse:
12
+
13
+ 1. **Animating something that shouldn't animate.** The gate below exists to produce zero lines of code sometimes. That's a success, not a dodge.
14
+ 2. **Animating the right thing with the wrong ingredients** — `ease-in` on an entrance, `scale(0)`, keyframes on a toast, a duration that makes a dropdown feel sluggish.
15
+
16
+ ## Hard Rules
17
+
18
+ 1. **Run the sequence in order.** Steps 1 and 2 gate everything. Don't reach for a curve before you know whether it animates at all.
19
+ 2. **No approximated values.** Every curve, duration, and spring config comes from the tables below. Never invent `cubic-bezier(0.4, 0, 0.2, 1)` because it looks familiar.
20
+ 3. **Extend the codebase's tokens, don't fork them.** If `--ease-out` or a duration scale already exists, use it. Adding a parallel system is a defect.
21
+ 4. **Reduced motion and hover gating ship with the animation**, not as a follow-up.
22
+ 5. **Cheapest tool that works.** Don't install a motion library for a fade.
23
+
24
+ ## The Build Sequence
25
+
26
+ ### 1. Should this animate at all?
27
+
28
+ | Frequency | Decision |
29
+ | --- | --- |
30
+ | 100+ times/day (keyboard shortcuts, command palette toggle) | **No animation. Ever.** Stop here. |
31
+ | Tens of times/day (hover effects, list navigation) | Near-imperceptible only — fast and subtle, or nothing |
32
+ | Occasional (modals, drawers, toasts) | Standard animation |
33
+ | Rare / first-time (onboarding, success, celebration) | The delight budget lives here |
34
+
35
+ **Keyboard-initiated actions are a disqualifier, not a judgment call.** Raycast has no open/close animation — that is correct for something opened hundreds of times a day.
36
+
37
+ If the request fails this gate, say so plainly and don't write the animation. Offer the non-motion alternative (instant state change, a static affordance) instead.
38
+
39
+ ### 2. What is the purpose?
40
+
41
+ Name it in one of these words before continuing:
42
+
43
+ - **Feedback** — confirming the interface heard the user
44
+ - **Spatial consistency** — showing where something came from or went
45
+ - **State indication** — making a state change legible
46
+ - **Preventing a jarring change** — bridging content that would otherwise teleport
47
+ - **Explanation** — demonstrating how something works (marketing/onboarding only)
48
+ - **Delight** — allowed *only* at the rare/first-time tier
49
+
50
+ Can't name it? Don't build it. "It looks cool" on a frequently-seen element is a reason to stop.
51
+
52
+ Also check **function**: data the user is reading or acting on should not move for style. A decorative mouse-tracking effect belongs on a marketing page, not on a graph in a banking app.
53
+
54
+ ### 3. Pick the tool — cheapest that works
55
+
56
+ Walk down; stop at the first that fits.
57
+
58
+ | Need | Tool |
59
+ | --- | --- |
60
+ | Hover, press, color, a state toggle you control with a class or attribute | **CSS transition** |
61
+ | Entry animation on mount, no JS state | **CSS `@starting-style`** |
62
+ | Predetermined motion that must stay smooth while the page is busy loading | **CSS animation** (runs off the main thread) |
63
+ | Motion tied to scroll position, no library | **CSS scroll-driven animation** (`animation-timeline: view()` / `scroll()`), with an `IntersectionObserver` fallback |
64
+ | Page navigation, or one element morphing into another across a state change | **View Transitions API** (`document.startViewTransition`, `view-transition-name`) |
65
+ | Programmatic control with CSS performance, no library | **WAAPI** (`element.animate()`) |
66
+ | Springs, layout animations, exit animations, gesture-driven values | **Motion** (`motion.dev`) |
67
+
68
+ CSS animations beat JS under load — they run off the main thread, while `requestAnimationFrame`-based animation drops frames while the browser loads, scripts, or paints. Use CSS for predetermined motion, JS for dynamic and interruptible motion.
69
+
70
+ If the task needs a *component* rather than an animation — a toast, a drawer, a command menu, a dropdown — stop and consult [libraries.md](libraries.md). Hand-rolling those is how you end up with a `<div>` dropdown and no focus management.
71
+
72
+ ### 4. Pick the properties
73
+
74
+ - **`transform` and `opacity` only.** They skip layout and paint and run on the GPU. `width`/`height`/`margin`/`padding`/`top`/`left` trigger all three. (`clip-path` is the sanctioned fourth — see the recipes. `height` is tolerated only for accordions, where there's no transform equivalent.)
75
+ - **Never `scale(0)`.** Start from `scale(0.9–0.97)` + `opacity: 0`. Nothing in the real world appears from nothing.
76
+ - **`transform-origin` at the trigger** for popovers, dropdowns, menus, tooltips — `var(--transform-origin)` in Base UI. **Modals are exempt**; they're not anchored to a trigger, so they stay centered.
77
+ - **Percentages in `translate()`** are relative to the element's own size — `translateY(100%)` moves by its own height whatever the content. Prefer over hardcoded pixels.
78
+ - **`scale()` scales children too** — the label and icons come along, which is what makes press feedback read as physical. That's a feature.
79
+ - **In Motion, use the full transform string.** `x`/`y`/`scale` shorthands are not hardware-accelerated and drop frames under load:
80
+
81
+ ```jsx
82
+ <motion.div animate={{ x: 100 }} /> // drops frames under load
83
+ <motion.div animate={{ transform: "translateX(100px)" }} /> // hardware accelerated
84
+ ```
85
+
86
+ - **Never drive a child's transform from a CSS variable on the parent** — it recalculates styles for every child. Set `transform` on the element directly.
87
+ - **`will-change` is a scalpel, not a seasoning.** It permanently promotes a layer; applied broadly it exhausts memory and makes things slower.
88
+
89
+ ### 5. Easing and duration — or a spring
90
+
91
+ **Easing**, in decision order:
92
+
93
+ | Situation | Easing |
94
+ | --- | --- |
95
+ | Entering or exiting | `ease-out` |
96
+ | Moving / morphing on screen | `ease-in-out` |
97
+ | Hover / color change | `ease` |
98
+ | Constant motion (marquee, progress) | `linear` |
99
+ | Default | `ease-out` |
100
+
101
+ **Never `ease-in` on UI.** It starts slow, delaying the exact moment the user is watching. `ease-out` at 200ms *feels* faster than `ease-in` at 200ms.
102
+
103
+ Built-in CSS easings are too weak. Use these:
104
+
105
+ ```css
106
+ --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* strong ease-out for UI */
107
+ --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* strong ease-in-out for on-screen movement */
108
+ --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); /* iOS-like drawer curve (Ionic) */
109
+ ```
110
+
111
+ Need a curve that isn't here? Take it from [easing.dev](https://easing.dev/) or [easings.co](https://easings.co/). Don't hand-roll one. (Award-level marketing work uses stronger expo/quart curves — those live in [animation-patterns.md](animation-patterns.md) and are for immersive pages, not everyday UI.)
112
+
113
+ **Duration:**
114
+
115
+ | Element | Duration |
116
+ | --- | --- |
117
+ | Button press feedback | 100–160ms |
118
+ | Tooltips, small popovers | 125–200ms |
119
+ | Dropdowns, selects | 150–250ms |
120
+ | Modals, drawers | 200–500ms |
121
+ | Marketing / explanatory | Can be longer |
122
+
123
+ **UI animations stay under 300ms.** A 180ms dropdown feels more responsive than a 400ms one. Two rules that modulate the table:
124
+
125
+ - **Exits are faster than entrances**, usually by about a third. The user has already decided to leave; making them watch is holding a door closed.
126
+ - **Distance changes duration.** The same 200ms feels snappy across 20px and sluggish across 600px. Scale duration with travel, not with importance.
127
+
128
+ **Perceived performance** is part of the craft: a fast-spinning spinner makes loading feel faster at identical load time; instant tooltips after the first one is open (skip delay + skip animation) make a whole toolbar feel faster. The perception of speed matters as much as actual speed, and `ease-out` amplifies it because the user sees immediate movement.
129
+
130
+ **Reach for a spring instead** when the motion is drag with momentum, an element that should feel alive, a gesture the user can interrupt or reverse, or decorative mouse-tracking:
131
+
132
+ ```js
133
+ { type: "spring", duration: 0.5, bounce: 0.2 } // Apple-style — easier to reason about
134
+ { type: "spring", mass: 1, stiffness: 100, damping: 10 } // traditional physics — more control
135
+ ```
136
+
137
+ Keep bounce at 0.1–0.3, and avoid bounce in most UI — reserve it for drag-to-dismiss and playful interactions. Overshoot on a menu that faded in feels wrong; overshoot on a card the user flicked feels right. For mouse-tracking, interpolate through `useSpring` rather than tying the value directly to the pointer — direct coupling feels artificial because it has no momentum. Velocity handoff, momentum projection, and rubber-banding live in [apple-fluid.md](apple-fluid.md).
138
+
139
+ ### 6. Interruption and exit
140
+
141
+ The most common animation bug is not visual — it is that the animation ignores the user.
142
+
143
+ - **Transitions, not keyframes, for anything triggered rapidly** — toasts, toggles, anything a user can fire twice in a second. Transitions retarget from the current value; keyframes restart from zero.
144
+ - **Springs for gestures**, because they carry velocity through an interruption.
145
+ - **Reversing mid-flight starts from the current position**, never snap-to-end-then-play-backwards. A menu closed halfway through opening closes from where it is.
146
+ - **Never block input while animating.** A 300ms modal transition that swallows clicks makes fast users feel the interface is broken — and fast users are the ones who use it most.
147
+ - **Never queue.** If state changed three times, animate to the third — do not play three animations in sequence.
148
+ - **Exit the way it entered.** A toast that slides in from the bottom leaves through the bottom. Symmetric paths are what make swipe-to-dismiss feel obvious.
149
+ - **Asymmetric timing where the user is deciding.** Slow on the deliberate phase (a hold-to-confirm press: 2s linear), snappy on the system response (release: 200ms ease-out).
150
+
151
+ ### 7. Reduced motion and pointer gating
152
+
153
+ Ships with the animation, every time.
154
+
155
+ ```css
156
+ @media (prefers-reduced-motion: reduce) {
157
+ .element { animation: fade 0.2s ease; } /* keep opacity/color, drop transform-based motion */
158
+ }
159
+
160
+ @media (hover: hover) and (pointer: fine) {
161
+ .element:hover { transform: scale(1.05); } /* touch fires false hovers on tap */
162
+ }
163
+ ```
164
+
165
+ ```jsx
166
+ const reduce = useReducedMotion();
167
+ const closedX = reduce ? 0 : '-100%';
168
+ ```
169
+
170
+ Motion is an accessibility surface, not a style preference:
171
+
172
+ - **Reduced motion means fewer and gentler animations, not zero.** Replace a slide with a fade; keep transitions that aid comprehension, remove movement and position changes. Removing all feedback makes state changes invisible — that's a different failure, not a fix.
173
+ - **Nothing critical may depend on motion being seen.** If the only signal that a message sent is an animation, it did not communicate to anyone using a screen reader.
174
+ - **Never animate anything that flashes more than three times a second.** That is a seizure risk, not a style choice.
175
+ - Large moving surfaces and parallax are the nausea triggers — for people with vestibular disorders this is a health issue, not a preference.
176
+
177
+ ## Cohesion — motion has a personality
178
+
179
+ Match the motion to the component's and the product's mood. Sonner reads as elegant partly because its motion is tuned to the component's personality — slightly slower than typical UI, `ease` rather than `ease-out`. A playful consumer app can be bouncier; a professional dashboard stays crisp and fast. One bouncy component in a crisp app is a defect even when its values are individually correct.
180
+
181
+ Two places where there is no formula and you tune by eye: the opacity/height balance when items enter or leave a list, and any crossfade between two visible states. For the second, a subtle `filter: blur(2px)` during the transition blends two overlapping states into one perceived transformation — keep it under 20px; heavy blur is expensive, especially in Safari.
182
+
183
+ ## Debugging feel
184
+
185
+ When an animation is mechanically correct but feels wrong:
186
+
187
+ - **Slow motion.** Play at 2–5× duration or slow playback in the DevTools Animations panel. Look for: two states visibly overlapping in a crossfade, easing that stops abruptly, a wrong `transform-origin`, coordinated properties out of sync.
188
+ - **Frame by frame.** Step through in the Animations panel — timing drift between coordinated properties is invisible at full speed.
189
+ - **Real devices for gestures.** Connect a phone, hit the dev server by IP, use remote devtools. Simulators hide exactly the jank you're looking for.
190
+ - **Fresh eyes the next day.** Imperfections invisible during development surface later. Budget for it.
191
+
192
+ ## Never Ship
193
+
194
+ Self-check before you finish. Each of these is an automatic block in review mode ([review-audit.md](review-audit.md)):
195
+
196
+ | Never | Instead |
197
+ | --- | --- |
198
+ | `transition: all` | Name the exact properties |
199
+ | `transform: scale(0)` entrance | `scale(0.95)` + `opacity: 0` |
200
+ | `ease-in` on a UI element | `ease-out` or a strong custom curve |
201
+ | Built-in `ease-out` on a deliberate animation | `cubic-bezier(0.23, 1, 0.32, 1)` |
202
+ | Animation on a keyboard shortcut or 100+/day action | No animation |
203
+ | UI duration over 300ms with no reason | 150–250ms |
204
+ | `transform-origin: center` on a trigger-anchored popover | `var(--transform-origin)` (modals exempt) |
205
+ | Keyframes on toasts, toggles, rapidly-triggered elements | CSS transitions |
206
+ | Animating `width`/`height`/`margin`/`padding`/`top`/`left` | `transform` / `opacity` |
207
+ | Motion `x`/`y`/`scale` props under load | Full `transform` string |
208
+ | Driving a child's transform via a parent CSS variable | `element.style.transform` directly |
209
+ | Ungated `:hover` motion | `@media (hover: hover) and (pointer: fine)` |
210
+ | Missing `prefers-reduced-motion` | Gentler variant, not zero |
211
+ | Everything entering at once | 30–80ms stagger (decorative — never blocks input) |
212
+ | Symmetric timing on press-and-release / hold interactions | Slow the deliberate phase, snap the response |
213
+
214
+ ## Output
215
+
216
+ Write the code. Then, in at most a few lines:
217
+
218
+ - **The gate result** — frequency tier and the named purpose. If something in the request was rejected, say which and why.
219
+ - **The ingredients** — tool, properties, curve, duration or spring config, in one line each.
220
+ - **What to feel-check** — if the result depends on feel you can't judge from code (a crossfade, a spring's bounce, the opacity/height balance in an entering list), say so and point at the check from *Debugging feel* above.
221
+
222
+ Don't pad this into a report. The code is the deliverable. When the honest answer is "this shouldn't animate," give it — that answer is the reason this doctrine exists.
@@ -0,0 +1,197 @@
1
+ # The Picker
2
+
3
+ The picker's appearance is **not a design decision** — it is this spec. Copy the markup, CSS, and wiring below verbatim; the only values that change per run are the variant names and count. It stays identical across every project so it always reads as harness chrome, never as part of the design being judged. Do not restyle it with the project's tokens, fonts, or colors.
4
+
5
+ It is a floating dark pill, bottom-center. Dark glass works on top of any page — light or dark — which is why it is not theme-aware.
6
+
7
+ ## Markup
8
+
9
+ The sliding highlight span first, one button per variant, a hairline divider, then the replay button (only when at least one variant has motion to re-trigger):
10
+
11
+ ```html
12
+ <nav class="proto-picker" aria-label="Prototype variants">
13
+ <span class="proto-picker-highlight" aria-hidden="true"></span>
14
+ <button class="proto-picker-item" data-active aria-current="true">Quiet</button>
15
+ <button class="proto-picker-item">Editorial</button>
16
+ <button class="proto-picker-item">Playful</button>
17
+ <span class="proto-picker-divider" aria-hidden="true"></span>
18
+ <button class="proto-picker-item proto-picker-replay" aria-label="Replay animation (R)">↻</button>
19
+ </nav>
20
+ ```
21
+
22
+ In a framework, keep the class names and structure; only the rendering syntax changes.
23
+
24
+ ## Styles
25
+
26
+ ```css
27
+ .proto-picker {
28
+ position: fixed;
29
+ bottom: 24px;
30
+ left: 50%;
31
+ transform: translateX(-50%);
32
+ z-index: 2147483647;
33
+ display: flex;
34
+ align-items: center;
35
+ gap: 2px;
36
+ padding: 4px;
37
+ border-radius: 999px;
38
+ background: rgba(10, 10, 10, 0.82);
39
+ -webkit-backdrop-filter: blur(12px) saturate(1.4);
40
+ backdrop-filter: blur(12px) saturate(1.4);
41
+ box-shadow:
42
+ 0 0 0 1px rgba(255, 255, 255, 0.08) inset,
43
+ 0 8px 24px rgba(0, 0, 0, 0.24),
44
+ 0 2px 6px rgba(0, 0, 0, 0.12);
45
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
46
+ font-size: 13px;
47
+ line-height: 1;
48
+ -webkit-font-smoothing: antialiased;
49
+ user-select: none;
50
+ -webkit-user-select: none;
51
+ }
52
+
53
+ .proto-picker-highlight {
54
+ position: absolute;
55
+ top: 4px;
56
+ left: 0;
57
+ height: 28px;
58
+ border-radius: 999px;
59
+ background: rgba(255, 255, 255, 0.12);
60
+ will-change: transform;
61
+ }
62
+
63
+ /* The slide is enabled only after first paint (data-ready), so load doesn't animate. */
64
+ .proto-picker[data-ready] .proto-picker-highlight {
65
+ transition:
66
+ transform 250ms cubic-bezier(0.23, 1, 0.32, 1),
67
+ width 250ms cubic-bezier(0.23, 1, 0.32, 1);
68
+ }
69
+
70
+ @media (prefers-reduced-motion: reduce) {
71
+ .proto-picker[data-ready] .proto-picker-highlight { transition: none; }
72
+ }
73
+
74
+ .proto-picker-item {
75
+ position: relative; /* sits above the highlight */
76
+ display: flex;
77
+ align-items: center;
78
+ height: 28px;
79
+ padding: 0 12px;
80
+ border: 0;
81
+ border-radius: 999px;
82
+ background: transparent;
83
+ color: rgba(255, 255, 255, 0.55);
84
+ font: inherit;
85
+ cursor: pointer;
86
+ transition: color 150ms ease-out;
87
+ }
88
+
89
+ .proto-picker-item:hover {
90
+ color: rgba(255, 255, 255, 0.85);
91
+ }
92
+
93
+ .proto-picker-item:active {
94
+ transform: scale(0.97);
95
+ }
96
+
97
+ .proto-picker-item:focus-visible {
98
+ outline: 2px solid rgba(255, 255, 255, 0.4);
99
+ outline-offset: 2px;
100
+ }
101
+
102
+ .proto-picker-item[data-active] {
103
+ color: #fff;
104
+ }
105
+
106
+ .proto-picker-divider {
107
+ width: 1px;
108
+ height: 16px;
109
+ margin: 0 4px;
110
+ background: rgba(255, 255, 255, 0.12);
111
+ }
112
+
113
+ .proto-picker-replay {
114
+ padding: 0 10px;
115
+ font-size: 14px;
116
+ }
117
+
118
+ .proto-picker[data-position="top"] {
119
+ bottom: auto;
120
+ top: 24px;
121
+ }
122
+ ```
123
+
124
+ ## Rules
125
+
126
+ - **Verbatim.** These values are the spec. No project fonts, no brand colors, no theme switching, no extra shadows or borders.
127
+ - **The highlight slides; the variant swap stays instant.** The active pill animates between buttons (250ms, strong ease-out) as spatial feedback on the picker itself — but the variant being previewed still switches with no transition. The `width` transition is a deliberate exception to the transform/opacity rule: the element is 28px tall, absolutely positioned, and has no layout dependents, so the paint cost is negligible.
128
+ - **One allowed modification:** if a variant occupies the bottom-center of the screen (a toast stack, a bottom sheet, a dock), set `data-position="top"` so the picker never covers the work. Nothing else about it may move or change.
129
+ - **Replay is conditional.** Render the replay button and its divider only when at least one variant has an entrance or state animation worth re-triggering; a static comparison gets a shorter pill.
130
+
131
+ ## Behavior contract
132
+
133
+ The contract is fixed regardless of how the harness renders:
134
+
135
+ - Number keys `1–N` and `←`/`→` switch variants; `R` replays. Ignore key events when focus is in an input, textarea, select, or contenteditable, or when a modifier is held.
136
+ - Clicking an item switches to it; exactly one item carries `data-active` and `aria-current="true"` at all times, and the highlight slides to it.
137
+ - Selection persists across reload via a URL param (`?v=2`), falling back to variant 1. The highlight takes its initial position without animating (`data-ready` is added after first paint).
138
+ - Switching re-mounts the variant (so entrance animations re-run); the replay key re-mounts without switching.
139
+
140
+ ## Reference wiring
141
+
142
+ Verbatim for the standalone-HTML branch; in a framework, keep the same behavior but express it idiomatically (state instead of `innerHTML`, a keyed re-mount instead of `requestAnimationFrame`, refs + a layout effect for the highlight measurement).
143
+
144
+ ```js
145
+ // `variants` is an array of render functions, one per variant, in picker order.
146
+ const stage = document.getElementById('stage');
147
+ const picker = document.querySelector('.proto-picker');
148
+ const highlight = picker.querySelector('.proto-picker-highlight');
149
+ const items = [...picker.querySelectorAll('.proto-picker-item:not(.proto-picker-replay)')];
150
+ const replay = picker.querySelector('.proto-picker-replay');
151
+ let current = 0;
152
+
153
+ function moveHighlight() {
154
+ const el = items[current];
155
+ highlight.style.width = el.offsetWidth + 'px';
156
+ highlight.style.transform = `translateX(${el.offsetLeft}px)`;
157
+ }
158
+
159
+ function mount(i) {
160
+ stage.innerHTML = '';
161
+ // Clear first, render next frame, so entrance animations re-run.
162
+ requestAnimationFrame(() => { stage.innerHTML = variants[i](); });
163
+ }
164
+
165
+ function setActive(i) {
166
+ if (i < 0 || i >= variants.length) return;
167
+ current = i;
168
+ items.forEach((el, j) => {
169
+ el.toggleAttribute('data-active', j === i);
170
+ if (j === i) el.setAttribute('aria-current', 'true');
171
+ else el.removeAttribute('aria-current');
172
+ });
173
+ moveHighlight();
174
+ const url = new URL(location);
175
+ url.searchParams.set('v', i + 1);
176
+ history.replaceState(null, '', url);
177
+ mount(i);
178
+ }
179
+
180
+ items.forEach((el, i) => el.addEventListener('click', () => setActive(i)));
181
+ replay?.addEventListener('click', () => mount(current));
182
+ window.addEventListener('resize', moveHighlight);
183
+
184
+ document.addEventListener('keydown', (e) => {
185
+ if (/^(INPUT|TEXTAREA|SELECT)$/.test(e.target.tagName) || e.target.isContentEditable) return;
186
+ if (e.metaKey || e.ctrlKey || e.altKey) return;
187
+ const num = parseInt(e.key, 10);
188
+ if (num >= 1 && num <= variants.length) setActive(num - 1);
189
+ else if (e.key === 'ArrowRight') setActive((current + 1) % variants.length);
190
+ else if (e.key === 'ArrowLeft') setActive((current - 1 + variants.length) % variants.length);
191
+ else if (e.key === 'r' || e.key === 'R') mount(current);
192
+ });
193
+
194
+ setActive((parseInt(new URLSearchParams(location.search).get('v'), 10) || 1) - 1);
195
+ // Enable the slide only after first paint, so load doesn't animate.
196
+ requestAnimationFrame(() => requestAnimationFrame(() => picker.setAttribute('data-ready', '')));
197
+ ```
@@ -0,0 +1,73 @@
1
+ # Plan Template
2
+
3
+ Every plan written in audit mode ([review-audit.md](review-audit.md)) follows this structure. The executor may be a less capable model with zero context and zero taste — the plan must contain everything, exactly. No references to "the audit above" or "the easing we discussed."
4
+
5
+ ```markdown
6
+ # NNN — <Short imperative title>
7
+
8
+ - **Status**: TODO
9
+ - **Commit**: <output of `git rev-parse --short HEAD` when this plan was written>
10
+ - **Severity**: HIGH | MEDIUM | LOW
11
+ - **Category**: <audit category>
12
+ - **Estimated scope**: <n files, rough size>
13
+
14
+ ## Problem
15
+
16
+ What is wrong, where, and why it matters to how the product feels. Cite every
17
+ location as `path/to/file.tsx:123` and include the current code verbatim:
18
+
19
+ ​```css
20
+ /* src/components/dropdown.css:14 — current */
21
+ .dropdown { transition: all 400ms ease-in; }
22
+ ​```
23
+
24
+ ## Target
25
+
26
+ The exact end state. Every value spelled out — curves, durations, spring
27
+ configs, media queries. Never "use a nicer easing":
28
+
29
+ ​```css
30
+ /* target */
31
+ .dropdown {
32
+ transition: transform 200ms var(--ease-out), opacity 200ms var(--ease-out);
33
+ transform-origin: var(--transform-origin);
34
+ }
35
+ ​```
36
+
37
+ ## Repo conventions to follow
38
+
39
+ How this codebase already does it, with one exemplar the executor should
40
+ imitate (token names, file placement, prop patterns):
41
+
42
+ - Easing tokens live in `src/styles/tokens.css`; add new curves there, e.g. `--ease-out: cubic-bezier(0.23, 1, 0.32, 1);`
43
+ - <exemplar file:line that already does this correctly>
44
+
45
+ ## Steps
46
+
47
+ 1. <One concrete edit per step: file, what changes, resulting code.>
48
+ 2. …
49
+
50
+ ## Boundaries
51
+
52
+ - Do NOT touch <files/components out of scope>.
53
+ - Do NOT change markup/structure — motion properties only (unless a step says otherwise).
54
+ - Do NOT add new dependencies.
55
+ - If a step doesn't match the code you find (drift since the commit stamp), STOP and report instead of improvising.
56
+
57
+ ## Verification
58
+
59
+ - **Mechanical**: <exact commands — typecheck, lint, build — with expected outcome>.
60
+ - **Feel check**: run the UI, trigger <interaction>, and confirm:
61
+ - <observable check, e.g. "the dropdown scales from its trigger, not from center">
62
+ - <e.g. "spamming the toggle never restarts the animation from zero">
63
+ - In DevTools, set playback to 10% (Animations panel) and confirm <detail>.
64
+ - Toggle `prefers-reduced-motion` (Rendering panel) and confirm movement is dropped but opacity feedback remains.
65
+ - **Done when**: <machine- or eye-checkable completion criteria>.
66
+ ```
67
+
68
+ ## Notes for the plan author
69
+
70
+ - One plan per finding. If two findings share every file and the same fix pattern (e.g. the same easing token swap across components), they may merge into one plan.
71
+ - Pull every value from [motion.md](motion.md) — never approximate from memory.
72
+ - The feel check is not optional. Motion can be mechanically correct and still feel wrong; give the executor (or the human reviewing the executor's diff) concrete things to watch for in slow motion.
73
+ - After writing plans, create or update `plans/README.md` with: a table of plans (number, title, severity, status), the recommended execution order, and any dependencies between plans.
@@ -0,0 +1,85 @@
1
+
2
+ # Prototyping Variants
3
+
4
+ A divergence skill. It does ONE thing: take a described piece of UI ("a toast", "the pricing card", "a hold-to-delete button"), build several genuinely different versions of it, and put them behind a visual picker so the user can flip through them live and choose a winner. It does not review existing UI (that is review mode in [review-audit.md](review-audit.md)), plan fixes for it (audit mode, same file), or choose dependencies (that is [libraries.md](libraries.md)).
5
+
6
+ ## Operating Posture
7
+
8
+ You are a senior design engineer running a design exploration. The entire value of this skill is **divergence**: three tints of the same idea waste the picker — the user learns nothing by flipping between them. Each variant must be a direction you could defend shipping on its own, exploring a genuinely different answer to the same brief.
9
+
10
+ Divergence is not an excuse to drop the craft bar. Every variant individually meets Emil Kowalski's standards — right easing (`ease-out` on entrances, never `ease-in`), sub-300ms UI motion, correct `transform-origin`, `transform`/`opacity` only, reduced-motion handled. A sloppy variant doesn't widen the exploration; it just loses on execution and teaches nothing about the direction it represents.
11
+
12
+ ## Hard Rules
13
+
14
+ 1. **Never touch production code during exploration.** Everything lives in an isolated prototype surface (see Phase 4). Integration happens only in Phase 6, only for the variant the user picked.
15
+ 2. **Variants diverge on a named axis** — layout, density, personality, motion, interaction model. Before building, you must be able to state each variant's axis in a phrase. Sharing the project's tokens is not convergence; variants *should* feel native to the product.
16
+ 3. **Every variant fully works.** Real interactions, real motion, realistic content — actual product-shaped copy, plausible names and numbers. No lorem ipsum, no dead buttons, no "imagine this part".
17
+ 4. **The picker is chrome, not a contestant.** Its exact markup, styles, and behavior are specified in [picker.md](picker.md) — copy them verbatim. Its look is not a design decision and never adapts to the project.
18
+ 5. **Clean up after the choice.** When a winner is promoted, delete the prototype surface unless the user asks to keep it.
19
+
20
+ ## Workflow
21
+
22
+ ### Phase 1 — Scope
23
+
24
+ One thing per run. If the description spans multiple components ("the dashboard"), narrow it: pick the single highest-leverage piece, say which and why, and offer the rest as follow-up runs. Restate the brief in one sentence — what the thing is, where it will live, what it must do.
25
+
26
+ ### Phase 2 — Recon
27
+
28
+ Before designing anything, map the ground the variants must stand on:
29
+
30
+ - **Stack**: framework, styling system (Tailwind, CSS modules, vanilla), motion library if any.
31
+ - **Tokens**: colors, radii, spacing, fonts, easing/duration variables. Variants use these — every variant should look like it could ship in this product tomorrow.
32
+ - **Personality**: playful consumer app or crisp dashboard? This bounds how far the boldest variant may go.
33
+ - **Context**: where the piece renders — against what background, beside what neighbors, at what sizes.
34
+
35
+ If there is no project (empty directory, or the user is just exploring), skip to the standalone branch in Phase 4 and choose a restrained default look: neutral grays, one accent, system font stack.
36
+
37
+ ### Phase 3 — Choose directions
38
+
39
+ Default **3 variants**; up to 5 when the user asks or the design space is genuinely wide. More than 5 dilutes the comparison.
40
+
41
+ Before writing any code, list the set: a name and an axis for each. Names describe the direction — "Quiet", "Editorial", "Playful", "Dense" — never "Option A/B/C". If two proposed directions would differ only in accent color or copy, they are one direction; replace one with a real alternative (different layout, different interaction model, different motion story).
42
+
43
+ **Completion criterion:** every variant has a name and a stated axis, and no two variants share an axis position.
44
+
45
+ ### Phase 4 — Build the picker harness
46
+
47
+ Two branches, by what exists:
48
+
49
+ - **In a project with a dev server** — an isolated route or page (`/prototypes/<slug>`, or the framework's equivalent), one file per variant plus a small harness file. Nothing imports from the prototype surface into production code.
50
+ - **No project / static context** — a single self-contained HTML file (inline CSS/JS) the user can open directly in a browser.
51
+
52
+ The picker's markup, styles, keyboard wiring, and placement come from [picker.md](picker.md), verbatim — load it now and build exactly that. Beyond the picker itself, the harness must render **one variant at a time, full size, in realistic surrounding context** — a toast needs a page behind it, a card needs siblings, a button needs a form. Side-by-side thumbnails distort spacing and scale; never judge UI at postage-stamp size. Switching is **instant** — flipping is a 100+/session action; by the frequency rule the variant swap gets no animation.
53
+
54
+ ### Phase 5 — Verify and hand off
55
+
56
+ Run the harness. Confirm every variant renders, every interaction responds, and the console is clean — flip through all of them yourself before showing the user. If browser tooling is available, screenshot each variant.
57
+
58
+ Then present the set and **stop — the choice belongs to the user**:
59
+
60
+ | # | Variant | Axis | When it's the right choice | Its cost |
61
+ | --- | --- | --- | --- | --- |
62
+ | 1 | Quiet | Minimal motion, borders over shadows | The product is a daily-use tool | Least memorable |
63
+ | 2 | Editorial | Large type, generous whitespace | The moment deserves weight | Eats vertical space |
64
+
65
+ Close with where the picker is running (URL or file path) and the keys to flip.
66
+
67
+ **Completion criterion:** every variant is reachable from the picker and behaves correctly; no console errors; the table names each variant's tradeoff honestly.
68
+
69
+ ### Phase 6 — Promote on selection
70
+
71
+ When the user picks: integrate that variant where it belongs, following the project's existing conventions (file layout, naming, token usage), then delete the prototype surface per Hard Rule 5. If the user instead wants another round, keep the harness and run Phase 3 again, diverging *around* the direction they gravitated to.
72
+
73
+ ## Invocation Variants
74
+
75
+ | Invocation | Behavior |
76
+ | --- | --- |
77
+ | `<description>` | Full workflow: scope → recon → 3 variants → picker → wait for choice |
78
+ | `<description> x5` | Same, with that many variants (capped at 5) |
79
+ | `riff <variant>` | New round: keep the harness, generate a fresh set diverging around the named variant's direction |
80
+ | `keep <variant>` | Promote that variant into the codebase and delete the prototype surface |
81
+ | `keep <variant>, leave the picker` | Promote, but keep the prototype surface around |
82
+
83
+ ## Tone
84
+
85
+ Sell each variant honestly — one line on when it wins, one on what it costs. Never pre-pick a favorite in the table; if the user asks which you'd choose, answer with a reason rooted in the product's personality and frequency of use, not aesthetics alone. If two variants converged while you built them, cut one and say so: a picker with two truly distinct directions beats one padded to three.