@polymorphism-tech/morph-spec 7.0.0 → 7.1.1

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 (89) hide show
  1. package/README.md +368 -368
  2. package/claude-plugin.json +14 -14
  3. package/docs/CHEATSHEET.md +199 -199
  4. package/docs/QUICKSTART.md +200 -200
  5. package/framework/CLAUDE.md +1 -1
  6. package/framework/MORPH.md +4 -1
  7. package/framework/agents.json +132 -127
  8. package/framework/rubrics/backend.json +41 -36
  9. package/framework/rules/ai-agents-standards.md +45 -15
  10. package/framework/rules/neon-standards.md +25 -26
  11. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  12. package/framework/skills/core/morph-plan/SKILL.md +3 -1
  13. package/framework/skills/core/morph-stack-scan/SKILL.md +3 -3
  14. package/framework/standards/STANDARDS.json +1729 -1133
  15. package/framework/standards/ai-agents/agent-session.md +160 -0
  16. package/framework/standards/ai-agents/batching.md +193 -0
  17. package/framework/standards/ai-agents/context-providers.md +188 -0
  18. package/framework/standards/ai-agents/mcp-server.md +250 -0
  19. package/framework/standards/ai-agents/mcp-tools.md +197 -0
  20. package/framework/standards/ai-agents/middleware-patterns.md +207 -0
  21. package/framework/standards/ai-agents/modalities-image-gen.md +173 -0
  22. package/framework/standards/ai-agents/modalities-speech-to-text.md +171 -0
  23. package/framework/standards/ai-agents/modalities-text-to-speech.md +181 -0
  24. package/framework/standards/ai-agents/modalities-vision.md +201 -0
  25. package/framework/standards/ai-agents/multi-agent-patterns.md +155 -0
  26. package/framework/standards/ai-agents/production.md +114 -258
  27. package/framework/standards/ai-agents/prompts-in-db.md +214 -0
  28. package/framework/standards/ai-agents/providers/model-registry.md +158 -0
  29. package/framework/standards/ai-agents/rag-custom-pgvector.md +243 -0
  30. package/framework/standards/ai-agents/service-tier-flex.md +135 -0
  31. package/framework/standards/ai-agents/setup.md +142 -316
  32. package/framework/standards/ai-agents/structured-output.md +249 -0
  33. package/framework/standards/ai-agents/sweet-spot.md +109 -0
  34. package/framework/standards/ai-agents/workflows.md +114 -284
  35. package/framework/standards/architecture/vertical-slice/vertical-slice.md +439 -429
  36. package/framework/standards/backend/api/validation.md +92 -88
  37. package/framework/standards/backend/database/postgresql/database.md +336 -332
  38. package/framework/standards/backend/database/vector-search-rag.md +599 -541
  39. package/framework/standards/backend/dotnet/fluent-validation-vsa.md +4 -0
  40. package/framework/standards/backend/dotnet/result-pattern.md +4 -0
  41. package/framework/standards/backend/dotnet/scalar-ui.md +176 -172
  42. package/framework/standards/backend/dotnet/scrutor.md +4 -0
  43. package/framework/standards/backend/dotnet/vsa-handler-patterns.md +310 -274
  44. package/framework/standards/backend/integrations/asaas/asaas-api.md +260 -216
  45. package/framework/standards/backend/integrations/hangfire/hangfire-jobs.md +354 -350
  46. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +30 -19
  47. package/framework/standards/backend/integrations/resend/resend-email.md +400 -385
  48. package/framework/standards/data/nosql/cache/redis.md +106 -97
  49. package/framework/standards/data/nosql/cosmos-db.md +127 -118
  50. package/framework/standards/data/vector-search/rag-chunking.md +113 -104
  51. package/framework/standards/frontend/design-system/ai-image-generation.md +4 -0
  52. package/framework/standards/frontend/design-system/animations.md +164 -160
  53. package/framework/standards/frontend/design-system/naming.md +68 -64
  54. package/framework/standards/frontend/gsap/gsap-core.md +14 -8
  55. package/framework/standards/frontend/gsap/gsap-plugins.md +26 -21
  56. package/framework/standards/frontend/gsap/gsap-scrolltrigger.md +9 -7
  57. package/framework/standards/frontend/nextjs/app-router.md +127 -123
  58. package/framework/standards/frontend/nextjs/components.md +136 -132
  59. package/framework/standards/frontend/nextjs/data-fetching.md +130 -126
  60. package/framework/standards/frontend/nextjs/forms.md +134 -128
  61. package/framework/standards/frontend/nextjs/motion-patterns.md +328 -322
  62. package/framework/standards/frontend/nextjs/naming-conventions.md +71 -67
  63. package/framework/standards/frontend/nextjs/nextjs-patterns.md +229 -225
  64. package/framework/standards/frontend/nextjs/project-structure.md +106 -102
  65. package/framework/standards/frontend/nextjs/state-management.md +76 -72
  66. package/framework/standards/frontend/nextjs/testing.md +115 -111
  67. package/framework/standards/infrastructure/docker/easypanel-deploy.md +196 -192
  68. package/framework/standards/infrastructure/neon/neon-pgrag.md +6 -2
  69. package/framework/standards/infrastructure/neon/neon-pgvector.md +4 -0
  70. package/framework/standards/infrastructure/neon/neon-setup.md +5 -1
  71. package/framework/standards/integration/mcp/mcp-tools.md +471 -462
  72. package/framework/templates/CLAUDE.md.core.template +1 -1
  73. package/framework/templates/REGISTRY.json +1745 -1239
  74. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -0
  75. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -0
  76. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -0
  77. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -0
  78. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -0
  79. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -0
  80. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -0
  81. package/framework/templates/code/dotnet/backend/repository.cs +3 -10
  82. package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -0
  83. package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -0
  84. package/package.json +89 -83
  85. package/src/core/templates/template-registry.js +289 -256
  86. package/src/lib/generators/context-generator.js +516 -518
  87. package/src/lib/generators/scaffold-generator.js +23 -26
  88. package/framework/standards/infrastructure/neon/neon-semantic-kernel.md +0 -310
  89. package/framework/templates/integrations/semantic-kernel-neon.cs +0 -125
@@ -1,104 +1,113 @@
1
- # Data Standard: RAG Chunking Strategies
2
-
3
- ## Overview
4
- Chunking splits documents into segments for embedding. Chunk quality directly impacts RAG answer quality.
5
-
6
- ## Chunking Strategies
7
-
8
- ### 1. Fixed-Size (Baseline)
9
- ```csharp
10
- public IEnumerable<Chunk> FixedSizeChunk(string text, int size = 512, int overlap = 50)
11
- {
12
- for (int i = 0; i < text.Length; i += size - overlap)
13
- {
14
- yield return new Chunk
15
- {
16
- Content = text[i..Math.Min(i + size, text.Length)],
17
- StartIndex = i,
18
- EndIndex = Math.Min(i + size, text.Length)
19
- };
20
- }
21
- }
22
- ```
23
-
24
- ### 2. Sentence-Aware (Recommended for prose)
25
- ```csharp
26
- public IEnumerable<Chunk> SentenceChunk(string text, int maxTokens = 256)
27
- {
28
- var sentences = SplitSentences(text);
29
- var current = new StringBuilder();
30
- var tokenCount = 0;
31
-
32
- foreach (var sentence in sentences)
33
- {
34
- var sentenceTokens = EstimateTokens(sentence);
35
- if (tokenCount + sentenceTokens > maxTokens && current.Length > 0)
36
- {
37
- yield return new Chunk { Content = current.ToString().Trim() };
38
- current.Clear();
39
- tokenCount = 0;
40
- }
41
- current.Append(sentence).Append(' ');
42
- tokenCount += sentenceTokens;
43
- }
44
-
45
- if (current.Length > 0)
46
- yield return new Chunk { Content = current.ToString().Trim() };
47
- }
48
- ```
49
-
50
- ### 3. Semantic (Best quality, higher cost)
51
- Split at semantic boundaries (paragraphs, headers, sections) rather than character count.
52
-
53
- ```csharp
54
- public IEnumerable<Chunk> SemanticChunk(string markdown)
55
- {
56
- // Split at markdown headers
57
- var sections = Regex.Split(markdown, @"(?=^#{1,3} )", RegexOptions.Multiline);
58
- foreach (var section in sections.Where(s => s.Trim().Length > 0))
59
- yield return new Chunk { Content = section.Trim() };
60
- }
61
- ```
62
-
63
- ## Token Estimation
64
- ```csharp
65
- // Rough estimate: 1 token ≈ 4 characters (English), ≈ 3 characters (Portuguese)
66
- private static int EstimateTokens(string text) => text.Length / 4;
67
-
68
- // More accurate: use tiktoken (if available)
69
- // var encoder = TiktokenSharp.TikToken.EncodingForModel("gpt-4");
70
- // return encoder.Encode(text).Count;
71
- ```
72
-
73
- ## Chunk Metadata
74
- Always store metadata with chunks for filtering and citation:
75
- ```csharp
76
- public record Chunk
77
- {
78
- public string Content { get; init; } = "";
79
- public string DocumentId { get; init; } = "";
80
- public string DocumentTitle { get; init; } = "";
81
- public string SourceUrl { get; init; } = "";
82
- public int ChunkIndex { get; init; }
83
- public int StartCharIndex { get; init; }
84
- public string Section { get; init; } = ""; // H1/H2 header this belongs to
85
- public DateTime IndexedAt { get; init; } = DateTime.UtcNow;
86
- }
87
- ```
88
-
89
- ## Strategy Selection Guide
90
- | Document Type | Strategy | Chunk Size |
91
- |---------------|----------|------------|
92
- | Legal documents | Sentence-aware | 256 tokens |
93
- | Technical docs | Semantic (headers) | Variable |
94
- | Q&A pairs | Keep as-is | Whole Q+A |
95
- | Code files | Function-boundary | Whole function |
96
- | News articles | Paragraph | 512 tokens |
97
-
98
- ## Quality Checklist
99
- - [ ] Chunks overlap by 10-20% to avoid cutting context at boundaries
100
- - [ ] Minimum chunk size: 50 tokens (avoid noisy small chunks)
101
- - [ ] Maximum chunk size: 512 tokens for ada-002 (8192 token model limit)
102
- - [ ] Metadata preserved and searchable
103
- - [ ] Source URL included for citation
104
- - [ ] Re-index when document changes (detect via content hash)
1
+ # Data Standard: RAG Chunking Strategies
2
+
3
+ > **Scope:** data-vector-search
4
+ > **Layer:** 2
5
+ > **Keywords:** chunking, rag, embeddings, vector-search, document-segmentation, overlap, retrieval
6
+ > **Load When:** building a RAG pipeline or embedding documents for vector search
7
+
8
+ **Verified against:** .NET 10 (chunking algorithms — language-level, no external package). Last-verified: 2026-05-20.
9
+
10
+ ---
11
+
12
+ ## Overview
13
+ Chunking splits documents into segments for embedding. Chunk quality directly impacts RAG answer quality.
14
+
15
+ ## Chunking Strategies
16
+
17
+ ### 1. Fixed-Size (Baseline)
18
+ ```csharp
19
+ public IEnumerable<Chunk> FixedSizeChunk(string text, int size = 512, int overlap = 50)
20
+ {
21
+ for (int i = 0; i < text.Length; i += size - overlap)
22
+ {
23
+ yield return new Chunk
24
+ {
25
+ Content = text[i..Math.Min(i + size, text.Length)],
26
+ StartIndex = i,
27
+ EndIndex = Math.Min(i + size, text.Length)
28
+ };
29
+ }
30
+ }
31
+ ```
32
+
33
+ ### 2. Sentence-Aware (Recommended for prose)
34
+ ```csharp
35
+ public IEnumerable<Chunk> SentenceChunk(string text, int maxTokens = 256)
36
+ {
37
+ var sentences = SplitSentences(text);
38
+ var current = new StringBuilder();
39
+ var tokenCount = 0;
40
+
41
+ foreach (var sentence in sentences)
42
+ {
43
+ var sentenceTokens = EstimateTokens(sentence);
44
+ if (tokenCount + sentenceTokens > maxTokens && current.Length > 0)
45
+ {
46
+ yield return new Chunk { Content = current.ToString().Trim() };
47
+ current.Clear();
48
+ tokenCount = 0;
49
+ }
50
+ current.Append(sentence).Append(' ');
51
+ tokenCount += sentenceTokens;
52
+ }
53
+
54
+ if (current.Length > 0)
55
+ yield return new Chunk { Content = current.ToString().Trim() };
56
+ }
57
+ ```
58
+
59
+ ### 3. Semantic (Best quality, higher cost)
60
+ Split at semantic boundaries (paragraphs, headers, sections) rather than character count.
61
+
62
+ ```csharp
63
+ public IEnumerable<Chunk> SemanticChunk(string markdown)
64
+ {
65
+ // Split at markdown headers
66
+ var sections = Regex.Split(markdown, @"(?=^#{1,3} )", RegexOptions.Multiline);
67
+ foreach (var section in sections.Where(s => s.Trim().Length > 0))
68
+ yield return new Chunk { Content = section.Trim() };
69
+ }
70
+ ```
71
+
72
+ ## Token Estimation
73
+ ```csharp
74
+ // Rough estimate: 1 token ≈ 4 characters (English), ≈ 3 characters (Portuguese)
75
+ private static int EstimateTokens(string text) => text.Length / 4;
76
+
77
+ // More accurate: use tiktoken (if available)
78
+ // var encoder = TiktokenSharp.TikToken.EncodingForModel("gpt-4");
79
+ // return encoder.Encode(text).Count;
80
+ ```
81
+
82
+ ## Chunk Metadata
83
+ Always store metadata with chunks for filtering and citation:
84
+ ```csharp
85
+ public record Chunk
86
+ {
87
+ public string Content { get; init; } = "";
88
+ public string DocumentId { get; init; } = "";
89
+ public string DocumentTitle { get; init; } = "";
90
+ public string SourceUrl { get; init; } = "";
91
+ public int ChunkIndex { get; init; }
92
+ public int StartCharIndex { get; init; }
93
+ public string Section { get; init; } = ""; // H1/H2 header this belongs to
94
+ public DateTime IndexedAt { get; init; } = DateTime.UtcNow;
95
+ }
96
+ ```
97
+
98
+ ## Strategy Selection Guide
99
+ | Document Type | Strategy | Chunk Size |
100
+ |---------------|----------|------------|
101
+ | Legal documents | Sentence-aware | 256 tokens |
102
+ | Technical docs | Semantic (headers) | Variable |
103
+ | Q&A pairs | Keep as-is | Whole Q+A |
104
+ | Code files | Function-boundary | Whole function |
105
+ | News articles | Paragraph | 512 tokens |
106
+
107
+ ## Quality Checklist
108
+ - [ ] Chunks overlap by 10-20% to avoid cutting context at boundaries
109
+ - [ ] Minimum chunk size: 50 tokens (avoid noisy small chunks)
110
+ - [ ] Maximum chunk size: ~512 tokens (well under the 8192-token input limit of `text-embedding-3-small`/`-large`)
111
+ - [ ] Metadata preserved and searchable
112
+ - [ ] Source URL included for citation
113
+ - [ ] Re-index when document changes (detect via content hash)
@@ -5,6 +5,10 @@
5
5
  > **Keywords:** image, gemini, asset, ai-generation, placeholder, mcp, next/image
6
6
  > **Load When:** feature has UI components requiring image assets
7
7
 
8
+ **Verified against:** Gemini Image MCP + Next.js 15 `next/image`. Last-verified: 2026-05-20.
9
+
10
+ ---
11
+
8
12
  ## When to Use AI-Generated Images
9
13
 
10
14
  | Use Case | Approach | Examples |
@@ -1,160 +1,164 @@
1
- # CSS Animation Patterns
2
-
3
- > **Scope:** universal
4
- > **Layer:** 0 (always load)
5
- > **Keywords:** css, animation, keyframe, transition, stagger, shimmer
6
- > **Load When:** always
7
-
8
- ## Keyframes Library
9
-
10
- ```css
11
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
12
- @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
13
- @keyframes slideInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
14
- @keyframes slideInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }
15
- @keyframes slideInLeft { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } }
16
- @keyframes slideInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
17
- @keyframes scaleIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
18
- @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
19
- @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
20
- @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
21
- @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
22
- ```
23
-
24
- ## Animation Classes
25
-
26
- | Class | Animation | Duration | Iteration |
27
- |-------|-----------|----------|-----------|
28
- | `.animate-fadeIn` | fadeIn | 0.3s | once |
29
- | `.animate-fadeOut` | fadeOut | 0.3s | once |
30
- | `.animate-slideInUp` | slideInUp | 0.5s | once |
31
- | `.animate-slideInDown` | slideInDown | 0.5s | once |
32
- | `.animate-slideInLeft` | slideInLeft | 0.5s | once |
33
- | `.animate-slideInRight` | slideInRight | 0.5s | once |
34
- | `.animate-scaleIn` | scaleIn | 0.3s | once |
35
- | `.animate-bounce` | bounce | 1s | infinite |
36
- | `.animate-pulse` | pulse | 2s | infinite |
37
- | `.animate-spin` | spin | 1s | infinite |
38
-
39
- ```css
40
- .animate-fadeIn { animation: fadeIn 0.3s ease forwards; }
41
- .animate-slideInUp { animation: slideInUp 0.5s ease forwards; }
42
- .animate-bounce { animation: bounce 1s ease infinite; }
43
- ```
44
-
45
- ## Stagger & Timing
46
-
47
- ```css
48
- /* Stagger delays (0.1s - 1.0s) */
49
- .stagger-1 { animation-delay: 0.1s; } .stagger-2 { animation-delay: 0.2s; }
50
- .stagger-3 { animation-delay: 0.3s; } /* ... up to .stagger-10 */
51
-
52
- /* Durations */
53
- .duration-fast { animation-duration: 150ms; }
54
- .duration-normal { animation-duration: 300ms; }
55
- .duration-slow { animation-duration: 500ms; }
56
-
57
- /* Easing */
58
- .ease-bounce { animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); }
59
- ```
60
-
61
- ## Shimmer (Skeleton Loading)
62
-
63
- ```css
64
- .shimmer {
65
- background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
66
- background-size: 200% 100%;
67
- animation: shimmer 1.5s infinite;
68
- }
69
- ```
70
-
71
- ---
72
-
73
- ## Blazor Usage
74
-
75
- ### Stagger Pattern
76
-
77
- ```razor
78
- @for (int i = 0; i < _items.Count; i++)
79
- {
80
- var index = i;
81
- <div class="card animate-slideInUp"
82
- style="@($"animation-delay: {0.05 * index}s; animation-fill-mode: backwards;")">
83
- @_items[index].Name
84
- </div>
85
- }
86
- ```
87
-
88
- **CRITICAL:** Use `animation-fill-mode: backwards` to avoid flash before delay.
89
-
90
- ### Conditional Enter/Exit
91
-
92
- ```razor
93
- @if (_showMessage)
94
- {
95
- <div class="@(_isEntering ? "animate-slideInUp" : "animate-fadeOut")">Msg</div>
96
- }
97
- @code {
98
- private async Task HideMessage() {
99
- _isEntering = false;
100
- await Task.Delay(300); // wait for exit animation
101
- _showMessage = false;
102
- }
103
- }
104
- ```
105
-
106
- ### Skeleton Loading
107
-
108
- ```razor
109
- @if (_isLoading)
110
- {
111
- <div class="shimmer" style="width: 200px; height: 24px; border-radius: 4px;"></div>
112
- }
113
- else { <h2>@_title</h2> }
114
- ```
115
-
116
- ## Transitions (Hover/Focus)
117
-
118
- ```css
119
- .card { transition: transform 0.2s ease, box-shadow 0.2s ease; }
120
- .card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
121
-
122
- .button { transition: background-color 0.15s ease, transform 0.15s ease; }
123
- .button:active { transform: scale(0.98); }
124
-
125
- .link::after { content: ''; position: absolute; width: 0; height: 2px; background: var(--primary); transition: width 0.3s ease; }
126
- .link:hover::after { width: 100%; }
127
- ```
128
-
129
- ## Accessibility
130
-
131
- ```css
132
- @media (prefers-reduced-motion: reduce) {
133
- *, *::before, *::after {
134
- animation-duration: 0.01ms !important;
135
- animation-iteration-count: 1 !important;
136
- transition-duration: 0.01ms !important;
137
- }
138
- }
139
- ```
140
-
141
- ## Checklist
142
-
143
- - [ ] Keyframes in design-system.css
144
- - [ ] `.animate-*` classes created
145
- - [ ] `animation-fill-mode: backwards` for stagger
146
- - [ ] `@media (prefers-reduced-motion)` implemented
147
- - [ ] Shimmer for loading states
148
-
149
- ## JavaScript Animation Libraries
150
-
151
- For animations beyond CSS capabilities:
152
-
153
- | Need | Library | Standard |
154
- |------|---------|----------|
155
- | Simple UI transitions (enter/exit, layout, gestures) | Framer Motion | `frontend/nextjs/motion-patterns.md` |
156
- | Complex animations (ScrollTrigger, SVG morph, timelines) | GSAP | `frontend/gsap/gsap-core.md` |
157
-
158
- ---
159
-
160
- *MORPH-SPEC by Polymorphism Tech*
1
+ # CSS Animation Patterns
2
+
3
+ > **Scope:** universal
4
+ > **Layer:** 0 (always load)
5
+ > **Keywords:** css, animation, keyframe, transition, stagger, shimmer
6
+ > **Load When:** always
7
+
8
+ **Verified against:** CSS animations/transitions (language-level, no framework). Last-verified: 2026-05-20.
9
+
10
+ ---
11
+
12
+ ## Keyframes Library
13
+
14
+ ```css
15
+ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
16
+ @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
17
+ @keyframes slideInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
18
+ @keyframes slideInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }
19
+ @keyframes slideInLeft { from { opacity: 0; transform: translateX(-20px); } to { opacity: 1; transform: translateX(0); } }
20
+ @keyframes slideInRight { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } }
21
+ @keyframes scaleIn { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
22
+ @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
23
+ @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
24
+ @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
25
+ @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }
26
+ ```
27
+
28
+ ## Animation Classes
29
+
30
+ | Class | Animation | Duration | Iteration |
31
+ |-------|-----------|----------|-----------|
32
+ | `.animate-fadeIn` | fadeIn | 0.3s | once |
33
+ | `.animate-fadeOut` | fadeOut | 0.3s | once |
34
+ | `.animate-slideInUp` | slideInUp | 0.5s | once |
35
+ | `.animate-slideInDown` | slideInDown | 0.5s | once |
36
+ | `.animate-slideInLeft` | slideInLeft | 0.5s | once |
37
+ | `.animate-slideInRight` | slideInRight | 0.5s | once |
38
+ | `.animate-scaleIn` | scaleIn | 0.3s | once |
39
+ | `.animate-bounce` | bounce | 1s | infinite |
40
+ | `.animate-pulse` | pulse | 2s | infinite |
41
+ | `.animate-spin` | spin | 1s | infinite |
42
+
43
+ ```css
44
+ .animate-fadeIn { animation: fadeIn 0.3s ease forwards; }
45
+ .animate-slideInUp { animation: slideInUp 0.5s ease forwards; }
46
+ .animate-bounce { animation: bounce 1s ease infinite; }
47
+ ```
48
+
49
+ ## Stagger & Timing
50
+
51
+ ```css
52
+ /* Stagger delays (0.1s - 1.0s) */
53
+ .stagger-1 { animation-delay: 0.1s; } .stagger-2 { animation-delay: 0.2s; }
54
+ .stagger-3 { animation-delay: 0.3s; } /* ... up to .stagger-10 */
55
+
56
+ /* Durations */
57
+ .duration-fast { animation-duration: 150ms; }
58
+ .duration-normal { animation-duration: 300ms; }
59
+ .duration-slow { animation-duration: 500ms; }
60
+
61
+ /* Easing */
62
+ .ease-bounce { animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); }
63
+ ```
64
+
65
+ ## Shimmer (Skeleton Loading)
66
+
67
+ ```css
68
+ .shimmer {
69
+ background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
70
+ background-size: 200% 100%;
71
+ animation: shimmer 1.5s infinite;
72
+ }
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Blazor Usage
78
+
79
+ ### Stagger Pattern
80
+
81
+ ```razor
82
+ @for (int i = 0; i < _items.Count; i++)
83
+ {
84
+ var index = i;
85
+ <div class="card animate-slideInUp"
86
+ style="@($"animation-delay: {0.05 * index}s; animation-fill-mode: backwards;")">
87
+ @_items[index].Name
88
+ </div>
89
+ }
90
+ ```
91
+
92
+ **CRITICAL:** Use `animation-fill-mode: backwards` to avoid flash before delay.
93
+
94
+ ### Conditional Enter/Exit
95
+
96
+ ```razor
97
+ @if (_showMessage)
98
+ {
99
+ <div class="@(_isEntering ? "animate-slideInUp" : "animate-fadeOut")">Msg</div>
100
+ }
101
+ @code {
102
+ private async Task HideMessage() {
103
+ _isEntering = false;
104
+ await Task.Delay(300); // wait for exit animation
105
+ _showMessage = false;
106
+ }
107
+ }
108
+ ```
109
+
110
+ ### Skeleton Loading
111
+
112
+ ```razor
113
+ @if (_isLoading)
114
+ {
115
+ <div class="shimmer" style="width: 200px; height: 24px; border-radius: 4px;"></div>
116
+ }
117
+ else { <h2>@_title</h2> }
118
+ ```
119
+
120
+ ## Transitions (Hover/Focus)
121
+
122
+ ```css
123
+ .card { transition: transform 0.2s ease, box-shadow 0.2s ease; }
124
+ .card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
125
+
126
+ .button { transition: background-color 0.15s ease, transform 0.15s ease; }
127
+ .button:active { transform: scale(0.98); }
128
+
129
+ .link::after { content: ''; position: absolute; width: 0; height: 2px; background: var(--primary); transition: width 0.3s ease; }
130
+ .link:hover::after { width: 100%; }
131
+ ```
132
+
133
+ ## Accessibility
134
+
135
+ ```css
136
+ @media (prefers-reduced-motion: reduce) {
137
+ *, *::before, *::after {
138
+ animation-duration: 0.01ms !important;
139
+ animation-iteration-count: 1 !important;
140
+ transition-duration: 0.01ms !important;
141
+ }
142
+ }
143
+ ```
144
+
145
+ ## Checklist
146
+
147
+ - [ ] Keyframes in design-system.css
148
+ - [ ] `.animate-*` classes created
149
+ - [ ] `animation-fill-mode: backwards` for stagger
150
+ - [ ] `@media (prefers-reduced-motion)` implemented
151
+ - [ ] Shimmer for loading states
152
+
153
+ ## JavaScript Animation Libraries
154
+
155
+ For animations beyond CSS capabilities:
156
+
157
+ | Need | Library | Standard |
158
+ |------|---------|----------|
159
+ | Simple UI transitions (enter/exit, layout, gestures) | Motion (formerly Framer Motion) | `frontend/nextjs/motion-patterns.md` |
160
+ | Complex animations (ScrollTrigger, SVG morph, timelines) | GSAP | `frontend/gsap/gsap-core.md` |
161
+
162
+ ---
163
+
164
+ *MORPH-SPEC by Polymorphism Tech*