-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathllms-full.txt
More file actions
926 lines (798 loc) · 96 KB
/
Copy pathllms-full.txt
File metadata and controls
926 lines (798 loc) · 96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
# melta UI — llms-full.txt
> 主要ドキュメントの全文連結(scripts/design/build-llms-txt.ts で生成。直接編集しない)。
> インデックス版: https://raw.githubusercontent.com/tsubotax/melta-ui/main/llms.txt
===== DESIGN.md =====
---
# Generated from design/contracts/tokens.json by scripts/design/export-designmd.ts — do not edit by hand.
# Format: Google DESIGN.md spec (github.com/google-labs-code/design.md). SSOT remains design/contracts/.
version: alpha
name: melta UI
description: 声を張らずに伝わる UI — Quiet Precision / Breathable / Flat & Layered / Subtle Warmth
colors:
primary: "#2b70ef"
primary-50: "#f0f5ff"
primary-100: "#dde8ff"
primary-200: "#c0d4ff"
primary-300: "#95b6ff"
primary-400: "#6492ff"
primary-500: "#2b70ef"
primary-600: "#2250df"
primary-700: "#1a40b5"
primary-800: "#13318d"
primary-900: "#0e266a"
primary-950: "#07194e"
body: "#3d4b5f"
neutral: "#f9fafb"
success: "#059669"
warning: "#d97706"
danger: "#dc2626"
typography:
h1:
fontFamily: Inter
fontSize: 2rem
lineHeight: 1.4
letterSpacing: 0.01em
h2:
fontFamily: Inter
fontSize: 1.625rem
lineHeight: 1.4
letterSpacing: 0.01em
h3:
fontFamily: Inter
fontSize: 1.375rem
lineHeight: 1.4
letterSpacing: 0.01em
body-lg:
fontFamily: Inter
fontSize: 1.25rem
lineHeight: 1.5
letterSpacing: 0.02em
body:
fontFamily: Inter
fontSize: 1.125rem
lineHeight: 2.0
letterSpacing: 0.02em
body-sm:
fontFamily: Inter
fontSize: 0.9375rem
lineHeight: 1.7
letterSpacing: 0.02em
caption:
fontFamily: Inter
fontSize: 0.8125rem
lineHeight: 1.4
letterSpacing: 0.02em
rounded:
sm: 0.25rem
md: 0.5rem
lg: 0.75rem
full: 9999px
spacing:
"1": 4px
"2": 8px
"3": 12px
"4": 16px
"5": 20px
"6": 24px
"8": 32px
"10": 40px
"12": 48px
"14": 56px
"16": 64px
components:
accordion-single:
rounded: "{rounded.md}"
accordion-multiple:
rounded: "{rounded.md}"
alert-info:
backgroundColor: "{colors.primary-50}"
textColor: "{colors.primary-800}"
rounded: "{rounded.md}"
padding: 16px
alert-success:
backgroundColor: "#ecfdf5"
textColor: "#065f46"
rounded: "{rounded.md}"
padding: 16px
alert-warning:
backgroundColor: "#fffbeb"
textColor: "#92400e"
rounded: "{rounded.md}"
padding: 16px
alert-error:
backgroundColor: "#fef2f2"
textColor: "#991b1b"
rounded: "{rounded.md}"
padding: 16px
avatar-image:
height: 40px
rounded: "{rounded.full}"
avatar-initials:
height: 40px
rounded: "{rounded.full}"
backgroundColor: "{colors.primary-50}"
textColor: "{colors.primary-600}"
badge-neutral:
rounded: "{rounded.full}"
backgroundColor: "#f1f5f9"
textColor: "#334155"
badge-success:
rounded: "{rounded.full}"
backgroundColor: "#ecfdf5"
textColor: "#047857"
badge-warning:
rounded: "{rounded.full}"
backgroundColor: "#fffbeb"
textColor: "#b45309"
badge-danger:
rounded: "{rounded.full}"
backgroundColor: "#fef2f2"
textColor: "#b91c1c"
badge-accent:
rounded: "{rounded.full}"
backgroundColor: "{colors.primary-50}"
textColor: "{colors.primary-700}"
button-contained:
height: 40px
backgroundColor: "{colors.primary-500}"
textColor: "#ffffff"
rounded: "{rounded.md}"
button-contained-hover:
backgroundColor: "{colors.primary-700}"
button-outlined:
height: 40px
backgroundColor: "#ffffff"
textColor: "#334155"
rounded: "{rounded.md}"
button-outlined-hover:
backgroundColor: "{colors.neutral}"
button-brand-outline:
height: 40px
textColor: "{colors.primary-500}"
backgroundColor: "#ffffff"
rounded: "{rounded.md}"
button-brand-outline-hover:
backgroundColor: "{colors.primary-50}"
button-neutral:
height: 40px
backgroundColor: "#f1f5f9"
textColor: "#334155"
rounded: "{rounded.md}"
button-neutral-hover:
backgroundColor: "#e2e8f0"
button-lighted:
height: 40px
backgroundColor: "{colors.primary-50}"
textColor: "{colors.primary-600}"
rounded: "{rounded.md}"
button-lighted-hover:
backgroundColor: "{colors.primary-100}"
button-danger:
height: 40px
backgroundColor: "{colors.danger}"
textColor: "#ffffff"
rounded: "{rounded.md}"
button-danger-hover:
backgroundColor: "#b91c1c"
button-subtle:
height: 40px
textColor: "#334155"
rounded: "{rounded.md}"
button-subtle-hover:
backgroundColor: "{colors.neutral}"
card-basic:
backgroundColor: "#ffffff"
rounded: "{rounded.lg}"
padding: 24px
card-media:
backgroundColor: "#ffffff"
rounded: "{rounded.lg}"
card-action:
backgroundColor: "#ffffff"
rounded: "{rounded.lg}"
padding: 24px
card-link:
backgroundColor: "#ffffff"
rounded: "{rounded.lg}"
padding: 24px
checkbox-default:
height: 16px
checkbox-disabled:
height: 16px
checkbox-indeterminate:
height: 16px
copy-button-outlined:
backgroundColor: "#ffffff"
datepicker-trigger:
rounded: "{rounded.md}"
backgroundColor: "#ffffff"
datepicker-calendar:
backgroundColor: "#ffffff"
rounded: "{rounded.lg}"
padding: 16px
datepicker-day-cell:
height: 40px
rounded: "{rounded.md}"
dropdown-basic:
backgroundColor: "#ffffff"
rounded: "{rounded.md}"
dropdown-with-icons:
backgroundColor: "#ffffff"
rounded: "{rounded.md}"
dropdown-with-separator:
backgroundColor: "#ffffff"
rounded: "{rounded.md}"
list-link:
textColor: "{colors.body}"
list-link-hover:
backgroundColor: "{colors.neutral}"
list-information:
textColor: "{colors.body}"
list-action:
textColor: "{colors.body}"
list-action-hover:
backgroundColor: "{colors.neutral}"
pagination-active:
height: 40px
textColor: "#ffffff"
backgroundColor: "{colors.primary-500}"
rounded: "{rounded.md}"
pagination-inactive:
height: 40px
textColor: "#334155"
backgroundColor: "#ffffff"
rounded: "{rounded.md}"
pagination-inactive-hover:
backgroundColor: "{colors.neutral}"
pagination-disabled:
height: 40px
textColor: "#cbd5e1"
progress-primary:
backgroundColor: "#e2e8f0"
rounded: "{rounded.full}"
height: 8px
progress-success:
backgroundColor: "#e2e8f0"
rounded: "{rounded.full}"
height: 8px
progress-indeterminate:
backgroundColor: "#e2e8f0"
rounded: "{rounded.full}"
height: 8px
select-default:
rounded: "{rounded.md}"
select-error:
rounded: "{rounded.md}"
backgroundColor: "#fef2f2"
select-disabled:
rounded: "{rounded.md}"
backgroundColor: "#f1f5f9"
textColor: "#94a3b8"
sidebar-standard:
backgroundColor: "#ffffff"
sidebar-compact:
backgroundColor: "#ffffff"
sidebar-drawer:
backgroundColor: "#ffffff"
skeleton-text:
backgroundColor: "#e2e8f0"
rounded: 6px
height: 16px
skeleton-card:
backgroundColor: "#ffffff"
rounded: "{rounded.lg}"
padding: 24px
skeleton-circle:
backgroundColor: "#e2e8f0"
rounded: "{rounded.full}"
height: 40px
tabs-underline-active:
textColor: "{colors.primary-500}"
tabs-underline-inactive:
textColor: "#64748b"
tabs-bar-active:
textColor: "#0f172a"
tabs-bar-active-hover:
backgroundColor: "#f1f5f9"
tabs-bar-inactive:
textColor: "#94a3b8"
tabs-bar-inactive-hover:
backgroundColor: "#f1f5f9"
tag-basic:
rounded: "{rounded.full}"
backgroundColor: "#f1f5f9"
textColor: "#334155"
tag-removable:
rounded: "{rounded.full}"
backgroundColor: "#f1f5f9"
textColor: "#334155"
tag-filter-chip:
rounded: "{rounded.full}"
backgroundColor: "#ffffff"
textColor: "#334155"
textfield-default:
rounded: "{rounded.md}"
textfield-error:
rounded: "{rounded.md}"
backgroundColor: "#fef2f2"
textfield-disabled:
rounded: "{rounded.md}"
backgroundColor: "#f1f5f9"
textColor: "#94a3b8"
textfield-success:
rounded: "{rounded.md}"
toast-success:
backgroundColor: "#ecfdf5"
textColor: "#065f46"
rounded: "{rounded.md}"
padding: 16px
toast-error:
backgroundColor: "#fef2f2"
textColor: "#991b1b"
rounded: "{rounded.md}"
padding: 16px
toast-warning:
backgroundColor: "#fffbeb"
textColor: "#92400e"
rounded: "{rounded.md}"
padding: 16px
toast-info:
backgroundColor: "{colors.primary-50}"
textColor: "{colors.primary-800}"
rounded: "{rounded.md}"
padding: 16px
toggle-off:
height: 24px
rounded: "{rounded.full}"
backgroundColor: "#cbd5e1"
toggle-on:
height: 24px
rounded: "{rounded.full}"
backgroundColor: "{colors.primary-500}"
tooltip-top:
backgroundColor: "#475569"
textColor: "#ffffff"
rounded: "{rounded.md}"
tooltip-bottom:
backgroundColor: "#475569"
textColor: "#ffffff"
rounded: "{rounded.md}"
tooltip-left:
backgroundColor: "#475569"
textColor: "#ffffff"
rounded: "{rounded.md}"
tooltip-right:
backgroundColor: "#475569"
textColor: "#ffffff"
rounded: "{rounded.md}"
---
# melta UI — Design Constitution
> AI エージェントが UI を生成するとき、最初に読むファイル。
> 思想・非交渉原則・クイックリファレンス・参照先をこの 1 枚に集約する。
---
## Brand Identity
**"声を張らずに伝わる UI"** — 機能的な黒子であり、たまに微笑む。
| キーワード | 意味 |
|---|---|
| Quiet Precision | 静かだが精密。目立たないところほど丁寧に |
| Breathable | 文字・要素の周囲に空気がある |
| Flat & Layered | Background → Surface → Text の 3 層で奥行き |
| Subtle Warmth | 控えめだが冷たくない。機能性にエモーショナルな温度 |
参考: Linear / Notion / Stripe / Vercel
アンチ: ネオン SaaS、Bootstrap 的テンプレート
---
## Non-Negotiable Principles
1. **Content First** — UI は黒子。コンテンツが主役
2. **WCAG 2.1 AA** — コントラスト 4.5:1 以上。アクセシビリティはデフォルト
3. **Semantic Color** — `bg-primary-500` を使う。`bg-blue-*` は使わない
4. **3-Color Rule** — 1 画面に使う色は 3 色まで(背景・アクセント・テキスト)
5. **4px Grid** — スペーシングは 4 の倍数、8 の倍数推奨
6. **Minimal Elevation** — `shadow-sm` 〜 `shadow-md`。`shadow-lg` 以上はオーバーレイ限定
7. **No AI-ish Decoration** — カード上部/左端のカラーバー禁止。全周ボーダーで構成
8. **Baseline Widely Available** — CSS/HTML 機能は Baseline **Widely available** のみ使用。Newly / Limited(Anchor Positioning・Invoker Commands・popover 等)は fallback を併記しコメントで明示宣言した場合のみ許可(`BASELINE_*` ルールが検知)
> **disabled の規範(2026-07-19)**: `disabled` 属性には `aria-disabled="true"` を併記する(`A11Y_DISABLED_REQUIRES_ARIA` が検知)。タブ順を維持したい文脈(ツールバー・ページネーション等)では native `disabled` を使わず **`aria-disabled` 単独 + JS click ガード(preventDefault)** でフォーカス可能なまま無効を伝えてよい。ただし `aria-disabled` は click / Enter / submit を止めないため JS ガード必須、フォーム送信除外も効かない(送信除外が必要なら native `disabled` を維持する)。
> **コントラストの既知境界(意図宣言, 2026-07-03)**: `primary-500 × 白`(contained ボタン / brand-outline 文字 / pagination active)は実測 4.50:1 の AA 境界上。axe の判定(4.5 ちょうど = pass)を採用し、ブランド基準色を優先して**意図的に維持**する。より高いコントラストが必要な文脈では `primary-600` を使う(lighted 系の文字・avatar initials は 600 に引き上げ済み、danger base は `#dc2626` に引き上げ済み)。disabled 状態のコントラストは WCAG 1.4.3 の除外対象で対応不要。
---
## Quick Reference
> この section だけで基本的な UI コード生成が可能。
### HTML テンプレート(Tailwind CDN)
> プロトタイプ = この CDN テンプレ(Tailwind v3 構文)/ プロダクション = `foundations/theme.md` の v4 `@theme`。
> 値の SSOT は `design/contracts/tokens.json`(`scripts/ds-config.js` / `ds-theme.css` と同期)。
> **fontSize は 8 段すべて Tailwind デフォルトと異なる**(本文 18px / 行間 2.0 が melta の核。xxs はタブラベル等の最小ラベル専用)。省略すると DS のタイポグラフィが再現されない。
```html
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50:'#f0f5ff',100:'#dde8ff',200:'#c0d4ff',300:'#95b6ff',
400:'#6492ff',500:'#2b70ef',600:'#2250df',700:'#1a40b5',
800:'#13318d',900:'#0e266a',950:'#07194e'
},
body: '#3d4b5f',
wf: { bg:'#FFFFFF', surface:'#F5F5F5', border:'#E0E0E0', text:'#333333', 'text-sub':'#888888', accent:'#666666' }
},
fontFamily: {
sans: ['Inter','Hiragino Sans','Hiragino Kaku Gothic ProN','Noto Sans JP','sans-serif'],
mono: ['JetBrains Mono','SF Mono','monospace']
},
fontSize: {
xxs: ['0.625rem', { lineHeight: '1.4' }],
xs: ['0.8125rem', { lineHeight: '1.4' }],
sm: ['0.9375rem', { lineHeight: '1.7' }],
base: ['1.125rem', { lineHeight: '2.0' }],
lg: ['1.25rem', { lineHeight: '1.5' }],
xl: ['1.375rem', { lineHeight: '1.4' }],
'2xl': ['1.625rem', { lineHeight: '1.4' }],
'3xl': ['2rem', { lineHeight: '1.4' }]
}
}
}
}
</script>
<style>
body { line-height: 2.0; letter-spacing: 0.02em; }
h1, h2, h3, h4, h5, h6 { line-height: 1.4; letter-spacing: 0.01em; }
.text-body { color: #3d4b5f; } /* colors.body と同値(旧テンプレ互換) */
</style>
```
### レイアウト
```
ページ全体 : bg-gray-50 min-h-screen
ページコンテンツ : max-w-[1042px] mx-auto px-4(melta ショーケース実装値。1サイト内では全ページ同一幅で揃える。アプリ画面は patterns/layout.md の用途別幅でも可)
サイドバー+メイン : flex h-screen(ボーダー分離、gap不要)
セクション間隔 : mt-10 〜 mt-14
仕切り線 : border-t border-slate-200
```
### テキスト
```
見出し : text-3xl font-bold text-slate-900(32px)
本文 : text-base text-body(18px, line-height 2.0。leading-* で上書きしない)
フォーム制御ラベル : 包含 <div> に leading-normal(body の lh 2.0 リセット)
空状態メッセージ : text-base text-slate-500 text-center py-16
フォントスタック : Inter, Hiragino Sans, Hiragino Kaku Gothic ProN, Noto Sans JP, sans-serif
```
### コンポーネント
```
カード : bg-white rounded-xl border border-slate-200 p-6 shadow-sm
カードグリッド : grid grid-cols-2 md:grid-cols-3 gap-6
CTAボタン(M) : inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-primary-500 text-white rounded-lg hover:bg-primary-700 cursor-pointer
CTAボタン(L) : inline-flex items-center justify-center gap-2 h-12 px-6 text-[1rem] font-medium bg-primary-500 text-white rounded-lg hover:bg-primary-700 cursor-pointer
CTAボタン(S) : inline-flex items-center justify-center gap-1.5 h-8 px-3 text-[0.875rem] font-medium bg-primary-500 text-white rounded-lg hover:bg-primary-700 cursor-pointer
サブボタン : inline-flex items-center justify-center gap-2 h-10 px-4 text-[1rem] font-medium bg-white text-slate-700 border border-slate-200 rounded-lg hover:bg-gray-50 cursor-pointer
Icon+Textボタン : inline-flex items-center justify-center gap-2 h-10 pl-3 pr-4 text-[1rem] font-medium(アイコン側を狭く)
アイコンボタン(M): w-10 h-10 inline-flex items-center justify-center cursor-pointer + aria-label(icon w-5 h-5)
アイコンボタン(S): w-8 h-8 inline-flex items-center justify-center cursor-pointer + aria-label(icon w-4 h-4)
アイコンボタン(L): w-12 h-12 inline-flex items-center justify-center cursor-pointer + aria-label(icon w-5 h-5)
入力欄 : w-full px-3 py-2 text-base border border-slate-300 rounded-lg focus:ring-2 focus:ring-primary-500/50 caret-primary-500
セレクト : appearance-none pl-3 pr-10 + relative wrapper + SVG chevron(absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4)← ネイティブ矢印は使用禁止
横並びフォーム : flex flex-wrap items-end gap-4 + 各 div.leading-normal > label + 要素 h-11
バッジ : bg-slate-100 text-slate-700 px-3 py-1 rounded-full text-xs font-medium
タグ(削除可能) : inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-medium + ×ボタン
Alert(Info) : flex items-start gap-3 p-4 bg-primary-50 border border-primary-200 text-primary-800 rounded-lg
テーブル外枠 : bg-white rounded-xl border border-slate-200 overflow-hidden
テーブルヘッダ : <th scope="col"> text-left py-3 px-4 text-xs font-medium text-slate-500 uppercase tracking-wider
テーブルデータ行 : hover:bg-gray-50 transition-colors
```
### ナビゲーション
```
サイドバー(標準) : w-64 bg-white border-r border-slate-200 flex-shrink-0 flex flex-col h-screen
ナビ(Active) : flex items-center gap-3 px-4 py-2.5 text-sm font-medium text-primary-500 bg-primary-50 rounded-lg + aria-current="page"
ナビ(Default) : flex items-center gap-3 px-4 py-2.5 text-sm font-medium text-body hover:bg-gray-50 rounded-lg transition-colors
タブ(Active) : text-sm font-semibold text-primary-500 border-b-2 border-primary-500
パンくず : text-sm + text-slate-500 hover:text-slate-700 / 現在ページ text-slate-900 font-medium
```
### アイコン
```
Charcoal : w-5 h-5 fill="currentColor" text-body ← assets/icons/{Name}.svg(207個)
Lucide : w-5 h-5 stroke="currentColor" fill="none" ← assets/icons/lucide/{name}.svg(15個)
小サイズ : w-4 h-4
```
### ワイヤーフレーム(低忠実度プロトタイプ用)
```
背景 : bg-wf-bg (#FFFFFF)
サーフェス : bg-wf-surface (#F5F5F5)
ボーダー : border-wf-border (#E0E0E0)
テキスト : text-wf-text (#333333)
サブテキスト : text-wf-text-sub (#888888)
アクセント : text-wf-accent / bg-wf-accent (#666666)
```
### 禁止パターン要約(Top 10)
| 禁止 | 代替 |
|------|------|
| `text-black` | `text-slate-900` |
| `bg-indigo-*` / `bg-blue-*` | `primary-*` |
| `shadow-lg` / `shadow-2xl` | `shadow-sm` 〜 `shadow-md` |
| `rounded-none` on cards | `rounded-xl` |
| `border-t-4` / `border-l-4` カラーバー | `border border-*-200 rounded-lg` 全周 |
| `text-gray-400` for body | `text-body` (#3d4b5f) |
| `font-light` | `font-normal` 以上 |
| `tracking-tight` | `tracking-normal` 以上 |
| `py-0.5` for buttons | `h-8` 以上 |
| `bg-green-*` / `bg-yellow-*` | `bg-emerald-*` / `bg-amber-*` |
> 全ルール(107 件): `design/contracts/rules.json`(machine-readable)
> 人間向け解説: `foundations/prohibited.md`
---
## Source of Truth 読み順
| # | ファイル | 役割 |
|---|---------|------|
| 1 | `DESIGN.md`(本ファイル) | 憲法 + quick ref |
| 2 | `design/authority.md` | SSOT 宣言 |
| 3 | `design/contracts/tokens.json` | トークン exact value |
| 4 | `design/contracts/rules.json` | 禁止ルール registry |
| 5 | `design/contracts/components/*.contract.json` | コンポーネント仕様 |
| 6 | `foundations/theme.md` | テーマ設定・CSS 変数 |
| 7 | `foundations/design_philosophy.md` | 哲学の詳細 |
| 8 | `components/*.md` / `patterns/*.md` | 人間向けの詳細ガイド |
---
## Agent Prompt Guide
### クイック(単体 UI 生成)
`DESIGN.md` のみ読めば OK。Quick Reference のクラスをそのまま使う。
### 標準(ページ単位)
`DESIGN.md` → `foundations/theme.md` → 関連 `components/*.md` or `*.contract.json`
### フル(新規プロジェクト / DS 変更)
全ファイルを読み順に従って読む。
### MCP
MCP ツール `get_token` / `get_component` / `check_rule` / `check_html` / `get_rules` / `search` を使用。Resource は `melta://tokens` / `melta://components` / `melta://rules`(全99件)/ `melta://rules/auto-detectable`(自動検出サブセット)。
> 生成後は `check_html` に生成コード全体を渡して自己検証する(CI / hook と同一ロジック)。violations が空でも文脈依存の manual ルールは自動検査外(応答の coverage に明記される)。
---
## Theme
| 設定 | 値 |
|------|-----|
| ダークモード | `OFF`(ライトモードのみ) |
| Primary | `#2B70EF`(WCAG AA 4.50:1) |
| Font | Inter, Hiragino Sans, Noto Sans JP |
| Icon | Charcoal 207 個 + Lucide 15 個 |
| Locale | ja(日本語) |
> 詳細: `foundations/theme.md`
===== design/authority.md =====
# Authority Table — Source of Truth 宣言
> melta UI のすべての情報について、**唯一の真実の所在(SSOT)**を定義する。
> 二重管理を防ぐため、各領域の authoring source と generated view を明確に分離する。
---
## Authoring Source(人が編集する)
| 領域 | SSOT | 形式 | 説明 |
|------|------|------|------|
| AI 向け入口・デザイン憲法 | `DESIGN.md` | Markdown | 思想・原則・quick ref・読み順 |
| Claude Code 作業手順 | `CLAUDE.md` | Markdown | この repo での作業ルール |
| デザイントークン | `design/contracts/tokens.json` | JSON | 色・spacing・typography 等の exact value |
| コンポーネント仕様 | `design/contracts/components/*.contract.json` | JSON | variant・size・a11y・rules 等の厳密仕様 |
| 禁止ルール | `design/contracts/rules.json` | JSON | ルール ID + severity + detector |
| デザイン哲学 | `foundations/design_philosophy.md` | Markdown | ブランド思想の詳細 |
| テーマ設定 | `foundations/theme.md` | Markdown | プライマリカラー・フォント・アイコン等 |
## Generated View(ビルドで生成する / 直接編集しない)
| 成果物 | 生成元 | 用途 |
|--------|--------|------|
| `metadata/components.json` | `design/contracts/components/*.contract.json` | MCP サーバー・AI ツール用の集約データ |
| MCP `melta://design-constitution` レスポンス | `DESIGN.md` | MCP だけで接続する AI の最初の入口(runtime 直読、内容の複製なし) |
| MCP `melta://rules` レスポンス | `design/contracts/rules.json` | AI エージェントからのルール参照 |
| `docs/` の component count・nav | contracts + tokens | 公開サイト表示 |
| `llms.txt` / `llms-full.txt` | contracts + DESIGN.md ほか(`build-llms-txt.ts`) | AI エージェント入口(llmstxt.org 形式)。リンク先は GitHub raw。melta.tsubotax.com は showcase 専用で配信しない |
## Human-Readable Docs(参照用。値の SSOT ではない)
| ファイル群 | 役割 | SSOT との関係 |
|-----------|------|---------------|
| `foundations/*.md`(theme.md, design_philosophy.md 除く) | 人間向けの設計ガイド | contracts/tokens の値を prose で解説 |
| `components/*.md` | 人間向けのコンポーネントガイド | contracts の仕様を prose で解説 |
| `patterns/*.md` | 組み合わせパターン | 複数 contracts を横断する指針 |
| `foundations/prohibited.md` | 禁止パターン一覧(人間向け) | `rules.json` の prose 版 |
---
## 移行ルール
1. **値を変更するときは authoring source を編集する**。generated view は `build-legacy.ts` で再生成する
2. **contracts に移行済みのコンポーネント**は `*.contract.json` が SSOT。`components/*.md` と `metadata/components.json` は参照用
3. **contracts 未移行のコンポーネント**は当面 `metadata/components.json` の既存データが SSOT
4. **禁止ルール**の SSOT は `design/contracts/rules.json`。`foundations/prohibited.md` は人間向けの説明文書
5. **drift が発生したら**、authoring source を正として generated view を再生成する
6. **deprecated compatibility path `tokens/tokens.json` は存在してはならない**。tokens の SSOT は `design/contracts/tokens.json` のみで、旧パスの復活はファイル・symlink を問わず `npm run design:check` が検出する
6. **ドキュメント間で値が競合したら**、`design/contracts/` > `DESIGN.md` Quick Reference > `patterns/` / `components/` md の順で優先する
===== foundations/theme.md =====
# Theme Configuration
> プロジェクトごとのカスタマイズはこのファイルで完結する。
> プロジェクト側に `design-system/foundations/theme.md` がある場合はそちらの値で上書きされる。
---
## Brand
- Primary color: `#2B70EF`(OKLCH再生成 — WCAG AA 4.50:1)
- Brand name: (プロジェクトで設定)
## Primary Palette
```css
--color-primary-50: #f0f5ff;
--color-primary-100: #dde8ff;
--color-primary-200: #c0d4ff;
--color-primary-300: #95b6ff;
--color-primary-400: #6492ff;
--color-primary-500: #2b70ef; /* ★ CTA・ボタン・アクティブ状態(hover は 700) */
--color-primary-600: #2250df;
--color-primary-700: #1a40b5;
--color-primary-800: #13318d;
--color-primary-900: #0e266a;
--color-primary-950: #07194e;
```
WCAGコントラスト比:
- 白文字 on primary-500: **4.50:1** — AA準拠
- primary-500 on 白背景: **4.50:1** — AA準拠
ダークモードでの使い分け:
| 用途 | Light | Dark | 理由 |
|------|-------|------|------|
| CTAボタン背景 | primary-500 | primary-500 | 暗い背景での視認性確保 |
| テキストリンク | primary-500 | primary-400 | slate-800上でのコントラスト比確保 |
| Subtle背景 | primary-50 | primary-500/12% | 透過で暗い背景に馴染ませる |
| フォーカスリング | primary-500/50 | primary-400/50 | 同上 |
## Font Stack
```
font-sans: "Inter", "Hiragino Sans", "Hiragino Kaku Gothic ProN", "Noto Sans JP", sans-serif
font-mono: "JetBrains Mono", "SF Mono", monospace
```
## Icon Library
デュアルソース構成。Charcoal をプライマリとし、SaaS 向けの不足分を Lucide で補完する。
### プライマリ: Charcoal Icons 2.0
- Source: **Charcoal Icons 2.0**(pixiv design system)
- Format: SVGファイル(`assets/icons/{Name}.svg`)全207個
- Size: 24px統一(表示サイズはTailwindクラスで制御)
- Naming: PascalCase(例: `ArrowDown`, `OpenInNew`)
- Color: `fill="currentColor"` でテーマカラーを継承
### セカンダリ: Lucide Icons(補完用)
- Source: **Lucide Icons**(Charcoal に存在しないアイコンのみ)
- Format: SVGファイル(`assets/icons/lucide/{name}.svg`)15個
- Size: 24px viewBox(表示サイズはTailwindクラスで制御)
- Naming: kebab-case(例: `bar-chart-2`, `trending-up`)
- Color: `stroke="currentColor"` + `fill="none"` でテーマカラーを継承
- 対象: Analytics(bar-chart-2, trending-up/down, activity)、Time(clock)、Security(shield, key)、Infrastructure(cloud, database, server)、Files(folder)、Payment(credit-card)、Device(monitor)、International(globe)、Communication(phone)
> **ルール**: 同じ概念のアイコンが Charcoal にある場合は必ず Charcoal を使う。Lucide は Charcoal に明確に存在しないアイコンのみ許可。
- 詳細: `foundations/icons.md` を参照
## Tech Stack
- CSS: Tailwind CSS 4
- Component: (プロジェクトで設定 — Stimulus / React / Vue / etc.)
- Template: HTML(プロジェクトで設定 — HTML / ERB / JSX / etc.)
## Locale
- Language: ja(日本語)
- ラベル例: 保存する、キャンセル、削除する、閉じる、戻る、次へ
- 日付形式: YYYY-MM-DD
- 通貨形式: ¥1,000
## CSS変数の定義
`application.css`(または同等のエントリCSS)の `@theme` ブロックで以下を定義する:
```css
@theme {
--color-primary-50: #f0f5ff;
--color-primary-100: #dde8ff;
--color-primary-200: #c0d4ff;
--color-primary-300: #95b6ff;
--color-primary-400: #6492ff;
--color-primary-500: #2b70ef;
--color-primary-600: #2250df;
--color-primary-700: #1a40b5;
--color-primary-800: #13318d;
--color-primary-900: #0e266a;
--color-primary-950: #07194e;
/* text-body: 本文デフォルト色(slate-600〜700の中間) */
--color-body: #3d4b5f;
/* セマンティックカラー変数(ダークモード対応) */
--color-bg-page: var(--bg-page);
--color-bg-surface: var(--bg-surface);
--color-text-heading: var(--text-heading);
--color-text-default: var(--text-default);
--color-text-muted: var(--text-muted);
--color-border-default: var(--border-default);
}
/* ---- Light Theme (default) ---- */
:root {
--bg-page: #f9fafb; /* gray-50 */
--bg-page-alt: #f3f4f6; /* gray-100 */
--bg-surface: #ffffff;
--bg-surface-alt: #f9fafb; /* gray-50 */
--text-heading: #0f172a; /* slate-900 */
--text-default: #3d4b5f; /* body */
--text-muted: #64748b; /* slate-500 */
--border-default: #e2e8f0; /* slate-200 */
--border-strong: #cbd5e1; /* slate-300 */
--input-bg: #ffffff;
--input-border: #cbd5e1; /* slate-300 */
--shadow-color: 0, 0, 0; /* black base */
--shadow-opacity: 0.05;
}
/* ---- Dark Theme ---- */
/* 切替: prefers-color-scheme OR html[data-theme="dark"] */
@media (prefers-color-scheme: dark) {
:root { @mixin dark-tokens; }
}
html[data-theme="dark"] { @mixin dark-tokens; }
/* dark-tokens mixin(実際のCSS実装では共通ブロックにまとめる) */
/*
--bg-page: #0f172a; slate-900
--bg-page-alt: #334155; slate-700
--bg-surface: #1e293b; slate-800
--bg-surface-alt: #0f172a; slate-900
--text-heading: #f1f5f9; slate-100
--text-default: #cbd5e1; slate-300
--text-muted: #94a3b8; slate-400
--border-default: #334155; slate-700
--border-strong: #475569; slate-600
--input-bg: #0f172a; slate-900
--input-border: #475569; slate-600
--shadow-color: 0, 0, 0;
--shadow-opacity: 0.3;
*/
```
> `text-body` は Tailwind 4 のカスタムカラーとして `--color-body` で定義する。`text-body` クラスで自動的に適用される。
> ダークモードでは `--color-body` を `:root` の `--text-default` にバインドし、`prefers-color-scheme: dark` または `data-theme="dark"` で `#cbd5e1`(slate-300)に切り替える。
---
## Semantic Colors
セマンティックカラーマッピング。CSS変数として `@theme` に定義し、ダークモードで値を切り替える。
> 全トークン詳細(Background / Surface / Text / Border / Focus / Input / Shadow): `foundations/color.md` 参照
## Elevation (Shadow)
| トークン | Tailwind | 用途 |
|---------|----------|------|
| elevation-none | `shadow-none` | フラット、disabled |
| elevation-sm | `shadow-sm` | カード、トースト |
| elevation-md | `shadow-md` | カード hover、ドロップダウン |
| elevation-overlay | `shadow-xl` | モーダル |
> 詳細: `foundations/elevation.md`
## Border Radius
| トークン | Tailwind | 用途 |
|---------|----------|------|
| radius-sm | `rounded` | チェックボックス |
| radius-md | `rounded-lg` | ボタン、入力欄、トースト |
| radius-lg | `rounded-xl` | カード、モーダル |
| radius-full | `rounded-full` | バッジ、トグル |
> 詳細: `foundations/radius.md`
## Motion
| トークン | 値 | 用途 |
|---------|-----|------|
| duration-fast | 150ms | ボタン hover 等 |
| duration-normal | 200ms | フェード |
| duration-slow | 300ms | トースト、複合 |
> 詳細: `foundations/motion.md`
## Z-index
| トークン | Tailwind | 用途 |
|---------|----------|------|
| z-base | `z-0` | コンテンツ |
| z-dropdown | `z-20` | ドロップダウン |
| z-sticky | `z-30` | sticky ヘッダー |
| z-overlay | `z-40` | モーダル背景 |
| z-modal | `z-50` | モーダル本体、トースト |
> 詳細: `foundations/z-index.md`
===== design/contracts/tokens.json =====
{"version":"1.0.0","color":{"primary":{"50":{"value":"#f0f5ff","tailwind":"primary-50"},"100":{"value":"#dde8ff","tailwind":"primary-100"},"200":{"value":"#c0d4ff","tailwind":"primary-200"},"300":{"value":"#95b6ff","tailwind":"primary-300"},"400":{"value":"#6492ff","tailwind":"primary-400"},"500":{"value":"#2b70ef","tailwind":"primary-500"},"600":{"value":"#2250df","tailwind":"primary-600"},"700":{"value":"#1a40b5","tailwind":"primary-700"},"800":{"value":"#13318d","tailwind":"primary-800"},"900":{"value":"#0e266a","tailwind":"primary-900"},"950":{"value":"#07194e","tailwind":"primary-950"}},"body":{"value":"#3d4b5f","tailwind":"body"},"semantic":{"light":{"bg-page":{"value":"#f9fafb","tailwind":"bg-gray-50","cssVar":"--bg-page"},"bg-page-alt":{"value":"#f3f4f6","tailwind":"bg-gray-100","cssVar":"--bg-page-alt"},"bg-surface":{"value":"#ffffff","tailwind":"bg-white","cssVar":"--bg-surface"},"bg-surface-alt":{"value":"#f9fafb","tailwind":"bg-gray-50","cssVar":"--bg-surface-alt"},"text-heading":{"value":"#0f172a","tailwind":"text-slate-900","cssVar":"--text-heading"},"text-default":{"value":"#3d4b5f","tailwind":"text-body","cssVar":"--text-default"},"text-muted":{"value":"#64748b","tailwind":"text-slate-500","cssVar":"--text-muted"},"border-default":{"value":"#e2e8f0","tailwind":"border-slate-200","cssVar":"--border-default"},"border-strong":{"value":"#cbd5e1","tailwind":"border-slate-300","cssVar":"--border-strong"},"input-bg":{"value":"#ffffff","tailwind":"bg-white","cssVar":"--input-bg"},"input-border":{"value":"#cbd5e1","tailwind":"border-slate-300","cssVar":"--input-border"},"text-accent":{"value":"#2b70ef","tailwind":"text-primary-500","cssVar":"--text-accent"},"text-on-accent":{"value":"#ffffff","tailwind":"text-white","cssVar":"--text-on-accent"}},"dark":{"bg-page":{"value":"#0f172a","tailwind":"bg-slate-900","cssVar":"--bg-page"},"bg-page-alt":{"value":"#334155","tailwind":"bg-slate-700","cssVar":"--bg-page-alt"},"bg-surface":{"value":"#1e293b","tailwind":"bg-slate-800","cssVar":"--bg-surface"},"bg-surface-alt":{"value":"#0f172a","tailwind":"bg-slate-900","cssVar":"--bg-surface-alt"},"text-heading":{"value":"#f1f5f9","tailwind":"text-slate-100","cssVar":"--text-heading"},"text-default":{"value":"#cbd5e1","tailwind":"text-slate-300","cssVar":"--text-default"},"text-muted":{"value":"#94a3b8","tailwind":"text-slate-400","cssVar":"--text-muted"},"border-default":{"value":"#334155","tailwind":"border-slate-700","cssVar":"--border-default"},"border-strong":{"value":"#475569","tailwind":"border-slate-600","cssVar":"--border-strong"},"input-bg":{"value":"#0f172a","tailwind":"bg-slate-900","cssVar":"--input-bg"},"input-border":{"value":"#475569","tailwind":"border-slate-600","cssVar":"--input-border"},"text-accent":{"value":"#6492ff","tailwind":"text-primary-400","cssVar":"--text-accent"},"text-on-accent":{"value":"#ffffff","tailwind":"text-white","cssVar":"--text-on-accent"}}},"status":{"success":{"base":{"value":"#059669","tailwind":"emerald-600"},"subtle-light":{"value":"#ecfdf5","tailwind":"bg-emerald-50"},"text-light":{"value":"#047857","tailwind":"text-emerald-700"},"subtle-dark":{"value":"rgba(5,150,105,0.12)","tailwind":"bg-emerald-500/[.12]"},"text-dark":{"value":"#6ee7b7","tailwind":"text-emerald-300"}},"warning":{"base":{"value":"#d97706","tailwind":"amber-600"},"subtle-light":{"value":"#fffbeb","tailwind":"bg-amber-50"},"text-light":{"value":"#b45309","tailwind":"text-amber-700"},"subtle-dark":{"value":"rgba(217,119,6,0.12)","tailwind":"bg-amber-500/[.12]"},"text-dark":{"value":"#fcd34d","tailwind":"text-amber-300"}},"danger":{"base":{"value":"#dc2626","tailwind":"red-600"},"subtle-light":{"value":"#fef2f2","tailwind":"bg-red-50"},"text-light":{"value":"#b91c1c","tailwind":"text-red-700"},"subtle-dark":{"value":"rgba(220,38,38,0.12)","tailwind":"bg-red-600/[.12]"},"text-dark":{"value":"#fca5a5","tailwind":"text-red-300"}}}},"typography":{"fontFamily":{"sans":{"value":["Inter","Hiragino Sans","Hiragino Kaku Gothic ProN","Noto Sans JP","sans-serif"],"tailwind":"font-sans"},"mono":{"value":["JetBrains Mono","SF Mono","monospace"],"tailwind":"font-mono"}},"fontSize":{"xxs":{"size":"0.625rem","px":10,"lineHeight":"1.4","tailwind":"text-xxs"},"xs":{"size":"0.8125rem","px":13,"lineHeight":"1.4","tailwind":"text-xs"},"sm":{"size":"0.9375rem","px":15,"lineHeight":"1.7","tailwind":"text-sm"},"base":{"size":"1.125rem","px":18,"lineHeight":"2.0","tailwind":"text-base"},"lg":{"size":"1.25rem","px":20,"lineHeight":"1.5","tailwind":"text-lg"},"xl":{"size":"1.375rem","px":22,"lineHeight":"1.4","tailwind":"text-xl"},"2xl":{"size":"1.625rem","px":26,"lineHeight":"1.4","tailwind":"text-2xl"},"3xl":{"size":"2rem","px":32,"lineHeight":"1.4","tailwind":"text-3xl"}},"fontWeight":{"normal":{"value":400,"tailwind":"font-normal"},"medium":{"value":500,"tailwind":"font-medium"},"semibold":{"value":600,"tailwind":"font-semibold"},"bold":{"value":700,"tailwind":"font-bold"}},"letterSpacing":{"heading":{"value":"0.01em"},"body":{"value":"0.02em"}},"lineHeight":{"heading":{"value":"1.4"},"subheading":{"value":"1.5"},"small":{"value":"1.7"},"body":{"value":"2.0"}}},"spacing":{"1":{"value":"4px","rem":"0.25rem","tailwind":"1"},"2":{"value":"8px","rem":"0.5rem","tailwind":"2"},"3":{"value":"12px","rem":"0.75rem","tailwind":"3"},"4":{"value":"16px","rem":"1rem","tailwind":"4"},"5":{"value":"20px","rem":"1.25rem","tailwind":"5"},"6":{"value":"24px","rem":"1.5rem","tailwind":"6"},"8":{"value":"32px","rem":"2rem","tailwind":"8"},"10":{"value":"40px","rem":"2.5rem","tailwind":"10"},"12":{"value":"48px","rem":"3rem","tailwind":"12"},"14":{"value":"56px","rem":"3.5rem","tailwind":"14"},"16":{"value":"64px","rem":"4rem","tailwind":"16"}},"elevation":{"none":{"value":"none","tailwind":"shadow-none"},"sm":{"value":"0 1px 2px rgba(0,0,0,0.05)","tailwind":"shadow-sm"},"md":{"value":"0 4px 6px rgba(0,0,0,0.1)","tailwind":"shadow-md"},"overlay":{"value":"0 20px 25px rgba(0,0,0,0.1)","tailwind":"shadow-xl"}},"radius":{"sm":{"value":"0.25rem","px":4,"tailwind":"rounded"},"md":{"value":"0.5rem","px":8,"tailwind":"rounded-lg"},"lg":{"value":"0.75rem","px":12,"tailwind":"rounded-xl"},"full":{"value":"9999px","px":9999,"tailwind":"rounded-full"}},"motion":{"duration":{"fast":{"value":"150ms","tailwind":"duration-150"},"normal":{"value":"200ms","tailwind":"duration-200"},"slow":{"value":"300ms","tailwind":"duration-300"}},"easing":{"default":{"value":"cubic-bezier(0.4, 0, 0.2, 1)","tailwind":"ease-in-out"},"in":{"value":"cubic-bezier(0.4, 0, 1, 1)","tailwind":"ease-in"},"out":{"value":"cubic-bezier(0, 0, 0.2, 1)","tailwind":"ease-out"}}},"zIndex":{"base":{"value":0,"tailwind":"z-0"},"dropdown":{"value":20,"tailwind":"z-20"},"sticky":{"value":30,"tailwind":"z-30"},"overlay":{"value":40,"tailwind":"z-40"},"modal":{"value":50,"tailwind":"z-50"}},"wireframe":{"bg":{"value":"#FFFFFF","cssVar":"--wf-bg","tailwind":"wf-bg"},"surface":{"value":"#F5F5F5","cssVar":"--wf-surface","tailwind":"wf-surface"},"border":{"value":"#E0E0E0","cssVar":"--wf-border","tailwind":"wf-border"},"text":{"value":"#333333","cssVar":"--wf-text","tailwind":"wf-text"},"text-sub":{"value":"#888888","cssVar":"--wf-text-sub","tailwind":"wf-text-sub"},"accent":{"value":"#666666","cssVar":"--wf-accent","tailwind":"wf-accent"}}}
===== design/contracts/rules.json =====
{"version":"2.1.0","description":"melta UI 禁止ルール registry。foundations/prohibited.md の machine-readable 版(SSOT)。","schemaVersion":1,"vocabulary":{"ruleCategories":["accessibility","ai-pattern","baseline","button","color","datepicker","divider","form","list","modal","motion","philosophy","skeleton","spacing","stepper","table","tag","typography"],"componentCategories":["data-display","feedback","form-input","layout","navigation"]},"rules":[{"id":"COLOR_NO_TEXT_BLACK","category":"color","severity":"error","description":"純黒はコントラストが強すぎて長時間の利用で目が疲れる","detector":"tailwind-class","pattern":"text-black","alternative":"text-slate-900","contractLint":"enforce"},{"id":"COLOR_NO_ARBITRARY_TEXT_HEX","category":"color","severity":"warn","description":"text-[#...] / text-[rgb(...)] / text-[hsl(...)] / text-[black] 等で色を直書きすると tokens.json のパレット外になりセマンティックカラー原則を回避できてしまう(最頻の検知すり抜け)。フォントサイズの text-[1rem] 等は対象外","detector":"tailwind-class-prefix","pattern":"text-[#","prefixPatterns":["text-[rgb","text-[hsl","text-[oklch","text-[black]","text-[white]"],"alternative":"text-slate-900 / text-primary-600 などカラートークンを使う","contractLint":"warn"},{"id":"COLOR_NO_ARBITRARY_BG_HEX","category":"color","severity":"warn","description":"bg-[#...] / bg-[rgb(...)] / bg-[hsl(...)] / bg-[black] 等で背景色を直書きするとパレット外の色が混入する。bg-[url(...)] 等は対象外","detector":"tailwind-class-prefix","pattern":"bg-[#","prefixPatterns":["bg-[rgb","bg-[hsl","bg-[oklch","bg-[black]","bg-[white]"],"alternative":"bg-white / bg-slate-50 / bg-primary-500 などカラートークンを使う","contractLint":"warn"},{"id":"COLOR_NO_ARBITRARY_BORDER_HEX","category":"color","severity":"warn","description":"border-[#...] / border-[rgb(...)] / border-[hsl(...)] / border-[black] 等で枠線色を直書きするとパレット外の色が混入する。border-[1px] 等の太さ指定は対象外","detector":"tailwind-class-prefix","pattern":"border-[#","prefixPatterns":["border-[rgb","border-[hsl","border-[oklch","border-[black]","border-[white]"],"alternative":"border-slate-200 / border-primary-500 などカラートークンを使う","contractLint":"warn"},{"id":"SPACE_NO_ARBITRARY_SHADOW","category":"spacing","severity":"warn","description":"shadow-[...] で影を直書きすると elevation トークンを回避でき、過剰な影で安っぽく見える","detector":"tailwind-class-prefix","pattern":"shadow-[","alternative":"shadow-sm / shadow-md など elevation トークンを使う","contractLint":"warn"},{"id":"TYPO_NO_ARBITRARY_FONT","category":"typography","severity":"warn","description":"font-[...] で font-weight / font-family を直書きすると typography トークンを回避できる(font-[300] など細すぎる weight の混入経路)","detector":"tailwind-class-prefix","pattern":"font-[","alternative":"font-normal / font-medium / font-semibold などタイポグラフィトークンを使う","contractLint":"warn"},{"id":"COLOR_NO_INLINE_STYLE_HARDCODE","category":"color","severity":"warn","description":"inline style で色をハードコードするとカラールール(class 検査)を迂回できる。var(--...) 経由の CSS 変数は対象外で、# / rgb / hsl の直書きのみ検知する","detector":"html-attr","pattern":null,"alternative":"Tailwind カラートークン(bg-primary-600 等) か CSS 変数 var(--text-default) を使う","contractLint":"skip","htmlAttrCheck":{"kind":"attr-value-contains","attr":"style","valueRegex":"(?:background|background-color|color|border-color|fill|stroke|box-shadow|outline-color)\\s*:\\s*(?:#|rgb|hsl)"}},{"id":"PHILOSOPHY_NO_STYLE_BLOCK","category":"philosophy","severity":"warn","description":"生 CSS の <style> ブロックは Tailwind トークン体系を迂回する escape hatch。CDN 運用では意図的回避でしか発生しない","detector":"html-attr","pattern":null,"alternative":"Tailwind ユーティリティ / デザイントークンで表現する。どうしても必要なら @layer で正規化","contractLint":"skip","htmlAttrCheck":{"kind":"tag-present","tag":"style"}},{"id":"COLOR_NO_DARK_BG_GRAY","category":"color","severity":"error","description":"テキストのコントラスト確保が困難になる","detector":"tailwind-class-prefix","pattern":"bg-gray-[3-9]00","matchPatterns":["bg-gray-300","bg-gray-400","bg-gray-500","bg-gray-600","bg-gray-700","bg-gray-800","bg-gray-900"],"alternative":"bg-gray-50 〜 bg-gray-200","contractLint":"enforce"},{"id":"COLOR_NO_PRIMARY_400","category":"color","severity":"warn","description":"CTAとして弱く、目立たない","detector":"tailwind-class","pattern":"bg-primary-400","alternative":"bg-primary-500","contractLint":"enforce"},{"id":"COLOR_NO_GRAY_400_BODY","category":"color","severity":"error","description":"WCAG不適合(コントラスト比不足)","detector":"tailwind-class","pattern":"text-gray-400","alternative":"text-body (#3d4b5f)","contractLint":"enforce"},{"id":"COLOR_NO_GRAY_100_BORDER","category":"color","severity":"error","description":"薄すぎて境界が見えない","detector":"tailwind-class","pattern":"border-gray-100","alternative":"border-slate-200","contractLint":"enforce"},{"id":"COLOR_NO_GREEN","category":"color","severity":"error","description":"emeraldで統一する","detector":"tailwind-class-prefix","pattern":"bg-green-","alternative":"bg-emerald-*","contractLint":"enforce"},{"id":"COLOR_NO_YELLOW","category":"color","severity":"error","description":"amberで統一する","detector":"tailwind-class-prefix","pattern":"bg-yellow-","alternative":"bg-amber-*","contractLint":"enforce"},{"id":"COLOR_NO_ROSE","category":"color","severity":"error","description":"redで統一する","detector":"tailwind-class-prefix","pattern":"bg-rose-","alternative":"bg-red-*","contractLint":"enforce"},{"id":"COLOR_NO_BLUE_BG","category":"color","severity":"error","description":"primaryで統一する","detector":"tailwind-class-prefix","pattern":"bg-blue-","alternative":"bg-primary-*","contractLint":"enforce"},{"id":"COLOR_NO_BLUE_LINKS","category":"color","severity":"error","description":"primaryで統一する","detector":"tailwind-class-prefix","pattern":"text-blue-","alternative":"text-primary-500","contractLint":"enforce"},{"id":"COLOR_NO_INDIGO","category":"color","severity":"error","description":"primaryで統一する","detector":"tailwind-class-prefix","pattern":"bg-indigo-","alternative":"bg-primary-*","contractLint":"enforce"},{"id":"COLOR_ONLY_FORBIDDEN","category":"color","severity":"error","description":"色だけで情報伝達すると色覚多様性への非対応になる","detector":"manual","pattern":null,"alternative":"アイコン/テキストを必ず併用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"PHILOSOPHY_NO_EXCESSIVE_ANIMATION","category":"philosophy","severity":"error","description":"操作の邪魔になり、認知コストを増加させる","detector":"manual","pattern":null,"alternative":"150〜300ms の状態変化フィードバックに限定","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"MOTION_NO_LONG_DURATION","category":"motion","severity":"error","description":"操作が鈍く感じる(Progress フィルバーは例外)","detector":"tailwind-class-prefix","pattern":"duration-[5-9]00|duration-1000","matchPatterns":["duration-500","duration-700","duration-1000"],"alternative":"duration-300 以下","contractLint":"skip","requiresContext":true},{"id":"MOTION_REDUCED_MOTION_REQUIRED","category":"motion","severity":"error","description":"prefers-reduced-motion 無視はアクセシビリティ違反","detector":"manual","pattern":null,"alternative":"メディアクエリで対応","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"TYPO_NO_TRACKING_TIGHT","category":"typography","severity":"error","description":"日本語の可読性が低下する","detector":"tailwind-class","pattern":"tracking-tight","alternative":"tracking-normal 以上(本文2%、見出し1%)","contractLint":"enforce"},{"id":"TYPO_NO_XS_BODY","category":"typography","severity":"error","description":"本文には小さすぎて読みづらい","detector":"manual","pattern":null,"alternative":"text-base(16px)","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"TYPO_NO_FONT_LIGHT","category":"typography","severity":"error","description":"細すぎて可読性が低い","detector":"tailwind-class","pattern":"font-light","alternative":"font-normal(400)以上","contractLint":"enforce"},{"id":"TYPO_NO_PLACEHOLDER_ONLY","category":"typography","severity":"error","description":"入力開始で消え、目的がわからなくなる","detector":"manual","pattern":null,"alternative":"<label> を必ず使用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SPACE_NO_ROUNDED_NONE_CARDS","category":"spacing","severity":"error","description":"UIの統一感を損なう","detector":"tailwind-class","pattern":"rounded-none","alternative":"rounded-xl(12px)","contractLint":"skip","requiresContext":true},{"id":"SPACE_NO_SHADOW_LG","category":"spacing","severity":"error","description":"影が強すぎてノイズになる","detector":"tailwind-class","pattern":"shadow-lg","alternative":"shadow-sm 〜 shadow-md(オーバーレイ: shadow-xl)","contractLint":"enforce"},{"id":"SPACE_NO_SHADOW_2XL","category":"spacing","severity":"error","description":"影が強すぎてノイズになる","detector":"tailwind-class","pattern":"shadow-2xl","alternative":"shadow-sm 〜 shadow-md(オーバーレイ: shadow-xl)","contractLint":"enforce"},{"id":"SPACE_NO_PY_05_BTN","category":"spacing","severity":"error","description":"タップターゲットが小さすぎる","detector":"tailwind-class","pattern":"py-0.5","alternative":"h-8 以上(S: h-8 / M: h-10 / L: h-12)","contractLint":"skip","requiresContext":true},{"id":"SPACE_NO_P0_CARDS","category":"spacing","severity":"error","description":"コンテンツが窮屈になる","detector":"tailwind-class","pattern":"p-0","alternative":"p-5 以上","contractLint":"skip","requiresContext":true},{"id":"SPACE_NO_GAP0_SECTIONS","category":"spacing","severity":"warn","description":"セクションの区切りが不明瞭","detector":"tailwind-class","pattern":"gap-0","alternative":"gap-6 以上","contractLint":"skip","requiresContext":true},{"id":"SPACE_NO_M0_PAGE","category":"spacing","severity":"warn","description":"ページ端にコンテンツが張り付く","detector":"manual","pattern":null,"alternative":"px-6 py-8 以上","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SPACE_NO_DARK_SIDEBAR_BG","category":"spacing","severity":"error","description":"メインコンテンツとのコントラストが強すぎる","detector":"manual","pattern":null,"alternative":"bg-white + ボーダー","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SPACE_NO_NONSTANDARD_SIDEBAR_WIDTH","category":"spacing","severity":"error","description":"実装ごとにバラつきが出る","detector":"tailwind-class","pattern":"w-60","alternative":"w-64(標準)or w-16(コンパクト)","contractLint":"skip","requiresContext":true},{"id":"SPACE_NO_ROUNDED_XL_NAV","category":"spacing","severity":"error","description":"ボタン等他コンポーネントとの一貫性を損なう","detector":"manual","pattern":null,"alternative":"rounded-lg","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SPACE_NO_LARGE_NAV_ICON","category":"spacing","severity":"error","description":"DS標準アイコンサイズからの逸脱","detector":"manual","pattern":null,"alternative":"w-5 h-5","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SPACE_NO_DRAWER_NO_FOCUS_TRAP","category":"spacing","severity":"error","description":"キーボードユーザーが背面要素を操作してしまう","detector":"manual","pattern":null,"alternative":"フォーカストラップを実装","contractLint":"skip","automationStatus":"human-only"},{"id":"SPACE_NO_MISSING_ARIA_CURRENT","category":"spacing","severity":"error","description":"スクリーンリーダーが現在ページを識別できない","detector":"html-attr","pattern":null,"alternative":"Active ナビアイテムに aria-current=\"page\" を付与","contractLint":"skip","automationStatus":"impossible-static"},{"id":"SPACE_NO_3COL_LAYOUT","category":"spacing","severity":"warn","description":"認知負荷が高い","detector":"manual","pattern":null,"alternative":"サイドバー + メインの2列","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"AI_NO_CARD_COLOR_BAR_TOP","category":"ai-pattern","severity":"error","description":"AI生成UIの典型パターン。装飾過剰で汎用性が低い","detector":"tailwind-class","pattern":"border-t-4","alternative":"border border-slate-200 のみでカードを構成","contractLint":"enforce"},{"id":"AI_NO_CARD_COLOR_BAR_LEFT","category":"ai-pattern","severity":"error","description":"Alert含め全コンポーネントで禁止","detector":"tailwind-class","pattern":"border-l-4","alternative":"border border-*-200 rounded-lg で全周ボーダー","contractLint":"enforce"},{"id":"AI_NO_GRADIENT_BG","category":"ai-pattern","severity":"error","description":"装飾的なグラデーション背景はAI生成UIの典型tell。安っぽく見える","detector":"tailwind-class-prefix","pattern":"bg-gradient-","alternative":"単色の bg-primary-500 / bg-white / bg-slate-50 を使う","contractLint":"enforce"},{"id":"AI_NO_DECORATIVE_PURPLE","category":"ai-pattern","severity":"error","description":"purple/violet/fuchsia 系の装飾カラーはAI生成UIの典型tell。brand colorを使う","detector":"tailwind-class-segment","pattern":null,"matchPatterns":["purple","violet","fuchsia"],"alternative":"bg-primary-* / text-primary-* (brand color)を使う","contractLint":"enforce"},{"id":"BTN_NO_SAME_STYLE_PARALLEL","category":"button","severity":"warn","description":"重要度の区別がつかない(Neutralのみ例外)","detector":"manual","pattern":null,"alternative":"階層の異なるボタンを組み合わせる","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"BTN_NO_LIGHTED_SOLO","category":"button","severity":"warn","description":"トグル状態の対比がないと意味不明","detector":"manual","pattern":null,"alternative":"Neutralとペアで使用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"BTN_ICON_ONLY_ARIA_REQUIRED","category":"button","severity":"error","description":"操作内容がスクリーンリーダーに伝わらない","detector":"composition","pattern":null,"alternative":"aria-label=\"閉じる\" 等を付与","contractLint":"skip","compositionCheck":{"kind":"dom-attr-required","selector":"button","requireAnyAttr":["aria-label","aria-labelledby","title"],"when":"icon-only"},"automationStatus":"auto"},{"id":"BTN_MIN_TAP_TARGET","category":"button","severity":"error","description":"高さ 44px 未満のボタン(h-6〜h-10)は当たり判定拡張が無いとモバイルで操作困難(WCAG 2.2 SC 2.5.5 Target Size (Enhanced) = AAA の 44px 水準。AA の SC 2.5.8 は 24px だが melta は 44px を採る。インラインテキストリンクを除く)。見た目を変えず after: 擬似要素でタップ領域だけ広げる。icon-only ボタンは幅拡張が別式のため第一弾対象外(2026-07-19 に manual から composition 自動検出へ昇格)。横断方針は A11Y_MIN_TAP_TARGET_44 が正。本ルールはその web(button)実装形","detector":"composition","pattern":null,"alternative":"relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2 を付与(button recipe 準拠なら自動で付く)","contractLint":"skip","compositionCheck":{"kind":"dom-class-required","selector":"button.h-6, button.h-7, button.h-8, button.h-9, button.h-10","requireAnyClass":["after:h-11","min-h-11"],"excludeWhen":"icon-only"},"automationStatus":"auto"},{"id":"FORM_SELECT_APPEARANCE_NONE","category":"form","severity":"error","description":"ネイティブ矢印はブラウザ間で位置・余白が不安定","detector":"manual","pattern":null,"alternative":"appearance-none + pr-10 + カスタムSVGシェブロン","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"FORM_NO_LABEL_OMIT","category":"form","severity":"error","description":"スクリーンリーダーが目的を読み上げられない","detector":"manual","pattern":null,"alternative":"<label> を for 属性で関連付け","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"FORM_NO_SIDE_LABEL","category":"form","severity":"warn","description":"モバイルで破綻し、視線移動が増える","detector":"manual","pattern":null,"alternative":"ラベルは入力欄の上","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"FORM_FIELDSET_LEGEND_REQUIRED","category":"form","severity":"error","description":"グループの目的が伝わらない","detector":"manual","pattern":null,"alternative":"グループ時は <fieldset> / <legend> を使用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"FORM_NO_AUTO_HIDE_ERROR","category":"form","severity":"error","description":"ユーザーが読む前に消える","detector":"manual","pattern":null,"alternative":"修正されるまで表示","contractLint":"skip","automationStatus":"human-only"},{"id":"FORM_NO_COLOR_ONLY_ERROR","category":"form","severity":"error","description":"色覚多様性への非対応","detector":"manual","pattern":null,"alternative":"ボーダー色 + エラーアイコン + テキスト","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"FORM_NO_CARD_FIELDSET_LEGEND","category":"form","severity":"error","description":"<legend> のブラウザデフォルト描画がカードの border と干渉する","detector":"manual","pattern":null,"alternative":"カードレベルは <div> + <h2>。<fieldset>/<legend> はカード内部のフォームグループに限定","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"FORM_NO_DATE_EQUAL_WIDTH","category":"form","severity":"warn","description":"月・日セレクトが不必要に広くなり選択しにくい","detector":"manual","pattern":null,"alternative":"flex レイアウトで年 w-28、月・日 w-20 に固定","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"FORM_NO_CHECK_ONLY_CONFIRM","category":"form","severity":"error","description":"意図しない確定が起きる","detector":"manual","pattern":null,"alternative":"確認ボタンを必ず配置","contractLint":"skip","automationStatus":"human-only"},{"id":"FORM_NO_AUTO_FOCUS_MOVE","category":"form","severity":"error","description":"ユーザーを混乱させる","detector":"manual","pattern":null,"alternative":"ユーザー操作に任せる","contractLint":"skip","automationStatus":"human-only"},{"id":"FORM_NO_DISTANT_ERROR","category":"form","severity":"error","description":"フィールドとの対応がわからない","detector":"manual","pattern":null,"alternative":"フィールド直下に表示","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"MODAL_FOCUS_TRAP_REQUIRED","category":"modal","severity":"error","description":"キーボードユーザーがモーダル外に出てしまう","detector":"manual","pattern":null,"alternative":"Tab/Shift+Tabがモーダル内を循環","contractLint":"skip","automationStatus":"covered-by-test"},{"id":"MODAL_ESC_CLOSE_REQUIRED","category":"modal","severity":"error","description":"ユーザーが脱出できない","detector":"manual","pattern":null,"alternative":"Escキーで閉じる","contractLint":"skip","automationStatus":"covered-by-test"},{"id":"MODAL_CLOSE_REQUIRED","category":"modal","severity":"error","description":"ユーザーが操作を中断できない","detector":"manual","pattern":null,"alternative":"閉じるボタン + Esc + オーバーレイクリック","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"MODAL_ROLE_DIALOG_REQUIRED","category":"modal","severity":"error","description":"スクリーンリーダーがモーダルを認識できない","detector":"html-attr","pattern":null,"alternative":"role=\"dialog\" を必ず付与","contractLint":"skip","automationStatus":"covered-by-test"},{"id":"MODAL_OVERLAY_REQUIRED","category":"modal","severity":"error","description":"背景との分離が不明確","detector":"manual","pattern":null,"alternative":"bg-black/50 のオーバーレイ","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"MODAL_NO_NESTED","category":"modal","severity":"error","description":"モーダルの中にモーダルを開くとUXが複雑になりすぎる。合法な部品だけで構成しても合成として崩壊する","detector":"composition","pattern":null,"alternative":"設計を見直す(role=dialog を2階層以上ネストしない)","contractLint":"skip","compositionCheck":{"kind":"nested-selector","selector":"[role=\"dialog\"]"}},{"id":"A11Y_NO_NESTED_INTERACTIVE","category":"accessibility","severity":"error","description":"インタラクティブ要素の入れ子(button/a/role=button の中に別のインタラクティブ要素)は HTML 仕様上不正で、キーボード操作・スクリーンリーダー・クリック判定が壊れる。合法な部品でも組み方で崩壊する典型","detector":"composition","pattern":null,"alternative":"入れ子を解消する。クリック領域を分ける、外側を div 等の非インタラクティブ要素にする、または stretched-link パターンを使う","contractLint":"skip","compositionCheck":{"kind":"nested-selector","selector":"a[href], button, [role=\"button\"]"}},{"id":"LIST_NO_FIXED_HEIGHT_MISMATCH","category":"list","severity":"error","description":"テキストが切れる or 余白が不均等","detector":"manual","pattern":null,"alternative":"可変高さにする","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"LIST_NO_COLOR_ONLY_SELECTION","category":"list","severity":"error","description":"色覚多様性への非対応","detector":"manual","pattern":null,"alternative":"ボーダー太さ + 背景スタイルを併用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"LIST_NO_GESTURE_ONLY","category":"list","severity":"error","description":"キーボード/スクリーンリーダーで操作不可","detector":"manual","pattern":null,"alternative":"ボタンによる代替操作を提供","contractLint":"skip","automationStatus":"human-only"},{"id":"LIST_NO_ICON_BORDER","category":"list","severity":"warn","description":"情報の断絶を誤解させる","detector":"manual","pattern":null,"alternative":"ボーダーはアイテム間のみ","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"TABLE_NO_LAYOUT_TABLE","category":"table","severity":"error","description":"セマンティクス違反","detector":"manual","pattern":null,"alternative":"flex / grid を使う","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"TABLE_TH_SCOPE_REQUIRED","category":"table","severity":"error","description":"ヘッダーとデータの関係が不明確","detector":"html-attr","pattern":null,"alternative":"scope=\"col\" を付与","contractLint":"skip","htmlAttrCheck":{"kind":"tag-missing-attr","tag":"th","requiredAttr":"scope"}},{"id":"TAG_REMOVABLE_X_REQUIRED","category":"tag","severity":"error","description":"キーボードのみでは削除操作を発見できない","detector":"manual","pattern":null,"alternative":"×ボタンを必ず表示","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"TAG_X_MIN_TAP_TARGET","category":"tag","severity":"error","description":"モバイルで誤タップが頻発する。横断方針は A11Y_MIN_TAP_TARGET_44 が正。本ルールはその web(tag の × ボタン)実装形","detector":"manual","pattern":null,"alternative":"p-0.5 + SVG w-3 h-3(実質24px以上)","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"TAG_X_ARIA_LABEL_REQUIRED","category":"tag","severity":"error","description":"スクリーンリーダーがボタンの目的を読み上げられない","detector":"composition","pattern":null,"alternative":"aria-label=\"{タグ名}を削除\" を付与","contractLint":"skip","compositionCheck":{"kind":"dom-attr-required","selector":"button","requireAnyAttr":["aria-label","aria-labelledby"],"when":"text-glyph","glyphs":["×","✕","✖","╳","⨯"]},"automationStatus":"auto"},{"id":"TAG_FILTER_ARIA_SELECTED_REQUIRED","category":"tag","severity":"error","description":"選択状態がスクリーンリーダーに伝わらない","detector":"html-attr","pattern":null,"alternative":"aria-selected=\"true\" / \"false\" を付与","contractLint":"skip","automationStatus":"impossible-static"},{"id":"TAG_BADGE_CONFUSION","category":"tag","severity":"warn","description":"Badge はステータス表示、Tag はユーザー管理メタデータ","detector":"manual","pattern":null,"alternative":"用途に応じて badge / tag を使い分ける","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"DIVIDER_NO_DIV_BORDER_B","category":"divider","severity":"error","description":"セマンティクス違反。支援技術が区切りを認識できない","detector":"manual","pattern":null,"alternative":"<hr> or role=\"separator\"","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"DIVIDER_NO_GRAY_100","category":"divider","severity":"error","description":"薄すぎて境界が見えない","detector":"tailwind-class","pattern":"border-gray-100","alternative":"border-slate-200","contractLint":"enforce"},{"id":"DIVIDER_NO_SLATE_400_PLUS","category":"divider","severity":"warn","description":"線が強すぎてノイズになる","detector":"manual","pattern":null,"alternative":"border-slate-200(標準)/ border-slate-300(強調)","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"STEPPER_NO_COLOR_ONLY_STATE","category":"stepper","severity":"error","description":"色覚多様性への非対応","detector":"manual","pattern":null,"alternative":"アイコン + ボーダー + 背景色を併用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"STEPPER_ARIA_CURRENT_REQUIRED","category":"stepper","severity":"error","description":"スクリーンリーダーが現在ステップを識別できない","detector":"html-attr","pattern":null,"alternative":"Active ステップに aria-current=\"step\" を付与","contractLint":"skip","automationStatus":"impossible-static"},{"id":"STEPPER_MIN_INDICATOR_SIZE","category":"stepper","severity":"error","description":"タップターゲットが小さすぎる","detector":"manual","pattern":null,"alternative":"w-8 h-8(標準)/ w-6 h-6(コンパクト最小)","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"STEPPER_NO_DARK_CONNECTOR","category":"stepper","severity":"warn","description":"線が強すぎてノイズになる","detector":"manual","pattern":null,"alternative":"bg-primary-500(完了区間)/ bg-slate-200(未着手区間)","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"DATEPICKER_NO_NATIVE_INPUT","category":"datepicker","severity":"warn","description":"ブラウザ間で表示が不統一","detector":"html-attr","pattern":null,"alternative":"カスタム Date Picker を使用","contractLint":"skip","htmlAttrCheck":{"kind":"element-present","tag":"input","attr":"type","attrValue":"date"}},{"id":"DATEPICKER_NO_SHADOW_LG","category":"datepicker","severity":"error","description":"影が強すぎてノイズになる(datepicker コンテキスト。汎用は SPACE_NO_SHADOW_LG で検出)","detector":"manual","pattern":null,"alternative":"shadow-md","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"DATEPICKER_Z_INDEX_20","category":"datepicker","severity":"error","description":"Dropdown レイヤーの統一が崩れる","detector":"manual","pattern":null,"alternative":"z-20(Dropdown レイヤー)","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"DATEPICKER_NO_COLOR_ONLY_TODAY","category":"datepicker","severity":"error","description":"色覚多様性への非対応","detector":"manual","pattern":null,"alternative":"font-semibold を併用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"DATEPICKER_KEYBOARD_NAV_REQUIRED","category":"datepicker","severity":"error","description":"キーボードユーザーが操作不可","detector":"manual","pattern":null,"alternative":"矢印 + Enter + Escape を実装","contractLint":"skip","automationStatus":"human-only"},{"id":"DATEPICKER_WEEKDAY_HEADER_REQUIRED","category":"datepicker","severity":"error","description":"日付の曜日が判別できない","detector":"manual","pattern":null,"alternative":"日〜土のラベルを必ず表示","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SKELETON_BG_SLATE_200_ONLY","category":"skeleton","severity":"error","description":"DS統一から外れる","detector":"manual","pattern":null,"alternative":"bg-slate-200 固定","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SKELETON_NO_SPINNER_ONLY","category":"skeleton","severity":"warn","description":"進捗が伝わらず不安を与える","detector":"manual","pattern":null,"alternative":"スケルトン or プログレスバーを併用","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"SKELETON_ARIA_BUSY_REQUIRED","category":"skeleton","severity":"error","description":"スクリーンリーダーがローディング状態を認識できない","detector":"composition","pattern":null,"alternative":"コンテナに aria-busy=\"true\" + role=\"status\"","contractLint":"skip","compositionCheck":{"kind":"dom-attr-required","selector":".skeleton-pulse","requireAnyAttr":["aria-busy"],"scope":"ancestor-or-self"},"automationStatus":"auto"},{"id":"SKELETON_ARIA_BUSY_RELEASE","category":"skeleton","severity":"error","description":"ローディング完了が伝わらない","detector":"manual","pattern":null,"alternative":"aria-busy=\"false\" に変更","contractLint":"skip","automationStatus":"human-only"},{"id":"A11Y_NO_OUTLINE_NONE_WITHOUT_RING","category":"accessibility","severity":"error","description":"フォーカスインジケーターが消える","detector":"manual","pattern":null,"alternative":"focus:ring-2 focus:ring-primary-500/50","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"A11Y_NO_TABINDEX_POSITIVE","category":"accessibility","severity":"error","description":"フォーカス順序が混乱する","detector":"html-attr","pattern":null,"alternative":"DOM順に従い、tabindex=\"0\" or \"-1\" のみ使用","contractLint":"skip","htmlAttrCheck":{"kind":"attr-value-forbidden","attr":"tabindex","valueRegex":"^[1-9][0-9]*$"}},{"id":"A11Y_NO_TIME_LIMIT","category":"accessibility","severity":"error","description":"ユーザーが操作を完了できない可能性","detector":"manual","pattern":null,"alternative":"時間制限を設けない","contractLint":"skip","automationStatus":"human-only"},{"id":"A11Y_NO_DECORATIVE_ANIMATION","category":"accessibility","severity":"warn","description":"動きに敏感なユーザーへの配慮不足","detector":"manual","pattern":null,"alternative":"状態変化のフィードバックのみ","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"A11Y_NO_TEXT_TRUNCATION_200","category":"accessibility","severity":"error","description":"コンテンツにアクセスできなくなる","detector":"manual","pattern":null,"alternative":"レスポンシブに対応","contractLint":"skip","automationStatus":"human-only"},{"id":"A11Y_DISABLED_REQUIRES_ARIA","category":"accessibility","severity":"warn","description":"disabled 属性単独では支援技術への状態通知が実装依存になる。契約(button stateSpecs.disabled)の規範どおり aria-disabled=\"true\" を併記し、視覚状態クラス(opacity-50 cursor-not-allowed)とセットにする。タブ順維持が要る文脈(ツールバー/ページネーション)では aria-disabled 単独 + JS click ガードも可(DESIGN.md 注記参照)","detector":"composition","pattern":null,"alternative":"disabled aria-disabled=\"true\" class=\"opacity-50 cursor-not-allowed ...\"(契約 stateSpecs.disabled の tailwind 準拠)","contractLint":"skip","compositionCheck":{"kind":"dom-attr-required","selector":"button[disabled]","requireAnyAttr":["aria-disabled"]}},{"id":"A11Y_MIN_TAP_TARGET_44","category":"accessibility","severity":"error","description":"すべての操作要素は実効タップ標的 44pt(web は 44px)を下回らない — melta の横断方針(WCAG 2.2 SC 2.5.5 Target Size (Enhanced) = AAA の 44px 水準を採る。AA の SC 2.5.8 は 24px だが melta はそこで止めない。インラインテキストリンクは例外)。視覚寸法は契約どおり据え置き、当たり判定だけを広げる: web は h-8/h-10 のまま after: 擬似要素で 44px(または min-h-11)、app は視覚 24pt + hitSlop 10 の正典パターンか minHeight で下限を保証する(height 固定は fontScale でクリップするので使わない)。コンポーネント別の BTN_MIN_TAP_TARGET / TAG_X_MIN_TAP_TARGET は本方針の実装形であり、方針そのものの正本は本ルール","detector":"manual","pattern":null,"alternative":"視覚寸法は変えずタップ領域だけ拡張する。web: relative after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2(または min-h-11)/ app: hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }} か minHeight: 44","contractLint":"skip","automationStatus":"llm-judge-candidate"},{"id":"A11Y_NAV_ARIA_LABEL_REQUIRED","category":"accessibility","severity":"error","description":"<nav>(および role=\"navigation\")にアクセシブルネームが無いと、スクリーンリーダーのランドマーク一覧で複数のナビゲーションを区別できない。nav が 1 つしか無い画面でも、後から増えたときに無名ランドマークが並ぶため常に付与する","detector":"composition","pattern":null,"alternative":"<nav aria-label=\"メインナビゲーション\"> のように aria-label を付与する(見出し要素を指す aria-labelledby でもよい)。空文字・空白のみの値はアクセシブルネームにならないので不可。aria-labelledby の参照先の存在は静的検査しない(fragment 検査では参照先が文書外にあるのが常態のため。design-review の目視で確認する)","contractLint":"skip","compositionCheck":{"kind":"dom-attr-required","selector":"nav, [role~=\"navigation\" i]","requireAnyAttr":["aria-label","aria-labelledby"]},"automationStatus":"auto"},{"id":"BASELINE_NO_ANCHOR_POSITIONING","category":"baseline","severity":"warn","description":"CSS Anchor Positioning は Baseline Limited(2026-07 時点, webstatus.dev)。fallback なしでは非対応ブラウザで配置が崩壊する。Baseline Widely available 未達機能は fallback 併記 + コメント明示宣言がない限り使わない","detector":"tailwind-class-prefix","pattern":"[anchor-name:","prefixPatterns":["[position-anchor:","[position-area:","[position-try"],"alternative":"absolute + top/left トークン系ユーティリティによる従来配置(DESIGN.md の配置パターン準拠)","contractLint":"warn"},{"id":"BASELINE_NO_INVOKER_COMMANDS","category":"baseline","severity":"warn","description":"Invoker Commands(commandfor / command 属性)は Baseline Limited(2026-07 時点)。非対応ブラウザではボタンが完全に無反応になる","detector":"html-attr","pattern":null,"alternative":"明示的な JS イベントリスナー、または dialog は showModal() 呼び出しで開閉する","contractLint":"skip","htmlAttrCheck":{"kind":"attr-present","attr":"(?:commandfor|command)"}},{"id":"BASELINE_NO_POPOVER_ATTR","category":"baseline","severity":"warn","description":"popover 属性は Baseline Newly → Widely 境界(2026-07 時点)。polyfill なしの生成では古い環境で開閉不能になる。使う場合は fallback かコメント明示宣言を伴うこと","detector":"html-attr","pattern":null,"alternative":"dropdown/tooltip contract の実装パターン(絶対配置 + JS toggle)を使う","contractLint":"skip","htmlAttrCheck":{"kind":"attr-present","attr":"popover"}},{"id":"BASELINE_NO_VIEW_TRANSITION","category":"baseline","severity":"warn","description":"View Transitions は same-document が Baseline Newly / cross-document が Limited(2026-07 時点)。演出前提の UI 構造にすると非対応環境で意味が壊れる","detector":"tailwind-class-prefix","pattern":"[view-transition-name:","prefixPatterns":["[view-transition-class:"],"alternative":"motion トークン(duration/easing)による CSS transition で代替する","contractLint":"warn"},{"id":"BASELINE_NO_TEXT_BOX_TRIM","category":"baseline","severity":"warn","description":"text-box-trim / text-box-edge は Baseline Newly(2026-07 時点)。行ボックスの光学調整に依存したレイアウトは非対応環境で余白がズレる","detector":"tailwind-class-prefix","pattern":"[text-box-trim:","prefixPatterns":["[text-box-edge:","[text-box:"],"alternative":"spacing トークン(py-* / leading-*)で余白を明示指定する","contractLint":"warn"}]}
===== contract summaries(全 40 contract。全文は design/contracts/components/{id}.contract.json) =====
{"id":"accordion","description":"折りたたみ式コンテンツ。aria-expanded必須。","variants":["single","multiple"],"states":["default","expanded","collapsed","hover","focus"],"anatomy":["container","item","trigger","icon","panel"],"rules":[]}
{"id":"action-sheet","description":"画面下から出るアクション/選択リスト。web の select / dropdown を APP に adapted 変換する際の受け皿(構造的 P0)。destructive アクションは色で区別しラベルでも伝える。","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["overlay","sheet","title?","action","cancelAction"],"rules":[]}
{"id":"alert","description":"インラインアラート通知。Info / Success / Warning / Error の4タイプ。","variants":["info","success","warning","error"],"states":["default","dismissing"],"anatomy":["container","icon","title?","message","closeButton?"],"rules":["COLOR_ONLY_FORBIDDEN","AI_NO_CARD_COLOR_BAR_LEFT","AI_NO_CARD_COLOR_BAR_TOP"]}
{"id":"avatar","description":"ユーザーアバター。Image / Initials / Status / Group。","variants":["image","initials","group"],"states":["default","online","away","offline"],"anatomy":["container","image?","initials?","statusDot?"],"rules":[]}
{"id":"badge","description":"ステータス・カウント表示。Status / Dot / Count / Outline の4バリエーション。","variants":["neutral","success","warning","danger","accent"],"states":["default"],"anatomy":["container","dotIndicator?","label"],"rules":["COLOR_ONLY_FORBIDDEN","TAG_BADGE_CONFUSION"]}
{"id":"bottom-sheet","description":"画面下から出る汎用シート container(content は自由 slot)。フィルタ・詳細・複雑な選択 UI の受け皿。ActionSheet がリスト特化なのに対しこちらは容器。","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["overlay","sheet","grabber","title?","content"],"rules":[]}
{"id":"breadcrumb","description":"階層パスナビゲーション。ol要素で構造化。","variants":["text-separator","chevron-separator"],"states":["default","hover"],"anatomy":["nav","orderedList","linkItem","separator","currentPage","ellipsis?","homeIcon?"],"rules":["SPACE_NO_MISSING_ARIA_CURRENT","A11Y_NAV_ARIA_LABEL_REQUIRED"]}
{"id":"button","description":"CTA / secondary / icon button。3階層ヒエラルキー。","variants":["contained","outlined","brand-outline","neutral","lighted","danger","subtle"],"states":["default","hover","focus","disabled","loading"],"stateSpecs":{"disabled":{"description":"操作不可。全 variant 共通。","tailwind":"opacity-50 cursor-not-allowed pointer-events-none","ariaChanges":"disabled 属性 + aria-disabled=\"true\"。hover/focus は効かせない。"},"loading":{"description":"非同期処理中。全 variant 共通。","tailwind":"opacity-70 cursor-wait pointer-events-none","ariaChanges":"aria-busy=\"true\" + disabled。","htmlNote":"label 前にスピナーを prepend(スピナーのクラスは htmlSample/anatomy 側で表現。htmlNote は prose でリンタ非対象)。"}},"anatomy":["leadingIcon?","label","trailingIcon?"],"rules":["SPACE_NO_PY_05_BTN","BTN_ICON_ONLY_ARIA_REQUIRED","BTN_MIN_TAP_TARGET","BTN_NO_SAME_STYLE_PARALLEL","BTN_NO_LIGHTED_SOLO"]}
{"id":"card","description":"コンテンツコンテナ。Basic / Metrics / Media / Action / Link の5バリエーション。","variants":["basic","media","action","link"],"states":["default","hover","focus-within"],"anatomy":["header?","body","footer?","media?"],"rules":["SPACE_NO_ROUNDED_NONE_CARDS","SPACE_NO_SHADOW_LG","SPACE_NO_SHADOW_2XL","SPACE_NO_P0_CARDS","AI_NO_CARD_COLOR_BAR_TOP","AI_NO_CARD_COLOR_BAR_LEFT"]}
{"id":"checkbox","description":"複数選択フォームコントロール。CSS 18px サイズ。","variants":["default","disabled","indeterminate"],"states":["default","checked","unchecked","indeterminate","disabled","error","focus"],"anatomy":["box","checkmark?","indeterminateMark?","label","groupLabel?","helperText?","errorText?"],"rules":["FORM_NO_LABEL_OMIT"]}
{"id":"copy-button","description":"クリップボードコピー + pop アニメーション付きアイコンボタン。","variants":["outlined","subtle"],"states":["default","hover","active","copied","focus"],"anatomy":["container","copyIcon","checkIcon"],"rules":["BTN_ICON_ONLY_ARIA_REQUIRED"]}
{"id":"datepicker","description":"日付選択コンポーネント。カレンダーポップアップ + キーボードナビ。","variants":["trigger","calendar","day-cell"],"states":["default","open","selected","today","disabled","error","hover","focus"],"stateSpecs":{"open":{"description":"カレンダー展開。calendar variant が開いた姿そのもの=差分なし。","tailwind":"","ariaChanges":"トリガーに aria-expanded=\"true\"。calendarPopup を role=\"dialog\" で表示しフォーカス移動。","htmlNote":"structural 状態。calendar variant の tailwind(absolute mt-1 ... z-20)が open の表示。default は calendarPopup を hidden で隠す。"},"selected":{"description":"選択済み日セル。day-cell 基底への overlay 差分。","tailwind":"bg-primary-500 text-white hover:bg-primary-600","ariaChanges":"当該 day セルに aria-selected=\"true\"。"},"today":{"description":"今日のマーカー。day-cell 基底への overlay 差分(選択とは独立)。","tailwind":"font-semibold ring-1 ring-inset ring-primary-300","htmlNote":"text color は持たず ring + 太字のみ=selected(bg-primary-500 text-white) と併用しても文字色が衝突しない。未選択時は基底の text 色を継承。"},"error":{"description":"不正入力。trigger 基底への overlay 差分。","tailwind":"border-red-600","ariaChanges":"トリガーに aria-invalid=\"true\" + aria-describedby でエラーメッセージ参照。"},"disabled":{"description":"操作不可。全 variant 共通。","tailwind":"opacity-50 cursor-not-allowed pointer-events-none","ariaChanges":"トリガーに disabled 属性 + aria-disabled=\"true\"。カレンダーを開けない。"}},"anatomy":["trigger","hiddenInput","calendarPopup","monthHeader","dayOfWeekHeader","dayGrid","todayButton?"],"rules":["DATEPICKER_NO_NATIVE_INPUT","DATEPICKER_NO_SHADOW_LG","DATEPICKER_Z_INDEX_20","DATEPICKER_NO_COLOR_ONLY_TODAY","DATEPICKER_KEYBOARD_NAV_REQUIRED","DATEPICKER_WEEKDAY_HEADER_REQUIRED"]}
{"id":"divider","description":"セクション間の視覚的区切り。水平 / テキスト付き / 垂直の3パターン。","variants":["horizontal","with-text","vertical"],"states":["default"],"anatomy":["line","label?","container?"],"rules":["DIVIDER_NO_DIV_BORDER_B","DIVIDER_NO_GRAY_100","DIVIDER_NO_SLATE_400_PLUS"]}
{"id":"dropdown","description":"ドロップダウンメニュー。キーボードナビゲーション対応。","variants":["basic","with-icons","with-separator"],"states":["default","open","hover","focus","disabled","destructive"],"stateSpecs":{"open":{"description":"メニュー展開。menuContainer variant が開いた姿そのもの=差分なし。","tailwind":"","ariaChanges":"triggerButton に aria-expanded=\"true\"。menuContainer を role=\"menu\" で表示。","htmlNote":"structural 状態。variant の tailwind(absolute top-full ... z-20)が open の表示。default は menuContainer を hidden で隠す。"},"destructive":{"description":"破壊的アクションの menuItem。menuItem 基底への overlay 差分。","tailwind":"text-red-700 hover:bg-red-50","htmlNote":"「削除」等の危険操作項目に適用。アイコンも text-red-600 に揃える。"},"disabled":{"description":"操作不可。全 variant 共通。","tailwind":"opacity-50 cursor-not-allowed pointer-events-none","ariaChanges":"トリガーに aria-disabled=\"true\"。開けない(aria-expanded は false のまま)。"}},"anatomy":["triggerButton","menuContainer","menuItem","leadingIcon?","separator?","menuGroupLabel?"],"rules":[]}
{"id":"empty-state","description":"データ無し時のプレースホルダー(アイコン + タイトル + 説明 + 任意のアクション)。Text + Button の compose。","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["icon?","title","description?","actionButton?"],"rules":[]}
{"id":"header","description":"画面ヘッダー。defaultは可視見出し、actionsは見出しを視覚的に隠した操作バー。どちらも意味のあるtitleを必須とし、leading/trailingの操作を個別に読み上げる。","webStatus":"pending","variants":["default","actions"],"states":["default"],"anatomy":["container","title","leading?","trailing?"],"rules":[]}
{"id":"icon","description":"統一アイコン primitive。name prop でグリフを選択し(グリフ集合は実装側の公開面 = assets/icons の Charcoal セット由来)、色は semantic token キー限定の prop(default ","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["glyph"],"rules":[]}
{"id":"image","description":"画像表示 primitive。aspectRatio / radius / contentFit / onError fallback を持つ。Phase1 は RN コア Image、expo-image は Phase2。","webStatus":"pending","variants":["default"],"states":["default","error"],"anatomy":["image","fallback?"],"rules":[]}
{"id":"list","description":"リストアイテム。Link / Information / Action / Toggle / Selection の6タイプ。","variants":["link","information","action"],"states":["default","hover","active","selected","focus"],"anatomy":["container","primaryText","secondaryText?","leftIcon?","leftImage?","rightIcon?","rightImage?","action?","border?"],"rules":["LIST_NO_FIXED_HEIGHT_MISMATCH","LIST_NO_COLOR_ONLY_SELECTION","LIST_NO_GESTURE_ONLY","LIST_NO_ICON_BORDER"]}
{"id":"metric","description":"数値 + 単位 + ラベルの指標表示 primitive(距離 / 時間 / 獲得標高 等の走行サマリー表示)。tabular-nums で桁揃え。sizes の height は数値テキストの想定行高(px)で、実 fontSize は実","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["value","unit?","label?"],"rules":[]}
{"id":"modal","description":"フォーカストラップとバックドロップを備えたモーダルダイアログ。","variants":["confirmation","form","alert"],"states":["default","open","closing"],"stateSpecs":{"default":{"description":"閉。DOM 上 hidden。","tailwind":"hidden","ariaChanges":"aria-hidden=\"true\"。"},"open":{"description":"表示。フォーカストラップ作動。","tailwind":"","ariaChanges":"aria-modal=\"true\"。Escape で閉じる(MODAL_ESC_CLOSE_REQUIRED)。","htmlNote":"variant tailwind(fixed inset-0 flex items-center justify-center z-50)がそのまま open の表示。open は variant 基底=差分なし。"},"closing":{"description":"閉アニメ中。完了後 hidden に戻し focus 復帰。","tailwind":"opacity-0 transition-opacity duration-150","htmlNote":"トランジション終了で default(hidden) へ。"}},"anatomy":["overlay","container","header","body","footer","closeButton"],"rules":["MODAL_FOCUS_TRAP_REQUIRED","MODAL_ESC_CLOSE_REQUIRED","MODAL_CLOSE_REQUIRED","MODAL_ROLE_DIALOG_REQUIRED","MODAL_OVERLAY_REQUIRED","MODAL_NO_NESTED"]}
{"id":"pagination","description":"ページ送りナビゲーション。w-10 h-10タップターゲット。","variants":["active","inactive","disabled"],"states":["default","active","disabled","hover","focus"],"anatomy":["navContainer","pageButton","prevButton","nextButton","ellipsis?"],"rules":["BTN_MIN_TAP_TARGET","A11Y_NAV_ARIA_LABEL_REQUIRED"]}
{"id":"progress","description":"リニアプログレスバー。aria-valuenow/min/max必須。","variants":["primary","success","indeterminate"],"states":["default","determinate","indeterminate","complete"],"anatomy":["track","fill","label?","percentage?"],"rules":["MOTION_REDUCED_MOTION_REQUIRED"]}
{"id":"radio","description":"単一選択フォームコントロール。fieldsetラッパー必須。","variants":["vertical","horizontal","card-style"],"states":["default","selected","unselected","disabled","error","focus"],"stateSpecs":{"selected":{"description":"選択済み。radioCircle 基底への overlay 差分 + selectedIndicator 表示。","tailwind":"border-primary-500","ariaChanges":"当該 <input type=\"radio\"> に checked + aria-checked=\"true\"。selectedIndicator(内側ドット bg-primary-500)を表示。"},"unselected":{"description":"未選択(radioCircle の基底状態)。default の resting と同義=差分なし。","tailwind":"","ariaChanges":"aria-checked=\"false\"。selectedIndicator は非表示。"},"error":{"description":"バリデーションエラー。radioCircle 基底への overlay 差分。","tailwind":"border-red-600","ariaChanges":"radiogroup に aria-invalid=\"true\" + aria-describedby で errorText 参照。","htmlNote":"errorText を text-red-600 で表示。selected と併用時は error の border-red-600 を優先(選択済みでもエラーなら赤枠)。"},"disabled":{"description":"操作不可。全 variant 共通。","tailwind":"opacity-50 cursor-not-allowed pointer-events-none","ariaChanges":"各 <input type=\"radio\"> に disabled + aria-disabled=\"true\"。"}},"anatomy":["radioCircle","selectedIndicator?","label","groupLabel","description?","helperText?","errorText?"],"rules":["FORM_FIELDSET_LEGEND_REQUIRED","FORM_NO_LABEL_OMIT"]}
{"id":"row","description":"子要素を横に並べる layout primitive。gap は spacing token キー限定の prop。折返し(wrap)と主軸配置(justify)を持ち、タグ列・メトリクス列・ヘッダー行の生 flexbox 手書きを置き換え","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["container"],"rules":[]}
{"id":"screen","description":"画面骨格 primitive(SafeArea + bg-page + content padding)。header slot を scroll 外に固定し、毎画面手書きされる SafeAreaView + ScrollView + ヘッ","webStatus":"pending","variants":["fixed","scroll"],"states":["default"],"anatomy":["safeArea","header?","content"],"rules":[]}
{"id":"select","description":"ドロップダウン選択。appearance-none + カスタムSVGシェブロン必須。","variants":["default","error","disabled"],"states":["default","hover","focus","error","disabled"],"anatomy":["label","wrapper","select","chevronIcon"],"rules":["FORM_SELECT_APPEARANCE_NONE","FORM_NO_LABEL_OMIT"]}
{"id":"sidebar","description":"メインナビゲーション用サイドバー。Standard / Compact / Drawer の3バリエーション。","variants":["standard","compact","drawer"],"states":["default","collapsed","drawer-open"],"anatomy":["header","nav","navItem","footer"],"rules":["SPACE_NO_NONSTANDARD_SIDEBAR_WIDTH","SPACE_NO_DARK_SIDEBAR_BG","SPACE_NO_ROUNDED_XL_NAV","SPACE_NO_LARGE_NAV_ICON","SPACE_NO_MISSING_ARIA_CURRENT","SPACE_NO_DRAWER_NO_FOCUS_TRAP","A11Y_NAV_ARIA_LABEL_REQUIRED"]}
{"id":"skeleton","description":"ローディングプレースホルダー。aria-busy=\"true\"必須。","variants":["text","card","circle"],"states":["default","loading","loaded"],"anatomy":["container","circle?","bar","srOnlyText"],"rules":["SKELETON_ARIA_BUSY_REQUIRED","SKELETON_ARIA_BUSY_RELEASE","SKELETON_BG_SLATE_200_ONLY","SKELETON_NO_SPINNER_ONLY","MOTION_REDUCED_MOTION_REQUIRED"]}
{"id":"stack","description":"子要素を縦に積む layout primitive。gap は spacing token キー限定の prop(省略時 gap なし)。画面の縦リズムを生 flexbox 手書きから置き換える(dogfood 不足-1)。","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["container"],"rules":[]}
{"id":"stepper","description":"マルチステッププロセスの進捗表示。Completed / Active / Upcoming の3状態。","variants":["horizontal","vertical"],"states":["completed","active","upcoming"],"anatomy":["container","step","indicator","label","description?","connector"],"rules":["STEPPER_NO_COLOR_ONLY_STATE","STEPPER_ARIA_CURRENT_REQUIRED","STEPPER_MIN_INDICATOR_SIZE","STEPPER_NO_DARK_CONNECTOR"]}
{"id":"surface","description":"Card / Skeleton / EmptyState の共通土台となる箱 primitive(bg / radius / elevation / padding)。melta-app では internal(未 export)。","webStatus":"pending","variants":["default"],"states":["default"],"anatomy":["container"],"rules":[]}
{"id":"table","description":"データテーブル。th scope=\"col\"必須。","variants":["basic","sortable"],"states":["default","hover","empty"],"stateSpecs":{"empty":{"description":"0件。空状態行を表示。全 variant 共通。","tailwind":"","htmlNote":"<tbody> 内に colspan 全列結合の1行で中央寄せ「データがありません」。"}},"anatomy":["wrapper","caption","th","row","td"],"rules":["TABLE_TH_SCOPE_REQUIRED","TABLE_NO_LAYOUT_TABLE"]}
{"id":"tabs","description":"コンテンツ切り替えタブ。underline(下線)/ bar(丸角バー)の2バリアント。キーボードナビ対応。","variants":["underline-active","underline-inactive","bar-active","bar-inactive"],"states":["default","active","inactive","disabled","hover","focus"],"stateSpecs":{"disabled":{"description":"操作不可。全 variant 共通。","tailwind":"opacity-50 cursor-not-allowed pointer-events-none","ariaChanges":"tab に aria-disabled=\"true\" + tabindex=\"-1\"(フォーカス・選択不可)。"}},"anatomy":["tabList","tab","tabPanel","indicator"],"rules":[]}
{"id":"tag","description":"削除可能なタグ / フィルターチップ。","variants":["basic","removable","filter-chip"],"states":["default","active","inactive","hover","focus"],"anatomy":["container","labelText","removeButton?","checkmarkIcon?"],"rules":["TAG_X_ARIA_LABEL_REQUIRED","TAG_REMOVABLE_X_REQUIRED","TAG_X_MIN_TAP_TARGET","TAG_FILTER_ARIA_SELECTED_REQUIRED","TAG_BADGE_CONFUSION"]}
{"id":"text","description":"本文・見出し・キャプションの基本テキスト primitive。fontSize variant と semantic color、heading/body で letterSpacing を切替。","webStatus":"pending","variants":["xxs","xs","sm","base","lg","xl","2xl","3xl"],"states":["default"],"anatomy":["textNode"],"rules":[]}
{"id":"textfield","description":"テキスト入力フィールド。Default / Error / Disabled / Success の4状態。","variants":["default","error","disabled","success"],"states":["default","hover","focus","error","disabled","success"],"anatomy":["label","input","helperText?","errorMessage?"],"rules":["TYPO_NO_PLACEHOLDER_ONLY","FORM_NO_LABEL_OMIT","FORM_NO_COLOR_ONLY_ERROR","FORM_NO_DISTANT_ERROR"]}
{"id":"toast","description":"一時的な通知メッセージ。4タイプ(success/error/warning/info)。","variants":["success","error","warning","info"],"states":["default","entering","visible","dismissing","hover"],"anatomy":["container","statusIcon","message","description?","closeButton","actionButton?","progressBar?"],"rules":[]}
{"id":"toggle","description":"ON/OFFスイッチコンポーネント。role=\"switch\"必須。","variants":["off","on"],"states":["off","on","hover","focus","disabled"],"stateSpecs":{"disabled":{"description":"操作不可。off/on 共通。","tailwind":"opacity-50 cursor-not-allowed pointer-events-none","ariaChanges":"disabled 属性 + aria-disabled=\"true\"。aria-checked は現状態を保持。"}},"anatomy":["track","thumb","label","description?","statusText?"],"rules":[]}
{"id":"tooltip","description":"ホバー/フォーカスで表示される補足情報。max-width: 20rem。","variants":["top","bottom","left","right"],"states":["default","visible","hidden"],"anatomy":["container","text"],"rules":[]}