@hegemonart/get-design-done 1.43.0 → 1.45.0

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.
@@ -1,6 +1,27 @@
1
- # Motion & Animation Framework
1
+ # Motion - Animation Domain Index
2
2
 
3
- Based on Emil Kowalski's design engineering philosophy. Apply these rules in order - do not skip to "how should this animate" before answering "should this animate."
3
+ Based on Emil Kowalski's design engineering philosophy. Apply these rules in order. Do not skip to "how should this animate" before answering "should this animate."
4
+
5
+ <!-- Phase 45 domain-index: loads this file instead of individual motion fragments -->
6
+
7
+ ---
8
+
9
+ ## Mission
10
+
11
+ Motion governs animation decisions across the UI: whether to animate, duration budgets, easing choices, spring physics, transition taxonomy, and interpolation. Read this file first for the decision framework and core rules, then drill into the specialist fragment below. Does not cover CSS layout transitions (see `spatial.md`) or OS-level reduced-motion policy (see `responsive.md`).
12
+
13
+ ---
14
+
15
+ ## Fragment Index
16
+
17
+ | Fragment | When to load |
18
+ |---|---|
19
+ | `./motion-easings.md` | Choosing or auditing easing curve values: 12 canonical `--ease-*` presets, cubic-bezier equivalents, 60fps settle-times |
20
+ | `./motion-spring.md` | Interaction is draggable or needs physics feel: gentle/wobbly/stiff/slow presets, Framer Motion and React Spring syntax |
21
+ | `./motion-transition-taxonomy.md` | Classifying page or route transitions: 8 families (3d, blur, cover, destruction, dissolve, distortion, grid, light) |
22
+ | `./motion-interpolate.md` | Mapping input-to-output ranges: progress/scroll/gesture/time-linked animations, 4 extrapolation modes |
23
+ | `./motion-advanced.md` | Advanced platform APIs: FLIP, scroll-driven, View Transitions, gesture/drag, clip-path, WAAPI |
24
+ | `./framer-motion-patterns.md` | Codebase uses Framer Motion: spring/tween config, AnimatePresence, variants, gestures, a11y, bounce:0 rule |
4
25
 
5
26
  ---
6
27
 
@@ -12,7 +33,7 @@ Based on Emil Kowalski's design engineering philosophy. Apply these rules in ord
12
33
  |---|---|
13
34
  | 100+/day - keyboard shortcuts, command palette, list navigation | **No animation. Ever.** |
14
35
  | Tens/day - hover states, toggles, tab switching | Remove or keep to <80ms. No delay. |
15
- | Occasional - modals opening, drawers, toasts | Standard animation (150300ms) |
36
+ | Occasional - modals opening, drawers, toasts | Standard animation (150-300ms) |
16
37
  | Rare - onboarding, celebrations, first-time flows | Can add personality and delight |
17
38
  | Once - loading splash, page transitions | Full animation budget |
18
39
 
@@ -25,9 +46,9 @@ Valid animation purposes only. If it doesn't serve one of these, remove it.
25
46
  | Purpose | Example |
26
47
  |---|---|
27
48
  | **Spatial consistency** | Toast enters/exits same edge each time |
28
- | **State indication** | Button morphs to show loading success |
49
+ | **State indication** | Button morphs to show loading to success |
29
50
  | **Cause-effect explanation** | Item deletion - item flies to trash |
30
- | **Feedback** | Button scales 0.97 on press |
51
+ | **Feedback** | Button scales on press |
31
52
  | **Prevent jarring changes** | Content appearing/disappearing needs transition |
32
53
 
33
54
  Invalid purposes: "It looks cool", "It feels modern", "Other apps do it."
@@ -42,44 +63,28 @@ Invalid purposes: "It looks cool", "It feels modern", "Other apps do it."
42
63
  | **Interactive/draggable** | Spring physics | Follows finger/cursor naturally |
43
64
  | **Bounce/elastic** | **Never** | Feels toy-like and dated |
44
65
 
45
- CSS:
46
- ```css
47
- /* Enter */
48
- transition: transform 200ms cubic-bezier(0, 0, 0.2, 1); /* ease-out */
49
-
50
- /* Exit */
51
- transition: transform 150ms cubic-bezier(0.4, 0, 1, 1); /* ease-in */
52
-
53
- /* Transition */
54
- transition: all 200ms cubic-bezier(0.4, 0, 0.2, 1); /* ease-in-out */
55
- ```
66
+ See `reference/motion-easings.md` for the full `--ease-*` token catalog.
56
67
 
57
68
  ### Question 4: What Duration?
58
69
 
59
70
  | Animation type | Duration | Notes |
60
71
  |---|---|---|
61
- | Micro-interactions | 80150ms | Hover, press, toggle |
62
- | Component enter/exit | 150250ms | Modals, drawers, dropdowns |
63
- | Page transitions | 200350ms | Route changes |
64
- | Complex/orchestrated | 400ms | Multi-step, staggered reveals |
72
+ | Micro-interactions | 80-150ms | Hover, press, toggle |
73
+ | Component enter/exit | 150-250ms | Modals, drawers, dropdowns |
74
+ | Page transitions | 200-350ms | Route changes |
75
+ | Complex/orchestrated | <=400ms | Multi-step, staggered reveals |
65
76
  | **Never exceed** | 400ms | Anything longer feels broken |
66
77
 
67
- **Exit faster than enter**: Exit animations should run at **6070%** of the enter duration. Exiting elements should get out of the way fast.
68
-
69
- ```
70
- Enter: 250ms
71
- Exit: 150ms (60% of 250)
72
- ```
78
+ **Exit faster than enter**: Exit animations should run at **60-70%** of the enter duration.
73
79
 
74
80
  ### Question 5: Only Animate `transform` and `opacity`
75
81
 
76
- **Only these properties animate on the GPU:**
77
82
  ```css
78
- /* SAFE */
83
+ /* SAFE - GPU-accelerated */
79
84
  transform: translateX(), translateY(), scale(), rotate()
80
- opacity: 0 1
85
+ opacity: 0 to 1
81
86
 
82
- /* DANGEROUS triggers layout/paint */
87
+ /* DANGEROUS - triggers layout/paint */
83
88
  width, height, top, left, margin, padding, font-size
84
89
  ```
85
90
 
@@ -89,319 +94,73 @@ Exception: `filter` (blur) is GPU-accelerated in modern browsers but battery-exp
89
94
 
90
95
  ## Stagger Rules
91
96
 
92
- When animating a list of items entering:
93
- - Stagger delay: **30–50ms** per item
94
- - Maximum stagger depth: **6–8 items** (items beyond that appear simultaneously)
95
- - Direction: top-to-bottom OR left-to-right - never random
96
-
97
- ```css
98
- .item:nth-child(1) { animation-delay: 0ms; }
99
- .item:nth-child(2) { animation-delay: 40ms; }
100
- .item:nth-child(3) { animation-delay: 80ms; }
101
- /* etc. — cap at ~6 staggered items */
102
- ```
97
+ - Stagger delay: **30-50ms** per item
98
+ - Maximum stagger depth: **6-8 items** (items beyond that appear simultaneously)
99
+ - Direction: top-to-bottom OR left-to-right, never random
103
100
 
104
101
  ---
105
102
 
106
103
  ## Press Feedback
107
104
 
108
- Every clickable element must give visual feedback within **100ms** of interaction.
105
+ Every clickable element must give visual feedback within **100ms** of interaction. The canonical scale value for press feedback is **`0.96`**.
106
+
107
+ - Never use `scale(0.95)` - too large, feels unresponsive
108
+ - Never use `scale(0.97)` or higher - imperceptible at high DPI
109
+ - `0.96` is the correct value for standard interactive elements
109
110
 
110
111
  ```css
111
112
  button:active {
112
- transform: scale(0.97); /* NOT 0.90 — too dramatic */
113
+ transform: scale(0.96);
113
114
  transition: transform 80ms ease-out;
114
115
  }
115
-
116
- /* On release */
117
- button:not(:active) {
118
- transform: scale(1);
119
- transition: transform 150ms ease-out;
120
- }
121
116
  ```
122
117
 
123
- Scale range: **0.95–0.98** for buttons. **0.97** is the safest default.
124
- Never scale below 0.90 - it looks broken.
125
-
126
118
  ---
127
119
 
128
120
  ## `prefers-reduced-motion`
129
121
 
130
- Always respect this. It's not optional.
122
+ Always respect this. It is not optional.
131
123
 
132
124
  ```css
133
125
  @media (prefers-reduced-motion: reduce) {
134
- *,
135
- *::before,
136
- *::after {
126
+ *, *::before, *::after {
137
127
  animation-duration: 0.01ms !important;
138
- animation-iteration-count: 1 !important;
139
128
  transition-duration: 0.01ms !important;
140
129
  scroll-behavior: auto !important;
141
130
  }
142
131
  }
143
132
  ```
144
133
 
145
- Or in JavaScript:
146
- ```js
147
- const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
148
- if (!prefersReduced) {
149
- // Run animation
150
- }
151
- ```
152
-
153
- ---
154
-
155
- ## What Never To Animate
156
-
157
- - Keyboard shortcuts and commands (too frequent)
158
- - Tab switching within a page
159
- - Filter/sort toggles on data tables
160
- - Expanding/collapsing sidebar navigation items during heavy use
161
- - Any interaction the user will perform 50+ times in a session
162
-
163
- ---
164
-
165
- ## The Invisible Detail Rule
166
-
167
- The best animations are ones users cannot describe but notice when absent. Signs of this:
168
- - The interaction feels "snappy" or "responsive" without thinking about why
169
- - Removing the animation makes the UI feel broken
170
- - Users say "it feels premium" but can't point to any specific feature
171
-
172
- This is the goal. Not "look at this animation" - "why does this feel so good to use?"
173
-
174
134
  ---
175
135
 
176
- ## Quick Animation Audit Checklist
136
+ ## Quick Audit Checklist
177
137
 
178
138
  - [ ] No animation on keyboard-triggered actions
179
- - [ ] All durations 400ms
139
+ - [ ] All durations <=400ms
180
140
  - [ ] Exit < enter duration
181
141
  - [ ] Only `transform` and `opacity` for performance
182
142
  - [ ] `prefers-reduced-motion` implemented
183
- - [ ] Stagger 50ms per item, capped at 68 items
143
+ - [ ] Stagger <=50ms per item, capped at 6-8 items
184
144
  - [ ] Press feedback on all interactive elements
185
145
  - [ ] No bounce/elastic easing anywhere
186
146
  - [ ] All animations have a defined purpose
187
147
 
188
148
  ---
189
149
 
190
- ## Spring Physics
191
-
192
- Spring-based animation replaces duration-based tweening with physics parameters
193
- (stiffness, damping, mass). Output feels more organic and adapts to interruption.
194
-
195
- ### React Spring
196
-
197
- ```jsx
198
- import { useSpring, animated } from '@react-spring/web';
199
-
200
- const styles = useSpring({
201
- from: { opacity: 0, transform: 'translateY(20px)' },
202
- to: { opacity: 1, transform: 'translateY(0px)' },
203
- config: { tension: 170, friction: 26 } // default preset
204
- });
205
- ```
206
-
207
- React Spring presets:
208
-
209
- | Preset | tension | friction | Character |
210
- |--------|---------|----------|-----------|
211
- | default | 170 | 26 | balanced |
212
- | gentle | 120 | 14 | smooth, leisurely |
213
- | wobbly | 180 | 12 | playful bounce |
214
- | stiff | 210 | 20 | snappy |
215
- | slow | 280 | 60 | slow and deliberate |
216
- | molasses | 280 | 120 | very slow, no bounce |
217
-
218
- ### Framer Motion
219
-
220
- ```jsx
221
- <motion.div
222
- animate={{ x: 100 }}
223
- transition={{ type: "spring", stiffness: 100, damping: 15, mass: 1 }}
224
- />
225
- ```
226
-
227
- Parameter guidance:
228
-
229
- | Param | Range | Effect |
230
- |-------|-------|--------|
231
- | stiffness | 50–300 | higher = snappier arrival |
232
- | damping | 10–40 | higher = less oscillation |
233
- | mass | 0.5–2 | higher = more inertia, slower response |
234
-
235
- Rule of thumb: for UI micro-interactions use stiffness 150–250, damping 20–30, mass 1.
236
-
237
- ---
238
-
239
- ## Scroll-Triggered Animations
240
-
241
- Use IntersectionObserver for scroll-reveal effects - it replaces scroll-event
242
- listeners with a throttled browser-native API.
243
-
244
- ### Basic pattern
245
-
246
- ```js
247
- const observer = new IntersectionObserver((entries) => {
248
- entries.forEach(entry => {
249
- if (entry.isIntersecting) {
250
- entry.target.classList.add('in-view');
251
- // Optional: disconnect after first trigger
252
- // observer.unobserve(entry.target);
253
- }
254
- });
255
- }, {
256
- threshold: 0.1,
257
- rootMargin: '0px 0px -100px 0px' // trigger 100px before entering viewport bottom
258
- });
259
-
260
- document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
261
- ```
262
-
263
- ### Threshold guidance
264
-
265
- | threshold | Meaning |
266
- |-----------|---------|
267
- | 0.0 | element enters viewport edge |
268
- | 0.1–0.25 | element partially visible (most common for reveals) |
269
- | 0.5 | element half-visible |
270
- | 1.0 | element fully visible |
271
-
272
- ### Once vs repeat
273
-
274
- - **Once** - call `observer.unobserve(entry.target)` after first intersection.
275
- Use for: hero reveals, one-shot entrance animations, stat counters.
276
- - **Repeat** - leave observer active. Use for: progress indicators, parallax effects,
277
- sticky nav state changes.
278
-
279
- ### Performance rules
280
-
281
- 1. Animate only `transform` and `opacity` (GPU-accelerated). Avoid `top`, `left`, `width`, `height`.
282
- 2. No debounce/throttle needed - IntersectionObserver is already throttled by the browser.
283
- 3. For many elements, share a single observer instance and call `observe()` once per element.
284
- 4. Prefer CSS transitions triggered by a class toggle over requestAnimationFrame loops.
285
- 5. Use `will-change: transform, opacity` sparingly (only on elements that animate repeatedly).
286
-
287
- ---
288
-
289
- ## MIFB Micro-Motion Extensions
290
- Source: jakubkrehel/make-interfaces-feel-better (MIT) - motion.md
291
-
292
- ### Interruptible Animations
293
-
294
- Use CSS transitions for interactive elements because transitions retarget mid-animation - when a user moves their cursor away before a hover animation completes, the transition reverses smoothly from wherever it currently is. Keyframe animations restart from the beginning, creating a jarring jump.
295
-
296
- **Decision rule:**
297
- - Interactive states (hover, focus, active, pressed): always CSS transitions
298
- - Orchestrated sequences, entrance effects, data-driven animations: keyframe or JS animation
299
-
300
- ```css
301
- /* Good — transition retargets smoothly */
302
- .button { transition: background-color 150ms ease-out; }
303
-
304
- /* Avoid for interactive — restarts on interruption */
305
- .button:hover { animation: hover-bg 150ms ease-out forwards; }
306
- ```
307
-
308
- ### Split-and-Stagger Enter/Exit
309
-
310
- For multi-element entrances (card grids, lists, feature sections):
311
-
312
- - Default stagger: 100ms between elements
313
- - Heading words: 80ms per word
314
- - Entrance transform: `opacity: 0 → 1` + `translateY(12px → 0)` + `blur(4px → 0)`
315
- - Entrance duration: 300ms, `ease-out`
316
- - Exit transform: `opacity: 1 → 0` + `translateY(0 → -12px)` (opposite direction, smaller offset)
317
- - Exit duration: 150ms (half the entrance duration - exits should be faster)
318
-
319
- The blur component adds a depth cue that makes entrances feel less flat. Keep blur modest (4px) - the goal is a subtle focus effect, not a visible blur.
320
-
321
- ### Contextual Icon Animations - Cross-Fade Pattern
322
-
323
- When swapping two icons (e.g., play ↔ pause, chevron-up ↔ chevron-down, bookmark ↔ bookmarked), use this exact cross-fade spec:
324
-
325
- **Framer Motion spring (preferred):**
326
- - `scale: 0.25 → 1` (entering), `scale: 1 → 0.25` (exiting)
327
- - `opacity: 0 → 1` (entering), `opacity: 1 → 0` (exiting)
328
- - `filter: blur(4px) → blur(0)` (entering), `blur(0) → blur(4px)` (exiting)
329
- - `transition: { type: "spring", duration: 0.3, bounce: 0 }` - **bounce MUST be 0**
150
+ ## Rules of Thumb
330
151
 
331
- **CSS fallback (no Framer):**
332
- - Keep both icons in the DOM, one `position: absolute`
333
- - Use `cubic-bezier(0.2, 0, 0, 1)` easing
334
- - Duration: 200ms
335
-
336
- The scale + blur combination creates a focus-snap effect that feels intentional rather than mechanical. The `bounce: 0` hard constraint exists because any bounce on a 0.25-scale origin point makes icons appear to "pop" invasively.
337
-
338
- ### Scale on Press - Canonical Value
339
-
340
- The canonical scale value for press feedback is **`0.96`**.
341
-
342
- Rules:
343
- - Never use `scale(0.95)` - too large, feels unresponsive
344
- - Never use `scale(0.97)` - too subtle at high DPI, not perceived as feedback
345
- - Never use `scale(0.98)` or higher - imperceptible
346
- - `0.96` is the ONLY correct value for standard interactive elements
347
-
348
- Tailwind: `active:scale-[0.96]`
349
- Framer: `whileTap={{ scale: 0.96 }}`
350
-
351
- For primary CTAs where maximum tactility is needed (purchase, send, confirm):
352
- use `0.96` with a shadow reduction: `box-shadow: none` during press.
353
-
354
- Deprecation note: earlier versions of `reference/checklists.md` referenced `scale(0.97)`. That entry has been reconciled. **0.96 is the canonical value.**
355
-
356
- ### AnimatePresence initial={false}
357
-
358
- When `AnimatePresence` wraps UI that exists in the DOM before it enters the animation scope (e.g., a tab panel that renders its first tab immediately, a dropdown that's already open on first load), use `initial={false}`:
359
-
360
- ```tsx
361
- <AnimatePresence initial={false}>
362
- {isOpen && <motion.div key="panel" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} />}
363
- </AnimatePresence>
364
- ```
365
-
366
- Without `initial={false}`, Framer will animate the FIRST render of children - meaning UI that's immediately visible on page load will "fade in" unnecessarily. This creates a flash/flicker that signals poor craftsmanship.
367
-
368
- **Rule:** Any `AnimatePresence` wrapping persistent UI should have `initial={false}`.
369
-
370
- ### will-change - GPU Property Table
371
-
372
- Only add `will-change` when you observe first-frame stutter on lower-end hardware. Do NOT add it preemptively - it consumes GPU memory continuously for every element that has it.
373
-
374
- GPU-compositable properties (safe with will-change):
375
- | Property | will-change value |
376
- |----------|------------------|
377
- | transform (translate, scale, rotate) | `transform` |
378
- | opacity | `opacity` |
379
- | filter (blur, brightness, contrast) | `filter` |
380
- | clip-path | `clip-path` |
381
-
382
- Never use `will-change: all` or `will-change: contents` - this forces the entire element and its subtree onto a new compositor layer, thrashing memory.
383
-
384
- Remove `will-change` after the animation completes if applied dynamically:
385
- ```js
386
- element.addEventListener('transitionend', () => element.style.willChange = 'auto')
387
- ```
152
+ 1. Keyboard-initiated actions (command palette, list navigation, shortcuts) must have zero animation. They repeat hundreds of times daily and every ms is felt.
153
+ 2. Default to named spring presets (gentle/wobbly/stiff/slow) rather than raw stiffness/damping numbers; presets are tuned for 60fps settle-time and predictable feel.
154
+ 3. Always use `--ease-*` CSS custom property tokens rather than inline `cubic-bezier()` strings; tokens keep easing consistent and respect `prefers-reduced-motion`.
155
+ 4. OKLCH is the correct color space for animated color transitions; sRGB interpolation produces muddy mid-transition colors. See `reference/color-theory.md` for color interpolation in animation.
388
156
 
389
157
  ---
390
158
 
391
- ## Advanced Patterns
392
-
393
- For spring physics, scroll-driven animation, FLIP, View Transitions API, gesture & drag mechanics, clip-path animation patterns, blur-to-mask crossfades, WAAPI, Framer Motion hardware-acceleration gotcha, motion cohesion & personality, and the next-day slow-motion review process, see:
394
-
395
- → **`reference/motion-advanced.md`** (Phase 18)
396
-
397
- For the canonical easing catalog (`--ease-*` tokens, cubic-bezier equivalents, 60fps settle-times):
398
-
399
- → **`reference/motion-easings.md`** (Phase 18)
400
-
401
- For spring parameter presets (gentle / wobbly / stiff / slow):
402
-
403
- → **`reference/motion-spring.md`** (Phase 18)
404
-
405
- For transition family taxonomy (8 families: 3d / blur / cover / destruction / dissolve / distortion / grid / light):
159
+ ## Cross-Domain See Also
406
160
 
407
- **`reference/motion-transition-taxonomy.md`** (Phase 18)
161
+ - Color animation uses OKLCH path: `reference/color.md`
162
+ - Gesture semantics (velocity, pointer capture): `reference/interaction.md`
163
+ - OS-level reduced-motion: `reference/responsive.md`
164
+ - CSS layout transitions: `reference/spatial.md`
165
+ - Typography: `reference/typography.md`
166
+ - UX writing: `reference/ux-writing.md`
@@ -625,8 +625,9 @@
625
625
  {
626
626
  "name": "motion",
627
627
  "path": "reference/motion.md",
628
- "type": "motion",
629
- "description": "Motion vocabulary seed (extended in Phase 18)"
628
+ "type": "domain-index",
629
+ "description": "Phase 45 domain-index: motion navigation - indexes easings, spring, transition-taxonomy, interpolate, advanced, framer-motion-patterns.",
630
+ "phase": 45
630
631
  },
631
632
  {
632
633
  "name": "motion-advanced",
@@ -797,8 +798,9 @@
797
798
  {
798
799
  "name": "typography",
799
800
  "path": "reference/typography.md",
800
- "type": "heuristic",
801
- "description": "Typography-system heuristics used by visual-hierarchy-mapper"
801
+ "type": "domain-index",
802
+ "description": "Phase 45 domain-index: typography navigation - indexes type-scale heuristics, variable-fonts-loading, proportion-systems.",
803
+ "phase": 45
802
804
  },
803
805
  {
804
806
  "name": "user-research",
@@ -1049,6 +1051,41 @@
1049
1051
  "type": "meta-rules",
1050
1052
  "phase": 42,
1051
1053
  "description": "Phase 42 multi-harness skill-placeholder catalogue: the four placeholders ({{command_prefix}}/{{model}}/{{config_file}}/{{ask_instruction}}) + per-harness substitution table + the \\{{...}} escape + the <!-- harness-only: a,b --> block rule. Skills authored once in source/skills/, compiled per-harness by scripts/build-skills.cjs via scripts/lib/build/factory.cjs reading scripts/lib/manifest/harnesses.json."
1054
+ },
1055
+ {
1056
+ "name": "color",
1057
+ "path": "reference/color.md",
1058
+ "type": "domain-index",
1059
+ "phase": 45,
1060
+ "description": "Phase 45 domain-index: color + contrast navigation - color-theory, palette-catalog, contrast-advanced, style-vocabulary."
1061
+ },
1062
+ {
1063
+ "name": "spatial",
1064
+ "path": "reference/spatial.md",
1065
+ "type": "domain-index",
1066
+ "phase": 45,
1067
+ "description": "Phase 45 domain-index: layout/spacing/composition - composition, proportion-systems, css-grid-layout, visual-hierarchy-layout, gestalt, image-optimization, data-visualization, surfaces."
1068
+ },
1069
+ {
1070
+ "name": "interaction",
1071
+ "path": "reference/interaction.md",
1072
+ "type": "domain-index",
1073
+ "phase": 45,
1074
+ "description": "Phase 45 domain-index: interaction + a11y + components - accessibility, component-authoring, form-patterns, information-architecture, onboarding-progressive-disclosure, emotional-design, components/."
1075
+ },
1076
+ {
1077
+ "name": "responsive",
1078
+ "path": "reference/responsive.md",
1079
+ "type": "domain-index",
1080
+ "phase": 45,
1081
+ "description": "Phase 45 domain-index: responsive + i18n + platforms - i18n, rtl-cjk-cultural, platforms, native-platforms, performance, css-grid-layout."
1082
+ },
1083
+ {
1084
+ "name": "ux-writing",
1085
+ "path": "reference/ux-writing.md",
1086
+ "type": "domain-index",
1087
+ "phase": 45,
1088
+ "description": "Phase 45 domain-index: UX-writing + voice - brand-voice, style-vocabulary, anti-patterns."
1052
1089
  }
1053
1090
  ]
1054
1091
  }
@@ -4,19 +4,41 @@
4
4
  "title": "Reference Registry",
5
5
  "description": "Typed index of every reference/*.md (and reference/*.json default) in the plugin. Enables agents to query by type instead of grep-hunting import strings. Round-trip enforced: every reference/*.md must appear in entries[], every entry must resolve to an existing file.",
6
6
  "type": "object",
7
- "required": ["version", "generated_at", "entries"],
7
+ "required": [
8
+ "version",
9
+ "generated_at",
10
+ "entries"
11
+ ],
8
12
  "properties": {
9
- "$schema": { "type": "string" },
10
- "version": { "const": 1 },
11
- "generated_at": { "type": "string", "format": "date-time" },
13
+ "$schema": {
14
+ "type": "string"
15
+ },
16
+ "version": {
17
+ "const": 1
18
+ },
19
+ "generated_at": {
20
+ "type": "string",
21
+ "format": "date-time"
22
+ },
12
23
  "entries": {
13
24
  "type": "array",
14
25
  "items": {
15
26
  "type": "object",
16
- "required": ["name", "path", "type"],
27
+ "required": [
28
+ "name",
29
+ "path",
30
+ "type"
31
+ ],
17
32
  "properties": {
18
- "name": { "type": "string", "minLength": 1, "pattern": "^[a-z0-9][a-z0-9-._]*$" },
19
- "path": { "type": "string", "minLength": 1 },
33
+ "name": {
34
+ "type": "string",
35
+ "minLength": 1,
36
+ "pattern": "^[a-z0-9][a-z0-9-._]*$"
37
+ },
38
+ "path": {
39
+ "type": "string",
40
+ "minLength": 1
41
+ },
20
42
  "type": {
21
43
  "type": "string",
22
44
  "enum": [
@@ -41,13 +63,28 @@
41
63
  "typography",
42
64
  "layout",
43
65
  "performance",
44
- "component-spec"
66
+ "component-spec",
67
+ "domain-index"
68
+ ]
69
+ },
70
+ "tier": {
71
+ "enum": [
72
+ "L0",
73
+ "L1",
74
+ "L2"
45
75
  ]
46
76
  },
47
- "tier": { "enum": ["L0", "L1", "L2"] },
48
- "phase": { "type": "number", "description": "Phase that introduced this entry. Numbers are allowed (e.g., 19.6, 27.5, 27.6, 27.7, 28.5) — decimal phases are valid per the long-standing precedent established by Phases 19.6 / 27.5 / 27.6 / 27.7 / 28.5." },
49
- "description": { "type": "string" },
50
- "registered_at": { "type": "string", "format": "date-time" }
77
+ "phase": {
78
+ "type": "number",
79
+ "description": "Phase that introduced this entry. Numbers are allowed (e.g., 19.6, 27.5, 27.6, 27.7, 28.5) — decimal phases are valid per the long-standing precedent established by Phases 19.6 / 27.5 / 27.6 / 27.7 / 28.5."
80
+ },
81
+ "description": {
82
+ "type": "string"
83
+ },
84
+ "registered_at": {
85
+ "type": "string",
86
+ "format": "date-time"
87
+ }
51
88
  },
52
89
  "additionalProperties": false
53
90
  }
@@ -0,0 +1,74 @@
1
+ # Responsive Design - Domain Index
2
+
3
+ This is the domain entry-point for responsive design. Load this file when the
4
+ interface will render in more than one locale, platform, or viewport condition.
5
+ It covers i18n engineering primitives, RTL and CJK cultural adaptation,
6
+ platform-specific conventions, native token bridging, and performance budgets.
7
+ It does not cover the CSS Grid implementation of responsive layouts (see
8
+ `reference/spatial.md` for container queries and `clamp()`); it does not cover
9
+ copy tone for localized content (see `reference/ux-writing.md`).
10
+
11
+ ---
12
+
13
+ ## Fragment Index
14
+
15
+ → **`reference/i18n.md`** (Phase 28) - use when localizing text: expansion
16
+ budgets (+30-40%), CSS logical props, `Intl.*` APIs, ICU MessageFormat,
17
+ bidi isolation, Unicode normalization, multi-script font stacks
18
+
19
+ → **`reference/rtl-cjk-cultural.md`** (Phase 28) - use when targeting RTL
20
+ locales or CJK audiences: layout mirroring rules, bidirectional text isolation,
21
+ Arabic/Hebrew/Devanagari rendering, cultural color meanings and imagery norms
22
+
23
+ → **`reference/platforms.md`** (Phase 19) - use when targeting multiple
24
+ platforms: iOS/Android/web/visionOS/watchOS nav patterns, safe area insets,
25
+ gesture vocabularies, haptics, native typography conventions
26
+
27
+ → **`reference/native-platforms.md`** (Phase 34.1) - use when bridging design
28
+ tokens to native code: canonical CSS token to SwiftUI Color / Compose Color /
29
+ Flutter ThemeData mapping, precision contract for the round-trip
30
+
31
+ → **`reference/performance.md`** (Phase 19) - use for any production
32
+ responsive build: Core Web Vitals budgets by project type, JS/font/image
33
+ budgets, React runtime perf rules
34
+
35
+ → **`reference/css-grid-layout.md`** (Phase 18) - load the container-queries
36
+ and `clamp()` sections only: fluid responsive components, safe-area insets,
37
+ logical CSS props in Grid context
38
+
39
+ ---
40
+
41
+ ## Rules of Thumb
42
+
43
+ **1. Size containers for the worst-case expansion locale.**
44
+ Russian and Finnish strings expand +40% from an English baseline. Any text
45
+ container designed at English width will overflow in those locales. Build for
46
+ `EN base x 1.4` as the standard layout-budget rule; top-aligned labels absorb
47
+ expansion without horizontal breakage.
48
+
49
+ **2. CSS logical properties are the implementation primitive for RTL.**
50
+ Never use `left`/`right` in a layout that will need to mirror. Replace
51
+ `margin-left` with `margin-inline-start`, `padding-right` with
52
+ `padding-inline-end`, and positioned `left` with `inset-inline-start`. The full
53
+ mapping is in `reference/rtl-cjk-cultural.md`.
54
+
55
+ **3. `prefers-reduced-motion` is a responsive property, not optional.**
56
+ Any animation behind a media query must resolve to `transition: none` or
57
+ `animation-duration: 0.01ms` when the user has set OS-level reduced-motion.
58
+ The CSS reset pattern is in `reference/motion.md`.
59
+
60
+ **4. Native token precision contract: no re-derivation in component code.**
61
+ Color hex values bridge to native at 8-bit channel precision (no rounding).
62
+ Dimension px values bridge as integer dp/pt. The token-bridge round-trip in
63
+ `reference/native-platforms.md` is the source of truth - any re-derivation
64
+ in component code will drift from the canonical value.
65
+
66
+ ---
67
+
68
+ ## Cross-Domain See Also
69
+
70
+ - i18n text expansion affects type container sizing: `reference/typography.md`
71
+ - Touch targets differ from pointer targets: `reference/interaction.md`
72
+ - Layout shifts at breakpoints: `reference/spatial.md`
73
+ - OS-level reduced-motion links to animation rules: `reference/motion.md`
74
+ - Civic multi-language government forms: `reference/domains/civic-patterns.md`