medesign 0.0.0-stage → 1.2.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.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +128 -2
  3. package/bin/medesign.js +200 -0
  4. package/integrations/claude-code/SKILL.md +20 -0
  5. package/integrations/cursor/medesign.mdc +26 -0
  6. package/medesign.config.js +46 -0
  7. package/package.json +62 -4
  8. package/presets/apple/design-tokens.css +115 -0
  9. package/presets/apple/guidelines.md +19 -0
  10. package/presets/apple/preset.json +53 -0
  11. package/presets/metha/design-tokens.css +127 -0
  12. package/presets/metha/guidelines.md +23 -0
  13. package/presets/metha/preset.json +53 -0
  14. package/presets/schema.json +102 -0
  15. package/presets/tesla/design-tokens.css +112 -0
  16. package/presets/tesla/guidelines.md +17 -0
  17. package/presets/tesla/preset.json +53 -0
  18. package/references/ai-tells.md +127 -0
  19. package/references/appendices.md +220 -0
  20. package/references/architecture.md +39 -0
  21. package/references/argon-design-archetypes.md +317 -0
  22. package/references/banner-sizes-and-styles.md +118 -0
  23. package/references/block-library.md +61 -0
  24. package/references/brand-design-tokens.md +42 -0
  25. package/references/catalog.json +108 -0
  26. package/references/cip-deliverable-guide.md +95 -0
  27. package/references/cip-design.md +121 -0
  28. package/references/cip-prompt-engineering.md +84 -0
  29. package/references/cip-style-guide.md +68 -0
  30. package/references/cli-architecture.md +146 -0
  31. package/references/components.md +240 -0
  32. package/references/dark-mode.md +23 -0
  33. package/references/design-core.md +42 -0
  34. package/references/design-md-protocol.md +75 -0
  35. package/references/design-routing.md +207 -0
  36. package/references/eng-imagery-content.md +71 -0
  37. package/references/eng-layout.md +28 -0
  38. package/references/eng-other.md +26 -0
  39. package/references/eng-states-theme.md +22 -0
  40. package/references/eng-type-color.md +44 -0
  41. package/references/icon-design.md +122 -0
  42. package/references/image-mockup-direction.md +53 -0
  43. package/references/image-to-code.md +46 -0
  44. package/references/impeccable-polish.md +85 -0
  45. package/references/intake.md +90 -0
  46. package/references/logo-color-psychology.md +101 -0
  47. package/references/logo-design.md +110 -0
  48. package/references/logo-prompt-engineering.md +158 -0
  49. package/references/logo-style-guide.md +109 -0
  50. package/references/mesurv-dna.md +104 -0
  51. package/references/micro-interactions-and-auto-animate.md +71 -0
  52. package/references/modern-craft-invariants.md +332 -0
  53. package/references/motion-tokens.md +99 -0
  54. package/references/preflight.md +110 -0
  55. package/references/proactive-motion.md +167 -0
  56. package/references/quality-gate.md +147 -0
  57. package/references/redesign-audit.md +38 -0
  58. package/references/redesign.md +52 -0
  59. package/references/slides-copywriting-formulas.md +84 -0
  60. package/references/slides-create.md +4 -0
  61. package/references/slides-html-template.md +295 -0
  62. package/references/slides-layout-patterns.md +137 -0
  63. package/references/slides-strategies.md +94 -0
  64. package/references/slides.md +42 -0
  65. package/references/social-photos-design.md +329 -0
  66. package/references/spatial-canvas-engine.md +160 -0
  67. package/references/stitch-system.md +184 -0
  68. package/references/style-extraction.md +17 -0
  69. package/references/styles/brutalist.md +88 -0
  70. package/references/styles/minimalist.md +81 -0
  71. package/references/styles/soft.md +94 -0
  72. package/references/threeui-spatial-engine.md +224 -0
  73. package/references/ui-styling-shadcn.md +336 -0
  74. package/references/ui-ux-vocabulary-vault.json +1223 -0
  75. package/references/ui-ux-vocabulary-vault.md +438 -0
  76. package/references/vocab-protocol.md +52 -0
  77. package/references/vocabulary.md +78 -0
  78. package/scripts/export-tokens.js +403 -0
  79. package/tests/browser-audit.js +442 -0
  80. package/tests/linter.js +412 -0
  81. package/tests/schemas/sarif-2.1.0.schema.json +2915 -0
  82. package/tests/visual-testbed.html +681 -0
@@ -0,0 +1,332 @@
1
+ # Modern Craft Invariants & Apple Design Award Standards (v2.0 Manifesto)
2
+
3
+ คู่มือวิศวกรรมดีไซน์ขั้นสูง สังเคราะห์จากบททดสอบ Red-Team Audit และการถอดรหัสของ Gemini 4.0 Argon สำหรับใช้งานใน `/medesign` ครอบคลุมกฎเหล็ก 10 ประการ, สถาปัตยกรรม CSS Engine ปี 2026, คณิตศาสตร์ทางสายตา (Visual Optics), และการบริหารทรัพยากร GPU/Display
4
+
5
+ ---
6
+
7
+ ## 1. 🏆 10 กฎเหล็กระดับ Apple Design Award (The 10 Golden Invariants)
8
+
9
+ ### กฎข้อที่ 1: Area-Proportional Press Scaling (กฎการยุบตัวแปรผันผกผันกับขนาดพื้นที่)
10
+ - **ปัญหา:** การใช้ `active:scale-95` (`0.95`) กับทุกขนาดทำให้การ์ดขนาดใหญ่ (เช่น 600×400px) ขอบกระชากเข้ามาถึง 30px ซึ่งรุนแรงเกินไป
11
+ - **สูตรคำนวณและระยะขอบเขต (Optical Displacement):**
12
+ ระยะยุบตัวทางสายตารวม ($\Delta P$) ต้องคงที่ที่ประมาณ **2px ถึง 3px** (เฉลี่ยขอบเคลื่อนเข้า $\approx 1.25\text{px}$ ต่อด้าน) พร้อมล็อก `clamp()` เพื่อป้องกันการเสียรูป:
13
+ $$\text{Scale}_{\text{active}} = \text{clamp}\left(0.96, \; 1 - \frac{2.5}{\max(\text{Width}, \text{Height})}, \; 0.995\right)$$
14
+ - **กฎเหล็ก Hit-Target Isolation:** **ห้าม Scale กล่อง Interactive Container ที่รับสัมผัส/การคลิกโดยตรง** เพราะจะทำให้พื้นที่ Hit Test หดตัวลงตาม ให้แยกกล่อง Hit Target ออกจาก Visual Surface เสมอ:
15
+ ```css
16
+ /* Interactive Container: รักษาระยะสัมผัส 44px HIG เต็มพื้นที่ */
17
+ .btn-control {
18
+ position: relative;
19
+ min-height: 44px;
20
+ display: inline-flex;
21
+ align-items: center;
22
+ }
23
+ /* Visual Surface: รับหน้าที่ยุบตัวทางสายตาเท่านั้น */
24
+ .btn-control:active .visual-surface {
25
+ transform: scale(var(--press-scale, 0.975));
26
+ transition: transform 80ms cubic-bezier(0.2, 0, 0, 1);
27
+ }
28
+ ```
29
+ - **ค่ามาตรฐานประจำ Scale:**
30
+ - ปุ่มเล็ก ($32\times 32\text{px}$): `transform: scale(0.96);`
31
+ - ปุ่มกลาง ($48\times 48\text{px}$): `transform: scale(0.98);`
32
+ - การ์ด/คอนเทนเนอร์ใหญ่ ($400\text{px}+$): `transform: scale(0.994);`
33
+
34
+ ### กฎข้อที่ 2: Asymmetric Entry / Exit Timing & The 4 Motion Profiles
35
+ - **หลักการ:** สมองมนุษย์ต้องการเห็นทิศทางที่มาเมื่อวัตถุปรากฏตัว (Entry) แต่ต้องการให้วัตถุที่สั่งปิดหายไปเร็วที่สุดเพื่อทำงานต่อ (Exit)
36
+ - **สูตรคำนวณเวลาที่สอดคล้องกัน:**
37
+ $$T_{\text{exit}} = 0.65 \times T_{\text{entry}} \quad (280\text{ms} \times 0.65 = 182\text{ms} \approx 180\text{ms})$$
38
+ - **แยกแยะ Ease-Out กับ Spring Physics ผ่าน 4 Motion Profiles:**
39
+ | Motion Profile | พฤติกรรมเป้าหมาย | ตัวอย่างการใช้งานจริง | สเปก CSS / Animation |
40
+ |---|---|---|---|
41
+ | **`precision`** | เข้าสถานะทันที ไม่มี Overshoot | CAD/GIS Crosshair, ตารางสแกน, สลับข้อมูล | `duration: 0–100ms`, linear/ease-out |
42
+ | **`soft-settle`** | เร่งต้น ชะลอปลาย นุ่มนวล | Popover, Modal, Dropdown, Tooltip | `240–280ms cubic-bezier(0.16, 1, 0.3, 1)` (Exit: `160–180ms`) |
43
+ | **`spring-settle`** | มีแรงเฉื่อยทางกายภาพ มี Bounce เบาๆ | การ์ด Drag-and-Drop, Morphing ขยายเต็มจอ | CSS `linear()` spring curve หรือ WAAPI |
44
+ | **`instant`** | ตัดแอนิเมชันทิ้ง (0ms) | สลับเหรียญ/ฟิลเตอร์, `@media (prefers-reduced-motion)` | `transition: none !important; duration: 0ms;` |
45
+
46
+ ### กฎข้อที่ 3: Diagonal Menu Safe-Triangle (Hover Tunneling Invariant)
47
+ - **ปัญหา:** เมื่อเลื่อนเมาส์แนวทแยงจากเมนูหลักไปยังเมนูย่อย (Submenu) เมาส์จะหลุดข้ามเมนูตัวอื่นและทำให้เมนูย่อยปิดตัวเองทันที
48
+ - **สูตรบังคับ:** สร้างชั้นเรขาคณิตล่องหนด้วย SVG หรือ CSS `clip-path` เชื่อมจากตำแหน่งเมาส์ปัจจุบันไปยังมุมบนและมุมล่างของ Submenu หรือหน่วงเวลาปิด `120ms` เมื่อเวกเตอร์ความเร็วเมาส์ ($\vec{v}$) มุ่งหน้าเข้าหาพื้นที่ Submenu
49
+
50
+ ### กฎข้อที่ 4: Dual-Context Typography & Script-Specific Trimming
51
+ - **UI Chrome (ปุ่ม, แท็บ, เมนู, เซลล์ตาราง, Badge):**
52
+ - ภาษาอังกฤษ: `line-height: 1.25;` + Progressive `text-box: trim-both cap alphabetic;`
53
+ - ภาษาไทย: `line-height: 1.38;` + `text-box: trim-both text alphabetic;`
54
+ - **Thai Diacritic Headroom Invariant:** สระบนและวรรณยุกต์ไทย (ปิ๊, ผู้, ที่) ยื่นเลยระดับ Cap Height เสมอ **ห้าม Trim จนเฉือนวรรณยุกต์ขาด** ต้องใส่ `padding-top: 2px–4px` สำรองเป็น Optical Headroom และห่อหุ้มด้วย `@supports`:
55
+ ```css
56
+ @supports (text-box: trim-both cap alphabetic) {
57
+ .ui-label-en { text-box: trim-both cap alphabetic; }
58
+ .ui-label-th {
59
+ text-box: trim-both text alphabetic;
60
+ padding-top: 2px; /* สำรองระยะวรรณยุกต์ไทย */
61
+ }
62
+ }
63
+ ```
64
+ - **Reading Prose (บทความ, เอกสารรายงาน, คำอธิบายยาว):**
65
+ - ภาษาอังกฤษ: `line-height: 1.60;` + ความกว้างบรรทัด `55ch–68ch;`
66
+ - ภาษาไทย: `line-height: 1.70–1.75;`
67
+ - **Font Metric Calibration:** คำสั่ง `size-adjust` เป็น **Descriptor ภายใน `@font-face`** สำหรับปรับจูน Fallback font ให้ความสูง x-height เท่ากับ Web Font จริง ไม่ใช่ CSS inline property:
68
+ ```css
69
+ @font-face {
70
+ font-family: "Geist-Fallback";
71
+ src: local("Arial");
72
+ size-adjust: 104%; /* เทียบขนาด Glyph จริง ป้องกัน Layout Shift */
73
+ ascent-override: 96%;
74
+ }
75
+ ```
76
+
77
+ ### กฎข้อที่ 5: Touch-Target Invisible Halo (44×44px HIG Compliance)
78
+ - **ปัญหา:** ใน High-Density WebApp ไอคอนมีขนาดเล็กเพียง `24×24px` หรือ `28×28px` ซึ่งเล็กเกินไปสำหรับการสัมผัสบนมือถือ/แท็บเล็ต
79
+ - **สูตรบังคับ:** แยก Visual Box ออกจาก Hit Box โดยใช้ `::after` ขยายพื้นที่รับสัมผัสเฉพาะอุปกรณ์สัมผัส:
80
+ ```css
81
+ .icon-btn-compact {
82
+ position: relative;
83
+ width: 28px;
84
+ height: 28px;
85
+ }
86
+ @media (pointer: coarse) {
87
+ .icon-btn-compact::after {
88
+ content: "";
89
+ position: absolute;
90
+ inset: -8px; /* 28px + 8px + 8px = 44px ตามมาตรฐาน Apple HIG */
91
+ }
92
+ }
93
+ ```
94
+
95
+ ### กฎข้อที่ 6: Mobile 16px Input Zoom Prevention (Scale-Down Trick)
96
+ - **ปัญหา:** บน iOS Safari หาก `<input>` มี `font-size` ต่ำกว่า `16px` (เช่น `13px` หรือ `14px` ในระบบ High-Density UI) Safari จะบังคับซูมหน้าจออัตโนมัติ
97
+ - **สูตรบังคับ:** บน `@media (max-width: 768px)` กำหนด `font-size: 16px` เพื่อหลอก iOS Safari แล้วย่อขนาดด้วย Transform:
98
+ ```css
99
+ @media (max-width: 768px) {
100
+ .input-compact {
101
+ font-size: 16px;
102
+ transform: scale(0.875); /* แสดงผลจริงเทียบเท่า 14px */
103
+ transform-origin: left center;
104
+ width: 114.2857%; /* 100 / 0.875 ชดเชยความกว้าง */
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### กฎข้อที่ 7: Dark Mode Variable Font Grade Compensation (Optical Halation Thinning)
110
+ - **ปัญหา:** ตัวหนังสือสีสว่างบนพื้นหลังสีมืดจะบวมขึ้นทางสายตาจากแสงฟุ้ง (Halation Effect)
111
+ - **สูตรบังคับ:** ใน Dark Mode ต้องลดน้ำหนักฟอนต์ลงอัตโนมัติ:
112
+ ```css
113
+ [data-theme="dark"] {
114
+ /* ถ้าเป็น Variable Font ที่มีแกน GRAD */
115
+ font-variation-settings: "GRAD" -25;
116
+ /* หรือถ้าเป็น Static Weight ให้ลดน้ำหนักลง 25–30 หน่วย */
117
+ --font-weight-normal: 375;
118
+ --font-weight-medium: 470;
119
+ }
120
+ ```
121
+
122
+ ### กฎข้อที่ 8: Rubber-Band Resistance Logarithm (กฎความหนืดเมื่อลากสุดขอบ)
123
+ - เมื่อผู้ใช้ลาก Drawer, Bottom Sheet หรือ Slider เกินจุดสิ้นสุด (Over-drag) ให้คำนวณระยะการเคลื่อนที่จริง ($d_{\text{rendered}}$) ด้วยสมการลอการิทึมของ iOS:
124
+ $$d_{\text{rendered}} = L_{\max} \times \left( 1 - \frac{1}{\frac{\Delta x \times c}{L_{\max}} + 1} \right) \quad (c = 0.55)$$
125
+
126
+ ### กฎข้อที่ 9: Subpixel Scrollbar Gutter & Safe-Area Symmetry
127
+ - บังคับใช้ `scrollbar-gutter: stable;` บนคอนเทนเนอร์ที่เลื่อนได้ทุกตัว เพื่อป้องกันหน้าจอกระตุก 15px เมื่อ Scrollbar ปรากฏขึ้น
128
+ - บนอุปกรณ์เคลื่อนที่ ต้องคำนวณระยะขอบล่างด้วย `padding-bottom: max(var(--space-md), env(safe-area-inset-bottom));` เพื่อไม่ให้ปุ่มโดนแถบ Home Indicator บดบัง
129
+
130
+ ### กฎข้อที่ 10: On-Demand WebGL Render Loop & VRAM Budget Gate
131
+ - สำหรับฉาก 3D Background หรือ CAD/GIS Viewer ที่ไม่มีการเคลื่อนไหวตลอดเวลา **ห้ามรัน `requestAnimationFrame` ต่อเนื่อง**
132
+ - ต้องใช้สถาปัตยกรรม **`frameloop="demand"`**: เรนเดอร์เฉพาะเฟรมที่มีการขยับเมาส์ ซูม หรือระหว่างที่สปริงกล้องยังขยับ เมื่อความเร็ว $\lvert v \rvert < 0.0001$ ให้ตัด Loop ทันทีเพื่อให้ GPU ใช้พลังงาน **0 วัตต์**
133
+ - **งบประมาณ VRAM:** ไฟล์โมเดล 3D ต้องใช้ **Meshopt Compression + KTX2 (Basis Universal) Textures** โดยจำกัดหน่วยความจำหลังคลายบีบอัดบน GPU ไม่เกิน **$32\text{MB}$**
134
+
135
+ ---
136
+
137
+ ## 2. ⚡ Modern CSS Engine Primitives (2026 Standards)
138
+
139
+ การใช้คุณสมบัติ CSS สมัยใหม่ช่วยตัดโค้ด JavaScript ที่ซับซ้อนทิ้งไปได้มากกว่า 70%:
140
+
141
+ | ฟีเจอร์ CSS 2026 | การแก้ปัญหาเชิงสถาปัตยกรรม | ไวยากรณ์ระดับ Production |
142
+ |---|---|---|
143
+ | **`light-dark(lightVal, darkVal)`** | ลดความซ้ำซ้อนของการเขียน `.dark { --var: ... }` และป้องกันปัญหาลืมอัปเดตคู่ตัวแปร | ประกาศ `color-scheme: light dark;` ที่ `:root` แล้วเขียนคู่สีในบรรทัดเดียว: `--surface: light-dark(oklch(0.99 0.002 260), oklch(0.14 0.008 260));` |
144
+ | **`text-box-trim` & `text-box-edge`** | ตัดช่องว่าง Half-leading ส่วนเกินของฟอนต์ออก ทำให้ปุ่มและ Badge อยู่กึ่งกลางแนวตั้งเป๊ะ | `@supports (text-box: trim-both cap alphabetic) { text-box: trim-both cap alphabetic; }` |
145
+ | **Popover API + `@starting-style`** | ทำ Modal/Dropdown ลอยบน Browser **Top Layer** (เหนือทุก `z-index`) พร้อมทำ Transition เข้า-ออกโดยไม่ต้องพึ่ง JS | `<div popover>` ควบคู่กับ `@starting-style` และ `transition-behavior: allow-discrete;` |
146
+ | **CSS Anchor Positioning** | ผูก Tooltip/Menu ติดกับปุ่ม พร้อมพลิกหลบขอบจออัตโนมัติบน Compositor Thread 120fps โดยไม่ต้องใช้ Floating UI | `position-anchor: --my-btn;` + `position-try-fallbacks: flip-block, flip-inline;` |
147
+ | **Scroll-Driven Animations** | เชื่อมไทม์ไลน์แอนิเมชันเข้ากับการเลื่อน Viewport โดยตรงที่ระดับ Compositor thread | `animation-timeline: view(); animation-range: entry 0% cover 25%;` (ครอบด้วย reduced-motion gate) |
148
+ | **OKLCH `color-mix()`** | สร้างโทนสี Hover, Focus, Selected และ Tinted Surfaces แบบไดนามิกจากแม่สีตัวแปรเดียว | `color-mix(in oklch, var(--surface-base) 88%, white)` |
149
+ | **`interpolate-size: allow-keywords`** | ปลดล็อกการทำ CSS Transition/Spring ไปหา `height: auto` ได้โดยตรงทั้งระบบ | กำหนด `interpolate-size: allow-keywords;` ที่ `:root` |
150
+
151
+ ### 2.A Scroll-Driven Progressive Animations & Reduced-Motion Gate
152
+ ```css
153
+ .section-reveal {
154
+ opacity: 1;
155
+ transform: none;
156
+ }
157
+ @media (prefers-reduced-motion: no-preference) {
158
+ @supports (animation-timeline: view()) {
159
+ .section-reveal[data-reveal] {
160
+ animation: section-enter linear both;
161
+ animation-timeline: view();
162
+ animation-range: entry 0% cover 25%;
163
+ }
164
+ @keyframes section-enter {
165
+ from { opacity: 0.55; transform: translateY(12px); }
166
+ to { opacity: 1; transform: translateY(0); }
167
+ }
168
+ }
169
+ }
170
+ ```
171
+
172
+ ### 2.B View Transitions Level 2: Semantic Transition Types
173
+ แทนการใช้ Fade/Spinner แบบเดียว ให้ผูก Transition เข้ากับเจตนาทางสถาปัตยกรรม (Intent):
174
+ | Transition Type | พฤติกรรม UX | การนำไปใช้ |
175
+ |---|---|---|
176
+ | `navigation-forward` | เลื่อนสไลด์ไปข้างหน้า (Drill down) | คลิกดูรายละเอียดแปลงที่ดิน / telemetry telemetry |
177
+ | `navigation-back` | ถอยหลังกลับสู่บริบทเดิม | กดย้อนกลับสู่ Dashboard หลัก |
178
+ | `content-update` | ข้อมูลเปลี่ยนแต่โครงสร้างเดิมนิ่งสนิท | สลับคู่เหรียญ / เปลี่ยนหน่วยพิกัด UTM |
179
+ | `selection-change` | มีแค่ Indicator วิ่งไปหาตัวเลือกใหม่ | สลับแท็บ / สลับเครื่องมือสำรวจ |
180
+ | `layout-reflow` | Bento Card ขยาย/ยุบตัวตามสัดส่วน | กางแถวตารางข้อมูลเชิงลึก |
181
+
182
+ ### 2.C Perceptual Intent Color Engine (OKLab vs OKLCH)
183
+ ยกเลิกการใช้กฎมุมองศาแข็งทื่อ ($\Delta H > 60^\circ$) และปรับใช้ **Perceptual Intent Rules**:
184
+ 1. **เมื่อต้องการรักษาความสดฉ่ำของคู่สี (Vibrant Chroma Trajectory):** บังคับใช้ `in oklch shorter hue`
185
+ 2. **เมื่อต้องการการเปลี่ยนผ่านความสว่างที่นุ่มนวลหรือไล่เข้าหา Neutral/White/Black:** บังคับใช้ `in oklab` เพื่อขจัดรอยตัดขอบที่ไม่สม่ำเสมอ
186
+ 3. **Midpoint Inspection Invariant:** ทดสอบความสว่างและความสดที่ตำแหน่ง `25%`, `50%`, และ `75%` ของ Gradient เสมอ เพื่อป้องกันสีหม่นเทาหรือวูบผิดเจตนา
187
+ 4. **Dynamic Token Derivation ผ่าน `color-mix()`:**
188
+ ```css
189
+ :root {
190
+ --color-accent: oklch(0.68 0.18 42); /* Terracotta */
191
+ --surface-base: oklch(0.14 0.008 260); /* Obsidian Base */
192
+
193
+ /* สร้างพื้นผิวยกระดับและสถานะโดยไม่ต้องฮาร์ดโค้ด Hex */
194
+ --surface-raised: color-mix(in oklch, var(--surface-base) 88%, white);
195
+ --surface-hover: color-mix(in oklch, var(--surface-base) 90%, var(--color-accent));
196
+ --border-subtle: color-mix(in oklch, var(--surface-base) 82%, white);
197
+ }
198
+ ```
199
+ 5. **Functional Dark Mode Neutrals:** กำหนด Token ตามหน้าที่ ไม่พึ่งพาเพียงแค่ค่าตัวเลข Chroma:
200
+ - `--surface-canvas`: พื้นหลังลึกสุด (`oklch(0.10 0.006 260)`) ควบคู่ OLED Black `#000000`
201
+ - `--surface-raised`: การ์ดและคอนเทนเนอร์ลอย (`oklch(0.14 0.008 260)`)
202
+ - `--surface-inset`: พื้นที่กรอกข้อมูล / หน้าจอแผนที่ (`oklch(0.12 0.006 260)`)
203
+ - `--border-subtle`: เส้นแบ่งความคมชัดต่ำที่ไม่แย่งความสนใจ
204
+ - `--border-focus`: เส้นโฟกัสความคมชัดสูง (>3:1 ต่อพื้นผิว)
205
+
206
+ ### 2.D Anchor Positioning & Interactive Popover Menu
207
+ ```css
208
+ :root {
209
+ color-scheme: light dark;
210
+ interpolate-size: allow-keywords;
211
+
212
+ --surface-popover: light-dark(oklch(0.99 0.002 260 / 0.90), oklch(0.16 0.008 260 / 0.88));
213
+ --border-popover: light-dark(oklch(0.15 0.008 260 / 0.08), oklch(1.00 0.000 0 / 0.10));
214
+ }
215
+
216
+ .trigger-btn {
217
+ anchor-name: --menu-anchor;
218
+ }
219
+
220
+ .popover-menu[popover] {
221
+ position: fixed;
222
+ position-anchor: --menu-anchor;
223
+ top: calc(anchor(bottom) + 6px);
224
+ left: anchor(left);
225
+ position-try-fallbacks: flip-block, flip-inline;
226
+
227
+ background: var(--surface-popover);
228
+ backdrop-filter: blur(20px) saturate(180%);
229
+ border-radius: 10px;
230
+ box-shadow: 0 0 0 1px var(--border-popover), 0 12px 32px -4px oklch(0 0 0 / 0.28);
231
+
232
+ opacity: 0;
233
+ transform: scale(0.96) translateY(-4px);
234
+ transition:
235
+ opacity 160ms ease,
236
+ transform 200ms cubic-bezier(0.16, 1, 0.3, 1),
237
+ overlay 200ms allow-discrete,
238
+ display 200ms allow-discrete;
239
+ }
240
+
241
+ .popover-menu[popover]:popover-open {
242
+ opacity: 1;
243
+ transform: scale(1) translateY(0);
244
+ }
245
+
246
+ @starting-style {
247
+ .popover-menu[popover]:popover-open {
248
+ opacity: 0;
249
+ transform: scale(0.96) translateY(-4px);
250
+ }
251
+ }
252
+ ```
253
+
254
+ ---
255
+
256
+ ## 3. 📐 Optical Geometry & Spacing Mathematics
257
+
258
+ ### 3.1 Optical Centering ของไอคอนสามเหลี่ยม (Play Button)
259
+ จุดศูนย์ถ่วงมวล (Centroid) ของสามเหลี่ยมด้านเท่าที่มีความกว้าง $W$ อยู่ที่ระยะ $\frac{1}{3}W$ จากฐาน ในขณะที่ Bounding Box กึ่งกลางอยู่ที่ $\frac{1}{2}W$
260
+ - **ระยะชดเชยที่ถูกต้อง:** ต้องเลื่อนไอคอนไปทางขวาตามแนวแกน X:
261
+ $$\Delta x = \frac{W}{2} - \frac{W}{3} = \frac{W}{6} \approx 0.167 \times W \quad (\text{หรือ } \frac{W}{8} \text{ สำหรับไอคอนขอบมน})$$
262
+
263
+ ### 3.2 Concentric Border Radius & Smooth Morphing Invariant
264
+ - **สูตรคำนวณ Safe Concentric Radius:**
265
+ $$R_{\text{inner}} = \max\left(0\text{px}, \; R_{\text{outer}} - B_{\text{width}} - \text{Padding}\right)$$
266
+ - ป้องกันค่าติดลบจน Browser ทิ้งคำสั่ง และชดเชยความหนาของขอบ Border จริง
267
+ - **Morphing Invariant (Finite Geometry vs Infinity):**
268
+ - สำหรับรูปทรงสถิต (Static Pills): อนุญาตให้ใช้ `calc(infinity * 1px)` หรือ `999px`
269
+ - สำหรับรูปทรงที่มีการ Animate / Morphing ระหว่างสี่เหลี่ยมผืนผ้าไปเป็นวงรี/แคปซูล: **ห้ามใช้ infinity** เพราะจะทำให้การ Interpolate ขอบกระตุก ให้ผูกกับมิติทางเรขาคณิตจริง เช่น `calc(var(--el-height) / 2)` หรือลงทะเบียนผ่าน `@property <length>` เสมอเพื่อความราบรื่นระดับ 120fps:
270
+ ```css
271
+ @property --corner-r {
272
+ syntax: "<length>";
273
+ inherits: false;
274
+ initial-value: 8px;
275
+ }
276
+ .morphing-surface {
277
+ border-radius: var(--corner-r);
278
+ transition: --corner-r 260ms cubic-bezier(0.16, 1, 0.3, 1);
279
+ }
280
+ ```
281
+
282
+ ### 3.3 Doppelrand (Double-Border Specular Catch-Light)
283
+ เทคนิคจำลองขอบ Anodized Aluminum และการ์ดระดับ Linear:
284
+ ```css
285
+ .surface-doppelrand {
286
+ background: oklch(0.16 0.008 260 / 0.85);
287
+ backdrop-filter: blur(16px) saturate(180%);
288
+ border-radius: 12px;
289
+ /* Layer 1: Outer dark hairline (1px)
290
+ Layer 2: Top edge specular highlight (1px inset)
291
+ Layer 3: Omnidirectional inner rim (1px inset) */
292
+ box-shadow:
293
+ 0 0 0 1px oklch(0.08 0.008 260 / 0.90),
294
+ inset 0 1px 0 0 oklch(1 0 0 / 0.14),
295
+ inset 0 0 0 1px oklch(1 0 0 / 0.04);
296
+ }
297
+ ```
298
+
299
+ ### 3.4 Multi-Layered Exponential Ambient Shadows
300
+ จำลองการกระจายตัวของแสงในธรรมชาติด้วยสมการ Exponential Progression ($y_n = 2^{n-1}, \sigma_n = 2y_n$):
301
+ ```css
302
+ :root {
303
+ --shadow-hue: 260;
304
+ --elevation-high:
305
+ 0px 1px 1px -0.5px oklch(0.05 0.01 var(--shadow-hue) / 0.36),
306
+ 0px 3px 6px -1.5px oklch(0.05 0.01 var(--shadow-hue) / 0.28),
307
+ 0px 8px 16px -4px oklch(0.05 0.01 var(--shadow-hue) / 0.22),
308
+ 0px 20px 40px -8px oklch(0.05 0.01 var(--shadow-hue) / 0.16),
309
+ 0px 0px 0px 1px oklch(0.05 0.01 var(--shadow-hue) / 0.60);
310
+ }
311
+ ```
312
+
313
+ ### 3.5 Fluid Typography & Spacing Math (`clamp()`)
314
+ สมการเส้นตรง $y = mx + b$ สำหรับปรับขนาดฟอนต์ระหว่าง Viewport $375\text{px}$ ถึง $1440\text{px}$ แบบไร้รอยต่อ:
315
+ ```css
316
+ :root {
317
+ --text-xs: clamp(0.75rem, 0.7148rem + 0.1502vw, 0.85rem);
318
+ --text-sm: clamp(0.875rem, 0.8310rem + 0.1878vw, 1.00rem);
319
+ --text-base: clamp(1.00rem, 0.9472rem + 0.2254vw, 1.15rem);
320
+ --text-lg: clamp(1.25rem, 1.1620rem + 0.3756vw, 1.50rem);
321
+ --text-xl: clamp(1.625rem, 1.4049rem + 0.9390vw, 2.25rem);
322
+ --text-2xl: clamp(2.25rem, 1.6338rem + 2.6291vw, 4.00rem);
323
+ }
324
+ ```
325
+
326
+ ---
327
+
328
+ ## 4. 🧬 2.5-Tier Token Architecture & Polarity Discipline
329
+
330
+ เพื่อป้องกันปัญหา CSS Variable Waterfall Cascade บนตารางข้อมูลขนาดใหญ่ ให้ใช้สถาปัตยกรรม **2.5-Tier**:
331
+ 1. **Tier 1 (Primitives) & Tier 2 (Semantics):** กำหนดไว้ที่ `:root` ผ่านฟังก์ชัน `light-dark()`
332
+ 2. **Tier 3 (Components):** ห้ามประกาศเป็น Global Tokens เด็ดขาด ให้ใช้เป็น **Private Scoped Aliases** ที่ขึ้นต้นด้วย Underscore (`--_bg`, `--_border`, `--_text`) ภายใน Class ของ Component นั้นๆ เท่านั้น
@@ -0,0 +1,99 @@
1
+ # Motion Design Tokens (Takayu Studio Framework)
2
+
3
+ ระบบตัวแปร Motion & Animation ระดับ Production ดัดแปลงจาก Takayu Studio Motion Reference (782 Demos) เพื่อเปลี่ยน Animation เชยๆ แบบสุ่ม (`0.3s ease`) ให้กลายเป็นความรู้สึกสัมผัสที่มีน้ำหนักและประณีต (High-Fidelity Tactile Feel)
4
+
5
+ ---
6
+
7
+ ## 1. The 5 Feel Archetypes (บุคลิกความรู้สึก 5 ระดับ)
8
+
9
+ | Archetype | Feel & Sensation | Duration (ms) | Cubic-Bezier Curve | Component Mappings |
10
+ | :--- | :--- | :--- | :--- | :--- |
11
+ | **1. Crisp** | เฉียบคม ฉับไว แม่นยำ | `120 - 180ms` | `cubic-bezier(0.2, 0.0, 0.0, 1.0)` | ปุ่มกด (Button active), Toggle, Tooltip, Checkbox, Icon tap |
12
+ | **2. Smooth** | ลื่นไหล เป็นธรรมชาติ มีจังหวะ | `250 - 350ms` | `cubic-bezier(0.4, 0.0, 0.2, 1.0)` | Dropdown menu, Tab switch, Accordion, Modal slide-in |
13
+ | **3. Soft** | นุ่มนวล ละมุนตา ไม่เร่งรีบ | `400 - 500ms` | `cubic-bezier(0.25, 1.0, 0.5, 1.0)` | Backdrop fade, Hero section reveal, Toast entry, Skeleton pulse |
14
+ | **4. Heavy** | หนักแน่น มีมวลแรงโน้มถ่วง | `500 - 700ms` | `cubic-bezier(0.7, 0.0, 0.3, 1.0)` | Drawer slide-up, Fullscreen sheet, Large card expansion |
15
+ | **5. Bouncy** | เด้งดึ๋ง สปริง มีพลัง (Overshoot) | `350 - 500ms` | `cubic-bezier(0.34, 1.56, 0.64, 1.0)` | Notification badge pop, Success checkmark, Like heart, Pin drop |
16
+
17
+ ---
18
+
19
+ ## 2. Standard CSS Variables (`:root`)
20
+
21
+ คัดลอกชุดตัวแปรนี้ไปวางในไฟล์ CSS หลัก (`globals.css` หรือ `design-tokens.css`):
22
+
23
+ ```css
24
+ :root {
25
+ /* --- Duration Tokens --- */
26
+ --motion-duration-instant: 100ms;
27
+ --motion-duration-crisp: 180ms;
28
+ --motion-duration-smooth: 300ms;
29
+ --motion-duration-soft: 450ms;
30
+ --motion-duration-heavy: 600ms;
31
+
32
+ /* --- Easing Curves (Cubic-Bezier) --- */
33
+ --motion-ease-crisp: cubic-bezier(0.2, 0.0, 0.0, 1.0);
34
+ --motion-ease-smooth: cubic-bezier(0.4, 0.0, 0.2, 1.0);
35
+ --motion-ease-soft: cubic-bezier(0.25, 1.0, 0.5, 1.0);
36
+ --motion-ease-heavy: cubic-bezier(0.7, 0.0, 0.3, 1.0);
37
+ --motion-ease-bouncy: cubic-bezier(0.34, 1.56, 0.64, 1.0);
38
+
39
+ /* --- Composite Transition Tokens --- */
40
+ --transition-button: transform var(--motion-duration-crisp) var(--motion-ease-crisp),
41
+ background-color var(--motion-duration-crisp) var(--motion-ease-crisp);
42
+ --transition-dropdown: opacity var(--motion-duration-smooth) var(--motion-ease-smooth),
43
+ transform var(--motion-duration-smooth) var(--motion-ease-smooth);
44
+ --transition-modal: opacity var(--motion-duration-smooth) var(--motion-ease-smooth),
45
+ transform var(--motion-duration-smooth) var(--motion-ease-smooth);
46
+ --transition-drawer: transform var(--motion-duration-heavy) var(--motion-ease-heavy);
47
+ --transition-badge: transform var(--motion-duration-smooth) var(--motion-ease-bouncy);
48
+ }
49
+ ```
50
+
51
+ ---
52
+
53
+ ## 3. Tailwind CSS Integration (`tailwind.config.js`)
54
+
55
+ ```javascript
56
+ module.exports = {
57
+ theme: {
58
+ extend: {
59
+ transitionDuration: {
60
+ 'instant': '100ms',
61
+ 'crisp': '180ms',
62
+ 'smooth': '300ms',
63
+ 'soft': '450ms',
64
+ 'heavy': '600ms',
65
+ },
66
+ transitionTimingFunction: {
67
+ 'crisp': 'cubic-bezier(0.2, 0.0, 0.0, 1.0)',
68
+ 'smooth': 'cubic-bezier(0.4, 0.0, 0.2, 1.0)',
69
+ 'soft': 'cubic-bezier(0.25, 1.0, 0.5, 1.0)',
70
+ 'heavy': 'cubic-bezier(0.7, 0.0, 0.3, 1.0)',
71
+ 'bouncy': 'cubic-bezier(0.34, 1.56, 0.64, 1.0)',
72
+ },
73
+ },
74
+ },
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## 4. Framer Motion / Spring Physics Presets
81
+
82
+ สำหรับ React และ Next.js ที่ใช้ `framer-motion`:
83
+
84
+ ```typescript
85
+ export const motionSpring = {
86
+ crisp: { type: "spring", stiffness: 500, damping: 30, mass: 0.8 },
87
+ smooth: { type: "spring", stiffness: 350, damping: 25, mass: 1 },
88
+ heavy: { type: "spring", stiffness: 220, damping: 28, mass: 1.5 },
89
+ bouncy: { type: "spring", stiffness: 400, damping: 15, mass: 1 },
90
+ };
91
+ ```
92
+
93
+ ---
94
+
95
+ ## 5. Best Practices & Invariants
96
+
97
+ 1. **ห้ามใช้ `transition: all 0.3s ease` มักง่าย:** ให้ระบุ Properties ชัดเจน (`transform`, `opacity`) เสมอเพื่อประสิทธิภาพ GPU Render (60-120fps)
98
+ 2. **Reduced Motion Respect:** ต้องรองรับ `@media (prefers-reduced-motion: reduce)` เสมอ สำหรับผู้ใช้ที่เวียนหัวจากภาพเคลื่อนไหว
99
+ 3. **Data-Dense UIs (Trading/Survey):** ในตารางข้อมูล แดชบอร์ดคำนวณ ห้ามใส่ Motion นานเกิน $150\text{ms}$ (ใช้เฉพาะ Crisp หรือ Instant เท่านั้น)
@@ -0,0 +1,110 @@
1
+ ## 6. PERFORMANCE & ACCESSIBILITY GUARDRAILS
2
+
3
+ ### 6.A Hardware Acceleration
4
+ * Animate ONLY `transform` and `opacity`. Never animate `top`, `left`, `width`, `height`.
5
+ * Use `will-change: transform` sparingly - only on elements that will actually animate.
6
+
7
+ ### 6.B Reduced Motion (mandatory)
8
+ * **Any motion above `MOTION_INTENSITY > 3` MUST honor `prefers-reduced-motion`.** This is non-negotiable.
9
+ * In Motion: wrap with `useReducedMotion()` and degrade to static.
10
+ * In CSS: gate animations behind `@media (prefers-reduced-motion: no-preference)` or provide an override block under `@media (prefers-reduced-motion: reduce)` that disables.
11
+ * Infinite loops, parallax, scroll-hijack, and magnetic physics MUST collapse to static / instant under reduced motion.
12
+
13
+ ### 6.C Dark Mode (mandatory for any consumer-facing page)
14
+ * Design for **both modes from the start**. Never ship light-only or dark-only without explicit user instruction.
15
+ * Use Tailwind `dark:` variant OR CSS variables for tokens. Pick one strategy per project.
16
+ * **Do not prescribe specific dark-mode colors here.** The brief decides. Maintain visual hierarchy, brand identity, and WCAG AA contrast (AAA for body) across both modes.
17
+ * Respect `prefers-color-scheme: dark`. Default to system preference unless the brand insists on one mode.
18
+
19
+ ### 6.D Core Web Vitals Targets
20
+ * **LCP** < 2.5s. Hero image must be `next/image priority` or preloaded.
21
+ * **INP** < 200ms. Heavy work off main thread.
22
+ * **CLS** < 0.1. Reserve space for images, fonts, embeds.
23
+ * Run Lighthouse before declaring a page done.
24
+
25
+ ### 6.E DOM Cost
26
+ * Apply grain / noise filters EXCLUSIVELY to fixed, `pointer-events-none` pseudo-elements (e.g., `fixed inset-0 z-[60] pointer-events-none`). NEVER on scrolling containers - continuous GPU repaints destroy mobile FPS.
27
+ * Be aware of bundle size. Motion is not tiny. Three.js is large. Lazy-load anything that's not above-the-fold.
28
+
29
+ ### 6.F Z-Index Restraint
30
+ NEVER spam arbitrary `z-50` or `z-10`. Use z-index strictly for systemic layer contexts (sticky navbars, modals, overlays, grain). Document the z-index scale in a project constants file.
31
+
32
+ ---
33
+
34
+ ## 14. FINAL PRE-FLIGHT CHECK
35
+
36
+ Run this matrix before outputting code. This is the last filter.
37
+
38
+ **THIS IS NOT OPTIONAL. Run every box. If any box fails, the output is not done.**
39
+
40
+ - [ ] **Brief inference** declared (Section 0.B one-liner)?
41
+ - [ ] **Dial values** explicit and reasoned from the brief, not silently using baseline?
42
+ - [ ] **Design system** chosen from Section 2 if applicable, or aesthetic labeled honestly?
43
+ - [ ] **Redesign mode** detected and audit performed (if applicable, Section 11)?
44
+ - [ ] **ZERO em-dashes (`—`) anywhere on the page.** Headlines, eyebrows, pills, body, quotes, attribution, captions, buttons, alt text. Zero. (Section 9.G - non-negotiable.)
45
+ - [ ] **Page Theme Lock**: ONE theme (light, dark, or auto) for the whole page. No section flips to inverted mode mid-page (Section 4.11)?
46
+ - [ ] **Color Consistency Lock**: one accent color used identically across all sections (Section 4.2)?
47
+ - [ ] **Shape Consistency Lock**: one corner-radius system applied consistently (Section 4.4)?
48
+ - [ ] **Button Contrast Check**: every CTA text is readable against its background (no white-on-white, WCAG AA 4.5:1)?
49
+ - [ ] **CTA Button Wrap**: no CTA label wraps to 2+ lines at desktop?
50
+ - [ ] **Form Contrast Check**: form inputs, placeholders, focus rings, labels all pass WCAG AA against the section background?
51
+ - [ ] **Serif discipline**: if a serif is used, it is NOT Fraunces or Instrument_Serif (or it is, with explicit brand justification)? Different serif from your previous project?
52
+ - [ ] **Premium-consumer palette check**: if the brief is premium-consumer (cookware / wellness / artisan / luxury), the palette is NOT the AI-default beige+brass+oxblood+espresso family? Different family from your previous premium-consumer project?
53
+ - [ ] **Italic descender clearance**: every italic word with `y g j p q` has `leading-[1.1]` min + `pb-1` reserve?
54
+ - [ ] **Hero fits the viewport**: headline ≤ 2 lines, subtext ≤ 20 words AND ≤ 4 lines, CTA visible without scroll, font scale planned around image?
55
+ - [ ] **Hero top padding**: max `pt-24` at desktop, hero content does not float halfway down the viewport?
56
+ - [ ] **Hero stack discipline**: max 4 text elements in hero (eyebrow OR brand strip, headline, subtext, CTAs)? No tiny tagline below CTAs, no trust micro-strip in hero?
57
+ - [ ] **EYEBROW COUNT (mechanical)**: count instances of `uppercase tracking` micro-labels above section headlines across all components. Count ≤ ceil(sectionCount / 3)? Hero counts as 1.
58
+ - [ ] **Split-Header Ban**: no "left big headline + right small explainer paragraph" pattern as a section header (vertical stack instead)?
59
+ - [ ] **Zigzag Alternation Cap**: no 3+ consecutive sections with the same image+text-split layout?
60
+ - [ ] **No Duplicate CTA Intent**: no two CTAs with the same intent ("Get in touch" + "Let's talk" both on page = Fail)?
61
+ - [ ] **Logo wall = logo only**: no industry / category labels printed below logos?
62
+ - [ ] **Bento Background Diversity**: at least 2-3 bento cells have real visual variation (image, gradient, pattern), not all white-on-white text cards?
63
+ - [ ] **"Used by / Trusted by" logo wall** lives UNDER the hero, not inside it, uses REAL SVG logos (Simple Icons / devicon) or generated SVG marks, NOT plain text wordmarks?
64
+ - [ ] **Copy Self-Audit**: every visible string re-read, no grammatically-broken or AI-hallucinated phrases ("free on its past" type) shipped?
65
+ - [ ] **Motion motivated**: every animation can be justified in one sentence (hierarchy / storytelling / feedback / state transition), no GSAP-for-show?
66
+ - [ ] **Marquee max-one-per-page**: no two horizontal marquees on the same page?
67
+ - [ ] **Navigation on ONE line** at desktop, height ≤ 80px?
68
+ - [ ] **Section-Layout-Repetition** check: no two sections share the same layout family (at least 4 different families across 8 sections)?
69
+ - [ ] **Bento has rhythm AND exact cell count** (N items → N cells, no empty cells in middle or at end)?
70
+ - [ ] **Long lists use the right UI component** (not default `<ul>` with `divide-y` for > 5 items - see Section 4.9 alternatives)?
71
+ - [ ] **Real images used** (gen-tool first, then Picsum-seed, then explicit placeholder slots) - NO div-based fake screenshots, NO hand-rolled decorative SVGs, NO pure-text minimalism?
72
+ - [ ] **No pills/labels overlaid on images** (no `Plate · Brand`, no `Field notes - journal`)?
73
+ - [ ] **No photo-credit captions as decoration** (`Field study no. 12 · Ines Caetano`)?
74
+ - [ ] **No version footers** (`v1.4.2`, `Build 0048`) on marketing pages?
75
+ - [ ] **No micro-meta-sentences** under eyebrows ("Each of these is a feature we ship today...")?
76
+ - [ ] **No decoration text strip at hero bottom** (`BRAND. MOTION. SPATIAL.`)?
77
+ - [ ] **No floating top-right sub-text** in section headings?
78
+ - [ ] **No scoring/progress bars with filled background tracks** as comparison visuals?
79
+ - [ ] **No locale / city-name / time / weather strips** unless brief is genuinely globally-distributed or place-focused?
80
+ - [ ] **No scroll cues** (`Scroll`, `↓ scroll`, `Scroll to explore`)?
81
+ - [ ] **No version labels in hero** (V0.6, BETA, INVITE-ONLY) unless the brief is a launch?
82
+ - [ ] **No section-numbering eyebrows** (`00 / INDEX`, `001 · Capabilities`, `06 · how it works`)?
83
+ - [ ] **No decorative dots** (zero by default, only for real semantic state)?
84
+ - [ ] **No `border-t` + `border-b` on every row** of long lists / spec tables?
85
+ - [ ] **Content density** sane: no 20-row data tables, no fake-precise specs without justification, ≤ 25-word sub-paragraphs by default?
86
+ - [ ] **Quotes ≤ 3 lines** of body, attribution clean (no em-dash)?
87
+ - [ ] **Motion claimed = motion shown**: if `MOTION_INTENSITY > 4`, page actually animates, not just claimed?
88
+ - [ ] **GSAP sticky-stack / horizontal-pan** implemented per Section 5.A / 5.B canonical skeleton (`start: "top top"`, `pin: true`, correct scrub)?
89
+ - [ ] **No `window.addEventListener('scroll')`** - using Motion `useScroll()` / ScrollTrigger / IntersectionObserver / CSS scroll-driven animations only?
90
+ - [ ] **Reduced motion** wrapped for everything `MOTION_INTENSITY > 3`?
91
+ - [ ] **Dark mode** tokens defined and tested in both modes?
92
+ - [ ] **Mobile collapse** explicit (`w-full`, `px-4`, `max-w-7xl mx-auto`) for high-variance layouts?
93
+ - [ ] **Viewport stability**: `min-h-[100dvh]`, never `h-screen`?
94
+ - [ ] **`useEffect` animations** have strict cleanup functions?
95
+ - [ ] **Empty / loading / error** states provided?
96
+ - [ ] **Cards omitted** in favor of spacing where possible?
97
+ - [ ] **Icons** from an allowed library only (Phosphor / HugeIcons / Radix / Tabler), no hand-rolled SVG paths?
98
+ - [ ] **Motion** isolated in client-leaf components with `'use client'` at the top, memoized?
99
+ - [ ] **No AI Tells** from Section 9 (Inter as default, AI-purple, three-equal cards, Jane Doe, Acme, "Quietly in use at")?
100
+ - [ ] **Core Web Vitals** plausibly hit (LCP < 2.5s, INP < 200ms, CLS < 0.1)?
101
+ - [ ] **One design system** per project (no Material + shadcn mixed)?
102
+
103
+ If a single checkbox cannot be honestly ticked, the page is not done. Fix it before delivering.
104
+
105
+ ---
106
+
107
+ # APPENDICES - Real Source-Backed Reference Material
108
+
109
+ The sections below are vendored reference content. They give the agent real install commands, real canonical doc links, and real working starter snippets for each design system named in Section 2. Use them to ground decisions in production reality, not training-data fiction.
110
+